From 6a2173f6996d92c79faf3570e45dd3bfb7b80db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Mon, 29 Aug 2022 12:03:30 +0200 Subject: [PATCH] armature window, object window meshID selection (#542) * armature window, object window meshID selection * fixes, default blink applied --- Editor/ArmatureWindow.cpp | 201 ++++++++++++++++++++++++++ Editor/ArmatureWindow.h | 21 +++ Editor/CMakeLists.txt | 1 + Editor/ComponentsWindow.cpp | 17 ++- Editor/ComponentsWindow.h | 2 + Editor/Editor.cpp | 5 +- Editor/Editor_SOURCE.vcxitems | 2 + Editor/Editor_SOURCE.vcxitems.filters | 2 + Editor/ObjectWindow.cpp | 50 ++++++- Editor/ObjectWindow.h | 1 + WickedEngine/wiScene.h | 2 +- 11 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 Editor/ArmatureWindow.cpp create mode 100644 Editor/ArmatureWindow.h diff --git a/Editor/ArmatureWindow.cpp b/Editor/ArmatureWindow.cpp new file mode 100644 index 000000000..79a06884a --- /dev/null +++ b/Editor/ArmatureWindow.cpp @@ -0,0 +1,201 @@ +#include "stdafx.h" +#include "ArmatureWindow.h" +#include "Editor.h" + +using namespace wi::ecs; +using namespace wi::scene; + +void ArmatureWindow::Create(EditorComponent* _editor) +{ + editor = _editor; + + wi::gui::Window::Create(ICON_ARMATURE " Armature", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE); + SetSize(XMFLOAT2(670, 300)); + + closeButton.SetTooltip("Delete ArmatureComponent"); + OnClose([=](wi::gui::EventArgs args) { + + wi::Archive& archive = editor->AdvanceHistory(); + archive << EditorComponent::HISTORYOP_COMPONENT_DATA; + editor->RecordEntity(archive, entity); + + editor->GetCurrentScene().armatures.Remove(entity); + + editor->RecordEntity(archive, entity); + + editor->optionsWnd.RefreshEntityTree(); + }); + + float x = 60; + float y = 4; + float hei = 20; + float step = hei + 2; + float wid = 220; + + resetPoseButton.Create("Reset Pose"); + resetPoseButton.SetSize(XMFLOAT2(wid, hei)); + resetPoseButton.OnClick([=](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + const ArmatureComponent* armature = scene.armatures.GetComponent(entity); + if (armature == nullptr) + return; + + XMMATRIX R = XMMatrixIdentity(); + const TransformComponent* armature_transform = scene.transforms.GetComponent(entity); + if (armature_transform != nullptr) + { + R = XMMatrixInverse(nullptr, XMLoadFloat4x4(&armature_transform->world)); + } + + for (size_t i = 0; i < armature->boneCollection.size(); ++i) + { + Entity bone = armature->boneCollection[i]; + TransformComponent* transform = scene.transforms.GetComponent(bone); + if (transform != nullptr) + { + transform->ClearTransform(); + transform->MatrixTransform(XMMatrixInverse(nullptr, XMLoadFloat4x4(&armature->inverseBindMatrices[i])) * R); + transform->UpdateTransform(); + const HierarchyComponent* hier = scene.hierarchy.GetComponent(bone); + if (hier != nullptr && hier->parentID != INVALID_ENTITY) + { + scene.Component_Attach(bone, hier->parentID, false); + } + } + } + }); + AddWidget(&resetPoseButton); + + boneList.Create("Bones: "); + boneList.SetSize(XMFLOAT2(wid, 200)); + boneList.SetPos(XMFLOAT2(4, y += step)); + boneList.OnSelect([=](wi::gui::EventArgs args) { + + if (args.iValue < 0) + return; + + wi::Archive& archive = editor->AdvanceHistory(); + archive << EditorComponent::HISTORYOP_SELECTION; + // record PREVIOUS selection state... + editor->RecordSelection(archive); + + editor->translator.selected.clear(); + + for (int i = 0; i < boneList.GetItemCount(); ++i) + { + const wi::gui::TreeList::Item& item = boneList.GetItem(i); + if (item.selected) + { + wi::scene::PickResult pick; + pick.entity = (Entity)item.userdata; + editor->AddSelected(pick); + } + } + + // record NEW selection state... + editor->RecordSelection(archive); + + editor->optionsWnd.RefreshEntityTree(); + + }); + AddWidget(&boneList); + + + SetMinimized(true); + SetVisible(false); + + SetEntity(INVALID_ENTITY); +} + +void ArmatureWindow::SetEntity(Entity entity) +{ + if (this->entity == entity) + return; + + Scene& scene = editor->GetCurrentScene(); + + const ArmatureComponent* armature = scene.armatures.GetComponent(entity); + + if (armature != nullptr || IsCollapsed()) + { + this->entity = entity; + RefreshBoneList(); + } +} +void ArmatureWindow::RefreshBoneList() +{ + Scene& scene = editor->GetCurrentScene(); + + const ArmatureComponent* armature = scene.armatures.GetComponent(entity); + + if (armature != nullptr) + { + boneList.ClearItems(); + for (Entity bone : armature->boneCollection) + { + wi::gui::TreeList::Item item; + item.userdata = bone; + item.name += ICON_BONE " "; + + const NameComponent* name = scene.names.GetComponent(bone); + if (name == nullptr) + { + item.name += "[no_name] " + std::to_string(entity); + } + else if (name->name.empty()) + { + item.name += "[name_empty] " + std::to_string(entity); + } + else + { + item.name += name->name; + } + boneList.AddItem(item); + } + } +} + +void ArmatureWindow::ResizeLayout() +{ + wi::gui::Window::ResizeLayout(); + const float padding = 4; + const float width = GetWidgetAreaSize().x; + float y = padding; + float jump = 20; + + const float margin_left = 110; + const float margin_right = 45; + + auto add = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + widget.SetPos(XMFLOAT2(margin_left, y)); + widget.SetSize(XMFLOAT2(width - margin_left - margin_right, widget.GetScale().y)); + y += widget.GetSize().y; + y += padding; + }; + auto add_right = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + widget.SetPos(XMFLOAT2(width - margin_right - widget.GetSize().x, y)); + y += widget.GetSize().y; + y += padding; + }; + auto add_fullwidth = [&](wi::gui::Widget& widget) { + if (!widget.IsVisible()) + return; + const float margin_left = padding; + const float margin_right = padding; + widget.SetPos(XMFLOAT2(margin_left, y)); + widget.SetSize(XMFLOAT2(width - margin_left - margin_right, widget.GetScale().y)); + y += widget.GetSize().y; + y += padding; + }; + + add_fullwidth(resetPoseButton); + + y += jump; + + add_fullwidth(boneList); + +} diff --git a/Editor/ArmatureWindow.h b/Editor/ArmatureWindow.h new file mode 100644 index 000000000..d43c651d6 --- /dev/null +++ b/Editor/ArmatureWindow.h @@ -0,0 +1,21 @@ +#pragma once +#include "WickedEngine.h" + +class EditorComponent; + +class ArmatureWindow : public wi::gui::Window +{ +public: + void Create(EditorComponent* editor); + + EditorComponent* editor = nullptr; + wi::ecs::Entity entity = wi::ecs::INVALID_ENTITY; + void SetEntity(wi::ecs::Entity entity); + void RefreshBoneList(); + + wi::gui::Button resetPoseButton; + wi::gui::TreeList boneList; + + void ResizeLayout() override; +}; + diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index ee3d51f96..f669c7da2 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -35,6 +35,7 @@ set (SOURCE_FILES ColliderWindow.cpp HierarchyWindow.cpp ExpressionWindow.cpp + ArmatureWindow.cpp OptionsWindow.cpp ComponentsWindow.cpp TerrainGenerator.cpp diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp index a91ca318b..03ad3c30d 100644 --- a/Editor/ComponentsWindow.cpp +++ b/Editor/ComponentsWindow.cpp @@ -39,6 +39,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) hierarchyWnd.Create(editor); cameraComponentWnd.Create(editor); expressionWnd.Create(editor); + armatureWnd.Create(editor); newComponentCombo.Create("Add: "); @@ -299,6 +300,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) AddWidget(&hierarchyWnd); AddWidget(&cameraComponentWnd); AddWidget(&expressionWnd); + AddWidget(&armatureWnd); materialWnd.SetVisible(false); weatherWnd.SetVisible(false); @@ -324,7 +326,7 @@ void ComponentsWindow::Create(EditorComponent* _editor) hierarchyWnd.SetVisible(false); cameraComponentWnd.SetVisible(false); expressionWnd.SetVisible(false); - + armatureWnd.SetVisible(false); SetSize(editor->optionsWnd.GetSize()); } @@ -679,4 +681,17 @@ void ComponentsWindow::ResizeLayout() { expressionWnd.SetVisible(false); } + + if (scene.armatures.Contains(armatureWnd.entity)) + { + armatureWnd.SetVisible(true); + armatureWnd.SetPos(pos); + armatureWnd.SetSize(XMFLOAT2(width, armatureWnd.GetScale().y)); + pos.y += armatureWnd.GetSize().y; + pos.y += padding; + } + else + { + armatureWnd.SetVisible(false); + } } diff --git a/Editor/ComponentsWindow.h b/Editor/ComponentsWindow.h index 3d399d694..fb689bb79 100644 --- a/Editor/ComponentsWindow.h +++ b/Editor/ComponentsWindow.h @@ -24,6 +24,7 @@ #include "HierarchyWindow.h" #include "CameraComponentWindow.h" #include "ExpressionWindow.h" +#include "ArmatureWindow.h" class EditorComponent; @@ -61,4 +62,5 @@ public: HierarchyWindow hierarchyWnd; CameraComponentWindow cameraComponentWnd; ExpressionWindow expressionWnd; + ArmatureWindow armatureWnd; }; diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 7c9db43dd..27a510ceb 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -348,6 +348,7 @@ void EditorComponent::Load() componentsWnd.hierarchyWnd.SetEntity(INVALID_ENTITY); componentsWnd.cameraComponentWnd.SetEntity(INVALID_ENTITY); componentsWnd.expressionWnd.SetEntity(INVALID_ENTITY); + componentsWnd.armatureWnd.SetEntity(INVALID_ENTITY); optionsWnd.RefreshEntityTree(); ResetHistory(); @@ -954,7 +955,7 @@ void EditorComponent::Update(float dt) if (translator.selected.empty() && object->GetRenderTypes() & wi::enums::RENDERTYPE_WATER) { // if water, then put a water ripple onto it: - scene.PutWaterRipple("images/ripple.png", hovered.position); + scene.PutWaterRipple("../Content/models/ripple.png", hovered.position); } else if (componentsWnd.decalWnd.IsEnabled() && componentsWnd.decalWnd.placementCheckBox.GetCheck() && wi::input::Press(wi::input::MOUSE_BUTTON_LEFT)) { @@ -1303,6 +1304,7 @@ void EditorComponent::Update(float dt) componentsWnd.hierarchyWnd.SetEntity(INVALID_ENTITY); componentsWnd.cameraComponentWnd.SetEntity(INVALID_ENTITY); componentsWnd.expressionWnd.SetEntity(INVALID_ENTITY); + componentsWnd.armatureWnd.SetEntity(INVALID_ENTITY); } else { @@ -1341,6 +1343,7 @@ void EditorComponent::Update(float dt) componentsWnd.hierarchyWnd.SetEntity(picked.entity); componentsWnd.cameraComponentWnd.SetEntity(picked.entity); componentsWnd.expressionWnd.SetEntity(picked.entity); + componentsWnd.armatureWnd.SetEntity(picked.entity); if (picked.subsetIndex >= 0) { diff --git a/Editor/Editor_SOURCE.vcxitems b/Editor/Editor_SOURCE.vcxitems index 304630c49..4ce698489 100644 --- a/Editor/Editor_SOURCE.vcxitems +++ b/Editor/Editor_SOURCE.vcxitems @@ -15,6 +15,7 @@ + @@ -132,6 +133,7 @@ + diff --git a/Editor/Editor_SOURCE.vcxitems.filters b/Editor/Editor_SOURCE.vcxitems.filters index cde3855c3..dc0c25a2b 100644 --- a/Editor/Editor_SOURCE.vcxitems.filters +++ b/Editor/Editor_SOURCE.vcxitems.filters @@ -83,6 +83,7 @@ + @@ -130,6 +131,7 @@ + diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 0bfa5669c..489bb2b1f 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -284,6 +284,24 @@ void ObjectWindow::Create(EditorComponent* _editor) float step = hei + 2; float wid = 130; + meshCombo.Create("Mesh: "); + meshCombo.SetSize(XMFLOAT2(wid, hei)); + meshCombo.OnSelect([=](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + ObjectComponent* object = scene.objects.GetComponent(entity); + if (object == nullptr) + return; + + wi::Archive& archive = editor->AdvanceHistory(); + archive << EditorComponent::HISTORYOP_COMPONENT_DATA; + editor->RecordEntity(archive, entity); + + object->meshID = (Entity)args.userdata; + + editor->RecordEntity(archive, entity); + }); + AddWidget(&meshCombo); + renderableCheckBox.Create("Renderable: "); renderableCheckBox.SetTooltip("Set object to be participating in rendering."); renderableCheckBox.SetSize(XMFLOAT2(hei, hei)); @@ -556,6 +574,23 @@ void ObjectWindow::SetEntity(Entity entity) { SetEnabled(true); + meshCombo.ClearItems(); + meshCombo.AddItem("INVALID_ENTITY", (uint64_t)INVALID_ENTITY); + for (size_t i = 0; i < scene.meshes.GetCount(); ++i) + { + Entity meshID = scene.meshes.GetEntity(i); + const NameComponent* name = scene.names.GetComponent(meshID); + if (name == nullptr) + { + meshCombo.AddItem(std::to_string(meshID), (uint64_t)meshID); + } + else + { + meshCombo.AddItem(name->name, (uint64_t)meshID); + } + } + meshCombo.SetSelectedByUserdataWithoutCallback(object->meshID); + renderableCheckBox.SetCheck(object->IsRenderable()); shadowCheckBox.SetCheck(object->IsCastingShadow()); cascadeMaskSlider.SetValue((float)object->cascadeMask); @@ -591,11 +626,12 @@ void ObjectWindow::ResizeLayout() float y = padding; float jump = 20; + float margin_left = 140; + float margin_right = 40; + auto add = [&](wi::gui::Widget& widget) { if (!widget.IsVisible()) return; - const float margin_left = 140; - const float margin_right = 40; widget.SetPos(XMFLOAT2(margin_left, y)); widget.SetSize(XMFLOAT2(width - margin_left - margin_right, widget.GetScale().y)); y += widget.GetSize().y; @@ -604,7 +640,6 @@ void ObjectWindow::ResizeLayout() auto add_right = [&](wi::gui::Widget& widget) { if (!widget.IsVisible()) return; - const float margin_right = 40; widget.SetPos(XMFLOAT2(width - margin_right - widget.GetSize().x, y)); y += widget.GetSize().y; y += padding; @@ -620,6 +655,12 @@ void ObjectWindow::ResizeLayout() y += padding; }; + margin_left = 80; + + add(meshCombo); + + margin_left = 140; + add_right(renderableCheckBox); add_right(shadowCheckBox); add(ditherSlider); @@ -628,6 +669,9 @@ void ObjectWindow::ResizeLayout() add(colorComboBox); add_fullwidth(colorPicker); add(lightmapResolutionSlider); + + margin_left = 80; + add(lightmapSourceUVSetComboBox); add(generateLightmapButton); add(stopLightmapGenButton); diff --git a/Editor/ObjectWindow.h b/Editor/ObjectWindow.h index f146e437b..712f08a50 100644 --- a/Editor/ObjectWindow.h +++ b/Editor/ObjectWindow.h @@ -12,6 +12,7 @@ public: wi::ecs::Entity entity; void SetEntity(wi::ecs::Entity entity); + wi::gui::ComboBox meshCombo; wi::gui::CheckBox renderableCheckBox; wi::gui::CheckBox shadowCheckBox; wi::gui::Slider ditherSlider; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index dad647c49..764cfe59c 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1485,7 +1485,7 @@ namespace wi::scene Blend, }; - float blink_frequency = 0; // number of blinks per second + float blink_frequency = 0.3f; // number of blinks per second float blink_length = 0.1f; // blink's completion time in seconds int blink_count = 2; float look_frequency = 0; // number of lookAt changes per second