added editor WIP
This commit is contained in:
@@ -7,6 +7,8 @@ std::ofstream TSE::Debug::logFile;
|
|||||||
const std::string fileName = "log.txt";
|
const std::string fileName = "log.txt";
|
||||||
const std::string fileNameOld = "lastlog.txt";
|
const std::string fileNameOld = "lastlog.txt";
|
||||||
|
|
||||||
|
std::vector<void(*)(const std::string&, const TSE::LogEntryType&)> TSE::Debug::onLogCallbacks = std::vector<void(*)(const std::string&, const LogEntryType&)>();
|
||||||
|
|
||||||
int luaPrintRedirect(lua_State* L)
|
int luaPrintRedirect(lua_State* L)
|
||||||
{
|
{
|
||||||
int n = lua_gettop(L);
|
int n = lua_gettop(L);
|
||||||
@@ -61,18 +63,30 @@ void TSE::Debug::Log(string msg)
|
|||||||
{
|
{
|
||||||
std::cout << msg << std::endl;
|
std::cout << msg << std::endl;
|
||||||
logFile << msg << std::endl;
|
logFile << msg << std::endl;
|
||||||
|
for(auto fnc : onLogCallbacks)
|
||||||
|
{
|
||||||
|
fnc(msg, LogEntryType::Log);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::Debug::Error(string msg)
|
void TSE::Debug::Error(string msg)
|
||||||
{
|
{
|
||||||
std::cerr << "[Error] " << msg << std::endl;
|
std::cerr << "[Error] " << msg << std::endl;
|
||||||
logFile << "[Error] " << msg << std::endl;
|
logFile << "[Error] " << msg << std::endl;
|
||||||
|
for(auto fnc : onLogCallbacks)
|
||||||
|
{
|
||||||
|
fnc("[Error] " + msg, LogEntryType::Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::Debug::Warning(string msg)
|
void TSE::Debug::Warning(string msg)
|
||||||
{
|
{
|
||||||
std::cout << "[Warning] " << msg << std::endl;
|
std::cout << "[Warning] " << msg << std::endl;
|
||||||
logFile << "[Warning] " << msg << std::endl;
|
logFile << "[Warning] " << msg << std::endl;
|
||||||
|
for(auto fnc : onLogCallbacks)
|
||||||
|
{
|
||||||
|
fnc("[Warning] " + msg, LogEntryType::Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::Debug::Close()
|
void TSE::Debug::Close()
|
||||||
@@ -80,3 +94,8 @@ void TSE::Debug::Close()
|
|||||||
logFile.flush();
|
logFile.flush();
|
||||||
logFile.close();
|
logFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TSE::Debug::AddCallback(void (*func)(const std::string &, const LogEntryType &))
|
||||||
|
{
|
||||||
|
onLogCallbacks.push_back(func);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
|
|
||||||
namespace TSE
|
namespace TSE
|
||||||
{
|
{
|
||||||
|
enum LogEntryType
|
||||||
|
{
|
||||||
|
Log,
|
||||||
|
Error,
|
||||||
|
Warning,
|
||||||
|
};
|
||||||
|
|
||||||
class Debug
|
class Debug
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -25,9 +32,11 @@ namespace TSE
|
|||||||
static void Warning(string msg);
|
static void Warning(string msg);
|
||||||
/// @brief closes the log file
|
/// @brief closes the log file
|
||||||
static void Close();
|
static void Close();
|
||||||
|
static void AddCallback(void(*func)(const std::string&, const LogEntryType&));
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::ofstream logFile;
|
static std::ofstream logFile;
|
||||||
|
static std::vector<void(*)(const std::string&, const LogEntryType&)> onLogCallbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace TSE
|
} // namespace TSE
|
||||||
|
|||||||
@@ -132,7 +132,9 @@ void TSE::Camera::OnUpdate()
|
|||||||
{
|
{
|
||||||
mainCamera = this;
|
mainCamera = this;
|
||||||
}
|
}
|
||||||
IRenderer::camerasToRenderWith.push_back(this);
|
|
||||||
|
if(rt != nullptr)
|
||||||
|
IRenderer::camerasToRenderWith.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::Camera::Start()
|
void TSE::Camera::Start()
|
||||||
|
|||||||
63
TSE_Editor/CMakeLists.txt
Normal file
63
TSE_Editor/CMakeLists.txt
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#cmake version
|
||||||
|
cmake_minimum_required(VERSION 3.31)
|
||||||
|
|
||||||
|
#project name
|
||||||
|
project(TSE_Editor)
|
||||||
|
|
||||||
|
#cpp settings
|
||||||
|
find_program(CLANG_C NAMES clang)
|
||||||
|
find_program(CLANG_CXX NAMES clang++)
|
||||||
|
|
||||||
|
if(CLANG_C AND CLANG_CXX)
|
||||||
|
message(STATUS "foung Clang, using as Compiler")
|
||||||
|
set(CMAKE_C_COMPILER ${CLANG_C} CACHE STRING "C Compiler" FORCE)
|
||||||
|
set(CMAKE_CXX_COMPILER ${CLANG_CXX} CACHE STRING "C++ Compiler" FORCE)
|
||||||
|
else()
|
||||||
|
message(STATUS "Clang not found, using Standard-Compiler")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
#project output settings
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/lib")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${PROJECT_SOURCE_DIR}/lib/Debug")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${PROJECT_SOURCE_DIR}/lib/Release")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${PROJECT_SOURCE_DIR}/lib/Debug")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${PROJECT_SOURCE_DIR}/lib/Release")
|
||||||
|
|
||||||
|
#source files
|
||||||
|
file(GLOB CPP_SOURCE_TSE
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*/*.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*/*/*.cpp"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*.c"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*.c"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*/*.c"
|
||||||
|
"${PROJECT_SOURCE_DIR}/src/*/*/*/*.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
#includes
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_Base/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_Base/include)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_Math/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_Core/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_Core/include)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_GlfwImpl/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_GlfwImpl/include)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_GlfwOpenGlImpl/src)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../TSE_GlfwOpenGlImpl/include)
|
||||||
|
|
||||||
|
#project def
|
||||||
|
if(Lib)
|
||||||
|
add_library(TSE_Editor SHARED ${CPP_SOURCE_TSE})
|
||||||
|
else()
|
||||||
|
add_library(TSE_Editor STATIC ${CPP_SOURCE_TSE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#flags
|
||||||
|
target_compile_options(TSE_Editor PRIVATE -march=native)
|
||||||
|
|
||||||
53
TSE_Editor/src/BehaviourScriptRegistry.hpp
Normal file
53
TSE_Editor/src/BehaviourScriptRegistry.hpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <functional>
|
||||||
|
#include "elements/BehaviourScript.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class BehaviourScriptRegistry
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using BehaviourScriptCtor = BehaviourScript* (*)();
|
||||||
|
|
||||||
|
inline static std::unordered_map<string, BehaviourScriptCtor> registeredScripts = {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline static void RegisterBehaviourScript(string name, BehaviourScriptCtor ctor )
|
||||||
|
{
|
||||||
|
registeredScripts[name] = ctor;
|
||||||
|
}
|
||||||
|
inline static BehaviourScript* CreateBehaviourScript(string name)
|
||||||
|
{
|
||||||
|
auto it = registeredScripts.find(name);
|
||||||
|
if (it != registeredScripts.end())
|
||||||
|
return it->second();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
inline static void UnregisterBehaviourScript(string name)
|
||||||
|
{
|
||||||
|
registeredScripts.erase(name);
|
||||||
|
}
|
||||||
|
inline static int GetScriptCount()
|
||||||
|
{
|
||||||
|
return registeredScripts.size();
|
||||||
|
}
|
||||||
|
inline static string GetScriptNameAt(int i)
|
||||||
|
{
|
||||||
|
if (i < 0 || i >= static_cast<int>(registeredScripts.size()))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
auto it = registeredScripts.begin();
|
||||||
|
std::advance(it, i);
|
||||||
|
return it->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const auto& GetRegistry()
|
||||||
|
{
|
||||||
|
return registeredScripts;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
|
|
||||||
40
TSE_Editor/src/EditorSubsystem.cpp
Normal file
40
TSE_Editor/src/EditorSubsystem.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include "EditorSubsystem.hpp"
|
||||||
|
|
||||||
|
#include "BehaviourScriptRegistry.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::EditorSubsystem::EditorSubsystem() : sv(nullptr), rt({10,10}), editorLayer("")
|
||||||
|
{
|
||||||
|
rt = TSE::GLFW::RenderTexture({100,100});
|
||||||
|
sv = SceneView(&rt);
|
||||||
|
|
||||||
|
controller.AddGuiElement("Scene", &sv);
|
||||||
|
controller.AddGuiElement("Consol", &cv);
|
||||||
|
controller.AddGuiElement("Hirearchie", &hv);
|
||||||
|
controller.AddGuiElement("Properties", &pv);
|
||||||
|
controller.AddGuiElement("Debug", &dv);
|
||||||
|
controller.AddGuiElement("Camera", &camv);
|
||||||
|
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Image", []() -> BehaviourScript* {return new Image();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Image Animation", []() -> BehaviourScript* {return new ImageAnimation();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Mesh Container", []() -> BehaviourScript* {return new MeshContainer();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Rect Base", []() -> BehaviourScript* {return new RectBase();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Renderable", []() -> BehaviourScript* {return new Renderable();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Particle System", []() -> BehaviourScript* {return new ParticleSystem();});
|
||||||
|
BehaviourScriptRegistry::RegisterBehaviourScript("Camera", []() -> BehaviourScript* {return new Camera();});
|
||||||
|
|
||||||
|
#pragma region camerastuff
|
||||||
|
|
||||||
|
Transformable* editorCamera = new Transformable(".EditorCamera");
|
||||||
|
|
||||||
|
Camera* editorCam = new Camera();
|
||||||
|
editorCam->SetRenderTarget(&rt);
|
||||||
|
editorCamera->AddBehaviourScript(editorCam);
|
||||||
|
|
||||||
|
// basicCameraControls controls = basicCameraControls();
|
||||||
|
// editorCamera->AddBehaviourScript(&controls);
|
||||||
|
|
||||||
|
editorLayer = Layer(".editor");
|
||||||
|
editorLayer.AddTransformable(editorCamera);
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
}
|
||||||
29
TSE_Editor/src/EditorSubsystem.hpp
Normal file
29
TSE_Editor/src/EditorSubsystem.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/ViewportController.hpp"
|
||||||
|
#include "UI/windows/CameraView.hpp"
|
||||||
|
#include "UI/windows/ConsolView.hpp"
|
||||||
|
#include "UI/windows/DebugView.hpp"
|
||||||
|
#include "UI/windows/HirearchieView.hpp"
|
||||||
|
#include "UI/windows/PropertiesView.hpp"
|
||||||
|
#include "UI/windows/SceneView.hpp"
|
||||||
|
#include "RenderTexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class EditorSubsystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewportController controller;
|
||||||
|
ConsolView cv;
|
||||||
|
DebugView dv;
|
||||||
|
HirearchieView hv = HirearchieView(nullptr);
|
||||||
|
PropertiesView pv;
|
||||||
|
CameraView camv;
|
||||||
|
TSE::GLFW::RenderTexture rt;
|
||||||
|
SceneView sv;
|
||||||
|
Layer editorLayer;
|
||||||
|
|
||||||
|
EditorSubsystem();
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
981
TSE_Editor/src/UI/ElementDrawer.cpp
Normal file
981
TSE_Editor/src/UI/ElementDrawer.cpp
Normal file
@@ -0,0 +1,981 @@
|
|||||||
|
#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", ¤tSelection, 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", ¤tSelection, 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
|
||||||
89
TSE_Editor/src/UI/ElementDrawer.hpp
Normal file
89
TSE_Editor/src/UI/ElementDrawer.hpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include "elements/Transformable.hpp"
|
||||||
|
#include "elements/Scene.hpp"
|
||||||
|
#include "elements/Layer.hpp"
|
||||||
|
#include "Debug.hpp"
|
||||||
|
#include "BehaviourScripts/Renderable.hpp"
|
||||||
|
#include "BehaviourScripts/MeshContainer.hpp"
|
||||||
|
#include "BehaviourScripts/ImageAnimation.hpp"
|
||||||
|
#include "BehaviourScripts/RectBase.hpp"
|
||||||
|
#include "BehaviourScripts/ParticleSystem.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
enum class InspectableType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Transformable,
|
||||||
|
Scene,
|
||||||
|
Layer
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Inspectable
|
||||||
|
{
|
||||||
|
InspectableType type = InspectableType::None;
|
||||||
|
void* ptr = nullptr;
|
||||||
|
|
||||||
|
Inspectable() = default;
|
||||||
|
Inspectable(InspectableType t, void* p) : type(t), ptr(p) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ElementDrawer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
inline static bool addDropdownOpen = false;
|
||||||
|
inline static char searchBuffer[128] = "";
|
||||||
|
inline static ImGuiTextFilter filter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Draw(const Inspectable& element,const bool& debug) {
|
||||||
|
switch (element.type) {
|
||||||
|
case InspectableType::Transformable:
|
||||||
|
Draw(static_cast<Transformable*>(element.ptr), debug);
|
||||||
|
break;
|
||||||
|
case InspectableType::Scene:
|
||||||
|
Draw(static_cast<Scene*>(element.ptr), debug);
|
||||||
|
break;
|
||||||
|
case InspectableType::Layer:
|
||||||
|
Draw(static_cast<Layer*>(element.ptr), debug);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TSE_WARNING("Draw not implemented for this type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void DrawAddDropdown(const std::vector<std::string>& options, std::string& selectedOption);
|
||||||
|
static void Draw(Transformable* element,const bool& debug);
|
||||||
|
static void Draw(Scene* element,const bool& debug);
|
||||||
|
static void Draw(Layer* element,const bool& debug);
|
||||||
|
static void Draw(BehaviourScript* element,const bool& debug, const int& id = 0);
|
||||||
|
static void Draw(Renderable* element, const bool& debug);
|
||||||
|
static void Draw(MeshContainer* element, const bool& debug);
|
||||||
|
static void Draw(Image* element, const bool& debug);
|
||||||
|
static void Draw(ImageAnimation* element, const bool& debug);
|
||||||
|
static void Draw(RectBase* element, const bool& debug);
|
||||||
|
static void Draw(Material* element, const bool& debug);
|
||||||
|
static void Draw(Texture* element, const bool& debug, const std::string& label = "", const bool small = false);
|
||||||
|
static void Draw(Sprite* element, const bool& debug, const std::string& label = "", const bool small = false);
|
||||||
|
static void Draw(Mesh* element, const bool& debug, const std::string& label = "", const bool small = false);
|
||||||
|
static void Draw(ImageAnimationSet* element, const bool& debug, const std::string& label = "", const bool small = false);
|
||||||
|
static void Draw(Camera* element, const bool& debug);
|
||||||
|
static void Draw(ParticleSystem* element, const bool& debug);
|
||||||
|
|
||||||
|
|
||||||
|
static void DrawImageAnimationSetCompact(ImageAnimationSet* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawImageAnimationSetNormal(ImageAnimationSet* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawMeshCompact(Mesh* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawMeshNormal(Mesh* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawSpriteCompact(Sprite* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawSpriteNormal(Sprite* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawTextureCompact(Texture* element, const bool& debug, const std::string& label);
|
||||||
|
static void DrawTextureNormal(Texture* element, const bool& debug, const std::string& label);
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
213
TSE_Editor/src/UI/ViewportController.cpp
Normal file
213
TSE_Editor/src/UI/ViewportController.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
#include "ViewportController.hpp"
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "tinyfiledialogs.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::EDITOR::ViewportController::ViewportController()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable | ImGuiConfigFlags_DockingEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wantOpenCreate = false;
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::ShowFileMenu()
|
||||||
|
{
|
||||||
|
// if(ImGui::MenuItem("New Project"))
|
||||||
|
// {
|
||||||
|
// wantOpenCreate = true;
|
||||||
|
// gCreateState.confirmed = false;
|
||||||
|
// gCreateState.nameBuf[0] = '\0';
|
||||||
|
// gCreateState.pathBuf[0] = '\0';
|
||||||
|
// }
|
||||||
|
// if(ImGui::MenuItem("Load Project"))
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// if(ImGui::MenuItem("Save Project"))
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// ImGui::Separator();
|
||||||
|
// if(ImGui::MenuItem("Build"))
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// ImGui::Separator();
|
||||||
|
if(ImGui::MenuItem("Exit"))
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::optional<std::string> PickFolderBlocking(const char* startPath)
|
||||||
|
{
|
||||||
|
const char* chosen = tinyfd_selectFolderDialog("Ordner wählen", startPath);
|
||||||
|
if (chosen && chosen[0]) return std::string(chosen);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::NewProjectPopup()
|
||||||
|
{
|
||||||
|
if (wantOpenCreate) {
|
||||||
|
ImGui::OpenPopup("Neues Element##CreateItemModal");
|
||||||
|
wantOpenCreate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WICHTIG: Diese SetNext*-Aufrufe OHNE IF davor!
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(520, 0), ImGuiCond_Appearing);
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(),
|
||||||
|
ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||||
|
ImGui::SetNextWindowSizeConstraints(ImVec2(480, 0), ImVec2(620, FLT_MAX));
|
||||||
|
|
||||||
|
// --- POPUP ---
|
||||||
|
if (ImGui::BeginPopupModal("Neues Element##CreateItemModal", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted("Name");
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
ImGui::InputText("##name", gCreateState.nameBuf, IM_ARRAYSIZE(gCreateState.nameBuf));
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0, 8));
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Ordner");
|
||||||
|
ImGui::PushItemWidth(-40);
|
||||||
|
ImGui::InputText("##path", gCreateState.pathBuf, IM_ARRAYSIZE(gCreateState.pathBuf));
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (!gCreateState.pickingFolder) {
|
||||||
|
if (ImGui::Button("...", ImVec2(28, 0))) {
|
||||||
|
const char* startPath = (gCreateState.pathBuf[0] ? gCreateState.pathBuf : nullptr);
|
||||||
|
gCreateState.pickingFolder = true;
|
||||||
|
// Erzwinge neuen Thread: std::launch::async
|
||||||
|
gCreateState.pickFuture = std::async(std::launch::async, [startPath]{
|
||||||
|
return PickFolderBlocking(startPath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Während der Auswahl: Button disabled + kleines Status-Label
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::Button("...", ImVec2(28, 0));
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextUnformatted("Öffne Ordner-Dialog...");
|
||||||
|
|
||||||
|
// Poll das Future: sobald fertig, Ergebnis übernehmen
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
if (gCreateState.pickFuture.valid() &&
|
||||||
|
gCreateState.pickFuture.wait_for(0ms) == std::future_status::ready)
|
||||||
|
{
|
||||||
|
if (auto res = gCreateState.pickFuture.get(); res && !res->empty()) {
|
||||||
|
std::snprintf(gCreateState.pathBuf, IM_ARRAYSIZE(gCreateState.pathBuf), "%s", res->c_str());
|
||||||
|
}
|
||||||
|
gCreateState.pickingFolder = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Dummy(ImVec2(0, 10));
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Dummy(ImVec2(0, 2));
|
||||||
|
|
||||||
|
// Buttons rechts
|
||||||
|
float btnW = 80.0f;
|
||||||
|
float totalW = btnW*2 + ImGui::GetStyle().ItemSpacing.x;
|
||||||
|
float avail = ImGui::GetContentRegionAvail().x;
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + avail - totalW);
|
||||||
|
|
||||||
|
if (ImGui::Button("OK", ImVec2(btnW, 0))) {
|
||||||
|
bool valid = gCreateState.nameBuf[0] && gCreateState.pathBuf[0];
|
||||||
|
if (valid) {
|
||||||
|
gCreateState.confirmed = true;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Cancel", ImVec2(btnW, 0))) {
|
||||||
|
gCreateState.confirmed = false;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gCreateState.confirmed)
|
||||||
|
{
|
||||||
|
gCreateState.confirmed = false;
|
||||||
|
//ProjectManager::NewProject(gCreateState.pathBuf, gCreateState.nameBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::ShowViewsMenu()
|
||||||
|
{
|
||||||
|
for(auto ui : uiElements)
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem(ui.first.c_str()))
|
||||||
|
{
|
||||||
|
ui.second->SetEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::MenuBar()
|
||||||
|
{
|
||||||
|
ImGui::BeginMainMenuBar();
|
||||||
|
|
||||||
|
if(ImGui::BeginMenu("File"))
|
||||||
|
{
|
||||||
|
ShowFileMenu();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginMenu("Views"))
|
||||||
|
{
|
||||||
|
ShowViewsMenu();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::EndMainMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::Docking()
|
||||||
|
{
|
||||||
|
ImGuiWindowFlags wndFlags = ImGuiWindowFlags_NoDocking;
|
||||||
|
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||||
|
// ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||||
|
// ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||||
|
// ImGui::SetNextWindowViewport(viewport->ID);
|
||||||
|
// ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
|
// ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
|
// wndFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||||
|
// wndFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||||
|
// ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0,0});
|
||||||
|
// ImGui::Begin("DockSpace", &dockSpaceOpen, wndFlags);
|
||||||
|
// ImGui::PopStyleVar(3);
|
||||||
|
uint dockspaceID = ImGui::GetID("MyDockSpace");
|
||||||
|
ImGui::DockSpaceOverViewport(dockspaceID, viewport);
|
||||||
|
// ImGui::DockSpace(dockspaceID, {0,0});
|
||||||
|
// ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::Update()
|
||||||
|
{
|
||||||
|
MenuBar();
|
||||||
|
NewProjectPopup();
|
||||||
|
Docking();
|
||||||
|
for(auto ui : uiElements)
|
||||||
|
{
|
||||||
|
ui.second->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ViewportController::AddGuiElement(const std::string &name, IGUIElement *element)
|
||||||
|
{
|
||||||
|
uiElements[name] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::EDITOR::IGUIElement *TSE::EDITOR::ViewportController::GetGuiElement(const std::string &name)
|
||||||
|
{
|
||||||
|
return uiElements.at(name);
|
||||||
|
}
|
||||||
41
TSE_Editor/src/UI/ViewportController.hpp
Normal file
41
TSE_Editor/src/UI/ViewportController.hpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/IGUIElement.hpp"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <future>
|
||||||
|
#include <atomic>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
struct CreateItemState
|
||||||
|
{
|
||||||
|
bool confirmed = false;
|
||||||
|
char nameBuf[256] = "";
|
||||||
|
char pathBuf[1024] = "";
|
||||||
|
|
||||||
|
std::atomic<bool> pickingFolder{false};
|
||||||
|
std::future<std::optional<string>> pickFuture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ViewportController
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool dockSpaceOpen = true;
|
||||||
|
std::unordered_map<string, IGUIElement*> uiElements;
|
||||||
|
CreateItemState gCreateState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ViewportController();
|
||||||
|
|
||||||
|
void ShowFileMenu();
|
||||||
|
void NewProjectPopup();
|
||||||
|
void ShowViewsMenu();
|
||||||
|
void MenuBar();
|
||||||
|
void Docking();
|
||||||
|
void Update();
|
||||||
|
void AddGuiElement(const std::string& name, IGUIElement* element);
|
||||||
|
IGUIElement* GetGuiElement(const std::string& name);
|
||||||
|
};
|
||||||
|
} // namespace TSE::Editor
|
||||||
35
TSE_Editor/src/UI/base/GuiWindow.cpp
Normal file
35
TSE_Editor/src/UI/base/GuiWindow.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "GuiWindow.h"
|
||||||
|
|
||||||
|
TSE::EDITOR::GuiWindow::GuiWindow(const string &title, const ImGuiWindowFlags &flags)
|
||||||
|
{
|
||||||
|
this->title = title;
|
||||||
|
this->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::EDITOR::GuiWindow::GuiWindow(const string &title, const Vector2 pos, const Vector2 size, const ImGuiWindowFlags &flags)
|
||||||
|
{
|
||||||
|
this->title = title;
|
||||||
|
this->pos = pos;
|
||||||
|
this->size = size;
|
||||||
|
this->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::GuiWindow::Render()
|
||||||
|
{
|
||||||
|
if(enabled)
|
||||||
|
{
|
||||||
|
Begin();
|
||||||
|
Define();
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::GuiWindow::Begin()
|
||||||
|
{
|
||||||
|
ImGui::Begin(title.c_str(), &enabled, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::GuiWindow::End()
|
||||||
|
{
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
27
TSE_Editor/src/UI/base/GuiWindow.h
Normal file
27
TSE_Editor/src/UI/base/GuiWindow.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IGUIElement.hpp"
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include "Vector2.hpp"
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class GuiWindow : public IGUIElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector2 pos = Vector2::zero;
|
||||||
|
Vector2 size = Vector2(100,100);
|
||||||
|
ImGuiWindowFlags flags = ImGuiWindowFlags_None;
|
||||||
|
string title = "Title";
|
||||||
|
|
||||||
|
GuiWindow(const string& title, const ImGuiWindowFlags& flags = ImGuiWindowFlags_None);
|
||||||
|
GuiWindow(const string& title, const Vector2 pos, const Vector2 size, const ImGuiWindowFlags& flags = ImGuiWindowFlags_None);
|
||||||
|
void Render() override;
|
||||||
|
virtual void Define() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Begin();
|
||||||
|
void End();
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
16
TSE_Editor/src/UI/base/IGUIElement.hpp
Normal file
16
TSE_Editor/src/UI/base/IGUIElement.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class IGUIElement
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool enabled = true;
|
||||||
|
public:
|
||||||
|
virtual void Render() = 0;
|
||||||
|
inline void SetEnabled(bool state)
|
||||||
|
{
|
||||||
|
enabled = state;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
29
TSE_Editor/src/UI/windows/CameraView.cpp
Normal file
29
TSE_Editor/src/UI/windows/CameraView.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "CameraView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::CameraView::CameraView() : GuiWindow("Camera", ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar)
|
||||||
|
, fb({100,100}) { }
|
||||||
|
|
||||||
|
void TSE::EDITOR::CameraView::Define()
|
||||||
|
{
|
||||||
|
if(currentCamera != Camera::mainCamera)
|
||||||
|
{
|
||||||
|
if(currentCamera != nullptr)
|
||||||
|
currentCamera->SetRenderTarget(nullptr);
|
||||||
|
currentCamera = Camera::mainCamera;
|
||||||
|
if(currentCamera != nullptr)
|
||||||
|
currentCamera->SetRenderTarget(&fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiWindowFlags flags2 = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar;
|
||||||
|
if(ImGui::BeginChild("##SceneChild", {0,0}, ImGuiChildFlags_None, flags2))
|
||||||
|
{
|
||||||
|
float w = fb.width();
|
||||||
|
ImGui::Image(fb.GetTextureId(), {fb.width(), fb.height()},{0,1}, {1,0});
|
||||||
|
auto vec2 = ImGui::GetWindowSize();
|
||||||
|
if(fb.width() != vec2.x || fb.height() != vec2.y)
|
||||||
|
{
|
||||||
|
fb.SetSize({vec2.x, vec2.y});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
18
TSE_Editor/src/UI/windows/CameraView.hpp
Normal file
18
TSE_Editor/src/UI/windows/CameraView.hpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include "RenderTexture.hpp"
|
||||||
|
#include "BehaviourScripts/Camera.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class CameraView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Camera* currentCamera = nullptr;
|
||||||
|
TSE::GLFW::RenderTexture fb;
|
||||||
|
public:
|
||||||
|
CameraView();
|
||||||
|
void Define() override;
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
117
TSE_Editor/src/UI/windows/ConsolView.cpp
Normal file
117
TSE_Editor/src/UI/windows/ConsolView.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include "ConsolView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::ConsolView::ConsolView() : GuiWindow("Console", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse)
|
||||||
|
{
|
||||||
|
Debug::AddCallback(CreateLogEntry);
|
||||||
|
textbuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
TSE::EDITOR::ConsolView::~ConsolView()
|
||||||
|
{
|
||||||
|
delete[] textbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::MenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Clear"))
|
||||||
|
{
|
||||||
|
entries.clear();
|
||||||
|
}
|
||||||
|
bool style = logs;
|
||||||
|
if(style) ImGui::PushStyleColor(ImGuiCol_Text, {0,1,0,1});
|
||||||
|
if(ImGui::MenuItem("Logs")) logs = !logs;
|
||||||
|
if(style) ImGui::PopStyleColor();
|
||||||
|
style = warnings;
|
||||||
|
if(style) ImGui::PushStyleColor(ImGuiCol_Text, {0,1,0,1});
|
||||||
|
if(ImGui::MenuItem("Warning")) warnings = !warnings;
|
||||||
|
if(style) ImGui::PopStyleColor();
|
||||||
|
style = errors;
|
||||||
|
if(style) ImGui::PushStyleColor(ImGuiCol_Text, {0,1,0,1});
|
||||||
|
if(ImGui::MenuItem("Errors")) errors = !errors;
|
||||||
|
if(style) ImGui::PopStyleColor();
|
||||||
|
style = autoScroll;
|
||||||
|
if(style) ImGui::PushStyleColor(ImGuiCol_Text, {0,1,0,1});
|
||||||
|
if(ImGui::MenuItem("Auto Scroll")) autoScroll = !autoScroll;
|
||||||
|
if(style) ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::LogList()
|
||||||
|
{
|
||||||
|
float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||||
|
if(ImGui::BeginChild("ScrollingRegion", {0, -footer_height_to_reserve}, ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_HorizontalScrollbar))
|
||||||
|
{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {4, 1});
|
||||||
|
for(auto entry : entries)
|
||||||
|
{
|
||||||
|
switch (entry.type)
|
||||||
|
{
|
||||||
|
case LogEntryType::Warning:
|
||||||
|
if (warnings) continue;
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, {1,1,0,1});
|
||||||
|
ImGui::TextUnformatted(entry.CreateTimedMSG().c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
break;
|
||||||
|
case LogEntryType::Error:
|
||||||
|
if (errors) continue;
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, {1,0,0,1});
|
||||||
|
ImGui::TextUnformatted(entry.CreateTimedMSG().c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
break;
|
||||||
|
case LogEntryType::Log:
|
||||||
|
if (logs) continue;
|
||||||
|
ImGui::TextUnformatted(entry.CreateTimedMSG().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
|
||||||
|
ImGui::SetScrollHereY(1.0f);
|
||||||
|
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Callback(ImGuiInputTextCallbackData* data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::Input()
|
||||||
|
{
|
||||||
|
ImGuiInputTextFlags _flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
|
||||||
|
|
||||||
|
if(ImGui::InputText("<-- Command", textbuffer, 512, _flags, Callback))
|
||||||
|
{
|
||||||
|
HandleInput(std::string(textbuffer));
|
||||||
|
textbuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::Define()
|
||||||
|
{
|
||||||
|
MenuBar();
|
||||||
|
LogList();
|
||||||
|
Input();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::HandleInput(const string &input)
|
||||||
|
{
|
||||||
|
LuaStateHandler::RunLuaString(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::ConsolView::CreateLogEntry(const string &msg, const LogEntryType &t)
|
||||||
|
{
|
||||||
|
if(entries.size() > 0 && entries[entries.size() - 1].msg == msg)
|
||||||
|
{
|
||||||
|
entries[entries.size() - 1].count += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogEntry entry(msg, t);
|
||||||
|
entries.push_back(entry);
|
||||||
|
}
|
||||||
65
TSE_Editor/src/UI/windows/ConsolView.hpp
Normal file
65
TSE_Editor/src/UI/windows/ConsolView.hpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include "Types.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include "Debug.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
struct LogEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LogEntryType type;
|
||||||
|
string msg;
|
||||||
|
std::chrono::hh_mm_ss<std::chrono::milliseconds> time;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
inline LogEntry(const string& message, const LogEntryType& t)
|
||||||
|
{
|
||||||
|
msg = message;
|
||||||
|
type = t;
|
||||||
|
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
auto today = std::chrono::floor<std::chrono::days>(now);
|
||||||
|
auto time_since_midnight = now - today;
|
||||||
|
|
||||||
|
time = std::chrono::hh_mm_ss<std::chrono::milliseconds>(std::chrono::floor<std::chrono::milliseconds>(time_since_midnight));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline string CreateTimedMSG()
|
||||||
|
{
|
||||||
|
string res = std::to_string(time.hours().count()) + ":" + std::to_string(time.minutes().count()) + ":" + std::to_string(time.seconds().count());
|
||||||
|
res += " -> " + msg;
|
||||||
|
if(count > 1)
|
||||||
|
{
|
||||||
|
res += " (" + std::to_string(count) + ")";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConsolView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static inline std::vector<LogEntry> entries = {};
|
||||||
|
|
||||||
|
bool logs = false, warnings = false, errors = false, autoScroll = true;
|
||||||
|
char* textbuffer = new char[512];
|
||||||
|
public:
|
||||||
|
static std::vector<string> arguments;
|
||||||
|
|
||||||
|
ConsolView();
|
||||||
|
~ConsolView();
|
||||||
|
void MenuBar();
|
||||||
|
void LogList();
|
||||||
|
void Input();
|
||||||
|
void Define() override;
|
||||||
|
void HandleInput(const string& input);
|
||||||
|
static void CreateLogEntry(const string& msg, const LogEntryType& t);
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
24
TSE_Editor/src/UI/windows/DebugView.cpp
Normal file
24
TSE_Editor/src/UI/windows/DebugView.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "DebugView.hpp"
|
||||||
|
#include "utils/Time.hpp"
|
||||||
|
#include "elements/Transformable.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::DebugView::DebugView() : GuiWindow("Debug", ImGuiWindowFlags_NoCollapse) { }
|
||||||
|
|
||||||
|
void TSE::EDITOR::DebugView::Define()
|
||||||
|
{
|
||||||
|
lasttime += Time::deltaTime();
|
||||||
|
if(lasttime >= 1)
|
||||||
|
{
|
||||||
|
lasttime = 0;
|
||||||
|
debugFps = std::to_string(frameCount) + " FPS";
|
||||||
|
|
||||||
|
frameCount = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
frameCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Text(debugFps.c_str());
|
||||||
|
ImGui::Text(("Object count: " + std::to_string(Transformable::GetTansformableCount())).c_str());
|
||||||
|
}
|
||||||
23
TSE_Editor/src/UI/windows/DebugView.hpp
Normal file
23
TSE_Editor/src/UI/windows/DebugView.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include "Types.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class DebugView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
string debugFps = "0 FPS";
|
||||||
|
float lasttime = 0;
|
||||||
|
int frameCount = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DebugView();
|
||||||
|
|
||||||
|
~DebugView() = default;
|
||||||
|
|
||||||
|
void Define() override;
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
392
TSE_Editor/src/UI/windows/HirearchieView.cpp
Normal file
392
TSE_Editor/src/UI/windows/HirearchieView.cpp
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
#include "HirearchieView.hpp"
|
||||||
|
#include "PropertiesView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::HirearchieView::HirearchieView(Scene *s) : GuiWindow("Hirearchie", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse)
|
||||||
|
{
|
||||||
|
SetScene(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::SetScene(Scene *s)
|
||||||
|
{
|
||||||
|
currentScene = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::Define()
|
||||||
|
{
|
||||||
|
if(currentScene == nullptr) return;
|
||||||
|
MenuBar();
|
||||||
|
|
||||||
|
bool collapseOpen = ImGui::CollapsingHeader(currentScene->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
|
if(ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Rename"))
|
||||||
|
{
|
||||||
|
strcpy(inputBuffer, currentScene->GetName().c_str());
|
||||||
|
activatePopUpNamingLayer = true;
|
||||||
|
inputPurpose = RenamingScene;
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
AddMenu(nullptr, nullptr);
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
if(collapseOpen)
|
||||||
|
{
|
||||||
|
int layerCount = currentScene->GetLayerCount();
|
||||||
|
for (int i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
auto layer = currentScene->GetLayerAt(i);
|
||||||
|
//if(layer->GetName() != ".editor")
|
||||||
|
DisplayLayer(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(activatePopUpNamingLayer)
|
||||||
|
{
|
||||||
|
activatePopUpNamingLayer = false;
|
||||||
|
openPopUpNamingLayer = true;
|
||||||
|
ImGui::OpenPopup("Enter Text");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openPopUpNamingLayer) {
|
||||||
|
if (ImGui::BeginPopupModal("Enter Text", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
ImGui::Text("Please enter a Name:");
|
||||||
|
|
||||||
|
ImGui::InputText("##input", inputBuffer, IM_ARRAYSIZE(inputBuffer));
|
||||||
|
|
||||||
|
bool inputValid = strlen(inputBuffer) > 0;
|
||||||
|
|
||||||
|
if (!inputValid) {
|
||||||
|
ImGui::TextColored(ImVec4(1,0,0,1), "Not Valid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button("OK", ImVec2(120, 0))) {
|
||||||
|
if (inputValid) {
|
||||||
|
inputConfirmed = true;
|
||||||
|
openPopUpNamingLayer = false;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Cancel", ImVec2(120, 0))) {
|
||||||
|
openPopUpNamingLayer = false;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inputConfirmed) {
|
||||||
|
switch (inputPurpose)
|
||||||
|
{
|
||||||
|
case LayerCreation:
|
||||||
|
CreateLayer();
|
||||||
|
break;
|
||||||
|
case RenamingLayer:
|
||||||
|
currentScene->RenameLayer(tmpHolder2->GetName(), inputBuffer);
|
||||||
|
tmpHolder2 = nullptr;
|
||||||
|
break;
|
||||||
|
case RenamingScene:
|
||||||
|
currentScene->SetName(inputBuffer);
|
||||||
|
break;
|
||||||
|
case RenamingTransformable:
|
||||||
|
tmpHolder1->name = inputBuffer;
|
||||||
|
tmpHolder1 = nullptr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
inputConfirmed = false;
|
||||||
|
inputPurpose = Nothing;
|
||||||
|
strcpy(inputBuffer, ""); // Reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::MenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenu("Add"))
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Empty"))
|
||||||
|
{
|
||||||
|
CreateEmpty(currentScene->GetLayerAt(0));
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
if(ImGui::MenuItem("Layer"))
|
||||||
|
{
|
||||||
|
activatePopUpNamingLayer = true;
|
||||||
|
inputPurpose = LayerCreation;
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::DisplayLayer(Layer *l)
|
||||||
|
{
|
||||||
|
ImGui::Indent(20.0f);
|
||||||
|
bool collapseOpen = ImGui::CollapsingHeader(l->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
|
if(ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
bool disabled = currentScene->GetLayerCount() <= 1;
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Move Up") && !disabled)
|
||||||
|
{
|
||||||
|
MoveUpLayer(l);
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Move Down") && !disabled)
|
||||||
|
{
|
||||||
|
MoveDownLayer(l);
|
||||||
|
}
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Rename"))
|
||||||
|
{
|
||||||
|
strcpy(inputBuffer, l->GetName().c_str());
|
||||||
|
activatePopUpNamingLayer = true;
|
||||||
|
inputPurpose = RenamingLayer;
|
||||||
|
tmpHolder2 = l;
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
AddMenu(nullptr, l);
|
||||||
|
ImGui::Separator();
|
||||||
|
if(ImGui::MenuItem("Delete"))
|
||||||
|
{
|
||||||
|
currentScene->RemoveLayer(l->GetName());
|
||||||
|
//property display remove if present
|
||||||
|
|
||||||
|
//exit early:
|
||||||
|
ImGui::EndPopup();
|
||||||
|
ImGui::Unindent(20.0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
auto payload = ImGui::AcceptDragDropPayload("OBJ_TRANS_PTR");
|
||||||
|
if(payload != nullptr)
|
||||||
|
{
|
||||||
|
auto t2 = *(Transformable**)payload->Data;
|
||||||
|
HandleDropping(l, t2);
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
if(collapseOpen)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < l->GetAllObjects().size(); i++)
|
||||||
|
{
|
||||||
|
DisplayObj(l->GetAllObjects()[i], l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Unindent(20.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::DisplayObj(Transformable *t, Layer *l)
|
||||||
|
{
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth;
|
||||||
|
if(t->GetChildren().size() == 0)
|
||||||
|
{
|
||||||
|
flags |= ImGuiTreeNodeFlags_Leaf;
|
||||||
|
}
|
||||||
|
if(selected == t->id)
|
||||||
|
{
|
||||||
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
|
}
|
||||||
|
bool open = ImGui::TreeNodeEx((t->GetName() + "##" + to_string(t->id)).c_str(), flags);
|
||||||
|
if(ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
bool disabled = false;
|
||||||
|
if(t->GetParent() != nullptr)
|
||||||
|
disabled = t->GetParent()->GetChildren().size() < 1;
|
||||||
|
else
|
||||||
|
disabled = l->GetAllObjects().size() <= 1;
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Move Up") && !disabled)
|
||||||
|
{
|
||||||
|
t->MoveUp(l);
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Move Down") && !disabled)
|
||||||
|
{
|
||||||
|
t->MoveDown(l);
|
||||||
|
}
|
||||||
|
if (disabled)
|
||||||
|
{
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
|
if(ImGui::MenuItem("Rename"))
|
||||||
|
{
|
||||||
|
strcpy(inputBuffer, t->name.c_str());
|
||||||
|
activatePopUpNamingLayer = true;
|
||||||
|
inputPurpose = RenamingTransformable;
|
||||||
|
tmpHolder1 = t;
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
AddMenu(t, nullptr);
|
||||||
|
ImGui::Separator();
|
||||||
|
if(ImGui::MenuItem("Delete"))
|
||||||
|
{
|
||||||
|
t->SetParent(nullptr);
|
||||||
|
int layerCount = currentScene->GetLayerCount();
|
||||||
|
for (int i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
auto layer = currentScene->GetLayerAt(i);
|
||||||
|
if(layer->HasTransformable(t))
|
||||||
|
{
|
||||||
|
layer->RemoveTransformable(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Transformable::HardDelete(t->id);
|
||||||
|
PropertiesView::ForceClearInspectorElement();
|
||||||
|
|
||||||
|
//exit early:
|
||||||
|
ImGui::EndPopup();
|
||||||
|
if(open)
|
||||||
|
{
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginDragDropSource())
|
||||||
|
{
|
||||||
|
auto ptr = &t;
|
||||||
|
ImGui::SetDragDropPayload("OBJ_TRANS_PTR", ptr, sizeof(ptr));
|
||||||
|
std::string name = t->GetName();
|
||||||
|
ImGui::Text((std::string("Move \"") + t->GetName() + "\"").c_str());
|
||||||
|
ImGui::EndDragDropSource();
|
||||||
|
}
|
||||||
|
if(ImGui::BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
auto payload = ImGui::AcceptDragDropPayload("OBJ_TRANS_PTR");
|
||||||
|
if(payload != nullptr)
|
||||||
|
{
|
||||||
|
auto t2 = *(Transformable**)payload->Data;
|
||||||
|
HandleDropping(t, t2);
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
if(ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
|
||||||
|
{
|
||||||
|
selected = t->id;
|
||||||
|
PropertiesView::SetInspectorElement(InspectableType::Transformable, t);
|
||||||
|
}
|
||||||
|
if(open)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < t->GetChildren().size(); i++)
|
||||||
|
{
|
||||||
|
DisplayObj(t->GetChildren()[i], nullptr);
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::HandleDropping(Layer *target, Transformable *payload)
|
||||||
|
{
|
||||||
|
payload->SetParent(nullptr);
|
||||||
|
int layerCount = currentScene->GetLayerCount();
|
||||||
|
for (int i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
auto layer = currentScene->GetLayerAt(i);
|
||||||
|
if(layer == target && layer->HasTransformable(payload)) return;
|
||||||
|
if(layer->HasTransformable(payload))
|
||||||
|
{
|
||||||
|
layer->RemoveTransformable(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target->AddTransformable(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::HandleDropping(Transformable *target, Transformable *payload)
|
||||||
|
{
|
||||||
|
if(target->id == payload->id) return;
|
||||||
|
if(payload->IsMyChild(target)) return;
|
||||||
|
int layerCount = currentScene->GetLayerCount();
|
||||||
|
for (int i = 0; i < layerCount; i++)
|
||||||
|
{
|
||||||
|
auto layer = currentScene->GetLayerAt(i);
|
||||||
|
if(layer->HasTransformable(payload))
|
||||||
|
{
|
||||||
|
layer->RemoveTransformable(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
payload->SetParent(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::AddMenu(Transformable *t, Layer *l)
|
||||||
|
{
|
||||||
|
if(t== nullptr && l == nullptr) //Scene
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Add Layer"))
|
||||||
|
{
|
||||||
|
activatePopUpNamingLayer = true;
|
||||||
|
inputPurpose = LayerCreation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //Layer and Transformable
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Add Empty"))
|
||||||
|
{
|
||||||
|
if(t == nullptr)
|
||||||
|
CreateEmpty(l);
|
||||||
|
else
|
||||||
|
CreateEmpty(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::MoveUpLayer(Layer *t)
|
||||||
|
{
|
||||||
|
if(currentScene->GetLayerAt(0) == t) return;
|
||||||
|
currentScene->MoveLayerUp(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::MoveDownLayer(Layer *t)
|
||||||
|
{
|
||||||
|
int lc = currentScene->GetLayerCount();
|
||||||
|
if(currentScene->GetLayerAt(lc - 1) == t) return;
|
||||||
|
currentScene->MoveLayerDown(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::CreateEmpty(Transformable *parent)
|
||||||
|
{
|
||||||
|
Transformable* t = new Transformable("Unnamed Object");
|
||||||
|
if(parent != nullptr)
|
||||||
|
{
|
||||||
|
t->SetParent(parent);
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // TODO: need to chose a layer to put it in. I would suggest the first one?
|
||||||
|
// currentScene->GetLayerAt(0)->AddTransformable(t);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::CreateEmpty(Layer *parent)
|
||||||
|
{
|
||||||
|
Transformable* t = new Transformable("Unnamed Object");
|
||||||
|
if(parent != nullptr)
|
||||||
|
{
|
||||||
|
parent->AddTransformable(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::HirearchieView::CreateLayer()
|
||||||
|
{
|
||||||
|
Layer* l = new Layer(inputBuffer);
|
||||||
|
currentScene->AddLayer(l);
|
||||||
|
}
|
||||||
47
TSE_Editor/src/UI/windows/HirearchieView.hpp
Normal file
47
TSE_Editor/src/UI/windows/HirearchieView.hpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
#include "elements/Scene.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class HirearchieView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
enum NamingPopUpPorPuse
|
||||||
|
{
|
||||||
|
Nothing = 0,
|
||||||
|
LayerCreation = 1,
|
||||||
|
RenamingLayer = 2,
|
||||||
|
RenamingTransformable = 3,
|
||||||
|
RenamingScene = 4
|
||||||
|
};
|
||||||
|
Scene* currentScene;
|
||||||
|
uuids::uuid selected = uuids::uuid();
|
||||||
|
|
||||||
|
bool openPopUpNamingLayer = false;
|
||||||
|
bool activatePopUpNamingLayer = false;
|
||||||
|
char inputBuffer[128] = "";
|
||||||
|
bool inputConfirmed = false;
|
||||||
|
NamingPopUpPorPuse inputPurpose = Nothing;
|
||||||
|
Transformable* tmpHolder1 = nullptr;
|
||||||
|
Layer* tmpHolder2 = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HirearchieView(Scene* s);
|
||||||
|
void SetScene(Scene* s);
|
||||||
|
void Define() override;
|
||||||
|
void MenuBar();
|
||||||
|
void DisplayLayer(Layer* l);
|
||||||
|
void DisplayObj(Transformable* t, Layer* l);
|
||||||
|
void HandleDropping(Layer* target, Transformable* payload);
|
||||||
|
void HandleDropping(Transformable* target, Transformable* payload);
|
||||||
|
void AddMenu(Transformable* t, Layer* l);
|
||||||
|
void MoveUpLayer(Layer* t);
|
||||||
|
void MoveDownLayer(Layer* t);
|
||||||
|
void CreateEmpty(Transformable* parent);
|
||||||
|
void CreateEmpty(Layer* parent);
|
||||||
|
void CreateLayer();
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
48
TSE_Editor/src/UI/windows/PropertiesView.cpp
Normal file
48
TSE_Editor/src/UI/windows/PropertiesView.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include "PropertiesView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::PropertiesView::PropertiesView() : GuiWindow("Properies", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse) { }
|
||||||
|
|
||||||
|
void TSE::EDITOR::PropertiesView::Define()
|
||||||
|
{
|
||||||
|
MenuBar();
|
||||||
|
if(currentlyInspecting.type == InspectableType::None) return;
|
||||||
|
|
||||||
|
ElementDrawer::Draw(currentlyInspecting, debugMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::PropertiesView::MenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenu("..."))
|
||||||
|
{
|
||||||
|
if(ImGui::MenuItem("Debug"))
|
||||||
|
{
|
||||||
|
debugMode = !debugMode;
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
bool style = locked;
|
||||||
|
if(style) ImGui::PushStyleColor(ImGuiCol_Text, {0,1,0,1});
|
||||||
|
if(ImGui::MenuItem("Lock")) locked = !locked;
|
||||||
|
if(style) ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::PropertiesView::SetInspectorElement(InspectableType type, void *element)
|
||||||
|
{
|
||||||
|
if(!locked)
|
||||||
|
currentlyInspecting = Inspectable(type, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::PropertiesView::ClearInspectorElement()
|
||||||
|
{
|
||||||
|
if(!locked)
|
||||||
|
currentlyInspecting = Inspectable(InspectableType::None, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::PropertiesView::ForceClearInspectorElement()
|
||||||
|
{
|
||||||
|
currentlyInspecting = Inspectable(InspectableType::None, nullptr);
|
||||||
|
}
|
||||||
24
TSE_Editor/src/UI/windows/PropertiesView.hpp
Normal file
24
TSE_Editor/src/UI/windows/PropertiesView.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include "UI/ElementDrawer.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class PropertiesView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
inline static Inspectable currentlyInspecting = {};
|
||||||
|
bool debugMode = false;
|
||||||
|
inline static bool locked = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PropertiesView();
|
||||||
|
|
||||||
|
void Define() override;
|
||||||
|
void MenuBar();
|
||||||
|
static void SetInspectorElement(InspectableType type, void* element);
|
||||||
|
static void ClearInspectorElement();
|
||||||
|
static void ForceClearInspectorElement();
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
21
TSE_Editor/src/UI/windows/SceneView.cpp
Normal file
21
TSE_Editor/src/UI/windows/SceneView.cpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include "SceneView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::SceneView::SceneView(TSE::GLFW::RenderTexture *frameBuffer) : GuiWindow("Scene", ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar)
|
||||||
|
{
|
||||||
|
fb = frameBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSE::EDITOR::SceneView::Define()
|
||||||
|
{
|
||||||
|
ImGuiWindowFlags flags2 = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar;
|
||||||
|
if(ImGui::BeginChild("##SceneChild", {0,0}, ImGuiChildFlags_None, flags2))
|
||||||
|
{
|
||||||
|
ImGui::Image(fb->GetTextureId(), {fb->width(), fb->height()},{0,1}, {1,0});
|
||||||
|
auto vec2 = ImGui::GetWindowSize();
|
||||||
|
if(fb->width() != vec2.x || fb->height() != vec2.y)
|
||||||
|
{
|
||||||
|
fb->SetSize({vec2.x, vec2.y});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
16
TSE_Editor/src/UI/windows/SceneView.hpp
Normal file
16
TSE_Editor/src/UI/windows/SceneView.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "UI/base/GuiWindow.h"
|
||||||
|
#include "RenderTexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class SceneView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
TSE::GLFW::RenderTexture* fb;
|
||||||
|
public:
|
||||||
|
SceneView(TSE::GLFW::RenderTexture* frameBuffer);
|
||||||
|
void Define() override;
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
@@ -14,12 +14,16 @@ TSE::GLFW::FrameBuffer::FrameBuffer(const Vector2 &size)
|
|||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::Bind()
|
void TSE::GLFW::FrameBuffer::Bind()
|
||||||
{
|
{
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRboID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, bufferID);
|
glBindFramebuffer(GL_FRAMEBUFFER, bufferID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::Unbind()
|
void TSE::GLFW::FrameBuffer::Unbind()
|
||||||
{
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSE::GLFW::FrameBuffer::~FrameBuffer()
|
TSE::GLFW::FrameBuffer::~FrameBuffer()
|
||||||
@@ -69,6 +73,8 @@ void TSE::GLFW::FrameBuffer::Initialize()
|
|||||||
TSE_LOG(std::to_string(glGetError()));
|
TSE_LOG(std::to_string(glGetError()));
|
||||||
}
|
}
|
||||||
Unbind();
|
Unbind();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::LoadFBTexture()
|
void TSE::GLFW::FrameBuffer::LoadFBTexture()
|
||||||
|
|||||||
Reference in New Issue
Block a user