diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index 6bfff723c..0e540452a 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -298,11 +298,14 @@ An entity is just an int value and works as a handle to retrieve associated comp #### Scene - [outer]GetScene() : Scene result -- returns the current scene - [outer]LoadModel(string fileName, opt Matrix transform) : int rootEntity -- Load Model from file. returns a root entity that everything in this model is attached to -- [outer]Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against +- [outer]LoadModel(Scene scene, string fileName, opt Matrix transform) : int rootEntity -- Load Model from file into specified scene. returns a root entity that everything in this model is attached to +- [outer]Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) : int entity, Vector position,normal, float distance -- Perform ray-picking in the scene. pickType is a bitmask specifying object types to check against. layerMask is a bitmask specifying which layers to check against. Scene parameter is optional and will use the global scene if not specified. - Update() -- updates the scene and every entity and component inside the scene - Clear() -- deletes every entity and component inside the scene +- Merge() -- moves contents from an other scene into this one - Entity_FindByName(string value) : int entity -- returns an entity ID if it exists, and 0 otherwise - Entity_Remove(Entity entity) -- removes an entity and deletes all its components if it exists +- Entity_Duplicate(Entity entity) : int entity -- duplicates all of an entity's components and creates a new entity with them. Returns the clone entity handle - Component_CreateName(Entity entity) : NameComponent result -- attach a name component to an entity. The returned NameComponent is associated with the entity and can be manipulated - Component_CreateLayer(Entity entity) : LayerComponent result -- attach a layer component to an entity. The returned LayerComponent is associated with the entity and can be manipulated - Component_CreateTransform(Entity entity) : TransformComponent result -- attach a transform component to an entity. The returned TransformComponent is associated with the entity and can be manipulated diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 03fab8d43..da5e72f5d 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -838,6 +838,7 @@ void EditorComponent::Update(float dt) else if (wiInputManager::down(VK_LCONTROL) || currentMouse.z != 0.0f) { cameraWnd->camera_transform.Translate(XMFLOAT3(0, 0, yDif * 4 + currentMouse.z)); + cameraWnd->camera_transform.translation_local.z = min(0, cameraWnd->camera_transform.translation_local.z); camera.SetDirty(); } else if(abs(xDif) + abs(yDif) > 0) diff --git a/WickedEngine/wiFont_BindLua.cpp b/WickedEngine/wiFont_BindLua.cpp index 7aaf9305a..f5b780aea 100644 --- a/WickedEngine/wiFont_BindLua.cpp +++ b/WickedEngine/wiFont_BindLua.cpp @@ -155,7 +155,7 @@ int wiFont_BindLua::SetColor(lua_State* L) else { int code = wiLua::SGetInt(L, 1); - font->params.color.rgba = *((uint32_t*)&code); + font->params.color.rgba = (uint32_t)code; } } else @@ -177,7 +177,7 @@ int wiFont_BindLua::SetShadowColor(lua_State* L) else { int code = wiLua::SGetInt(L, 1); - font->params.shadowColor.rgba = *((uint32_t*)&code); + font->params.shadowColor.rgba = (uint32_t)code; } } else diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index b9979379d..fc4b1de73 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -5504,15 +5504,19 @@ void DrawDebugWorld(const CameraComponent& camera, GRAPHICSTHREAD threadID) int j = 0; for (Entity entity : armature.boneCollection) { + const HierarchyComponent* hierarchy = scene.hierarchy.GetComponent(entity); + if (hierarchy == nullptr) + { + continue; + } const TransformComponent& transform = *scene.transforms.GetComponent(entity); + const TransformComponent& parent = *scene.transforms.GetComponent(hierarchy->parentID); - XMMATRIX world = XMLoadFloat4x4(&transform.world); - XMVECTOR a = XMVectorSet(0, 0, 0, 1); - XMVECTOR b = XMVectorSet(0, 0, 1, 1); - - a = XMVector4Transform(a, world); - b = XMVector4Transform(b, world); + XMMATRIX transform_world = XMLoadFloat4x4(&transform.world); + XMMATRIX parent_world = XMLoadFloat4x4(&parent.world); + XMVECTOR a = XMVector3Transform(XMVectorSet(0, 0, 0, 1), transform_world); + XMVECTOR b = XMVector3Transform(XMVectorSet(0, 0, 0, 1), parent_world); LineSegment segment; XMStoreFloat4(&segment.a, a); diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index 11b6f80ab..c604d823d 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -2085,60 +2085,60 @@ namespace wiSceneSystem Entity LoadModel(const std::string& fileName, const XMMATRIX& transformMatrix, bool attached) + { + Scene scene; + Entity root = LoadModel(scene, fileName, transformMatrix, attached); + GetScene().Merge(scene); + return root; + } + + Entity LoadModel(Scene& scene, const std::string& fileName, const XMMATRIX& transformMatrix, bool attached) { wiArchive archive(fileName, true); if (archive.IsOpen()) { - // Create new scene - Scene scene; - // Serialize it from file: scene.Serialize(archive); - // First, create new root parent: - Entity parent = CreateEntity(); - scene.transforms.Create(parent); - scene.layers.Create(parent).layerMask = ~0; + // First, create new root: + Entity root = CreateEntity(); + scene.transforms.Create(root); + scene.layers.Create(root).layerMask = ~0; { // Apply the optional transformation matrix to the new scene: - // Parent all unparented(root) transforms to "parent" - for (size_t i = 0; i < scene.transforms.GetCount() - 1; ++i) // GetCount() - 1 because the last added was the "parent" + // Parent all unparented transforms to new root entity + for (size_t i = 0; i < scene.transforms.GetCount() - 1; ++i) // GetCount() - 1 because the last added was the "root" { Entity entity = scene.transforms.GetEntity(i); if (!scene.hierarchy.Contains(entity)) { - scene.Component_Attach(entity, parent); + scene.Component_Attach(entity, root); } } - // The parent component is transformed, scene is updated: - scene.transforms.GetComponent(parent)->MatrixTransform(transformMatrix); + // The root component is transformed, scene is updated: + scene.transforms.GetComponent(root)->MatrixTransform(transformMatrix); scene.Update(0); } if (!attached) { // In this case, we don't care about the root anymore, so delete it. This will simplify overall hierarchy - scene.Component_DetachChildren(parent); - scene.Entity_Remove(parent); - parent = INVALID_ENTITY; + scene.Component_DetachChildren(root); + scene.Entity_Remove(root); + root = INVALID_ENTITY; } - // Merge with the original scene: - GetScene().Merge(scene); - - return parent; + return root; } return INVALID_ENTITY; } - PickResult Pick(const RAY& ray, UINT renderTypeMask, uint32_t layerMask) + PickResult Pick(const RAY& ray, UINT renderTypeMask, uint32_t layerMask, const Scene& scene) { - const Scene& scene = GetScene(); - PickResult result; if (scene.objects.GetCount() > 0) diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index 3d834032e..c31790dcb 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -1132,12 +1132,22 @@ namespace wiSceneSystem } // Helper function to open a wiscene file and add the contents to the global scene + // fileName : file path // transformMatrix : everything will be transformed by this matrix (optional) // attached : everything will be attached to a base entity // // returns INVALID_ENTITY if attached argument was false, else it returns the base entity handle wiECS::Entity LoadModel(const std::string& fileName, const XMMATRIX& transformMatrix = XMMatrixIdentity(), bool attached = false); + // Helper function to open a wiscene file and add the contents to the specified scene. This is thread safe as it doesn't modify global scene + // scene : the scene that will contain the model + // fileName : file path + // transformMatrix : everything will be transformed by this matrix (optional) + // attached : everything will be attached to a base entity + // + // returns INVALID_ENTITY if attached argument was false, else it returns the base entity handle + wiECS::Entity LoadModel(Scene& scene, const std::string& fileName, const XMMATRIX& transformMatrix = XMMatrixIdentity(), bool attached = false); + struct PickResult { wiECS::Entity entity = wiECS::INVALID_ENTITY; @@ -1155,7 +1165,11 @@ namespace wiSceneSystem return entity == other.entity; } }; - // Given a ray, finds the closest intersection point against all instances - PickResult Pick(const RAY& ray, UINT renderTypeMask = RENDERTYPE_OPAQUE, uint32_t layerMask = ~0); + // Given a ray, finds the closest intersection point against all mesh instances + // ray : the incoming ray that will be traced + // renderTypeMask : filter based on render type + // layerMask : filter based on layer + // scene : the scene that will be traced against the ray + PickResult Pick(const RAY& ray, UINT renderTypeMask = RENDERTYPE_OPAQUE, uint32_t layerMask = ~0, const Scene& scene = GetScene()); } diff --git a/WickedEngine/wiSceneSystem_BindLua.cpp b/WickedEngine/wiSceneSystem_BindLua.cpp index 9a70a3668..244f28a0f 100644 --- a/WickedEngine/wiSceneSystem_BindLua.cpp +++ b/WickedEngine/wiSceneSystem_BindLua.cpp @@ -31,23 +31,57 @@ int LoadModel(lua_State* L) int argc = wiLua::SGetArgCount(L); if (argc > 0) { - string fileName = wiLua::SGetString(L, 1); - XMMATRIX transform = XMMatrixIdentity(); - if (argc > 1) + Scene_BindLua* custom_scene = Luna::lightcheck(L, 1); + if (custom_scene) { - Matrix_BindLua* matrix = Luna::lightcheck(L, 2); - if (matrix != nullptr) + // Overload 1: thread safe version + if (argc > 1) { - transform = matrix->matrix; + string fileName = wiLua::SGetString(L, 2); + XMMATRIX transform = XMMatrixIdentity(); + if (argc > 2) + { + Matrix_BindLua* matrix = Luna::lightcheck(L, 3); + if (matrix != nullptr) + { + transform = matrix->matrix; + } + else + { + wiLua::SError(L, "LoadModel(Scene scene, string fileName, opt Matrix transform) argument is not a matrix!"); + } + } + Entity root = wiSceneSystem::LoadModel(*custom_scene->scene, fileName, transform, true); + wiLua::SSetInt(L, int(root)); + return 1; } else { - wiLua::SError(L, "LoadModel(string fileName, opt Matrix transform) argument is not a matrix!"); + wiLua::SError(L, "LoadModel(Scene scene, string fileName, opt Matrix transform) not enough arguments!"); + return 0; } } - Entity root = wiSceneSystem::LoadModel(fileName, transform, true); - wiLua::SSetInt(L, int(root)); - return 1; + else + { + // Overload 2: global scene version + string fileName = wiLua::SGetString(L, 1); + XMMATRIX transform = XMMatrixIdentity(); + if (argc > 1) + { + Matrix_BindLua* matrix = Luna::lightcheck(L, 2); + if (matrix != nullptr) + { + transform = matrix->matrix; + } + else + { + wiLua::SError(L, "LoadModel(string fileName, opt Matrix transform) argument is not a matrix!"); + } + } + Entity root = wiSceneSystem::LoadModel(fileName, transform, true); + wiLua::SSetInt(L, int(root)); + return 1; + } } else { @@ -65,6 +99,7 @@ int Pick(lua_State* L) { UINT renderTypeMask = RENDERTYPE_OPAQUE; uint32_t layerMask = 0xFFFFFFFF; + Scene* scene = &wiSceneSystem::GetScene(); if (argc > 1) { renderTypeMask = (UINT)wiLua::SGetInt(L, 2); @@ -72,9 +107,22 @@ int Pick(lua_State* L) { int mask = wiLua::SGetInt(L, 3); layerMask = *reinterpret_cast(&mask); + + if (argc > 3) + { + Scene_BindLua* custom_scene = Luna::lightcheck(L, 4); + if (custom_scene) + { + scene = custom_scene->scene; + } + else + { + wiLua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) last argument is not of type Scene!"); + } + } } } - auto& pick = wiSceneSystem::Pick(ray->ray, renderTypeMask, layerMask); + auto& pick = wiSceneSystem::Pick(ray->ray, renderTypeMask, layerMask, *scene); wiLua::SSetInt(L, (int)pick.entity); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.position))); Luna::push(L, new Vector_BindLua(XMLoadFloat3(&pick.normal))); @@ -82,11 +130,11 @@ int Pick(lua_State* L) return 4; } - wiLua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask) first argument must be of Ray type!"); + wiLua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) first argument must be of Ray type!"); } else { - wiLua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask) not enough arguments!"); + wiLua::SError(L, "Pick(Ray ray, opt PICKTYPE pickType, opt uint layerMask, opt Scene scene) not enough arguments!"); } return 0; @@ -126,8 +174,10 @@ const char Scene_BindLua::className[] = "Scene"; Luna::FunctionType Scene_BindLua::methods[] = { lunamethod(Scene_BindLua, Update), lunamethod(Scene_BindLua, Clear), + lunamethod(Scene_BindLua, Merge), lunamethod(Scene_BindLua, Entity_FindByName), lunamethod(Scene_BindLua, Entity_Remove), + lunamethod(Scene_BindLua, Entity_Duplicate), lunamethod(Scene_BindLua, Component_CreateName), lunamethod(Scene_BindLua, Component_CreateLayer), lunamethod(Scene_BindLua, Component_CreateTransform), @@ -149,9 +199,15 @@ Luna::PropertyType Scene_BindLua::properties[] = { Scene_BindLua::Scene_BindLua(lua_State *L) { + owning = true; + scene = new Scene; } Scene_BindLua::~Scene_BindLua() { + if (owning) + { + delete scene; + } } @@ -174,6 +230,27 @@ int Scene_BindLua::Clear(lua_State* L) scene->Clear(); return 0; } +int Scene_BindLua::Merge(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Scene_BindLua* other = Luna::lightcheck(L, 1); + if (other) + { + scene->Merge(*other->scene); + } + else + { + wiLua::SError(L, "Scene::Merge(Scene other) argument is not of type Scene!"); + } + } + else + { + wiLua::SError(L, "Scene::Merge(Scene other) not enough arguments!"); + } + return 0; +} int Scene_BindLua::Entity_FindByName(lua_State* L) { @@ -208,6 +285,24 @@ int Scene_BindLua::Entity_Remove(lua_State* L) } return 0; } +int Scene_BindLua::Entity_Duplicate(lua_State* L) +{ + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + Entity entity = (Entity)wiLua::SGetInt(L, 1); + + Entity clone = scene->Entity_Duplicate(entity); + + wiLua::SSetInt(L, (int)clone); + return 1; + } + else + { + wiLua::SError(L, "Scene::Entity_Duplicate(Entity entity) not enough arguments!"); + } + return 0; +} int Scene_BindLua::Component_CreateName(lua_State* L) { diff --git a/WickedEngine/wiSceneSystem_BindLua.h b/WickedEngine/wiSceneSystem_BindLua.h index dabe25b87..a0b341660 100644 --- a/WickedEngine/wiSceneSystem_BindLua.h +++ b/WickedEngine/wiSceneSystem_BindLua.h @@ -10,6 +10,7 @@ namespace wiSceneSystem_BindLua class Scene_BindLua { public: + bool owning = false; wiSceneSystem::Scene* scene = nullptr; static const char className[]; @@ -22,9 +23,11 @@ namespace wiSceneSystem_BindLua int Update(lua_State* L); int Clear(lua_State* L); + int Merge(lua_State* L); int Entity_FindByName(lua_State* L); int Entity_Remove(lua_State* L); + int Entity_Duplicate(lua_State* L); int Component_CreateName(lua_State* L); int Component_CreateLayer(lua_State* L); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index de2e85425..24872fbce 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 26; // minor bug fixes, alterations, refactors, updates - const int revision = 9; + const int revision = 10; long GetVersion()