Merge remote-tracking branch 'origin/main' into SP3-2-Physics

This commit is contained in:
Diren D Bharwani 2022-10-01 01:13:13 +08:00
commit e956797441
38 changed files with 1806 additions and 420 deletions

View File

@ -42,6 +42,8 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Tools/SHLogger.h"
using namespace SHADE; using namespace SHADE;
namespace Sandbox namespace Sandbox
@ -97,6 +99,11 @@ namespace Sandbox
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
SHADE::SHAssetManager::LoadDataTemp("../../Assets/TD_Checker_Base_Color.dds"); SHADE::SHAssetManager::LoadDataTemp("../../Assets/TD_Checker_Base_Color.dds");
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
//TODO: REMOVE AFTER PRESENTATION //TODO: REMOVE AFTER PRESENTATION
//SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>(); //SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>();
@ -112,7 +119,9 @@ namespace Sandbox
#else #else
#endif #endif
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
} }

View File

@ -36,7 +36,6 @@ namespace Sandbox
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
// Create temp meshes // Create temp meshes
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
//graphicsSystem->BuildMeshBuffers();
//Test Racoon mesh //Test Racoon mesh
auto meshes = SHADE::SHAssetManager::GetAllMeshes(); auto meshes = SHADE::SHAssetManager::GetAllMeshes();
@ -45,7 +44,7 @@ namespace Sandbox
{ {
if (mesh.meshName == "Cube.012") if (mesh.meshName == "Cube.012")
{ {
handles.push_back(graphicsSystem->AddMesh( handles.push_back(graphicsSystem->AddMesh(
mesh.header.vertexCount, mesh.header.vertexCount,
mesh.vertexPosition.data(), mesh.vertexPosition.data(),
mesh.texCoords.data(), mesh.texCoords.data(),
@ -108,9 +107,9 @@ namespace Sandbox
stressTestObjects.emplace_back(entity); stressTestObjects.emplace_back(entity);
} }
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); auto raccoonSpin = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity); auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity); auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
renderable.Mesh = handles.front(); renderable.Mesh = handles.front();
renderable.SetMaterial(customMat); renderable.SetMaterial(customMat);
@ -138,7 +137,21 @@ namespace Sandbox
//testObjRenderable.SetMaterial(matInst); //testObjRenderable.SetMaterial(matInst);
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->AddScript(testObj, "TestScript"); scriptEngine->AddScript(raccoonSpin, "RaccoonSpin");
auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
renderableShowcase.Mesh = handles.front();
renderableShowcase.SetMaterial(customMat);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 1);
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
} }
void SBTestScene::Update(float dt) void SBTestScene::Update(float dt)

View File

@ -14,6 +14,7 @@
#include "SHpch.h" #include "SHpch.h"
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -117,4 +118,7 @@ namespace SHADE
}; };
template class SH_API SHFamilyID<SHComponent>;
} }

View File

@ -0,0 +1,12 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
namespace SHADE
{
struct SHComponentAddedEvent
{
EntityID eid;
ComponentTypeID addedComponentType;
};
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
namespace SHADE
{
struct SHComponentRemovedEvent
{
EntityID eid;
ComponentTypeID removedComponentType;
};
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "SHFamily.h"
#include "SHpch.h"
namespace SHADE
{
//initialize currentID as 0
}

View File

@ -14,16 +14,17 @@
#pragma once #pragma once
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
template<typename BaseClass> template<typename BaseClass>
class SHFamilyID class SH_API SHFamilyID
{ {
private: private:
//this is used to keep track of the new current ID to be assign to a new Derived class type.
static ComponentTypeID currentID;
/*!************************************************************************* /*!*************************************************************************
* \brief Construct a new SHFamilyID object * \brief Construct a new SHFamilyID object
@ -46,6 +47,9 @@ namespace SHADE
} }
public: public:
//this is used to keep track of the new current ID to be assign to a new Derived class type.
static inline ComponentTypeID currentID = 0;
/*!************************************************************************* /*!*************************************************************************
* \brief * \brief
* Checks if this identifier is cuurrently in use / valid. * Checks if this identifier is cuurrently in use / valid.
@ -59,7 +63,6 @@ namespace SHADE
{ {
return(id < currentID); return(id < currentID);
} }
/*!************************************************************************* /*!*************************************************************************
* \brief * \brief
* Get the ID of a derived class type. * Get the ID of a derived class type.
@ -68,16 +71,27 @@ namespace SHADE
* @tparam DerivedClass * @tparam DerivedClass
* The derived class type that we are trying to get the ID of. * The derived class type that we are trying to get the ID of.
***************************************************************************/ ***************************************************************************/
#ifdef SH_API_EXPORT
template<typename DerivedClass> template<typename DerivedClass>
static ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept
{ {
//The first time a new derived class type call this get id, it will initialize id using the currentID from familyID class. //The first time a new derived class type call this get id, it will initialize id using the currentID from familyID class.
static ComponentTypeID id = currentID++; static ComponentTypeID id = SHFamilyID<BaseClass>::currentID++;
return id; return id;
//return 0;
} }
#else
template<typename DerivedClass>
static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept;
#endif // SH_API_EXPORT
}; };
//initialize currentID as 0
template<typename BaseClass>
ComponentTypeID SHFamilyID<BaseClass>::currentID = 0;
} }

View File

