Modern features (height texturing, WMO scaling, maptexture generation)
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <optional>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
4
src/noggit/Action.cpp
Executable file → Normal file
4
src/noggit/Action.cpp
Executable file → Normal file
@@ -246,7 +246,7 @@ unsigned Noggit::Action::handleObjectAdded(unsigned uid, bool redo)
|
||||
unsigned old_uid = pair.first;
|
||||
SceneObject* obj;
|
||||
if (pair.second.type == ActionObjectTypes::WMO)
|
||||
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir, false);
|
||||
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir, pair.second.scale, false);
|
||||
else
|
||||
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.file_key, pair.second.pos,
|
||||
pair.second.scale, pair.second.dir, nullptr, false, false);
|
||||
@@ -310,7 +310,7 @@ unsigned Noggit::Action::handleObjectRemoved(unsigned uid, bool redo)
|
||||
unsigned old_uid = pair.first;
|
||||
SceneObject* obj;
|
||||
if (pair.second.type == ActionObjectTypes::WMO)
|
||||
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir, false);
|
||||
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir, pair.second.scale, false);
|
||||
else
|
||||
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.file_key, pair.second.pos,
|
||||
pair.second.scale, pair.second.dir, nullptr, false, false);
|
||||
|
||||
2
src/noggit/MapChunk.cpp
Executable file → Normal file
2
src/noggit/MapChunk.cpp
Executable file → Normal file
@@ -1762,7 +1762,7 @@ void MapChunk::save(util::sExtendableArray& lADTFile
|
||||
header_ptr->ofsLiquid = lCurrentPosition - lMCNK_Position;
|
||||
|
||||
// When saving a tile that had MLCQ, also remove flags in MCNK
|
||||
// Client sees the flag and loads random data as if it were MCLQ, which we don<EFBFBD>t save.
|
||||
// Client sees the flag and loads random data as if it were MCLQ, which we dont save.
|
||||
// clear MCLQ liquid flags (0x4, 0x8, 0x10, 0x20)
|
||||
header_ptr->flags.value &= 0xFFFFFFC3;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ struct ENTRY_MODF
|
||||
uint16_t flags;
|
||||
uint16_t doodadSet;
|
||||
uint16_t nameSet;
|
||||
uint16_t unknown;
|
||||
uint16_t scale;
|
||||
};
|
||||
|
||||
struct MapChunkHeader {
|
||||
|
||||
27
src/noggit/MapTile.cpp
Executable file → Normal file
27
src/noggit/MapTile.cpp
Executable file → Normal file
@@ -13,6 +13,7 @@
|
||||
#include <noggit/texture_set.hpp>
|
||||
#include <noggit/ui/TexturingGUI.h>
|
||||
#include <noggit/application/NoggitApplication.hpp>
|
||||
#include <noggit/project/CurrentProject.hpp>
|
||||
#include <ClientFile.hpp>
|
||||
#include <opengl/scoped.hpp>
|
||||
#include <opengl/shader.hpp>
|
||||
@@ -259,6 +260,8 @@ void MapTile::finishLoading()
|
||||
for (unsigned int i = 0; i < size / sizeof(ENTRY_MODF); ++i)
|
||||
{
|
||||
lWMOInstances.push_back(modf_ptr[i]);
|
||||
if(lWMOInstances[i].scale == 0.0f)
|
||||
lWMOInstances[i].scale = 1024.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,7 +863,7 @@ void MapTile::save(World* world, bool save_using_mclq_liquids)
|
||||
lMODF_Data[lID].flags = object->mFlags;
|
||||
lMODF_Data[lID].doodadSet = object->doodadset();
|
||||
lMODF_Data[lID].nameSet = object->mNameset;
|
||||
lMODF_Data[lID].unknown = object->mUnknown;
|
||||
lMODF_Data[lID].scale = (uint16_t)(object->scale * 1024);
|
||||
lID++;
|
||||
}
|
||||
|
||||
@@ -1777,6 +1780,24 @@ void MapTile::calcCamDist(glm::vec3 const& camera)
|
||||
_cam_dist = glm::distance(camera, _center);
|
||||
}
|
||||
|
||||
const texture_heightmapping_data& MapTile::GetTextureHeightMappingData(const std::string& name) const
|
||||
{
|
||||
return Noggit::Project::CurrentProject::get()->ExtraMapData.GetTextureHeightDataForADT(_world->mapIndex._map_id, index,name);
|
||||
}
|
||||
|
||||
void MapTile::forceAlphaUpdate()
|
||||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
auto chunk = mChunks[i][j].get();
|
||||
auto texSet = chunk->getTextureSet();
|
||||
texSet->markDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MapTile::childrenFinishedLoading()
|
||||
{
|
||||
if (!objectsFinishedLoading())
|
||||
@@ -1864,6 +1885,4 @@ void MapTile::recalcCombinedExtents()
|
||||
}
|
||||
|
||||
_combined_extents_dirty = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
4
src/noggit/MapTile.h
Executable file → Normal file
4
src/noggit/MapTile.h
Executable file → Normal file
@@ -177,6 +177,9 @@ public:
|
||||
Noggit::Rendering::TileRender* renderer() { return &_renderer; };
|
||||
Noggit::Rendering::FlightBoundsRender* flightBoundsRenderer() { return &_fl_bounds_render; };
|
||||
|
||||
const texture_heightmapping_data& GetTextureHeightMappingData(const std::string& name) const;
|
||||
|
||||
void forceAlphaUpdate();
|
||||
bool childrenFinishedLoading();
|
||||
bool texturesFinishedLoading();
|
||||
bool objectsFinishedLoading();
|
||||
@@ -191,6 +194,7 @@ private:
|
||||
bool _requires_object_extents_recalc = true;
|
||||
|
||||
|
||||
|
||||
std::array<glm::vec3, 2> _extents;
|
||||
std::array<glm::vec3, 2> _object_instance_extents;
|
||||
std::array<glm::vec3, 2> _combined_extents;
|
||||
|
||||
20
src/noggit/MapView.cpp
Executable file → Normal file
20
src/noggit/MapView.cpp
Executable file → Normal file
@@ -103,6 +103,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QClipboard>
|
||||
#include <QProcess>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@@ -267,6 +268,8 @@ void MapView::set_editing_mode(editing_mode mode)
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_groundeffectid_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_groundeffect_layerid_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_noeffectdoodad_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_only_normals = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->point_normals_up = false;
|
||||
_minimap->use_selection(nullptr);
|
||||
|
||||
if (terrainMode != mode)
|
||||
@@ -331,6 +334,7 @@ void MapView::ResetSelectedObjectRotation()
|
||||
WMOInstance* wmo = static_cast<WMOInstance*>(obj);
|
||||
_world->updateTilesWMO(wmo, model_update::remove);
|
||||
wmo->resetDirection();
|
||||
wmo->recalcExtents();
|
||||
_world->updateTilesWMO(wmo, model_update::add);
|
||||
}
|
||||
else if (obj->which() == eMODEL)
|
||||
@@ -3148,12 +3152,12 @@ void MapView::tick (float dt)
|
||||
. arg (std::floor (_camera.position.z / TILESIZE))
|
||||
);
|
||||
status += ( QString ("; coordinates client: (%1, %2, %3), server: (%4, %5, %6)")
|
||||
. arg (_camera.position.x)
|
||||
. arg (_camera.position.z)
|
||||
. arg (_camera.position.y)
|
||||
. arg (ZEROPOINT - _camera.position.z)
|
||||
. arg (ZEROPOINT - _camera.position.x)
|
||||
. arg (_camera.position.y)
|
||||
. arg (_camera.position.x, 0, 'f', 2)
|
||||
. arg (_camera.position.z, 0, 'f', 2)
|
||||
. arg (_camera.position.y, 0, 'f', 2)
|
||||
. arg (ZEROPOINT - _camera.position.z, 0, 'f', 2)
|
||||
. arg (ZEROPOINT - _camera.position.x, 0, 'f', 2)
|
||||
. arg (_camera.position.y, 0, 'f', 2)
|
||||
);
|
||||
|
||||
_status_position->setText (status);
|
||||
@@ -3200,6 +3204,10 @@ void MapView::tick (float dt)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_status_selection->setText(QString::number(currentSelection.size()) + " objects selected");
|
||||
}
|
||||
|
||||
if (selection_changed || NOGGIT_CUR_ACTION)
|
||||
updateDetailInfos(); // checks if sel changed
|
||||
|
||||
@@ -13,13 +13,15 @@ enum MinimapGenMode
|
||||
{
|
||||
CURRENT_ADT,
|
||||
SELECTED_ADTS,
|
||||
MAP
|
||||
MAP,
|
||||
LOD_MAPTEXTURES,
|
||||
LOD_MAPTEXTURES_N,
|
||||
};
|
||||
|
||||
struct MinimapRenderSettings
|
||||
{
|
||||
MinimapGenMode export_mode = CURRENT_ADT;
|
||||
std::string file_format = ".blp";
|
||||
std::string file_format = ".blp (DXT1)";
|
||||
|
||||
// Render settings
|
||||
int resolution = 512;
|
||||
@@ -31,11 +33,13 @@ struct MinimapRenderSettings
|
||||
bool draw_shadows = false;
|
||||
bool use_filters = false;
|
||||
bool combined_minimap = false;
|
||||
bool draw_only_normals = false;
|
||||
bool point_normals_up = false;
|
||||
|
||||
// Selection
|
||||
// std::array<bool, 4096> selected_tiles = {false};
|
||||
// std::array<bool, 4096> selected_tiles = {false};
|
||||
|
||||
std::vector<char> selected_tiles = std::vector<char>( size_t{4096}, false, {} );
|
||||
std::vector<char> selected_tiles = std::vector<char>(size_t{ 4096 }, false, {});
|
||||
|
||||
// Filtering
|
||||
QListWidget* m2_model_filter_include = nullptr;
|
||||
|
||||
@@ -269,6 +269,16 @@ void blp_texture::upload()
|
||||
void blp_texture::unload()
|
||||
{
|
||||
_uploaded = false;
|
||||
finished = false;
|
||||
if (hasHeightMap() && heightMap)
|
||||
{
|
||||
heightMap->unload();
|
||||
}
|
||||
_compression_format.reset();
|
||||
_texture_array = 0;
|
||||
_array_index = -1;
|
||||
_data.clear();
|
||||
_compressed_data.clear();
|
||||
|
||||
// load data back from file. pretty sad. maybe keep it after loading?
|
||||
finishLoading();
|
||||
@@ -402,10 +412,10 @@ void blp_texture::finishLoading()
|
||||
LogError << "file not found: '" << _file_key.stringRepr() << "'" << std::endl;
|
||||
}
|
||||
|
||||
std::string spec_filename;
|
||||
bool has_specular = false;
|
||||
std::string spec_filename = "", height_filename = "";
|
||||
bool has_specular = false, has_height = false;
|
||||
|
||||
if (_file_key.filepath().starts_with("tileset/"))
|
||||
if (_file_key.filepath().starts_with("tileset/") )
|
||||
{
|
||||
_is_tileset = true;
|
||||
|
||||
@@ -416,6 +426,22 @@ void blp_texture::finishLoading()
|
||||
{
|
||||
_is_specular = true;
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
// Only load _h in map view when modern features are enabled
|
||||
if(_context == Noggit::NoggitRenderContext::MAP_VIEW && modern_features)
|
||||
{
|
||||
height_filename = _file_key.filepath().substr(0, _file_key.filepath().find_last_of(".")) + "_h.blp";
|
||||
has_height = Noggit::Application::NoggitApplication::instance()->clientData()->exists(height_filename);
|
||||
if (has_height)
|
||||
{
|
||||
_has_heightmap = true;
|
||||
heightMap = std::make_unique<blp_texture>(height_filename,_context);
|
||||
heightMap->finishLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlizzardArchive::ClientFile f(
|
||||
|
||||
20
src/noggit/TextureManager.h
Executable file → Normal file
20
src/noggit/TextureManager.h
Executable file → Normal file
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <QtGui/QOffscreenSurface>
|
||||
#include <QtGui/QOpenGLFramebufferObjectFormat>
|
||||
#include <QPainter>
|
||||
#include <QtGui/QPixmap>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
@@ -23,6 +24,19 @@
|
||||
#include <tuple>
|
||||
|
||||
|
||||
struct texture_heightmapping_data
|
||||
{
|
||||
texture_heightmapping_data(uint32_t scale = 0, float heightscale = 0, float heightoffset = 1.0f)
|
||||
{
|
||||
uvScale = scale;
|
||||
heightScale = heightscale;
|
||||
heightOffset = heightoffset;
|
||||
}
|
||||
uint32_t uvScale = 0;
|
||||
float heightScale = 0.0f;
|
||||
float heightOffset = 1.0f;
|
||||
};
|
||||
|
||||
struct tuple_hash
|
||||
{
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
@@ -73,7 +87,10 @@ struct blp_texture : public AsyncObject
|
||||
{
|
||||
return async_priority::high;
|
||||
}
|
||||
// Mists HeightMapping
|
||||
bool hasHeightMap() {return _has_heightmap; };
|
||||
|
||||
blp_texture* getHeightMap() { return heightMap.get(); };
|
||||
private:
|
||||
bool _uploaded = false;
|
||||
|
||||
@@ -84,6 +101,7 @@ private:
|
||||
|
||||
bool _is_specular = false;
|
||||
bool _is_tileset = false;
|
||||
bool _has_heightmap = false;
|
||||
|
||||
private:
|
||||
std::map<int, std::vector<uint32_t>> _data;
|
||||
@@ -91,6 +109,8 @@ private:
|
||||
std::optional<GLint> _compression_format;
|
||||
int _array_index = -1;
|
||||
GLuint _texture_array = 0;
|
||||
|
||||
std::unique_ptr<blp_texture> heightMap;
|
||||
};
|
||||
|
||||
struct TexArrayParams
|
||||
|
||||
@@ -131,7 +131,7 @@ void WMO::finishLoading ()
|
||||
f.read(&materials[i], sizeof(WMOMaterial));
|
||||
|
||||
uint32_t shader = materials[i].shader;
|
||||
bool use_second_texture = (shader == 6 || shader == 5 || shader == 3);
|
||||
bool use_second_texture = (shader == 6 || shader == 5 || shader == 3 || shader == 21 || shader == 23);
|
||||
|
||||
materials[i].texture1 = load_texture(materials[i].texture_offset_1);
|
||||
if (use_second_texture)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Noggit::Rendering
|
||||
|
||||
struct wmo_batch
|
||||
{
|
||||
int8_t unused[12];
|
||||
int16_t unused[6];
|
||||
|
||||
uint32_t index_start;
|
||||
uint16_t index_count;
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
WMOInstance::WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, ENTRY_MODF const* d, Noggit::NoggitRenderContext context)
|
||||
: SceneObject(SceneObjectTypes::eWMO, context)
|
||||
, wmo(file_key, context)
|
||||
, mFlags(d->flags)
|
||||
, mUnknown(d->unknown), mNameset(d->nameSet)
|
||||
, mNameset(d->nameSet)
|
||||
, _doodadset(d->doodadSet)
|
||||
{
|
||||
pos = glm::vec3(d->pos[0], d->pos[1], d->pos[2]);
|
||||
@@ -25,6 +27,16 @@ WMOInstance::WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, ENT
|
||||
|
||||
uid = d->uniqueID;
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
if (modern_features) {
|
||||
scale = static_cast<float>(d->scale) / 1024.0f;
|
||||
}
|
||||
else {
|
||||
scale = 1.0f;
|
||||
}
|
||||
|
||||
extents[0] = glm::vec3(d->extents[0][0], d->extents[0][1], d->extents[0][2]);
|
||||
extents[1] = glm::vec3(d->extents[1][0], d->extents[1][1], d->extents[1][2]);
|
||||
|
||||
@@ -37,7 +49,6 @@ WMOInstance::WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, Nog
|
||||
: SceneObject(SceneObjectTypes::eWMO, context)
|
||||
, wmo(file_key, context)
|
||||
, mFlags(0)
|
||||
, mUnknown(0)
|
||||
, mNameset(0)
|
||||
, _doodadset(0)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
scoped_wmo_reference wmo;
|
||||
|
||||
uint16_t mFlags;
|
||||
uint16_t mUnknown;
|
||||
uint16_t mNameset;
|
||||
|
||||
uint16_t doodadset() const { return _doodadset; }
|
||||
@@ -48,7 +47,6 @@ public:
|
||||
, wmo (std::move (other.wmo))
|
||||
, group_extents(other.group_extents)
|
||||
, mFlags (other.mFlags)
|
||||
, mUnknown (other.mUnknown)
|
||||
, mNameset (other.mNameset)
|
||||
, _doodadset (other._doodadset)
|
||||
, _doodads_per_group(other._doodads_per_group)
|
||||
@@ -57,6 +55,7 @@ public:
|
||||
{
|
||||
std::swap (extents, other.extents);
|
||||
pos = other.pos;
|
||||
scale = other.scale;
|
||||
dir = other.dir;
|
||||
_context = other._context;
|
||||
uid = other.uid;
|
||||
@@ -73,8 +72,8 @@ public:
|
||||
std::swap(group_extents, other.group_extents);
|
||||
std::swap(dir, other.dir);
|
||||
std::swap(uid, other.uid);
|
||||
std::swap(scale, other.scale);
|
||||
std::swap(mFlags, other.mFlags);
|
||||
std::swap(mUnknown, other.mUnknown);
|
||||
std::swap(mNameset, other.mNameset);
|
||||
std::swap(_doodadset, other._doodadset);
|
||||
std::swap(_doodads_per_group, other._doodads_per_group);
|
||||
|
||||
127
src/noggit/World.cpp
Executable file → Normal file
127
src/noggit/World.cpp
Executable file → Normal file
@@ -772,11 +772,15 @@ void World::snap_selected_models_to_the_ground()
|
||||
update_selected_model_groups();
|
||||
}
|
||||
|
||||
void World::scale_selected_models(float v, m2_scaling_type type)
|
||||
void World::scale_selected_models(float v, object_scaling_type type)
|
||||
{
|
||||
ZoneScoped;
|
||||
if (!_selected_model_count)
|
||||
return;
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
for (auto& entry : _current_selection)
|
||||
{
|
||||
if (entry.index() == eEntry_Object)
|
||||
@@ -784,37 +788,72 @@ void World::scale_selected_models(float v, m2_scaling_type type)
|
||||
auto obj = std::get<selected_object_type>(entry);
|
||||
|
||||
if (obj->which() != eMODEL)
|
||||
continue;
|
||||
|
||||
ModelInstance* mi = static_cast<ModelInstance*>(obj);
|
||||
|
||||
NOGGIT_CUR_ACTION->registerObjectTransformed(mi);
|
||||
|
||||
float scale = mi->scale;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case World::m2_scaling_type::set:
|
||||
scale = v;
|
||||
break;
|
||||
case World::m2_scaling_type::add:
|
||||
scale += v;
|
||||
break;
|
||||
case World::m2_scaling_type::mult:
|
||||
scale *= v;
|
||||
break;
|
||||
}
|
||||
// If we are not using modern features, we don't want to scale WMOs
|
||||
if(!modern_features)
|
||||
continue;
|
||||
|
||||
// if the change is too small, do nothing
|
||||
if (std::abs(scale - mi->scale) < ModelInstance::min_scale())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
WMOInstance* wi = static_cast<WMOInstance*>(obj);
|
||||
|
||||
updateTilesModel(mi, model_update::remove);
|
||||
mi->scale = std::min(ModelInstance::max_scale(), std::max(ModelInstance::min_scale(), scale));
|
||||
mi->recalcExtents();
|
||||
updateTilesModel(mi, model_update::add);
|
||||
NOGGIT_CUR_ACTION->registerObjectTransformed(wi);
|
||||
|
||||
float scale = wi->scale;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case World::object_scaling_type::set:
|
||||
scale = v;
|
||||
break;
|
||||
case World::object_scaling_type::add:
|
||||
scale += v;
|
||||
break;
|
||||
case World::object_scaling_type::mult:
|
||||
scale *= v;
|
||||
break;
|
||||
}
|
||||
|
||||
// if the change is too small, do nothing
|
||||
if (std::abs(scale - wi->scale) < ModelInstance::min_scale())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
updateTilesWMO(wi, model_update::remove);
|
||||
wi->scale = std::min(ModelInstance::max_scale(), std::max(ModelInstance::min_scale(), scale));
|
||||
wi->recalcExtents();
|
||||
updateTilesWMO(wi, model_update::add);
|
||||
}
|
||||
else {
|
||||
ModelInstance* mi = static_cast<ModelInstance*>(obj);
|
||||
|
||||
NOGGIT_CUR_ACTION->registerObjectTransformed(mi);
|
||||
|
||||
float scale = mi->scale;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case World::object_scaling_type::set:
|
||||
scale = v;
|
||||
break;
|
||||
case World::object_scaling_type::add:
|
||||
scale += v;
|
||||
break;
|
||||
case World::object_scaling_type::mult:
|
||||
scale *= v;
|
||||
break;
|
||||
}
|
||||
|
||||
// if the change is too small, do nothing
|
||||
if (std::abs(scale - mi->scale) < ModelInstance::min_scale())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
updateTilesModel(mi, model_update::remove);
|
||||
mi->scale = std::min(ModelInstance::max_scale(), std::max(ModelInstance::min_scale(), scale));
|
||||
mi->recalcExtents();
|
||||
updateTilesModel(mi, model_update::add);
|
||||
}
|
||||
}
|
||||
}
|
||||
update_selected_model_groups();
|
||||
@@ -2026,7 +2065,9 @@ ModelInstance* World::addM2AndGetInstance ( BlizzardArchive::Listfile::FileKey c
|
||||
|
||||
void World::addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
, glm::vec3 newPos
|
||||
, float scale
|
||||
, math::degrees::vec3 rotation
|
||||
, Noggit::object_paste_params* paste_params
|
||||
, bool action
|
||||
)
|
||||
{
|
||||
@@ -2037,6 +2078,32 @@ void World::addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
wmo_instance.pos = newPos;
|
||||
wmo_instance.dir = rotation;
|
||||
|
||||
if (paste_params)
|
||||
{
|
||||
if (_settings->value("model/random_rotation", false).toBool())
|
||||
{
|
||||
float min = paste_params->minRotation;
|
||||
float max = paste_params->maxRotation;
|
||||
wmo_instance.dir.y += math::degrees(misc::randfloat(min, max))._;
|
||||
}
|
||||
|
||||
if (_settings->value("model/random_tilt", false).toBool())
|
||||
{
|
||||
float min = paste_params->minTilt;
|
||||
float max = paste_params->maxTilt;
|
||||
wmo_instance.dir.x += math::degrees(misc::randfloat(min, max))._;
|
||||
wmo_instance.dir.z += math::degrees(misc::randfloat(min, max))._;
|
||||
}
|
||||
|
||||
if (_settings->value("model/random_size", false).toBool())
|
||||
{
|
||||
float min = paste_params->minScale;
|
||||
float max = paste_params->maxScale;
|
||||
wmo_instance.scale = misc::randfloat(min, max);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// to ensure the tiles are updated correctly
|
||||
wmo_instance.wmo->wait_until_loaded();
|
||||
wmo_instance.recalcExtents();
|
||||
@@ -2047,6 +2114,7 @@ void World::addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
WMOInstance* World::addWMOAndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
, glm::vec3 newPos
|
||||
, math::degrees::vec3 rotation
|
||||
, float scale
|
||||
, bool action
|
||||
)
|
||||
{
|
||||
@@ -2056,6 +2124,7 @@ WMOInstance* World::addWMOAndGetInstance ( BlizzardArchive::Listfile::FileKey co
|
||||
wmo_instance.uid = mapIndex.newGUID();
|
||||
wmo_instance.pos = newPos;
|
||||
wmo_instance.dir = rotation;
|
||||
wmo_instance.scale = scale;
|
||||
|
||||
// to ensure the tiles are updated correctly
|
||||
wmo_instance.wmo->wait_until_loaded();
|
||||
|
||||
8
src/noggit/World.h
Executable file → Normal file
8
src/noggit/World.h
Executable file → Normal file
@@ -147,7 +147,7 @@ public:
|
||||
void range_add_to_selection(glm::vec3 const& pos, float radius, bool remove);
|
||||
Noggit::world_model_instances_storage& getModelInstanceStorage() { return _model_instance_storage; };
|
||||
|
||||
enum class m2_scaling_type
|
||||
enum class object_scaling_type
|
||||
{
|
||||
set,
|
||||
add,
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
};
|
||||
|
||||
void snap_selected_models_to_the_ground();
|
||||
void scale_selected_models(float v, m2_scaling_type type);
|
||||
void scale_selected_models(float v, object_scaling_type type);
|
||||
void move_selected_models(float dx, float dy, float dz);
|
||||
void move_model(selection_type entry, float dx, float dy, float dz);
|
||||
void move_selected_models(glm::vec3 const& delta)
|
||||
@@ -289,7 +289,8 @@ public:
|
||||
);
|
||||
void addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
, glm::vec3 newPos
|
||||
, math::degrees::vec3 rotation
|
||||
, float scale, math::degrees::vec3 rotation
|
||||
, Noggit::object_paste_params*
|
||||
, bool action
|
||||
);
|
||||
|
||||
@@ -304,6 +305,7 @@ public:
|
||||
WMOInstance* addWMOAndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
|
||||
, glm::vec3 newPos
|
||||
, math::degrees::vec3 rotation
|
||||
, float scale
|
||||
, bool action
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "ApplicationProject.h"
|
||||
#include <noggit/World.h>
|
||||
|
||||
namespace Noggit::Project
|
||||
{
|
||||
|
||||
|
||||
void ApplicationProject::loadExtraData(NoggitProject& project)
|
||||
{
|
||||
std::filesystem::path extraDataFolder = (project.ProjectPath);
|
||||
extraDataFolder /= "extraData";
|
||||
|
||||
Log << "Loading extra data from " << extraDataFolder << std::endl;
|
||||
|
||||
if (std::filesystem::exists(extraDataFolder) && std::filesystem::is_directory(extraDataFolder))
|
||||
{
|
||||
for (const auto& entry : std::filesystem::directory_iterator(extraDataFolder))
|
||||
{
|
||||
if (entry.path().extension() == ".cfg")
|
||||
{
|
||||
QFile input_file(QString::fromStdString(entry.path().generic_string()));
|
||||
input_file.open(QIODevice::ReadOnly);
|
||||
QJsonParseError err;
|
||||
auto document = QJsonDocument().fromJson(input_file.readAll(), &err);
|
||||
auto root = document.object();
|
||||
auto keys = root.keys();
|
||||
if (entry.path().stem() == "global")
|
||||
{
|
||||
for (auto const& entry : keys)
|
||||
{
|
||||
texture_heightmapping_data newData;
|
||||
newData.uvScale = root[entry].toObject()["Scale"].toInt();
|
||||
newData.heightOffset = root[entry].toObject()["HeightOffset"].toDouble();
|
||||
newData.heightScale = root[entry].toObject()["HeightScale"].toDouble();
|
||||
project.ExtraMapData.SetTextureHeightData_Global(entry.toStdString(), newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void NoggitExtraMapData::SetTextureHeightData_Global(const std::string& texture, texture_heightmapping_data data, World* worldToUpdate)
|
||||
{
|
||||
TextureHeightData_Global[texture] = data;
|
||||
if (worldToUpdate)
|
||||
{
|
||||
for (MapTile* tile : worldToUpdate->mapIndex.loaded_tiles())
|
||||
{
|
||||
tile->registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
|
||||
tile->forceAlphaUpdate();
|
||||
tile->forceRecalcExtents();
|
||||
}
|
||||
}
|
||||
}
|
||||
void NoggitExtraMapData::SetTextureHeightDataForADT(int mapID, const TileIndex& ti, const std::string& texture, texture_heightmapping_data data, World* worldToUpdate)
|
||||
{
|
||||
TextureHeightData_ADT[mapID][ti.x][ti.z][texture] = data;
|
||||
if (worldToUpdate)
|
||||
{
|
||||
MapTile* tile = worldToUpdate->mapIndex.getTile(ti);
|
||||
tile->registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
|
||||
tile->forceAlphaUpdate();
|
||||
tile->forceRecalcExtents();
|
||||
}
|
||||
}
|
||||
const texture_heightmapping_data NoggitExtraMapData::GetTextureHeightDataForADT(int mapID, const TileIndex& tileIndex, const std::string& texture) const
|
||||
{
|
||||
static texture_heightmapping_data defaultValue;
|
||||
auto foundMapIter = TextureHeightData_ADT.find(mapID);
|
||||
if (foundMapIter != TextureHeightData_ADT.end())
|
||||
{
|
||||
auto foundXIter = foundMapIter->second.find(tileIndex.x);
|
||||
if (foundXIter != foundMapIter->second.end())
|
||||
{
|
||||
auto foundYIter = foundXIter->second.find(tileIndex.z);
|
||||
if (foundYIter != foundXIter->second.end())
|
||||
{
|
||||
auto foundTexData = foundYIter->second.find(texture);
|
||||
if (foundTexData != foundYIter->second.end())
|
||||
{
|
||||
return foundTexData->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto foundGenericSettings = TextureHeightData_Global.find(texture);
|
||||
if (foundGenericSettings != TextureHeightData_Global.end())
|
||||
{
|
||||
return foundGenericSettings->second;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
};
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <blizzard-database-library/include/BlizzardDatabase.h>
|
||||
#include <noggit/application/Configuration/NoggitApplicationConfiguration.hpp>
|
||||
#include <noggit/ui/windows/downloadFileDialog/DownloadFileDialog.h>
|
||||
#include <noggit/TextureManager.h>
|
||||
#include <external/tsl/robin_map.h>
|
||||
#include <noggit/World.h>
|
||||
#include <noggit/Log.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
@@ -85,6 +88,22 @@ namespace Noggit::Project
|
||||
std::string MapName;
|
||||
};
|
||||
|
||||
struct NoggitExtraMapData
|
||||
{
|
||||
public:
|
||||
//Mists Heightmapping
|
||||
// Valid for every map that doesn't override its specific data
|
||||
tsl::robin_map< std::string, texture_heightmapping_data > TextureHeightData_Global;
|
||||
// MapID,TileX,TileY, SMTextureParams for this specific ADT, fallback to global otherwise.
|
||||
tsl::robin_map<int,
|
||||
tsl::robin_map< int, tsl::robin_map<int , tsl::robin_map<std::string, texture_heightmapping_data> >>> TextureHeightData_ADT;
|
||||
|
||||
void SetTextureHeightData_Global(const std::string& texture, texture_heightmapping_data data, World* worldToUpdate = nullptr);
|
||||
void SetTextureHeightDataForADT(int mapID, const TileIndex& ti, const std::string& texture, texture_heightmapping_data data, World* worldToUpdate = nullptr);
|
||||
|
||||
const texture_heightmapping_data GetTextureHeightDataForADT(int mapID, const TileIndex& ti, const std::string& texture) const;
|
||||
};
|
||||
|
||||
struct NoggitProjectObjectPalette
|
||||
{
|
||||
int MapId;
|
||||
@@ -120,6 +139,7 @@ namespace Noggit::Project
|
||||
std::vector<NoggitProjectTexturePalette> TexturePalettes;
|
||||
std::vector<NoggitProjectSelectionGroups> ObjectSelectionGroups;
|
||||
|
||||
NoggitExtraMapData ExtraMapData;
|
||||
NoggitProject()
|
||||
{
|
||||
PinnedMaps = std::vector<NoggitProjectPinnedMap>();
|
||||
@@ -330,7 +350,20 @@ namespace Noggit::Project
|
||||
return {};
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
if (modern_features)
|
||||
{
|
||||
Log << "Modern Features Enabled" << std::endl;
|
||||
loadExtraData(project.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log << "Modern Features Disabled" << std::endl;
|
||||
}
|
||||
return std::make_shared<NoggitProject>(project.value());
|
||||
}
|
||||
|
||||
void loadExtraData(NoggitProject& project);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1007,6 +1007,12 @@ void ModelRenderPass::bindTexture(size_t index, Model* m, OpenGL::M2RenderState&
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m->_specialTextures[tex] >= m->_replaceTextures.size())
|
||||
{
|
||||
LogError << "model: special texture index out of range " << m->file_key().stringRepr() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& texture = m->_replaceTextures.at (m->_specialTextures[tex]);
|
||||
texture->upload();
|
||||
GLuint tex_array = texture->texture_array();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <noggit/MapChunk.h>
|
||||
#include <noggit/ui/TexturingGUI.h>
|
||||
#include <external/tracy/Tracy.hpp>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
using namespace Noggit::Rendering;
|
||||
|
||||
@@ -520,18 +521,23 @@ bool TileRender::fillSamplers(MapChunk* chunk, unsigned chunk_index, unsigned i
|
||||
|
||||
static constexpr unsigned NUM_SAMPLERS = 11;
|
||||
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[0] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[1] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[2] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[3] = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[i] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[i] = -1;
|
||||
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[0] = -1;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[1] = -1;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[2] = -1;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[3] = -1;
|
||||
// Mists Heightmapping
|
||||
_chunk_instance_data[chunk_index].ChunkHeightTextureSamplers[i] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureUVScale[i] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureHeightScale[i] = 0;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureHeightOffset[i] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
auto& chunk_textures = (*chunk->texture_set->getTextures());
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
for (int k = 0; k < chunk->texture_set->num(); ++k)
|
||||
{
|
||||
chunk_textures[k]->upload();
|
||||
@@ -542,6 +548,26 @@ bool TileRender::fillSamplers(MapChunk* chunk, unsigned chunk_index, unsigned i
|
||||
continue;
|
||||
}
|
||||
|
||||
auto heightRef = chunk_textures[k]->getHeightMap();
|
||||
if (chunk_textures[k]->hasHeightMap() && heightRef)
|
||||
{
|
||||
heightRef->upload();
|
||||
|
||||
if(!heightRef->is_uploaded())
|
||||
{
|
||||
_texture_not_loaded = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (modern_features) {
|
||||
// Mists Heightmapping
|
||||
auto hData = chunk->mt->GetTextureHeightMappingData(chunk_textures[k]->file_key().filepath());
|
||||
_chunk_instance_data[chunk_index].ChunkTextureUVScale[k] = hData.uvScale;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureHeightScale[k] = hData.heightScale;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureHeightOffset[k] = hData.heightOffset;
|
||||
}
|
||||
|
||||
GLuint tex_array = (*chunk->texture_set->getTextures())[k]->texture_array();
|
||||
int tex_index = (*chunk->texture_set->getTextures())[k]->array_index();
|
||||
|
||||
@@ -572,7 +598,35 @@ bool TileRender::fillSamplers(MapChunk* chunk, unsigned chunk_index, unsigned i
|
||||
|
||||
_chunk_instance_data[chunk_index].ChunkTextureSamplers[k] = sampler_id;
|
||||
_chunk_instance_data[chunk_index].ChunkTextureArrayIDs[k] = (*chunk->texture_set->getTextures())[k]->is_specular() ? tex_index : -tex_index;
|
||||
|
||||
if(modern_features && heightRef)
|
||||
{
|
||||
GLuint hTex_array = (*chunk->texture_set->getTextures())[k]->getHeightMap()->texture_array();
|
||||
|
||||
sampler_id = -1;
|
||||
for (int n = 0; n < draw_call.samplers.size(); ++n)
|
||||
{
|
||||
if (draw_call.samplers[n] == hTex_array)
|
||||
{
|
||||
sampler_id = n;
|
||||
break;
|
||||
}
|
||||
else if (draw_call.samplers[n] < 0)
|
||||
{
|
||||
draw_call.samplers[n] = hTex_array;
|
||||
sampler_id = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sampler_id < 0)
|
||||
[[unlikely]]
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_chunk_instance_data[chunk_index].ChunkHeightTextureSamplers[k] = sampler_id;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "WMOGroupRender.hpp"
|
||||
#include <noggit/WMO.h>
|
||||
#include <noggit/Log.h> // LogDebug
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
using namespace Noggit::Rendering;
|
||||
|
||||
@@ -21,7 +22,11 @@ void WMOGroupRender::upload()
|
||||
std::size_t batch_counter = 0;
|
||||
for (auto& batch : _wmo_group->_batches)
|
||||
{
|
||||
WMOMaterial const& mat (_wmo_group->wmo->materials.at (batch.texture));
|
||||
std::uint16_t material_to_use = batch.texture;
|
||||
if (batch.flags == 2)
|
||||
material_to_use = batch.unused[5];
|
||||
|
||||
WMOMaterial const& mat(_wmo_group->wmo->materials.at(material_to_use));
|
||||
|
||||
auto& tex1 = _wmo_group->wmo->textures.at(mat.texture1);
|
||||
|
||||
@@ -33,7 +38,8 @@ void WMOGroupRender::upload()
|
||||
|
||||
std::uint32_t tex_array1 = 0;
|
||||
std::uint32_t array_index1 = 0;
|
||||
bool use_tex2 = mat.shader == 6 || mat.shader == 5 || mat.shader == 3;
|
||||
|
||||
bool use_tex2 = mat.shader == 6 || mat.shader == 5 || mat.shader == 3 || mat.shader == 21 || mat.shader == 23;
|
||||
|
||||
if (use_tex2)
|
||||
{
|
||||
@@ -61,13 +67,20 @@ void WMOGroupRender::upload()
|
||||
_draw_calls.clear();
|
||||
WMOCombinedDrawCall* draw_call = nullptr;
|
||||
std::vector<WMORenderBatch*> _used_batches;
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
batch_counter = 0;
|
||||
for (auto& batch : _wmo_group->_batches)
|
||||
{
|
||||
WMOMaterial& mat = _wmo_group->wmo->materials.at(batch.texture);
|
||||
std::uint16_t material_to_use = batch.texture;
|
||||
if (modern_features && batch.flags & 2)
|
||||
material_to_use = batch.unused[5];
|
||||
|
||||
WMOMaterial& mat(_wmo_group->wmo->materials.at(material_to_use));
|
||||
|
||||
bool backface_cull = !mat.flags.unculled;
|
||||
bool use_tex2 = mat.shader == 6 || mat.shader == 5 || mat.shader == 3;
|
||||
bool use_tex2 = mat.shader == 6 || mat.shader == 5 || mat.shader == 3 || mat.shader == 21 || mat.shader == 23;
|
||||
|
||||
bool create_draw_call = false;
|
||||
if (draw_call && draw_call->backface_cull == backface_cull && batch.index_start == draw_call->index_start + draw_call->index_count)
|
||||
@@ -336,6 +349,9 @@ void WMOGroupRender::initRenderBatches()
|
||||
|
||||
_render_batches.resize(_wmo_group->_batches.size());
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
std::size_t batch_counter = 0;
|
||||
for (auto& batch : _wmo_group->_batches)
|
||||
{
|
||||
@@ -361,7 +377,11 @@ void WMOGroupRender::initRenderBatches()
|
||||
flags |= WMORenderBatchFlags::eWMOBatch_HasMOCV;
|
||||
}
|
||||
|
||||
WMOMaterial const& mat (_wmo_group->wmo->materials.at (batch.texture));
|
||||
std::uint16_t material_to_use = batch.texture;
|
||||
if (modern_features && batch.flags == 2)
|
||||
material_to_use = batch.unused[5];
|
||||
|
||||
WMOMaterial const& mat (_wmo_group->wmo->materials.at (material_to_use));
|
||||
|
||||
if (mat.flags.unlit)
|
||||
{
|
||||
|
||||
@@ -74,15 +74,33 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
_terrain_params_ubo_data.draw_groundeffectid_overlay = false;
|
||||
_terrain_params_ubo_data.draw_groundeffect_layerid_overlay = false;
|
||||
_terrain_params_ubo_data.draw_noeffectdoodad_overlay = false;
|
||||
_terrain_params_ubo_data.draw_only_normals = minimap_render_settings->draw_only_normals;
|
||||
_terrain_params_ubo_data.point_normals_up = minimap_render_settings->point_normals_up;
|
||||
_need_terrain_params_ubo_update = true;
|
||||
}
|
||||
|
||||
// After coming out of minimap rendering mode and draw_only_normals is still on, disable it.
|
||||
if (!render_settings.minimap_render && _terrain_params_ubo_data.draw_only_normals) {
|
||||
_terrain_params_ubo_data.draw_only_normals = false;
|
||||
_need_terrain_params_ubo_update = true;
|
||||
}
|
||||
|
||||
// After coming out of minimap rendering mode and point_normals_up is still on, disable it.
|
||||
if (!render_settings.minimap_render && _terrain_params_ubo_data.point_normals_up) {
|
||||
_terrain_params_ubo_data.point_normals_up = false;
|
||||
_need_terrain_params_ubo_update = true;
|
||||
}
|
||||
|
||||
if (_need_terrain_params_ubo_update)
|
||||
updateTerrainParamsUniformBlock();
|
||||
|
||||
// Frustum culling
|
||||
_world->_n_loaded_tiles = 0;
|
||||
unsigned tile_counter = 0;
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
for (MapTile* tile : _world->mapIndex.loaded_tiles())
|
||||
{
|
||||
tile->_was_rendered_last_frame = false;
|
||||
@@ -243,6 +261,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
{
|
||||
OpenGL::Scoped::use_program mcnk_shader{ *_mcnk_program.get() };
|
||||
|
||||
mcnk_shader.uniform("enable_mists_heightmapping", modern_features);
|
||||
mcnk_shader.uniform("camera", glm::vec3(camera_pos.x, camera_pos.y, camera_pos.z));
|
||||
mcnk_shader.uniform("animtime", static_cast<int>(_world->animtime));
|
||||
|
||||
@@ -1572,10 +1591,17 @@ void WorldRender::updateLightingUniformBlockMinimap(MinimapRenderSettings* setti
|
||||
glm::vec3 diffuse = settings->diffuse_color;
|
||||
glm::vec3 ambient = settings->ambient_color;
|
||||
|
||||
_lighting_ubo_data.DiffuseColor_FogStart = { diffuse, 0 };
|
||||
_lighting_ubo_data.AmbientColor_FogEnd = { ambient, 0 };
|
||||
_lighting_ubo_data.FogColor_FogOn = { 0, 0, 0, 0 };
|
||||
_lighting_ubo_data.LightDir_FogRate = { _outdoor_light_stats.dayDir.x, _outdoor_light_stats.dayDir.y, _outdoor_light_stats.dayDir.z, _skies->fogRate() };
|
||||
if (settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES) {
|
||||
_lighting_ubo_data.DiffuseColor_FogStart = { 0.5, 0.5, 0.5, 0 };
|
||||
_lighting_ubo_data.AmbientColor_FogEnd = { 0.5, 0.5, 0.5, 0 };
|
||||
_lighting_ubo_data.LightDir_FogRate = { 0.0, -1.0, 0.0, _skies->fogRate() };
|
||||
}
|
||||
else {
|
||||
_lighting_ubo_data.DiffuseColor_FogStart = { diffuse, 0 };
|
||||
_lighting_ubo_data.AmbientColor_FogEnd = { ambient, 0 };
|
||||
_lighting_ubo_data.LightDir_FogRate = { _outdoor_light_stats.dayDir.x, _outdoor_light_stats.dayDir.y, _outdoor_light_stats.dayDir.z, _skies->fogRate() };
|
||||
}
|
||||
_lighting_ubo_data.OceanColorLight = settings->ocean_color_light;
|
||||
_lighting_ubo_data.OceanColorDark = settings->ocean_color_dark;
|
||||
_lighting_ubo_data.RiverColorLight = settings->river_color_light;
|
||||
@@ -1996,17 +2022,27 @@ bool WorldRender::saveMinimap(TileIndex const& tile_idx, MinimapRenderSettings*
|
||||
str += "/";
|
||||
}
|
||||
|
||||
QDir dir(str + "/textures/minimap/");
|
||||
QString target_dir = QString("/textures/minimap/");
|
||||
if(settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES || settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES_N)
|
||||
{
|
||||
target_dir = QString("/textures/maptextures/");
|
||||
}
|
||||
|
||||
QDir dir(str + target_dir);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
std::string tex_name = std::string(_world->basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".blp");
|
||||
if (settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES_N)
|
||||
{
|
||||
tex_name = std::string(_world->basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + "_n.blp");
|
||||
}
|
||||
|
||||
if (settings->file_format == ".png")
|
||||
{
|
||||
image.save(dir.filePath(std::string(_world->basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".png").c_str()));
|
||||
}
|
||||
else if (settings->file_format == ".blp")
|
||||
else if (settings->file_format == ".blp (DXT1)" || settings->file_format == ".blp (DXT5)")
|
||||
{
|
||||
QByteArray bytes;
|
||||
QBuffer buffer( &bytes );
|
||||
@@ -2020,7 +2056,7 @@ bool WorldRender::saveMinimap(TileIndex const& tile_idx, MinimapRenderSettings*
|
||||
uint32_t file_size;
|
||||
// void* blp_image = blp.createBlpDxtInMemory(true, FORMAT_DXT5, file_size);
|
||||
// this mirrors blizzards : dxt1, no mipmap
|
||||
void* blp_image = blp.createBlpDxtInMemory(false, FORMAT_DXT1, file_size);
|
||||
void* blp_image = blp.createBlpDxtInMemory(settings->file_format == ".blp (DXT5)" ? true : false, settings->file_format == ".blp (DXT5)" ? FORMAT_DXT5 : FORMAT_DXT1, file_size);
|
||||
|
||||
// converts the texture name to an md5 hash like blizzard, this is used to avoid duplicates textures for ocean
|
||||
// downside is that if the file gets updated regularly there will be a lot of duplicates in the project folder
|
||||
|
||||
94
src/noggit/rendering/glsl/terrain_frag.glsl
Executable file → Normal file
94
src/noggit/rendering/glsl/terrain_frag.glsl
Executable file → Normal file
@@ -36,6 +36,8 @@ layout (std140) uniform overlay_params
|
||||
int draw_groundeffectid_overlay;
|
||||
int draw_groundeffect_layerid_overlay;
|
||||
int draw_noeffectdoodad_overlay;
|
||||
int draw_only_normals;
|
||||
int point_normals_up;
|
||||
};
|
||||
|
||||
struct ChunkInstanceData
|
||||
@@ -48,6 +50,14 @@ struct ChunkInstanceData
|
||||
ivec4 AreaIDColor_Pad2_DrawSelection;
|
||||
ivec4 ChunkXZ_TileXZ;
|
||||
ivec4 ChunkTexAnimDir;
|
||||
|
||||
// Mists Heightmapping
|
||||
|
||||
ivec4 ChunkHeightTextureSamplers;
|
||||
ivec4 ChunkTextureUVScale;
|
||||
vec4 ChunkTextureHeightScale;
|
||||
vec4 ChunkTextureHeightOffset;
|
||||
|
||||
vec4 ChunkGroundEffectColor;
|
||||
// pack 8x8 bools in two ints. Simplified ChunksLayerEnabled to a bool instead of 2 bits id.
|
||||
// If those modes are mutually exclusive, we can do it in ChunkGroundEffectColor for now.
|
||||
@@ -71,6 +81,7 @@ uniform float cursorRotation;
|
||||
uniform float outer_cursor_radius;
|
||||
uniform float inner_cursor_ratio;
|
||||
uniform vec4 cursor_color;
|
||||
uniform bool enable_mists_heightmapping;
|
||||
|
||||
in vec3 vary_position;
|
||||
in vec2 vary_texcoord;
|
||||
@@ -188,6 +199,71 @@ vec4 get_tex_color(vec2 tex_coord, int tex_sampler, int array_index)
|
||||
|
||||
}
|
||||
|
||||
const int numChunks = 16;
|
||||
const int numTiles = 64;
|
||||
|
||||
vec2 getAdjustedUV(vec2 uv, int textureScale) {
|
||||
vec2 worldOffset = (numChunks * instances[instanceID].ChunkXZ_TileXZ.zw) + instances[instanceID].ChunkXZ_TileXZ.xy;
|
||||
|
||||
// Scale the UV coordinates. Wow Interprets texture scaling this way.
|
||||
vec2 combinedUV = fract((uv + worldOffset) / ((1 << textureScale) / 8.0f));
|
||||
|
||||
return combinedUV;
|
||||
}
|
||||
|
||||
vec4 mists_texture_blend()
|
||||
{
|
||||
vec3 alpha = texture(alphamap, vec3(vary_texcoord / 8.0, instanceID)).rgb;
|
||||
|
||||
int layer_count = instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b;
|
||||
|
||||
alpha.r = mix(alpha.r, 0.0, float(layer_count < 2));
|
||||
alpha.g = mix(alpha.g, 0.0, float(layer_count < 3));
|
||||
alpha.b = mix(alpha.b, 0.0, float(layer_count < 4));
|
||||
|
||||
|
||||
vec2 worldScaled_vary_t0_uv = getAdjustedUV(vary_t0_uv/8.0, instances[instanceID].ChunkTextureUVScale.x);
|
||||
vec2 worldScaled_vary_t1_uv = getAdjustedUV(vary_t1_uv/8.0, instances[instanceID].ChunkTextureUVScale.y);
|
||||
vec2 worldScaled_vary_t2_uv = getAdjustedUV(vary_t2_uv/8.0, instances[instanceID].ChunkTextureUVScale.z);
|
||||
vec2 worldScaled_vary_t3_uv = getAdjustedUV(vary_t3_uv/8.0, instances[instanceID].ChunkTextureUVScale.w);
|
||||
|
||||
// Mists HeightMapping: Multi Layer Blending.
|
||||
vec4 layer_weights = vec4(1.0 - clamp(dot(vec3(1.0),alpha), 0, 1), alpha);
|
||||
|
||||
vec4 t0h = get_tex_color(worldScaled_vary_t0_uv, instances[instanceID].ChunkHeightTextureSamplers.x, abs(instances[instanceID].ChunkTextureArrayIDs.x));
|
||||
vec4 t1h = get_tex_color(worldScaled_vary_t1_uv, instances[instanceID].ChunkHeightTextureSamplers.y, abs(instances[instanceID].ChunkTextureArrayIDs.y));
|
||||
vec4 t2h = get_tex_color(worldScaled_vary_t2_uv, instances[instanceID].ChunkHeightTextureSamplers.z, abs(instances[instanceID].ChunkTextureArrayIDs.z));
|
||||
vec4 t3h = get_tex_color(worldScaled_vary_t3_uv, instances[instanceID].ChunkHeightTextureSamplers.w, abs(instances[instanceID].ChunkTextureArrayIDs.w));
|
||||
|
||||
vec4 layer_pct = vec4 ( layer_weights.x * ( t0h.a * instances[instanceID].ChunkTextureHeightScale.x + instances[instanceID].ChunkTextureHeightOffset.x)
|
||||
, layer_weights.y * ( t1h.a * instances[instanceID].ChunkTextureHeightScale.y + instances[instanceID].ChunkTextureHeightOffset.y)
|
||||
, layer_weights.z * ( t2h.a * instances[instanceID].ChunkTextureHeightScale.z + instances[instanceID].ChunkTextureHeightOffset.z)
|
||||
, layer_weights.w * ( t3h.a * instances[instanceID].ChunkTextureHeightScale.w + instances[instanceID].ChunkTextureHeightOffset.w)
|
||||
);
|
||||
vec4 layer_pct_max = vec4( max( max(layer_pct.x, layer_pct.y) , max(layer_pct.z, layer_pct.w) ) );
|
||||
layer_pct = layer_pct * (vec4(1.0) - clamp(layer_pct_max - layer_pct, 0, 1));
|
||||
layer_pct = layer_pct / vec4( dot(vec4(1.0),layer_pct) );
|
||||
|
||||
vec4 t0 = get_tex_color(worldScaled_vary_t0_uv, instances[instanceID].ChunkTextureSamplers.x,
|
||||
abs(instances[instanceID].ChunkTextureArrayIDs.x)) * layer_pct.x;
|
||||
t0.a = mix(t0.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.x < 0));
|
||||
|
||||
vec4 t1 = get_tex_color(worldScaled_vary_t1_uv, instances[instanceID].ChunkTextureSamplers.y,
|
||||
abs(instances[instanceID].ChunkTextureArrayIDs.y)) * layer_pct.y;
|
||||
//vec4 t1 = get_tex_color(vary_t1_uv / 5 , instances[instanceID].ChunkTextureSamplers.y, abs(instances[instanceID].ChunkTextureArrayIDs.y));
|
||||
t1.a = mix(t1.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.y < 0));
|
||||
|
||||
vec4 t2 = get_tex_color(worldScaled_vary_t2_uv, instances[instanceID].ChunkTextureSamplers.z,
|
||||
abs(instances[instanceID].ChunkTextureArrayIDs.z)) * layer_pct.z;
|
||||
t2.a = mix(t2.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.z < 0));
|
||||
|
||||
vec4 t3 =get_tex_color(worldScaled_vary_t3_uv, instances[instanceID].ChunkTextureSamplers.w,
|
||||
abs(instances[instanceID].ChunkTextureArrayIDs.w)) * layer_pct.w;
|
||||
t3.a = mix(t3.a, 0.f, int(instances[instanceID].ChunkTextureArrayIDs.w < 0));
|
||||
|
||||
return vec4 (t0 + t1 + t2 + t3);//(t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2);
|
||||
}
|
||||
|
||||
vec4 texture_blend()
|
||||
{
|
||||
vec3 alpha = texture(alphamap, vec3(vary_texcoord / 8.0, instanceID)).rgb;
|
||||
@@ -243,6 +319,10 @@ void main()
|
||||
// vec3 accumlatedLight = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
vec3 normalized_normal = normalize(vary_normal);
|
||||
if(point_normals_up == 1)
|
||||
{
|
||||
normalized_normal = vec3(0, 1, 0);
|
||||
}
|
||||
float nDotL = clamp(dot(normalized_normal, -normalize(LightDir_FogRate.xyz)), 0.0, 1.0); // default LightDir = -0.6
|
||||
|
||||
vec3 skyColor = (AmbientColor_FogEnd.xyz * 1.10000002);
|
||||
@@ -255,7 +335,14 @@ void main()
|
||||
float specularFactor = max(dot(reflection, normalize(camera - vary_position)), 0.0);
|
||||
|
||||
// blend textures
|
||||
out_color = mix(vec4(1.0, 1.0, 1.0, 0.0), texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
|
||||
if(enable_mists_heightmapping)
|
||||
{
|
||||
out_color = mix(vec4(1.0, 1.0, 1.0, 0.0), mists_texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = mix(vec4(1.0, 1.0, 1.0, 0.0), texture_blend(), int(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.b > 0));
|
||||
}
|
||||
|
||||
vec3 spc = out_color.a * out_color.rgb * pow(specularFactor, 8);
|
||||
out_color.a = 1.0;
|
||||
@@ -533,4 +620,9 @@ void main()
|
||||
out_color.rgb = mix(cursor_color.rgb, out_color.rgb, alpha);*/
|
||||
}
|
||||
|
||||
if(draw_only_normals != 0)
|
||||
{
|
||||
out_color.rgb = vec3(vary_normal.z * -1, vary_normal.y, vary_normal.x * -1) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,14 @@ struct ChunkInstanceData
|
||||
ivec4 AreaIDColor_Pad2_DrawSelection;
|
||||
ivec4 ChunkXZ_TileXZ;
|
||||
ivec4 ChunkTexAnimDir;
|
||||
|
||||
// Mists Heightmapping
|
||||
|
||||
ivec4 ChunkHeightTextureSamplers;
|
||||
ivec4 ChunkTextureUVScale;
|
||||
vec4 ChunkTextureHeightScale;
|
||||
vec4 ChunkTextureHeightOffset;
|
||||
|
||||
vec4 ChunkGroundEffectColor;
|
||||
ivec4 ChunkDoodadsEnabled2_ChunksLayerEnabled2;
|
||||
};
|
||||
|
||||
@@ -194,6 +194,10 @@ void main()
|
||||
vec3 layer2 = mix(tex.rgb, tex_2.rgb, tex_2.a);
|
||||
out_color = vec4(apply_lighting(mix(layer2, tex.rgb, vertex_color.a)), 1.);
|
||||
}
|
||||
else if (shader == 21 || shader == 23)
|
||||
{
|
||||
out_color = vec4(apply_lighting(tex_2.rgb), 1.);
|
||||
}
|
||||
else // default shader, used for shader 0,1,2,4 (Diffuse, Specular, Metal, Opaque)
|
||||
{
|
||||
out_color = vec4(apply_lighting(tex.rgb), 1.);
|
||||
|
||||
8
src/noggit/scripting/script_global.cpp
Executable file → Normal file
8
src/noggit/scripting/script_global.cpp
Executable file → Normal file
@@ -41,12 +41,20 @@ namespace Noggit {
|
||||
state->set_function("add_wmo",[global](
|
||||
std::string const& filename
|
||||
, glm::vec3 const& pos
|
||||
, float scale
|
||||
, glm::vec3 const& rotation)
|
||||
{
|
||||
// note: we set both min/max random scale and the normal scale parameter,
|
||||
// because noggit picks one based on random scale settings in the object tool
|
||||
object_paste_params p;
|
||||
p.minScale = scale;
|
||||
p.maxScale = scale;
|
||||
global->get_view()->_world.get()->addWMO(
|
||||
filename
|
||||
, pos
|
||||
, scale
|
||||
, math::degrees::vec3(rotation)
|
||||
, &p
|
||||
, false);
|
||||
});
|
||||
|
||||
|
||||
5
src/noggit/scripting/script_model.cpp
Executable file → Normal file
5
src/noggit/scripting/script_model.cpp
Executable file → Normal file
@@ -53,13 +53,10 @@ namespace Noggit
|
||||
|
||||
void model::set_scale(float scale)
|
||||
{
|
||||
if (_object->which() != eWMO)
|
||||
{
|
||||
world()->updateTilesEntry(_object, model_update::remove);
|
||||
_object->scale = scale;
|
||||
_object->recalcExtents();
|
||||
world()->updateTilesEntry(_object, model_update::add);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned model::get_uid()
|
||||
@@ -101,7 +98,7 @@ namespace Noggit
|
||||
if (filename.ends_with(".wmo"))
|
||||
{
|
||||
_object =
|
||||
world()->addWMOAndGetInstance(filename, get_pos(), math::degrees::vec3 {get_rot()}, false);
|
||||
world()->addWMOAndGetInstance(filename, get_pos(), math::degrees::vec3 {get_rot()}, get_scale(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
7
src/noggit/texture_set.cpp
Executable file → Normal file
7
src/noggit/texture_set.cpp
Executable file → Normal file
@@ -295,6 +295,13 @@ bool TextureSet::eraseUnusedTextures()
|
||||
return false;
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
bool cleanup_unused_textures = settings.value("cleanup_unused_textures", true).toBool();
|
||||
if (!cleanup_unused_textures)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<int> visible_tex;
|
||||
|
||||
if (tmp_edit_values)
|
||||
|
||||
5
src/noggit/texture_set.hpp
Executable file → Normal file
5
src/noggit/texture_set.hpp
Executable file → Normal file
@@ -150,6 +150,11 @@ private:
|
||||
|
||||
std::vector<scoped_blp_texture_reference> textures;
|
||||
std::array<std::unique_ptr<Alphamap>, MAX_ALPHAMAPS> alphamaps;
|
||||
|
||||
// Mists Heightmapping
|
||||
std::vector<scoped_blp_texture_reference> heightTextures;
|
||||
std::array<texture_heightmapping_data, 4> heightMappingData;
|
||||
|
||||
size_t nTextures;
|
||||
|
||||
// byte[8][8] // can store the 2bits value in a byte, but might never be higher than 3 or layer count.
|
||||
|
||||
@@ -182,6 +182,8 @@ namespace Noggit
|
||||
break;
|
||||
}
|
||||
case MinimapGenMode::MAP:
|
||||
case MinimapGenMode::LOD_MAPTEXTURES:
|
||||
case MinimapGenMode::LOD_MAPTEXTURES_N:
|
||||
{
|
||||
// init progress
|
||||
if (!_mmap_async_index)
|
||||
@@ -192,6 +194,26 @@ namespace Noggit
|
||||
if (!saving_minimap)
|
||||
return false;
|
||||
|
||||
QSettings noggitSettings;
|
||||
bool modern_features = noggitSettings.value("modern_features", false).toBool();
|
||||
if (modern_features && (settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES || settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES_N)) {
|
||||
settings->draw_m2 = false;
|
||||
settings->draw_wmo = false;
|
||||
settings->draw_water = false;
|
||||
settings->resolution = 512;
|
||||
settings->file_format = ".blp (DXT5)";
|
||||
|
||||
if (settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES_N)
|
||||
{
|
||||
settings->draw_only_normals = true;
|
||||
settings->resolution = 256;
|
||||
}
|
||||
else if (settings->export_mode == MinimapGenMode::LOD_MAPTEXTURES) {
|
||||
// Point normals upwards for diffuse maptexture baking
|
||||
settings->point_normals_up = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_mmap_async_index < 4096 && static_cast<int>(_mmap_render_index) < progress->maximum())
|
||||
{
|
||||
save();
|
||||
|
||||
@@ -315,7 +315,7 @@ namespace Noggit
|
||||
// auto replace_wmo = static_cast<WMOInstance*>(replacement_obj);
|
||||
// auto source_wmo = static_cast<WMOInstance*>(old_obj);
|
||||
|
||||
auto new_obj = world->addWMOAndGetInstance(replace_path, source_pos, source_rot, true);
|
||||
auto new_obj = world->addWMOAndGetInstance(replace_path, source_pos, source_rot, source_scale, true);
|
||||
new_obj->wmo->wait_until_loaded();
|
||||
new_obj->wmo->waitForChildrenLoaded();
|
||||
new_obj->recalcExtents();
|
||||
@@ -521,7 +521,7 @@ namespace Noggit
|
||||
{
|
||||
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
|
||||
Noggit::ActionModalityControllers::eSCALE);
|
||||
world->scale_selected_models(_keys * numpad_moveratio / 50.f, World::m2_scaling_type::add);
|
||||
world->scale_selected_models(_keys * numpad_moveratio / 50.f, World::object_scaling_type::add);
|
||||
updateRotationEditor();
|
||||
}
|
||||
if (_keyr != 0.f)
|
||||
@@ -543,7 +543,7 @@ namespace Noggit
|
||||
NOGGIT_ACTION_MGR->beginAction(mv, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
|
||||
Noggit::ActionModalityControllers::eALT
|
||||
| Noggit::ActionModalityControllers::eMMB);
|
||||
world->scale_selected_models(std::pow(2.f, _mv * 4.f), World::m2_scaling_type::mult);
|
||||
world->scale_selected_models(std::pow(2.f, _mv * 4.f), World::object_scaling_type::mult);
|
||||
}
|
||||
else if (params.mod_shift_down)
|
||||
{
|
||||
@@ -688,7 +688,7 @@ namespace Noggit
|
||||
float min = _object_paste_params.minScale;
|
||||
float max = _object_paste_params.maxScale;
|
||||
|
||||
world->scale_selected_models(misc::randfloat(min, max), World::m2_scaling_type::set);
|
||||
world->scale_selected_models(misc::randfloat(min, max), World::object_scaling_type::set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <QtGui/QDrag>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
|
||||
namespace Noggit
|
||||
{
|
||||
|
||||
@@ -65,11 +65,24 @@ namespace Noggit
|
||||
auto cur_adt_btn = new QPushButton("Current ADT", generate_widget);
|
||||
auto sel_adts_btn = new QPushButton("Selected ADTs", generate_widget);
|
||||
auto all_adts_btn = new QPushButton("Map", generate_widget);
|
||||
auto maptexture_btn = new QPushButton("Map Textures", generate_widget);
|
||||
maptexture_btn->setVisible(false);
|
||||
auto maptexture_n_btn = new QPushButton("Map Textures (Normals)", generate_widget);
|
||||
maptexture_n_btn->setVisible(false);
|
||||
|
||||
generate_layout->addRow (cur_adt_btn);
|
||||
generate_layout->addRow (sel_adts_btn);
|
||||
generate_layout->addRow (all_adts_btn);
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
if (modern_features) {
|
||||
generate_layout->addRow (maptexture_btn);
|
||||
maptexture_btn->setVisible(true);
|
||||
generate_layout->addRow(maptexture_n_btn);
|
||||
maptexture_n_btn->setVisible(true);
|
||||
}
|
||||
|
||||
// Render settings box
|
||||
auto render_settings_box = new QGroupBox("Render options", generate_widget);
|
||||
generate_layout->addRow (render_settings_box);
|
||||
@@ -88,9 +101,10 @@ namespace Noggit
|
||||
render_settings_box_layout->addRow (resolution);
|
||||
|
||||
auto file_format = new QComboBox(this);
|
||||
file_format->addItem(".blp");
|
||||
file_format->addItem(".blp (DXT1)");
|
||||
file_format->addItem(".blp (DXT5)");
|
||||
file_format->addItem(".png");
|
||||
file_format->setCurrentText(".blp");
|
||||
file_format->setCurrentText(".blp (DXT1)");
|
||||
|
||||
render_settings_box_layout->addRow (file_format);
|
||||
|
||||
@@ -840,6 +854,16 @@ namespace Noggit
|
||||
emit onSave();
|
||||
});
|
||||
|
||||
connect(maptexture_btn, &QPushButton::clicked, [=]() {
|
||||
_render_settings.export_mode = MinimapGenMode::LOD_MAPTEXTURES;
|
||||
emit onSave();
|
||||
});
|
||||
|
||||
connect(maptexture_n_btn, &QPushButton::clicked, [=]() {
|
||||
_render_settings.export_mode = MinimapGenMode::LOD_MAPTEXTURES_N;
|
||||
emit onSave();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void MinimapCreator::changeRadius(float change)
|
||||
|
||||
0
src/noggit/ui/MinimapCreator.hpp
Executable file → Normal file
0
src/noggit/ui/MinimapCreator.hpp
Executable file → Normal file
8
src/noggit/ui/ObjectEditor.cpp
Executable file → Normal file
8
src/noggit/ui/ObjectEditor.cpp
Executable file → Normal file
@@ -700,14 +700,16 @@ namespace Noggit
|
||||
}
|
||||
else if (obj->which() == eWMO)
|
||||
{
|
||||
float scale(1.f);
|
||||
math::degrees::vec3 rotation(math::degrees(0)._, math::degrees(0)._, math::degrees(0)._);
|
||||
if (_copy_model_stats)
|
||||
{
|
||||
// copy rot from original model. Dirty but working
|
||||
// copy rot size from original model. Dirty but working
|
||||
scale = obj->scale;
|
||||
rotation = obj->dir;
|
||||
}
|
||||
|
||||
auto new_obj = world->addWMOAndGetInstance(obj->instance_model()->file_key(), pos, rotation, true);
|
||||
auto new_obj = world->addWMOAndGetInstance(obj->instance_model()->file_key(), pos, rotation, scale, true);
|
||||
new_obj->wmo->wait_until_loaded();
|
||||
new_obj->wmo->waitForChildrenLoaded();
|
||||
new_obj->recalcExtents();
|
||||
@@ -834,6 +836,8 @@ namespace Noggit
|
||||
{
|
||||
auto original = static_cast<WMOInstance*>(obj);
|
||||
auto clone = new WMOInstance(original->wmo->file_key().filepath(), _map_view->getRenderContext());
|
||||
|
||||
clone->scale = original->scale;
|
||||
clone->dir = original->dir;
|
||||
clone->pos = pivot ? original->pos - pivot.value() : glm::vec3();
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace Noggit
|
||||
{
|
||||
NOGGIT_ACTION_MGR->beginAction(reinterpret_cast<MapView*>(parent),
|
||||
Noggit::ActionFlags::eOBJECTS_TRANSFORMED);
|
||||
world->scale_selected_models(v, World::m2_scaling_type::set);
|
||||
world->scale_selected_models(v, World::object_scaling_type::set);
|
||||
NOGGIT_ACTION_MGR->endAction();
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ namespace Noggit
|
||||
{
|
||||
NOGGIT_ACTION_MGR->beginAction(reinterpret_cast<MapView*>(parent),
|
||||
Noggit::ActionFlags::eOBJECTS_TRANSFORMED);
|
||||
world->scale_selected_models(_scale->value(), World::m2_scaling_type::mult);
|
||||
world->scale_selected_models(_scale->value(), World::object_scaling_type::mult);
|
||||
NOGGIT_ACTION_MGR->endAction();
|
||||
}
|
||||
else // reset value
|
||||
@@ -268,7 +268,23 @@ namespace Noggit
|
||||
|
||||
auto obj = std::get<selected_object_type>(selection);
|
||||
|
||||
_scale->setEnabled(obj->which() != eWMO);
|
||||
if(obj->which() == eWMO)
|
||||
{
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
if(modern_features)
|
||||
{
|
||||
_scale->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_scale->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_scale->setEnabled(true);
|
||||
}
|
||||
|
||||
_position_x->setValue(obj->pos.x);
|
||||
_position_y->setValue(obj->pos.y);
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Noggit
|
||||
|
||||
_radius_slider = new Noggit::Ui::Tools::UiCommon::ExtendedSlider (this);
|
||||
_radius_slider->setPrefix("Radius:");
|
||||
_radius_slider->setRange(0, 1000);
|
||||
_radius_slider->setRange(0, 10000);
|
||||
_radius_slider->setDecimals(2);
|
||||
_radius_slider->setValue (15.0f);
|
||||
|
||||
|
||||
0
src/noggit/ui/TexturePicker.cpp
Executable file → Normal file
0
src/noggit/ui/TexturePicker.cpp
Executable file → Normal file
40
src/noggit/ui/TexturingGUI.cpp
Executable file → Normal file
40
src/noggit/ui/TexturingGUI.cpp
Executable file → Normal file
@@ -67,6 +67,10 @@ namespace Noggit
|
||||
std::vector<std::string> tilesets;
|
||||
std::unordered_set<std::string> tilesets_with_specular_variant;
|
||||
|
||||
// If modern features are enabled, set filtering to height textures (_h), otherwise specular (_s).
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
for (auto const& entry_pair : Application::NoggitApplication::instance()->clientData()->listfile()->pathToFileDataIDMap())
|
||||
{
|
||||
std::string const& filepath = entry_pair.first;
|
||||
@@ -75,7 +79,7 @@ namespace Noggit
|
||||
&& filepath.find (".blp") != std::string::npos
|
||||
)
|
||||
{
|
||||
auto suffix_pos (filepath.find ("_s.blp"));
|
||||
auto suffix_pos (filepath.find (modern_features ? "_h.blp" : "_s.blp"));
|
||||
if (suffix_pos == std::string::npos)
|
||||
{
|
||||
tilesets.emplace_back (filepath);
|
||||
@@ -83,7 +87,7 @@ namespace Noggit
|
||||
else
|
||||
{
|
||||
std::string specular (filepath);
|
||||
specular.erase (suffix_pos, strlen ("_s"));
|
||||
specular.erase (suffix_pos, strlen (modern_features ? "_h" : "_s"));
|
||||
tilesets_with_specular_variant.emplace (specular);
|
||||
}
|
||||
}
|
||||
@@ -107,7 +111,7 @@ namespace Noggit
|
||||
&& entry.find("_h.blp") == std::string::npos // skip _h textures
|
||||
)
|
||||
{
|
||||
auto suffix_pos (entry.find ("_s.blp"));
|
||||
auto suffix_pos (entry.find (modern_features ? "_h.blp" : "_s.blp"));
|
||||
if (suffix_pos == std::string::npos)
|
||||
{
|
||||
tilesets.emplace_back (entry);
|
||||
@@ -115,7 +119,7 @@ namespace Noggit
|
||||
else
|
||||
{
|
||||
std::string specular (entry);
|
||||
specular.erase (suffix_pos, strlen ("_s"));
|
||||
specular.erase (suffix_pos, strlen (modern_features ? "_h" : "_s"));
|
||||
tilesets_with_specular_variant.emplace (specular);
|
||||
}
|
||||
}
|
||||
@@ -138,12 +142,12 @@ namespace Noggit
|
||||
model->appendRow (item);
|
||||
}
|
||||
|
||||
auto specular_filter (new QSortFilterProxyModel);
|
||||
specular_filter->setSourceModel (model);
|
||||
specular_filter->setFilterRole (has_specular_role);
|
||||
auto texture_filter (new QSortFilterProxyModel);
|
||||
texture_filter->setSourceModel (model);
|
||||
texture_filter->setFilterRole (has_specular_role);
|
||||
|
||||
auto search_filter (new QSortFilterProxyModel);
|
||||
search_filter->setSourceModel (specular_filter);
|
||||
search_filter->setSourceModel (texture_filter);
|
||||
search_filter->sort (0, Qt::AscendingOrder);
|
||||
|
||||
|
||||
@@ -165,17 +169,19 @@ namespace Noggit
|
||||
}
|
||||
);
|
||||
|
||||
auto texture_filter_box(new QCheckBox("only with specular texture variant"));
|
||||
|
||||
auto only_specular (new QCheckBox ("only with specular texture variant"));
|
||||
connect ( only_specular, &QCheckBox::toggled
|
||||
, [=] (bool on)
|
||||
{
|
||||
specular_filter->setFilterRegExp (on ? "true" : "");
|
||||
}
|
||||
);
|
||||
only_specular->setChecked (false);
|
||||
if (modern_features)
|
||||
texture_filter_box->setText("only with height texture variant");
|
||||
|
||||
connect(texture_filter_box, &QCheckBox::toggled
|
||||
, [=](bool on)
|
||||
{
|
||||
texture_filter->setFilterRegExp(on ? "true" : "");
|
||||
}
|
||||
);
|
||||
|
||||
texture_filter_box->setChecked(true);
|
||||
|
||||
auto list = new TextureList(this);
|
||||
list->setEditTriggers (QAbstractItemView::NoEditTriggers);
|
||||
@@ -214,7 +220,7 @@ namespace Noggit
|
||||
layout->addLayout (top_bar);
|
||||
top_bar->addWidget (size_slider);
|
||||
top_bar->addStretch();
|
||||
top_bar->addWidget (only_specular);
|
||||
top_bar->addWidget (texture_filter_box);
|
||||
top_bar->addWidget (filter);
|
||||
layout->addWidget (list);
|
||||
|
||||
|
||||
132
src/noggit/ui/texturing_tool.cpp
Executable file → Normal file
132
src/noggit/ui/texturing_tool.cpp
Executable file → Normal file
@@ -12,18 +12,21 @@
|
||||
#include <noggit/ui/texture_swapper.hpp>
|
||||
#include <noggit/DBC.h>
|
||||
#include <util/qt/overload.hpp>
|
||||
#include <noggit/TextureManager.h>
|
||||
#include <noggit/ui/tools/AssetBrowser/Ui/AssetBrowser.hpp>
|
||||
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QTabWidget>
|
||||
#include <noggit/ui/tools/UiCommon/ExtendedSlider.hpp>
|
||||
#include <QClipboard>
|
||||
#include <noggit/ui/tools/UiCommon/expanderwidget.h>
|
||||
#include <noggit/ui/WeightListWidgetItem.hpp>
|
||||
#include <noggit/ui/FontAwesome.hpp>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <noggit/project/CurrentProject.hpp>
|
||||
|
||||
namespace Noggit
|
||||
{
|
||||
@@ -208,8 +211,73 @@ namespace Noggit
|
||||
tool_layout->addWidget(quick_palette_btn);
|
||||
tool_layout->setAlignment(quick_palette_btn, Qt::AlignTop);
|
||||
|
||||
// Mists HeightMapping, only enable if modern feature setting is on
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
auto geffect_tools_btn(new QPushButton(/*"Ground Effect Tools"*/ "In developement", this));
|
||||
// Define UI elements regardless of modern_features being enabled because they're used later on as well.
|
||||
_heightmapping_group = new QGroupBox("Height Mapping", tool_widget);
|
||||
_heightmapping_group->setVisible(modern_features);
|
||||
|
||||
auto heightmapping_scale_spin = new QDoubleSpinBox(_heightmapping_group);
|
||||
heightmapping_scale_spin->setVisible(modern_features);
|
||||
|
||||
auto heightmapping_heightscale_spin = new QDoubleSpinBox(_heightmapping_group);
|
||||
heightmapping_heightscale_spin->setVisible(modern_features);
|
||||
|
||||
auto heightmapping_heightoffset_spin = new QDoubleSpinBox(_heightmapping_group);
|
||||
heightmapping_heightoffset_spin->setVisible(modern_features);
|
||||
|
||||
QPushButton* _heightmapping_copy_btn = new QPushButton("Copy to JSON", this);
|
||||
_heightmapping_copy_btn->setVisible(modern_features);
|
||||
|
||||
if (modern_features) {
|
||||
|
||||
auto heightmapping_group_layout(new QFormLayout(_heightmapping_group));
|
||||
|
||||
heightmapping_scale_spin->setRange(0, 512);
|
||||
heightmapping_scale_spin->setSingleStep(1);
|
||||
heightmapping_scale_spin->setDecimals(0);
|
||||
heightmapping_scale_spin->setValue(0);
|
||||
heightmapping_group_layout->addRow("Scale:", heightmapping_scale_spin);
|
||||
|
||||
heightmapping_heightscale_spin->setRange(-512, 512);
|
||||
heightmapping_heightscale_spin->setSingleStep(0.1);
|
||||
heightmapping_heightscale_spin->setDecimals(3);
|
||||
heightmapping_heightscale_spin->setValue(0);
|
||||
heightmapping_group_layout->addRow("Height Scale:", heightmapping_heightscale_spin);
|
||||
|
||||
heightmapping_heightoffset_spin->setRange(-512, 512);
|
||||
heightmapping_heightoffset_spin->setSingleStep(0.1);
|
||||
heightmapping_heightoffset_spin->setDecimals(3);
|
||||
heightmapping_heightoffset_spin->setValue(1);
|
||||
heightmapping_group_layout->addRow("Height Offset:", heightmapping_heightoffset_spin);
|
||||
|
||||
auto heightmapping_btngroup_layout(new QVBoxLayout(_heightmapping_group));
|
||||
auto heightmapping_buttons_widget = new QWidget(_heightmapping_group);
|
||||
heightmapping_buttons_widget->setLayout(heightmapping_btngroup_layout);
|
||||
|
||||
auto wrap_label = new QLabel("Note: This doesn't save to .cfg, use copy and do it manually.", _heightmapping_group);
|
||||
wrap_label->setWordWrap(true);
|
||||
heightmapping_group_layout->addRow(wrap_label);
|
||||
|
||||
_heightmapping_apply_global_btn = new QPushButton("Apply (Global)", this);
|
||||
_heightmapping_apply_global_btn->setFixedHeight(30);
|
||||
heightmapping_btngroup_layout->addWidget(_heightmapping_apply_global_btn);
|
||||
|
||||
_heightmapping_apply_adt_btn = new QPushButton("Apply (Current ADT)", this);
|
||||
_heightmapping_apply_adt_btn->setFixedHeight(30);
|
||||
heightmapping_btngroup_layout->addWidget(_heightmapping_apply_adt_btn);
|
||||
|
||||
_heightmapping_copy_btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
_heightmapping_copy_btn->setFixedHeight(30);
|
||||
heightmapping_btngroup_layout->addWidget(_heightmapping_copy_btn);
|
||||
|
||||
heightmapping_group_layout->addRow(heightmapping_buttons_widget);
|
||||
|
||||
tool_layout->addWidget(_heightmapping_group);
|
||||
}
|
||||
|
||||
auto geffect_tools_btn(new QPushButton("In development", this));
|
||||
tool_layout->addWidget(geffect_tools_btn);
|
||||
tool_layout->setAlignment(geffect_tools_btn, Qt::AlignTop);
|
||||
|
||||
@@ -261,6 +329,28 @@ namespace Noggit
|
||||
|
||||
connect (anim_speed_slider, &QSlider::valueChanged, &_anim_speed_prop, &Noggit::unsigned_int_property::set);
|
||||
connect (anim_orientation_dial, &QDial::valueChanged, &_anim_rotation_prop, &Noggit::unsigned_int_property::set);
|
||||
|
||||
if (modern_features) {
|
||||
connect(heightmapping_scale_spin, qOverload<double>(&QDoubleSpinBox::valueChanged)
|
||||
, [&](double v)
|
||||
{
|
||||
textureHeightmappingData.uvScale = v;
|
||||
}
|
||||
);
|
||||
|
||||
connect(heightmapping_heightscale_spin, qOverload<double>(&QDoubleSpinBox::valueChanged)
|
||||
, [&](double v)
|
||||
{
|
||||
textureHeightmappingData.heightScale = v;
|
||||
}
|
||||
);
|
||||
connect(heightmapping_heightoffset_spin, qOverload<double>(&QDoubleSpinBox::valueChanged)
|
||||
, [&](double v)
|
||||
{
|
||||
textureHeightmappingData.heightOffset = v;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
connect ( tabs, &QTabWidget::currentChanged
|
||||
, [this] (int index)
|
||||
@@ -377,7 +467,47 @@ namespace Noggit
|
||||
connect (_radius_slider, &Noggit::Ui::Tools::UiCommon::ExtendedSlider::valueChanged, this, &texturing_tool::updateMaskImage);
|
||||
connect(_image_mask_group, &Noggit::Ui::Tools::ImageMaskSelector::pixmapUpdated, this, &texturing_tool::updateMaskImage);
|
||||
|
||||
// Mists Heightmapping
|
||||
|
||||
if (modern_features) {
|
||||
connect(_current_texture, &Noggit::Ui::current_texture::texture_updated
|
||||
, [=]()
|
||||
{
|
||||
auto proj = Noggit::Project::CurrentProject::get();
|
||||
auto foundTexture = proj->ExtraMapData.TextureHeightData_Global.find(_current_texture->filename());
|
||||
if (foundTexture != proj->ExtraMapData.TextureHeightData_Global.end())
|
||||
{
|
||||
heightmapping_scale_spin->setValue(foundTexture->second.uvScale);
|
||||
heightmapping_heightscale_spin->setValue(foundTexture->second.heightScale);
|
||||
heightmapping_heightoffset_spin->setValue(foundTexture->second.heightOffset);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
connect(_heightmapping_copy_btn, &QPushButton::pressed
|
||||
, [=]()
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "{\r\n \"" << _current_texture->filename() << "\": {\r\n"
|
||||
<< " \"Scale\": " << textureHeightmappingData.uvScale << ",\r\n"
|
||||
<< " \"HeightScale\": " << textureHeightmappingData.heightScale << ",\r\n"
|
||||
<< " \"HeightOffset\": " << textureHeightmappingData.heightOffset << "\r\n"
|
||||
<< " }\r\n}";
|
||||
|
||||
QClipboard* clip = QApplication::clipboard();
|
||||
clip->setText(QString::fromStdString(oss.str()));
|
||||
|
||||
QMessageBox::information
|
||||
(nullptr
|
||||
, "Copied"
|
||||
, "JSON Copied to Clipboard",
|
||||
QMessageBox::Ok
|
||||
);
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_spray_content->hide();
|
||||
update_brush_hardness();
|
||||
|
||||
10
src/noggit/ui/texturing_tool.hpp
Executable file → Normal file
10
src/noggit/ui/texturing_tool.hpp
Executable file → Normal file
@@ -199,6 +199,9 @@ namespace Noggit
|
||||
QJsonObject toJSON();
|
||||
void fromJSON(QJsonObject const& json);
|
||||
|
||||
QPushButton* const heightmappingApplyGlobalButton() { return _heightmapping_apply_global_btn; }
|
||||
QPushButton* const heightmappingApplyAdtButton() { return _heightmapping_apply_adt_btn; }
|
||||
texture_heightmapping_data& getCurrentHeightMappingSetting() {return textureHeightmappingData; }
|
||||
signals:
|
||||
void texturePaletteToggled();
|
||||
|
||||
@@ -217,6 +220,8 @@ namespace Noggit
|
||||
int _brush_level;
|
||||
bool _show_unpaintable_chunks;
|
||||
|
||||
int* _heightinfo_group;
|
||||
|
||||
float _spray_size;
|
||||
float _spray_pressure;
|
||||
|
||||
@@ -226,6 +231,7 @@ namespace Noggit
|
||||
BoolToggleProperty _overbright_prop;
|
||||
|
||||
texturing_mode _texturing_mode; // use getTexturingMode() to check for ground effect mode
|
||||
texture_heightmapping_data textureHeightmappingData;
|
||||
|
||||
private:
|
||||
OpacitySlider* _brush_level_slider;
|
||||
@@ -248,6 +254,10 @@ namespace Noggit
|
||||
|
||||
texture_swapper* _texture_switcher;
|
||||
|
||||
QGroupBox* _heightmapping_group;
|
||||
QPushButton* _heightmapping_apply_global_btn;
|
||||
QPushButton* _heightmapping_apply_adt_btn;
|
||||
|
||||
GroundEffectsTool* _ground_effect_tool;
|
||||
|
||||
Noggit::Ui::Tools::ImageMaskSelector* _image_mask_group;
|
||||
|
||||
10
src/noggit/ui/tools/LightEditor/LightEditor.cpp
Executable file → Normal file
10
src/noggit/ui/tools/LightEditor/LightEditor.cpp
Executable file → Normal file
@@ -1,7 +1,6 @@
|
||||
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
||||
|
||||
#include "LightEditor.hpp"
|
||||
#include <noggit/DBC.h>
|
||||
#include <noggit/World.h>
|
||||
#include <noggit/MapView.h>
|
||||
#include <noggit/ui/FontAwesome.hpp>
|
||||
@@ -20,6 +19,7 @@
|
||||
#include <QTextStream>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
using namespace Noggit::Ui::Tools;
|
||||
|
||||
LightEditor::LightEditor(MapView* map_view, QWidget* parent)
|
||||
@@ -321,14 +321,14 @@ LightEditor::LightEditor(MapView* map_view, QWidget* parent)
|
||||
global_values_layout->addRow(name_layout);
|
||||
|
||||
pos_x_spin = new QDoubleSpinBox(this);
|
||||
pos_x_spin->setRange(-17066.66656 * 2, 17066.66656 * 2); // size = <20>17066.66656
|
||||
pos_x_spin->setRange(-17066.66656 * 2, 17066.66656 * 2); // size = <20>17066.66656
|
||||
pos_x_spin->setValue(0);
|
||||
pos_x_spin->setSingleStep(50);
|
||||
pos_x_spin->setEnabled(false);
|
||||
global_values_layout->addRow("Position X:", pos_x_spin);
|
||||
|
||||
pos_y_spin = new QDoubleSpinBox(this);
|
||||
pos_y_spin->setRange(-17066.66656 * 2, 17066.66656 * 2); // size = <20>17066.66656
|
||||
pos_y_spin->setRange(-17066.66656 * 2, 17066.66656 * 2); // size = <20>17066.66656
|
||||
pos_y_spin->setValue(0);
|
||||
pos_y_spin->setSingleStep(50);
|
||||
pos_y_spin->setEnabled(false);
|
||||
@@ -342,14 +342,14 @@ LightEditor::LightEditor(MapView* map_view, QWidget* parent)
|
||||
global_values_layout->addRow("Position Z:", pos_z_spin);
|
||||
|
||||
inner_radius_spin = new QDoubleSpinBox(this);
|
||||
inner_radius_spin->setRange(0, 100000); // max seen in dbc is 3871 (139363 <20>E36 )
|
||||
inner_radius_spin->setRange(0, 100000); // max seen in dbc is 3871 (139363 <20>E36 )
|
||||
inner_radius_spin->setValue(0);
|
||||
inner_radius_spin->setSingleStep(50);
|
||||
inner_radius_spin->setEnabled(false);
|
||||
global_values_layout->addRow("Inner Radius:", inner_radius_spin);
|
||||
|
||||
outer_radius_spin = new QDoubleSpinBox(this);
|
||||
outer_radius_spin->setRange(0, 100000); // max seen in dbc is 3871 (139363 <20>E36 )
|
||||
outer_radius_spin->setRange(0, 100000); // max seen in dbc is 3871 (139363 <20>E36 )
|
||||
outer_radius_spin->setValue(0);
|
||||
outer_radius_spin->setSingleStep(50);
|
||||
outer_radius_spin->setEnabled(false);
|
||||
|
||||
0
src/noggit/ui/tools/LightEditor/LightEditor.hpp
Executable file → Normal file
0
src/noggit/ui/tools/LightEditor/LightEditor.hpp
Executable file → Normal file
2
src/noggit/ui/tools/NodeEditor/Nodes/World/Object/AddObjectInstance.cpp
Executable file → Normal file
2
src/noggit/ui/tools/NodeEditor/Nodes/World/Object/AddObjectInstance.cpp
Executable file → Normal file
@@ -62,7 +62,7 @@ void AddObjectInstanceNode::compute()
|
||||
}
|
||||
else if (QString(path.c_str()).endsWith(".wmo", Qt::CaseInsensitive))
|
||||
{
|
||||
obj = world->addWMOAndGetInstance(path, {pos.x, pos.y, pos.z}, {math::degrees(dir.x)._, math::degrees(dir.y)._, math::degrees(dir.z)._ }, false);
|
||||
obj = world->addWMOAndGetInstance(path, {pos.x, pos.y, pos.z}, {math::degrees(dir.x)._, math::degrees(dir.y)._, math::degrees(dir.z)._ }, scale, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ void ObjectInstanceInfoNode::compute()
|
||||
|
||||
if (_out_ports[2].connected)
|
||||
{
|
||||
_out_ports[2].out_value = std::make_shared<DecimalData>(obj->which() == eMODEL ? obj->scale : 1.0);
|
||||
_out_ports[2].out_value = std::make_shared<DecimalData>(obj->scale);
|
||||
_node->onDataUpdated(2);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,19 @@ void ObjectInstanceSetScaleNode::compute()
|
||||
return;
|
||||
}
|
||||
|
||||
obj->scale = obj->which() == eMODEL ? scale : 1.0;
|
||||
if (obj->which() == eWMO) {
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
if (modern_features) {
|
||||
obj->scale = scale;
|
||||
}
|
||||
else {
|
||||
obj->scale = 1.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
obj->scale = scale;
|
||||
}
|
||||
|
||||
obj->recalcExtents();
|
||||
|
||||
|
||||
@@ -35,15 +35,15 @@ void ScaleSelectedObjectInstancesNode::compute()
|
||||
switch (_operation->currentIndex())
|
||||
{
|
||||
case 0: // Set
|
||||
world->scale_selected_models(delta, World::m2_scaling_type::set);
|
||||
world->scale_selected_models(delta, World::object_scaling_type::set);
|
||||
break;
|
||||
|
||||
case 1: // Add
|
||||
world->scale_selected_models(delta, World::m2_scaling_type::add);
|
||||
world->scale_selected_models(delta, World::object_scaling_type::add);
|
||||
break;
|
||||
|
||||
case 2: // Multiply
|
||||
world->scale_selected_models(delta, World::m2_scaling_type::mult);
|
||||
world->scale_selected_models(delta, World::object_scaling_type::mult);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,9 @@ void ViewportGizmo::handleTransformGizmo(MapView* map_view
|
||||
NOGGIT_ACTION_MGR->beginAction(map_view, Noggit::ActionFlags::eOBJECTS_TRANSFORMED,
|
||||
Noggit::ActionModalityControllers::eLMB);
|
||||
|
||||
QSettings settings;
|
||||
bool modern_features = settings.value("modern_features", false).toBool();
|
||||
|
||||
if (gizmo_selection_type == MULTISELECTION)
|
||||
{
|
||||
|
||||
@@ -163,8 +166,13 @@ void ViewportGizmo::handleTransformGizmo(MapView* map_view
|
||||
|
||||
glm::vec3& pos = obj_instance->pos;
|
||||
math::degrees::vec3& rotation = obj_instance->dir;
|
||||
float wmo_scale = 0.f;
|
||||
float& scale = obj_instance->which() == eMODEL ? obj_instance->scale : wmo_scale;
|
||||
float& scale = obj_instance->scale;
|
||||
|
||||
// If modern features are disabled, we don't want to scale WMOs
|
||||
if (obj_instance->which() == eWMO && !modern_features && _gizmo_operation == ImGuizmo::SCALE) {
|
||||
scale = 1.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_world)
|
||||
_world->updateTilesEntry(selected, model_update::remove);
|
||||
@@ -279,8 +287,13 @@ void ViewportGizmo::handleTransformGizmo(MapView* map_view
|
||||
|
||||
glm::vec3& pos = obj_instance->pos;
|
||||
math::degrees::vec3& rotation = obj_instance->dir;
|
||||
float wmo_scale = 0.f;
|
||||
float& scale = obj_instance->which() == eMODEL ? obj_instance->scale : wmo_scale;
|
||||
float& scale = obj_instance->scale;
|
||||
|
||||
// If modern features are disabled, we don't want to scale WMOs
|
||||
if (obj_instance->which() == eWMO && !modern_features && _gizmo_operation == ImGuizmo::SCALE) {
|
||||
scale = 1.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_world)
|
||||
_world->updateTilesEntry(selected, model_update::remove);
|
||||
|
||||
2
src/noggit/ui/windows/settingsPanel/SettingsPanel.cpp
Executable file → Normal file
2
src/noggit/ui/windows/settingsPanel/SettingsPanel.cpp
Executable file → Normal file
@@ -225,6 +225,7 @@ namespace Noggit
|
||||
ui->_keyboard_locale->setCurrentText(_settings->value("keyboard_locale", "QWERTY").toString());
|
||||
ui->_use_mclq_liquids_export->setChecked(_settings->value("use_mclq_liquids_export", false).toBool());
|
||||
ui->_theme->setCurrentText(_settings->value("theme", "Dark").toString());
|
||||
ui->_modern_features->setChecked(_settings->value("modern_features", false).toBool());
|
||||
|
||||
ui->assetBrowserBgCol->setColor(_settings->value("assetBrowser/background_color",
|
||||
QVariant::fromValue(QColor(127, 127, 127))).value<QColor>());
|
||||
@@ -316,6 +317,7 @@ namespace Noggit
|
||||
_settings->setValue("systemWindowFrame", ui->_systemWindowFrame->isChecked());
|
||||
_settings->setValue("nativeMenubar", ui->_nativeMenubar->isChecked());
|
||||
_settings->setValue("classicUI", ui->_classic_ui->isChecked());
|
||||
_settings->setValue("modern_features", ui->_modern_features->isChecked());
|
||||
_settings->setValue("use_mclq_liquids_export", ui->_use_mclq_liquids_export->isChecked());
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
|
||||
@@ -797,6 +797,29 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_44">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Requires restart. This will enable modern features added in expansions after WotLK. This enables height texturing and WMO scaling. Some features may require additional tools.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Modern features (MoP/Legion+)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="_modern_features">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="minimumSize">
|
||||
|
||||
@@ -61,7 +61,9 @@ namespace OpenGL
|
||||
int draw_groundeffectid_overlay = false;
|
||||
int draw_groundeffect_layerid_overlay = false;
|
||||
int draw_noeffectdoodad_overlay = false;
|
||||
// int padding[3];
|
||||
int draw_only_normals = false;
|
||||
int point_normals_up = false;
|
||||
// int padding;
|
||||
};
|
||||
|
||||
struct ChunkInstanceDataUniformBlock
|
||||
@@ -74,6 +76,13 @@ namespace OpenGL
|
||||
int AreaIDColor_Pad2_DrawSelection[4];
|
||||
int ChunkXZ_TileXZ[4];
|
||||
int ChunkTexAnimDir[4];
|
||||
|
||||
// Mists Heightmapping
|
||||
int ChunkHeightTextureSamplers[4];
|
||||
int ChunkTextureUVScale[4];
|
||||
float ChunkTextureHeightScale[4];
|
||||
float ChunkTextureHeightOffset[4];
|
||||
|
||||
float ChunkGroundEffectColor[4];
|
||||
int ChunkDoodadsEnabled2_ChunksLayerEnabled2[4];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user