Add Editor Features - Transform Gizmo #105
|
@ -22,6 +22,7 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "Serialization/SHSerialization.h"
|
#include "Serialization/SHSerialization.h"
|
||||||
|
#include "Tools/SHClipboardUtilities.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -80,6 +81,8 @@ namespace SHADE
|
||||||
|
|
||||||
void SHHierarchyPanel::SetScrollTo(EntityID eid)
|
void SHHierarchyPanel::SetScrollTo(EntityID eid)
|
||||||
{
|
{
|
||||||
|
if(eid == MAX_EID)
|
||||||
|
return;
|
||||||
scrollTo = eid;
|
scrollTo = eid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +188,15 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable("Copy"))
|
if(ImGui::Selectable("Copy"))
|
||||||
{
|
{
|
||||||
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
|
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(editor->selectedEntities));
|
||||||
|
}
|
||||||
|
if(ImGui::Selectable("Paste"))
|
||||||
|
{
|
||||||
|
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard()));
|
||||||
|
}
|
||||||
|
if(ImGui::Selectable("Paste as Child"))
|
||||||
|
{
|
||||||
|
SetScrollTo(SHSerialization::DeserializeEntitiesFromString(SHClipboardUtilities::GetDataFromClipboard(), eid));
|
||||||
}
|
}
|
||||||
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,11 +52,13 @@ namespace SHADE
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
|
static EntityID DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
|
||||||
{
|
{
|
||||||
if (!node[EIDNode])
|
EntityID eid = MAX_EID;
|
||||||
return;
|
if(!node)
|
||||||
EntityID eid = node[EIDNode].as<EntityID>();
|
return eid;
|
||||||
|
if (node[EIDNode])
|
||||||
|
eid = node[EIDNode].as<EntityID>();
|
||||||
std::string name = "Default";
|
std::string name = "Default";
|
||||||
if (node[EntityNameNode])
|
if (node[EntityNameNode])
|
||||||
name = node[EntityNameNode].as<std::string>();
|
name = node[EntityNameNode].as<std::string>();
|
||||||
|
@ -77,6 +79,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return eid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
|
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
|
||||||
|
@ -111,7 +114,11 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
DeserializeEntity(it, (*it), createdEntities);
|
DeserializeEntity(it, (*it), createdEntities);
|
||||||
}
|
}
|
||||||
|
if(createdEntities.empty())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Failed to create entities from deserializaiton")
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Initialize Entity
|
//Initialize Entity
|
||||||
auto entityVecIt = createdEntities.begin();
|
auto entityVecIt = createdEntities.begin();
|
||||||
for (auto it = entities.begin(); it != entities.end(); ++it)
|
for (auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
|
@ -130,17 +137,19 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities)
|
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept
|
||||||
{
|
{
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
YAML::Node node;
|
YAML::Node node;
|
||||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
out << YAML::BeginSeq;
|
||||||
for (auto const& eid : entities)
|
for (auto const& eid : entities)
|
||||||
{
|
{
|
||||||
auto entityNode = sceneGraph.GetNode(eid);
|
auto entityNode = sceneGraph.GetNode(eid);
|
||||||
EmitEntity(entityNode, out);
|
EmitEntity(entityNode, out);
|
||||||
}
|
}
|
||||||
return std::basic_string<char>(out.c_str());
|
out << YAML::EndSeq;
|
||||||
|
return std::string(out.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
|
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
|
||||||
|
@ -182,6 +191,30 @@ namespace SHADE
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityID SHSerialization::DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID) noexcept
|
||||||
|
{
|
||||||
|
if(data.empty())
|
||||||
|
return MAX_EID;
|
||||||
|
YAML::Node entities = YAML::Load(data.c_str());
|
||||||
|
EntityID eid{MAX_EID};
|
||||||
|
std::vector<EntityID> createdEntities;
|
||||||
|
for(auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
|
{
|
||||||
|
eid = DeserializeEntity(it, *it, createdEntities, parentEID);
|
||||||
|
}
|
||||||
|
if(createdEntities.empty())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Failed to create entities from deserializaiton")
|
||||||
|
return MAX_EID;
|
||||||
|
}
|
||||||
|
auto entityVecIt = createdEntities.begin();
|
||||||
|
for(auto it = entities.begin(); it != entities.end(); ++it)
|
||||||
|
{
|
||||||
|
InitializeEntity(*it, *entityVecIt++);
|
||||||
|
}
|
||||||
|
return eid;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
|
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,14 +28,18 @@ namespace SHADE
|
||||||
static void SerializeSceneToFile(std::filesystem::path const& path);
|
static void SerializeSceneToFile(std::filesystem::path const& path);
|
||||||
static std::string SerializeSceneToString();
|
static std::string SerializeSceneToString();
|
||||||
static void SerializeSceneToEmitter(YAML::Emitter& out);
|
static void SerializeSceneToEmitter(YAML::Emitter& out);
|
||||||
|
|
||||||
static void DeserializeSceneFromFile(std::filesystem::path const& path);
|
static void DeserializeSceneFromFile(std::filesystem::path const& path);
|
||||||
|
|
||||||
|
|
||||||
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
|
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
|
||||||
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities);
|
|
||||||
|
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities) noexcept;
|
||||||
static void SerializeEntityToFile(std::filesystem::path const& path);
|
static void SerializeEntityToFile(std::filesystem::path const& path);
|
||||||
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
|
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
|
||||||
|
|
||||||
|
static EntityID DeserializeEntitiesFromString(std::string const& data, EntityID const& parentEID = MAX_EID) noexcept;
|
||||||
|
|
||||||
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
|
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
|
||||||
private:
|
private:
|
||||||
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
|
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHClipboardUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
void SHClipboardUtilities::WriteToClipboard(std::string const& str) noexcept
|
||||||
|
{
|
||||||
|
if(str.empty())
|
||||||
|
return;
|
||||||
|
HWND const hwnd = GetDesktopWindow();
|
||||||
|
OpenClipboard(hwnd);
|
||||||
|
EmptyClipboard();
|
||||||
|
|
||||||
|
auto const size = str.size() + 1;
|
||||||
|
const HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||||
|
if(hGlobal)
|
||||||
|
{
|
||||||
|
std::memcpy(GlobalLock(hGlobal), str.c_str(), size);
|
||||||
|
GlobalUnlock(hGlobal);
|
||||||
|
SetClipboardData(CF_TEXT, hGlobal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Failed to write to clipboard: {}", str.c_str())
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
GlobalFree(hGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string const SHClipboardUtilities::GetDataFromClipboard() noexcept
|
||||||
|
{
|
||||||
|
HWND const hwnd = GetDesktopWindow();
|
||||||
|
if(!OpenClipboard(hwnd))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("Failed to open clipboard")
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(HANDLE const dataHandle = GetClipboardData(CF_TEXT); dataHandle)
|
||||||
|
{
|
||||||
|
std::string data(static_cast<char*>(GlobalLock(dataHandle)));
|
||||||
|
GlobalUnlock(dataHandle);
|
||||||
|
CloseClipboard();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHClipboardUtilities
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void WriteToClipboard(std::string const& str) noexcept;
|
||||||
|
static std::string const GetDataFromClipboard() noexcept;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue