e97e1cd79c
* terrain material editing * serialization updates, refactors --------- Co-authored-by: Turánszki János <turanszkij@users.noreply.github.com>
768 lines
23 KiB
C++
768 lines
23 KiB
C++
#include "stdafx.h"
|
|
#include "OptionsWindow.h"
|
|
|
|
using namespace wi::ecs;
|
|
using namespace wi::scene;
|
|
using namespace wi::graphics;
|
|
|
|
void OptionsWindow::Create(EditorComponent* _editor)
|
|
{
|
|
editor = _editor;
|
|
|
|
wi::gui::Window::Create("Options", wi::gui::Window::WindowControls::RESIZE_TOPRIGHT);
|
|
SetShadowRadius(2);
|
|
|
|
enum NEW_THING
|
|
{
|
|
NEW_TRANSFORM,
|
|
NEW_MATERIAL,
|
|
NEW_POINTLIGHT,
|
|
NEW_SPOTLIGHT,
|
|
NEW_DIRECTIONALLIGHT,
|
|
NEW_ENVIRONMENTPROBE,
|
|
NEW_FORCE,
|
|
NEW_DECAL,
|
|
NEW_SOUND,
|
|
NEW_VIDEO,
|
|
NEW_WEATHER,
|
|
NEW_EMITTER,
|
|
NEW_HAIR,
|
|
NEW_CAMERA,
|
|
NEW_CUBE,
|
|
NEW_PLANE,
|
|
NEW_SPHERE,
|
|
NEW_ANIMATION,
|
|
NEW_SCRIPT,
|
|
NEW_COLLIDER,
|
|
NEW_TERRAIN,
|
|
NEW_SPRITE,
|
|
NEW_FONT,
|
|
NEW_VOXELGRID,
|
|
};
|
|
|
|
newCombo.Create("New: ");
|
|
newCombo.selected_font.anim.typewriter.looped = true;
|
|
newCombo.selected_font.anim.typewriter.time = 2;
|
|
newCombo.selected_font.anim.typewriter.character_start = 1;
|
|
newCombo.SetInvalidSelectionText("...");
|
|
newCombo.AddItem("Transform " ICON_TRANSFORM, NEW_TRANSFORM);
|
|
newCombo.AddItem("Material " ICON_MATERIAL, NEW_MATERIAL);
|
|
newCombo.AddItem("Point Light " ICON_POINTLIGHT, NEW_POINTLIGHT);
|
|
newCombo.AddItem("Spot Light " ICON_SPOTLIGHT, NEW_SPOTLIGHT);
|
|
newCombo.AddItem("Directional Light " ICON_DIRECTIONALLIGHT, NEW_DIRECTIONALLIGHT);
|
|
newCombo.AddItem("Environment Probe " ICON_ENVIRONMENTPROBE, NEW_ENVIRONMENTPROBE);
|
|
newCombo.AddItem("Force " ICON_FORCE, NEW_FORCE);
|
|
newCombo.AddItem("Decal " ICON_DECAL, NEW_DECAL);
|
|
newCombo.AddItem("Sound " ICON_SOUND, NEW_SOUND);
|
|
newCombo.AddItem("Video " ICON_VIDEO, NEW_VIDEO);
|
|
newCombo.AddItem("Weather " ICON_WEATHER, NEW_WEATHER);
|
|
newCombo.AddItem("Emitter " ICON_EMITTER, NEW_EMITTER);
|
|
newCombo.AddItem("HairParticle " ICON_HAIR, NEW_HAIR);
|
|
newCombo.AddItem("Camera " ICON_CAMERA, NEW_CAMERA);
|
|
newCombo.AddItem("Cube " ICON_CUBE, NEW_CUBE);
|
|
newCombo.AddItem("Plane " ICON_SQUARE, NEW_PLANE);
|
|
newCombo.AddItem("Sphere " ICON_CIRCLE, NEW_SPHERE);
|
|
newCombo.AddItem("Animation " ICON_ANIMATION, NEW_ANIMATION);
|
|
newCombo.AddItem("Script " ICON_SCRIPT, NEW_SCRIPT);
|
|
newCombo.AddItem("Collider " ICON_COLLIDER, NEW_COLLIDER);
|
|
newCombo.AddItem("Terrain " ICON_TERRAIN, NEW_TERRAIN);
|
|
newCombo.AddItem("Sprite " ICON_SPRITE, NEW_SPRITE);
|
|
newCombo.AddItem("Font " ICON_FONT, NEW_FONT);
|
|
newCombo.AddItem("Voxel Grid " ICON_VOXELGRID, NEW_VOXELGRID);
|
|
newCombo.OnSelect([&](wi::gui::EventArgs args) {
|
|
newCombo.SetSelectedWithoutCallback(-1);
|
|
const EditorComponent::EditorScene& editorscene = editor->GetCurrentEditorScene();
|
|
const CameraComponent& camera = editorscene.camera;
|
|
Scene& scene = editor->GetCurrentScene();
|
|
PickResult pick;
|
|
|
|
XMFLOAT3 in_front_of_camera;
|
|
XMStoreFloat3(&in_front_of_camera, XMVectorAdd(camera.GetEye(), camera.GetAt() * 4));
|
|
|
|
switch (args.userdata)
|
|
{
|
|
case NEW_TRANSFORM:
|
|
pick.entity = scene.Entity_CreateTransform("transform");
|
|
break;
|
|
case NEW_MATERIAL:
|
|
pick.entity = scene.Entity_CreateMaterial("material");
|
|
break;
|
|
case NEW_POINTLIGHT:
|
|
pick.entity = scene.Entity_CreateLight("pointlight", in_front_of_camera, XMFLOAT3(1, 1, 1), 2, 60);
|
|
scene.lights.GetComponent(pick.entity)->type = LightComponent::POINT;
|
|
scene.lights.GetComponent(pick.entity)->intensity = 20;
|
|
break;
|
|
case NEW_SPOTLIGHT:
|
|
pick.entity = scene.Entity_CreateLight("spotlight", in_front_of_camera, XMFLOAT3(1, 1, 1), 2, 60);
|
|
scene.lights.GetComponent(pick.entity)->type = LightComponent::SPOT;
|
|
scene.lights.GetComponent(pick.entity)->intensity = 100;
|
|
break;
|
|
case NEW_DIRECTIONALLIGHT:
|
|
pick.entity = scene.Entity_CreateLight("dirlight", XMFLOAT3(0, 3, 0), XMFLOAT3(1, 1, 1), 2, 60);
|
|
scene.lights.GetComponent(pick.entity)->type = LightComponent::DIRECTIONAL;
|
|
scene.lights.GetComponent(pick.entity)->intensity = 10;
|
|
break;
|
|
case NEW_ENVIRONMENTPROBE:
|
|
pick.entity = scene.Entity_CreateEnvironmentProbe("envprobe", in_front_of_camera);
|
|
break;
|
|
case NEW_FORCE:
|
|
pick.entity = scene.Entity_CreateForce("force");
|
|
break;
|
|
case NEW_DECAL:
|
|
pick.entity = scene.Entity_CreateDecal("decal", "");
|
|
if (scene.materials.Contains(pick.entity))
|
|
{
|
|
MaterialComponent* decal_material = scene.materials.GetComponent(pick.entity);
|
|
decal_material->textures[MaterialComponent::BASECOLORMAP].resource.SetTexture(*wi::texturehelper::getLogo());
|
|
}
|
|
scene.transforms.GetComponent(pick.entity)->RotateRollPitchYaw(XMFLOAT3(XM_PIDIV2, 0, 0));
|
|
break;
|
|
case NEW_SOUND:
|
|
{
|
|
wi::helper::FileDialogParams params;
|
|
params.type = wi::helper::FileDialogParams::OPEN;
|
|
params.description = "Sound";
|
|
params.extensions = wi::resourcemanager::GetSupportedSoundExtensions();
|
|
wi::helper::FileDialog(params, [=](std::string fileName) {
|
|
wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
|
|
Entity entity = editor->GetCurrentScene().Entity_CreateSound(wi::helper::GetFileNameFromPath(fileName), fileName);
|
|
|
|
wi::Archive& archive = editor->AdvanceHistory();
|
|
archive << EditorComponent::HISTORYOP_ADD;
|
|
editor->RecordSelection(archive);
|
|
|
|
editor->ClearSelected();
|
|
editor->AddSelected(entity);
|
|
|
|
editor->RecordSelection(archive);
|
|
editor->RecordEntity(archive, entity);
|
|
|
|
RefreshEntityTree();
|
|
editor->componentsWnd.soundWnd.SetEntity(entity);
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
break;
|
|
case NEW_VIDEO:
|
|
{
|
|
wi::helper::FileDialogParams params;
|
|
params.type = wi::helper::FileDialogParams::OPEN;
|
|
params.description = "Video";
|
|
params.extensions = wi::resourcemanager::GetSupportedVideoExtensions();
|
|
wi::helper::FileDialog(params, [=](std::string fileName) {
|
|
wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
|
|
Entity entity = editor->GetCurrentScene().Entity_CreateVideo(wi::helper::GetFileNameFromPath(fileName), fileName);
|
|
|
|
wi::Archive& archive = editor->AdvanceHistory();
|
|
archive << EditorComponent::HISTORYOP_ADD;
|
|
editor->RecordSelection(archive);
|
|
|
|
editor->ClearSelected();
|
|
editor->AddSelected(entity);
|
|
|
|
editor->RecordSelection(archive);
|
|
editor->RecordEntity(archive, entity);
|
|
|
|
RefreshEntityTree();
|
|
editor->componentsWnd.videoWnd.SetEntity(entity);
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
break;
|
|
case NEW_WEATHER:
|
|
pick.entity = CreateEntity();
|
|
scene.weathers.Create(pick.entity);
|
|
scene.names.Create(pick.entity) = "weather";
|
|
break;
|
|
case NEW_EMITTER:
|
|
pick.entity = scene.Entity_CreateEmitter("emitter");
|
|
break;
|
|
case NEW_HAIR:
|
|
pick.entity = scene.Entity_CreateHair("hair");
|
|
break;
|
|
case NEW_CAMERA:
|
|
pick.entity = scene.Entity_CreateCamera("camera", camera.width, camera.height);
|
|
*scene.cameras.GetComponent(pick.entity) = camera;
|
|
*scene.transforms.GetComponent(pick.entity) = editorscene.camera_transform;
|
|
break;
|
|
case NEW_CUBE:
|
|
pick.entity = scene.Entity_CreateCube("cube");
|
|
pick.subsetIndex = 0;
|
|
break;
|
|
case NEW_PLANE:
|
|
pick.entity = scene.Entity_CreatePlane("plane");
|
|
pick.subsetIndex = 0;
|
|
break;
|
|
case NEW_SPHERE:
|
|
pick.entity = scene.Entity_CreateSphere("sphere");
|
|
pick.subsetIndex = 0;
|
|
break;
|
|
case NEW_ANIMATION:
|
|
pick.entity = CreateEntity();
|
|
scene.animations.Create(pick.entity);
|
|
scene.names.Create(pick.entity) = "animation";
|
|
break;
|
|
case NEW_SCRIPT:
|
|
pick.entity = CreateEntity();
|
|
scene.scripts.Create(pick.entity);
|
|
scene.names.Create(pick.entity) = "script";
|
|
break;
|
|
case NEW_COLLIDER:
|
|
pick.entity = CreateEntity();
|
|
scene.colliders.Create(pick.entity);
|
|
scene.transforms.Create(pick.entity);
|
|
scene.names.Create(pick.entity) = "collider";
|
|
break;
|
|
case NEW_TERRAIN:
|
|
editor->componentsWnd.terrainWnd.entity = pick.entity;
|
|
editor->componentsWnd.terrainWnd.SetupAssets();
|
|
pick.entity = CreateEntity();
|
|
scene.terrains.Create(pick.entity) = editor->componentsWnd.terrainWnd.terrain_preset;
|
|
scene.names.Create(pick.entity) = "terrain";
|
|
break;
|
|
case NEW_SPRITE:
|
|
{
|
|
pick.entity = CreateEntity();
|
|
wi::Sprite& sprite = scene.sprites.Create(pick.entity);
|
|
sprite.params.pivot = XMFLOAT2(0.5f, 0.5f);
|
|
sprite.anim.repeatable = true;
|
|
scene.transforms.Create(pick.entity).Translate(XMFLOAT3(0, 2, 0));
|
|
scene.names.Create(pick.entity) = "sprite";
|
|
}
|
|
break;
|
|
case NEW_FONT:
|
|
{
|
|
pick.entity = CreateEntity();
|
|
wi::SpriteFont& font = scene.fonts.Create(pick.entity);
|
|
font.SetText("Text");
|
|
font.params.h_align = wi::font::Alignment::WIFALIGN_CENTER;
|
|
font.params.v_align = wi::font::Alignment::WIFALIGN_CENTER;
|
|
font.params.scaling = 0.1f;
|
|
font.params.size = 26;
|
|
font.anim.typewriter.looped = true;
|
|
scene.transforms.Create(pick.entity).Translate(XMFLOAT3(0, 2, 0));
|
|
scene.names.Create(pick.entity) = "font";
|
|
}
|
|
break;
|
|
case NEW_VOXELGRID:
|
|
{
|
|
pick.entity = CreateEntity();
|
|
scene.voxel_grids.Create(pick.entity).init(64, 64, 64);
|
|
scene.transforms.Create(pick.entity).Scale(XMFLOAT3(0.25f, 0.25f, 0.25f));
|
|
scene.names.Create(pick.entity) = "voxelgrid";
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (pick.entity != INVALID_ENTITY)
|
|
{
|
|
wi::Archive& archive = editor->AdvanceHistory();
|
|
archive << EditorComponent::HISTORYOP_ADD;
|
|
editor->RecordSelection(archive);
|
|
|
|
editor->ClearSelected();
|
|
editor->AddSelected(pick);
|
|
|
|
editor->RecordSelection(archive);
|
|
editor->RecordEntity(archive, pick.entity);
|
|
}
|
|
RefreshEntityTree();
|
|
});
|
|
newCombo.SetEnabled(true);
|
|
newCombo.SetTooltip("Create new entity");
|
|
AddWidget(&newCombo);
|
|
|
|
|
|
|
|
|
|
|
|
filterCombo.Create("");
|
|
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);
|
|
filterCombo.AddItem(ICON_OBJECT, (uint64_t)Filter::Object);
|
|
filterCombo.AddItem(ICON_ENVIRONMENTPROBE, (uint64_t)Filter::EnvironmentProbe);
|
|
filterCombo.AddItem(ICON_DECAL, (uint64_t)Filter::Decal);
|
|
filterCombo.AddItem(ICON_SOUND, (uint64_t)Filter::Sound);
|
|
filterCombo.AddItem(ICON_VIDEO, (uint64_t)Filter::Video);
|
|
filterCombo.AddItem(ICON_WEATHER, (uint64_t)Filter::Weather);
|
|
filterCombo.AddItem(ICON_POINTLIGHT, (uint64_t)Filter::Light);
|
|
filterCombo.AddItem(ICON_ANIMATION, (uint64_t)Filter::Animation);
|
|
filterCombo.AddItem(ICON_FORCE, (uint64_t)Filter::Force);
|
|
filterCombo.AddItem(ICON_EMITTER, (uint64_t)Filter::Emitter);
|
|
filterCombo.AddItem(ICON_HAIR, (uint64_t)Filter::Hairparticle);
|
|
filterCombo.AddItem(ICON_IK, (uint64_t)Filter::IK);
|
|
filterCombo.AddItem(ICON_CAMERA, (uint64_t)Filter::Camera);
|
|
filterCombo.AddItem(ICON_ARMATURE, (uint64_t)Filter::Armature);
|
|
filterCombo.AddItem(ICON_SPRING, (uint64_t)Filter::Spring);
|
|
filterCombo.AddItem(ICON_COLLIDER, (uint64_t)Filter::Collider);
|
|
filterCombo.AddItem(ICON_SCRIPT, (uint64_t)Filter::Script);
|
|
filterCombo.AddItem(ICON_EXPRESSION, (uint64_t)Filter::Expression);
|
|
filterCombo.AddItem(ICON_HUMANOID, (uint64_t)Filter::Humanoid);
|
|
filterCombo.AddItem(ICON_TERRAIN, (uint64_t)Filter::Terrain);
|
|
filterCombo.AddItem(ICON_SPRITE, (uint64_t)Filter::Sprite);
|
|
filterCombo.AddItem(ICON_FONT, (uint64_t)Filter::Font);
|
|
filterCombo.AddItem(ICON_VOXELGRID, (uint64_t)Filter::VoxelGrid);
|
|
filterCombo.SetTooltip("Apply filtering to the Entities by components");
|
|
filterCombo.OnSelect([&](wi::gui::EventArgs args) {
|
|
filter = (Filter)args.userdata;
|
|
RefreshEntityTree();
|
|
});
|
|
AddWidget(&filterCombo);
|
|
|
|
|
|
filterInput.Create("");
|
|
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));
|
|
entityTree.OnSelect([this](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 < entityTree.GetItemCount(); ++i)
|
|
{
|
|
const wi::gui::TreeList::Item& item = entityTree.GetItem(i);
|
|
if (item.selected)
|
|
{
|
|
wi::scene::PickResult pick;
|
|
pick.entity = (Entity)item.userdata;
|
|
editor->AddSelected(pick);
|
|
}
|
|
}
|
|
|
|
// record NEW selection state...
|
|
editor->RecordSelection(archive);
|
|
|
|
});
|
|
entityTree.OnDelete([=](wi::gui::EventArgs args) {
|
|
// Deletions will be performed in a batch next frame:
|
|
// We don't delete here, because this callback will execute once for each item
|
|
editor->deleting = true;
|
|
});
|
|
AddWidget(&entityTree);
|
|
|
|
graphicsWnd.Create(editor);
|
|
graphicsWnd.SetCollapsed(true);
|
|
AddWidget(&graphicsWnd);
|
|
|
|
cameraWnd.Create(editor);
|
|
cameraWnd.SetCollapsed(true);
|
|
AddWidget(&cameraWnd);
|
|
|
|
paintToolWnd.Create(editor);
|
|
paintToolWnd.SetCollapsed(true);
|
|
AddWidget(&paintToolWnd);
|
|
|
|
materialPickerWnd.Create(editor);
|
|
AddWidget(&materialPickerWnd);
|
|
|
|
|
|
generalWnd.Create(editor);
|
|
generalWnd.SetCollapsed(true);
|
|
AddWidget(&generalWnd);
|
|
|
|
|
|
XMFLOAT2 size = XMFLOAT2(338, 500);
|
|
if (editor->main->config.GetSection("layout").Has("options.width"))
|
|
{
|
|
size.x = editor->main->config.GetSection("layout").GetFloat("options.width");
|
|
}
|
|
if (editor->main->config.GetSection("layout").Has("options.height"))
|
|
{
|
|
size.y = editor->main->config.GetSection("layout").GetFloat("options.height");
|
|
}
|
|
SetSize(size);
|
|
}
|
|
void OptionsWindow::Update(float dt)
|
|
{
|
|
cameraWnd.Update();
|
|
paintToolWnd.Update(dt);
|
|
graphicsWnd.Update();
|
|
}
|
|
|
|
void OptionsWindow::ResizeLayout()
|
|
{
|
|
wi::gui::Window::ResizeLayout();
|
|
const float padding = 4;
|
|
XMFLOAT2 pos = XMFLOAT2(padding, padding);
|
|
const float width = GetWidgetAreaSize().x - padding * 2;
|
|
float x_off = 100;
|
|
editor->main->config.GetSection("layout").Set("options.width", GetSize().x);
|
|
editor->main->config.GetSection("layout").Set("options.height", GetSize().y);
|
|
|
|
generalWnd.SetPos(pos);
|
|
generalWnd.SetSize(XMFLOAT2(width, generalWnd.GetScale().y));
|
|
pos.y += generalWnd.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
graphicsWnd.SetPos(pos);
|
|
graphicsWnd.SetSize(XMFLOAT2(width, graphicsWnd.GetScale().y));
|
|
pos.y += graphicsWnd.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
cameraWnd.SetPos(pos);
|
|
cameraWnd.SetSize(XMFLOAT2(width, cameraWnd.GetScale().y));
|
|
pos.y += cameraWnd.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
materialPickerWnd.SetPos(pos);
|
|
materialPickerWnd.SetSize(XMFLOAT2(width, materialPickerWnd.GetScale().y));
|
|
pos.y += materialPickerWnd.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
paintToolWnd.SetPos(pos);
|
|
paintToolWnd.SetSize(XMFLOAT2(width, paintToolWnd.GetScale().y));
|
|
pos.y += paintToolWnd.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
x_off = 45;
|
|
|
|
newCombo.SetPos(XMFLOAT2(pos.x + x_off, pos.y));
|
|
newCombo.SetSize(XMFLOAT2(width - x_off - newCombo.GetScale().y - 1, newCombo.GetScale().y));
|
|
pos.y += newCombo.GetSize().y;
|
|
pos.y += padding;
|
|
|
|
|
|
|
|
float filterHeight = filterCombo.GetSize().y;
|
|
float filterComboWidth = 30;
|
|
|
|
filterInput.SetPos(XMFLOAT2(pos.x + x_off, pos.y));
|
|
filterInput.SetSize(XMFLOAT2(width - x_off - filterHeight - 5 - filterComboWidth - filterHeight, 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;
|
|
|
|
|
|
|
|
entityTree.SetPos(pos);
|
|
entityTree.SetSize(XMFLOAT2(width, editor->GetLogicalHeight() - pos.y - this->translation_local.y - this->control_size - padding));
|
|
pos.y += entityTree.GetSize().y;
|
|
pos.y += padding;
|
|
}
|
|
|
|
|
|
void OptionsWindow::PushToEntityTree(wi::ecs::Entity entity, int level)
|
|
{
|
|
if (entitytree_added_items.count(entity) != 0)
|
|
{
|
|
return;
|
|
}
|
|
const Scene& scene = editor->GetCurrentScene();
|
|
|
|
if (CheckEntityFilter(entity))
|
|
{
|
|
wi::gui::TreeList::Item item;
|
|
if (filter == Filter::All)
|
|
{
|
|
item.level = level;
|
|
}
|
|
else
|
|
{
|
|
item.level = 0;
|
|
}
|
|
item.userdata = entity;
|
|
item.selected = editor->IsSelected(entity);
|
|
item.open = entitytree_opened_items.count(entity) != 0;
|
|
|
|
const NameComponent* name = scene.names.GetComponent(entity);
|
|
|
|
std::string name_string;
|
|
if (name == nullptr)
|
|
{
|
|
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:
|
|
if (scene.layers.Contains(entity))
|
|
{
|
|
item.name += ICON_LAYER " ";
|
|
}
|
|
if (scene.transforms.Contains(entity))
|
|
{
|
|
item.name += ICON_TRANSFORM " ";
|
|
}
|
|
if (scene.terrains.Contains(entity))
|
|
{
|
|
item.name += ICON_TERRAIN " ";
|
|
}
|
|
if (scene.meshes.Contains(entity))
|
|
{
|
|
item.name += ICON_MESH " ";
|
|
}
|
|
if (scene.objects.Contains(entity))
|
|
{
|
|
item.name += ICON_OBJECT " ";
|
|
}
|
|
if (scene.rigidbodies.Contains(entity))
|
|
{
|
|
item.name += ICON_RIGIDBODY " ";
|
|
}
|
|
if (scene.softbodies.Contains(entity))
|
|
{
|
|
item.name += ICON_SOFTBODY " ";
|
|
}
|
|
if (scene.emitters.Contains(entity))
|
|
{
|
|
item.name += ICON_EMITTER " ";
|
|
}
|
|
if (scene.hairs.Contains(entity))
|
|
{
|
|
item.name += ICON_HAIR " ";
|
|
}
|
|
if (scene.forces.Contains(entity))
|
|
{
|
|
item.name += ICON_FORCE " ";
|
|
}
|
|
if (scene.sounds.Contains(entity))
|
|
{
|
|
item.name += ICON_SOUND " ";
|
|
}
|
|
if (scene.videos.Contains(entity))
|
|
{
|
|
item.name += ICON_VIDEO " ";
|
|
}
|
|
if (scene.decals.Contains(entity))
|
|
{
|
|
item.name += ICON_DECAL " ";
|
|
}
|
|
if (scene.cameras.Contains(entity))
|
|
{
|
|
item.name += ICON_CAMERA " ";
|
|
}
|
|
if (scene.probes.Contains(entity))
|
|
{
|
|
item.name += ICON_ENVIRONMENTPROBE " ";
|
|
}
|
|
if (scene.animations.Contains(entity))
|
|
{
|
|
item.name += ICON_ANIMATION " ";
|
|
}
|
|
if (scene.animation_datas.Contains(entity))
|
|
{
|
|
item.name += "[animation_data] ";
|
|
}
|
|
if (scene.armatures.Contains(entity))
|
|
{
|
|
item.name += ICON_ARMATURE " ";
|
|
}
|
|
if (scene.humanoids.Contains(entity))
|
|
{
|
|
item.name += ICON_HUMANOID " ";
|
|
}
|
|
if (scene.sprites.Contains(entity))
|
|
{
|
|
item.name += ICON_SPRITE " ";
|
|
}
|
|
if (scene.fonts.Contains(entity))
|
|
{
|
|
item.name += ICON_FONT " ";
|
|
}
|
|
if (scene.voxel_grids.Contains(entity))
|
|
{
|
|
item.name += ICON_VOXELGRID " ";
|
|
}
|
|
if (scene.lights.Contains(entity))
|
|
{
|
|
const LightComponent* light = scene.lights.GetComponent(entity);
|
|
switch (light->type)
|
|
{
|
|
default:
|
|
case LightComponent::POINT:
|
|
item.name += ICON_POINTLIGHT " ";
|
|
break;
|
|
case LightComponent::SPOT:
|
|
item.name += ICON_SPOTLIGHT " ";
|
|
break;
|
|
case LightComponent::DIRECTIONAL:
|
|
item.name += ICON_DIRECTIONALLIGHT " ";
|
|
break;
|
|
}
|
|
}
|
|
if (scene.materials.Contains(entity))
|
|
{
|
|
item.name += ICON_MATERIAL " ";
|
|
}
|
|
if (scene.weathers.Contains(entity))
|
|
{
|
|
item.name += ICON_WEATHER " ";
|
|
}
|
|
if (scene.inverse_kinematics.Contains(entity))
|
|
{
|
|
item.name += ICON_IK " ";
|
|
}
|
|
if (scene.springs.Contains(entity))
|
|
{
|
|
item.name += ICON_SPRING " ";
|
|
}
|
|
if (scene.colliders.Contains(entity))
|
|
{
|
|
item.name += ICON_COLLIDER " ";
|
|
}
|
|
if (scene.scripts.Contains(entity))
|
|
{
|
|
item.name += ICON_SCRIPT " ";
|
|
}
|
|
if (scene.expressions.Contains(entity))
|
|
{
|
|
item.name += ICON_EXPRESSION " ";
|
|
}
|
|
bool bone_found = false;
|
|
for (size_t i = 0; i < scene.armatures.GetCount() && !bone_found; ++i)
|
|
{
|
|
const ArmatureComponent& armature = scene.armatures[i];
|
|
for (Entity bone : armature.boneCollection)
|
|
{
|
|
if (entity == bone)
|
|
{
|
|
item.name += ICON_BONE " ";
|
|
bone_found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
item.name += name_string;
|
|
entityTree.AddItem(item);
|
|
|
|
entitytree_added_items.insert(entity);
|
|
}
|
|
|
|
for (size_t i = 0; i < scene.hierarchy.GetCount(); ++i)
|
|
{
|
|
if (scene.hierarchy[i].parentID == entity)
|
|
{
|
|
PushToEntityTree(scene.hierarchy.GetEntity(i), level + 1);
|
|
}
|
|
}
|
|
}
|
|
void OptionsWindow::RefreshEntityTree()
|
|
{
|
|
const Scene& scene = editor->GetCurrentScene();
|
|
materialPickerWnd.RecreateButtons();
|
|
|
|
for (int i = 0; i < entityTree.GetItemCount(); ++i)
|
|
{
|
|
const wi::gui::TreeList::Item& item = entityTree.GetItem(i);
|
|
if (item.open)
|
|
{
|
|
entitytree_opened_items.insert((Entity)item.userdata);
|
|
}
|
|
}
|
|
|
|
entityTree.ClearItems();
|
|
|
|
entitytree_temp_items.clear();
|
|
scene.FindAllEntities(entitytree_temp_items);
|
|
|
|
// Add items to level 0 that are not in hierarchy (not in hierarchy can also mean top level parent):
|
|
// Note that PushToEntityTree will add children recursively, so this is all we need
|
|
for (auto& x : entitytree_temp_items)
|
|
{
|
|
if (!scene.hierarchy.Contains(x))
|
|
{
|
|
PushToEntityTree(x, 0);
|
|
}
|
|
}
|
|
|
|
entitytree_added_items.clear();
|
|
entitytree_opened_items.clear();
|
|
}
|
|
|
|
bool OptionsWindow::CheckEntityFilter(wi::ecs::Entity entity)
|
|
{
|
|
if (filter == Filter::All)
|
|
return true;
|
|
|
|
const Scene& scene = editor->GetCurrentScene();
|
|
bool valid = false;
|
|
|
|
if (
|
|
has_flag(filter, Filter::Transform) && scene.transforms.Contains(entity) ||
|
|
has_flag(filter, Filter::Material) && scene.materials.Contains(entity) ||
|
|
has_flag(filter, Filter::Mesh) && scene.meshes.Contains(entity) ||
|
|
has_flag(filter, Filter::Object) && scene.objects.Contains(entity) ||
|
|
has_flag(filter, Filter::EnvironmentProbe) && scene.probes.Contains(entity) ||
|
|
has_flag(filter, Filter::Decal) && scene.decals.Contains(entity) ||
|
|
has_flag(filter, Filter::Sound) && scene.sounds.Contains(entity) ||
|
|
has_flag(filter, Filter::Weather) && scene.weathers.Contains(entity) ||
|
|
has_flag(filter, Filter::Light) && scene.lights.Contains(entity) ||
|
|
has_flag(filter, Filter::Animation) && scene.animations.Contains(entity) ||
|
|
has_flag(filter, Filter::Force) && scene.forces.Contains(entity) ||
|
|
has_flag(filter, Filter::Emitter) && scene.emitters.Contains(entity) ||
|
|
has_flag(filter, Filter::IK) && scene.inverse_kinematics.Contains(entity) ||
|
|
has_flag(filter, Filter::Camera) && scene.cameras.Contains(entity) ||
|
|
has_flag(filter, Filter::Armature) && scene.armatures.Contains(entity) ||
|
|
has_flag(filter, Filter::Collider) && scene.colliders.Contains(entity) ||
|
|
has_flag(filter, Filter::Script) && scene.scripts.Contains(entity) ||
|
|
has_flag(filter, Filter::Expression) && scene.expressions.Contains(entity) ||
|
|
has_flag(filter, Filter::Terrain) && scene.terrains.Contains(entity) ||
|
|
has_flag(filter, Filter::Spring) && scene.springs.Contains(entity) ||
|
|
has_flag(filter, Filter::Humanoid) && scene.humanoids.Contains(entity) ||
|
|
has_flag(filter, Filter::Video) && scene.videos.Contains(entity) ||
|
|
has_flag(filter, Filter::Sprite) && scene.sprites.Contains(entity) ||
|
|
has_flag(filter, Filter::Font) && scene.fonts.Contains(entity) ||
|
|
has_flag(filter, Filter::VoxelGrid) && scene.voxel_grids.Contains(entity)
|
|
)
|
|
{
|
|
valid = true;
|
|
}
|
|
|
|
return valid;
|
|
}
|