Merge branch 'noggit-shadowlands' of https://gitlab.com/prophecy-rp/noggit-red into noggit-shadowlands

This commit is contained in:
Alister
2021-12-12 15:34:22 +00:00
20 changed files with 331 additions and 230 deletions

223
README.md
View File

@@ -2,15 +2,13 @@
This software is open source software licensed under GPL3, as found in
the COPYING file.
# DISCORD #
You can follow Noggit's development and get the latest build here: https://discord.gg/UbdFHyM
# BUILDING #
This project requires CMake to be built. It also requires the
following libraries:
* OpenGL
* StormLib (by Ladislav Zezula)
* CascLib (by Ladislav Zezula)
* Boost
* Qt 5
@@ -113,101 +111,140 @@ To pull the latest version of submodules use the following command at the root d
git submodule update --recursive --remote
```
# DEVELOPMENT #
Feel free to ask the owner of the official repository
(https://github.com/wowdev/noggit3) for write access or
fork and post a pull request.
There is a bug tracker at https://github.com/wowdev/noggit3/issues which should be used.
Discord, as linked above, may be used for communication.
# CODING GUIDELINES #
Following is an example for file `src/noggit/ui/foo_ban.hpp`. `.cpp` files
are similar.
File naming rules:
```.hpp``` - is used for header files (C++ language).
```.h``` - is used **only** for header files or modules written in C language.
```.c``` - is used **only** for implementation files or modules written in C language.
```.cpp``` - is used for project implementation files.
```.inl``` - is used for include files providing template instantiations.
```.ui``` - is used for QT UI definitions (output of QtDesigner/QtCreator).
### Project structure: ###
```/src/Noggit``` - is the main directory hosting .cpp, .hpp, .inl, .ui files of the project.
Within this directory the subdirs should correspond to namespace names (case sensitive).
File names should use PascalCase (e.g. ```FooBan.hpp```) and either correspond to the type defined in the file,
or represent sematics of the module.
```/src/External``` - is the directory of hosting included libraries and subprojects. This is external or modified
external code, so no rules from Noggit project apply to its content.
```/src/Glsl``` - is the directory to store .glsl shaders for the OpenGL renderer. It is not recommended,
but not strictly prohibited to inline shader code as strings to ```.cpp``` implementation files.
### Code style ###
Following is an example for file `src/Noggit/Ui/FooBan.hpp`.
```cpp
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
//! \note Include guard shall be using #pragma once
#pragma once
//! \note Use fully qualified paths rather than "../relative". Order
//! includes with own first, then external dependencies, then c++ STL.
#include <noggit/bar.hpp>
//! \note Namespaces equal directories. (java style packages.)
namespace noggit
{
namespace ui
{
//! \note Lower case, underscore separated.
class foo_ban : public QWidget
{
Q_OBJECT;
public:
//! \note Long parameter list. Would be more than 80 chars.
//! chars. Break with comma in front. Use spaces to be
//! aligned below the braces.
foo_ban ( type name
, type_2 const& name_2
, type const& name3
)
: QWidget (nullptr)
//! \note Prefer initialization lists over assignment.
, _var (std::move (name))
{}
#ifndef INCLUDE_GUARD_BASED_ON_FILENAME
#define INCLUDE_GUARD_BASED_ON_FILENAME
// We do not use #pragma once in headers as it is technically not cross-platform.
// Use include guards instead. For example, CLion IDE creates them automatically on .hpp file creation.
//! \note Use const where possible. No space between name and
//! braces when no arguments are given.
void render() const;
//! \note If you really need getters and setters, your design
//! might be broken. Please avoid them or consider just a
//! public data member, or use proper methods with semantics.
type const& var() const
{
return _var;
}
void var (type var_)
{
_var = std::move (var_);
}
//! \note Prefer const where possible. If you need to copy,
//! just take a `T`. Otherwise prefer taking a `T const&`.
//! Don't bother when it comes to tiny types.
baz_type count_some_numbers ( std::size_t begin
, std::size_t end
) const
{
bazs_type bazs;
//! \note Prefer construction over assignment. Prefer
//! preincrement.
for (size_t it (begin); it != end; ++it)
{
bazs.emplace_back (it);
}
//! \note Prefer STL algorithms over hand written code.
assert (!bazs.empty());
auto const smallest
(std::min_element (bazs.begin(), bazs.end()));
return *smallest;
}
// <> are prefered for includes.
// Local imports go here
#include <SomeLocalFile.hpp>
// Lib imports go here
#include <external/SomeLibCode.hpp
// STL imports go here
#include <string>
#include <mutex>
#include <vector> // etc
// Forward declarations in headers are encouraged. That prevents type leaking into bigger scopes
// Also reduces compile time
namespace Parent::SomeOtherChild
{
class ForwardDeclaredClass;
}
// Namespaces are defined as PascalCase names. Namespace concatenation for nested namespaces
// is adviced, but not strictly enforced.
namespace Parent::Child
{
// types are name in PascalCase,
class Test : public TestBase
{
public:
Test();
int x; // public fields like that are discourged, but occur here and there through the project.
// Subject to refactoring.
// methods are named in camelCase.
// trivial getter methods are declared in the header file.
int somePrivateMember() { return _some_private_member; } const;
// trivial setters are declared in the header file. Preceded by "set" prefix.
void setSomePrivateMember(int a) { _some_private_member = a; };
// private members are snake lower case, separated by underscore, preceded by underscore to indicate they're private.
private:
int _some_private_member;
ForwardDeclaredClass* _some_other_private_member_using_forward_decl;
std::mutex _mutex;
// static methods
private:
//! \note Member variables are prefixed with an underscore.
type _var;
//! \note Typedef when using complex types. Fully qualify
//! types.
using baz_type = type_2;
using bazs_type = std::vector<baz_type>;
bazs_type _bazs;
}
}
static void someStaticMethod();
};
}
#endif
```
Following is an example for file `src/Noggit/Ui/FooBan.cpp`.
```cpp
// the header of this .cpp comes first
// <> are prefered for includes.
#include <Noggit/Ui/FooBan.hpp>
// same order of includes as in header.
using namespace Parent::Child;
Test::Test()
: TestBase("some_arg")
, _some_private_member(0)
, _some_other_private_member_using_forward_decl(new ForwardDeclaredClass()) // do not forget to import ForwardDeclaredClass in .cpp
{
// body of ctor
}
void Test::someStaticMethod()
{
// local variables are named in snake_case, no preceding underscore.
int local_var = 0;
// preceding underscore is used on variables that are used for RAII patterns, such as scoped stuff (e.g. a scoped mutex)
std::lock_guard<std::mutex> _lock (_mutex); // _lock is never accessed later, it just needs to live as long as the scope lives.
// So, it has an underscore prefix.
someFunc(local_var); // free floating functions use the same naming rules as methods
}
```
Additional examples:
```cpp
constexpr unsigned SOME_CONSTANT = 10; // constants are named in SCREAMING_CASE
#define SOME_MACRO // macro definitions are named in SCREAMING_CASE
```

View File

@@ -216,10 +216,10 @@ unsigned noggit::Action::handleObjectAdded(unsigned uid, bool redo)
{
unsigned old_uid = pair.first;
SceneObject* obj;
if (pair.second.filename.ends_with(".wmo"))
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.filename, pair.second.pos, pair.second.dir);
if (pair.second.type == ActionObjectTypes::WMO)
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir);
else
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.filename, pair.second.pos,
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.file_key, pair.second.pos,
pair.second.scale, pair.second.dir, nullptr);
obj->instance_model()->wait_until_loaded();
@@ -258,10 +258,7 @@ unsigned noggit::Action::handleObjectAdded(unsigned uid, bool redo)
}
else
{
if (pair.second.filename.ends_with(".wmo"))
_map_view->getWorld()->deleteWMOInstance(pair.first);
else
_map_view->getWorld()->deleteModelInstance(pair.first);
_map_view->getWorld()->deleteInstance(pair.first);
}
return new_uid;
@@ -283,10 +280,10 @@ unsigned noggit::Action::handleObjectRemoved(unsigned uid, bool redo)
{
unsigned old_uid = pair.first;
SceneObject* obj;
if (pair.second.filename.ends_with(".wmo"))
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.filename, pair.second.pos, pair.second.dir);
if (pair.second.type == ActionObjectTypes::WMO)
obj = _map_view->getWorld()->addWMOAndGetInstance(pair.second.file_key, pair.second.pos, pair.second.dir);
else
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.filename, pair.second.pos,
obj = _map_view->getWorld()->addM2AndGetInstance(pair.second.file_key, pair.second.pos,
pair.second.scale, pair.second.dir, nullptr);
obj->instance_model()->wait_until_loaded();
@@ -325,10 +322,7 @@ unsigned noggit::Action::handleObjectRemoved(unsigned uid, bool redo)
}
else
{
if (pair.second.filename.ends_with(".wmo"))
_map_view->getWorld()->deleteWMOInstance(pair.first);
else
_map_view->getWorld()->deleteModelInstance(pair.first);
_map_view->getWorld()->deleteInstance(pair.first);
}
return new_uid;
@@ -621,8 +615,13 @@ void noggit::Action::registerObjectTransformed(SceneObject* obj)
_object_operations[obj->uid].emplace_back(ActionFlags::eOBJECTS_TRANSFORMED);
ActionObjectTypes type = obj->which() == eWMO ? ActionObjectTypes::WMO : ActionObjectTypes::M2;
_transformed_objects_pre.emplace_back(std::make_pair(obj->uid,
ObjectInstanceCache{obj->getFilename(), obj->pos, obj->dir, obj->scale}));
ObjectInstanceCache{obj->instance_model()->file_key()
, type
, obj->pos
, obj->dir
, obj->scale}));
}
void noggit::Action::registerObjectAdded(SceneObject* obj)
@@ -637,8 +636,14 @@ void noggit::Action::registerObjectAdded(SceneObject* obj)
_object_operations[obj->uid].emplace_back(ActionFlags::eOBJECTS_ADDED);
ActionObjectTypes type = obj->which() == eWMO ? ActionObjectTypes::WMO : ActionObjectTypes::M2;
_added_objects_pre.emplace_back(std::make_pair(obj->uid,
ObjectInstanceCache{obj->getFilename(), obj->pos, obj->dir, obj->scale}));
ObjectInstanceCache{obj->instance_model()->file_key()
, type
, obj->pos
, obj->dir
, obj->scale}
));
}
void noggit::Action::registerObjectRemoved(SceneObject* obj)
@@ -653,8 +658,14 @@ void noggit::Action::registerObjectRemoved(SceneObject* obj)
_object_operations[obj->uid].emplace_back(ActionFlags::eOBJECTS_REMOVED);
ActionObjectTypes type = obj->which() == eWMO ? ActionObjectTypes::WMO : ActionObjectTypes::M2;
_removed_objects_pre.emplace_back(std::make_pair(obj->uid,
ObjectInstanceCache{obj->getFilename(), obj->pos, obj->dir, obj->scale}));
ObjectInstanceCache{obj->instance_model()->file_key()
, type
, obj->pos
, obj->dir
, obj->scale}
));
}
void noggit::Action::registerChunkHoleChange(MapChunk* chunk)

View File

@@ -16,6 +16,7 @@
#include <noggit/liquid_layer.hpp>
#include <noggit/ChunkWater.hpp>
#include <QObject>
#include <ClientData.hpp>
class MapView;
class MapChunk;
@@ -55,6 +56,12 @@ namespace noggit
eNUM = 0x100
};
enum class ActionObjectTypes
{
WMO,
M2
};
struct TextureChangeCache
{
size_t n_textures;
@@ -66,7 +73,8 @@ namespace noggit
struct ObjectInstanceCache
{
std::string filename;
BlizzardArchive::Listfile::FileKey file_key;
ActionObjectTypes type;
glm::vec3 pos;
math::degrees::vec3 dir;
float scale;

View File

@@ -251,16 +251,20 @@ public:
void updateEmitters(float dt);
virtual void finishLoading();
virtual void waitForChildrenLoaded() override;
void finishLoading() override;
void waitForChildrenLoaded() override;
[[nodiscard]]
bool is_hidden() const { return _hidden; }
void toggle_visibility() { _hidden = !_hidden; }
void show() { _hidden = false ; }
[[nodiscard]]
bool use_fake_geometry() const { return !!_fake_geometry; }
virtual bool is_required_when_saving() const
[[nodiscard]]
bool is_required_when_saving() const override
{
return true;
}

View File

@@ -13,30 +13,24 @@
#include <opengl/scoped.hpp>
#include <opengl/shader.hpp>
ModelInstance::ModelInstance(std::string const& filename, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eMODEL, context, filename)
, model (filename, context)
ModelInstance::ModelInstance(BlizzardArchive::Listfile::FileKey const& file_key
, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eMODEL, context)
, model(file_key, context)
{
}
ModelInstance::ModelInstance(std::string const& filename, ENTRY_MDDF const*d, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eMODEL, context, filename)
, model (filename, context)
ModelInstance::ModelInstance(BlizzardArchive::Listfile::FileKey const& file_key
, ENTRY_MDDF const*d, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eMODEL, context)
, model(file_key, context)
{
uid = d->uniqueID;
pos = glm::vec3(d->pos[0], d->pos[1], d->pos[2]);
dir = math::degrees::vec3( math::degrees(d->rot[0])._, math::degrees(d->rot[1])._, math::degrees(d->rot[2])._);
// scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float?
scale = d->scale / 1024.0f;
if (model->finishedLoading())
{
recalcExtents();
}
else
{
_need_recalc_extents = true;
}
_need_recalc_extents = true;
}
@@ -197,7 +191,7 @@ void ModelInstance::recalcExtents()
auto transposedMat = _transform_mat;
for (auto const& point : corners_in_world)
{
rotated_corners_in_world.push_back(transposedMat * glm::vec4(point, 1.f));
rotated_corners_in_world.emplace_back(transposedMat * glm::vec4(point, 1.f));
}
math::aabb const bounding_of_rotated_points (rotated_corners_in_world);
@@ -265,8 +259,10 @@ void ModelInstance::updateDetails(noggit::ui::detail_infos* detail_widget)
detail_widget->setText(select_info.str());
}
wmo_doodad_instance::wmo_doodad_instance(std::string const& filename, BlizzardArchive::ClientFile* f, noggit::NoggitRenderContext context)
: ModelInstance(filename, context)
wmo_doodad_instance::wmo_doodad_instance(BlizzardArchive::Listfile::FileKey const& file_key
, BlizzardArchive::ClientFile* f
, noggit::NoggitRenderContext context)
: ModelInstance(file_key, context)
{
float ff[4];

View File

@@ -3,7 +3,7 @@
#pragma once
#include <math/ray.hpp>
#include <ClientFile.hpp> // BlizzardArchive::ClientFile
#include <ClientFile.hpp>
#include <noggit/MapHeaders.h> // ENTRY_MDDF
#include <noggit/ModelManager.h>
#include <noggit/Selection.h>
@@ -33,15 +33,17 @@ public:
// longest side of an AABB transformed model's bounding box from the M2 header
float size_cat;
explicit ModelInstance(std::string const& filename, noggit::NoggitRenderContext context);
explicit ModelInstance(BlizzardArchive::Listfile::FileKey const& file_key
, noggit::NoggitRenderContext context);
explicit ModelInstance(std::string const& filename, ENTRY_MDDF const*d, noggit::NoggitRenderContext context);
explicit ModelInstance(BlizzardArchive::Listfile::FileKey const& file_key
, ENTRY_MDDF const*d, noggit::NoggitRenderContext context);
ModelInstance(ModelInstance const& other) = default;
ModelInstance& operator= (ModelInstance const& other) = default;
ModelInstance (ModelInstance&& other)
: SceneObject(other._type, other._context, other._filename)
: SceneObject(other._type, other._context)
, model (std::move (other.model))
, light_color (other.light_color)
, size_cat (other.size_cat)
@@ -57,7 +59,7 @@ public:
uid = other.uid;
}
ModelInstance& operator= (ModelInstance&& other)
ModelInstance& operator= (ModelInstance&& other) noexcept
{
std::swap (model, other.model);
std::swap (pos, other.pos);
@@ -100,9 +102,9 @@ public:
virtual bool isWMODoodad() const { return false; };
[[nodiscard]]
AsyncObject* instance_model() override { return model.get(); };
AsyncObject* instance_model() const override { return model.get(); };
virtual void updateDetails(noggit::ui::detail_infos* detail_widget) override;
void updateDetails(noggit::ui::detail_infos* detail_widget) override;
[[nodiscard]]
std::uint32_t gpuTransformUid() const { return _gpu_transform_uid; }
@@ -120,12 +122,12 @@ public:
glm::quat doodad_orientation;
glm::vec3 world_pos;
explicit wmo_doodad_instance(std::string const& filename
explicit wmo_doodad_instance(BlizzardArchive::Listfile::FileKey const& file_key
, BlizzardArchive::ClientFile* f
, noggit::NoggitRenderContext context );
wmo_doodad_instance(wmo_doodad_instance const& other)
: ModelInstance(other.model->file_key().filepath(), other._context)
: ModelInstance(other.model->file_key(), other._context)
, doodad_orientation(other.doodad_orientation)
, world_pos(other.world_pos)
, _need_matrix_update(other._need_matrix_update)
@@ -135,7 +137,7 @@ public:
wmo_doodad_instance& operator= (wmo_doodad_instance const& other) = delete;
wmo_doodad_instance(wmo_doodad_instance&& other)
wmo_doodad_instance(wmo_doodad_instance&& other) noexcept
: ModelInstance(reinterpret_cast<ModelInstance&&>(other))
, doodad_orientation(other.doodad_orientation)
, world_pos(other.world_pos)
@@ -157,10 +159,11 @@ public:
void update_transform_matrix_wmo(WMOInstance* wmo);
virtual glm::vec3 const& get_pos() const override { return world_pos; };
[[nodiscard]]
glm::vec3 const& get_pos() const override { return world_pos; };
[[nodiscard]]
virtual bool isWMODoodad() const override { return true; };
bool isWMODoodad() const override { return true; };
protected:
// to avoid redefining recalcExtents

View File

@@ -5,6 +5,7 @@
#include <noggit/Model.h>
#include <noggit/AsyncObjectMultimap.hpp>
#include <noggit/ContextObject.hpp>
#include <ClientData.hpp>
#include <map>
#include <string>
@@ -30,33 +31,33 @@ private:
struct scoped_model_reference
{
scoped_model_reference (
std::string const& filename, noggit::NoggitRenderContext context)
BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context)
: _valid(true)
, _filename(filename)
, _model(ModelManager::_.emplace (_filename, context))
, _file_key(file_key)
, _model(ModelManager::_.emplace (_file_key, context))
, _context(context)
{}
scoped_model_reference (scoped_model_reference const& other)
: _valid (other._valid)
, _filename (other._filename)
, _model (ModelManager::_.emplace(_filename, other._context))
, _file_key (other._file_key)
, _model (ModelManager::_.emplace(_file_key, other._context))
, _context(other._context)
{}
scoped_model_reference& operator= (scoped_model_reference const& other)
{
_valid = other._valid;
_filename = other._filename;
_model = ModelManager::_.emplace (_filename, other._context);
_file_key = other._file_key;
_model = ModelManager::_.emplace (_file_key, other._context);
_context = other._context;
return *this;
}
scoped_model_reference (scoped_model_reference&& other)
: _valid(other._valid)
, _filename(other._filename)
, _file_key(other._file_key)
, _model(other._model)
, _context(other._context)
{
@@ -65,7 +66,7 @@ struct scoped_model_reference
scoped_model_reference& operator= (scoped_model_reference&& other)
{
std::swap(_valid, other._valid);
std::swap(_filename, other._filename);
std::swap(_file_key, other._file_key);
std::swap(_model, other._model);
std::swap(_context, other._context);
other._valid = false;
@@ -76,7 +77,7 @@ struct scoped_model_reference
{
if (_valid)
{
ModelManager::_.erase(_filename, _context);
ModelManager::_.erase(_file_key, _context);
}
}
@@ -84,6 +85,8 @@ struct scoped_model_reference
{
return _model;
}
[[nodiscard]]
Model* get() const
{
return _model;
@@ -91,7 +94,7 @@ struct scoped_model_reference
private:
bool _valid;
std::string _filename;
BlizzardArchive::Listfile::FileKey _file_key;
Model* _model;
noggit::NoggitRenderContext _context;
};

View File

@@ -2,15 +2,16 @@
#include "SceneObject.hpp"
#include <ClientData.hpp>
#include <noggit/AsyncObject.h>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <noggit/Misc.h>
#include <math/trig.hpp>
#include <limits>
SceneObject::SceneObject(SceneObjectTypes type, noggit::NoggitRenderContext context, std::string filename)
SceneObject::SceneObject(SceneObjectTypes type, noggit::NoggitRenderContext context)
: _type(type)
, _filename(filename)
, _context(context)
, pos(0.f, 0.f, 0.f)
, dir(0.f, 0.f, 0.f)
@@ -27,8 +28,22 @@ bool SceneObject::isInsideRect(std::array<glm::vec3, 2> const* rect) const
bool SceneObject::isDuplicateOf(SceneObject const& other)
{
return _filename == other._filename
&& misc::vec3d_equals(pos, other.pos)
auto a_obj_this = instance_model();
auto a_obj_other = other.instance_model();
if ((a_obj_this && a_obj_other) && a_obj_this->file_key() != a_obj_other->file_key())
{
return false;
}
// if one SceneObject has an AsyncObject bound and ther other is not,
// there is no point in comparing further
if (static_cast<bool>(a_obj_this) != static_cast<bool>(a_obj_other))
{
return false;
}
return misc::vec3d_equals(pos, other.pos)
&& misc::deg_vec3d_equals(dir, other.dir)
&& misc::float_equals(scale, other.scale);
}

View File

@@ -11,6 +11,11 @@
#include <unordered_set>
#include <array>
namespace BlizzardArchive::Listfile
{
class FileKey;
}
class AsyncObject;
enum SceneObjectTypes
@@ -24,7 +29,7 @@ class MapTile;
class SceneObject : public Selectable
{
public:
SceneObject(SceneObjectTypes type, noggit::NoggitRenderContext context, std::string filename = "");
SceneObject(SceneObjectTypes type, noggit::NoggitRenderContext context);
[[nodiscard]]
bool isInsideRect(std::array<glm::vec3, 2> const* rect) const;
@@ -36,6 +41,8 @@ public:
virtual void recalcExtents() = 0;
virtual void ensureExtents() = 0;
[[nodiscard]]
virtual bool finishedLoading() = 0;
void resetDirection();
@@ -46,16 +53,19 @@ public:
[[nodiscard]]
glm::mat4x4 transformMatrixInverted() const { return _transform_mat_inverted; };
[[nodiscard]]
SceneObjectTypes which() const { return _type; };
std::string const& getFilename() const { return _filename; };
void refTile(MapTile* tile);
void derefTile(MapTile* tile);
std::vector<MapTile*> const& getTiles() { return _tiles; };
virtual AsyncObject* instance_model() = 0;
[[nodiscard]]
std::vector<MapTile*> const& getTiles() const { return _tiles; };
[[nodiscard]]
virtual AsyncObject* instance_model() const = 0;
[[nodiscard]]
std::array<glm::vec3, 2> const& getExtents() { ensureExtents(); return extents; }
public:
@@ -74,8 +84,6 @@ protected:
noggit::NoggitRenderContext _context;
std::string _filename;
std::vector<MapTile*> _tiles;
};

View File

@@ -45,7 +45,7 @@ struct scoped_blp_texture_reference;
struct blp_texture : public AsyncObject
{
blp_texture (BlizzardArchive::Listfile::FileKey const& filename, noggit::NoggitRenderContext context);
void finishLoading();
void finishLoading() override;
virtual void waitForChildrenLoaded() override {};
void loadFromUncompressedData(BLPHeader const* lHeader, char const* lData);
@@ -70,7 +70,8 @@ struct blp_texture : public AsyncObject
noggit::NoggitRenderContext getContext() { return _context; };
virtual async_priority loading_priority() const
[[nodiscard]]
async_priority loading_priority() const override
{
return async_priority::high;
}

View File

@@ -22,9 +22,8 @@
#include <vector>
WMO::WMO(const std::string& filenameArg, noggit::NoggitRenderContext context)
: AsyncObject(filenameArg)
, _finished_upload(false)
WMO::WMO(BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context)
: AsyncObject(file_key)
, _context(context)
{
}

View File

@@ -291,7 +291,7 @@ static_assert ( sizeof (mohd_flags) == sizeof (std::uint16_t)
class WMO : public AsyncObject
{
public:
explicit WMO(const std::string& name, noggit::NoggitRenderContext context );
explicit WMO(BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context );
void draw ( opengl::scoped::use_program& wmo_shader
, glm::mat4x4 const& model_view
@@ -320,20 +320,18 @@ public:
, std::map<int, std::pair<glm::vec3, glm::vec3>> const& group_extents
) const;
[[nodiscard]]
std::vector<float> intersect (math::ray const&) const;
void finishLoading();
void finishLoading() override;
virtual void waitForChildrenLoaded() override;
void waitForChildrenLoaded() override;
void unload();
[[nodiscard]]
std::map<uint32_t, std::vector<wmo_doodad_instance>> doodads_per_group(uint16_t doodadset) const;
bool draw_group_boundingboxes;
bool _finished_upload;
std::vector<WMOGroup> groups;
std::vector<WMOMaterial> materials;
glm::vec3 extents[2];
@@ -355,11 +353,14 @@ public:
noggit::NoggitRenderContext _context;
[[nodiscard]]
bool is_hidden() const { return _hidden; }
void toggle_visibility() { _hidden = !_hidden; }
void show() { _hidden = false ; }
virtual bool is_required_when_saving() const
[[nodiscard]]
bool is_required_when_saving() const override
{
return true;
}
@@ -381,31 +382,31 @@ private:
struct scoped_wmo_reference
{
scoped_wmo_reference (std::string const& filename, noggit::NoggitRenderContext context)
scoped_wmo_reference (BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context)
: _valid(true)
, _filename(filename)
, _file_key(file_key)
, _context(context)
, _wmo (WMOManager::_.emplace(_filename, context))
, _wmo (WMOManager::_.emplace(file_key, context))
{}
scoped_wmo_reference (scoped_wmo_reference const& other)
: _valid(other._valid)
, _filename(other._filename)
, _wmo(WMOManager::_.emplace(_filename, other._context))
, _file_key(other._file_key)
, _wmo(WMOManager::_.emplace(_file_key, other._context))
, _context(other._context)
{}
scoped_wmo_reference& operator= (scoped_wmo_reference const& other)
{
_valid = other._valid;
_filename = other._filename;
_wmo = WMOManager::_.emplace(_filename, other._context);
_file_key = other._file_key;
_wmo = WMOManager::_.emplace(_file_key, other._context);
_context = other._context;
return *this;
}
scoped_wmo_reference (scoped_wmo_reference&& other)
: _valid (other._valid)
, _filename (other._filename)
, _file_key (other._file_key)
, _wmo (other._wmo)
, _context (other._context)
{
@@ -414,7 +415,7 @@ struct scoped_wmo_reference
scoped_wmo_reference& operator= (scoped_wmo_reference&& other)
{
std::swap(_valid, other._valid);
std::swap(_filename, other._filename);
std::swap(_file_key, other._file_key);
std::swap(_wmo, other._wmo);
std::swap(_context, other._context);
other._valid = false;
@@ -425,7 +426,7 @@ struct scoped_wmo_reference
{
if (_valid)
{
WMOManager::_.erase(_filename, _context);
WMOManager::_.erase(_file_key, _context);
}
}
@@ -433,6 +434,8 @@ struct scoped_wmo_reference
{
return _wmo;
}
[[nodiscard]]
WMO* get() const
{
return _wmo;
@@ -441,7 +444,7 @@ struct scoped_wmo_reference
private:
bool _valid;
std::string _filename;
BlizzardArchive::Listfile::FileKey _file_key;
WMO* _wmo;
noggit::NoggitRenderContext _context;
};

View File

@@ -11,9 +11,9 @@
#include <opengl/primitives.hpp>
#include <opengl/scoped.hpp>
WMOInstance::WMOInstance(std::string const& filename, ENTRY_MODF const* d, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eWMO, context, filename)
, wmo(filename, context)
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)
, _doodadset(d->doodadSet)
@@ -30,9 +30,9 @@ WMOInstance::WMOInstance(std::string const& filename, ENTRY_MODF const* d, noggi
change_doodadset(_doodadset);
}
WMOInstance::WMOInstance(std::string const& filename, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eWMO, context, filename)
, wmo(filename, context)
WMOInstance::WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context)
: SceneObject(SceneObjectTypes::eWMO, context)
, wmo(file_key, context)
, mFlags(0)
, mUnknown(0)
, mNameset(0)

View File

@@ -31,15 +31,15 @@ private:
bool _need_doodadset_update = true;
public:
WMOInstance(std::string const& filename, ENTRY_MODF const* d, noggit::NoggitRenderContext context);
WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, ENTRY_MODF const* d, noggit::NoggitRenderContext context);
explicit WMOInstance(std::string const& filename, noggit::NoggitRenderContext context);
explicit WMOInstance(BlizzardArchive::Listfile::FileKey const& file_key, noggit::NoggitRenderContext context);
WMOInstance(WMOInstance const& other) = default;
WMOInstance& operator=(WMOInstance const& other) = default;
WMOInstance (WMOInstance&& other)
: SceneObject(other._type, other._context, other._filename)
: SceneObject(other._type, other._context)
, wmo (std::move (other.wmo))
, group_extents(other.group_extents)
, mFlags (other.mFlags)
@@ -76,7 +76,6 @@ public:
std::swap(_transform_mat, other._transform_mat);
std::swap(_transform_mat_inverted, other._transform_mat_inverted);
std::swap(_context, other._context);
std::swap(_filename, other._filename);
return *this;
}
@@ -104,7 +103,7 @@ public:
virtual void updateDetails(noggit::ui::detail_infos* detail_widget) override;
[[nodiscard]]
AsyncObject* instance_model() override { return wmo.get(); };
AsyncObject* instance_model() const override { return wmo.get(); };
std::vector<wmo_doodad_instance*> get_visible_doodads( math::frustum const& frustum
, float const& cull_distance

View File

@@ -2614,27 +2614,40 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
return true;
}
void World::deleteModelInstance(int pUniqueID)
void World::deleteModelInstance(int uid)
{
ZoneScoped;
auto instance = _model_instance_storage.get_model_instance(pUniqueID);
auto instance = _model_instance_storage.get_model_instance(uid);
if (instance)
{
_model_instance_storage.delete_instance(pUniqueID);
_model_instance_storage.delete_instance(uid);
need_model_updates = true;
reset_selection();
}
}
void World::deleteWMOInstance(int pUniqueID)
void World::deleteWMOInstance(int uid)
{
ZoneScoped;
auto instance = _model_instance_storage.get_wmo_instance(pUniqueID);
auto instance = _model_instance_storage.get_wmo_instance(uid);
if (instance)
{
_model_instance_storage.delete_instance(pUniqueID);
_model_instance_storage.delete_instance(uid);
need_model_updates = true;
reset_selection();
}
}
void World::deleteInstance(int uid)
{
ZoneScoped;
auto instance = _model_instance_storage.get_instance(uid);
if (instance)
{
_model_instance_storage.delete_instance(uid);
need_model_updates = true;
reset_selection();
}
@@ -2665,7 +2678,7 @@ void World::unload_every_model_and_wmo_instance()
_models_by_filename.clear();
}
void World::addM2 ( std::string const& filename
void World::addM2 ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, float scale
, glm::vec3 rotation
@@ -2673,7 +2686,7 @@ void World::addM2 ( std::string const& filename
)
{
ZoneScoped;
ModelInstance model_instance = ModelInstance(filename, _context);
ModelInstance model_instance = ModelInstance(file_key, _context);
model_instance.uid = mapIndex.newGUID();
model_instance.pos = newPos;
@@ -2711,10 +2724,10 @@ void World::addM2 ( std::string const& filename
std::uint32_t uid = _model_instance_storage.add_model_instance(std::move(model_instance), true);
_models_by_filename[filename].push_back(_model_instance_storage.get_model_instance(uid).get());
_models_by_filename[file_key.filepath()].push_back(_model_instance_storage.get_model_instance(uid).get());
}
ModelInstance* World::addM2AndGetInstance ( std::string const& filename
ModelInstance* World::addM2AndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, float scale
, math::degrees::vec3 rotation
@@ -2722,7 +2735,7 @@ ModelInstance* World::addM2AndGetInstance ( std::string const& filename
)
{
ZoneScoped;
ModelInstance model_instance = ModelInstance(filename, _context);
ModelInstance model_instance = ModelInstance(file_key, _context);
model_instance.uid = mapIndex.newGUID();
model_instance.pos = newPos;
@@ -2761,18 +2774,18 @@ ModelInstance* World::addM2AndGetInstance ( std::string const& filename
std::uint32_t uid = _model_instance_storage.add_model_instance(std::move(model_instance), true);
auto instance = _model_instance_storage.get_model_instance(uid).get();
_models_by_filename[filename].push_back(instance);
_models_by_filename[file_key.filepath()].push_back(instance);
return instance;
}
void World::addWMO ( std::string const& filename
void World::addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, math::degrees::vec3 rotation
)
{
ZoneScoped;
WMOInstance wmo_instance(filename, _context);
WMOInstance wmo_instance(file_key, _context);
wmo_instance.uid = mapIndex.newGUID();
wmo_instance.pos = newPos;
@@ -2785,13 +2798,13 @@ void World::addWMO ( std::string const& filename
_model_instance_storage.add_wmo_instance(std::move(wmo_instance), true);
}
WMOInstance* World::addWMOAndGetInstance ( std::string const& filename
WMOInstance* World::addWMOAndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, math::degrees::vec3 rotation
)
{
ZoneScoped;
WMOInstance wmo_instance(filename, _context);
WMOInstance wmo_instance(file_key, _context);
wmo_instance.uid = mapIndex.newGUID();
wmo_instance.pos = newPos;

View File

@@ -292,23 +292,23 @@ public:
void notifyTileRendererOnSelectedTextureChange();
void addM2 ( std::string const& filename
void addM2 ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, float scale, math::degrees::vec3 rotation
, noggit::object_paste_params*
);
void addWMO ( std::string const& filename
void addWMO ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, math::degrees::vec3 rotation
);
ModelInstance* addM2AndGetInstance ( std::string const& filename
ModelInstance* addM2AndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, float scale, math::degrees::vec3 rotation
, noggit::object_paste_params*
);
WMOInstance* addWMOAndGetInstance ( std::string const& filename
WMOInstance* addWMOAndGetInstance ( BlizzardArchive::Listfile::FileKey const& file_key
, glm::vec3 newPos
, math::degrees::vec3 rotation
);
@@ -340,8 +340,9 @@ public:
, MinimapRenderSettings* settings
);
void deleteModelInstance(int pUniqueID);
void deleteWMOInstance(int pUniqueID);
void deleteModelInstance(int uid);
void deleteWMOInstance(int uid);
void deleteInstance(int uid);
bool uid_duplicates_found() const;
void delete_duplicate_model_and_wmo_instances();

View File

@@ -73,7 +73,7 @@ namespace noggit
std::string model::get_filename()
{
return _object->getFilename();
return _object->instance_model()->file_key().filepath();
}
bool model::has_filename(std::string const& name)

View File

@@ -553,7 +553,7 @@ namespace noggit
rotation = obj->dir;
}
auto new_obj = world->addM2AndGetInstance( obj->getFilename()
auto new_obj = world->addM2AndGetInstance( obj->instance_model()->file_key()
, pos
, scale
, rotation
@@ -574,7 +574,7 @@ namespace noggit
rotation = obj->dir;
}
auto new_obj = world->addWMOAndGetInstance(obj->getFilename(), pos, rotation);
auto new_obj = world->addWMOAndGetInstance(obj->instance_model()->file_key(), pos, rotation);
new_obj->wmo->wait_until_loaded();
new_obj->wmo->waitForChildrenLoaded();
new_obj->recalcExtents();
@@ -606,7 +606,7 @@ namespace noggit
auto selectedObject = new_selection.front();
if (selectedObject.which() == eEntry_Object)
{
ss << boost::get<selected_object_type>(selectedObject)->getFilename();
ss << boost::get<selected_object_type>(selectedObject)->instance_model()->file_key().filepath();
}
else
{
@@ -719,7 +719,7 @@ namespace noggit
continue;
}
std::string path = boost::get<selected_object_type>(selection)->getFilename();
std::string path = boost::get<selected_object_type>(selection)->instance_model()->file_key().filepath();
stream << path << std::endl;
}

View File

@@ -75,7 +75,7 @@ void ObjectInstanceInfoNode::compute()
if (_out_ports[6].connected)
{
_out_ports[6].out_value = std::make_shared<StringData>(obj->getFilename());
_out_ports[6].out_value = std::make_shared<StringData>(obj->instance_model()->file_key().filepath());
_node->onDataUpdated(6);
}