@ -17,8 +17,11 @@
#include "../General/SHSparseSetContainer.h" #include "../General/SHSparseSetContainer.h"
#include "../Components/SHComponent.h" #include "../Components/SHComponent.h"
#include "../Components/SHComponentGroup.h" #include "../Components/SHComponentGroup.h"
#include "../Events/SHComponentAddedEvent.h"
#include "../Events/SHComponentRemovedEvent.h"
//#include "Scene/SHSceneNode.h" //#include "Scene/SHSceneNode.h"
#include "SH_API.h" #include "SH_API.h"
#include "Events/SHEventManager.hpp"
#include <cassert> #include <cassert>
@ -216,6 +219,11 @@ namespace SHADE
comp->OnCreate(); comp->OnCreate();
} }
SHComponentAddedEvent eventData;
eventData.eid = entityID;
eventData.addedComponentType = ComponentFamily::GetID<T>();
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
} }
/************************************************************************** /**************************************************************************
@ -247,6 +255,13 @@ namespace SHADE
{ {
comp->OnCreate(); comp->OnCreate();
} }
SHComponentAddedEvent eventData;
eventData.eid = entityID;
eventData.addedComponentType = componentTypeID;
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
} }
@ -313,6 +328,12 @@ namespace SHADE
componentSet.GetSparseSet<T>()->Remove(EntityHandleGenerator::GetIndex(entityID)); componentSet.GetSparseSet<T>()->Remove(EntityHandleGenerator::GetIndex(entityID));
SHComponentRemovedEvent eventData;
eventData.eid = entityID;
eventData.removedComponentType = ComponentFamily::GetID<T>();
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
} }
/*!************************************************************************* /*!*************************************************************************
@ -464,11 +485,6 @@ namespace SHADE
return componentGroups[index]; return componentGroups[index];
} }
static void AddScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
static void RemoveScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
};// end SHComponentManager };// end SHComponentManager

View File

@ -68,6 +68,9 @@ namespace SHADE
id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID;
} }
systemContainer.emplace(id, std::make_unique<T>()); systemContainer.emplace(id, std::make_unique<T>());
auto size = systemContainer.size();
systemContainer[id].get()->systemID = id; systemContainer[id].get()->systemID = id;
return id; return id;

View File

@ -26,4 +26,6 @@ const EntityIndex MAX_EID = 51000;
#define ENABLE_IF_UINT(_TYPE, _RETURN)\ #define ENABLE_IF_UINT(_TYPE, _RETURN)\
typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type
#endif #endif

View File

@ -12,6 +12,7 @@
#include "../SHECSMacros.h" #include "../SHECSMacros.h"
#include "SH_API.h" #include "SH_API.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -69,5 +70,9 @@ namespace SHADE
}; };
template class SH_API SHFamilyID<SHSystem>;
} }

View File

@ -46,7 +46,7 @@ namespace SHADE
if (!component) if (!component)
return; return;
auto componentType = rttr::type::get(*component); auto componentType = rttr::type::get(*component);
CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data())) if (ImGui::CollapsingHeader(componentType.get_name().data()))
{ {
@ -63,7 +63,7 @@ namespace SHADE
std::vector<const char*> list; std::vector<const char*> list;
for(auto const& name : names) for(auto const& name : names)
list.push_back(name.data()); list.push_back(name.data());
ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx) SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx)
{ {
auto enumAlign = property.get_enumeration(); auto enumAlign = property.get_enumeration();
auto values = enumAlign.get_values(); auto values = enumAlign.get_values();
@ -75,7 +75,7 @@ namespace SHADE
{ {
if (type == rttr::type::get<bool>()) if (type == rttr::type::get<bool>())
{ {
CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);}); SHEditorWidgets::CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);});
} }
//else if (type == rttr::type::get<char>()) //else if (type == rttr::type::get<char>())
//{ //{
@ -87,11 +87,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin && metaMax) if(metaMin && metaMax)
{ {
SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);});
} }
else else
{ {
DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);}); SHEditorWidgets::DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);});
} }
} }
else if (type == rttr::type::get<uint8_t>()) else if (type == rttr::type::get<uint8_t>())
@ -100,11 +100,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if(metaMin.is_valid() && metaMax.is_valid())
{ {
SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu");
} }
else else
{ {
DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
} }
} }
else if (type == rttr::type::get<uint16_t>()) else if (type == rttr::type::get<uint16_t>())
@ -113,11 +113,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if(metaMin.is_valid() && metaMax.is_valid())
{ {
SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},"%zu");
} }
else else
{ {
DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
} }
} }
else if (type == rttr::type::get<uint32_t>()) else if (type == rttr::type::get<uint32_t>())
@ -126,11 +126,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if (metaMin.is_valid() && metaMax.is_valid()) if (metaMin.is_valid() && metaMax.is_valid())
{ {
SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },"%zu"); SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },"%zu");
} }
else else
{ {
DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu");
} }
} }
else if (type == rttr::type::get<uint64_t>()) else if (type == rttr::type::get<uint64_t>())
@ -139,11 +139,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if(metaMin.is_valid() && metaMax.is_valid())
{ {
SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},"%zu"); SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},"%zu");
} }
else else
{ {
DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu"); SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
} }
} }
else if (type == rttr::type::get<float>()) else if (type == rttr::type::get<float>())
@ -152,11 +152,11 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if(metaMin.is_valid() && metaMax.is_valid())
{ {
SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);});
} }
else else
{ {
DragFloat(property.get_name().data(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);}); SHEditorWidgets::DragFloat(property.get_name().data(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);});
} }
} }
else if (type == rttr::type::get<double>()) else if (type == rttr::type::get<double>())
@ -165,25 +165,25 @@ namespace SHADE
auto metaMax = property.get_metadata(META::max); auto metaMax = property.get_metadata(META::max);
if(metaMin.is_valid() && metaMax.is_valid()) if(metaMin.is_valid() && metaMax.is_valid())
{ {
SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}); SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);});
} }
else else
{ {
DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f); SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f);
} }
} }
} }
else if (type == rttr::type::get<SHVec4>()) else if (type == rttr::type::get<SHVec4>())
{ {
DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); }); SHEditorWidgets::DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
} }
else if (type == rttr::type::get<SHVec3>()) else if (type == rttr::type::get<SHVec3>())
{ {
DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); }); SHEditorWidgets::DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
} }
else if (type == rttr::type::get<SHVec2>()) else if (type == rttr::type::get<SHVec2>())
{ {
DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); }); SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); });
} }
} }

View File

@ -13,6 +13,8 @@
#include "SHEditorComponentView.hpp" #include "SHEditorComponentView.hpp"
#include "ECS_Base/UnitTesting/SHTestComponents.h" #include "ECS_Base/UnitTesting/SHTestComponents.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "AudioSystem/SHAudioSystem.h" #include "AudioSystem/SHAudioSystem.h"
@ -49,7 +51,7 @@ namespace SHADE
SHEntity* entity = SHEntityManager::GetEntityByID(eid); SHEntity* entity = SHEntityManager::GetEntityByID(eid);
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid); ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); }); SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputText("##EntityName", &entity->name); ImGui::InputText("##EntityName", &entity->name);
@ -74,6 +76,11 @@ namespace SHADE
DrawAddComponentButton<SHComponent_ENUM>(eid); DrawAddComponentButton<SHComponent_ENUM>(eid);
ImGui::EndMenu(); ImGui::EndMenu();
} }
// Render Scripts
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RenderScriptsInInspector(eid);
} }
ImGui::End(); ImGui::End();
} }

View File

@ -6,6 +6,9 @@
#include "SHEditorMenuBar.h" #include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h" #include "Editor/Command/SHCommandManager.h"
#include "Scripting/SHScriptEngine.h"
#include "Editor/SHEditor.hpp"
#include "ECS_Base/Managers/SHSystemManager.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -14,9 +17,6 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <rttr/type> #include <rttr/type>
#include "Editor/SHEditor.hpp"
namespace SHADE namespace SHADE
{ {
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -100,6 +100,25 @@ namespace SHADE
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("Scripts"))
{
if (ImGui::Selectable("Generate Visual Studio Project"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile();
}
if (ImGui::Selectable("Build Scripts - Debug"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->BuildScriptAssembly(true, true);
}
if (ImGui::Selectable("Build Scripts - Release"))
{
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->BuildScriptAssembly(false, true);
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }

View File

@ -23,6 +23,8 @@
#include "SHEditor.hpp" #include "SHEditor.hpp"
#include "SHEditorWidgets.hpp" #include "SHEditorWidgets.hpp"
#include "Math/Transform/SHTransformSystem.h"
//#==============================================================# //#==============================================================#
//|| Editor Window Includes || //|| Editor Window Includes ||
//#==============================================================# //#==============================================================#
@ -87,6 +89,11 @@ namespace SHADE
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
InitFonts(); InitFonts();
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>();
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
InitBackend(sdlWindow); InitBackend(sdlWindow);
SetStyle(Style::SHADE); SetStyle(Style::SHADE);
@ -104,7 +111,6 @@ namespace SHADE
{ {
(void)dt; (void)dt;
NewFrame(); NewFrame();
for (const auto& window : editorWindows | std::views::values) for (const auto& window : editorWindows | std::views::values)
{ {
if(window->isOpen) if(window->isOpen)

View File

@ -0,0 +1,259 @@
/************************************************************************************//*!
\file EditorUI.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 7, 2021
\brief Contains the implementation of the EditorUI class.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Header
#include "SHpch.h"
// Primary Header
#include "SHEditorUI.h"
// External Dependencies
#include <imgui.h>
#include "SHEditorWidgets.hpp"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - ID Stack */
/*-----------------------------------------------------------------------------------*/
void SHEditorUI::PushID(const std::string& id)
{
ImGui::PushID(id.c_str());
}
void SHEditorUI::PushID(int id)
{
ImGui::PushID(id);
}
void SHEditorUI::PopID()
{
ImGui::PopID();
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Indent */
/*-----------------------------------------------------------------------------------*/
void SHEditorUI::Indent()
{
ImGui::Indent();
}
void SHEditorUI::Unindent()
{
ImGui::Unindent();
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Organizers */
/*-----------------------------------------------------------------------------------*/
bool SHEditorUI::CollapsingHeader(const std::string& title)
{
return ImGui::CollapsingHeader(title.c_str());
}
void SHEditorUI::SameLine()
{
ImGui::SameLine();
}
void SHEditorUI::Separator()
{
ImGui::Separator();
}
bool SHEditorUI::BeginMenu(const std::string& label)
{
return ImGui::BeginMenu(label.data());
}
bool SHEditorUI::BeginMenu(const std::string& label, const char* icon)
{
return ImGui::BeginMenu(std::format("{} {}", icon, label.data()).data());
}
void SHEditorUI::EndMenu()
{
ImGui::EndMenu();
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
/*-----------------------------------------------------------------------------------*/
bool SHEditorUI::BeginPopup(const std::string& label)
{
return ImGui::BeginPopup(label.c_str());
}
bool SHEditorUI::BeginPopupContextItem(const std::string& label)
{
return ImGui::BeginPopupContextItem(label.data());
}
void SHEditorUI::EndPopup()
{
ImGui::EndPopup();
}
void SHEditorUI::OpenPopup(const std::string& label)
{
ImGui::OpenPopup(label.c_str());
}
bool SHEditorUI::MenuItem(const std::string& label)
{
return ImGui::MenuItem(label.c_str());
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Widgets */
/*-----------------------------------------------------------------------------------*/
void SHEditorUI::Text(const std::string& title)
{
ImGui::Text(title.c_str());
}
bool SHEditorUI::SmallButton(const std::string& title)
{
return ImGui::SmallButton(title.c_str());
}
bool SHEditorUI::Button(const std::string& title)
{
return ImGui::Button(title.c_str());
}
bool SHEditorUI::Selectable(const std::string& label)
{
return ImGui::Selectable(label.data());
}
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
{
return ImGui::Selectable(std::format("{} {}", icon, label).data());
}
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
{
ImGui::Text(label.c_str());
ImGui::SameLine();
return ImGui::Checkbox("#", &value);
}
bool SHEditorUI::InputInt(const std::string& label, int& value)
{
ImGui::Text(label.c_str());
ImGui::SameLine();
return ImGui::InputInt("#", &value,
1, 10,
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
{
int signedVal = static_cast<int>(value);
ImGui::Text(label.c_str());
ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal);
if (CHANGED)
{
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
value = static_cast<unsigned int>(signedVal);
}
return CHANGED;
}
bool SHEditorUI::InputFloat(const std::string& label, float& value)
{
ImGui::Text(label.c_str());
ImGui::SameLine();
return ImGui::InputFloat("#", &value,
0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputDouble(const std::string& label, double& value)
{
ImGui::Text(label.c_str());
ImGui::SameLine();
return ImGui::InputDouble("#", &value,
0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputAngle(const std::string& label, double& value)
{
ImGui::Text(label.c_str());
ImGui::SameLine();
return ImGui::InputDouble("#", &value,
1.0, 45.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value)
{
float val = static_cast<float>(value);
ImGui::Text(label.c_str());
ImGui::SameLine();
const bool CHANGED = ImGui::SliderFloat("#", &val,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
if (CHANGED)
{
value = val;
}
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y });
}
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f");
}
bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
{
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
ImGui::Text(label.c_str());
ImGui::SameLine();
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED)
{
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
}
return CHANGED;
}
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
{
// Clamp input value
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
bool b = false;
ImGui::Text(label.c_str());
ImGui::SameLine();
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{
for (int i = 0; i < enumNames.size(); ++i)
{
const bool IS_SELECTED = v == i;
if (ImGui::Selectable(enumNames[i].c_str(), IS_SELECTED))
{
v = i;
b = true;
}
if (IS_SELECTED)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
return b;
}
}

View File

@ -0,0 +1,286 @@
/************************************************************************************//*!
\file SHEditorUI.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\par email: t.yanchongclarence\@digipen.edu
\date Sep 27, 2022
\brief Defines a class that contains wrapper functions for ImGui.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Standard Library
#include <functional> // std::function
#include <string> // std::string
// Project Includes
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "Math/SHMatrix.h"
namespace SHADE
{
/// <summary>
/// Static class that contains useful functions for Editor UI using ImGui.
/// </summary>
class SH_API SHEditorUI final
{
public:
/*-----------------------------------------------------------------------------*/
/* Constants */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Maximum length of a string supported by InputTextField()
/// </summary>
static constexpr size_t TEXT_FIELD_MAX_LENGTH = 256;
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - ID Stack */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Marks the start of a stack of ImGui widgets with the specified id.
/// <br/>
/// Wraps up ImGui::PushID().
/// </summary>
/// <param name="id">String-based ID.</param>
static void PushID(const std::string& id);
/// <summary>
/// Marks the start of a stack of ImGui widgets with the specified id.
/// <br/>
/// Wraps up ImGui::PushID().
/// </summary>
/// <param name="id">Integer-based ID.</param>
static void PushID(int id);
/// <summary>
/// Marks the end of a stack of ImGui widgets from the last PushID() call.
/// <br/>
/// Wraps up ImGui::PopID().
/// </summary>
static void PopID();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Indent */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Indents the widgets rendered after this call.
/// <br/>
/// Wraps up ImGui::Indent().
/// </summary>
static void Indent();
/// <summary>
/// Unindents the widgets rendered after this call.
/// <br/>
/// Wraps up ImGui::Unindent().
/// </summary>
static void Unindent();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Organizers */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Creates a collapsing title header.
/// <br/>
/// Wraps up ImGui::CollapsingHeader().
/// </summary>
/// <param name="title">Label for the header.</param>
/// <returns>True if the header is open, false otherwise.</returns>
static bool CollapsingHeader(const std::string& title);
static void SameLine();
static void Separator();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Menu */
/*-----------------------------------------------------------------------------*/
static bool BeginMenu(const std::string& label);
static bool BeginMenu(const std::string& label, const char* icon);
static void EndMenu();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Marks the start of a definition of a mini pop up that can show options.
/// <br/>
/// Wraps up ImGui::BeginPopup().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <returns>Whether or not the pop up is open.</returns>
static bool BeginPopup(const std::string& label);
static bool BeginPopupContextItem(const std::string& label);
/// <summary>
/// Marks the end of a definition of a mini pop up that can show options.
/// <br/>
/// Wraps up ImGui::EndPopup().
/// </summary>
static void EndPopup();
/// <summary>
/// Opens the popup that was defined with the specified label.
/// <br/>
/// Wraps up ImGui::OpenPopup().
/// </summary>
static void OpenPopup(const std::string& label);
/// <summary>
/// Creates a menu item in the list of items for a mini popup.
/// <br/>
/// Wraps up ImGui::MenuItem().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <returns>Whether or not the menu item was selected.</returns>
static bool MenuItem(const std::string& label);
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Widgets */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Creates a visual text widget.
/// <br/>
/// Wraps up ImGui::Text().
/// </summary>
/// <param name="title">Text to display.</param>
static void Text(const std::string& title);
/// <summary>
/// Creates a small inline button widget.
/// <br/>
/// Wraps up ImGui::SmallButton().
/// </summary>
/// <param name="title">Text to display.</param>
/// <returns>True if button was pressed.</returns>
static bool SmallButton(const std::string& title);
/// <summary>
/// Creates a inline button widget.
/// <br/>
/// Wraps up ImGui::Button().
/// </summary>
/// <param name="title">Text to display.</param>
/// <returns>True if button was pressed.</returns>
static bool Button(const std::string& title);
static bool Selectable(const std::string& label);
static bool Selectable(const std::string& label, const char* icon);
/// <summary>
/// Creates a checkbox widget for boolean input.
/// <br/>
/// Wraps up ImGui::Checkbox().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputCheckbox(const std::string& label, bool& value);
/// <summary>
/// Creates a integer field widget for integer input.
/// <br/>
/// Wraps up ImGui::InputInt().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputInt(const std::string& label, int& value);
/// <summary>
/// Creates a integer field widget for unsigned integer input.
/// <br/>
/// Wraps up ImGui::InputInt() with an additional clamping of values.
/// <br/>
/// Note: As a result, the range of this function limits it to the maximum
/// value of a 32-bit signed integer instead of a 32-bit unsigned integer.
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputUnsignedInt(const std::string& label, unsigned int& value);
/// <summary>
/// Creates a decimal field widget for single precision float input.
/// <br/>
/// Wraps up ImGui::InputFloat().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputFloat(const std::string& label, float& value);
/// <summary>
/// Creates a decimal field widget for double precision float input.
/// <br/>
/// Wraps up ImGui::InputDouble().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputDouble(const std::string& label, double& value);
/// <summary>
/// Creates a decimal field widget for double input with increments of higher
/// steps meant for angle variables.
/// <br/>
/// Wraps up ImGui::InputDouble().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputAngle(const std::string& label, double& value);
/// <summary>
/// Creates a double slider field widget for double input.
/// <br/>
/// Wraps up ImGui::InputSliderFloat().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="min">Minimum value of the slider.</param>
/// <param name="max">Maximum value of the slider.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, double min, double max, double& value);
/// <summary>
/// Creates a 2x double field widget for Vector2 input.
/// <br/>
/// Wraps up ImGui::InputFloat2().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec2(const std::string& label, SHVec2& value);
/// <summary>
/// Creates a 3x double field widget for Vector3 input.
/// <br/>
/// Wraps up ImGui::InputFloat3().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
/// <summary>
/// Creates a text field widget for string input.
/// <br/>
/// Wraps up ImGui::InputText().
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <returns>True if the value was changed.</returns>
static bool InputTextField(const std::string& label, std::string& value);
/// <summary>
/// Creates a combo box for enumeration input.
/// </summary>
/// <typeparam name="Enum">The type of enum to input.</typeparam>
/// <param name="label">The name of the input.</param>
/// <param name="v">The reference to the value to modify.</param>
/// <param name="maxVal">The maximum value of the enum.</param>
/// <param name="toStrFn">
/// Conversion function from the type of enum to C-style string.
/// </param>
/// <returns>Whether the value was modified.</returns>
template<typename Enum>
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn);
/// <summary>
/// Creates a combo box for enumeration input using a specified list of names.
/// </summary>
/// <param name="label">The name of the input.</param>
/// <param name="v">The reference to the value to modify.</param>
/// <param name="enumNames">Vector of names for each enumeration value.</param>
/// <returns>Whether the value was modified.</returns>
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
private:
// Prevent instantiation of this static class
SHEditorUI() = delete;
};
}
#include "SHEditorUI.hpp"

View File

@ -0,0 +1,51 @@
/************************************************************************************//*!
\file SHEditorUI.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 27, 2022
\brief Contains the implementation of editor inspector template functions.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Primary Header
#include "SHEditorUI.h"
// External Dependencies
#include <imgui.h>
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Widgets */
/*---------------------------------------------------------------------------------*/
template<typename Enum>
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn)
{
std::vector<Enum> values;
for (int i = 0; i <= maxVal; ++i)
{
values.emplace_back(static_cast<Enum>(i));
}
bool b = false;
if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
{
for (int i = 0; i <= maxVal; ++i)
{
const auto VALUE = values[i];
const bool IS_SELECTED = v == VALUE;
if (ImGui::Selectable(toStrFn(VALUE), IS_SELECTED))
{
v = VALUE;
b = true;
}
if (IS_SELECTED)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
return b;
}
}

View File

@ -12,6 +12,7 @@
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "Command/SHCommandManager.h" #include "Command/SHCommandManager.h"
#include "SHImGuiHelpers.hpp" #include "SHImGuiHelpers.hpp"
#include "SH_API.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
@ -23,252 +24,223 @@
namespace SHADE namespace SHADE
{ {
//#==============================================================# class SH_API SHEditorWidgets
//|| Custom Widgets ||
//#==============================================================#
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{ {
ImGuiWindow* window = ImGui::GetCurrentWindow(); public:
const ImGuiID id = window->GetID("##Splitter"); //#==============================================================#
ImRect bb; //|| Constructor ||
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1)); //#==============================================================#
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness)); SHEditorWidgets() = delete;
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
}
template <typename T, std::size_t N> //#==============================================================#
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, //|| Custom Widgets ||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), //#==============================================================#
ImGuiSliderFlags flags = 0) static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiContext& g = *GImGui;
bool valueChanged = false;
ImGui::BeginGroup();
ImGui::PushID(fieldLabel.c_str());
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str());
ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i)
{ {
ImGui::PushID(static_cast<int>(i)); ImGuiWindow* window = ImGui::GetCurrentWindow();
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine(); const ImGuiID id = window->GetID("##Splitter");
ImGui::SetNextItemWidth(80.0f); ImRect bb;
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags); bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
const ImVec2 min = ImGui::GetItemRectMin(); return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
const ImVec2 max = ImGui::GetItemRectMax();
const float spacing = g.Style.FrameRounding;
const float halfSpacing = spacing / 2;
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
ImGuiColors::colors[i], 4);
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
ImGui::PopID();
ImGui::PopItemWidth();
}
ImGui::EndColumns();
ImGui::PopID();
ImGui::EndGroup();
return valueChanged;
}
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec2 values = get();
bool changed = false;
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
} }
if (changed) template <typename T, std::size_t N>
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
ImGuiSliderFlags flags = 0)
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) const ImGuiWindow* const window = ImGui::GetCurrentWindow();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false); if (window->SkipItems)
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) return false;
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
}
return changed; const ImGuiContext& g = *GImGui;
} bool valueChanged = false;
ImGui::BeginGroup();
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get, ImGui::PushID(fieldLabel.c_str());
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
ImGuiSliderFlags flags = 0) ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
{ ImGui::SetColumnWidth(-1, 80.0f);
SHVec3 values = get(); ImGui::Text(fieldLabel.c_str());
bool changed = false; ImGui::NextColumn();
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) for (std::size_t i = 0; i < N; ++i)
{
changed = true;
}
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
}
return changed;
}
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiSliderFlags flags = 0)
{
SHVec4 values = get();
bool changed = false;
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
}
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
}
return changed;
}
//#==============================================================#
//|| Widget Extensions ||
//#==============================================================#
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
{
bool value = get();
if (ImGui::Checkbox(label.c_str(), &value))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
return true;
}
return false;
}
template<typename T>
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
{
T type = get();
for (size_t i = 0; i < listTypes.size(); i++)
{
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false); ImGui::PushID(static_cast<int>(i));
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
ImGui::SetNextItemWidth(80.0f);
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
const ImVec2 min = ImGui::GetItemRectMin();
const ImVec2 max = ImGui::GetItemRectMax();
const float spacing = g.Style.FrameRounding;
const float halfSpacing = spacing / 2;
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
ImGuiColors::colors[i], 4);
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
ImGui::PopID();
ImGui::PopItemWidth();
} }
ImGui::SameLine(); ImGui::EndColumns();
ImGui::PopID();
ImGui::EndGroup();
return valueChanged;
} }
return true;
}
static bool InputText(const std::string& label, const std::function<std::string(void)> get, static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0, std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) ImGuiSliderFlags flags = 0)
{
std::string text = get();
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
{ {
if (ImGui::IsItemDeactivatedAfterEdit()) SHVec2 values = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false); bool changed = false;
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
{
changed = true;
}
return true; if (changed)
{
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
}
return changed;
} }
return false;
}
template <typename T> static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set, std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) ImGuiSliderFlags flags = 0)
{
T value = get();
std::cout << value <<" \n";
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) SHVec3 values = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false); bool changed = false;
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true); {
else if (ImGui::IsItemDeactivatedAfterEdit()) changed = true;
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false); }
return true; if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
}
return changed;
} }
return false;
}
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set, static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
{ ImGuiSliderFlags flags = 0)
float value = get();
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) SHVec4 values = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); bool changed = false;
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true); {
else if (ImGui::IsItemDeactivatedAfterEdit()) changed = true;
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); }
if (changed)
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
}
return changed;
}
//#==============================================================#
//|| Widget Extensions ||
//#==============================================================#
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
{
bool value = get();
if (ImGui::Checkbox(label.c_str(), &value))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
return true;
}
return false;
}
template<typename T>
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
{
T type = get();
for (size_t i = 0; i < listTypes.size(); i++)
{
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
}
ImGui::SameLine();
}
return true; return true;
} }
return false; static bool InputText(const std::string& label, const std::function<std::string(void)> get,
} const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
{
int value = get();
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
{ {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) std::string text = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false); if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true); if (ImGui::IsItemDeactivatedAfterEdit())
else if (ImGui::IsItemDeactivatedAfterEdit()) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
return true; return true;
}
return false;
} }
return false;
}
template <typename T> template <typename T>
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set, static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{ {
T value = get(); T value = get();
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) std::cout << value <<" \n";
{ //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false); if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
return true;
}
return false;
}
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{
float value = get();
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
{
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
return true; return true;
} }
@ -276,55 +248,91 @@ namespace SHADE
return false; return false;
} }
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set, static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
{
float value = get();
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) int value = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false); //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true); {
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
else if (ImGui::IsItemDeactivatedAfterEdit())
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
return true;
}
return false;
}
template <typename T>
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{
T value = get();
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
{
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
return true;
}
return false;
}
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
{
float value = get();
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
{
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
return true; return true;
}
return false;
} }
return false; static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
} const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
{
int value = get();
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
{ {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) int value = get();
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false); if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true); if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
return true; return true;
}
return false;
} }
return false; static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
}
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
{
bool edited = false;
int selected = get();
ImGui::PushID(fieldLabel.c_str());
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
if (edited = ImGui::Combo("##Combo", &selected, list.data(), list.size()))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false); bool edited = false;
int selected = get();
ImGui::PushID(fieldLabel.c_str());
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
if (edited = ImGui::Combo("##Combo", &selected, list.data(), list.size()))
{
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
}
ImGui::PopID();
return edited;
} }
ImGui::PopID(); };
return edited;
}
}//namespace SHADE }//namespace SHADE

