From 9c5992db4ab66d8953db309071629c00882eefcb Mon Sep 17 00:00:00 2001 From: Chewico Date: Wed, 11 Mar 2026 23:04:28 +0100 Subject: [PATCH] Working now --- Deer/Include/DeerCore/Scripting/Helpers.h | 68 +++++ Deer/Include/DeerRender/Resource.h | 10 +- .../DeerRender/Core/ResourceIdGenerator.cpp | 4 +- .../Scripting/InternalAPI/Resources.cpp | 2 +- .../Scripting/InternalAPI/Resources.h | 2 + .../Scripting/ResourcesRegistry.cpp | 7 +- .../Components/MeshComponentSerialization.h | 4 +- Deer/src/DeerRender/Voxel/VoxelBuilder.cpp | 2 +- DeerStudio/headers/DeerStudio/StudioAPI.h | 1 + .../headers/DeerStudio/StudioResources.h | 7 +- .../EditorDataImporter/TextureData.cpp | 34 +++ DeerStudio/src/DeerStudio/StudioAPI.cpp | 18 +- DeerStudio/src/DeerStudio/StudioResources.cpp | 42 +++- DeerStudio/src/DeerStudio/StudioScripting.cpp | 28 ++- Editor/Scripts/Previewer/Previewer.as | 4 +- Editor/Scripts/Properties/MeshProperties.as | 6 +- .../ResourceExplorer/ResourceExplorer.as | 211 ++-------------- .../ResourceExplorer.as.disabled | 233 ++++++++++++++++++ Editor/Scripts/Viewport/Viewport.as | 2 +- imgui.ini | 8 +- 20 files changed, 472 insertions(+), 221 deletions(-) create mode 100644 Deer/Include/DeerCore/Scripting/Helpers.h create mode 100644 Editor/Scripts/ResourceExplorer/ResourceExplorer.as.disabled diff --git a/Deer/Include/DeerCore/Scripting/Helpers.h b/Deer/Include/DeerCore/Scripting/Helpers.h new file mode 100644 index 0000000..b9249c4 --- /dev/null +++ b/Deer/Include/DeerCore/Scripting/Helpers.h @@ -0,0 +1,68 @@ +#pragma once +#include "DeerRender/Log.h" +#include "angelscript.h" + +namespace Deer { + namespace Scripting { + const char* getAngelScriptReturnCodeString(int code); + bool ImplementsInterface(asITypeInfo* type, asITypeInfo* iface); + } // namespace Scripting +} // namespace Deer + +#define REGISTER_GLOBAL_FUNC(scriptEngine, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterGlobalFunction( \ + funcdef, \ + asFUNCTION(func), asCALL_CDECL)) + +#define REGISTER_OBJECT_METHOD(scriptEngine, clasdef, funcdef, clas, func) \ + AS_CHECK(scriptEngine->RegisterObjectMethod( \ + clasdef, funcdef, \ + asMETHOD(clas, func), asCALL_THISCALL)) + +#define REGISTER_EXT_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterObjectMethod( \ + clasdef, funcdef, \ + asFUNCTION(func), asCALL_CDECL_OBJLAST)) + +#define REGISTER_GENERIC_OBJECT_METHOD(scriptEngine, clasdef, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterObjectMethod( \ + clasdef, funcdef, \ + asFUNCTION(func), asCALL_GENERIC)) + +#define REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, clasdef, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterObjectBehaviour( \ + clasdef, asBEHAVE_CONSTRUCT, funcdef, \ + asFUNCTION(func), asCALL_CDECL_OBJLAST)) + +#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterObjectBehaviour( \ + clasdef, asBEHAVE_DESTRUCT, funcdef, \ + asFUNCTION(func), asCALL_CDECL_OBJLAST)) + +#define REGISTER_EXT_OBJECT_DESTRUCTOR(scriptEngine, clasdef, funcdef, func) \ + AS_CHECK(scriptEngine->RegisterObjectBehaviour( \ + clasdef, asBEHAVE_DESTRUCT, funcdef, \ + asFUNCTION(func), asCALL_CDECL_OBJLAST)) + +#define AS_CHECK(f) \ + { \ + int __r = f; \ + if (__r < 0) { \ + DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \ + } \ + } +#define AS_CHECK_ADDITIONAL_INFO(f, i) \ + { \ + int __r = f; \ + if (__r < 0) { \ + DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r), i); \ + } \ + } +#define AS_RET_CHECK(f) \ + { \ + int __r = f; \ + if (__r < 0) { \ + DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::Scripting::getAngelScriptReturnCodeString(__r)); \ + return; \ + } \ + } diff --git a/Deer/Include/DeerRender/Resource.h b/Deer/Include/DeerRender/Resource.h index 6123396..cff30c3 100644 --- a/Deer/Include/DeerRender/Resource.h +++ b/Deer/Include/DeerRender/Resource.h @@ -13,8 +13,8 @@ namespace Deer { class ResourceManager; typedef uint32_t ResourceId; - ResourceId generatePhyisicalStorageId(); - ResourceId generateRuntimeStorageId(); + ResourceId generatePhyisicalResourceId(); + ResourceId generateRuntimeResourceId(); template class StorageBackend { @@ -26,8 +26,8 @@ namespace Deer { template class Resource { public: - int32_t getResourceId() const { return resourceId; } - ResourceId getStorageId() const { return ResourceManager::getStorageId(*this); } + int32_t getResourceIndex() const { return resourceId; } + ResourceId getResourceId() const { return ResourceManager::getResourceId(*this); } bool isValid() const { return ResourceManager::isValid(*this); } T& getData() { return ResourceManager::getResourceData(*this); } @@ -123,7 +123,7 @@ namespace Deer { return res.resourceId >= 0 && res.resourceId < static_cast(resources.size()); } - static inline ResourceId getStorageId(Resource res) { + static inline ResourceId getResourceId(Resource res) { if (!isValid(res)) return 0; diff --git a/Deer/src/DeerRender/Core/ResourceIdGenerator.cpp b/Deer/src/DeerRender/Core/ResourceIdGenerator.cpp index 3b2532a..155d51a 100644 --- a/Deer/src/DeerRender/Core/ResourceIdGenerator.cpp +++ b/Deer/src/DeerRender/Core/ResourceIdGenerator.cpp @@ -3,11 +3,11 @@ #include namespace Deer { - ResourceId generatePhyisicalStorageId() { + ResourceId generatePhyisicalResourceId() { return std::random_device{}() | 0x80000000; } - ResourceId generateRuntimeStorageId() { + ResourceId generateRuntimeResourceId() { return std::random_device{}() & 0x7FFFFFF; } } // namespace Deer \ No newline at end of file diff --git a/Deer/src/DeerRender/Scripting/InternalAPI/Resources.cpp b/Deer/src/DeerRender/Scripting/InternalAPI/Resources.cpp index e0c20f7..068bb12 100644 --- a/Deer/src/DeerRender/Scripting/InternalAPI/Resources.cpp +++ b/Deer/src/DeerRender/Scripting/InternalAPI/Resources.cpp @@ -26,7 +26,7 @@ namespace Deer { Resource createFrameBuffer(int width, int height) { FrameBufferData spec(width, height, 1, FrameBufferData::FrameBufferType::RGBA8); - return ResourceManager::loadResourceFromData(spec, generateRuntimeStorageId()); + return ResourceManager::loadResourceFromData(spec, generateRuntimeResourceId()); } void resource_defaultConstructor(void* mem) { diff --git a/Deer/src/DeerRender/Scripting/InternalAPI/Resources.h b/Deer/src/DeerRender/Scripting/InternalAPI/Resources.h index da05fe4..b383fe4 100644 --- a/Deer/src/DeerRender/Scripting/InternalAPI/Resources.h +++ b/Deer/src/DeerRender/Scripting/InternalAPI/Resources.h @@ -23,6 +23,8 @@ namespace Deer { // GENERIC RESOURCE template bool resource_isValid(Resource& resource) { return resource.isValid(); } + template + ResourceId resource_getResourceId(Resource& resource) { return resource.getResourceId(); } void resource_defaultConstructor(void*); // Frame Buffer diff --git a/Deer/src/DeerRender/Scripting/ResourcesRegistry.cpp b/Deer/src/DeerRender/Scripting/ResourcesRegistry.cpp index 7190968..076a5ad 100644 --- a/Deer/src/DeerRender/Scripting/ResourcesRegistry.cpp +++ b/Deer/src/DeerRender/Scripting/ResourcesRegistry.cpp @@ -21,11 +21,12 @@ namespace Deer { template void registerResourceBasics(const char* objName) { REGISTER_EXT_OBJECT_METHOD(scriptEngine, objName, "bool isValid() const", static_cast&)>(&resource_isValid)); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, objName, "ResourceId getResourceId() const", static_cast&)>(&resource_getResourceId)); } } // namespace Scripting void Scripting::registerResourceStructs() { - AS_CHECK(scriptEngine->RegisterObjectType("StorageId", sizeof(ResourceId), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits())); + AS_CHECK(scriptEngine->RegisterObjectType("ResourceId", sizeof(ResourceId), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits())); AS_CHECK(scriptEngine->RegisterObjectType("GPUMesh", sizeof(Resource), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits>())); AS_CHECK(scriptEngine->RegisterObjectType("Shader", sizeof(Resource), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits>())); @@ -36,7 +37,7 @@ namespace Deer { Resource createFrameBuffer(const std::string name, int sixeX, int sizeY); void Scripting::registerResourceFunctions() { - REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "StorageId", "void f()", resource_defaultConstructor); + REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "ResourceId", "void f()", resource_defaultConstructor); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "int get_width() const property", frameBuffer_getWidth); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "int get_heighqt() const property", frameBuffer_getHeight); @@ -46,7 +47,7 @@ namespace Deer { REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void drawMesh(GPUMesh, Shader, Transform, WorldCamera)", frameBuffer_drawMesh); scriptEngine->SetDefaultNamespace("Resource"); - REGISTER_GLOBAL_FUNC(scriptEngine, "FrameBuffer createFrameBuffer(string&in name, int sizeX, int sizeY)", createFrameBuffer); + REGISTER_GLOBAL_FUNC(scriptEngine, "FrameBuffer createFrameBuffer(int sizeX, int sizeY)", createFrameBuffer); scriptEngine->SetDefaultNamespace("Builtin"); REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh cube()", Builtin::cube); REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh sphere()", Builtin::sphere); diff --git a/Deer/src/DeerRender/Serialization/Components/MeshComponentSerialization.h b/Deer/src/DeerRender/Serialization/Components/MeshComponentSerialization.h index f0c6ec0..de76fcb 100644 --- a/Deer/src/DeerRender/Serialization/Components/MeshComponentSerialization.h +++ b/Deer/src/DeerRender/Serialization/Components/MeshComponentSerialization.h @@ -13,8 +13,8 @@ namespace Deer { template void save(Archive& archive) const { archive(cereal::make_nvp("IsActive", component.active)); - archive(cereal::make_nvp("Mesh", component.mesh.getStorageId())); - archive(cereal::make_nvp("Shader", component.shader.getStorageId())); + archive(cereal::make_nvp("Mesh", component.mesh.getResourceId())); + archive(cereal::make_nvp("Shader", component.shader.getResourceId())); } template diff --git a/Deer/src/DeerRender/Voxel/VoxelBuilder.cpp b/Deer/src/DeerRender/Voxel/VoxelBuilder.cpp index 27b4b5f..e101c9a 100644 --- a/Deer/src/DeerRender/Voxel/VoxelBuilder.cpp +++ b/Deer/src/DeerRender/Voxel/VoxelBuilder.cpp @@ -93,7 +93,7 @@ namespace Deer { meshData.getIndexData()[i] = indices[i]; } - return ResourceManager::loadResourceFromData(meshData, generateRuntimeStorageId()); + return ResourceManager::loadResourceFromData(meshData, generateRuntimeResourceId()); } VoxelBuilder::VoxelData& VoxelBuilder::getVoxelData(int x, int y, int z) { diff --git a/DeerStudio/headers/DeerStudio/StudioAPI.h b/DeerStudio/headers/DeerStudio/StudioAPI.h index 58268c8..b401108 100644 --- a/DeerStudio/headers/DeerStudio/StudioAPI.h +++ b/DeerStudio/headers/DeerStudio/StudioAPI.h @@ -10,6 +10,7 @@ namespace Deer { namespace StudioAPI { int32_t getResourceFolder(std::string&); + void resourceFolder_constructor(void*); bool resourceFolder_isValid(int32_t&); bool resourceFolder_isRoot(int32_t&); diff --git a/DeerStudio/headers/DeerStudio/StudioResources.h b/DeerStudio/headers/DeerStudio/StudioResources.h index d51d544..2dd2434 100644 --- a/DeerStudio/headers/DeerStudio/StudioResources.h +++ b/DeerStudio/headers/DeerStudio/StudioResources.h @@ -8,9 +8,10 @@ namespace Deer { class EditorDataSource; + class Texture; + class TextureData; class MeshData; class ShaderData; - class TextureData; enum class ResourceType : int { NONE = 0, @@ -51,9 +52,11 @@ namespace Deer { namespace StudioResources { ResourceInformation* getResourceInfoFromPath(const std::string& path); ResourceInformation* getResourceInfoFromId(uint32_t resource); - FolderInfo* getFolderInfoFromPath(std::string folderStr); + FolderInfo* getFolderInfoFromPath(const std::string& folderStr); + Resource getEditorIcon(const std::string& icon); void scanResources(); + Scope loadTextureFromPath(const std::string&); } // namespace StudioResources template <> diff --git a/DeerStudio/src/DeerStudio/EditorDataImporter/TextureData.cpp b/DeerStudio/src/DeerStudio/EditorDataImporter/TextureData.cpp index 224f539..0e41685 100644 --- a/DeerStudio/src/DeerStudio/EditorDataImporter/TextureData.cpp +++ b/DeerStudio/src/DeerStudio/EditorDataImporter/TextureData.cpp @@ -45,4 +45,38 @@ namespace Deer { return textureData; } + + Scope StudioResources::loadTextureFromPath(const std::string& path) { + stbi_set_flip_vertically_on_load(true); + int width, height, channels; + + stbi_uc* data = stbi_load(path.c_str(), &width, &height, &channels, 0); + + if (!data) { + DEER_CORE_ERROR("Error loading {}", path.c_str()); + return nullptr; + } + + TextureFormat format = NONE; + switch (channels) { + case 4: + format = RGBA8; + break; + case 3: + format = RGB8; + break; + case 1: + format = R8; + break; + default: + DEER_CORE_ERROR("Error loading {}, invalid chanel count {}", path.c_str(), channels); + return nullptr; + } + + Scope textureData = MakeScope(format, width, height); + std::memcpy(textureData->getData(), data, textureData->getSize()); + stbi_image_free(data); + + return textureData; + } } // namespace Deer \ No newline at end of file diff --git a/DeerStudio/src/DeerStudio/StudioAPI.cpp b/DeerStudio/src/DeerStudio/StudioAPI.cpp index 188bbcc..d24ceae 100644 --- a/DeerStudio/src/DeerStudio/StudioAPI.cpp +++ b/DeerStudio/src/DeerStudio/StudioAPI.cpp @@ -19,6 +19,10 @@ namespace Deer { extern std::unordered_map folderPathToFolderIndex; } // namespace StudioResources + void StudioAPI::resourceFolder_constructor(void* mem) { + new (mem) int32_t(-1); + } + int32_t StudioAPI::getResourceFolder(std::string& path) { if (!StudioResources::folderPathToFolderIndex.contains(path)) return -1; @@ -58,7 +62,7 @@ namespace Deer { FolderInfo& folderInfo = StudioResources::folders[folderIndex]; - return getResourceFolder(folderInfo.fullPath); + return getResourceFolder(folderInfo.parent); } int32_t StudioAPI::resourceFolder_getSubFolderCount(int32_t& folderIndex) { @@ -76,6 +80,12 @@ namespace Deer { } FolderInfo& folderInfo = StudioResources::folders[folderIndex]; + + if (subFolderIndex < 0 || subFolderIndex >= folderInfo.subfolders.size()) { + DEER_SCRIPT_ERROR("Error calling ResourceFolder.getSubfolderByIndex, out of index"); + return 0; + } + return getResourceFolder(folderInfo.subfolders[subFolderIndex]); } @@ -94,6 +104,12 @@ namespace Deer { } FolderInfo& folderInfo = StudioResources::folders[folderIndex]; + + if (resourceIndex < 0 || resourceIndex >= folderInfo.resources.size()) { + DEER_SCRIPT_ERROR("Error calling ResourceFolder.getResourceByIndex, out of index"); + return 0; + } + return folderInfo.resources[resourceIndex]; } diff --git a/DeerStudio/src/DeerStudio/StudioResources.cpp b/DeerStudio/src/DeerStudio/StudioResources.cpp index 9b92762..d05516e 100644 --- a/DeerStudio/src/DeerStudio/StudioResources.cpp +++ b/DeerStudio/src/DeerStudio/StudioResources.cpp @@ -3,6 +3,7 @@ #include "cereal/archives/json.hpp" +#include "DeerRender/Texture.h" #include "cereal/types/string.hpp" #include "cereal/types/vector.hpp" @@ -53,10 +54,14 @@ namespace Deer { std::vector folders; std::unordered_map folderPathToFolderIndex; + std::vector> icons; + std::unordered_map nameToIconIndex; + void registerResource(ResourceInformation& resource, size_t index); - FolderInfo& getCreateFolderInfo(std::string folderStr); + FolderInfo& getCreateFolderInfo(const std::string& folderStr); void clearFolderContent(); + void scanEditorIcons(); ResourceType getResourceType(const std::string& dir); } // namespace StudioResources @@ -86,7 +91,14 @@ namespace Deer { } } - FolderInfo* StudioResources::getFolderInfoFromPath(std::string path) { + Resource StudioResources::getEditorIcon(const std::string& icon) { + if (!nameToIconIndex.contains(icon)) + return Resource(); + + return icons[nameToIconIndex[icon]]; + } + + FolderInfo* StudioResources::getFolderInfoFromPath(const std::string& path) { if (!folderPathToFolderIndex.contains(path)) return nullptr; @@ -107,7 +119,7 @@ namespace Deer { return &resources[resourceIdToIndex[resource]]; } - FolderInfo& StudioResources::getCreateFolderInfo(std::string folderStr) { + FolderInfo& StudioResources::getCreateFolderInfo(const std::string& folderStr) { // If size == 0, we create the root folder if (folders.size() == 0) { Path resourcePath("Resources"); @@ -138,6 +150,9 @@ namespace Deer { folders.push_back(newFolder); folderInfo = &folders.back(); folderPathToFolderIndex[folderStr] = folders.size() - 1; + + FolderInfo& parent = StudioResources::getCreateFolderInfo(newFolder.parent); + parent.subfolders.push_back(folderStr); } return *folderInfo; @@ -163,6 +178,7 @@ namespace Deer { resourceIdToIndex.clear(); clearFolderContent(); + scanEditorIcons(); Path resourcePath("Resources"); Path resourceJsonPath = resourcePath / "ResourceData.json"; @@ -227,4 +243,24 @@ namespace Deer { archive(cereal::make_nvp("Resources", resources)); } } // namespace Deer + + void StudioResources::scanEditorIcons() { + icons.clear(); + nameToIconIndex.clear(); + + Path iconPath("Editor/Icons"); + for (auto& file : std::filesystem::recursive_directory_iterator(iconPath)) { + Path filePath = file.path(); + ResourceType type = getResourceType(filePath); + + if (type != ResourceType::TEXTURE) + continue; + + Scope textureData = loadTextureFromPath(filePath); + Resource textureResource = ResourceManager::loadResourceFromData(*textureData.get(), generateRuntimeResourceId()); + + nameToIconIndex[filePath.stem().string()] = icons.size(); + icons.push_back(textureResource); + } + } } // namespace Deer \ No newline at end of file diff --git a/DeerStudio/src/DeerStudio/StudioScripting.cpp b/DeerStudio/src/DeerStudio/StudioScripting.cpp index f7042e1..5188660 100644 --- a/DeerStudio/src/DeerStudio/StudioScripting.cpp +++ b/DeerStudio/src/DeerStudio/StudioScripting.cpp @@ -1,4 +1,5 @@ #include "DeerStudio/StudioScripting.h" +#include "DeerCore/Scripting/Helpers.h" #include "DeerRender/Scripting.h" #include "DeerStudio/StudioAPI.h" @@ -21,9 +22,30 @@ namespace Deer { scriptEngine->RegisterEnumValue("ResourceType", "Texture", (int)ResourceType::TEXTURE); scriptEngine->SetDefaultNamespace("Resources"); - scriptEngine->RegisterGlobalFunction("GPUMesh loadGPUMesh(StorageId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); - scriptEngine->RegisterGlobalFunction("Shader loadShader(StorageId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); - scriptEngine->RegisterGlobalFunction("Texture loadTexture(StorageId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); + scriptEngine->RegisterGlobalFunction("GPUMesh loadGPUMesh(ResourceId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); + scriptEngine->RegisterGlobalFunction("Shader loadShader(ResourceId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); + scriptEngine->RegisterGlobalFunction("Texture loadTexture(ResourceId)", asFUNCTION(ResourceManager::loadResource), asCALL_CDECL); + scriptEngine->SetDefaultNamespace(""); + + AS_CHECK(scriptEngine->RegisterObjectType("ResourceFolder", sizeof(int32_t), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits())); + REGISTER_EXT_OBJECT_CONSTRUCTOR(scriptEngine, "ResourceFolder", "void f()", StudioAPI::resourceFolder_constructor); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "bool isValid()", StudioAPI::resourceFolder_isValid); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "bool isRoot()", StudioAPI::resourceFolder_isRoot); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "string get_name() const property", StudioAPI::resourceFolder_getName); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "string get_path() const property", StudioAPI::resourceFolder_getFullPath); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "ResourceFolder get_parent() const property", StudioAPI::resourceFolder_getParentFolder); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "int getSubfolderCount()", StudioAPI::resourceFolder_getSubFolderCount); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "ResourceFolder getSubfolderByIndex(int)", StudioAPI::resourceFolder_getSubfolderByIndex); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "int getResourceIdCount()", StudioAPI::resourceFolder_getResourceCount); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceFolder", "ResourceId getResourceIdByIndex(int)", StudioAPI::resourceFolder_getResourceIdByIndex); + + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceId", "string get_name() const property", StudioAPI::resourceId_getName); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceId", "ResourceFolder get_folder() const property", StudioAPI::resourceId_getFolder); + REGISTER_EXT_OBJECT_METHOD(scriptEngine, "ResourceId", "ResourceType get_type() const property", StudioAPI::resourceId_getType); + + scriptEngine->SetDefaultNamespace("Studio"); + REGISTER_GLOBAL_FUNC(scriptEngine, "ResourceFolder getFolder(string&in)", StudioAPI::getResourceFolder); + REGISTER_GLOBAL_FUNC(scriptEngine, "Texture getIcon(string&in)", StudioResources::getEditorIcon); scriptEngine->SetDefaultNamespace(""); } } // namespace Deer \ No newline at end of file diff --git a/Editor/Scripts/Previewer/Previewer.as b/Editor/Scripts/Previewer/Previewer.as index b6ed864..bfd8d12 100644 --- a/Editor/Scripts/Previewer/Previewer.as +++ b/Editor/Scripts/Previewer/Previewer.as @@ -1,6 +1,6 @@ namespace Previewer { FrameBuffer getMeshPreview(GPUMesh mesh) { - FrameBuffer frame = Resource::createFrameBuffer(mesh.path, 128, 128); + FrameBuffer frame = Resource::createFrameBuffer(128, 128); frame.clearRGBA(0, 0, 0, 0); WorldCamera wcamera; @@ -16,7 +16,7 @@ namespace Previewer { } FrameBuffer getShaderPreview(Shader shader) { - FrameBuffer frame = Resource::createFrameBuffer(shader.path, 128, 128); + FrameBuffer frame = Resource::createFrameBuffer(128, 128); frame.clearRGBA(0, 0, 0, 0); WorldCamera wcamera; diff --git a/Editor/Scripts/Properties/MeshProperties.as b/Editor/Scripts/Properties/MeshProperties.as index cfbc91b..90924d0 100644 --- a/Editor/Scripts/Properties/MeshProperties.as +++ b/Editor/Scripts/Properties/MeshProperties.as @@ -17,7 +17,7 @@ class MeshComponentRender { ImGui::nextColumn(); if (meshComponent.hasMesh) { - ImGui::buttonExpanded(meshComponent.meshResource.name); + ImGui::buttonExpanded(meshComponent.meshResource.getResourceId().name); } else { ImGui::buttonExpanded(""); } @@ -32,7 +32,7 @@ class MeshComponentRender { ImGui::nextColumn(); if (meshComponent.hasShader) { - ImGui::buttonExpanded(meshComponent.shader.name); + ImGui::buttonExpanded(meshComponent.shader.getResourceId().name); } else { ImGui::buttonExpanded(""); } @@ -47,7 +47,7 @@ class MeshComponentRender { ImGui::nextColumn(); if (meshComponent.hasTexture) { - ImGui::buttonExpanded(meshComponent.texture.name); + ImGui::buttonExpanded(meshComponent.texture.getResourceId().name); } else { ImGui::buttonExpanded(""); } diff --git a/Editor/Scripts/ResourceExplorer/ResourceExplorer.as b/Editor/Scripts/ResourceExplorer/ResourceExplorer.as index 1df81f0..465a3c9 100644 --- a/Editor/Scripts/ResourceExplorer/ResourceExplorer.as +++ b/Editor/Scripts/ResourceExplorer/ResourceExplorer.as @@ -1,94 +1,6 @@ -bool allowRender = false; - -class MeshResource { - string displayName; - string path; - GPUMesh meshResource; - FrameBuffer frameBuffer; - - bool loaded = false; - - MeshResource(string _meshPath) { - path = _meshPath; - } - - void render(int size) { - if (!loaded) { - if (allowRender) { - meshResource = StudioAPI::loadGPUMesh(path); - frameBuffer = Previewer::getMeshPreview(meshResource); - displayName = meshResource.name; - allowRender = false; - loaded = true; - } else { - ImGui::text("Loading"); - return; - } - } - - ImGui::cartIconButton(displayName, frameBuffer, size, ImGui::getAvailableSizeX()); - ImGui::dragDropSource("MESH", any(meshResource), displayName); - } -} - -class ShaderResource { - string displayName; - string path; - Shader shaderResource; - FrameBuffer frameBuffer; - - bool loaded = false; - - ShaderResource(string _path) { - path = _path; - } - - void render(int size) { - if (!loaded) { - if (allowRender) { - shaderResource = StudioAPI::loadShader(path); - frameBuffer = Previewer::getShaderPreview(shaderResource); - displayName = shaderResource.name; - allowRender = false; - loaded = true; - } else { - ImGui::text("Loading"); - return; - } - } - - ImGui::cartIconButton(displayName, frameBuffer, size, ImGui::getAvailableSizeX()); - ImGui::dragDropSource("SHADER", any(shaderResource), displayName); - } -} - -class TextureResource { - string displayName; - string path; - Texture texture; - - TextureResource(string _path) { - path = _path; - texture = StudioAPI::loadTexture(_path); - displayName = texture.name; - } - - void render(int size) { - ImGui::cartIconButton(displayName, texture, size, ImGui::getAvailableSizeX()); - ImGui::dragDropSource("TEXTURE", any(texture), displayName); - } -} - class ResourceExplorer : Panel { - string selectedResource = ""; - string currentPath = ""; - int size = 96; - - array subFolders; - array meshes; - array shaders; - array textures; + ResourceFolder currentFolder; array subFiles; bool alreadyRendered = false; @@ -97,56 +9,25 @@ class ResourceExplorer : Panel { dictionary meshFrameBuffer; void onInit() { - setPath(""); - } - - void setPath(string&in path) { - meshFrameBuffer.deleteAll(); - currentPath = path; - subFolders = StudioAPI::getResourceFolders(path); - subFiles = StudioAPI::getResourceFiles(path); - meshes = array(0); - shaders = array(0); - textures = array(0); - - for ( uint i = 0; i < subFiles.length(); i++) { - ResourceType resType = StudioAPI::getResourceType(subFiles[i]); - if (resType == ResourceType::Mesh) { - MeshResource@ meshRes = @MeshResource(subFiles[i]); - meshes.insertLast(@meshRes); - } - if (resType == ResourceType::Shader) { - ShaderResource@ shaderRes = @ShaderResource(subFiles[i]); - shaders.insertLast(@shaderRes); - } - if (resType == ResourceType::Texture) { - TextureResource@ texture = @TextureResource(subFiles[i]); - textures.insertLast(@texture); - } - } + currentFolder = Studio::getFolder(""); } void onMenuBar() { - // If we select that path - if (ImGui::menuItem("Resources")) { - setPath(""); + array topFolders; + ResourceFolder renderFolder = currentFolder; + while (!renderFolder.isRoot()) { + topFolders.insertLast(renderFolder); + renderFolder = renderFolder.parent; } + topFolders.insertLast(renderFolder); - array@ paths = Path::divide(currentPath); - for (uint i = 0; i < paths.length(); i++) { - ImGui::text("/"); + for (int i = topFolders.length() - 1; i >= 0; i--) { + if (ImGui::menuItem(topFolders[i].name)) { + currentFolder = topFolders[i]; + } - // If we select that path - if (ImGui::menuItem(paths[i])) { - // We obtain that pat - string changePath = ""; - for (uint z = 0; z <= i; z++) { - if (z != 0) - changePath += "/"; - changePath += paths[z]; - } - - setPath(changePath); + if (i != 0) { + ImGui::text("/"); } } @@ -172,65 +53,19 @@ class ResourceExplorer : Panel { } void onImGui() { - - fase += 0.3; ImGui::automaticColumns(size + 64); - - string temp_path = currentPath; - // Render navigation folders - for (uint i = 0; i < subFolders.length(); i++) { - Texture folder = StudioAPI::loadIcon("folder.png"); - if (ImGui::cartIconButton(Path::getName(subFolders[i]), folder, size, ImGui::getAvailableSizeX())) { - setPath(subFolders[i]); + int subFolderCount = currentFolder.getSubfolderCount(); + Texture folderIcon = Studio::getIcon("folder"); + + for (int i = 0; i < subFolderCount; i++) { + ResourceFolder resourceFolder = currentFolder.getSubfolderByIndex(i); + if (ImGui::cartIconButton(resourceFolder.name, folderIcon, size, ImGui::getAvailableSizeX())) { + currentFolder = resourceFolder; + return; } + ImGui::nextColumn(); } - - allowRender = true; - for ( uint i = 0; i < meshes.length(); i++) { - meshes[i].render(size); - ImGui::nextColumn(); - } - for ( uint i = 0; i < shaders.length(); i++) { - shaders[i].render(size); - ImGui::nextColumn(); - } - for ( uint i = 0; i < textures.length(); i++) { - textures[i].render(size); - ImGui::nextColumn(); - } - - } - - void drawResource(string&in filename) { - ResourceType resType = StudioAPI::getResourceType(filename); - bool selected = filename == selectedResource; - - if (resType == ResourceType::Shader) { - Texture shaderTexture = StudioAPI::loadIcon("shader.png"); - Shader shader = StudioAPI::loadShader(filename); - FrameBuffer frame = Previewer::getShaderPreview(shader); - if (ImGui::cartIconButton(Path::getName(filename), frame, size, ImGui::getAvailableSizeX())) { - selectedResource = filename; - } - ImGui::dragDropSource("SHADER", any(shader), filename); - ImGui::nextColumn(); - return; - } - - if (resType == ResourceType::Texture) { - Texture texture = StudioAPI::loadTexture(filename); - if (ImGui::cartIconButton(Path::getName(filename), texture, size, ImGui::getAvailableSizeX())) { - selectedResource = filename; - } - ImGui::dragDropSource("TEXTURE", any(texture), filename); - ImGui::nextColumn(); - return; - } - - Texture fileTexture = StudioAPI::loadIcon("file.png"); - ImGui::cartIconButton(Path::getName(filename), fileTexture, size, ImGui::getAvailableSizeX()); - ImGui::nextColumn(); } } diff --git a/Editor/Scripts/ResourceExplorer/ResourceExplorer.as.disabled b/Editor/Scripts/ResourceExplorer/ResourceExplorer.as.disabled new file mode 100644 index 0000000..b793164 --- /dev/null +++ b/Editor/Scripts/ResourceExplorer/ResourceExplorer.as.disabled @@ -0,0 +1,233 @@ +bool allowRender = false; + +class MeshResource { + string displayName; + string path; + GPUMesh meshResource; + FrameBuffer frameBuffer; + + bool loaded = false; + + MeshResource(string _meshPath) { + path = _meshPath; + } + + void render(int size) { + if (!loaded) { + if (allowRender) { + meshResource = StudioAPI::loadGPUMesh(path); + frameBuffer = Previewer::getMeshPreview(meshResource); + displayName = meshResource.name; + allowRender = false; + loaded = true; + } else { + ImGui::text("Loading"); + return; + } + } + + ImGui::cartIconButton(displayName, frameBuffer, size, ImGui::getAvailableSizeX()); + ImGui::dragDropSource("MESH", any(meshResource), displayName); + } +} + +class ShaderResource { + string displayName; + string path; + Shader shaderResource; + FrameBuffer frameBuffer; + + bool loaded = false; + + ShaderResource(string _path) { + path = _path; + } + + void render(int size) { + if (!loaded) { + if (allowRender) { + shaderResource = StudioAPI::loadShader(path); + frameBuffer = Previewer::getShaderPreview(shaderResource); + displayName = shaderResource.name; + allowRender = false; + loaded = true; + } else { + ImGui::text("Loading"); + return; + } + } + + ImGui::cartIconButton(displayName, frameBuffer, size, ImGui::getAvailableSizeX()); + ImGui::dragDropSource("SHADER", any(shaderResource), displayName); + } +} + +class TextureResource { + string displayName; + string path; + Texture texture; + + TextureResource(string _path) { + path = _path; + texture = StudioAPI::loadTexture(_path); + displayName = texture.name; + } + + void render(int size) { + ImGui::cartIconButton(displayName, texture, size, ImGui::getAvailableSizeX()); + ImGui::dragDropSource("TEXTURE", any(texture), displayName); + } +} + +class ResourceExplorer : Panel { + string selectedResource = ""; + string currentPath = ""; + + int size = 96; + + array subFolders; + array meshes; + array shaders; + array textures; + + array subFiles; + bool alreadyRendered = false; + float fase = 0; + + dictionary meshFrameBuffer; + + void onInit() { + setPath(""); + } + + void setPath(string&in path) { + meshFrameBuffer.deleteAll(); + currentPath = path; + subFolders = StudioAPI::getResourceFolders(path); + subFiles = StudioAPI::getResourceFiles(path); + meshes = array(0); + shaders = array(0); + textures = array(0); + + for ( uint i = 0; i < subFiles.length(); i++) { + ResourceType resType = StudioAPI::getResourceType(subFiles[i]); + if (resType == ResourceType::Mesh) { + MeshResource@ meshRes = @MeshResource(subFiles[i]); + meshes.insertLast(@meshRes); + } + if (resType == ResourceType::Shader) { + ShaderResource@ shaderRes = @ShaderResource(subFiles[i]); + shaders.insertLast(@shaderRes); + } + if (resType == ResourceType::Texture) { + TextureResource@ texture = @TextureResource(subFiles[i]); + textures.insertLast(@texture); + } + } + } + + void onMenuBar() { + // If we select that path + if (ImGui::menuItem("Resources")) { + setPath(""); + } + + array@ paths = Path::divide(currentPath); + for (uint i = 0; i < paths.length(); i++) { + ImGui::text("/"); + + // If we select that path + if (ImGui::menuItem(paths[i])) { + // We obtain that pat + string changePath = ""; + for (uint z = 0; z <= i; z++) { + if (z != 0) + changePath += "/"; + changePath += paths[z]; + } + + setPath(changePath); + } + } + + ImGui::drawComboEnd("##IconSize", "Icon Size : " + size, SimpleFunction(this.setIconSize)); + } + + void setIconSize() { + if (ImGui::drawComboItem("64", size == 64)) { + size = 64; + } + + if (ImGui::drawComboItem("96", size == 96)) { + size = 96; + } + + if (ImGui::drawComboItem("128", size == 128)) { + size = 128; + } + + if (ImGui::drawComboItem("160", size == 160)) { + size = 160; + } + } + + void onImGui() { + + fase += 0.3; + ImGui::automaticColumns(size + 64); + + string temp_path = currentPath; + + // Render navigation folders + for (uint i = 0; i < subFolders.length(); i++) { + ImGui::text("Folder"); + ImGui::nextColumn(); + } + + allowRender = true; + for ( uint i = 0; i < meshes.length(); i++) { + meshes[i].render(size); + ImGui::nextColumn(); + } + for ( uint i = 0; i < shaders.length(); i++) { + shaders[i].render(size); + ImGui::nextColumn(); + } + for ( uint i = 0; i < textures.length(); i++) { + textures[i].render(size); + ImGui::nextColumn(); + } + + } + + void drawResource(string&in filename) { + ResourceType resType = StudioAPI::getResourceType(filename); + bool selected = filename == selectedResource; + + if (resType == ResourceType::Shader) { + Texture shaderTexture = StudioAPI::loadIcon("shader.png"); + Shader shader = StudioAPI::loadShader(filename); + FrameBuffer frame = Previewer::getShaderPreview(shader); + if (ImGui::cartIconButton(Path::getName(filename), frame, size, ImGui::getAvailableSizeX())) { + selectedResource = filename; + } + ImGui::dragDropSource("SHADER", any(shader), filename); + ImGui::nextColumn(); + return; + } + + if (resType == ResourceType::Texture) { + Texture texture = StudioAPI::loadTexture(filename); + if (ImGui::cartIconButton(Path::getName(filename), texture, size, ImGui::getAvailableSizeX())) { + selectedResource = filename; + } + ImGui::dragDropSource("TEXTURE", any(texture), filename); + ImGui::nextColumn(); + return; + } + + Texture fileTexture = StudioAPI::loadIcon("file.png"); + ImGui::cartIconButton(Path::getName(filename), fileTexture, size, ImGui::getAvailableSizeX()); + ImGui::nextColumn(); + } +} diff --git a/Editor/Scripts/Viewport/Viewport.as b/Editor/Scripts/Viewport/Viewport.as index beee663..a436ec6 100644 --- a/Editor/Scripts/Viewport/Viewport.as +++ b/Editor/Scripts/Viewport/Viewport.as @@ -114,7 +114,7 @@ class Viewport : Panel { } void onInit() { - frameBuffer = Resource::createFrameBuffer("MainFrameBuffer", 1000, 1000); + frameBuffer = Resource::createFrameBuffer(1000, 1000); sceneCamera.transform.position = vec3(0, 1, -2); sceneCamera.camera.nearZ = 0.1; diff --git a/imgui.ini b/imgui.ini index 7838a10..6efbef2 100644 --- a/imgui.ini +++ b/imgui.ini @@ -1,6 +1,6 @@ [Window][DockSpace Demo] Pos=0,0 -Size=1440,749 +Size=2560,1371 Collapsed=0 [Window][Debug##Default] @@ -48,7 +48,7 @@ DockId=0x00000007,0 Pos=425,28 Size=1513,992 Collapsed=0 -DockId=0x00000009,0 +DockId=0x00000009,1 [Window][Properties] Pos=1940,28 @@ -60,7 +60,7 @@ DockId=0x0000000A,0 Pos=425,28 Size=1513,992 Collapsed=0 -DockId=0x00000009,1 +DockId=0x00000009,0 [Window][Dear ImGui Style Editor] Pos=425,28 @@ -69,7 +69,7 @@ Collapsed=0 DockId=0x00000009,2 [Docking][Data] -DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=1440,723 Split=Y +DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,28 Size=2560,1343 Split=Y DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,662 Split=X DockNode ID=0x00000001 Parent=0x00000003 SizeRef=399,985 Selected=0x16E3C1E7 DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1519,985 Split=X