add trace for imgui.ini, add assets manager system and objects manager system, add some icons, add entity tree node for scene Hierachy's entities, add convert blend file process(but not actual use it, just implement) BUGS: file copy not work
@ -15,6 +15,7 @@
|
||||
#include "Prism/Physics/Physics3D.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
#include "Prism/Utilities/DragDropData.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -171,6 +172,9 @@ namespace Prism
|
||||
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
|
||||
UpdateWindowTitle("untitled Scene");
|
||||
|
||||
m_AssetManagerPanel = CreateScope<AssetsManagerPanel>();
|
||||
m_ObjectsPanel = CreateScope<ObjectsPanel>();
|
||||
|
||||
// OpenScene("assets/scenes/FPSDemo.scene");
|
||||
NewScene();
|
||||
}
|
||||
@ -654,6 +658,9 @@ namespace Prism
|
||||
if (m_UIShowBoundingBoxes && Property("On Top", m_UIShowBoundingBoxesOnTop))
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
|
||||
m_AssetManagerPanel->OnImGuiRender();
|
||||
m_ObjectsPanel->OnImGuiRender();
|
||||
|
||||
const char* label = m_SelectionMode == SelectionMode::Entity ? "Entity" : "Mesh";
|
||||
if (ImGui::Button(label))
|
||||
{
|
||||
@ -835,6 +842,44 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
auto payload = ImGui::AcceptDragDropPayload("scene_entity_objectP");
|
||||
if (payload)
|
||||
{
|
||||
const auto data = (DragDropData*)payload->Data;
|
||||
if (std::string_view(data->Type) == "Mesh")
|
||||
{
|
||||
auto entity = m_EditorScene->CreateEntity(data->Name);
|
||||
entity.AddComponent<MeshComponent>(Ref<Mesh>::Create(data->SourcePath));
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
/* Payload Implementation For Getting Assets In The Viewport From Asset Manager */
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
auto payload = ImGui::AcceptDragDropPayload("scene_entity_assetsP");
|
||||
if (payload)
|
||||
{
|
||||
auto data = (DragDropData*)payload->Data;
|
||||
|
||||
if (std::string_view(data->Type) == "PrismScene")
|
||||
{
|
||||
auto sceneName = data->SourcePath;
|
||||
OpenScene(sceneName);
|
||||
}
|
||||
|
||||
if (std::string_view(data->Type) == "Mesh")
|
||||
{
|
||||
auto entity = m_EditorScene->CreateEntity(data->Name);
|
||||
entity.AddComponent<MeshComponent>(Ref<Mesh>::Create(data->SourcePath));
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#define EDITORLAYER_H
|
||||
|
||||
#include "Prism.h"
|
||||
#include "Prism/Editor/AssetsManagerPanel.h"
|
||||
#include "Prism/Editor/ObjectsPanel.h"
|
||||
#include "Prism/Editor/SceneHierachyPanel.h"
|
||||
|
||||
namespace Prism
|
||||
@ -56,6 +58,8 @@ namespace Prism
|
||||
float GetSnapValue() const;
|
||||
private:
|
||||
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
|
||||
Scope<AssetsManagerPanel> m_AssetManagerPanel;
|
||||
Scope<ObjectsPanel> m_ObjectsPanel;
|
||||
|
||||
Ref<Scene> m_ActiveScene;
|
||||
Ref<Scene> m_RuntimeScene, m_EditorScene;
|
||||
|
||||
BIN
Editor/assets/editor/asset.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Editor/assets/editor/back.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
Editor/assets/editor/blend.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
Editor/assets/editor/btn_back.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Editor/assets/editor/btn_fwrd.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Editor/assets/editor/close.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Editor/assets/editor/csc.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Editor/assets/editor/favourites.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Editor/assets/editor/fbx.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
Editor/assets/editor/file.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
Editor/assets/editor/folder.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
Editor/assets/editor/folder_hierarchy.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
Editor/assets/editor/grid.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
Editor/assets/editor/list.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
Editor/assets/editor/obj.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
Editor/assets/editor/png.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Editor/assets/editor/resource.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
Editor/assets/editor/scene.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
Editor/assets/editor/script.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
Editor/assets/editor/search.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Editor/assets/editor/tags.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
Editor/assets/editor/wav.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Editor/assets/meshes/Default/Cone.fbx
Normal file
BIN
Editor/assets/meshes/Default/Cube.fbx
Normal file
BIN
Editor/assets/meshes/Default/Cylinder.fbx
Normal file
BIN
Editor/assets/meshes/Default/Plane.fbx
Normal file
BIN
Editor/assets/meshes/Default/Sphere.fbx
Normal file
BIN
Editor/assets/meshes/Default/Torus.fbx
Normal file
96
Editor/imgui.ini
Normal file
@ -0,0 +1,96 @@
|
||||
[Window][DockSpace Demo]
|
||||
Pos=0,0
|
||||
Size=2066,1198
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Scene Hierarchy]
|
||||
Pos=1595,24
|
||||
Size=471,428
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Properties]
|
||||
Pos=1595,454
|
||||
Size=471,744
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Scene Renderer]
|
||||
Pos=0,648
|
||||
Size=481,550
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Materials]
|
||||
Pos=0,24
|
||||
Size=481,622
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][Script Engine Debug]
|
||||
Pos=1595,454
|
||||
Size=471,744
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,2
|
||||
|
||||
[Window][Model]
|
||||
Pos=1595,454
|
||||
Size=471,744
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,3
|
||||
|
||||
[Window][Toolbar]
|
||||
Pos=483,24
|
||||
Size=1110,32
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=483,58
|
||||
Size=1110,722
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][Environment]
|
||||
Pos=1595,454
|
||||
Size=471,744
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,1
|
||||
|
||||
[Window][Project]
|
||||
Pos=483,782
|
||||
Size=1110,416
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[Window][Objects]
|
||||
Pos=483,782
|
||||
Size=1110,416
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,1
|
||||
|
||||
[Window][Physics]
|
||||
Pos=189,113
|
||||
Size=468,371
|
||||
Collapsed=0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xC0DFADC4 Window=0xD0388BC8 Pos=150,89 Size=2066,1174 Split=X Selected=0x0C01D6D5
|
||||
DockNode ID=0x00000007 Parent=0xC0DFADC4 SizeRef=1557,1542 Split=X
|
||||
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=481,1542 Split=Y Selected=0x5D711C2C
|
||||
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=481,817 Selected=0x5D711C2C
|
||||
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=481,723 Selected=0x68D924E0
|
||||
DockNode ID=0x00000004 Parent=0x00000007 SizeRef=1074,1542 Split=Y
|
||||
DockNode ID=0x00000001 Parent=0x00000004 SizeRef=2560,32 CentralNode=1 HiddenTabBar=1 Selected=0x0C01D6D5
|
||||
DockNode ID=0x00000002 Parent=0x00000004 SizeRef=2560,1508 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1401,669 HiddenTabBar=1 Selected=0xC450F867
|
||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=1401,386 Selected=0x9C21DE82
|
||||
DockNode ID=0x00000008 Parent=0xC0DFADC4 SizeRef=471,1542 Split=Y Selected=0x8C72BEA8
|
||||
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=315,563 Selected=0xB8729153
|
||||
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=315,977 Selected=0x73E3D51F
|
||||
|
||||
516
Prism/src/Prism/Editor/AssetsManagerPanel.cpp
Normal file
@ -0,0 +1,516 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#include "AssetsManagerPanel.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Utilities/DragDropData.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
AssetsManagerPanel::AssetsManagerPanel()
|
||||
{
|
||||
AssetTypes::Init();
|
||||
|
||||
m_FolderTex = Texture2D::Create("assets/editor/folder.png");
|
||||
m_FavoritesTex = Texture2D::Create("assets/editor/favourites.png");
|
||||
m_GoBackTex = Texture2D::Create("assets/editor/back.png");
|
||||
m_ScriptTex = Texture2D::Create("assets/editor/script.png");
|
||||
m_ResourceTex = Texture2D::Create("assets/editor/resource.png");
|
||||
m_SceneTex = Texture2D::Create("assets/editor/scene.png");
|
||||
|
||||
m_AssetIconMap[-1] = Texture2D::Create("assets/editor/file.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("fbx")] = Texture2D::Create("assets/editor/fbx.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("obj")] = Texture2D::Create("assets/editor/obj.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("wav")] = Texture2D::Create("assets/editor/wav.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("cs")] = Texture2D::Create("assets/editor/csc.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("png")] = Texture2D::Create("assets/editor/png.png");
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("blend")] = Texture2D::Create("assets/editor/blend.png");
|
||||
|
||||
// TODO: get a logo for this project
|
||||
m_AssetIconMap[AssetTypes::GetAssetTypeID("scene")] = Texture2D::Create("assets/editor/asset.png");
|
||||
|
||||
m_BackbtnTex = Texture2D::Create("assets/editor/btn_back.png");
|
||||
m_FwrdbtnTex = Texture2D::Create("assets/editor/btn_fwrd.png");
|
||||
m_FolderRightTex = Texture2D::Create("assets/editor/folder_hierarchy.png");
|
||||
m_SearchTex = Texture2D::Create("assets/editor/search.png");
|
||||
m_TagsTex = Texture2D::Create("assets/editor/tags.png");
|
||||
m_GridView = Texture2D::Create("assets/editor/grid.png");
|
||||
m_ListView = Texture2D::Create("assets/editor/list.png");
|
||||
|
||||
m_BaseDirPath = "assets";
|
||||
m_CurrentDirPath = m_BaseDirPath;
|
||||
m_PrevDirPath = m_CurrentDirPath;
|
||||
m_BaseProjectDir = m_AssetManager.GetFileSystemContents();
|
||||
m_CurrentDir = m_BaseProjectDir;
|
||||
m_BasePathLen = static_cast<int>(strlen(m_BaseDirPath.c_str()));
|
||||
m_DirDataLen = 0;
|
||||
|
||||
memset(m_InputBuffer, 0, sizeof(m_InputBuffer));
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Project", nullptr, ImGuiWindowFlags_MenuBar);
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
ImGui::SetColumnOffset(1, 200);
|
||||
|
||||
// There happens to be recursive tree unfolding issue which doesn't show nested directories/files
|
||||
ImGui::BeginChild("##folders_common");
|
||||
{
|
||||
if (ImGui::CollapsingHeader("res://", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
if (ImGui::TreeNode("Contents"))
|
||||
{
|
||||
for (int i = 0; i < m_BaseProjectDir.size(); i++)
|
||||
{
|
||||
if (ImGui::TreeNode(m_BaseProjectDir[i].Filename.c_str()))
|
||||
{
|
||||
auto dirData = m_AssetManager.GetDirectoryContents(m_BaseProjectDir[i].AbsolutePath);
|
||||
for (int j = 0; j < dirData.size(); j++)
|
||||
{
|
||||
if (!dirData[j].IsFile)
|
||||
{
|
||||
if (ImGui::TreeNode(dirData[j].Filename.c_str()))
|
||||
ImGui::TreePop();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string parentDir = m_AssetManager.GetParentPath(dirData[j].AbsolutePath);
|
||||
ImGui::Indent();
|
||||
ImGui::Selectable(dirData[j].Filename.c_str(), false);
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (m_IsDragging && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
{
|
||||
m_MovePath = m_BaseProjectDir[i].AbsolutePath.c_str();
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseDown(1))
|
||||
{
|
||||
//ImGui::OpenPopup("window");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
const auto data = ImGui::AcceptDragDropPayload("selectable", ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
|
||||
if (data)
|
||||
{
|
||||
const std::filesystem::path file = static_cast<char*>(data->Data);
|
||||
if (m_AssetManager.MoveFile(file, m_MovePath))
|
||||
{
|
||||
PM_CORE_INFO("Moved File: " + file.string() + " to " + m_MovePath);
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(m_CurrentDirPath);
|
||||
}
|
||||
m_IsDragging = false;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::NextColumn();
|
||||
|
||||
ImGui::BeginChild("##directory_structure", ImVec2(ImGui::GetColumnWidth() - 12, ImGui::GetWindowHeight() - 50));
|
||||
{
|
||||
RenderBreadCrumbs();
|
||||
ImGui::SameLine();
|
||||
ImGui::Dummy(ImVec2(ImGui::GetColumnWidth() - 350, 0));
|
||||
ImGui::SameLine();
|
||||
RenderSearch();
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::BeginChild("Scrolling");
|
||||
|
||||
if (!m_DisplayListView)
|
||||
ImGui::Columns(10, nullptr, false);
|
||||
|
||||
for (int i = 0; i < m_CurrentDir.size(); i++)
|
||||
{
|
||||
if (!m_CurrentDir.empty())
|
||||
{
|
||||
if (!m_DisplayListView)
|
||||
m_CurrentDir[i].IsFile ? RenderFileGridView(i) : RenderDirectoriesGridView(i);
|
||||
else
|
||||
m_CurrentDir[i].IsFile ? RenderFileListView(i) : RenderDirectoriesListView(i);
|
||||
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("Creating"))
|
||||
{
|
||||
if (ImGui::BeginMenu("New"))
|
||||
{
|
||||
if (ImGui::MenuItem("Folder"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Folder...");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Scene"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Scene...");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Script"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Script...");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Prefab"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Prefab...");
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Shaders"))
|
||||
{
|
||||
if (ImGui::MenuItem("Shader"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Shader File...");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Shader Graph"))
|
||||
{
|
||||
PM_CORE_INFO("Creating Shader Graph...");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
const auto data = ImGui::AcceptDragDropPayload("selectable", ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
|
||||
if (data)
|
||||
{
|
||||
const std::string a = static_cast<char*>(data->Data);
|
||||
if (m_AssetManager.MoveFile(a, m_MovePath))
|
||||
{
|
||||
PM_CORE_INFO("Moved File: " + a + " to " + m_MovePath);
|
||||
}
|
||||
m_IsDragging = false;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Create"))
|
||||
{
|
||||
if (ImGui::MenuItem("Import New Asset", "Ctrl + O"))
|
||||
{
|
||||
const std::string filename = Application::Get().OpenFile("");
|
||||
m_AssetManager.ProcessAsset(filename);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Refresh", "Ctrl + R"))
|
||||
{
|
||||
auto data = m_AssetManager.GetFileSystemContents();
|
||||
for (auto & i : data)
|
||||
{
|
||||
PM_CORE_INFO("{0}", i.Filename);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderFileListView(const int dirIndex)
|
||||
{
|
||||
const size_t fileID = AssetTypes::GetAssetTypeID(m_CurrentDir[dirIndex].FileType);
|
||||
const RendererID iconRef = m_AssetIconMap[fileID]->GetRendererID();
|
||||
ImGui::Image((ImTextureID)iconRef, ImVec2(20, 20));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Selectable((m_CurrentDir[dirIndex].Filename + std::to_string(dirIndex)).c_str(), false, ImGuiSelectableFlags_AllowDoubleClick))
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
m_AssetManager.HandleAsset(m_CurrentDir[dirIndex].AbsolutePath);
|
||||
}
|
||||
|
||||
HandleDragDrop(iconRef, dirIndex);
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderFileGridView(const int dirIndex)
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
const size_t fileID = AssetTypes::GetAssetTypeID(m_CurrentDir[dirIndex].FileType);
|
||||
const RendererID iconRef = m_AssetIconMap[fileID]->GetRendererID();
|
||||
const float columnWidth = ImGui::GetColumnWidth();
|
||||
|
||||
ImGui::ImageButton(std::string_view("##FileGridView" + std::to_string(dirIndex)).data(), (ImTextureID)iconRef, { columnWidth - 10.0F, columnWidth - 10.0F });
|
||||
|
||||
HandleDragDrop(iconRef, dirIndex);
|
||||
|
||||
const std::string newFileName = m_AssetManager.StripExtras(m_CurrentDir[dirIndex].Filename);
|
||||
ImGui::TextWrapped(newFileName.c_str());
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::HandleDragDrop(RendererID icon, int dirIndex)
|
||||
{
|
||||
// Drag 'n' Drop Implementation For File Moving
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image((ImTextureID)icon, ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(m_CurrentDir[dirIndex].Filename.c_str());
|
||||
const int size = static_cast<int>(sizeof(const char*) + strlen(m_CurrentDir[dirIndex].AbsolutePath.c_str()));
|
||||
ImGui::SetDragDropPayload("selectable", m_CurrentDir[dirIndex].AbsolutePath.c_str(), size);
|
||||
m_IsDragging = true;
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
// Drag 'n' Drop Implementation For Asset Handling In Scene Viewport
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image((ImTextureID)icon, ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(m_CurrentDir[dirIndex].Filename.c_str());
|
||||
|
||||
const AssetType assetType = AssetTypes::GetAssetTypeFromExtension(m_CurrentDir[dirIndex].FileType);
|
||||
|
||||
if (assetType == AssetType::Mesh)
|
||||
{
|
||||
const char* sourceType = m_CurrentDir[dirIndex].AbsolutePath.c_str();
|
||||
const char* name = m_CurrentDir[dirIndex].Filename.c_str();
|
||||
const char* type = "Mesh";
|
||||
|
||||
const DragDropData d(type, sourceType, name);
|
||||
ImGui::SetDragDropPayload("scene_entity_assetsP", &d, sizeof(d));
|
||||
m_IsDragging = true;
|
||||
}
|
||||
|
||||
if (assetType == AssetType::Scene)
|
||||
{
|
||||
const char* sourceType = m_CurrentDir[dirIndex].AbsolutePath.c_str();
|
||||
const char* name = m_CurrentDir[dirIndex].Filename.c_str();
|
||||
const char* type = "PrismScene";
|
||||
|
||||
const DragDropData d(type, sourceType, name);
|
||||
ImGui::SetDragDropPayload("scene_entity_assetsP", &d, sizeof(d));
|
||||
m_IsDragging = true;
|
||||
}
|
||||
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderDirectoriesListView(int dirIndex)
|
||||
{
|
||||
ImGui::Image((ImTextureID)m_FolderTex->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Selectable(m_CurrentDir[dirIndex].Filename.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick))
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
m_PrevDirPath = m_CurrentDir[dirIndex].AbsolutePath;
|
||||
m_CurrentDirPath = m_CurrentDir[dirIndex].AbsolutePath;
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(m_CurrentDir[dirIndex].AbsolutePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
|
||||
{
|
||||
ImGui::Image((ImTextureID)m_FolderTex->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(m_CurrentDir[dirIndex].Filename.c_str());
|
||||
const int size = static_cast<int>(sizeof(const char*) + strlen(m_CurrentDir[dirIndex].AbsolutePath.c_str()));
|
||||
ImGui::SetDragDropPayload("selectable", m_CurrentDir[dirIndex].AbsolutePath.c_str(), size);
|
||||
m_IsDragging = true;
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderDirectoriesGridView(int dirIndex)
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
|
||||
const float columnWidth = ImGui::GetColumnWidth();
|
||||
ImGui::ImageButton(std::string_view("##RenderDirectoriesGridView" + std::to_string(dirIndex)).data(), (ImTextureID)m_FolderTex->GetRendererID(), { columnWidth - 10.0F, columnWidth - 10.0F });
|
||||
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered())
|
||||
{
|
||||
m_PrevDirPath = m_CurrentDir[dirIndex].AbsolutePath;
|
||||
m_CurrentDirPath = m_CurrentDir[dirIndex].AbsolutePath;
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(m_CurrentDir[dirIndex].AbsolutePath);
|
||||
m_IsPathChanged = true;
|
||||
m_DirDataLen = static_cast<int>(m_CurrentDir.size());
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_AcceptNoDrawDefaultRect))
|
||||
{
|
||||
ImGui::Image((ImTextureID)m_FolderTex->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(m_CurrentDir[dirIndex].Filename.c_str());
|
||||
const int size = static_cast<int>(sizeof(const char*) + strlen(m_CurrentDir[dirIndex].AbsolutePath.c_str()));
|
||||
ImGui::SetDragDropPayload("selectable", m_CurrentDir[dirIndex].AbsolutePath.c_str(), size);
|
||||
m_IsDragging = true;
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
if (!m_IsPathChanged)
|
||||
{
|
||||
const auto fname = m_CurrentDir[dirIndex].Filename;
|
||||
const auto newFname = m_AssetManager.StripExtras(fname);
|
||||
ImGui::TextWrapped(newFname.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < m_DirDataLen; i++)
|
||||
{
|
||||
const auto fname = m_CurrentDir[i].Filename;
|
||||
const auto newFname = m_AssetManager.StripExtras(fname);
|
||||
ImGui::TextWrapped(newFname.c_str());
|
||||
m_IsPathChanged = false;
|
||||
m_DirDataLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderBreadCrumbs()
|
||||
{
|
||||
ImGui::BeginChild("##directory_breadcrumbs", ImVec2(ImGui::GetColumnWidth() - 100, 30));
|
||||
{
|
||||
const RendererID viewTexture = m_DisplayListView ? m_ListView->GetRendererID() : m_GridView->GetRendererID();
|
||||
if (ImGui::ImageButton((const char*)&viewTexture, (ImTextureID)viewTexture, ImVec2(20, 18)))
|
||||
{
|
||||
m_DisplayListView = !m_DisplayListView;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
const auto searchTexID = m_SearchTex->GetRendererID();
|
||||
|
||||
if (ImGui::ImageButton((const char*)&searchTexID,(ImTextureID)searchTexID, ImVec2(20, 18)))
|
||||
m_ShowSearchBar = !m_ShowSearchBar;
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (m_ShowSearchBar)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(200);
|
||||
|
||||
if (ImGui::InputTextWithHint("##Search", "Search...", m_InputBuffer, 100, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
{
|
||||
m_CurrentDir = m_AssetManager.SearchFiles(m_InputBuffer, m_CurrentDirPath);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
const auto backBtnTexID = m_BackbtnTex->GetRendererID();
|
||||
if (ImGui::ImageButton((const char*)&backBtnTexID,(ImTextureID)backBtnTexID, ImVec2(20, 18)))
|
||||
{
|
||||
if (strlen(m_CurrentDirPath.c_str()) == m_BasePathLen) return;
|
||||
m_ForwardPath = m_CurrentDirPath;
|
||||
m_BackPath = m_AssetManager.GetParentPath(m_CurrentDirPath);
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(m_BackPath);
|
||||
m_CurrentDirPath = m_BackPath;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
const auto FwrdBtnTexID = m_FwrdbtnTex->GetRendererID();
|
||||
if (ImGui::ImageButton((const char*)&FwrdBtnTexID,(ImTextureID)FwrdBtnTexID, ImVec2(20, 18)))
|
||||
{
|
||||
if (m_ForwardPath.empty()) return;
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(m_ForwardPath);
|
||||
m_CurrentDirPath = m_ForwardPath;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
const auto data = m_AssetManager.GetDirectories(m_CurrentDirPath);
|
||||
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (data[i] != m_BaseDirPath)
|
||||
{
|
||||
ImGui::Image((ImTextureID)m_FolderRightTex->GetRendererID(), ImVec2(22, 23));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Multiply the size of the folder name with 7(magic number) to set the size of selectable widget properly */
|
||||
const auto size = (float)(strlen(data[i].c_str()) * 7);
|
||||
|
||||
if (ImGui::Selectable(data[i].c_str(), false, 0, ImVec2(size, 22)))
|
||||
{
|
||||
/* Increament 1 to the existing index value to fully iterate the array */
|
||||
const int index = i + 1;
|
||||
std::string path;
|
||||
|
||||
/* Use the below loop to build a path from the selected folder from the breadcrumb to navigate to */
|
||||
for (int e = 0; e < index; e++)
|
||||
{
|
||||
path += data[e] + "/\\";
|
||||
}
|
||||
|
||||
m_CurrentDir = m_AssetManager.GetDirectoryContents(path);
|
||||
m_CurrentDirPath = path;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Dummy(ImVec2(ImGui::GetColumnWidth() - 400, 0));
|
||||
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderSearch()
|
||||
{
|
||||
// TODO: not implemented
|
||||
}
|
||||
|
||||
void AssetsManagerPanel::RenderBottom()
|
||||
{
|
||||
/* Will be used for object select indication. Ex. 3 folders 1 file selected */
|
||||
ImGui::BeginChild("##nav", ImVec2(ImGui::GetColumnWidth() - 12, 23));
|
||||
{
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
78
Prism/src/Prism/Editor/AssetsManagerPanel.h
Normal file
@ -0,0 +1,78 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#ifndef PRISM_ASSETSMANAGERPANEL_H
|
||||
#define PRISM_ASSETSMANAGERPANEL_H
|
||||
|
||||
#include "Prism/Utilities/AssetsManager.h"
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
#include "Prism/Core/ImGui/ImGui.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API AssetsManagerPanel
|
||||
{
|
||||
public:
|
||||
AssetsManagerPanel();
|
||||
void OnImGuiRender();
|
||||
|
||||
private:
|
||||
void RenderFileListView(int dirIndex);
|
||||
void RenderFileGridView(int dirIndex);
|
||||
void HandleDragDrop(RendererID icon, int dirIndex);
|
||||
void RenderDirectoriesListView(int dirIndex);
|
||||
void RenderDirectoriesGridView(int dirIndex);
|
||||
void RenderBreadCrumbs();
|
||||
void RenderSearch();
|
||||
void RenderBottom();
|
||||
|
||||
ImGuiInputTextCallback SearchCallback(ImGuiInputTextCallbackData* data);
|
||||
|
||||
private:
|
||||
Ref<Texture2D> m_FolderTex;
|
||||
Ref<Texture2D> m_FavoritesTex;
|
||||
Ref<Texture2D> m_FileTex;
|
||||
Ref<Texture2D> m_GoBackTex;
|
||||
Ref<Texture2D> m_ScriptTex;
|
||||
Ref<Texture2D> m_ResourceTex;
|
||||
Ref<Texture2D> m_SceneTex;
|
||||
|
||||
Ref<Texture2D> m_BackbtnTex;
|
||||
Ref<Texture2D> m_FwrdbtnTex;
|
||||
Ref<Texture2D> m_FolderRightTex;
|
||||
Ref<Texture2D> m_TagsTex;
|
||||
Ref<Texture2D> m_SearchTex;
|
||||
Ref<Texture2D> m_GridView;
|
||||
Ref<Texture2D> m_ListView;
|
||||
|
||||
std::string m_CurrentDirPath;
|
||||
std::string m_BaseDirPath;
|
||||
std::string m_PrevDirPath;
|
||||
std::string m_MovePath;
|
||||
|
||||
std::string m_ForwardPath;
|
||||
std::string m_BackPath;
|
||||
|
||||
int m_BasePathLen;
|
||||
int m_DirDataLen;
|
||||
|
||||
bool m_IsDragging = false;
|
||||
bool m_DisplayListView = false;
|
||||
bool m_UpdateBreadCrumbs = true;
|
||||
bool m_ShowSearchBar = false;
|
||||
bool m_IsPathChanged = false;
|
||||
|
||||
char m_InputBuffer[1024]{};
|
||||
|
||||
std::vector<DirectoryInfo> m_CurrentDir;
|
||||
std::vector<DirectoryInfo> m_BaseProjectDir;
|
||||
|
||||
ImGuiInputTextCallbackData m_Data;
|
||||
std::map<size_t, Ref<Texture2D>> m_AssetIconMap;
|
||||
//NotificationManager nManager;
|
||||
AssetsManager m_AssetManager;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PRISM_ASSETSMANAGERPANEL_H
|
||||
151
Prism/src/Prism/Editor/ObjectsPanel.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#include "ObjectsPanel.h"
|
||||
|
||||
|
||||
#include "imgui.h"
|
||||
#include "Prism/Utilities/DragDropData.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
ObjectsPanel::ObjectsPanel()
|
||||
{
|
||||
m_CubeImage = Texture2D::Create("assets/editor/asset.png");
|
||||
}
|
||||
|
||||
void ObjectsPanel::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Objects", nullptr, ImGuiWindowFlags_None);
|
||||
{
|
||||
char buff[100] = {};
|
||||
const auto inputText = "InputText";
|
||||
const auto inputHint = "Start Typing To Search";
|
||||
ImGui::PushItemWidth(ImGui::GetWindowWidth() - 20);
|
||||
ImGui::InputTextWithHint(inputText, inputHint, buff, 100);
|
||||
|
||||
ImGui::BeginChild("##objects_window");
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Cube");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Cube");
|
||||
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Cube.fbx", "Cube");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::Image((ImTextureID)m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Capsule");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image((ImTextureID)m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Capsule");
|
||||
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Capsule.fbx", "Capsule");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Sphere");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Sphere");
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Sphere.fbx", "Sphere");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Cylinder");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Cylinder");
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Cylinder.fbx", "Cylinder");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Torus");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Torus");
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Torus.fbx", "Torus");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Plane");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Plane");
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Plane.fbx", "Plane");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(30, 30));
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::Selectable("Cone");
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
ImGui::Image(m_CubeImage->GetRendererID(), ImVec2(20, 20));
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Text("Cone");
|
||||
const DragDropData data("Mesh", "assets/meshes/Default/Cone.fbx", "Cone");
|
||||
ImGui::SetDragDropPayload("scene_entity_objectP", &data, sizeof(data));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
24
Prism/src/Prism/Editor/ObjectsPanel.h
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#ifndef PRISM_OBJECTSPANEL_H
|
||||
#define PRISM_OBJECTSPANEL_H
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API ObjectsPanel
|
||||
{
|
||||
public:
|
||||
ObjectsPanel();
|
||||
|
||||
void OnImGuiRender();
|
||||
|
||||
private:
|
||||
Ref<Texture2D> m_CubeImage;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_OBJECTSPANEL_H
|
||||
@ -168,16 +168,42 @@ namespace Prism
|
||||
void SceneHierarchyPanel::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Scene Hierarchy");
|
||||
ImRect windowRect = { ImGui::GetWindowContentRegionMin(), ImGui::GetWindowContentRegionMax() };
|
||||
|
||||
if (m_Context)
|
||||
{
|
||||
uint32_t entityCount = 0, meshCount = 0;
|
||||
m_Context->m_Registry.view<entt::entity>().each([&](auto entity)
|
||||
{
|
||||
const Entity e(entity, m_Context.Raw());
|
||||
if (e.HasComponent<IDComponent>())
|
||||
Entity e(entity, m_Context.Raw());
|
||||
if (e.HasComponent<IDComponent>() && e.GetParentUUID() == 0)
|
||||
DrawEntityNode(e);
|
||||
});
|
||||
|
||||
if (ImGui::BeginDragDropTargetCustom(windowRect, ImGui::GetCurrentWindow()->ID))
|
||||
{
|
||||
const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("scene_entity_hierarchy", ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
|
||||
|
||||
if (payload)
|
||||
{
|
||||
const UUID droppedHandle = *((UUID*)payload->Data);
|
||||
Entity e = m_Context->FindEntityByUUID(droppedHandle);
|
||||
Entity previousParent = m_Context->FindEntityByUUID(e.GetParentUUID());
|
||||
|
||||
if (previousParent)
|
||||
{
|
||||
auto& children = previousParent.Children();
|
||||
children.erase(std::remove(children.begin(), children.end(), droppedHandle), children.end());
|
||||
}
|
||||
|
||||
e.SetParentUUID(0);
|
||||
|
||||
PM_CORE_INFO("Unparented Entity!");
|
||||
}
|
||||
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
@ -272,17 +298,53 @@ namespace Prism
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
UUID entityId = entity.GetUUID();
|
||||
ImGui::Text(entity.GetComponent<TagComponent>().Tag.c_str());
|
||||
ImGui::SetDragDropPayload("scene_entity_hierarchy", &entityId, sizeof(UUID));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget())
|
||||
{
|
||||
const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("scene_entity_hierarchy", ImGuiDragDropFlags_AcceptNoDrawDefaultRect);
|
||||
|
||||
if (payload)
|
||||
{
|
||||
UUID droppedHandle = *static_cast<UUID*>(payload->Data);
|
||||
Entity e = m_Context->FindEntityByUUID(droppedHandle);
|
||||
|
||||
// Remove from previous parent
|
||||
Entity previousParent = m_Context->FindEntityByUUID(e.GetParentUUID());
|
||||
if (previousParent)
|
||||
{
|
||||
auto& parentChildren = previousParent.Children();
|
||||
parentChildren.erase(std::remove(parentChildren.begin(), parentChildren.end(), droppedHandle), parentChildren.end());
|
||||
}
|
||||
|
||||
e.SetParentUUID(entity.GetUUID());
|
||||
auto& children = entity.Children();
|
||||
children.push_back(droppedHandle);
|
||||
|
||||
PM_CORE_INFO("Dropping Entity {0} on {1}", (uint64_t)droppedHandle, (uint64_t)entity.GetUUID());
|
||||
}
|
||||
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
if (opened)
|
||||
{
|
||||
// TODO: children
|
||||
/*
|
||||
if (entity.HasComponent<MeshComponent>())
|
||||
|
||||
for (const auto& child : entity.Children())
|
||||
{
|
||||
auto mesh = entity.GetComponent<MeshComponent>().Mesh;
|
||||
// if (mesh)
|
||||
// DrawMeshNode(mesh);
|
||||
const Entity e = m_Context->FindEntityByUUID(child);
|
||||
if (e)
|
||||
DrawEntityNode(e);
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
@ -185,15 +185,18 @@ namespace Prism
|
||||
{
|
||||
physx::PxPhysics& physics = PhysicsWrappers::GetPhysics();
|
||||
|
||||
Ref<Scene> scene = Scene::GetScene(m_Entity.GetSceneUUID());
|
||||
glm::mat4 transform = scene->GetTransformRelativeToParent(m_Entity);
|
||||
|
||||
if (m_RigidBody.BodyType == RigidBodyComponent::Type::Static)
|
||||
{
|
||||
m_ActorInternal = physics.createRigidStatic(ToPhysXTransform(m_Entity.Transform()));
|
||||
m_ActorInternal = physics.createRigidStatic(ToPhysXTransform(transform));
|
||||
}
|
||||
else
|
||||
{
|
||||
const PhysicsSettings& settings = Physics3D::GetSettings();
|
||||
|
||||
physx::PxRigidDynamic* actor = physics.createRigidDynamic(ToPhysXTransform(m_Entity.Transform()));
|
||||
physx::PxRigidDynamic* actor = physics.createRigidDynamic(ToPhysXTransform(transform));
|
||||
actor->setLinearDamping(m_RigidBody.LinearDrag);
|
||||
actor->setAngularDamping(m_RigidBody.AngularDrag);
|
||||
actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, m_RigidBody.IsKinematic);
|
||||
@ -249,7 +252,8 @@ namespace Prism
|
||||
else
|
||||
{
|
||||
// Synchronize Physics Actor with static Entity
|
||||
m_ActorInternal->setGlobalPose(ToPhysXTransform(m_Entity.Transform()));
|
||||
Ref<Scene> scene = Scene::GetScene(m_Entity.GetSceneUUID());
|
||||
m_ActorInternal->setGlobalPose(ToPhysXTransform(scene->GetTransformRelativeToParent(m_Entity)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -114,6 +114,7 @@ namespace Prism
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
//glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
|
||||
@ -262,6 +262,7 @@ namespace Prism
|
||||
if (aiMaterialName.Empty()) aiMaterialName = "Material_" + std::to_string(i);
|
||||
|
||||
auto mi = Ref<MaterialInstance>::Create(m_BaseMaterial, aiMaterialName.data);
|
||||
mi->SetFlag(MaterialFlag::TwoSided, false);
|
||||
m_Materials[i] = mi;
|
||||
|
||||
PM_MESH_LOG(" {0} (Index = {1})", aiMaterialName.data, i);
|
||||
|
||||
@ -28,6 +28,24 @@ namespace Prism
|
||||
UUID ID = 0;
|
||||
};
|
||||
|
||||
struct ParentComponent
|
||||
{
|
||||
UUID ParentHandle = 0;
|
||||
|
||||
ParentComponent() = default;
|
||||
ParentComponent(const ParentComponent& other) = default;
|
||||
ParentComponent(const UUID& parent)
|
||||
: ParentHandle(parent) {}
|
||||
};
|
||||
|
||||
struct ChildrenComponent
|
||||
{
|
||||
std::vector<UUID> Children;
|
||||
|
||||
ChildrenComponent() = default;
|
||||
ChildrenComponent(const ChildrenComponent& other) = default;
|
||||
};
|
||||
|
||||
struct TagComponent
|
||||
{
|
||||
std::string Tag;
|
||||
@ -49,6 +67,10 @@ namespace Prism
|
||||
glm::vec3 Rotation = { 0.0f, 0.0f, 0.0f };
|
||||
glm::vec3 Scale = { 1.0f, 1.0f, 1.0f };
|
||||
|
||||
glm::vec3 Up = { 0.0f, 1.0f, 0.0f };
|
||||
glm::vec3 Right = { 1.0f, 0.0f, 0.0f };
|
||||
glm::vec3 Forward = {0.0f, 0.0f, -1.0f};
|
||||
|
||||
TransformComponent() = default;
|
||||
TransformComponent(const TransformComponent& other) = default;
|
||||
TransformComponent(const glm::vec3& translation)
|
||||
|
||||
@ -67,6 +67,10 @@ namespace Prism
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void SetParentUUID(const UUID& parent) { GetComponent<ParentComponent>().ParentHandle = parent; }
|
||||
UUID GetParentUUID() { return GetComponent<ParentComponent>().ParentHandle; }
|
||||
std::vector<UUID>& Children() { return GetComponent<ChildrenComponent>().Children; }
|
||||
|
||||
UUID GetUUID() { return GetComponent<IDComponent>().ID; }
|
||||
UUID GetSceneUUID() const { return m_Scene->GetUUID(); }
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <PxPhysicsAPI.h>
|
||||
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -189,6 +190,27 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
// update transformComponent internal direction
|
||||
{
|
||||
const auto view = m_Registry.view<TransformComponent>();
|
||||
for (const auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& transformComponent = e.GetComponent<TransformComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||
glm::vec3 translation;
|
||||
glm::vec3 rotation;
|
||||
glm::vec3 scale;
|
||||
Math::DecomposeTransform(transform, translation, rotation, scale);
|
||||
|
||||
auto rotationQuat = glm::quat(rotation);
|
||||
transformComponent.Up = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||
transformComponent.Right = glm::normalize(glm::rotate(rotationQuat, glm::vec3(1.0f, 0.0f, 0.0f)));
|
||||
transformComponent.Forward = glm::normalize(glm::rotate(rotationQuat, glm::vec3(0.0f, 0.0f, -1.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Physics3D::Simulate(ts);
|
||||
|
||||
// Update all entities
|
||||
@ -212,7 +234,7 @@ namespace Prism
|
||||
if (!cameraEntity)
|
||||
return;
|
||||
|
||||
const glm::mat4 cameraViewMatrix = glm::inverse(cameraEntity.Transform().GetTransform());
|
||||
const glm::mat4 cameraViewMatrix = glm::inverse(GetTransformRelativeToParent(cameraEntity));
|
||||
PM_CORE_ASSERT(cameraEntity, "Scene does not contain any cameras!");
|
||||
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
||||
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
||||
@ -261,8 +283,10 @@ namespace Prism
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
SceneRenderer::SubmitMesh(meshComponent, transformComponent.GetTransform(), nullptr);
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
}
|
||||
}
|
||||
SceneRenderer::EndScene();
|
||||
@ -338,11 +362,13 @@ namespace Prism
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity{ entity, this });
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transformComponent.GetTransform());
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform);
|
||||
else
|
||||
SceneRenderer::SubmitMesh(meshComponent, transformComponent.GetTransform());
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,9 +378,10 @@ namespace Prism
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<BoxColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>().GetTransform());
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,9 +391,10 @@ namespace Prism
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<SphereColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>().GetTransform());
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,9 +404,10 @@ namespace Prism
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<CapsuleColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>().GetTransform());
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,11 +417,10 @@ namespace Prism
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<MeshColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
{
|
||||
SceneRenderer::SubmitColliderMesh(collider, e.GetComponent<TransformComponent>().GetTransform());
|
||||
}
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,6 +618,9 @@ namespace Prism
|
||||
idComponent.ID = {};
|
||||
|
||||
entity.AddComponent<TransformComponent>();
|
||||
entity.AddComponent<ParentComponent>();
|
||||
entity.AddComponent<ChildrenComponent>();
|
||||
|
||||
if (!name.empty())
|
||||
entity.AddComponent<TagComponent>(name);
|
||||
|
||||
@ -604,6 +635,9 @@ namespace Prism
|
||||
idComponent.ID = uuid;
|
||||
|
||||
entity.AddComponent<TransformComponent>();
|
||||
entity.AddComponent<ParentComponent>();
|
||||
entity.AddComponent<ChildrenComponent>();
|
||||
|
||||
if (!name.empty())
|
||||
entity.AddComponent<TagComponent>(name);
|
||||
|
||||
@ -646,6 +680,11 @@ namespace Prism
|
||||
newEntity = CreateEntity();
|
||||
|
||||
CopyComponentIfExists<TransformComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
|
||||
// TODO: should copy parent
|
||||
CopyComponentIfExists<ParentComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<ChildrenComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
|
||||
CopyComponentIfExists<MeshComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<DirectionalLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
CopyComponentIfExists<SkyLightComponent>(newEntity.m_EntityHandle, entity.m_EntityHandle, m_Registry);
|
||||
@ -676,6 +715,31 @@ namespace Prism
|
||||
return Entity{};
|
||||
}
|
||||
|
||||
Entity Scene::FindEntityByUUID(UUID uuid)
|
||||
{
|
||||
|
||||
auto view = m_Registry.view<IDComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& idComponent = m_Registry.get<IDComponent>(entity);
|
||||
if (idComponent.ID == uuid)
|
||||
return {entity, this};
|
||||
}
|
||||
|
||||
return Entity{};
|
||||
}
|
||||
|
||||
glm::mat4 Scene::GetTransformRelativeToParent(Entity entity)
|
||||
{
|
||||
glm::mat4 transform(1.0f);
|
||||
|
||||
const Entity parent = FindEntityByUUID(entity.GetParentUUID());
|
||||
if (parent)
|
||||
transform = GetTransformRelativeToParent(parent);
|
||||
|
||||
return transform * entity.Transform().GetTransform();
|
||||
}
|
||||
|
||||
void Scene::CopyTo(Ref<Scene>& target)
|
||||
{
|
||||
target->m_Light = m_Light;
|
||||
@ -697,6 +761,10 @@ namespace Prism
|
||||
|
||||
CopyComponent<TagComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<TransformComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
CopyComponent<ParentComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<ChildrenComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
CopyComponent<MeshComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<DirectionalLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
CopyComponent<SkyLightComponent>(target->m_Registry, m_Registry, enttMap);
|
||||
|
||||
@ -90,6 +90,9 @@ namespace Prism
|
||||
}
|
||||
|
||||
Entity FindEntityByTag(const std::string& tag);
|
||||
Entity FindEntityByUUID(UUID uuid);
|
||||
|
||||
glm::mat4 GetTransformRelativeToParent(Entity entity);
|
||||
|
||||
const EntityMap& GetEntityMap() const { return m_EntityIDMap; }
|
||||
void CopyTo(Ref<Scene>& target);
|
||||
|
||||
@ -160,12 +160,33 @@ namespace Prism
|
||||
out << YAML::Key << "Entity";
|
||||
out << YAML::Value << uuid;
|
||||
|
||||
if (entity.HasComponent<ParentComponent>())
|
||||
{
|
||||
auto& parent = entity.GetComponent<ParentComponent>();
|
||||
out << YAML::Key << "Parent" << YAML::Value << parent.ParentHandle;
|
||||
}
|
||||
|
||||
if (entity.HasComponent<ChildrenComponent>())
|
||||
{
|
||||
const auto& childrenComponent = entity.GetComponent<ChildrenComponent>();
|
||||
out << YAML::Key << "Children";
|
||||
out << YAML::Value << YAML::BeginSeq;
|
||||
|
||||
for (auto child : childrenComponent.Children)
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "Handle" << YAML::Value << child;
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
out << YAML::EndSeq;
|
||||
}
|
||||
|
||||
if (entity.HasComponent<TagComponent>())
|
||||
{
|
||||
out << YAML::Key << "TagComponent";
|
||||
out << YAML::BeginMap; // TagComponent
|
||||
|
||||
auto& tag = entity.GetComponent<TagComponent>().Tag;
|
||||
const auto& tag = entity.GetComponent<TagComponent>().Tag;
|
||||
out << YAML::Key << "Tag" << YAML::Value << tag;
|
||||
|
||||
out << YAML::EndMap; // TagComponent
|
||||
@ -176,7 +197,7 @@ namespace Prism
|
||||
out << YAML::Key << "TransformComponent";
|
||||
out << YAML::BeginMap; // TransformComponent
|
||||
|
||||
auto& transform = entity.GetComponent<TransformComponent>();
|
||||
const auto& transform = entity.GetComponent<TransformComponent>();
|
||||
out << YAML::Key << "Position" << YAML::Value << transform.Translation;
|
||||
out << YAML::Key << "Rotation" << YAML::Value << transform.Rotation;
|
||||
out << YAML::Key << "Scale" << YAML::Value << transform.Scale;
|
||||
@ -573,6 +594,20 @@ namespace Prism
|
||||
|
||||
Entity deserializedEntity = m_Scene->CreateEntityWithID(uuid, name);
|
||||
|
||||
|
||||
uint64_t parentHandle = entity["Parent"] ? entity["Parent"].as<uint64_t>() : 0;
|
||||
deserializedEntity.GetComponent<ParentComponent>().ParentHandle = parentHandle;
|
||||
|
||||
const auto children = entity["Children"];
|
||||
if (children)
|
||||
{
|
||||
for (auto child : children)
|
||||
{
|
||||
auto childHandle = child["Handle"].as<uint64_t>();
|
||||
deserializedEntity.GetComponent<ChildrenComponent>().Children.emplace_back(childHandle);
|
||||
}
|
||||
}
|
||||
|
||||
auto transformComponent = entity["TransformComponent"];
|
||||
if (transformComponent)
|
||||
{
|
||||
@ -605,20 +640,20 @@ namespace Prism
|
||||
auto scriptComponent = entity["ScriptComponent"];
|
||||
if (scriptComponent)
|
||||
{
|
||||
std::string moduleName = scriptComponent["ModuleName"].as<std::string>();
|
||||
const auto moduleName = scriptComponent["ModuleName"].as<std::string>();
|
||||
deserializedEntity.AddComponent<ScriptComponent>(moduleName);
|
||||
|
||||
PM_CORE_INFO(" Script Module: {0}", moduleName);
|
||||
|
||||
if (ScriptEngine::ModuleExists(moduleName))
|
||||
{
|
||||
auto storedFields = scriptComponent["StoredFields"];
|
||||
const auto storedFields = scriptComponent["StoredFields"];
|
||||
if (storedFields)
|
||||
{
|
||||
for (auto field : storedFields)
|
||||
{
|
||||
auto name = field["Name"].as<std::string>();
|
||||
auto type = (FieldType)field["Type"].as<uint32_t>();
|
||||
auto type = static_cast<FieldType>(field["Type"].as<uint32_t>());
|
||||
EntityInstanceData& data = ScriptEngine::GetEntityInstanceData(m_Scene->GetUUID(), uuid);
|
||||
auto& moduleFieldMap = data.ModuleFieldMap;
|
||||
auto& publicFields = moduleFieldMap[moduleName];
|
||||
|
||||
@ -322,52 +322,8 @@ namespace Prism { namespace Script {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void Prism_TransformComponent_GetRelativeDirection(const uint64_t entityID, glm::vec3* outDirection, const glm::vec3* inAbsoluteDirection)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
const auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
|
||||
auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transformation);
|
||||
*outDirection = glm::rotate(rotation, *inAbsoluteDirection);
|
||||
}
|
||||
|
||||
void Prism_TransformComponent_GetRotation(const uint64_t entityID, glm::vec3* outRotation)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
const auto& transformComponent = entity.GetComponent<TransformComponent>();
|
||||
|
||||
auto [position, rotation, scale] = GetTransformDecomposition(transformComponent.Transformation);
|
||||
*outRotation = glm::degrees(glm::eulerAngles(rotation));
|
||||
}
|
||||
|
||||
void Prism_TransformComponent_SetRotation(const uint64_t entityID, const glm::vec3* inRotation)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
auto& transform = entity.Transformation();
|
||||
|
||||
auto [position, rotation, scale] = GetTransformDecomposition(transform);
|
||||
transform = glm::translate(glm::mat4(1.0f), position) *
|
||||
glm::toMat4(glm::quat(glm::radians(*inRotation))) *
|
||||
glm::scale(glm::mat4(1.0f), scale);
|
||||
}
|
||||
*/
|
||||
|
||||
void Prism_TransformComponent_GetTransform(const uint64_t entityID, ScriptTransform* outTransform)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
@ -406,6 +362,32 @@ namespace Prism { namespace Script {
|
||||
transform.Rotation = glm::radians(inTransform->Rotation);
|
||||
transform.Scale = inTransform->Scale;
|
||||
}
|
||||
*/
|
||||
|
||||
void Prism_TransformComponent_GetTransform(const uint64_t entityID, TransformComponent* outTransform)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
*outTransform = entity.GetComponent<TransformComponent>();
|
||||
outTransform->Rotation = glm::degrees(outTransform->Rotation);
|
||||
}
|
||||
|
||||
void Prism_TransformComponent_SetTransform(const uint64_t entityID, const TransformComponent* inTransform)
|
||||
{
|
||||
Ref<Scene> scene = ScriptEngine::GetCurrentSceneContext();
|
||||
PM_CORE_ASSERT(scene, "No active scene!");
|
||||
const auto& entityMap = scene->GetEntityMap();
|
||||
PM_CORE_ASSERT(entityMap.find(entityID) != entityMap.end(), "Invalid entity ID or entity doesn't exist in scene!");
|
||||
|
||||
Entity entity = entityMap.at(entityID);
|
||||
|
||||
auto& transform = entity.GetComponent<TransformComponent>() = *inTransform;
|
||||
transform.Rotation = glm::radians(transform.Rotation);
|
||||
}
|
||||
|
||||
/*
|
||||
void Prism_TransformComponent_GetTransform(const uint64_t entityID, TransformComponent* outTransform)
|
||||
|
||||
@ -16,6 +16,7 @@ extern "C" {
|
||||
|
||||
namespace Prism { namespace Script {
|
||||
|
||||
/*
|
||||
struct ScriptTransform
|
||||
{
|
||||
glm::vec3 Translation;
|
||||
@ -23,6 +24,7 @@ namespace Prism { namespace Script {
|
||||
glm::vec3 Scale;
|
||||
glm::vec3 Up, Right, Forward;
|
||||
};
|
||||
*/
|
||||
|
||||
// Math
|
||||
float Prism_Noise_PerlinNoise(float x, float y);
|
||||
@ -57,8 +59,8 @@ namespace Prism { namespace Script {
|
||||
void Prism_TransformComponent_GetRotation(uint64_t entityID,glm::vec3* outRotation);
|
||||
void Prism_TransformComponent_SetRotation(uint64_t entityID,const glm::vec3* inRotation);
|
||||
*/
|
||||
void Prism_TransformComponent_GetTransform(uint64_t entityID, ScriptTransform* outTransform);
|
||||
void Prism_TransformComponent_SetTransform(uint64_t entityID, const ScriptTransform* inTransform);
|
||||
void Prism_TransformComponent_GetTransform(uint64_t entityID, TransformComponent* outTransform);
|
||||
void Prism_TransformComponent_SetTransform(uint64_t entityID, const TransformComponent* inTransform);
|
||||
void Prism_TransformComponent_GetTranslation(uint64_t entityID, glm::vec3* outTranslation);
|
||||
void Prism_TransformComponent_SetTranslation(uint64_t entityID, const glm::vec3* inTranslation);
|
||||
void Prism_TransformComponent_GetRotation(uint64_t entityID, glm::vec3* outRotation);
|
||||
|
||||
264
Prism/src/Prism/Utilities/AssetsManager.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#include "AssetsManager.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
void AssetTypes::Init()
|
||||
{
|
||||
s_Types["scene"] = AssetType::Scene;
|
||||
s_Types["fbx"] = AssetType::Mesh;
|
||||
s_Types["obj"] = AssetType::Mesh;
|
||||
s_Types["png"] = AssetType::Image;
|
||||
s_Types["blend"] = AssetType::Mesh;
|
||||
s_Types["wav"] = AssetType::Audio;
|
||||
s_Types["ogg"] = AssetType::Audio;
|
||||
s_Types["cs"] = AssetType::Script;
|
||||
}
|
||||
|
||||
size_t AssetTypes::GetAssetTypeID(const std::string& extension)
|
||||
{
|
||||
for (const auto& kv : s_Types)
|
||||
{
|
||||
if (kv.first == extension)
|
||||
return std::hash<std::string>()(extension);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
AssetType AssetTypes::GetAssetTypeFromExtension(const std::string& extension)
|
||||
{
|
||||
return s_Types.find(extension) != s_Types.end() ? s_Types[extension] : AssetType::Other;
|
||||
}
|
||||
|
||||
std::map<std::string, AssetType> AssetTypes::s_Types;
|
||||
|
||||
AssetsManager::AssetsManager()
|
||||
{
|
||||
}
|
||||
|
||||
std::string AssetsManager::ParseFilename(const std::string& filepath, const char& delim)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
size_t start;
|
||||
size_t end = 0;
|
||||
|
||||
while ((start = filepath.find_first_not_of(delim, end)) != std::string::npos)
|
||||
{
|
||||
end = filepath.find(delim, start);
|
||||
out.push_back(filepath.substr(start, end - start));
|
||||
}
|
||||
|
||||
return out[out.size() - 1];
|
||||
}
|
||||
|
||||
std::string AssetsManager::ParseFileType(const std::string& filename)
|
||||
{
|
||||
size_t start;
|
||||
size_t end = 0;
|
||||
std::vector<std::string> out;
|
||||
|
||||
while ((start = filename.find_first_not_of('.', end)) != std::string::npos)
|
||||
{
|
||||
end = filename.find('.', start);
|
||||
out.push_back(filename.substr(start, end - start));
|
||||
}
|
||||
|
||||
return out[out.size() - 1];
|
||||
}
|
||||
|
||||
void AssetsManager::HandleAsset(const std::string& filepath)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetsManager::ProcessAsset(const std::string& assetType)
|
||||
{
|
||||
std::string filename = ParseFilename(assetType, '/\\');
|
||||
const std::string filetype = ParseFileType(assetType);
|
||||
|
||||
if (filetype == "blend")
|
||||
{
|
||||
// TODO: this actually unuse now
|
||||
ConvertAsset(assetType, "fbx");
|
||||
}
|
||||
}
|
||||
|
||||
void AssetsManager::ConvertAsset(const std::string& assetPath, const std::string& conversionType)
|
||||
{
|
||||
// Create a filestream to write a blender python script for conversion of the asset
|
||||
// The 'bpy.ops.export_scene.(asset-type-to-convert) function runs blender in background and exports the file'
|
||||
std::string path = std::filesystem::temp_directory_path().string();
|
||||
std::ofstream fileStream(path + "export.py");
|
||||
|
||||
// Importing the python modules required for the export to work out
|
||||
fileStream << "import bpy\n";
|
||||
fileStream << "import sys\n";
|
||||
|
||||
if (conversionType == "fbx")
|
||||
fileStream << "bpy.ops.export_scene.fbx(filepath=r'" + path + "asset.fbx" + "', axis_forward='-Z', axis_up='Y')\n";
|
||||
|
||||
if (conversionType == "obj")
|
||||
fileStream << "bpy.ops.export_scene.obj(filepath=r'" + path + "asset.obj" + "', axis_forward='-Z', axis_up='Y')\n";
|
||||
|
||||
fileStream.close();
|
||||
|
||||
// This section involves creating the command to export the .blend file to the required asset type
|
||||
// The command goes something like this
|
||||
// blender.exe path\to\files\cube.blend --background --python path\to\file\export.py
|
||||
|
||||
std::string blender_base_path = R"(D:\Application\Blender5.0.1\blender.exe)";
|
||||
std::string p_asset_path = '"' + assetPath + '"';
|
||||
std::string p_blender_path = '"' + blender_base_path + '"';
|
||||
std::string p_script_path = '"' + path + "export.py" + '"';
|
||||
|
||||
// Creating the actual command that will execute
|
||||
std::string convCommand = '"' + p_blender_path + " " + p_asset_path + " --background --python " + p_script_path + "" + '"';
|
||||
|
||||
// Just for debugging(it took me 1hr for this string literals n stuff! It better work!)
|
||||
PM_CORE_INFO("{0}", convCommand);
|
||||
|
||||
// Fire the above created command
|
||||
|
||||
// TODO: Platform Abstraction!
|
||||
system(convCommand.c_str());
|
||||
}
|
||||
|
||||
std::vector<DirectoryInfo> AssetsManager::GetFileSystemContents()
|
||||
{
|
||||
const std::string path = "assets";
|
||||
std::vector<DirectoryInfo> directories;
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(path))
|
||||
{
|
||||
const bool isDir = std::filesystem::is_directory(entry);
|
||||
|
||||
std::string dir_data = ParseFilename(entry.path().string(), '/\\');
|
||||
std::string fileExt = ParseFileType(dir_data);
|
||||
directories.emplace_back(dir_data, fileExt, entry.path().string(), !isDir);
|
||||
}
|
||||
|
||||
return directories;
|
||||
}
|
||||
|
||||
std::vector<DirectoryInfo> AssetsManager::GetDirectoryContents(const std::string& filepath, bool recursive)
|
||||
{
|
||||
std::vector<DirectoryInfo> directories;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(filepath))
|
||||
{
|
||||
const bool isDir = std::filesystem::is_directory(entry);
|
||||
std::string dir_data = ParseFilename(entry.path().string(), '/\\');
|
||||
directories.emplace_back(dir_data, ".scene", entry.path().string(), !isDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& entry : std::filesystem::directory_iterator(filepath))
|
||||
{
|
||||
const bool isDir = std::filesystem::is_directory(entry);
|
||||
std::string dir_data = ParseFilename(entry.path().string(), '/\\');
|
||||
std::string fileExt = ParseFileType(dir_data);
|
||||
directories.emplace_back(dir_data, fileExt, entry.path().string(), !isDir);
|
||||
}
|
||||
}
|
||||
|
||||
return directories;
|
||||
}
|
||||
|
||||
std::vector<DirectoryInfo> AssetsManager::SearchFiles(const std::string& query, const std::string& searchPath)
|
||||
{
|
||||
std::vector<DirectoryInfo> result;
|
||||
|
||||
if (!searchPath.empty())
|
||||
{
|
||||
std::vector<DirectoryInfo> contents = GetDirectoryContents(searchPath, true);
|
||||
|
||||
for (auto& entry : contents)
|
||||
{
|
||||
if (entry.Filename.find(query) != std::string::npos)
|
||||
result.emplace_back(std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string AssetsManager::GetParentPath(const std::string& path)
|
||||
{
|
||||
return std::filesystem::path(path).parent_path().string();
|
||||
}
|
||||
|
||||
std::vector<std::string> AssetsManager::GetDirectories(const std::string& filepath)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
size_t start;
|
||||
size_t end = 0;
|
||||
|
||||
while ((start = filepath.find_first_not_of("/\\", end)) != std::string::npos)
|
||||
{
|
||||
end = filepath.find("/\\", start);
|
||||
result.push_back(filepath.substr(start, end - start));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AssetsManager::MoveFile(const std::filesystem::path& originalPath, const std::filesystem::path& dest)
|
||||
{
|
||||
// TODO: fixeme: MoveFile cannot work
|
||||
try
|
||||
{
|
||||
std::filesystem::rename(originalPath, dest);
|
||||
const std::string newPath = dest.string() + "/" + ParseFilename(originalPath.string(), '/\\');
|
||||
return std::filesystem::exists(newPath);
|
||||
}catch (const std::exception& e)
|
||||
{
|
||||
PM_CORE_ERROR("Move File error: {0}", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string AssetsManager::StripExtras(const std::string& filename)
|
||||
{
|
||||
std::vector<std::string> out;
|
||||
size_t start;
|
||||
size_t end = 0;
|
||||
|
||||
while ((start = filename.find_first_not_of('.', end)) != std::string::npos)
|
||||
{
|
||||
end = filename.find('.', start);
|
||||
out.push_back(filename.substr(start, end - start));
|
||||
}
|
||||
|
||||
if (out[0].length() >= 10)
|
||||
{
|
||||
auto cutFilename = out[0].substr(0, 9) + "...";
|
||||
return cutFilename;
|
||||
}
|
||||
|
||||
const auto filenameLength = out[0].length();
|
||||
const auto paddingToAdd = 9 - filenameLength;
|
||||
|
||||
std::string newFileName;
|
||||
|
||||
for (int i = 0; i <= paddingToAdd; i++)
|
||||
{
|
||||
newFileName += " ";
|
||||
}
|
||||
|
||||
newFileName += out[0];
|
||||
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
void AssetsManager::ImportAsset(const std::string& assetPath, const std::string& assetName)
|
||||
{
|
||||
}
|
||||
}
|
||||
94
Prism/src/Prism/Utilities/AssetsManager.h
Normal file
@ -0,0 +1,94 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#ifndef PRISM_ASSETSMANAGER_H
|
||||
#define PRISM_ASSETSMANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class AssetType
|
||||
{
|
||||
Scene, Mesh, Image, Audio, Script, Other
|
||||
};
|
||||
|
||||
class AssetTypes
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static size_t GetAssetTypeID(const std::string& extension);
|
||||
static AssetType GetAssetTypeFromExtension(const std::string& extension);
|
||||
|
||||
private:
|
||||
static std::map<std::string, AssetType> s_Types;
|
||||
};
|
||||
|
||||
struct DirectoryInfo
|
||||
{
|
||||
std::string Filename;
|
||||
std::string FileType;
|
||||
std::string AbsolutePath;
|
||||
bool IsFile;
|
||||
|
||||
DirectoryInfo(std::string filename, std::string fileType, std::string absolutePath, const bool isFile)
|
||||
: Filename(std::move(filename)), FileType(std::move(fileType)), AbsolutePath(std::move(absolutePath)), IsFile(isFile)
|
||||
{
|
||||
}
|
||||
|
||||
DirectoryInfo(const DirectoryInfo& other)
|
||||
: Filename(other.Filename), FileType(other.FileType), AbsolutePath(other.AbsolutePath), IsFile(other.IsFile)
|
||||
{
|
||||
}
|
||||
|
||||
DirectoryInfo(DirectoryInfo&& other)
|
||||
: Filename(std::move(other.Filename)), FileType(std::move(other.FileType)), AbsolutePath(std::move(other.AbsolutePath)), IsFile(other.IsFile)
|
||||
{
|
||||
}
|
||||
|
||||
DirectoryInfo& operator=(const DirectoryInfo& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Filename = other.Filename;
|
||||
FileType = other.FileType;
|
||||
AbsolutePath = other.AbsolutePath;
|
||||
IsFile = other.IsFile;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class PRISM_API AssetsManager
|
||||
{
|
||||
public:
|
||||
AssetsManager();
|
||||
|
||||
std::string ParseFilename(const std::string& filepath, const char& delim);
|
||||
std::string ParseFileType(const std::string& filename);
|
||||
|
||||
void HandleAsset(const std::string& filepath);
|
||||
void ProcessAsset(const std::string& assetType);
|
||||
void ConvertAsset(const std::string& assetPath, const std::string& conversionType);
|
||||
|
||||
std::vector<DirectoryInfo> GetFileSystemContents();
|
||||
std::vector<DirectoryInfo> GetDirectoryContents(const std::string& filepath, bool recursive = false);
|
||||
std::vector<DirectoryInfo> SearchFiles(const std::string& query, const std::string& searchPath);
|
||||
|
||||
std::string GetParentPath(const std::string& path);
|
||||
|
||||
std::vector<std::string> GetDirectories(const std::string& filepath);
|
||||
|
||||
bool MoveFile(const std::filesystem::path& originalPath, const std::filesystem::path& dest);
|
||||
|
||||
std::string StripExtras(const std::string& filename);
|
||||
|
||||
private:
|
||||
void ImportAsset(const std::string& assetPath, const std::string& assetName);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_ASSETSMANAGER_H
|
||||
24
Prism/src/Prism/Utilities/DragDropData.h
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/1/20.
|
||||
//
|
||||
|
||||
#ifndef PRISM_DRAGDROPDATA_H
|
||||
#define PRISM_DRAGDROPDATA_H
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct DragDropData
|
||||
{
|
||||
public:
|
||||
const char* Type;
|
||||
const char* SourcePath;
|
||||
const char* Name;
|
||||
|
||||
DragDropData(const char* type, const char* sourcePath, const char* name)
|
||||
: Type(type), SourcePath(sourcePath), Name(name)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PRISM_DRAGDROPDATA_H
|
||||