View File

@ -8,3 +8,5 @@ typedef uint32_t SHEventHandle;
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 }; constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 }; constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };

View File

@ -12,7 +12,9 @@
// Project Headers // Project Headers
#include "SH_API.h" #include "SH_API.h"
#include "Math/SHMath.h" #include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/SHMatrix.h"
namespace SHADE namespace SHADE
{ {

View File

@ -13,6 +13,7 @@
#include <string> #include <string>
#include "SHSceneGraph.h" #include "SHSceneGraph.h"
#include "ECS_Base/General/SHFamily.h"
namespace SHADE namespace SHADE
{ {
@ -42,6 +43,7 @@ namespace SHADE
virtual void Unload() = 0; virtual void Unload() = 0;
}; };
template class SH_API SHFamilyID<SHScene>;
} }

View File

@ -84,7 +84,8 @@ namespace SHADE
{ {
//prevSceneCreate = newScene; //prevSceneCreate = newScene;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName = sceneName; }; newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName = sceneName; };
nextSceneID = SHFamilyID<SHScene>::template GetID<T>(); //nextSceneID = SHFamilyID<SHScene>::GetID<T>();
nextSceneID = 0;
sceneChanged = true; sceneChanged = true;
} }
@ -101,13 +102,13 @@ namespace SHADE
static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> ChangeScene(std::string const& sceneName) noexcept static std::enable_if_t<std::is_base_of_v<SHScene, T>, void> ChangeScene(std::string const& sceneName) noexcept
{ {
//check if this new Scene is current Scene (Use RestartScene instead) //check if this new Scene is current Scene (Use RestartScene instead)
if (currentSceneID == SHFamilyID<SHScene>::template GetID<T>()) if (currentSceneID == SHFamilyID<SHScene>::GetID<T>())
{ {
return; return;
} }
//prevSceneCreate = newScene; //prevSceneCreate = newScene;
newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName; }; newScene = [sceneName]() { currentScene = new T(); currentScene->sceneName; };
nextSceneID = SHFamilyID<SHScene>::template GetID<T>(); nextSceneID = SHFamilyID<SHScene>::GetID<T>();
sceneChanged = true; sceneChanged = true;
} }

