diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 71ac80914..b3911423a 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -1695,11 +1695,6 @@ void EditorComponent::Update(float dt) { wi::renderer::SetToDrawDebugColliders(optionsWnd.generalWnd.colliderVisCheckBox.GetCheck()); } - - if (optionsWnd.filterInput.GetState() == wi::gui::WIDGETSTATE::ACTIVE) - { - optionsWnd.RefreshEntityTree(); - } } void EditorComponent::PostUpdate() { diff --git a/Editor/OptionsWindow.cpp b/Editor/OptionsWindow.cpp index 34cc628a9..e518aec92 100644 --- a/Editor/OptionsWindow.cpp +++ b/Editor/OptionsWindow.cpp @@ -179,7 +179,7 @@ void OptionsWindow::Create(EditorComponent* _editor) filterCombo.Create(""); - filterCombo.AddItem("", (uint64_t)Filter::All); + filterCombo.AddItem("*", (uint64_t)Filter::All); filterCombo.AddItem(ICON_TRANSFORM, (uint64_t)Filter::Transform); filterCombo.AddItem(ICON_MATERIAL, (uint64_t)Filter::Material); filterCombo.AddItem(ICON_MESH, (uint64_t)Filter::Mesh); @@ -214,8 +214,20 @@ void OptionsWindow::Create(EditorComponent* _editor) filterInput.SetTooltip("Apply filtering to the Entities by name"); filterInput.SetDescription(ICON_FILTER ": "); filterInput.SetCancelInputEnabled(false); + filterInput.OnInput([=](wi::gui::EventArgs args) { + RefreshEntityTree(); + }); AddWidget(&filterInput); + filterCaseCheckBox.Create(""); + filterCaseCheckBox.SetCheckText("Aa"); + filterCaseCheckBox.SetUnCheckText("a"); + filterCaseCheckBox.SetTooltip("Toggle case-sensitive name filtering"); + filterCaseCheckBox.OnClick([=](wi::gui::EventArgs args) { + RefreshEntityTree(); + }); + AddWidget(&filterCaseCheckBox); + entityTree.Create("Entities"); entityTree.SetSize(XMFLOAT2(300, 300)); @@ -336,13 +348,17 @@ void OptionsWindow::ResizeLayout() + float filterHeight = filterCombo.GetSize().y; float filterComboWidth = 30; filterInput.SetPos(XMFLOAT2(pos.x + x_off, pos.y)); - filterInput.SetSize(XMFLOAT2(width - x_off - filterInput.GetScale().y - 3 - filterComboWidth, filterCombo.GetScale().y)); + filterInput.SetSize(XMFLOAT2(width - x_off - filterHeight - 5 - filterComboWidth - filterHeight, filterCombo.GetScale().y)); - filterCombo.SetPos(XMFLOAT2(filterInput.GetPos().x + filterInput.GetSize().x + 2, pos.y)); - filterCombo.SetSize(XMFLOAT2(filterComboWidth, filterCombo.GetScale().y)); + filterCaseCheckBox.SetPos(XMFLOAT2(filterInput.GetPos().x + filterInput.GetSize().x + 2, pos.y)); + filterCaseCheckBox.SetSize(XMFLOAT2(filterHeight, filterHeight)); + + filterCombo.SetPos(XMFLOAT2(filterCaseCheckBox.GetPos().x + filterCaseCheckBox.GetSize().x + 2, pos.y)); + filterCombo.SetSize(XMFLOAT2(filterComboWidth, filterHeight)); pos.y += filterCombo.GetSize().y; pos.y += padding; @@ -370,9 +386,32 @@ void OptionsWindow::PushToEntityTree(wi::ecs::Entity entity, int level) item.open = entitytree_opened_items.count(entity) != 0; const NameComponent* name = scene.names.GetComponent(entity); - if (name == nullptr || name->name.find(filterInput.GetCurrentInputValue()) == std::string::npos) + + std::string name_string; + if (name == nullptr) { - return; + name_string = "[no_name] " + std::to_string(entity); + } + else if (name->name.empty()) + { + name_string = "[name_empty] " + std::to_string(entity); + } + else + { + name_string = name->name; + } + + std::string name_filter = filterInput.GetCurrentInputValue(); + if (!name_filter.empty()) + { + if (filterCaseCheckBox.GetCheck() && name_string.find(name_filter) == std::string::npos) + { + return; + } + else if (wi::helper::toUpper(name_string).find(wi::helper::toUpper(name_filter)) == std::string::npos) + { + return; + } } // Icons: @@ -504,18 +543,7 @@ void OptionsWindow::PushToEntityTree(wi::ecs::Entity entity, int level) } } - 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; - } + item.name += name_string; entityTree.AddItem(item); entitytree_added_items.insert(entity); diff --git a/Editor/OptionsWindow.h b/Editor/OptionsWindow.h index 5b38766e3..763276a4d 100644 --- a/Editor/OptionsWindow.h +++ b/Editor/OptionsWindow.h @@ -53,6 +53,7 @@ public: wi::gui::ComboBox newCombo; wi::gui::ComboBox filterCombo; wi::gui::TextInputField filterInput; + wi::gui::CheckBox filterCaseCheckBox; wi::gui::TreeList entityTree; wi::unordered_set entitytree_added_items; wi::unordered_set entitytree_opened_items; diff --git a/WickedEngine/wiGUI.cpp b/WickedEngine/wiGUI.cpp index a08bdfb1e..3f9d7cb6e 100644 --- a/WickedEngine/wiGUI.cpp +++ b/WickedEngine/wiGUI.cpp @@ -1247,6 +1247,7 @@ namespace wi::gui int caret_pos = 0; int caret_begin = 0; int caret_delay = 0; + bool input_updated = false; wi::Timer caret_timer; void TextInputField::Create(const std::string& name) { @@ -1286,7 +1287,7 @@ namespace wi::gui { return font_input.GetTextA(); } - return ""; + return GetValue(); } void TextInputField::Update(const wi::Canvas& canvas, float dt) { @@ -1465,6 +1466,14 @@ namespace wi::gui { SetValue(font_input.GetTextA()); } + + if (input_updated && onInput) + { + wi::gui::EventArgs args; + args.sValue = GetCurrentInputValue(); + onInput(args); + } + input_updated = false; } } @@ -1558,8 +1567,13 @@ namespace wi::gui { onInputAccepted = func; } + void TextInputField::OnInput(std::function func) + { + onInput = func; + } void TextInputField::AddInput(const wchar_t inputChar) { + input_updated = true; switch (inputChar) { case '\b': // BACKSPACE @@ -1591,6 +1605,7 @@ namespace wi::gui } void TextInputField::DeleteFromInput(int direction) { + input_updated = true; std::wstring value_new = font_input.GetText(); if (caret_begin != caret_pos) { @@ -2064,6 +2079,18 @@ namespace wi::gui wi::image::Draw(wi::texturehelper::getWhite(), params, cmd); } } + else if (!uncheck_text.empty()) + { + wi::font::Params params; + params.posX = translation.x + scale.x * 0.5f; + params.posY = translation.y + scale.y * 0.5f; + params.h_align = wi::font::WIFALIGN_CENTER; + params.v_align = wi::font::WIFALIGN_CENTER; + params.size = int(scale.y); + params.scaling = 0.75f; + params.color = font.params.color; + wi::font::Draw(uncheck_text, params, cmd); + } } void CheckBox::OnClick(std::function func) @@ -2087,6 +2114,10 @@ namespace wi::gui { wi::helper::StringConvert(text, check_text); } + void CheckBox::SetUnCheckText(const std::string& text) + { + wi::helper::StringConvert(text, uncheck_text); + } diff --git a/WickedEngine/wiGUI.h b/WickedEngine/wiGUI.h index 340f21fba..9cef1cac4 100644 --- a/WickedEngine/wiGUI.h +++ b/WickedEngine/wiGUI.h @@ -96,13 +96,14 @@ namespace wi::gui // Reduced version of wi::image::Params, excluding position, alignment, etc. struct Image { - XMFLOAT4 color = wi::image::Params().color; - wi::enums::BLENDMODE blendFlag = wi::image::Params().blendFlag; - wi::image::SAMPLEMODE sampleFlag = wi::image::Params().sampleFlag; - wi::image::QUALITY quality = wi::image::Params().quality; - bool background = wi::image::Params().isBackgroundEnabled(); - bool corner_rounding = wi::image::Params().isCornerRoundingEnabled(); - wi::image::Params::Rounding corners_rounding[arraysize(wi::image::Params().corners_rounding)]; + inline static const wi::image::Params params; // prototype for default values + XMFLOAT4 color = params.color; + wi::enums::BLENDMODE blendFlag = params.blendFlag; + wi::image::SAMPLEMODE sampleFlag = params.sampleFlag; + wi::image::QUALITY quality = params.quality; + bool background = params.isBackgroundEnabled(); + bool corner_rounding = params.isCornerRoundingEnabled(); + wi::image::Params::Rounding corners_rounding[arraysize(params.corners_rounding)]; void Apply(wi::image::Params& params) const { @@ -157,15 +158,16 @@ namespace wi::gui // Reduced version of wi::font::Params, excluding position, alignment, etc. struct Font { - wi::Color color = wi::font::Params().color; - wi::Color shadow_color = wi::font::Params().shadowColor; - int style = wi::font::Params().style; - float softness = wi::font::Params().softness; - float bolden = wi::font::Params().bolden; - float shadow_softness = wi::font::Params().shadow_softness; - float shadow_bolden = wi::font::Params().shadow_bolden; - float shadow_offset_x = wi::font::Params().shadow_offset_x; - float shadow_offset_y = wi::font::Params().shadow_offset_y; + inline static const wi::font::Params params; // prototype for default values + wi::Color color = params.color; + wi::Color shadow_color = params.shadowColor; + int style = params.style; + float softness = params.softness; + float bolden = params.bolden; + float shadow_softness = params.shadow_softness; + float shadow_bolden = params.shadow_bolden; + float shadow_offset_x = params.shadow_offset_x; + float shadow_offset_y = params.shadow_offset_y; void Apply(wi::font::Params& params) const { @@ -408,6 +410,7 @@ namespace wi::gui { protected: std::function onInputAccepted; + std::function onInput; static wi::SpriteFont font_input; bool cancel_input_enabled = true; @@ -439,7 +442,10 @@ namespace wi::gui void SetColor(wi::Color color, int id = -1) override; void SetTheme(const Theme& theme, int id = -1) override; + // Called when input was accepted with ENTER key: void OnInputAccepted(std::function func); + // Called when input was updated with new character: + void OnInput(std::function func); }; // Define an interval and slide the control along it @@ -482,6 +488,7 @@ namespace wi::gui std::function onClick; bool checked = false; std::wstring check_text; + std::wstring uncheck_text; public: void Create(const std::string& name); @@ -495,6 +502,7 @@ namespace wi::gui static void SetCheckTextGlobal(const std::string& text); void SetCheckText(const std::string& text); + void SetUnCheckText(const std::string& text); }; // Drop-down list diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index df7480781..9c4dee8ca 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 140; + const int revision = 141; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);