Files
TSE/TSE_Editor/src/UI/ElementDrawer.cpp

982 lines
38 KiB
C++

#include "ElementDrawer.hpp"
#include "BehaviourScriptRegistry.hpp"
#include "elements/ShaderRegistry.hpp"
#include "BehaviourScripts/Camera.hpp"
#include <algorithm>
namespace TSE::EDITOR
{
#pragma region helper
bool InputText(const char* label, std::string& str, size_t bufferSize = 256) {
std::vector<char> buffer(bufferSize);
strncpy(buffer.data(), str.c_str(), bufferSize);
buffer[bufferSize - 1] = '\0';
bool changed = ImGui::InputText(label, buffer.data(), bufferSize);
if (changed) {
str = std::string(buffer.data());
}
return changed;
}
void BeginList(std::string listName)
{
ImGui::BeginChild(listName.c_str(), {0,150}, ImGuiChildFlags_Borders);
}
bool ListAddBtn(std::string label = "Add")
{
float available_width = ImGui::GetContentRegionAvail().x;
return ImGui::Button(label.c_str(),{available_width, 0});
}
void BeginListItem(std::string name, float customHeight = 20)
{
float available_width = ImGui::GetContentRegionAvail().x;
ImGui::BeginChild(name.c_str(),{available_width - 30, customHeight});
}
void EndListItem()
{
ImGui::EndChild();
}
bool ListItemXBotton(std::string id)
{
ImGui::SameLine();
return ImGui::Button(id.c_str(), {20,0});
}
void EndList()
{
ImGui::EndChild();
}
#pragma endregion
void ElementDrawer::DrawAddDropdown(const std::vector<string>& options, string& selectedOption)
{
ImGuiStyle& style = ImGui::GetStyle();
float availableWidth = ImGui::GetContentRegionAvail().x;
// Add Button
if (ImGui::Button("Add", ImVec2(availableWidth, 0))) {
addDropdownOpen = !addDropdownOpen;
}
if (addDropdownOpen)
{
// Begin Popup
ImGui::BeginChild("##AddDropdownChild", ImVec2(availableWidth, 300), true);
// Suchfeld mit X Button
ImGui::PushItemWidth(-style.FramePadding.x * 4 - 24); // Platz für Clear Button
ImGui::InputTextWithHint("##SearchField", "Suchfeld", searchBuffer, IM_ARRAYSIZE(searchBuffer));
ImGui::PopItemWidth();
ImGui::SameLine();
if (ImGui::Button("X")) {
searchBuffer[0] = '\0';
}
ImGui::Separator();
// Scrollbare Liste mit Filter
ImGui::BeginChild("##OptionsList", ImVec2(0, 250), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
int count = 0;
for (const auto& option : options)
{
if (strlen(searchBuffer) == 0 || option.find(searchBuffer) != std::string::npos)
{
if (ImGui::Selectable(option.c_str()))
{
selectedOption = option;
addDropdownOpen = false;
break;
}
count++;
if (count >= 50) break; // Begrenze maximal gezeichnete Elemente zur Performance
}
}
ImGui::EndChild();
ImGui::EndChild();
}
}
void ElementDrawer::Draw(Transformable* element,const bool& debug) {
ImGui::SeparatorText("Transform");
ImGui::Checkbox("##checkbox", &element->_enabled);
ImGui::SameLine();
InputText("<-- Name##", element->name);
ImGui::DragFloat3("<-- Position", &element->position.x, 0.1f);
ImGui::DragFloat3("<--Scale", &element->scale.x, 0.1f);
Vector3 euler = element->GetEuler();
ImGui::DragFloat3("<-- Rotation", &(euler.x), 0.1f);
element->SetEuler(euler);
ImGui::Spacing();
if(debug)
{
ImGui::BeginDisabled();
ImGui::Text(("ID: " + to_string(element->id)).c_str());
ImGui::Text(("Child Count: " + std::to_string(element->GetChildren().size())).c_str());
ImGui::Text(("Component Count: " + std::to_string(element->GetComponentCount())).c_str());
ImGui::EndDisabled();
ImGui::Spacing();
}
if(element->GetComponentCount() > 0)
ImGui::SeparatorText("Components");
for (int i = 0; i < element->GetComponentCount(); i++)
{
Draw(element->GetBehaviourScriptAt(i), debug, i);
}
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
std::vector<std::string> behaviourScripts;
for (const auto& [name, _] : BehaviourScriptRegistry::GetRegistry())
{
behaviourScripts.push_back(name);
}
std::string selectedScript = "";
DrawAddDropdown(behaviourScripts, selectedScript);
if (!selectedScript.empty())
{
// Erzeuge das Script:
BehaviourScript* script = BehaviourScriptRegistry::CreateBehaviourScript(selectedScript);
if (script)
{
if(element->HasBehaviourScript(typeid(*script).name()))
{
delete script;
}
else
element->AddBehaviourScript(script);
}
selectedScript = ""; // Reset nach Hinzufügen
}
}
void ElementDrawer::Draw(Scene* element,const bool& debug) {
ImGui::Text("Scene Name: %s", element->GetName().c_str());
ImGui::Text("Layer Count: %d", element->GetLayerCount());
}
void ElementDrawer::Draw(Layer* element,const bool& debug) {
ImGui::Text("Layer Name: %s", element->GetName().c_str());
}
void ElementDrawer::Draw(BehaviourScript *element, const bool &debug, const int& id)
{
ImGui::PushID(("Script##" + std::to_string(id)).c_str());
std::string name = element->GetName();
if(ImGui::CollapsingHeader(name.c_str()))
{
bool enabled = element->IsEnabled();
ImGui::Checkbox("enabled", &enabled);
element->SetEnabled(enabled);
if(name == "Renderable")
{
Draw((Renderable*)element, debug);
}
else if (name == "Mesh Container")
{
Draw((MeshContainer*)element, debug);
}
else if (name == "Image")
{
Draw((Image*)element, debug);
}
else if (name == "Image Animation")
{
Draw((ImageAnimation*)element, debug);
}
else if (name == "Rect Base")
{
Draw((RectBase*)element, debug);
}
else if (name == "Camera")
{
Draw((Camera*)element, debug);
}
else if (name == "Particle System")
{
Draw((ParticleSystem*)element, debug);
}
else
{
element->CustomDraw(debug);
}
}
ImGui::PopID();
}
void ElementDrawer::Draw(Renderable *element, const bool &debug)
{
ImGui::SeparatorText("Material");
int height = 100;
if(element->GetMaterial() == nullptr)
{
height = 35;
}
ImVec2 size(0, height);
ImGui::BeginChild("MaterialViewer", size, ImGuiChildFlags_Borders);
Draw(element->GetMaterial(), debug);
ImGui::EndChild();
}
void ElementDrawer::Draw(MeshContainer *element, const bool &debug)
{
int height = ImGui::GetContentRegionAvail().x;
if(element->GetMesh() == nullptr)
{
height = 35;
}
ImVec2 size(0, height);
Draw(element->GetMesh(), debug, "Mesh", true);
}
void ElementDrawer::Draw(Image *element, const bool &debug)
{
int height = ImGui::GetContentRegionAvail().x + 50;
if(element->GetSpritePtr() == nullptr)
{
height = 35;
}
ImVec2 size(0, height);
ImGui::SeparatorText("Sprite");
Draw(element->GetSpritePtr(), debug, "Sprite", true);
}
void ElementDrawer::Draw(ImageAnimation *element, const bool &debug)
{
int currentSelection = -1;
int itemCount = element->GetImageAnimationSetCount();
std::vector<std::string> items;
for (int i = 0; i < itemCount; i++)
{
if(element->GetImageAnimationAt(i) == nullptr) continue;
items.push_back(element->GetImageAnimationAt(i)->Name);
if(element->GetImageAnimationAt(i)->Name == element->GetCurrentAnimation())
{
currentSelection = i;
}
}
auto getter = [](void* vec, int idx, const char** out_text) {
auto& vector = *static_cast<std::vector<std::string>*>(vec);
if (idx < 0 || idx >= static_cast<int>(vector.size())) return false;
*out_text = vector.at(idx).c_str();
return true;
};
if(ImGui::Combo("Active animation", &currentSelection, getter, static_cast<void*>(&items), items.size()))
{
element->StartAnimation(items[currentSelection]);
}
items.clear();
for (int i = 0; i < itemCount; i++)
{
if(element->GetImageAnimationAt(i) == nullptr)
{
items.push_back("NULL");
continue;
}
items.push_back(element->GetImageAnimationAt(i)->Name);
}
ImGui::Text(("Frame: " + std::to_string(element->GetCurrentFrame())).c_str());
if(debug)
{
ImGui::TextDisabled(("DeltaTime: " + std::to_string(element->GetDeltaTime())).c_str());
}
ImGui::SeparatorText("Animation Sets");
BeginList("ImageAnimationSetList");
if(ListAddBtn() && (itemCount == 0 || items[itemCount - 1] != "NULL"))
{
element->SetAnimationSet("NULL", nullptr);
itemCount++;
items.push_back("NULL");
}
for (int i = 0; i < itemCount; i++)
{
BeginListItem("subcomponent##" + std::to_string(i));
Draw(element->GetImageAnimationAt(i),debug, items[i], true);
EndListItem();
if(ListItemXBotton("x##" + std::to_string(i)))
{
element->RemoveAnimationSet(items[i]);
itemCount--;
i--;
}
}
EndList();
}
void ElementDrawer::Draw(RectBase *element, const bool &debug)
{
ImGui::DragFloat2("Size", &element->size.x);
ImGui::Separator();
if (ImGui::TreeNode("Anchors"))
{
ImGui::Text("Min");
ImGui::DragFloat("X##anchor_min_x", &element->anchors.p1.x,0.2f);
ImGui::DragFloat("Y##anchor_min_y", &element->anchors.p1.y,0.2f);
ImGui::Text("Max");
ImGui::DragFloat("X##anchor_max_x", &element->anchors.p2.x,0.2f);
ImGui::DragFloat("Y##anchor_max_y", &element->anchors.p2.y,0.2f);
ImGui::TreePop();
}
ImGui::Text("Pivot");
ImGui::DragFloat("X##pivot_x", &element->pivit.x,0.2f);
ImGui::DragFloat("Y##pivot_y", &element->pivit.y,0.2f);
}
void ElementDrawer::Draw(Material *element, const bool &debug)
{
if(element == nullptr)
{
ImGui::TextDisabled("No material");
return;
}
else
{
InputText("Name", element->GetName());
int currentSelection = -1;
int itemCount = ShaderRegistry::GetShaderCount();
std::vector<std::string> items;
for (int i = 0; i < itemCount; i++)
{
if(ShaderRegistry::GetShaderAt(i) == nullptr) continue;
items.push_back(ShaderRegistry::GetNameAt(i));
if(ShaderRegistry::GetShaderAt(i) == element->GetShader())
{
currentSelection = i;
}
}
auto getter = [](void* vec, int idx, const char** out_text) {
auto& vector = *static_cast<std::vector<std::string>*>(vec);
if (idx < 0 || idx >= static_cast<int>(vector.size())) return false;
*out_text = vector.at(idx).c_str();
return true;
};
if(ImGui::Combo("Shader", &currentSelection, getter, static_cast<void*>(&items), items.size()))
{
element->SetShader(ShaderRegistry::GetShader(items[currentSelection]));
}
if(debug)
ImGui::TextDisabled(to_string(element->GetID()).c_str());
ImGui::Separator();
int count = element->GetValueCount();
for(int i = 0; i < count; i++)
{
std::tuple<std::any, std::string, std::string> tupel = element->GetValueAt(i);
auto[ptr, type, name] = tupel;
if (type == typeid(int).name())
{
int value = element->GetValue<int>(name);
if(ImGui::InputInt(name.c_str(), &value))
{
element->SetValue(name, value);
}
}
else if (type == typeid(float).name())
{
float value = element->GetValue<float>(name);
if(ImGui::InputFloat(name.c_str(), &value))
{
element->SetValue(name, value);
}
}
else if (type == typeid(Vector2).name())
{
Vector2 value = element->GetValue<Vector2>(name);
if(ImGui::InputFloat2(name.c_str(), &value.x))
{
element->SetValue(name, value);
}
}
else if (type == typeid(Vector3).name())
{
Vector3 value = element->GetValue<Vector3>(name);
if(ImGui::InputFloat3(name.c_str(), &value.x))
{
element->SetValue(name, value);
}
}
else if (type == typeid(Vector4).name())
{
Vector4 value = element->GetValue<Vector4>(name);
if(ImGui::InputFloat4(name.c_str(), &value.x))
{
element->SetValue(name, value);
}
}
else if (type == typeid(Matrix4x4).name())
{
Matrix4x4 value = element->GetValue<Matrix4x4>(name);
//TODO: need to implement;
}
else if (type == typeid(Color).name())
{
Color value = element->GetValue<Color>(name);
if(ImGui::ColorEdit4(name.c_str(), &value.r))
{
element->SetValue(name, value);
}
}
else if (type == typeid(std::string).name())
{
Vector4 value = element->GetValue<Vector4>(name);
if(ImGui::InputFloat4(name.c_str(), &value.x))
{
element->SetValue(name, value);
}
}
else if (type == typeid(Texture*).name())
{
Texture* value = element->GetValue<Texture*>(name);
Draw(value, debug, name , true);
}
else
{
ImGui::TextDisabled(("Not Implemented: " + type).c_str());
}
}
}
}
void ElementDrawer::Draw(Texture *element, const bool &debug, const std::string& label, const bool small)
{
if(element == nullptr)
{
ImGui::Text("No Texture Set");
return;
}
if(small) DrawTextureCompact(element, debug, label);
else DrawTextureNormal(element, debug, label);
}
void ElementDrawer::Draw(Sprite *element, const bool &debug, const std::string &label, const bool small)
{
if(element == nullptr)
{
ImGui::Text("No Sprite Set");
return;
}
if(small) DrawSpriteCompact(element, debug, label);
else DrawSpriteNormal(element, debug, label);
}
void ElementDrawer::Draw(Mesh *element, const bool &debug, const std::string &label, const bool small)
{
if(element == nullptr)
{
ImGui::Text("No Mesh Set");
return;
}
if(small) DrawMeshCompact(element, debug, label);
else DrawMeshNormal(element, debug, label);
}
void ElementDrawer::Draw(ImageAnimationSet *element, const bool &debug, const std::string &label, const bool small)
{
if(element == nullptr)
{
ImGui::Text("No Animation Set Asigned");
return;
}
if(small) DrawImageAnimationSetCompact(element, debug, label);
else DrawImageAnimationSetNormal(element, debug, label);
}
void ElementDrawer::Draw(Camera *element, const bool &debug)
{
const bool isMain = (Camera::mainCamera == element);
if (!isMain && element->baseObject->name != ".EditorCamera") {
if (ImGui::Button("Make Main Camera")) {
Camera::mainCamera = element;
}
} else if(element->baseObject->name != ".EditorCamera") {
ImGui::Text("This is the Main Camera");
}
else
{
ImGui::Text("Editor Camera can't be main camera");
}
ImGui::Separator();
// Render Scale
float renderScale = element->GetRenderScale();
if (ImGui::DragFloat("Render Scale", &renderScale, 0.1f))
element->SetRenderScale(renderScale);
ImGui::Separator();
// Projection
int projIndex = (element->GetProjection() == ProjectionType::Orthographic) ? 0 : 1;
const char* projItems[] = { "Orthographic", "Perspective" };
if (ImGui::Combo("Projection", &projIndex, projItems, IM_ARRAYSIZE(projItems)))
element->SetProjection(projIndex == 0 ? ProjectionType::Orthographic
: ProjectionType::Perspective);
// Clipping Planes
float nearCP = element->GetNearClippingPlane();
if (ImGui::DragFloat("Near Clipping Plane", &nearCP, 0.1f))
element->SetNearClippingPlane(nearCP);
float farCP = element->GetFarClippingPlane();
if (ImGui::DragFloat("Far Clipping Plane", &farCP, 0.1f))
element->SetFarClippingPlane(farCP);
// Field of View (only relevant for Perspective)
const bool isPerspective = (element->GetProjection() == ProjectionType::Perspective);
if (!isPerspective) ImGui::BeginDisabled();
float fov = element->GetFov();
if (ImGui::DragFloat("Field of View (deg)", &fov, 0.1f))
element->SetFov(fov);
if (!isPerspective) ImGui::EndDisabled();
}
void ElementDrawer::Draw(ParticleSystem *element, const bool &debug)
{
float indent = 15.0f;
auto OpeningAngleDeg = [](float conePlane) -> float {
float cosA = std::clamp(conePlane * 2.0f - 1.0f, -1.0f, 1.0f);
return std::acos(cosA) * (180.0f / TSE_PI);
};
auto ClampPositive = [](float& v, float minv = 0.0f) { if (v < minv) v = minv; };
// =========================
// MISC
// =========================
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + indent);
if (ImGui::CollapsingHeader("Misc", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Indent(20.0f);
int pc = static_cast<int>(element->particleCount);
if (ImGui::DragInt("Max Particles", &pc, 1.0f, 0, 100000)) {
if (pc < 0) pc = 0;
element->particleCount = static_cast<uint>(pc);
}
ImGui::Checkbox("Start with Simulated Particles", &element->startWithSimulatedParicles);
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Wenn aktiv, wird beim Start bereits ein gefüllter Partikelpuffer simuliert.");
ImGui::Unindent(20.0f);
ImGui::Separator();
}
// =========================
// START CONDITIONS
// =========================
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + indent);
if (ImGui::CollapsingHeader("Start Conditions", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Indent(20.0f);
if (ImGui::TreeNodeEx("Rotation (Start)", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Random Rotation Direction", &element->startWithRandomRotationDirection);
if (!element->startWithRandomRotationDirection) {
int dirIdx = (element->rotationDirection >= 0.0f) ? 1 : 0;
const char* dirItems[] = { "-1 (CCW)", "+1 (CW)" };
if (ImGui::Combo("Rotation Direction", &dirIdx, dirItems, IM_ARRAYSIZE(dirItems))) {
element->rotationDirection = (dirIdx == 1) ? 1.0f : -1.0f;
}
} else {
ImGui::BeginDisabled();
float dummy = element->rotationDirection;
ImGui::InputFloat("Rotation Direction", &dummy);
ImGui::EndDisabled();
}
ImGui::Checkbox("Random Start Rotation", &element->startWithRandomRotation);
if (element->startWithRandomRotation) {
ImGui::DragFloat("Min Rotation (rad)", &element->minRotationRad, 0.01f);
ImGui::DragFloat("Max Rotation (rad)", &element->maxrotationRad, 0.01f);
if (element->maxrotationRad < element->minRotationRad) std::swap(element->minRotationRad, element->maxrotationRad);
} else {
ImGui::DragFloat("Start Rotation (rad)", &element->maxrotationRad, 0.01f);
ImGui::BeginDisabled(); ImGui::DragFloat("Min Rotation (rad)", &element->minRotationRad, 0.01f); ImGui::EndDisabled();
}
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
if (ImGui::TreeNode("Size (Start)"))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Random Start Size", &element->startWithRandomSize);
if (element->startWithRandomSize) {
if (ImGui::DragFloat("Min Size", &element->minSize, 0.01f)) { ClampPositive(element->minSize, 0.0f); }
if (ImGui::DragFloat("Max Size", &element->maxSize, 0.01f)) { ClampPositive(element->maxSize, 0.0f); }
if (element->maxSize < element->minSize) std::swap(element->minSize, element->maxSize);
} else {
if (ImGui::DragFloat("Start Size", &element->maxSize, 0.01f)) { ClampPositive(element->maxSize, 0.0f); }
ImGui::BeginDisabled(); ImGui::DragFloat("Min Size", &element->minSize, 0.01f); ImGui::EndDisabled();
}
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
if (ImGui::TreeNode("Lifetime (Start)"))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Random Start Lifetime", &element->startWithRandomLifetime);
if (element->startWithRandomLifetime) {
if (ImGui::DragFloat("Min Lifetime (s)", &element->minLifetime, 0.01f)) { ClampPositive(element->minLifetime, 0.0f); }
if (ImGui::DragFloat("Max Lifetime (s)", &element->maxLifetime, 0.01f)) { ClampPositive(element->maxLifetime, 0.0f); }
if (element->maxLifetime < element->minLifetime) std::swap(element->minLifetime, element->maxLifetime);
} else {
if (ImGui::DragFloat("Lifetime (s)", &element->maxLifetime, 0.01f)) { ClampPositive(element->maxLifetime, 0.0f); }
ImGui::BeginDisabled(); ImGui::DragFloat("Min Lifetime (s)", &element->minLifetime, 0.01f); ImGui::EndDisabled();
}
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
ImGui::Unindent(20.0f);
ImGui::Separator();
}
// =========================
// LIFETIME CONDITIONS
// =========================
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + indent);
if (ImGui::CollapsingHeader("Lifetime Conditions", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Indent(20.0f);
if (ImGui::TreeNode("Color over Lifetime"))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Enable Color over Lifetime", &element->changeColorOverLifetime);
// Start immer editierbar
ImGui::ColorEdit4("Start Color", &element->startColor.r, ImGuiColorEditFlags_Float);
// End nur wenn aktiviert
if (!element->changeColorOverLifetime) ImGui::BeginDisabled();
ImGui::ColorEdit4("End Color", &element->endColor.r, ImGuiColorEditFlags_Float);
if (!element->changeColorOverLifetime) ImGui::EndDisabled();
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
if (ImGui::TreeNode("Speed over Lifetime"))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Enable Speed over Lifetime", &element->changeSpeedOverLifetime);
// Start immer frei
ImGui::DragFloat("Start Speed", &element->startSpeed, 0.01f);
// End nur bei aktiv
if (!element->changeSpeedOverLifetime) ImGui::BeginDisabled();
ImGui::DragFloat("End Speed", &element->endSpeed, 0.01f);
if (!element->changeSpeedOverLifetime) ImGui::EndDisabled();
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
if (ImGui::TreeNode("Rotation Speed over Lifetime"))
{
ImGui::Indent(16.0f);
ImGui::Checkbox("Enable RotationSpeed over Lifetime", &element->changeRotationspeedOverLifetime);
// Start immer frei
ImGui::DragFloat("Start RotSpeed", &element->startRotationSpeed, 0.01f);
// End nur bei aktiv
if (!element->changeRotationspeedOverLifetime) ImGui::BeginDisabled();
ImGui::DragFloat("End RotSpeed", &element->endRotationSpeed, 0.01f);
if (!element->changeRotationspeedOverLifetime) ImGui::EndDisabled();
ImGui::Unindent(16.0f);
ImGui::TreePop();
}
ImGui::Unindent(20.0f);
ImGui::Separator();
}
// =========================
// SPAWN AREA
// =========================
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + indent);
if (ImGui::CollapsingHeader("Spawn Area", ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::Indent(20.0f);
ImGui::DragFloat3("Offset (world)", &element->offset.x, 0.01f);
ImGui::DragFloat3("Forward", &element->forward.x, 0.01f);
ImGui::SameLine();
if (ImGui::SmallButton("Normalize##fwd")) {
element->forward.NormalizeSafe(Vector3::forward);
}
if (ImGui::DragFloat("Radius", &element->radius, 0.01f)) {
if (element->radius < 0.0f) element->radius = 0.0f;
}
if (ImGui::SliderFloat("Cone Plane", &element->conePlane, 0.0f, 1.0f, "%.3f")) {
element->conePlane = std::clamp(element->conePlane, 0.0f, 1.0f);
}
float angle = OpeningAngleDeg(element->conePlane);
ImGui::Text("Opening Angle: %.2f deg", angle);
const char* mode = "Forward Cone";
if (element->conePlane == 1.0f) mode = "Full Sphere";
else if (element->conePlane <= 0.5f) mode = "Forward Cone";
else mode = "Inverse Cone";
ImGui::Text("Mode (derived): %s", mode);
if (debug) {
ImGui::Separator();
ImGui::TextDisabled("Debug:");
ImGui::BulletText("Forward len^2: %.6f", element->forward.LengthSqr());
}
ImGui::Unindent(20.0f);
}
}
void ElementDrawer::DrawImageAnimationSetCompact(ImageAnimationSet *element, const bool &debug, const std::string &label)
{
float item_spacing = ImGui::GetStyle().ItemSpacing.x;
ImVec2 label_size = ImGui::CalcTextSize(label.c_str());
float available_width = ImGui::GetContentRegionAvail().x;
float field_width = available_width - label_size.x - item_spacing;
ImVec2 field_size = ImVec2(field_width, label_size.y + 4);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetColorU32(ImGuiCol_FrameBg)); // gleiche Farbe wie InputText
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, ImGui::GetStyle().FrameRounding);
ImGui::BeginChild("##FakeInput", field_size, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGui::SetCursorPos(ImVec2(2, 2));
ImGui::TextUnformatted(element->Name.c_str());
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
ImGui::SameLine();
ImVec2 cursorCurrent = ImGui::GetCursorPos();
cursorCurrent.y += 2;
ImGui::SetCursorPos(cursorCurrent);
ImGui::TextUnformatted(label.c_str());
}
void ElementDrawer::DrawImageAnimationSetNormal(ImageAnimationSet *element, const bool &debug, const std::string &label)
{
InputText("Name", element->Name);
ImGui::InputFloat("Frame Time", &element->frameTime);
ImGui::SeparatorText("Sprites");
BeginList("SpriteList");
if(ListAddBtn())
{
element->Sprites.push_back(nullptr);
}
auto it = element->Sprites.begin();
for (int i = 0; i < element->Sprites.size(); i++)
{
BeginListItem("subcomponent##" + std::to_string(i),65);
Draw(element->Sprites[i],debug, std::to_string(i), true);
EndListItem();
if(ListItemXBotton("x##" + std::to_string(i)))
{
auto it2 = it;
it--;
element->Sprites.erase(it2);
i--;
}
it++;
}
EndList();
}
void ElementDrawer::DrawMeshCompact(Mesh *element, const bool &debug, const std::string &label)
{
float item_spacing = ImGui::GetStyle().ItemSpacing.x;
ImVec2 label_size = ImGui::CalcTextSize(label.c_str());
float available_width = ImGui::GetContentRegionAvail().x;
float field_width = available_width - label_size.x - item_spacing;
ImVec2 field_size = ImVec2(field_width, label_size.y + 4);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetColorU32(ImGuiCol_FrameBg)); // gleiche Farbe wie InputText
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, ImGui::GetStyle().FrameRounding);
ImGui::BeginChild("##FakeInput", field_size, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGui::SetCursorPos(ImVec2(2, 2));
ImGui::TextUnformatted(element->name.c_str());
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
ImGui::SameLine();
ImVec2 cursorCurrent = ImGui::GetCursorPos();
cursorCurrent.y += 2;
ImGui::SetCursorPos(cursorCurrent);
ImGui::TextUnformatted(label.c_str());
}
void ElementDrawer::DrawMeshNormal(Mesh *element, const bool &debug, const std::string &label)
{
ImGui::Text(("Name: " + element->name).c_str());
if(debug)
{
//ImGui::TextDisabled(("ID: " + to_string(element->id)).c_str());
}
ImGui::Separator();
ImGui::Text(("Vectex Count: " + std::to_string(element->vertecies.size())).c_str());
ImGui::Text(("Index Count: " + std::to_string(element->indecies.size())).c_str());
ImGui::Text(("UV Count: " + std::to_string(element->uvs.size())).c_str());
ImGui::Indent(20.0f);
if(ImGui::CollapsingHeader("Vertecies"))
{
ImGui::PushID("Verts");
ImGui::BeginDisabled();
for (int i = 0; i < element->vertecies.size(); i++)
{
ImGui::InputFloat3(std::to_string(i).c_str(), &element->vertecies[i].x);
}
ImGui::EndDisabled();
ImGui::PopID();
}
if(ImGui::CollapsingHeader("Indecies"))
{
ImGui::PushID("Inds");
ImGui::BeginDisabled();
for (int i = 0; i < element->indecies.size(); i++)
{
int val = element->indecies[i];
ImGui::InputInt(std::to_string(i).c_str(), &val);
}
ImGui::EndDisabled();
ImGui::PopID();
}
if(ImGui::CollapsingHeader("UVs"))
{
ImGui::PushID("Uvs");
ImGui::BeginDisabled();
for (int i = 0; i < element->uvs.size(); i++)
{
ImGui::InputFloat2(std::to_string(i).c_str(), &element->uvs[i].x);
}
ImGui::EndDisabled();
ImGui::PopID();
}
ImGui::Unindent(20.0f);
}
void ElementDrawer::DrawSpriteCompact(Sprite *element, const bool &debug, const std::string &label)
{
float item_spacing = ImGui::GetStyle().ItemSpacing.x;
ImVec2 label_size = ImGui::CalcTextSize(label.c_str());
float available_width = ImGui::GetContentRegionAvail().x;
float field_width = available_width - label_size.x - item_spacing;
ImVec2 field_size = ImVec2(field_width, 60);
Rect r = element->GetUVRect();
float ymultiplyer = (element->GetTexture()->Height() * r.height()) / (element->GetTexture()->Width() * r.width());
ImVec2 texSize (field_size.y - 2, (field_size.y - 2) * ymultiplyer);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetColorU32(ImGuiCol_FrameBg)); // gleiche Farbe wie InputText
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, ImGui::GetStyle().FrameRounding);
ImGui::BeginChild("##FakeInput", field_size, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGui::SetCursorPos(ImVec2(1,(60-texSize.y) / 2));
ImGui::Image(element->GetTexture()->GetTextureId(), texSize, {r.p1.x,r.p2.y}, {r.p2.x,r.p1.y});
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
ImGui::SameLine();
ImVec2 cursorCurrent = ImGui::GetCursorPos();
cursorCurrent.y += (60-label_size.y) / 2;
ImGui::SetCursorPos(cursorCurrent);
ImGui::TextUnformatted(label.c_str());
}
void ElementDrawer::DrawSpriteNormal(Sprite *element, const bool &debug, const std::string &label)
{
Rect& r = element->GetUVRect();
ImGui::InputFloat2("UV1", &r.p1.x);
ImGui::InputFloat2("UV2", &r.p2.x);
if(debug)
{
Draw(element->GetTexture(), debug, "Texture", true);
}
ImGui::Separator();
float available_width = ImGui::GetContentRegionAvail().x;
float ymultiplyer = (element->GetTexture()->Height() * r.height()) / (element->GetTexture()->Width() * r.width());
ImVec2 texSize (available_width, (available_width) * ymultiplyer);
ImGui::Image(element->GetTexture()->GetTextureId(), texSize, {r.p1.x,r.p2.y}, {r.p2.x,r.p1.y});
}
void ElementDrawer::DrawTextureCompact(Texture *element, const bool &debug, const std::string &label)
{
float item_spacing = ImGui::GetStyle().ItemSpacing.x;
ImVec2 label_size = ImGui::CalcTextSize(label.c_str());
float available_width = ImGui::GetContentRegionAvail().x;
float field_width = available_width - label_size.x - item_spacing;
ImVec2 field_size = ImVec2(field_width, 60);
float ymultiplyer = element->Height() / element->Width();
ImVec2 texSize (field_size.y - 2, (field_size.y - 2) * ymultiplyer);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetColorU32(ImGuiCol_FrameBg)); // gleiche Farbe wie InputText
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, ImGui::GetStyle().FrameRounding);
ImGui::BeginChild("##FakeInput", field_size, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
ImGui::SetCursorPos(ImVec2(1,(60-texSize.y) / 2));
ImGui::Image(element->GetTextureId(), texSize, {0,1}, {1,0});
ImGui::SameLine();
ImGui::SetCursorPos(ImVec2(field_size.y + 1,(60-label_size.y) / 2));
ImGui::TextUnformatted(element->name.c_str());
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
ImGui::SameLine();
ImVec2 cursorCurrent = ImGui::GetCursorPos();
cursorCurrent.y += (60-label_size.y) / 2;
ImGui::SetCursorPos(cursorCurrent);
ImGui::TextUnformatted(label.c_str());
}
void ElementDrawer::DrawTextureNormal(Texture *element, const bool &debug, const std::string& label)
{
ImGui::TextUnformatted(element->name.c_str());
if(debug)
{
ImGui::Separator();
ImGui::TextDisabled(("Width: " + std::to_string(element->Width())).c_str());
ImGui::TextDisabled(("Height: " + std::to_string(element->Height())).c_str());
ImGui::TextDisabled(("BPP: " + std::to_string(element->bpp())).c_str());
ImGui::TextDisabled(("Chanels: " + std::to_string(element->Chanels())).c_str());
ImGui::Separator();
ImGui::TextDisabled(("TextureID: " + std::to_string(element->GetTextureId())).c_str());
}
ImGui::Separator();
float available_width = ImGui::GetContentRegionAvail().x;
float ymultiplyer = element->Height() / element->Width();
ImVec2 texSize (available_width, (available_width) * ymultiplyer);
ImGui::Image(element->GetTextureId(), texSize, {0,1}, {1,0});
}
} // namespace TSE::EDITOR