Compare commits
5 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| 5fdcb6989f | |||
| a453612b9a | |||
| 23e7707122 | |||
| b73d09f09f | |||
| dc5b58d7d3 |
@@ -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
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace TSE
|
|||||||
{
|
{
|
||||||
#define TSE_VERSION_MAJOR 0
|
#define TSE_VERSION_MAJOR 0
|
||||||
#define TSE_VERSION_MINOR 1
|
#define TSE_VERSION_MINOR 1
|
||||||
#define TSE_VERSION_BUILD 0
|
#define TSE_VERSION_BUILD 1
|
||||||
|
|
||||||
#define TSE_VERSION_STRING std::to_string(TSE_VERSION_MAJOR) + "." + std::to_string(TSE_VERSION_MINOR) + "." + std::to_string(TSE_VERSION_BUILD)
|
#define TSE_VERSION_STRING std::to_string(TSE_VERSION_MAJOR) + "." + std::to_string(TSE_VERSION_MINOR) + "." + std::to_string(TSE_VERSION_BUILD)
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -118,12 +118,12 @@ TSE::Vector2 TSE::Texture::size() const
|
|||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TSE::Texture::width() const
|
float TSE::Texture::Width() const
|
||||||
{
|
{
|
||||||
return Size.x;
|
return Size.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TSE::Texture::height() const
|
float TSE::Texture::Height() const
|
||||||
{
|
{
|
||||||
return Size.y;
|
return Size.y;
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ void TSE::Texture::SetChanels(const byte &ch)
|
|||||||
chanels = ch;
|
chanels = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint TSE::Texture::GetTextureId() const
|
TSE::uint TSE::Texture::GetTextureId() const
|
||||||
{
|
{
|
||||||
return TextureID;
|
return TextureID;
|
||||||
}
|
}
|
||||||
@@ -181,9 +181,9 @@ void TSE::Texture::SetPixel(const int &x, const int &y, const Color &c)
|
|||||||
|
|
||||||
void TSE::Texture::GetPixel(const int &x, const int &y, Color &c) const
|
void TSE::Texture::GetPixel(const int &x, const int &y, Color &c) const
|
||||||
{
|
{
|
||||||
if(x >= width() || x < 0 ||y >= height() || y < 0)
|
if(x >= Width() || x < 0 ||y >= Height() || y < 0)
|
||||||
{
|
{
|
||||||
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(width()) + ";" + std::to_string(height()) );
|
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
byte* pixel = getPixelPointer(x,y);
|
byte* pixel = getPixelPointer(x,y);
|
||||||
@@ -201,9 +201,9 @@ void TSE::Texture::GetPixel(const int &x, const int &y, Color &c) const
|
|||||||
|
|
||||||
void TSE::Texture::Fill(const Color &c)
|
void TSE::Texture::Fill(const Color &c)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width(); x++)
|
for (int x = 0; x < Width(); x++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < height(); y++)
|
for (int y = 0; y < Height(); y++)
|
||||||
{
|
{
|
||||||
SetPixelNoApply(x,y,c);
|
SetPixelNoApply(x,y,c);
|
||||||
}
|
}
|
||||||
@@ -214,9 +214,9 @@ void TSE::Texture::Fill(const Color &c)
|
|||||||
|
|
||||||
void TSE::Texture::SetPixelNoApply(const int &x, const int &y, const Color &c)
|
void TSE::Texture::SetPixelNoApply(const int &x, const int &y, const Color &c)
|
||||||
{
|
{
|
||||||
if(x >= width() || x < 0 ||y >= height() || y < 0)
|
if(x >= Width() || x < 0 ||y >= Height() || y < 0)
|
||||||
{
|
{
|
||||||
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(width()) + ";" + std::to_string(height()) );
|
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,9 +244,9 @@ void TSE::Texture::SetPixelNoApply(const int &x, const int &y, const Color &c)
|
|||||||
|
|
||||||
void TSE::Texture::AddPixelNoApply(const int &x, const int &y, const Color &c)
|
void TSE::Texture::AddPixelNoApply(const int &x, const int &y, const Color &c)
|
||||||
{
|
{
|
||||||
if(x >= width() || x < 0 ||y >= height() || y < 0)
|
if(x >= Width() || x < 0 ||y >= Height() || y < 0)
|
||||||
{
|
{
|
||||||
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(width()) + ";" + std::to_string(height()) );
|
TSE_WARNING("trying to access pixel outside of texture.\n pixel: (" + std::to_string(x) + ";" + std::to_string(y) + ")\nTexture size: (" + std::to_string(Width()) + ";" + std::to_string(Height()) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ TSE::byte *TSE::Texture::getPixelPointer(const int &x, const int &y) const
|
|||||||
int alphaoffset = y * 2;
|
int alphaoffset = y * 2;
|
||||||
if(bpp() > 24)
|
if(bpp() > 24)
|
||||||
alphaoffset = 0;
|
alphaoffset = 0;
|
||||||
int offset = ((y * width() + x) * (bpp() / 8) + alphaoffset);
|
int offset = ((y * Width() + x) * (bpp() / 8) + alphaoffset);
|
||||||
return imagePtr + offset;
|
return imagePtr + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ namespace TSE
|
|||||||
|
|
||||||
uint bpp() const;
|
uint bpp() const;
|
||||||
Vector2 size() const override;
|
Vector2 size() const override;
|
||||||
float width() const override;
|
float Width() const override;
|
||||||
float height() const override;
|
float Height() const override;
|
||||||
byte Chanels() const;
|
byte Chanels() const;
|
||||||
byte* GetImagePtr() const;
|
byte* GetImagePtr() const;
|
||||||
void SetPixel(const Vector2& pos, const Color& c);
|
void SetPixel(const Vector2& pos, const Color& c);
|
||||||
|
|||||||
23
TSE_Core/src/interfaces/IRenderTexture.hpp
Normal file
23
TSE_Core/src/interfaces/IRenderTexture.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IResizeNotifiable.hpp"
|
||||||
|
#include "IRenderTarget.hpp"
|
||||||
|
#include "ITexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE
|
||||||
|
{
|
||||||
|
class IRenderTextureCreator;
|
||||||
|
|
||||||
|
class IRenderTexture : public IRenderTarget, public ITexture, public IResizeNotifiable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline static IRenderTextureCreator* factory = nullptr;
|
||||||
|
virtual void SetSize(Vector2 v) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRenderTextureCreator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IRenderTexture* CreateTextureHeap(Vector2 v) = 0;
|
||||||
|
};
|
||||||
|
} // namespace TSE
|
||||||
@@ -9,8 +9,8 @@ namespace TSE
|
|||||||
public:
|
public:
|
||||||
virtual ~ITexture() = default;
|
virtual ~ITexture() = default;
|
||||||
virtual Vector2 size() const = 0;
|
virtual Vector2 size() const = 0;
|
||||||
virtual float width() const = 0;
|
virtual float Width() const = 0;
|
||||||
virtual float height() const = 0;
|
virtual float Height() const = 0;
|
||||||
virtual uint GetTextureId() const = 0;
|
virtual uint GetTextureId() const = 0;
|
||||||
};
|
};
|
||||||
} // namespace TSE
|
} // namespace TSE
|
||||||
|
|||||||
59
TSE_Editor/CMakeLists.txt
Normal file
59
TSE_Editor/CMakeLists.txt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#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)
|
||||||
|
|
||||||
|
#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), editorLayer("")
|
||||||
|
{
|
||||||
|
rt = IRenderTexture::factory->CreateTextureHeap({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 "interfaces/IRenderTexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class EditorSubsystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewportController controller;
|
||||||
|
ConsolView cv;
|
||||||
|
DebugView dv;
|
||||||
|
HirearchieView hv = HirearchieView(nullptr);
|
||||||
|
PropertiesView pv;
|
||||||
|
CameraView camv;
|
||||||
|
TSE::IRenderTexture* 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"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
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
|
||||||
30
TSE_Editor/src/UI/windows/CameraView.cpp
Normal file
30
TSE_Editor/src/UI/windows/CameraView.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "CameraView.hpp"
|
||||||
|
|
||||||
|
TSE::EDITOR::CameraView::CameraView() : GuiWindow("Camera", ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar)
|
||||||
|
{
|
||||||
|
fb = IRenderTexture::factory->CreateTextureHeap({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))
|
||||||
|
{
|
||||||
|
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 "interfaces/IRenderTexture.hpp"
|
||||||
|
#include "BehaviourScripts/Camera.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class CameraView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Camera* currentCamera = nullptr;
|
||||||
|
TSE::IRenderTexture* 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::IRenderTexture *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 "interfaces/IRenderTexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE::EDITOR
|
||||||
|
{
|
||||||
|
class SceneView : public GuiWindow
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
TSE::IRenderTexture* fb;
|
||||||
|
public:
|
||||||
|
SceneView(TSE::IRenderTexture* frameBuffer);
|
||||||
|
void Define() override;
|
||||||
|
};
|
||||||
|
} // namespace TSE::EDITOR
|
||||||
@@ -10,6 +10,9 @@
|
|||||||
#include "PathHelper.hpp"
|
#include "PathHelper.hpp"
|
||||||
#include "elements/Texture.hpp"
|
#include "elements/Texture.hpp"
|
||||||
#include "TextureHelperOpenGL.hpp"
|
#include "TextureHelperOpenGL.hpp"
|
||||||
|
#include "interfaces/IRenderer.hpp"
|
||||||
|
#include "BehaviourScripts/Camera.hpp"
|
||||||
|
#include "RenderTextureCreatorOpenGL.hpp"
|
||||||
|
|
||||||
TSE::GLFW::OpenGLRenderingBackend::OpenGLRenderingBackend(Color _backgroundColor, bool _vsync)
|
TSE::GLFW::OpenGLRenderingBackend::OpenGLRenderingBackend(Color _backgroundColor, bool _vsync)
|
||||||
: OpenGLRenderingBackend(_backgroundColor, _vsync, 0, false){ }
|
: OpenGLRenderingBackend(_backgroundColor, _vsync, 0, false){ }
|
||||||
@@ -34,6 +37,7 @@ TSE::GLFW::OpenGLRenderingBackend::~OpenGLRenderingBackend()
|
|||||||
|
|
||||||
void TSE::GLFW::OpenGLRenderingBackend::InitPreWindow()
|
void TSE::GLFW::OpenGLRenderingBackend::InitPreWindow()
|
||||||
{
|
{
|
||||||
|
IRenderTexture::factory = new RenderTextureCreatorOpenGL();
|
||||||
Texture::helper = new TextureHelperOpenGL();
|
Texture::helper = new TextureHelperOpenGL();
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, TSE_OPENGL_VERSION_MAJOR);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, TSE_OPENGL_VERSION_MAJOR);
|
||||||
@@ -140,7 +144,13 @@ void TSE::GLFW::OpenGLRenderingBackend::onUpdate() const
|
|||||||
|
|
||||||
void TSE::GLFW::OpenGLRenderingBackend::onClear() const
|
void TSE::GLFW::OpenGLRenderingBackend::onClear() const
|
||||||
{
|
{
|
||||||
//cameras
|
for (int i = 0; i < IRenderer::camerasToRenderWith.size(); i++)
|
||||||
|
{
|
||||||
|
IRenderer::camerasToRenderWith[i]->Bind();
|
||||||
|
IRenderer::camerasToRenderWith[i]->UpdateRenderTarget();
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
IRenderer::camerasToRenderWith[i]->Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
if(useseImGui)
|
if(useseImGui)
|
||||||
@@ -153,7 +163,12 @@ void TSE::GLFW::OpenGLRenderingBackend::onClear() const
|
|||||||
|
|
||||||
void TSE::GLFW::OpenGLRenderingBackend::onClearDepthBuffer() const
|
void TSE::GLFW::OpenGLRenderingBackend::onClearDepthBuffer() const
|
||||||
{
|
{
|
||||||
//cameras
|
for (int i = 0; i < IRenderer::camerasToRenderWith.size(); i++)
|
||||||
|
{
|
||||||
|
IRenderer::camerasToRenderWith[i]->Bind();
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
IRenderer::camerasToRenderWith[i]->Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,17 @@ void TSE::GLFW::RenderTexture::SetSize(Vector2 v)
|
|||||||
buffer.Resize(v);
|
buffer.Resize(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
float TSE::GLFW::RenderTexture::width() const
|
float TSE::GLFW::RenderTexture::Width() const
|
||||||
{
|
{
|
||||||
return buffer.GetSize().x;
|
return buffer.GetSize().x;
|
||||||
}
|
}
|
||||||
|
|
||||||
float TSE::GLFW::RenderTexture::height() const
|
float TSE::GLFW::RenderTexture::Height() const
|
||||||
{
|
{
|
||||||
return buffer.GetSize().y;
|
return buffer.GetSize().y;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint TSE::GLFW::RenderTexture::GetTextureId() const
|
TSE::uint TSE::GLFW::RenderTexture::GetTextureId() const
|
||||||
{
|
{
|
||||||
return buffer.GetTextureId();
|
return buffer.GetTextureId();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
#include "interfaces/IRenderTarget.hpp"
|
#include "interfaces/IRenderTarget.hpp"
|
||||||
#include "interfaces/ITexture.hpp"
|
#include "interfaces/ITexture.hpp"
|
||||||
#include "interfaces/IResizeNotifiable.hpp"
|
#include "interfaces/IResizeNotifiable.hpp"
|
||||||
|
#include "interfaces/IRenderTexture.hpp"
|
||||||
|
|
||||||
namespace TSE::GLFW
|
namespace TSE::GLFW
|
||||||
{
|
{
|
||||||
class RenderTexture : public IRenderTarget, public ITexture, public IResizeNotifiable
|
class RenderTexture : public IRenderTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FrameBuffer buffer;
|
FrameBuffer buffer;
|
||||||
@@ -15,9 +16,9 @@ namespace TSE::GLFW
|
|||||||
RenderTexture(Vector2 v);
|
RenderTexture(Vector2 v);
|
||||||
|
|
||||||
Vector2 size() const override;
|
Vector2 size() const override;
|
||||||
void SetSize(Vector2 v);
|
void SetSize(Vector2 v) override;
|
||||||
float width() const override;
|
float Width() const override;
|
||||||
float height() const override;
|
float Height() const override;
|
||||||
uint GetTextureId() const override;
|
uint GetTextureId() const override;
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|||||||
16
TSE_GlfwOpenGlImpl/src/RenderTextureCreatorOpenGL.hpp
Normal file
16
TSE_GlfwOpenGlImpl/src/RenderTextureCreatorOpenGL.hpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "interfaces/IRenderTexture.hpp"
|
||||||
|
#include "RenderTexture.hpp"
|
||||||
|
|
||||||
|
namespace TSE::GLFW
|
||||||
|
{
|
||||||
|
class RenderTextureCreatorOpenGL : public IRenderTextureCreator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline IRenderTexture* CreateTextureHeap(Vector2 v) override
|
||||||
|
{
|
||||||
|
return new RenderTexture(v);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace name
|
||||||
@@ -18,19 +18,19 @@ void TSE::GLFW::TextureHelperOpenGL::Apply(Texture *tex)
|
|||||||
if(tex->Chanels() == 1)
|
if(tex->Chanels() == 1)
|
||||||
{
|
{
|
||||||
if (tex->bpp() == 8)
|
if (tex->bpp() == 8)
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->width(), tex->height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
||||||
}
|
}
|
||||||
if(tex->Chanels() == 3)
|
if(tex->Chanels() == 3)
|
||||||
{
|
{
|
||||||
if(tex->bpp() == 24)
|
if(tex->bpp() == 24)
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->width(), tex->height(), 0, GL_BGR, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_BGR, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
||||||
}
|
}
|
||||||
else if(tex->Chanels() == 4)
|
else if(tex->Chanels() == 4)
|
||||||
{
|
{
|
||||||
if(tex->bpp() == 32)
|
if(tex->bpp() == 32)
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->width(), tex->height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
||||||
if (tex->bpp() == 8) //need to decode it with bitwise operations in shader
|
if (tex->bpp() == 8) //need to decode it with bitwise operations in shader
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->width(), tex->height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, tex->Width(), tex->Height(), 0, GL_RED, GL_UNSIGNED_BYTE, tex->GetImagePtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
TSE::GLFW::FrameBuffer::FrameBuffer(const Vector2 &size)
|
TSE::GLFW::FrameBuffer::FrameBuffer(const Vector2 &size)
|
||||||
{
|
{
|
||||||
this->size = size;
|
width = size.x;
|
||||||
|
height = size.y;
|
||||||
CreateFBTexture();
|
CreateFBTexture();
|
||||||
for (auto const& i : objectsToResize)
|
for (auto const& i : objectsToResize)
|
||||||
{
|
{
|
||||||
@@ -31,7 +32,8 @@ TSE::GLFW::FrameBuffer::~FrameBuffer()
|
|||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::Resize(Vector2 size)
|
void TSE::GLFW::FrameBuffer::Resize(Vector2 size)
|
||||||
{
|
{
|
||||||
this->size = size;
|
width = size.x;
|
||||||
|
height = size.y;
|
||||||
shouldResize = true;
|
shouldResize = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ void TSE::GLFW::FrameBuffer::Update()
|
|||||||
CreateFBTexture();
|
CreateFBTexture();
|
||||||
for (auto const& i : objectsToResize)
|
for (auto const& i : objectsToResize)
|
||||||
{
|
{
|
||||||
i->OnResize(size.x, size.y, this);
|
i->OnResize(width, height, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ TSE::uint TSE::GLFW::FrameBuffer::GetTextureId() const
|
|||||||
|
|
||||||
TSE::Vector2 TSE::GLFW::FrameBuffer::GetSize() const
|
TSE::Vector2 TSE::GLFW::FrameBuffer::GetSize() const
|
||||||
{
|
{
|
||||||
return size;
|
return {width, height};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::Initialize()
|
void TSE::GLFW::FrameBuffer::Initialize()
|
||||||
@@ -74,7 +76,7 @@ void TSE::GLFW::FrameBuffer::Initialize()
|
|||||||
void TSE::GLFW::FrameBuffer::LoadFBTexture()
|
void TSE::GLFW::FrameBuffer::LoadFBTexture()
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
@@ -82,12 +84,12 @@ void TSE::GLFW::FrameBuffer::LoadFBTexture()
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, depthRboID);
|
glBindRenderbuffer(GL_RENDERBUFFER, depthRboID);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size.x, size.y);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TSE::GLFW::FrameBuffer::CreateFBTexture()
|
void TSE::GLFW::FrameBuffer::CreateFBTexture()
|
||||||
{
|
{
|
||||||
glViewport(0,0, size.x, size.y);
|
glViewport(0,0, width, height);
|
||||||
//resize
|
//resize
|
||||||
if(textureID == 0)
|
if(textureID == 0)
|
||||||
glGenTextures(1, &textureID);
|
glGenTextures(1, &textureID);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ namespace TSE::GLFW
|
|||||||
private:
|
private:
|
||||||
uint textureID = 0;
|
uint textureID = 0;
|
||||||
uint depthRboID = 0;
|
uint depthRboID = 0;
|
||||||
Vector2 size;
|
|
||||||
bool shouldResize = false;
|
bool shouldResize = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#define SHADER_PACKAGE_SIZE (sizeof(float) * (3 + 4 + 2 + 1))
|
#define SHADER_PACKAGE_SIZE (sizeof(float) * (3 + 4 + 2 + 1))
|
||||||
|
|
||||||
TSE::GLFW::BasicTextureShader* TSE::GLFW::BasicTextureShader::instance = nullptr;
|
TSE::GLFW::BasicTextureShader* TSE::GLFW::BasicTextureShader::instance = nullptr;
|
||||||
std::map<uint, float> TSE::GLFW::BasicTextureShader::textureSlots;
|
std::map<TSE::uint, float> TSE::GLFW::BasicTextureShader::textureSlots;
|
||||||
|
|
||||||
TSE::GLFW::BasicTextureShader *TSE::GLFW::BasicTextureShader::Instance()
|
TSE::GLFW::BasicTextureShader *TSE::GLFW::BasicTextureShader::Instance()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user