View File

@ -82,22 +82,18 @@ namespace SHADE
void SHScriptEngine::Exit() void SHScriptEngine::Exit()
{ {
// Do not allow deinitialization if not initialised // Do not allow deinitialization if not initialised
if (!dotNet.IsLoaded()) if (!dotNet.IsLoaded())
{ {
SHLOG_ERROR("[ScriptEngine] Attempted to clean up an unloaded DotNetRuntime."); SHLOG_ERROR("[ScriptEngine] Attempted to clean up an unloaded DotNetRuntime.");
return; return;
} }
// Unlink events // Clean up the CSharp Engine
/*ECS::OnEntityCreated -= onEntityCreate; csEngineExit();
ECS::OnEntityDestroy -= onEntityDestroy;*/
// Clean up the CSharp Engine // Shut down the CLR
csEngineExit(); dotNet.Exit();
// Shut down the CLR
dotNet.Exit();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -105,15 +101,15 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName) bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName)
{ {
return csScriptsAdd(entity, scriptName.data()); return csScriptsAdd(entity, scriptName.data());
} }
void SHScriptEngine::RemoveAllScripts(EntityID entity) void SHScriptEngine::RemoveAllScripts(EntityID entity)
{ {
csScriptsRemoveAll(entity); csScriptsRemoveAll(entity);
} }
void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy) void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy)
{ {
csScriptsRemoveAllImmediately(entity, callOnDestroy); csScriptsRemoveAllImmediately(entity, callOnDestroy);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -121,24 +117,24 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const
{ {
// Create buffer needed to store serialised script data // Create buffer needed to store serialised script data
constexpr int BUFFER_SIZE = 10240; constexpr int BUFFER_SIZE = 10240;
std::unique_ptr<char> buffer { new char[BUFFER_SIZE] }; std::unique_ptr<char> buffer { new char[BUFFER_SIZE] };
std::memset(buffer.get(), 0, BUFFER_SIZE); std::memset(buffer.get(), 0, BUFFER_SIZE);
// Attempt to serialise the script // Attempt to serialise the script
std::string result; std::string result;
if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE)) if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE))
{ {
result = std::string(buffer.get()); result = std::string(buffer.get());
} }
else else
{ {
SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts as string buffer is too small!"); SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts as string buffer is too small!");
} }
// Return an empty string since we failed to serialise // Return an empty string since we failed to serialise
return result; return result;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -152,18 +148,24 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Script Editor Functions */ /* Script Editor Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity) const void SHScriptEngine::RenderScriptsInInspector(EntityID entity) const
{ {
csEditorRenderScripts(entity.GetEID()); csEditorRenderScripts(entity);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHScriptEngine::BuildScriptAssembly(bool debug) const bool SHScriptEngine::BuildScriptAssembly(bool debug, bool reload)
{ {
static const std::string BUILD_LOG_PATH = "../Build.log"; static const std::string BUILD_LOG_PATH = "../Build.log";
// Unload if we need to reload
if (reload)
{
UnloadScriptAssembly();
}
// Generate csproj file if it doesn't exist // Generate csproj file if it doesn't exist
if (!std::filesystem::exists(CSPROJ_PATH)) if (!std::filesystem::exists(CSPROJ_PATH))
{ {
@ -209,6 +211,12 @@ namespace SHADE
// Delete the build log file since we no longer need it // Delete the build log file since we no longer need it
deleteFile(BUILD_LOG_PATH); deleteFile(BUILD_LOG_PATH);
// If reloading, we need to load
if (reload)
{
LoadScriptAssembly();
}
return BUILD_SUCCESS; return BUILD_SUCCESS;
} }
@ -255,7 +263,7 @@ namespace SHADE
// Attempt to create the file // Attempt to create the file
std::ofstream file(path); std::ofstream file(path);
if (!file.is_open()) if (!file.is_open())
throw std::runtime_error("Unable to create CsProj file!"); throw std::runtime_error("Unable to create CsProj file!");
// Fill the file // Fill the file
file << FILE_CONTENTS; file << FILE_CONTENTS;
@ -269,9 +277,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr) SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr)
{ {
auto eventData = reinterpret_cast<const SHEventSpec<SHEntityDestroyedEvent>*>(eventPtr.get()); auto eventData = reinterpret_cast<const SHEventSpec<SHEntityDestroyedEvent>*>(eventPtr.get());
csScriptsRemoveAll(eventData->data->eid); csScriptsRemoveAll(eventData->data->eid);
return eventData->handle; return eventData->handle;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -385,13 +393,13 @@ namespace SHADE
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"SerialiseScriptsYaml" "SerialiseScriptsYaml"
); );*/
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr> csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Editor", DEFAULT_CSHARP_NAMESPACE + ".Editor",
"RenderScriptsInInspector" "RenderScriptsInInspector"
);*/ );
} }
void SHScriptEngine::registerEvents() void SHScriptEngine::registerEvents()

