Working now

This commit is contained in:
Chewico 2026-03-11 23:04:28 +01:00
parent a4c8f44ae3
commit 9c5992db4a
20 changed files with 472 additions and 221 deletions

View File

@ -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; \
} \
}

View File

@ -13,8 +13,8 @@ namespace Deer {
class ResourceManager; class ResourceManager;
typedef uint32_t ResourceId; typedef uint32_t ResourceId;
ResourceId generatePhyisicalStorageId(); ResourceId generatePhyisicalResourceId();
ResourceId generateRuntimeStorageId(); ResourceId generateRuntimeResourceId();
template <typename DataSource> template <typename DataSource>
class StorageBackend { class StorageBackend {
@ -26,8 +26,8 @@ namespace Deer {
template <typename T> template <typename T>
class Resource { class Resource {
public: public:
int32_t getResourceId() const { return resourceId; } int32_t getResourceIndex() const { return resourceId; }
ResourceId getStorageId() const { return ResourceManager<T>::getStorageId(*this); } ResourceId getResourceId() const { return ResourceManager<T>::getResourceId(*this); }
bool isValid() const { return ResourceManager<T>::isValid(*this); } bool isValid() const { return ResourceManager<T>::isValid(*this); }
T& getData() { return ResourceManager<T>::getResourceData(*this); } T& getData() { return ResourceManager<T>::getResourceData(*this); }
@ -123,7 +123,7 @@ namespace Deer {
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size()); return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
} }
static inline ResourceId getStorageId(Resource<T> res) { static inline ResourceId getResourceId(Resource<T> res) {
if (!isValid(res)) if (!isValid(res))
return 0; return 0;

View File

@ -3,11 +3,11 @@
#include <random> #include <random>
namespace Deer { namespace Deer {
ResourceId generatePhyisicalStorageId() { ResourceId generatePhyisicalResourceId() {
return std::random_device{}() | 0x80000000; return std::random_device{}() | 0x80000000;
} }
ResourceId generateRuntimeStorageId() { ResourceId generateRuntimeResourceId() {
return std::random_device{}() & 0x7FFFFFF; return std::random_device{}() & 0x7FFFFFF;
} }
} // namespace Deer } // namespace Deer

View File

@ -26,7 +26,7 @@ namespace Deer {
Resource<FrameBuffer> createFrameBuffer(int width, int height) { Resource<FrameBuffer> createFrameBuffer(int width, int height) {
FrameBufferData spec(width, height, 1, FrameBufferData::FrameBufferType::RGBA8); FrameBufferData spec(width, height, 1, FrameBufferData::FrameBufferType::RGBA8);
return ResourceManager<FrameBuffer>::loadResourceFromData(spec, generateRuntimeStorageId()); return ResourceManager<FrameBuffer>::loadResourceFromData(spec, generateRuntimeResourceId());
} }
void resource_defaultConstructor(void* mem) { void resource_defaultConstructor(void* mem) {

View File

@ -23,6 +23,8 @@ namespace Deer {
// GENERIC RESOURCE // GENERIC RESOURCE
template <typename T> template <typename T>
bool resource_isValid(Resource<T>& resource) { return resource.isValid(); } bool resource_isValid(Resource<T>& resource) { return resource.isValid(); }
template <typename T>
ResourceId resource_getResourceId(Resource<T>& resource) { return resource.getResourceId(); }
void resource_defaultConstructor(void*); void resource_defaultConstructor(void*);
// Frame Buffer // Frame Buffer

View File

@ -21,11 +21,12 @@ namespace Deer {
template <class T> template <class T>
void registerResourceBasics(const char* objName) { void registerResourceBasics(const char* objName) {
REGISTER_EXT_OBJECT_METHOD(scriptEngine, objName, "bool isValid() const", static_cast<bool (*)(Resource<T>&)>(&resource_isValid<T>)); REGISTER_EXT_OBJECT_METHOD(scriptEngine, objName, "bool isValid() const", static_cast<bool (*)(Resource<T>&)>(&resource_isValid<T>));
REGISTER_EXT_OBJECT_METHOD(scriptEngine, objName, "ResourceId getResourceId() const", static_cast<ResourceId (*)(Resource<T>&)>(&resource_getResourceId<T>));
} }
} // namespace Scripting } // namespace Scripting
void Scripting::registerResourceStructs() { void Scripting::registerResourceStructs() {
AS_CHECK(scriptEngine->RegisterObjectType("StorageId", sizeof(ResourceId), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<ResourceId>())); AS_CHECK(scriptEngine->RegisterObjectType("ResourceId", sizeof(ResourceId), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<ResourceId>()));
AS_CHECK(scriptEngine->RegisterObjectType("GPUMesh", sizeof(Resource<GPUMesh>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<GPUMesh>>())); AS_CHECK(scriptEngine->RegisterObjectType("GPUMesh", sizeof(Resource<GPUMesh>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<GPUMesh>>()));
AS_CHECK(scriptEngine->RegisterObjectType("Shader", sizeof(Resource<Shader>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<Shader>>())); AS_CHECK(scriptEngine->RegisterObjectType("Shader", sizeof(Resource<Shader>), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_ALLINTS | asGetTypeTraits<Resource<Shader>>()));
@ -36,7 +37,7 @@ namespace Deer {
Resource<FrameBuffer> createFrameBuffer(const std::string name, int sixeX, int sizeY); Resource<FrameBuffer> createFrameBuffer(const std::string name, int sixeX, int sizeY);
void Scripting::registerResourceFunctions() { 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_width() const property", frameBuffer_getWidth);
REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "int get_heighqt() const property", frameBuffer_getHeight); 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); REGISTER_EXT_OBJECT_METHOD(scriptEngine, "FrameBuffer", "void drawMesh(GPUMesh, Shader, Transform, WorldCamera)", frameBuffer_drawMesh);
scriptEngine->SetDefaultNamespace("Resource"); 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"); scriptEngine->SetDefaultNamespace("Builtin");
REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh cube()", Builtin::cube); REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh cube()", Builtin::cube);
REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh sphere()", Builtin::sphere); REGISTER_GLOBAL_FUNC(scriptEngine, "GPUMesh sphere()", Builtin::sphere);

View File

@ -13,8 +13,8 @@ namespace Deer {
template <class Archive> template <class Archive>
void save(Archive& archive) const { void save(Archive& archive) const {
archive(cereal::make_nvp("IsActive", component.active)); archive(cereal::make_nvp("IsActive", component.active));
archive(cereal::make_nvp("Mesh", component.mesh.getStorageId())); archive(cereal::make_nvp("Mesh", component.mesh.getResourceId()));
archive(cereal::make_nvp("Shader", component.shader.getStorageId())); archive(cereal::make_nvp("Shader", component.shader.getResourceId()));
} }
template <class Archive> template <class Archive>

View File

@ -93,7 +93,7 @@ namespace Deer {
meshData.getIndexData()[i] = indices[i]; meshData.getIndexData()[i] = indices[i];
} }
return ResourceManager<GPUMesh>::loadResourceFromData(meshData, generateRuntimeStorageId()); return ResourceManager<GPUMesh>::loadResourceFromData(meshData, generateRuntimeResourceId());
} }
VoxelBuilder::VoxelData& VoxelBuilder::getVoxelData(int x, int y, int z) { VoxelBuilder::VoxelData& VoxelBuilder::getVoxelData(int x, int y, int z) {

View File

@ -10,6 +10,7 @@ namespace Deer {
namespace StudioAPI { namespace StudioAPI {
int32_t getResourceFolder(std::string&); int32_t getResourceFolder(std::string&);
void resourceFolder_constructor(void*);
bool resourceFolder_isValid(int32_t&); bool resourceFolder_isValid(int32_t&);
bool resourceFolder_isRoot(int32_t&); bool resourceFolder_isRoot(int32_t&);

View File

@ -8,9 +8,10 @@
namespace Deer { namespace Deer {
class EditorDataSource; class EditorDataSource;
class Texture;
class TextureData;
class MeshData; class MeshData;
class ShaderData; class ShaderData;
class TextureData;
enum class ResourceType : int { enum class ResourceType : int {
NONE = 0, NONE = 0,
@ -51,9 +52,11 @@ namespace Deer {
namespace StudioResources { namespace StudioResources {
ResourceInformation* getResourceInfoFromPath(const std::string& path); ResourceInformation* getResourceInfoFromPath(const std::string& path);
ResourceInformation* getResourceInfoFromId(uint32_t resource); ResourceInformation* getResourceInfoFromId(uint32_t resource);
FolderInfo* getFolderInfoFromPath(std::string folderStr); FolderInfo* getFolderInfoFromPath(const std::string& folderStr);
Resource<Texture> getEditorIcon(const std::string& icon);
void scanResources(); void scanResources();
Scope<TextureData> loadTextureFromPath(const std::string&);
} // namespace StudioResources } // namespace StudioResources
template <> template <>

View File

@ -45,4 +45,38 @@ namespace Deer {
return textureData; return textureData;
} }
Scope<TextureData> 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> textureData = MakeScope<TextureData>(format, width, height);
std::memcpy(textureData->getData(), data, textureData->getSize());
stbi_image_free(data);
return textureData;
}
} // namespace Deer } // namespace Deer

View File

@ -19,6 +19,10 @@ namespace Deer {
extern std::unordered_map<std::string, size_t> folderPathToFolderIndex; extern std::unordered_map<std::string, size_t> folderPathToFolderIndex;
} // namespace StudioResources } // namespace StudioResources
void StudioAPI::resourceFolder_constructor(void* mem) {
new (mem) int32_t(-1);
}
int32_t StudioAPI::getResourceFolder(std::string& path) { int32_t StudioAPI::getResourceFolder(std::string& path) {
if (!StudioResources::folderPathToFolderIndex.contains(path)) if (!StudioResources::folderPathToFolderIndex.contains(path))
return -1; return -1;
@ -58,7 +62,7 @@ namespace Deer {
FolderInfo& folderInfo = StudioResources::folders[folderIndex]; FolderInfo& folderInfo = StudioResources::folders[folderIndex];
return getResourceFolder(folderInfo.fullPath); return getResourceFolder(folderInfo.parent);
} }
int32_t StudioAPI::resourceFolder_getSubFolderCount(int32_t& folderIndex) { int32_t StudioAPI::resourceFolder_getSubFolderCount(int32_t& folderIndex) {
@ -76,6 +80,12 @@ namespace Deer {
} }
FolderInfo& folderInfo = StudioResources::folders[folderIndex]; 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]); return getResourceFolder(folderInfo.subfolders[subFolderIndex]);
} }
@ -94,6 +104,12 @@ namespace Deer {
} }
FolderInfo& folderInfo = StudioResources::folders[folderIndex]; 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]; return folderInfo.resources[resourceIndex];
} }

View File

@ -3,6 +3,7 @@
#include "cereal/archives/json.hpp" #include "cereal/archives/json.hpp"
#include "DeerRender/Texture.h"
#include "cereal/types/string.hpp" #include "cereal/types/string.hpp"
#include "cereal/types/vector.hpp" #include "cereal/types/vector.hpp"
@ -53,10 +54,14 @@ namespace Deer {
std::vector<FolderInfo> folders; std::vector<FolderInfo> folders;
std::unordered_map<std::string, size_t> folderPathToFolderIndex; std::unordered_map<std::string, size_t> folderPathToFolderIndex;
std::vector<Resource<Texture>> icons;
std::unordered_map<std::string, size_t> nameToIconIndex;
void registerResource(ResourceInformation& resource, size_t index); void registerResource(ResourceInformation& resource, size_t index);
FolderInfo& getCreateFolderInfo(std::string folderStr); FolderInfo& getCreateFolderInfo(const std::string& folderStr);
void clearFolderContent(); void clearFolderContent();
void scanEditorIcons();
ResourceType getResourceType(const std::string& dir); ResourceType getResourceType(const std::string& dir);
} // namespace StudioResources } // namespace StudioResources
@ -86,7 +91,14 @@ namespace Deer {
} }
} }
FolderInfo* StudioResources::getFolderInfoFromPath(std::string path) { Resource<Texture> StudioResources::getEditorIcon(const std::string& icon) {
if (!nameToIconIndex.contains(icon))
return Resource<Texture>();
return icons[nameToIconIndex[icon]];
}
FolderInfo* StudioResources::getFolderInfoFromPath(const std::string& path) {
if (!folderPathToFolderIndex.contains(path)) if (!folderPathToFolderIndex.contains(path))
return nullptr; return nullptr;
@ -107,7 +119,7 @@ namespace Deer {
return &resources[resourceIdToIndex[resource]]; 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 size == 0, we create the root folder
if (folders.size() == 0) { if (folders.size() == 0) {
Path resourcePath("Resources"); Path resourcePath("Resources");
@ -138,6 +150,9 @@ namespace Deer {
folders.push_back(newFolder); folders.push_back(newFolder);
folderInfo = &folders.back(); folderInfo = &folders.back();
folderPathToFolderIndex[folderStr] = folders.size() - 1; folderPathToFolderIndex[folderStr] = folders.size() - 1;
FolderInfo& parent = StudioResources::getCreateFolderInfo(newFolder.parent);
parent.subfolders.push_back(folderStr);
} }
return *folderInfo; return *folderInfo;
@ -163,6 +178,7 @@ namespace Deer {
resourceIdToIndex.clear(); resourceIdToIndex.clear();
clearFolderContent(); clearFolderContent();
scanEditorIcons();
Path resourcePath("Resources"); Path resourcePath("Resources");
Path resourceJsonPath = resourcePath / "ResourceData.json"; Path resourceJsonPath = resourcePath / "ResourceData.json";
@ -227,4 +243,24 @@ namespace Deer {
archive(cereal::make_nvp("Resources", resources)); archive(cereal::make_nvp("Resources", resources));
} }
} // namespace Deer } // 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> textureData = loadTextureFromPath(filePath);
Resource<Texture> textureResource = ResourceManager<Texture>::loadResourceFromData(*textureData.get(), generateRuntimeResourceId());
nameToIconIndex[filePath.stem().string()] = icons.size();
icons.push_back(textureResource);
}
}
} // namespace Deer } // namespace Deer

View File

@ -1,4 +1,5 @@
#include "DeerStudio/StudioScripting.h" #include "DeerStudio/StudioScripting.h"
#include "DeerCore/Scripting/Helpers.h"
#include "DeerRender/Scripting.h" #include "DeerRender/Scripting.h"
#include "DeerStudio/StudioAPI.h" #include "DeerStudio/StudioAPI.h"
@ -21,9 +22,30 @@ namespace Deer {
scriptEngine->RegisterEnumValue("ResourceType", "Texture", (int)ResourceType::TEXTURE); scriptEngine->RegisterEnumValue("ResourceType", "Texture", (int)ResourceType::TEXTURE);
scriptEngine->SetDefaultNamespace("Resources"); scriptEngine->SetDefaultNamespace("Resources");
scriptEngine->RegisterGlobalFunction("GPUMesh loadGPUMesh(StorageId)", asFUNCTION(ResourceManager<GPUMesh>::loadResource<EditorDataSource>), asCALL_CDECL); scriptEngine->RegisterGlobalFunction("GPUMesh loadGPUMesh(ResourceId)", asFUNCTION(ResourceManager<GPUMesh>::loadResource<EditorDataSource>), asCALL_CDECL);
scriptEngine->RegisterGlobalFunction("Shader loadShader(StorageId)", asFUNCTION(ResourceManager<Shader>::loadResource<EditorDataSource>), asCALL_CDECL); scriptEngine->RegisterGlobalFunction("Shader loadShader(ResourceId)", asFUNCTION(ResourceManager<Shader>::loadResource<EditorDataSource>), asCALL_CDECL);
scriptEngine->RegisterGlobalFunction("Texture loadTexture(StorageId)", asFUNCTION(ResourceManager<Texture>::loadResource<EditorDataSource>), asCALL_CDECL); scriptEngine->RegisterGlobalFunction("Texture loadTexture(ResourceId)", asFUNCTION(ResourceManager<Texture>::loadResource<EditorDataSource>), asCALL_CDECL);
scriptEngine->SetDefaultNamespace("");
AS_CHECK(scriptEngine->RegisterObjectType("ResourceFolder", sizeof(int32_t), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<int32_t>()));
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(""); scriptEngine->SetDefaultNamespace("");
} }
} // namespace Deer } // namespace Deer

View File

@ -1,6 +1,6 @@
namespace Previewer { namespace Previewer {
FrameBuffer getMeshPreview(GPUMesh mesh) { FrameBuffer getMeshPreview(GPUMesh mesh) {
FrameBuffer frame = Resource::createFrameBuffer(mesh.path, 128, 128); FrameBuffer frame = Resource::createFrameBuffer(128, 128);
frame.clearRGBA(0, 0, 0, 0); frame.clearRGBA(0, 0, 0, 0);
WorldCamera wcamera; WorldCamera wcamera;
@ -16,7 +16,7 @@ namespace Previewer {
} }
FrameBuffer getShaderPreview(Shader shader) { FrameBuffer getShaderPreview(Shader shader) {
FrameBuffer frame = Resource::createFrameBuffer(shader.path, 128, 128); FrameBuffer frame = Resource::createFrameBuffer(128, 128);
frame.clearRGBA(0, 0, 0, 0); frame.clearRGBA(0, 0, 0, 0);
WorldCamera wcamera; WorldCamera wcamera;

View File

@ -17,7 +17,7 @@ class MeshComponentRender {
ImGui::nextColumn(); ImGui::nextColumn();
if (meshComponent.hasMesh) { if (meshComponent.hasMesh) {
ImGui::buttonExpanded(meshComponent.meshResource.name); ImGui::buttonExpanded(meshComponent.meshResource.getResourceId().name);
} else { } else {
ImGui::buttonExpanded(""); ImGui::buttonExpanded("");
} }
@ -32,7 +32,7 @@ class MeshComponentRender {
ImGui::nextColumn(); ImGui::nextColumn();
if (meshComponent.hasShader) { if (meshComponent.hasShader) {
ImGui::buttonExpanded(meshComponent.shader.name); ImGui::buttonExpanded(meshComponent.shader.getResourceId().name);
} else { } else {
ImGui::buttonExpanded(""); ImGui::buttonExpanded("");
} }
@ -47,7 +47,7 @@ class MeshComponentRender {
ImGui::nextColumn(); ImGui::nextColumn();
if (meshComponent.hasTexture) { if (meshComponent.hasTexture) {
ImGui::buttonExpanded(meshComponent.texture.name); ImGui::buttonExpanded(meshComponent.texture.getResourceId().name);
} else { } else {
ImGui::buttonExpanded(""); ImGui::buttonExpanded("");
} }

View File

@ -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 { class ResourceExplorer : Panel {
string selectedResource = "";
string currentPath = "";
int size = 96; int size = 96;
ResourceFolder currentFolder;
array<string> subFolders;
array<MeshResource@> meshes;
array<ShaderResource@> shaders;
array<TextureResource@> textures;
array<string> subFiles; array<string> subFiles;
bool alreadyRendered = false; bool alreadyRendered = false;
@ -97,56 +9,25 @@ class ResourceExplorer : Panel {
dictionary meshFrameBuffer; dictionary meshFrameBuffer;
void onInit() { void onInit() {
setPath(""); currentFolder = Studio::getFolder("");
}
void setPath(string&in path) {
meshFrameBuffer.deleteAll();
currentPath = path;
subFolders = StudioAPI::getResourceFolders(path);
subFiles = StudioAPI::getResourceFiles(path);
meshes = array<MeshResource@>(0);
shaders = array<ShaderResource@>(0);
textures = array<TextureResource@>(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() { void onMenuBar() {
// If we select that path array<ResourceFolder> topFolders;
if (ImGui::menuItem("Resources")) { ResourceFolder renderFolder = currentFolder;
setPath(""); while (!renderFolder.isRoot()) {
topFolders.insertLast(renderFolder);
renderFolder = renderFolder.parent;
}
topFolders.insertLast(renderFolder);
for (int i = topFolders.length() - 1; i >= 0; i--) {
if (ImGui::menuItem(topFolders[i].name)) {
currentFolder = topFolders[i];
} }
array<string>@ paths = Path::divide(currentPath); if (i != 0) {
for (uint i = 0; i < paths.length(); i++) {
ImGui::text("/"); 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);
} }
} }
@ -172,65 +53,19 @@ class ResourceExplorer : Panel {
} }
void onImGui() { void onImGui() {
fase += 0.3;
ImGui::automaticColumns(size + 64); ImGui::automaticColumns(size + 64);
string temp_path = currentPath; int subFolderCount = currentFolder.getSubfolderCount();
Texture folderIcon = Studio::getIcon("folder");
// Render navigation folders for (int i = 0; i < subFolderCount; i++) {
for (uint i = 0; i < subFolders.length(); i++) { ResourceFolder resourceFolder = currentFolder.getSubfolderByIndex(i);
Texture folder = StudioAPI::loadIcon("folder.png"); if (ImGui::cartIconButton(resourceFolder.name, folderIcon, size, ImGui::getAvailableSizeX())) {
if (ImGui::cartIconButton(Path::getName(subFolders[i]), folder, size, ImGui::getAvailableSizeX())) { currentFolder = resourceFolder;
setPath(subFolders[i]);
}
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; 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(); ImGui::nextColumn();
} }
} }
}

View File

@ -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<string> subFolders;
array<MeshResource@> meshes;
array<ShaderResource@> shaders;
array<TextureResource@> textures;
array<string> 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<MeshResource@>(0);
shaders = array<ShaderResource@>(0);
textures = array<TextureResource@>(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<string>@ 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();
}
}

View File

@ -114,7 +114,7 @@ class Viewport : Panel {
} }
void onInit() { void onInit() {
frameBuffer = Resource::createFrameBuffer("MainFrameBuffer", 1000, 1000); frameBuffer = Resource::createFrameBuffer(1000, 1000);
sceneCamera.transform.position = vec3(0, 1, -2); sceneCamera.transform.position = vec3(0, 1, -2);
sceneCamera.camera.nearZ = 0.1; sceneCamera.camera.nearZ = 0.1;

View File

@ -1,6 +1,6 @@
[Window][DockSpace Demo] [Window][DockSpace Demo]
Pos=0,0 Pos=0,0
Size=1440,749 Size=2560,1371
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
@ -48,7 +48,7 @@ DockId=0x00000007,0
Pos=425,28 Pos=425,28
Size=1513,992 Size=1513,992
Collapsed=0 Collapsed=0
DockId=0x00000009,0 DockId=0x00000009,1
[Window][Properties] [Window][Properties]
Pos=1940,28 Pos=1940,28
@ -60,7 +60,7 @@ DockId=0x0000000A,0
Pos=425,28 Pos=425,28
Size=1513,992 Size=1513,992
Collapsed=0 Collapsed=0
DockId=0x00000009,1 DockId=0x00000009,0
[Window][Dear ImGui Style Editor] [Window][Dear ImGui Style Editor]
Pos=425,28 Pos=425,28
@ -69,7 +69,7 @@ Collapsed=0
DockId=0x00000009,2 DockId=0x00000009,2
[Docking][Data] [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=0x00000003 Parent=0x0AC2E849 SizeRef=1920,662 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=399,985 Selected=0x16E3C1E7 DockNode ID=0x00000001 Parent=0x00000003 SizeRef=399,985 Selected=0x16E3C1E7
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1519,985 Split=X DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1519,985 Split=X