Making UIEngine editor

This commit is contained in:
Arnau Alier Torres 2025-04-29 22:18:15 +02:00
parent af877c42ed
commit a0e49a2690
21 changed files with 208 additions and 47 deletions

View File

@ -7,13 +7,15 @@
#define DEER_SCENE_PATH "scenes"
#define DEER_SCRIPT_PATH "scripts"
#define DEER_UI_SCRIPT_PATH "ui_scripts"
#define DEER_SHADER_PATH "shaders"
#define DEER_VOXEL_PATH "voxels"
#define DEER_VOXEL_DATA_PATH "voxels/data"
#define DEER_VOXEL_ASPECT_PATH "voxels/aspect"
#define DEER_VOXEL_TEXTURE_PATH "voxels/textures"
#define DEER_VOXEL_SHADER_PATH "voxels/shaders"
#define DEER_DOCK_PANEL_PATH "editor"
#define DEER_UI_SCRIPT_PATH DEER_DOCK_PANEL_PATH
#define DEER_UI_ICON_PATH DEER_DOCK_PANEL_PATH
#define DEER_MESH_PATH "meshes"
#define DEER_BIN_PATH "bin"
@ -22,7 +24,7 @@
namespace Deer {
struct DirectoryData {
std::vector<Path> subDirs;
std::vector<Path> dirs;
std::vector<Path> elements;
};
@ -32,7 +34,14 @@ namespace Deer {
void clearCache();
// Rerturns a directory data with the elements relative to the id
const DirectoryData& getDirData(const Path& id, const Path& subDir, const char* extension);
const DirectoryData& getDirData(const Path& id, const Path& dir, const char* extension);
// TODO: Add safety
// Returns the data of the specified file path
bool loadFileData(const Path& id, const Path& name,uint8_t** data, uint32_t* size);
// Returns the data of the specified file path avoiding extension
bool loadGlobalFileData(const Path& id, const Path& name,uint8_t** data, uint32_t* size);
void freeFileData(uint8_t*);
void createFolder(const Path& path);

View File

@ -1,4 +1,5 @@
#pragma once
#include <string>
namespace Deer {
// This namespace implements all interface ported from c++ ImGui to an easier lua aproach with simplifications
@ -7,5 +8,10 @@ namespace Deer {
void deinitialize();
void execute();
}
namespace DataStore {
int getIconId(const std::string& name);
}
}

View File

@ -38,7 +38,7 @@ namespace Deer {
DirectoryData& dirData = dirData_cache[dirId];
for (const auto& entry : std::filesystem::directory_iterator(searchPath)) {
if (entry.is_directory())
dirData.subDirs.push_back(entry.path().lexically_relative(idPath));
dirData.dirs.push_back(entry.path().lexically_relative(idPath));
else if (entry.path().extension() == extension)
dirData.elements.push_back(entry.path().lexically_relative(idPath));
}
@ -46,6 +46,67 @@ namespace Deer {
return dirData;
}
bool DataStore::loadFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size) {
Path filePath = rootPath / id / name;
std::ifstream file(filePath, std::ios::in | std::ios::binary);
if (!file) {
file.close();
return false;
}
file.seekg(0, std::ios::end);
*size = (size_t)file.tellg();
file.seekg(0, std::ios::beg);
*data = new uint8_t[*size];
if (!file.read(reinterpret_cast<char*>(*data), *size)) {
DEER_CORE_ERROR("Failed to read file: {0}", filePath.generic_string().c_str());
delete[] *data;
return false;
}
file.close();
return true;
}
bool DataStore::loadGlobalFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size) {
Path filePath = rootPath / id;
for (auto& f : std::filesystem::recursive_directory_iterator(filePath)) {
if (f.path().stem() == name) {
std::ifstream file(f.path(), std::ios::in | std::ios::binary);
if (!file) {
file.close();
return false;
}
file.seekg(0, std::ios::end);
*size = (size_t)file.tellg();
file.seekg(0, std::ios::beg);
*data = new uint8_t[*size];
if (!file.read(reinterpret_cast<char*>(*data), *size)) {
DEER_CORE_ERROR("Failed to read file: {0}", filePath.generic_string().c_str());
delete[] *data;
return false;
}
file.close();
return true;
}
}
DEER_CORE_ERROR("File {0} not found", filePath.string().c_str());
return false;
}
void DataStore::freeFileData(uint8_t* data) {
delete[] data;
}
void DataStore::deleteFile(const Path& path) {
Path filePath = rootPath / toLowerCasePath(path);
std::filesystem::remove(filePath);

View File

@ -1,6 +1,6 @@
#include "DeerRender/UIEngine/DockPanelObject.h"
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
#include "angelscript.h"
#include <string>

View File

@ -0,0 +1,9 @@
#pragma once
#include <string>
namespace Deer {
namespace UIEngine {
// TO IMPLEMENT
bool button(std::string&);
}
}

View File

@ -0,0 +1,12 @@
#pragma once
namespace Deer {
namespace UIEngine {
// Set up the colums to fit the pixelSize elements
void setupAutomaticColumns(int pixelSize);
// Iterates to the next column
void nextColumn();
// Ends the columns made with setupColumns
void endColumns();
}
}

View File

@ -0,0 +1,11 @@
#pragma once
namespace Deer {
namespace UIEngine {
// Returns if the specified mouse button is clicked on the last element
bool isMouseClicked(int mouse);
// Returns if the specified mouse button is double clicked
bool isMouseDoubleClicked(int mouse);
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <string>
namespace Deer {
namespace UIEngine {
// Renders a text with the defined rgb values from range [0.0, 1.0]
void textColor(float r, float g, float b, std::string& msg);
// Renders a text
void text(std::string& msg);
}
}

View File

@ -1,6 +1,6 @@
#include "DeerRender/UIEngine.h"
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngineFunctions.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_Functions.h"
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine/DockPanelObject.h"

View File

@ -1,4 +1,4 @@
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
#include "angelscript.h"

View File

@ -1,5 +1,6 @@
#include "DeerRender/UIEngine/UIEngineFunctions.h"
#include "DeerRender/UIEngine/UIEngine_Functions.h"
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine.h"
#include "DeerRender/UIEngine/DockPanelObject.h"
#include "Deer/Log.h"
#include "Deer/DataStore.h"
@ -15,7 +16,7 @@ namespace Deer {
std::string getMeshPath(std::string& dir, int i) {
const DirectoryData& dirData = DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh");
if (i < 0 || i >= dirData.elements.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshPath(..), mas size {1}", i, dirData.subDirs.size());
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshPath(..), mas size {1}", i, dirData.dirs.size());
if (currentDockPanelExecution) {
currentDockPanelExecution->invalidate();
}
@ -26,7 +27,7 @@ namespace Deer {
std::string getMeshName(std::string& dir, int i) {
const DirectoryData& dirData = DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh");
if (i < 0 || i >= dirData.elements.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshName(..), mas size {1}", i, dirData.subDirs.size());
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshName(..), mas size {1}", i, dirData.dirs.size());
if (currentDockPanelExecution) {
currentDockPanelExecution->invalidate();
}
@ -36,40 +37,52 @@ namespace Deer {
}
int getMeshDirCount(std::string& dir) {
return DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh").subDirs.size();
return DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh").dirs.size();
}
std::string getMeshDirPath(std::string& dir, int i) {
const DirectoryData& dirData = DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh");
if (i < 0 || i >= dirData.subDirs.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshDirPath(..), mas size {1}", i, dirData.subDirs.size());
if (i < 0 || i >= dirData.dirs.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshDirPath(..), mas size {1}", i, dirData.dirs.size());
if (currentDockPanelExecution) {
currentDockPanelExecution->invalidate();
}
return "";
}
return dirData.subDirs[i].string();
return dirData.dirs[i].string();
}
std::string getMeshDirName(std::string& dir, int i) {
const DirectoryData& dirData = DataStore::getDirData(DEER_MESH_PATH, dir, ".dmesh");
if (i < 0 || i >= dirData.subDirs.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshDirName(..), mas size {1}", i, dirData.subDirs.size());
if (i < 0 || i >= dirData.dirs.size()){
DEER_UI_ENGINE_ERROR("Invalid id {0} calling getMeshDirName(..), mas size {1}", i, dirData.dirs.size());
if (currentDockPanelExecution) {
currentDockPanelExecution->invalidate();
}
return "";
}
return dirData.subDirs[i].filename().string();
return dirData.dirs[i].filename().string();
}
void coloredText(float r, float g, float b, std::string& msg) {
void textColor(float r, float g, float b, std::string& msg) {
ImGui::TextColored(ImVec4(r, g, b, 1.0f), "%s", msg.c_str());
}
void text(std::string& msg) {
ImGui::Text("%s", msg.c_str());
}
void drawIcon(std::string& , int size) {
// TODO
void drawIcon(std::string& name, int size) {
int iconId = DataStore::getIconId(name);
if (iconId < 0) {
DEER_UI_ENGINE_ERROR("Invalid icon name {0}", name.c_str());
if (currentDockPanelExecution) {
currentDockPanelExecution->invalidate();
}
return;
}
ImGui::Image((void*)(uint64_t)iconId,
ImVec2(size, size), ImVec2(0, 1),
ImVec2(1, 0));
}
// Interaction

View File

@ -1,12 +1,14 @@
#pragma once
#include <string>
#include "DeerRender/UIEngine/Functions/UIEngine_TextFunctions.h"
#include "DeerRender/UIEngine/Functions/UIEngine_ColumnFunctions.h"
#include "DeerRender/UIEngine/Functions/UIEngine_ButtonFunctions.h"
#include "DeerRender/UIEngine/Functions/UIEngine_ButtonFunctions.h"
class asSMessageInfo;
namespace Deer {
namespace UIEngine {
// TODO: Detect if it has menu bar
// TODO: Make icon an enum
// --- Mesh Data Store ---
// Returns the count of meshes in the dir relative to the mesh root dir
@ -26,26 +28,11 @@ namespace Deer {
// --- RENDERING ---
// TEXT
// Renders a text with the defined rgb values from range [0.0, 1.0]
void coloredText(float r, float g, float b, std::string& msg);
// Renders a text
void text(std::string& msg);
// Images
// TODO: Implement
void drawIcon(std::string& iconId, int size);
// Returns if the specified mouse button is clicked
bool isMouseClicked(int mouse);
// Returns if the specified mouse button is double clicked
bool isMouseDoubleClicked(int mouse);
// Set up the colums to fit the pixelSize elements
void setupAutomaticColumns(int pixelSize);
// Iterates to the next column
void nextColumn();
// Ends the columns made with setupColumns
void endColumns();
void errorCallback(const asSMessageInfo *msg, void *param);
// Prints in console a mesage

View File

@ -0,0 +1,28 @@
#include "DeerRender/UIEngine.h"
#include "DeerRender/Render/Texture.h"
#include "Deer/DataStore.h"
#include <unordered_map>
namespace Deer {
namespace DataStore {
std::unordered_map<std::string, Ref<Texture2D>> icons;
}
int DataStore::getIconId(const std::string& name) {
if (icons.contains(name))
return icons[name]->getTextureID();
uint8_t* data;
uint32_t size;
if (!DataStore::loadGlobalFileData(DEER_UI_ICON_PATH, name, &data, &size))
return -1;
icons[name] = Texture2D::create(data, size);
DataStore::freeFileData(data);
return icons[name]->getTextureID();
}
}

View File

@ -1,7 +1,7 @@
#include "angelscript.h"
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine/DockPanelObject.h"
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
namespace Deer {
void UIEngine::registerDockPanel() {

View File

@ -1,5 +1,5 @@
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
#include "Deer/Path.h"
#include "Deer/DataStore.h"

View File

@ -1,13 +1,13 @@
#include "DeerRender/UIEngine/UIEngineFunctions.h"
#include "DeerRender/UIEngine/UIEngine_Functions.h"
#include "DeerRender/UIEngine/UIEngine.h"
#include "DeerRender/UIEngine/ErrorHandle.h"
#include "DeerRender/UIEngine/UIEngine_ErrorHandle.h"
namespace Deer {
void UIEngine::registerUIEngineFunctions() {
AS_CHECK(scriptEngine->RegisterGlobalFunction(
"void coloredText(float, float, float, const string& in)",
"void textColor(float, float, float, const string& in)",
asFUNCTION(
Deer::UIEngine::coloredText
Deer::UIEngine::textColor
),
asCALL_CDECL
));
@ -20,6 +20,14 @@ namespace Deer {
asCALL_CDECL
));
AS_CHECK(scriptEngine->RegisterGlobalFunction(
"void drawIcon(const string& in, int)",
asFUNCTION(
Deer::UIEngine::drawIcon
),
asCALL_CDECL
));
AS_CHECK(scriptEngine->RegisterGlobalFunction(
"bool isMouseClicked(int)",
asFUNCTION(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 266 B

View File

@ -3,12 +3,14 @@ class MeshExplorer : DockPanel {
string currentPath = "";
void onRender() {
coloredText(0.5, 0.5, 0.5, currentPath);
textColor(0.5, 0.5, 0.5, currentPath);
setupAutomaticColumns(180);
int dirCount = getMeshDirCount(currentPath);
for (int i = 0; i < dirCount; i++) {
drawIcon("folder", 64);
text(getMeshDirName(currentPath, i));
nextColumn();
@ -16,6 +18,7 @@ class MeshExplorer : DockPanel {
int meshCount = getMeshCount(currentPath);
for (int i = 0; i < meshCount; i++) {
drawIcon("file", 64);
text(getMeshName(currentPath, i));
nextColumn();

View File

@ -73,5 +73,5 @@ DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=Y
DockNode ID=0x00000009 Parent=0x00000004 SizeRef=392,214 Selected=0x199AB496
DockNode ID=0x0000000A Parent=0x00000004 SizeRef=392,152 Selected=0x2A2C795E
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=2560,331 Selected=0xCF339702
DockNode ID=0x00000008 Parent=0xA1672E74 SizeRef=1280,326 Selected=0x7F7E0F9C
DockNode ID=0x00000008 Parent=0xA1672E74 SizeRef=1280,326 Selected=0xD962995A