View File

@ -170,7 +170,7 @@ namespace SHADE
/// rendering code. /// rendering code.
/// </summary> /// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
void RenderScriptsInInspector(const SHEntity& entity) const; void RenderScriptsInInspector(EntityID entity) const;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
@ -184,13 +184,16 @@ namespace SHADE
/// Whether or not a debug build will be built. Only debug built C# assemblies /// Whether or not a debug build will be built. Only debug built C# assemblies
/// can be debugged. /// can be debugged.
/// </param> /// </param>
/// <param name="reload">
/// Whether or not we are reloading the assembly, if so, unload and then reload it.
/// </param>
/// <returns>Whether or not the build succeeded.</returns> /// <returns>Whether or not the build succeeded.</returns>
bool BuildScriptAssembly(bool debug = false) const; bool BuildScriptAssembly(bool debug = false, bool reload = false);
/// <summary> /// <summary>
/// Generates a .csproj file for editing and compiling the C# scripts. /// Generates a .csproj file for editing and compiling the C# scripts.
/// </summary> /// </summary>
/// <param name="path">File path to the generated file.</param> /// <param name="path">File path to the generated file.</param>
void GenerateScriptsCsProjFile(const std::filesystem::path& path) const; void GenerateScriptsCsProjFile(const std::filesystem::path& path = CSPROJ_PATH) const;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -34,6 +34,11 @@ project "SHADE_Managed"
"%{wks.location}/SHADE_Engine/src" "%{wks.location}/SHADE_Engine/src"
} }
libdirs
{
"%{IncludeDir.RTTR}/lib"
}
links links
{ {
"yaml-cpp", "yaml-cpp",
@ -68,7 +73,9 @@ project "SHADE_Managed"
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG"} defines {"_DEBUG"}
links{"librttr_core_d.lib"}
filter "configurations:Release" filter "configurations:Release"
optimize "On" optimize "On"
defines{"_RELEASE"} defines{"_RELEASE"}
links{"librttr_core.lib"}

View File

@ -0,0 +1,107 @@
/************************************************************************************//*!
\file Transform.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 23, 2022
\brief Contains the definition of the functions of the managed Transform class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "Transform.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
Vector3 Transform::LocalPosition::get()
{
return Convert::ToCLI(GetNativeComponent()->GetLocalPosition());
}
void Transform::LocalPosition::set(Vector3 val)
{
GetNativeComponent()->SetLocalPosition(Convert::ToNative(val));
}
Vector3 Transform::LocalRotation::get()
{
return Convert::ToCLI(GetNativeComponent()->GetLocalRotation());
}
void Transform::LocalRotation::set(Vector3 val)
{
GetNativeComponent()->SetLocalRotation(Convert::ToNative(val));
}
Vector3 Transform::LocalScale::get()
{
return Convert::ToCLI(GetNativeComponent()->GetLocalScale());
}
void Transform::LocalScale::set(Vector3 val)
{
GetNativeComponent()->SetLocalScale(Convert::ToNative(val));
}
Vector3 Transform::GlobalPosition::get()
{
return Convert::ToCLI(GetNativeComponent()->GetWorldPosition());
}
void Transform::GlobalPosition::set(Vector3 val)
{
GetNativeComponent()->SetWorldPosition(Convert::ToNative(val));
}
Vector3 Transform::GlobalRotation::get()
{
return Convert::ToCLI(GetNativeComponent()->GetWorldRotation());
}
void Transform::GlobalRotation::set(Vector3 val)
{
GetNativeComponent()->SetWorldRotation(Convert::ToNative(val));
}
Vector3 Transform::GlobalScale::get()
{
return Convert::ToCLI(GetNativeComponent()->GetWorldScale());
}
void Transform::GlobalScale::set(Vector3 val)
{
GetNativeComponent()->SetWorldScale(Convert::ToNative(val));
}
Transform^ Transform::Parent::get()
{
auto node = SHSceneManager::GetCurrentSceneGraph().GetNode(owner.GetEntity());
if (!node)
throw gcnew System::InvalidOperationException("[Transform] Unable to retrieve SceneGraphNode for an Entity.");
const auto PARENT = node->GetParent();
return PARENT ? gcnew Transform(PARENT->GetEntityID()) : nullptr;
}
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
Transform::Transform(Entity entity)
: Component(entity)
{}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void Transform::SetParent(Transform^ parent, bool worldPositionStays)
{
auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto node = sceneGraph.GetNode(owner.GetEntity());
if (!node)
throw gcnew System::InvalidOperationException("[Transform] Unable to retrieve SceneGraphNode for an Entity.");
if (parent)
node->SetParent(sceneGraph.GetNode(parent->owner.GetEntity()));
else
sceneGraph.SetParent(parent->owner.GetEntity(), nullptr);
}
}

View File

@ -0,0 +1,121 @@
/************************************************************************************//*!
\file Transform.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 23, 2022
\brief Contains the definition of the managed Transform class with the
declaration of functions for working with it.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Project Includes
#include "Components/Component.hxx"
#include "Math/Vector3.hxx"
#include "Utility/Convert.hxx"
// External Dependencies
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
/// <summary>
/// CLR version of the the SHADE Engine's TransformComponent.
/// </summary>
public ref class Transform : public Component<SHTransformComponent>
{
internal:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Constructs a Transform Component that represents a native Transform component
/// tied to the specified Entity.
/// </summary>
/// <param name="entity">Entity that this Component will be tied to.</param>
Transform(Entity entity);
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Local position stored by this Transform.
/// </summary>
property Vector3 LocalPosition
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Local Z-axis rotation angle stored by this Transform in Radians.
/// </summary>
property Vector3 LocalRotation
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Local scale stored by this Transform.
/// </summary>
property Vector3 LocalScale
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Global position stored by this Transform.
/// </summary>
property Vector3 GlobalPosition
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Global Z-axis rotation angle stored by this Transform in Radians.
/// </summary>
property Vector3 GlobalRotation
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Global scale stored by this Transform.
/// Note that this operation is expensive.
/// </summary>
property Vector3 GlobalScale
{
Vector3 get();
void set(Vector3 val);
}
/// <summary>
/// Parent Transform that affects this Transform.
/// </summary>
property Transform^ Parent
{
Transform^ get();
}
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Sets the parent of this Transform component.
/// </summary>
/// <param name="parent">
/// Entity that contains the Transform component that this Transform will be
/// parented to. If null, unparenting will occur.
/// </param>
/// <param name="worldPositionStays">
/// If true, the transform values of this Transform component will retain their
/// pre-parent-change global transforms. The local transform values will be
/// modified to ensure that the global transforms do not change.
/// </param>
void SetParent(Transform^ parent, bool worldPositionStays);
};
}

View File

@ -0,0 +1,234 @@
/************************************************************************************//*!
\file Editor.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 27, 2022
\brief Contains the definition of the functions for the ScriptStore managed
static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "Editor/Editor.hxx"
// External Dependencies
#include "Editor/SHEditorUI.h"
// Project Headers
#include "Components/Component.hxx"
#include "Scripts/ScriptStore.hxx"
#include "Utility/Convert.hxx"
#include "Utility/Debug.hxx"
#include "Serialisation/ReflectionUtilities.hxx"
#include "Editor/IconsMaterialDesign.h"
// Using Directives
using namespace System;
using namespace System::Collections::Generic;
/*-------------------------------------------------------------------------------------*/
/* Macro Functions */
/*-------------------------------------------------------------------------------------*/
/// <summary>
/// Macro expansion that is used in renderFieldInInspector() to check the type of a field
/// named "field" against the specified type and if it matches, retrieves the value of
/// that field from an object named "object" and pass it into the specified SHEditorUI::
/// function named "FUNC" by casting it into the NATIVE_TYPE specified.
/// <br/>
/// This only works for primitive types that have the same types for managed and native.
/// </summary>
/// <param name="MANAGED_TYPE">The managed type of the object to edit.</param>
/// <param name="NATIVE_TYPE">The native type of the object to edit.</param>
/// <param name="FUNC">The SHEditorUI:: function to use for editing.</param>
#define RENDER_FIELD(MANAGED_TYPE, NATIVE_TYPE, FUNC) \
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \
field->SetValue(object, val); \
} \
} \
/// <summary>
/// Macro expansion that is used in renderFieldInInspector() to check the type of a field
/// named "field" against the specified type and if it matches, retrieves the value of
/// that field from an object named "object" and pass it into the specified SHEditorUI::
/// function named "FUNC" by casting it into the NATIVE_TYPE specified.
/// <br/>
/// This only works for types that have an implementation of Convert::ToNative and
/// Convert::ToCLI.
/// </summary>
/// <param name="MANAGED_TYPE">The managed type of the object to edit.</param>
/// <param name="NATIVE_TYPE">The native type of the object to edit.</param>
/// <param name="FUNC">The SHEditorUI:: function to use for editing.</param>
#define RENDER_FIELD_CASTED(MANAGED_TYPE, NATIVE_TYPE, FUNC) \
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \
field->SetValue(object, Convert::ToCLI(val)); \
} \
} \
/*-------------------------------------------------------------------------------------*/
/* Function Definitions */
/*-------------------------------------------------------------------------------------*/
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Script Rendering Functions */
/*---------------------------------------------------------------------------------*/
void Editor::RenderScriptsInInspector(Entity entity)
{
SAFE_NATIVE_CALL_BEGIN
// Get scripts
IEnumerable<Script^>^ scripts = ScriptStore::GetAllScripts(entity);
// Skip if no scripts
if (scripts != nullptr)
{
// Display each script if any
int index = 0;
for each (Script^ script in scripts)
{
renderScriptInInspector(entity, script, index++);
}
}
// Render Add Script
RenderScriptAddButton(entity);
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.RenderScriptsInInspector")
}
void Editor::RenderScriptAddButton(Entity entity)
{
// Get list of Scripts
auto scriptTypes = ScriptStore::GetAvailableScriptList();
// Define pop up
if (SHEditorUI::BeginMenu("Add Script", ICON_MD_LIBRARY_ADD))
{
for each (Type ^ type in scriptTypes)
{
if (SHEditorUI::Selectable(Convert::ToNative(type->Name)))
{
// Add the script
ScriptStore::AddScriptViaName(entity, type->Name);
}
}
SHEditorUI::EndMenu();
}
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void Editor::renderScriptInInspector(Entity entity, Script^ script, int index)
{
// Constants
const std::string LABEL = Convert::ToNative(script->GetType()->Name);
// Header
SHEditorUI::PushID(index);
if (SHEditorUI::CollapsingHeader(LABEL))
{
SHEditorUI::PushID(LABEL);
SHEditorUI::Indent();
{
// Right Click Menu
renderScriptContextMenu(entity, script);
// Go through all fields and output them
auto fields = ReflectionUtilities::GetInstanceFields(script);
int id = 0;
for each (auto field in fields)
{
// Ignore non-serialisable fields
if (!ReflectionUtilities::FieldIsSerialisable(field))
continue;
// Render the input field for this field
SHEditorUI::PushID(LABEL + std::to_string(id++));
renderFieldInInspector(field, script);
SHEditorUI::PopID();
}
}
SHEditorUI::Unindent();
SHEditorUI::PopID();
}
else
{
renderScriptContextMenu(entity, script);
}
SHEditorUI::PopID();
}
void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, Object^ object)
{
if RENDER_FIELD (Int16, int, InputInt)
else if RENDER_FIELD (Int32, int, InputInt)
else if RENDER_FIELD (Int64, int, InputInt)
else if RENDER_FIELD (UInt16, unsigned int, InputUnsignedInt)
else if RENDER_FIELD (UInt32, unsigned int, InputUnsignedInt)
else if RENDER_FIELD (UInt64, unsigned int, InputUnsignedInt)
else if RENDER_FIELD (Byte, int, InputInt)
else if RENDER_FIELD (bool, bool, InputCheckbox)
else if RENDER_FIELD (float, float, InputFloat)
else if RENDER_FIELD (double, double, InputDouble)
else if (field->FieldType->IsSubclassOf(Enum::typeid))
{
// Get all the names of the enums
const array<String^>^ ENUM_NAMES = field->FieldType->GetEnumNames();
std::vector<std::string> nativeEnumNames;
for each (String^ str in ENUM_NAMES)
{
nativeEnumNames.emplace_back(Convert::ToNative(str));
}
int val = safe_cast<int>(field->GetValue(object));
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames))
{
field->SetValue(object, val);
}
}
else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2)
else if RENDER_FIELD_CASTED(Vector3, SHVec3, InputVec3)
else if (field->FieldType == String::typeid)
{
// Prevent issues where String^ is null due to being empty
String^ stringVal = safe_cast<String^>(field->GetValue(object));
if (stringVal == nullptr)
{
stringVal = "";
}
// Actual Field
std::string val = Convert::ToNative(stringVal);
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val))
{
field->SetValue(object, Convert::ToCLI(val));
}
}
}
void Editor::renderScriptContextMenu(Entity entity, Script^ script)
{
// Right Click Menu
if (SHEditorUI::BeginPopupContextItem("scriptContextMenu"))
{
if (SHEditorUI::Selectable("Delete Script", ICON_MD_DELETE))
{
// Mark script for removal
ScriptStore::RemoveScript(entity, script);
}
SHEditorUI::EndPopup();
}
}
}

View File

@ -0,0 +1,77 @@
/************************************************************************************//*!
\file Editor.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 27, 2022
\brief Contains the definition of the managed Editor static class.
Note: This file is written in C++17/CLI.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Project Includes
#include "Engine/Entity.hxx"
#include "Scripts/Script.hxx"
namespace SHADE
{
/// <summary>
/// Static class for Editor-related functions
/// </summary>
public ref class Editor abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Script Rendering Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Renders the set of attached Scripts for the specified Entity into the
/// inspector.
/// <br/>
/// This function is meant for consumption from native code in the inspector
/// rendering code.
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
static void RenderScriptsInInspector(Entity entity);
/// <summary>
/// Renders a dropdown button that allows for the addition of PlushieScripts
/// onto the specified Entity.
/// </summary>
/// <param name="entity">The Entity to add PlushieScripts to.</param>
static void RenderScriptAddButton(Entity entity);
private:
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Renders a single specified Script's inspector.
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param>
/// <param name="index">
/// Indices used internally to differentiate each rendered Script
/// inspector. This is required to open and close each Script's inspector
/// independently from each other.
/// </param>
static void renderScriptInInspector(Entity entity, Script^ script, int index);
/// <summary>
/// Renders a field specified into the inspector.
/// </summary>
/// <param name="field">The field to render.</param>
/// <param name="object">
/// The object that contains the data of the field to render.
/// </param>
static void renderFieldInInspector(System::Reflection::FieldInfo^ field, Object^ object);
/// <summary>
/// Renders a context menu when right clicked for the scripts
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
};
}

View File

@ -21,12 +21,14 @@ of DigiPen Institute of Technology is prohibited.
#include <msclr\marshal_cppstd.h> #include <msclr\marshal_cppstd.h>
// External Dependencies // External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Scene/SHSceneGraph.h" #include "Scene/SHSceneGraph.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
// Project Headers // Project Headers
#include "Utility/Convert.hxx" #include "Utility/Convert.hxx"
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "Components/Transform.hxx"
namespace SHADE namespace SHADE
{ {
@ -239,8 +241,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static ECS::ECS() static ECS::ECS()
{ {
// TODO componentMap.Add(createComponentSet<SHTransformComponent, Transform>());
// componentMap.Add(createComponentSet<Transform, Transform>());
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -28,15 +28,8 @@ namespace SHADE
template <typename NativeComponent> template <typename NativeComponent>
NativeComponent* ECS::GetNativeComponent(Entity entity) NativeComponent* ECS::GetNativeComponent(Entity entity)
{ {
// Get native Entity
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity);
// Entity Validity Check
if (nativeEntity == nullptr)
throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity.");
// Null Check // Null Check
NativeComponent* component = SHComponentManager::GetComponent_s<NativeComponent>(nativeEntity); NativeComponent* component = SHComponentManager::GetComponent_s<NativeComponent>(entity);
if (component == nullptr) if (component == nullptr)
throw gcnew System::NullReferenceException("Attempted to get a native Component that does not exist."); throw gcnew System::NullReferenceException("Attempted to get a native Component that does not exist.");
@ -52,7 +45,6 @@ namespace SHADE
{ {
ManagedType::typeid, ManagedType::typeid,
SHComponentManager::AddComponent<NativeType>, SHComponentManager::AddComponent<NativeType>,
SHComponentManager::EnsureComponent<NativeType>,
SHComponentManager::HasComponent<NativeType>, SHComponentManager::HasComponent<NativeType>,
SHComponentManager::RemoveComponent<NativeType> SHComponentManager::RemoveComponent<NativeType>
}; };

View File

@ -99,8 +99,8 @@ namespace SHADE
/// <summary> /// <summary>
/// Pointer to a function for Component manipulation operations. /// Pointer to a function for Component manipulation operations.
/// </summary> /// </summary>
using ComponentFunc = void(*)(const EntityID&); using ComponentFunc = void(*)(EntityID) noexcept;
using ComponentHasFunc = bool(*)(const EntityID&); using ComponentHasFunc = bool(*)(EntityID) noexcept;
/// <summary> /// <summary>
/// Contains a set of Component related data used for resolving operations for /// Contains a set of Component related data used for resolving operations for
/// each Component. /// each Component.
@ -108,11 +108,10 @@ namespace SHADE
value struct ComponentSet value struct ComponentSet
{ {
public: public:
System::Type^ Type; System::Type^ Type;
ComponentFunc AddFunction; ComponentFunc AddFunction;
ComponentHasFunc HasFunction; ComponentHasFunc HasFunction;
ComponentFunc RemoveFunction; ComponentFunc RemoveFunction;
}; };
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -17,8 +17,8 @@ of DigiPen Institute of Technology is prohibited.
// Primary Header // Primary Header
#include "Convert.hxx" #include "Convert.hxx"
// External Dependencies // External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h"
#include <msclr/marshal_cppstd.h> #include <msclr/marshal_cppstd.h>
#include "ECS_Base/Managers/SHEntityManager.h"
namespace SHADE namespace SHADE
{ {
@ -30,6 +30,32 @@ namespace SHADE
return static_cast<Entity>(entity.GetEID()); return static_cast<Entity>(entity.GetEID());
} }
/*---------------------------------------------------------------------------------*/
/* Math Conversions */
/*---------------------------------------------------------------------------------*/
SHVec3 Convert::ToNative(Vector3 vec)
{
const double X = vec.x;
const double Y = vec.y;
const double Z = vec.z;
return SHVec3(X, Y, Z);
}
Vector3 Convert::ToCLI(const SHVec3& vec)
{
return Vector3(vec.x, vec.y, vec.z);
}
SHVec2 Convert::ToNative(Vector2 vec)
{
const double X = vec.x;
const double Y = vec.y;
return SHVec2(X, Y);
}
Vector2 Convert::ToCLI(const SHVec2& vec)
{
return Vector2(vec.x, vec.y);
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* String Conversions */ /* String Conversions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -16,8 +16,12 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies // External Dependencies
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
// Project Includes // Project Includes
#include "Engine/Entity.hxx" #include "Engine/Entity.hxx"
#include "Math/Vector2.hxx"
#include "Math/Vector3.hxx"
namespace SHADE namespace SHADE
{ {
@ -43,6 +47,34 @@ namespace SHADE
/// <returns>Managed representation of the specified Entity.</returns> /// <returns>Managed representation of the specified Entity.</returns>
static Entity ToCLI(SHEntity entity); static Entity ToCLI(SHEntity entity);
/*-----------------------------------------------------------------------------*/
/* Math Conversions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Converts from a managed Vector3 to a native Vector3.
/// </summary>
/// <param name="vec">The managed Vector3 to convert from.</param>
/// <returns>Native copy of a managed Vector3.</returns>
static SHVec3 ToNative(Vector3 vec);
/// <summary>
/// Converts from a native Vector3 to a managed Vector3.
/// </summary>
/// <param name="vec">The native Vector3 to convert from.</param>
/// <returns>Managed copy of a native Vector3.</returns>
static Vector3 ToCLI(const SHVec3& vec);
/// <summary>
/// Converts from a managed Vector2 to a native Vector2.
/// </summary>
/// <param name="vec">The managed Vector2 to convert from.</param>
/// <returns>Native copy of a managed Vector2.</returns>
static SHVec2 ToNative(Vector2 vec);
/// <summary>
/// Converts from a native Vector2 to a managed Vector2.
/// </summary>
/// <param name="vec">The native Vector2 to convert from.</param>
/// <returns>Managed copy of a native Vector2.</returns>
static Vector2 ToCLI(const SHVec2& vec);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* String Conversions */ /* String Conversions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -0,0 +1,31 @@
using SHADE;
using System;
public class RaccoonShowcase : Script
{
public double RotateSpeed = 1.0;
public Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
private Transform Transform;
private double rotation = 0.0;
private Vector3 scale = Vector3.Zero;
private double originalScale = 1.0f;
public RaccoonShowcase(GameObject gameObj) : base(gameObj) {}
protected override void awake()
{
Transform = GetComponent<Transform>();
if (Transform == null)
{
Debug.LogError("Transform is NULL!");
}
originalScale = Transform.LocalScale.z;
}
protected override void update()
{
rotation += RotateSpeed * 0.16;
scale += ScaleSpeed * 0.16;
Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
Transform.LocalScale = new Vector3(System.Math.Abs(System.Math.Sin(scale.x)) * originalScale, System.Math.Abs(System.Math.Cos(scale.y)) * originalScale, System.Math.Abs(System.Math.Sin(scale.z)) * originalScale);
}
}

View File

@ -0,0 +1,24 @@
using SHADE;
using System;
public class RaccoonSpin : Script
{
public double RotateSpeed = 1.0;
private double rotation = 0.0;
private Transform Transform;
public RaccoonSpin(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
Transform = GetComponent<Transform>();
if (Transform == null)
{
Debug.LogError("Transform is NULL!");
}
}
protected override void update()
{
rotation += RotateSpeed * 0.16;
Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
}
}

View File

@ -1,23 +0,0 @@
using SHADE;
public class TestScript : Script
{
public TestScript(GameObject gameObj) : base(gameObj) {}
protected override void awake()
{
Debug.Log("TestScript.Awake()");
}
protected override void start()
{
Debug.Log("TestScript.Start()");
}
protected override void update()
{
Debug.Log("TestScript.Update()");
}
protected override void onDestroy()
{
Debug.Log("TestScript.OnDestroy()");
}
}