Merge remote-tracking branch 'origin/main' into CameraIntegration

This commit is contained in:
Brandon Mak 2022-10-19 16:54:24 +08:00
commit 212e1e7c1f
23 changed files with 1012 additions and 99 deletions

View File

@ -21,6 +21,8 @@
//#==============================================================#
#include <imgui.h>
#include "Serialization/SHSerialization.h"
namespace SHADE
{
@ -171,6 +173,10 @@ namespace SHADE
editor->selectedEntities.clear();
editor->selectedEntities.push_back(eid);
}
if(ImGui::Selectable("Copy"))
{
SHLOG_INFO(SHSerialization::SerializeEntitiesToString(editor->selectedEntities))
}
if(ImGui::Selectable(std::format("{} Delete", ICON_MD_DELETE).data()))
{
SHEntityManager::DestroyEntity(eid);

View File

@ -17,6 +17,8 @@
#include <imgui_internal.h>
#include <rttr/type>
#include "Serialization/SHSerialization.h"
namespace SHADE
{
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -73,7 +75,14 @@ namespace SHADE
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::Selectable("Save"))
{
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
}
if(ImGui::Selectable("Load"))
{
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
}
ImGui::EndMenu();
}
if(ImGui::BeginMenu("Edit"))

View File

@ -67,6 +67,11 @@ namespace SHADE
ImGui::Separator();
}
bool SHEditorUI::IsItemHovered()
{
return ImGui::IsItemHovered();
}
bool SHEditorUI::BeginMenu(const std::string& label)
{
return ImGui::BeginMenu(label.data());
@ -82,6 +87,16 @@ namespace SHADE
ImGui::EndMenu();
}
void SHEditorUI::BeginTooltip()
{
ImGui::BeginTooltip();
}
void SHEditorUI::EndTooltip()
{
ImGui::EndTooltip();
}
/*-----------------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
/*-----------------------------------------------------------------------------------*/
@ -135,24 +150,30 @@ namespace SHADE
return ImGui::Selectable(std::format("{} {}", icon, label).data());
}
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::Checkbox("#", &value);
}
bool SHEditorUI::InputInt(const std::string& label, int& value)
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputInt("#", &value,
1, 10,
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
{
int signedVal = static_cast<int>(value);
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal);
if (CHANGED)
@ -162,64 +183,101 @@ namespace SHADE
}
return CHANGED;
}
bool SHEditorUI::InputFloat(const std::string& label, float& value)
bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputFloat("#", &value,
0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputDouble(const std::string& label, double& value)
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::InputDouble("#", &value,
0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputAngle(const std::string& label, double& value)
bool SHEditorUI::InputAngle(const std::string& label, double& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
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)
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
{
float val = static_cast<float>(value);
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = ImGui::SliderFloat("#", &val,
static_cast<float>(min), static_cast<float>(max), "%.3f",
return ImGui::SliderInt("##", &value,
static_cast<float>(min), static_cast<float>(max), "%d",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/)
{
int val = static_cast<int>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = val;
value = static_cast<int>(val);
}
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered)
{
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");
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderFloat("##", &value,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/)
{
float val = static_cast<float>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<double>(val);
}
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
}
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered, 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", float{}, float{}, 0, isHovered);
}
bool SHEditorUI::InputTextField(const std::string& label, std::string& value, bool* isHovered)
{
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());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED)
@ -229,13 +287,15 @@ namespace SHADE
return CHANGED;
}
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered)
{
// 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());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{

View File

@ -90,12 +90,19 @@ namespace SHADE
static void SameLine();
static void Separator();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Queries */
/*-----------------------------------------------------------------------------*/
static bool IsItemHovered();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Menu */
/*-----------------------------------------------------------------------------*/
static bool BeginMenu(const std::string& label);
static bool BeginMenu(const std::string& label, const char* icon);
static void EndMenu();
static void BeginTooltip();
static void EndTooltip();
/*-----------------------------------------------------------------------------*/
/* ImGui Wrapper Functions - Pop Ups */
@ -165,8 +172,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputCheckbox(const std::string& label, bool& value);
static bool InputCheckbox(const std::string& label, bool& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a integer field widget for integer input.
/// <br/>
@ -174,8 +182,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputInt(const std::string& label, int& value);
static bool InputInt(const std::string& label, int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a integer field widget for unsigned integer input.
/// <br/>
@ -186,8 +195,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputUnsignedInt(const std::string& label, unsigned int& value);
static bool InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for single precision float input.
/// <br/>
@ -195,8 +205,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputFloat(const std::string& label, float& value);
static bool InputFloat(const std::string& label, float& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for double precision float input.
/// <br/>
@ -204,8 +215,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputDouble(const std::string& label, double& value);
static bool InputDouble(const std::string& label, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a decimal field widget for double input with increments of higher
/// steps meant for angle variables.
@ -214,19 +226,57 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputAngle(const std::string& label, double& value);
static bool InputAngle(const std::string& label, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a double slider field widget for double input.
/// Creates an int slider field widget for double input.
/// <br/>
/// Wraps up ImGui::InputSliderFloat().
/// Wraps up ImGui::SliderInt().
/// </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>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, double min, double max, double& value);
static bool InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates an unsigned int slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderInt().
/// </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>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a float slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderFloat().
/// </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>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a double slider field widget for double input.
/// <br/>
/// Wraps up ImGui::SliderFloat().
/// </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>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a 2x double field widget for Vector2 input.
/// <br/>
@ -234,8 +284,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec2(const std::string& label, SHVec2& value);
static bool InputVec2(const std::string& label, SHVec2& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a 3x double field widget for Vector3 input.
/// <br/>
@ -243,8 +294,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
static bool InputVec3(const std::string& label, SHVec3& value, bool* isHovered = nullptr, float speed = 0.1f);
/// <summary>
/// Creates a text field widget for string input.
/// <br/>
@ -252,8 +304,9 @@ namespace SHADE
/// </summary>
/// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>True if the value was changed.</returns>
static bool InputTextField(const std::string& label, std::string& value);
static bool InputTextField(const std::string& label, std::string& value, bool* isHovered = nullptr);
/// <summary>
/// Creates a combo box for enumeration input.
/// </summary>
@ -264,17 +317,19 @@ namespace SHADE
/// <param name="toStrFn">
/// Conversion function from the type of enum to C-style string.
/// </param>
/// <param name="isHovered>If set, stores the hover state of this widget.</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);
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn, bool* isHovered = nullptr);
/// <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>
/// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <returns>Whether the value was modified.</returns>
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames, bool* isHovered = nullptr);
private:

View File

@ -16,11 +16,11 @@ of DigiPen Institute of Technology is prohibited.
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)
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn, bool* isHovered)
{
std::vector<Enum> values;
for (int i = 0; i <= maxVal; ++i)
@ -28,6 +28,11 @@ namespace SHADE
values.emplace_back(static_cast<Enum>(i));
}
bool b = false;
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
{
for (int i = 0; i <= maxVal; ++i)

View File

@ -160,7 +160,7 @@ namespace SHADE
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)
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
{
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
@ -174,6 +174,8 @@ namespace SHADE
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::Text(fieldLabel.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::NextColumn();
for (std::size_t i = 0; i < N; ++i)
{

View File

@ -14,7 +14,6 @@
#pragma once
#include <chrono>
#include "Tools/SHLogger.h"
#include "SH_API.h"
namespace SHADE

View File

@ -115,7 +115,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*---------------------------------------------------------------------------------*/
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity) const
std::string SHScriptEngine::SerialiseScripts(EntityID entity) const
{
// Create buffer needed to store serialised script data
constexpr int BUFFER_SIZE = 10240;
@ -124,7 +124,7 @@ namespace SHADE
// Attempt to serialise the script
std::string result;
if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE))
if (csScriptsSerialise(entity, buffer.get(), BUFFER_SIZE))
{
result = std::string(buffer.get());
}
@ -140,9 +140,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
/* Script Serialisation Functions */
/*-----------------------------------------------------------------------------------*/
void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml) const
void SHScriptEngine::DeserialiseScript(EntityID entity, const std::string& yaml) const
{
csScriptDeserialise(entity.GetEID(), yaml.c_str());
csScriptDeserialise(entity, yaml.c_str());
}
/*-----------------------------------------------------------------------------------*/

View File

@ -148,7 +148,7 @@ namespace SHADE
/// <returns>
/// String that represents the set of scripts attached to the specified Entity.
/// </returns>
std::string SerialiseScripts(const SHEntity& entity) const;
std::string SerialiseScripts(EntityID entity) const;
/// <summary>
/// Loads the specified JSON string and creates a Script for the specified Entity
/// based on the specified JSON string.
@ -157,7 +157,7 @@ namespace SHADE
/// <param name="yaml">
/// The YAML string that represents the Script to load into the Entity.
/// </param>
void DeserialiseScript(const SHEntity& entity, const std::string& yaml) const;
void DeserialiseScript(EntityID entity, const std::string& yaml) const;
/*-----------------------------------------------------------------------------*/
/* Script Editor Functions */

View File

@ -0,0 +1,220 @@
#include "SHpch.h"
#include "SHSerializationHelper.hpp"
#include "SHSerialization.h"
#include <yaml-cpp/yaml.h>
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Scene/SHSceneManager.h"
#include "Tools/SHException.h"
#include "Assets/SHAssetManager.h"
#include <fstream>
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Physics/Components/SHRigidBodyComponent.h"
namespace SHADE
{
void SHSerialization::SerializeSceneToFile(std::filesystem::path const& path)
{
YAML::Emitter out;
SerializeSceneToEmitter(out);
std::ofstream file(path.c_str());
if (file.good())
{
file << out.c_str();
file.close();
}
}
std::string SHSerialization::SerializeSceneToString()
{
YAML::Emitter out;
SerializeSceneToEmitter(out);
return std::basic_string<char>(out.c_str());
}
void SHSerialization::SerializeSceneToEmitter(YAML::Emitter& out)
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto root = sceneGraph.GetRoot();
SHASSERT(root != nullptr, "Root is null. Failed to serialize scene to node.");
auto const& children = root->GetChildren();
out << YAML::BeginSeq;
auto pred = [&out](SHSceneNode* node) {out << SerializeEntityToNode(node); };
sceneGraph.Traverse(pred);
//out << SerializeEntityToNode(child);
out << YAML::EndSeq;
}
static void DeserializeEntity(YAML::iterator& it, YAML::Node const& node, std::vector<EntityID>& createdEntities, EntityID parentEID = MAX_EID)
{
if (!node[EIDNode])
return;
EntityID eid = node[EIDNode].as<EntityID>();
std::string name = "Default";
if (node[EntityNameNode])
name = node[EntityNameNode].as<std::string>();
//Compile component IDs
const auto componentIDList = SHSerialization::GetComponentIDList(node[ComponentsNode]);
eid = SHEntityManager::CreateEntity(componentIDList, eid, name, parentEID);
createdEntities.push_back(eid);
if (node[NumberOfChildrenNode])
{
if(const int numOfChildren = node[NumberOfChildrenNode].as<int>(); numOfChildren > 0)
{
++it;
for (int i = 0; i < numOfChildren; ++i)
{
DeserializeEntity(it, (*it), createdEntities, eid);
if((i + 1) < numOfChildren)
++it;
}
}
}
}
void SHSerialization::DeserializeSceneFromFile(std::filesystem::path const& path)
{
//TODO:Shift to using XQ's FileIO
std::ifstream iFile;
iFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
std::string fileContent = "";
try
{
// Open file
// Read file's buffer contents into streams
iFile.open(path);
std::stringstream fileStream;
fileStream << iFile.rdbuf();
fileContent = fileStream.str();
// Close file handler
iFile.close();
}
catch (std::ifstream::failure e)
{
SHLOG_ERROR("Could not read file");
}
YAML::Node entities = YAML::Load(fileContent);
std::vector<EntityID> createdEntities{};
//Create Entities
for (auto it = entities.begin(); it != entities.end(); ++it)
{
DeserializeEntity(it, (*it), createdEntities);
}
//Initialize Entity
auto entityVecIt = createdEntities.begin();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
InitializeEntity(*it, *entityVecIt++);
}
}
void SHSerialization::EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out)
{
out << SerializeEntityToNode(entityNode);
auto const& children = entityNode->GetChildren();
for(auto const& child : children)
{
EmitEntity(child, out);
}
}
std::string SHSerialization::SerializeEntitiesToString(std::vector<EntityID> const& entities)
{
YAML::Emitter out;
YAML::Node node;
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for (auto const& eid : entities)
{
auto entityNode = sceneGraph.GetNode(eid);
EmitEntity(entityNode, out);
}
return std::basic_string<char>(out.c_str());
}
void SHSerialization::SerializeEntityToFile(std::filesystem::path const& path)
{
}
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
{
YAML::Node node;
auto eid = sceneNode->GetEntityID();
auto entity = SHEntityManager::GetEntityByID(eid);
if (!sceneNode || !entity)
{
node = YAML::Null;
return node;
}
node.SetStyle(YAML::EmitterStyle::Block);
node[EIDNode] = eid;
node[EntityNameNode] = entity->name;
node[IsActiveNode] = sceneNode->IsActive();
auto const& children = sceneNode->GetChildren();
node[NumberOfChildrenNode] = children.size();
YAML::Node components;
if (const auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
{
components[rttr::type::get<SHTransformComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(transform);
}
if (const auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(eid))
{
components[rttr::type::get<SHRenderable>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable);
}
if (const auto rigidbody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
components[rttr::type::get<SHRigidBodyComponent>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(rigidbody);
}
node[ComponentsNode] = components;
return node;
}
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
std::optional<ComponentTypeID> GetComponentID(YAML::Node const& componentNode)
{
if (componentNode[rttr::type::get<ComponentType>().get_name().data()])
return { SHFamilyID<SHComponent>::GetID<ComponentType>() };
else
return std::nullopt;
}
std::vector<ComponentTypeID> SHSerialization::GetComponentIDList(YAML::Node const& componentsNode)
{
std::vector<ComponentTypeID> componentIDList;
auto id = GetComponentID<SHTransformComponent>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
id = GetComponentID<SHRenderable>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
id = GetComponentID<SHRigidBodyComponent>(componentsNode);
if (id.has_value())
componentIDList.push_back(id.value());
return componentIDList;
}
void SHSerialization::InitializeEntity(YAML::Node const& entityNode, EntityID const& eid)
{
auto const componentsNode = entityNode[ComponentsNode];
if (!componentsNode)
return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "SH_API.h"
#include <string>
#include <filesystem>
#include <ECS_Base/Components/SHComponent.h>
namespace YAML
{
class Emitter;
class Node;
}
namespace SHADE
{
class SHSceneNode;
constexpr const char* ComponentsNode = "Components";
constexpr const char* EntityNameNode = "Name";
constexpr const char* EIDNode = "EID";
constexpr const char* IsActiveNode = "IsActive";
constexpr const char* NumberOfChildrenNode = "NumberOfChildren";
struct SH_API SHSerialization
{
//TODO: change paths to resource ID
static void SerializeSceneToFile(std::filesystem::path const& path);
static std::string SerializeSceneToString();
static void SerializeSceneToEmitter(YAML::Emitter& out);
static void DeserializeSceneFromFile(std::filesystem::path const& path);
static void EmitEntity(SHSceneNode* entityNode, YAML::Emitter& out);
static std::string SerializeEntitiesToString(std::vector<EntityID> const& entities);
static void SerializeEntityToFile(std::filesystem::path const& path);
static YAML::Node SerializeEntityToNode(SHSceneNode* sceneNode);
static std::vector<ComponentTypeID> GetComponentIDList(YAML::Node const& componentsNode);
private:
static void InitializeEntity(YAML::Node const& entityNode, EntityID const& eid);
};
}

View File

@ -0,0 +1,204 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
#include <yaml-cpp/yaml.h>
#include <rttr/registration>
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Vector/SHVec2.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
namespace SHADE
{
struct SHSerializationHelper
{
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static std::string SerializeComponentToString(ComponentType* component)
{
return std::string();
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
{
}
static YAML::Node RTTRToNode(const rttr::variant& var)
{
YAML::Node node;
auto varType = var.get_type();
if (varType == rttr::type::get<SHVec4>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec4>().x;
node["Y"] = var.convert<SHVec4>().y;
node["Z"] = var.convert<SHVec4>().z;
node["W"] = var.convert<SHVec4>().w;
}
else if (varType == rttr::type::get<SHVec3>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
node["Z"] = var.convert<SHVec3>().z;
}
else if (varType == rttr::type::get<SHVec2>())
{
node.SetStyle(YAML::EmitterStyle::Flow);
node["X"] = var.convert<SHVec3>().x;
node["Y"] = var.convert<SHVec3>().y;
}
else if (varType.is_arithmetic())
{
bool ok = false;
if (varType == rttr::type::get<bool>())
node = var.to_bool();
else if (varType == rttr::type::get<int8_t>())
node = var.to_int8(&ok);
else if (varType == rttr::type::get<int16_t>())
node = var.to_int16(&ok);
else if (varType == rttr::type::get<int32_t>())
node = var.to_int32(&ok);
else if (varType == rttr::type::get<int64_t>())
node = var.to_int64(&ok);
else if (varType == rttr::type::get<uint8_t>())
node = var.to_uint8(&ok);
else if (varType == rttr::type::get<uint16_t>())
node = var.to_uint16(&ok);
else if (varType == rttr::type::get<uint32_t>())
node = var.to_uint32(&ok);
else if (varType == rttr::type::get<uint64_t>())
node = var.to_uint64(&ok);
else if (varType == rttr::type::get<float>())
node = var.to_float(&ok);
else if (varType == rttr::type::get<double>())
node = var.to_double(&ok);
//else if (varType == rttr::type::get<char>()) //same as uint8_t
// node = var.to_uint8();
}
else if (varType.is_enumeration())
{
bool ok = false;
auto result = var.to_string(&ok);
if (ok)
{
node = var.to_string();
}
else
{
ok = false;
auto value = var.to_uint64(&ok);
if (ok)
node = value;
else
node = YAML::Null;
}
}
else
{
auto properties = var.get_type().get_properties();
for (auto property : properties)
{
node[property.get_name().data()] = RTTRToNode(property.get_value(var));
}
}
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static YAML::Node SerializeComponentToNode(ComponentType* component)
{
YAML::Node node{};
if (!component)
return node;
auto componentType = rttr::type::get<ComponentType>();
node = RTTRToNode(*component);
return node;
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeProperty(ComponentType* component, rttr::property const& prop, YAML::Node const& propertyNode)
{
auto propType = prop.get_type();
if (propType == rttr::type::get<SHVec4>())
{
SHVec4 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>(), propertyNode["W"].as<float>() };
prop.set_value(component, vec);
}
else if (propType == rttr::type::get<SHVec3>())
{
SHVec3 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>() };
prop.set_value(component, vec);
}
else if (propType == rttr::type::get<SHVec2>())
{
SHVec2 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>() };
prop.set_value(component, vec);
}
else if (propType.is_arithmetic())
{
bool ok = false;
if (propType == rttr::type::get<bool>())
prop.set_value(component, propertyNode.as<bool>());
else if (propType == rttr::type::get<int8_t>())
prop.set_value(component, propertyNode.as<int8_t>());
else if (propType == rttr::type::get<int16_t>())
prop.set_value(component, propertyNode.as<int16_t>());
else if (propType == rttr::type::get<int32_t>())
prop.set_value(component, propertyNode.as<int32_t>());
else if (propType == rttr::type::get<int64_t>())
prop.set_value(component, propertyNode.as<int64_t>());
else if (propType == rttr::type::get<uint8_t>())
prop.set_value(component, propertyNode.as<uint8_t>());
else if (propType == rttr::type::get<uint16_t>())
prop.set_value(component, propertyNode.as<uint16_t>());
else if (propType == rttr::type::get<uint32_t>())
prop.set_value(component, propertyNode.as<uint32_t>());
else if (propType == rttr::type::get<uint64_t>())
prop.set_value(component, propertyNode.as<uint64_t>());
else if (propType == rttr::type::get<float>())
prop.set_value(component, propertyNode.as<float>());
else if (propType == rttr::type::get<double>())
prop.set_value(component, propertyNode.as<double>());
}
else if (propType.is_enumeration())
{
auto enumAlign = prop.get_enumeration();
prop.set_value(component, enumAlign.name_to_value(propertyNode.as<std::string>()));
}
else
{
auto properties = propType.get_properties();
for (auto property : properties)
{
InitializeProperty(component, property, propertyNode[property.get_name().data()]);
}
}
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (componentsNode.IsNull())
return;
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{
if (componentNode[prop.get_name().data()])
{
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
}
}
}
};
}

View File

@ -29,6 +29,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/Command/SHCommand.hpp"
#include "TooltipAttribute.hxx"
#include "RangeAttribute.hxx"
// Using Directives
using namespace System;
@ -53,7 +55,44 @@ using namespace System::Collections::Generic;
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered))\
{ \
field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \
} \
/// <summary>
/// Alternative to RENDER_FIELD that checks for RangeAttribute and switches to a slider
/// instead.
/// </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_RANGE(MANAGED_TYPE, NATIVE_TYPE, FUNC) \
(field->FieldType == MANAGED_TYPE::typeid) \
{ \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
\
RangeAttribute^ rangeAttrib = hasAttribute<RangeAttribute^>(field); \
const std::string FIELD_NAME = Convert::ToNative(field->Name); \
bool changed = false; \
if (rangeAttrib) \
{ \
changed = SHEditorUI::InputSlider \
( \
FIELD_NAME, \
static_cast<NATIVE_TYPE>(rangeAttrib->Min), \
static_cast<NATIVE_TYPE>(rangeAttrib->Max), \
val, &isHovered \
); \
} \
else \
{ \
changed = SHEditorUI::FUNC(FIELD_NAME, val, &isHovered); \
} \
\
if (changed) \
{ \
field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
@ -76,7 +115,8 @@ using namespace System::Collections::Generic;
{ \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
\
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val, &isHovered)) \
{ \
field->SetValue(object, Convert::ToCLI(val)); \
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \
@ -196,16 +236,18 @@ namespace SHADE
}
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)
bool isHovered = false;
if RENDER_FIELD_RANGE (Int16, int, InputInt)
else if RENDER_FIELD_RANGE (Int32, int, InputInt)
else if RENDER_FIELD_RANGE (Int64, int, InputInt)
else if RENDER_FIELD_RANGE (UInt16, unsigned int, InputUnsignedInt)
else if RENDER_FIELD_RANGE (UInt32, unsigned int, InputUnsignedInt)
else if RENDER_FIELD_RANGE (UInt64, unsigned int, InputUnsignedInt)
else if RENDER_FIELD_RANGE (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 RENDER_FIELD_RANGE (float, float, InputFloat)
else if RENDER_FIELD_RANGE (double, double, InputDouble)
else if (field->FieldType->IsSubclassOf(Enum::typeid))
{
// Get all the names of the enums
@ -244,6 +286,15 @@ namespace SHADE
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
}
}
// Check if the field has a specific attribute
TooltipAttribute^ toolTip = hasAttribute<TooltipAttribute^>(field);
if (toolTip && isHovered)
{
SHEditorUI::BeginTooltip();
SHEditorUI::Text(Convert::ToNative(toolTip->Description));
SHEditorUI::EndTooltip();
}
}
void Editor::renderScriptContextMenu(Entity entity, Script^ script)
@ -274,4 +325,24 @@ namespace SHADE
SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCLICommand>()));
}
generic<typename Attribute>
Attribute Editor::hasAttribute(System::Reflection::FieldInfo^ field)
{
array<System::Object^>^ attributes = field->GetCustomAttributes(true);
for each (System::Object^ attrib in attributes)
{
try
{
Attribute attribute = safe_cast<Attribute>(attrib);
if (attribute != nullptr)
return attribute;
}
catch (System::InvalidCastException^)
{
continue;
}
}
// Failed to find
return Attribute{};
}
}

View File

@ -23,7 +23,7 @@ namespace SHADE
/// <summary>
/// Static class for Editor-related functions
/// </summary>
public ref class Editor abstract sealed
private ref class Editor abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
@ -48,7 +48,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Undoes the last script inspector change if there is any.
/// </summary>
static void Undo();
/// <summary>
/// Redoes the last script inspector change if there is any.
/// </summary>
static void Redo();
private:
@ -86,5 +92,7 @@ namespace SHADE
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
generic<typename Attribute> where Attribute : System::Attribute
static Attribute hasAttribute(System::Reflection::FieldInfo^ field);
};
}

View File

@ -0,0 +1,39 @@
/************************************************************************************//*!
\file RangeAttribute.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 18, 2022
\brief Contains the definition of the functions of the managed Range Attribute
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.
*//*************************************************************************************/
#include "SHpch.h"
#include "RangeAttribute.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
float RangeAttribute::Min::get()
{
return minVal;
}
float RangeAttribute::Max::get()
{
return maxVal;
}
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
RangeAttribute::RangeAttribute(float min, float max)
: minVal { min }
, maxVal { max }
{}
}

View File

@ -0,0 +1,61 @@
/************************************************************************************//*!
\file RangeAttribute.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 18, 2022
\brief Contains the definition of the managed Range Attribute 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
namespace SHADE
{
/// <summary>
/// Simple attribute to constrain the range of values for a field on the editor.
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class RangeAttribute : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Minimum value for the Ranged field.
/// </summary>
property float Min
{
float get();
}
/// <summary>
/// Maximum value for the Ranged field.
/// </summary>
property float Max
{
float get();
}
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Constructor for a Tooltip attribute that fills in the description.
/// </summary>
/// <param name="description">Text to be shown when a field is hovered.</param>
RangeAttribute(float min, float max);
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
float minVal;
float maxVal;
};
}

View File

@ -0,0 +1,34 @@
/************************************************************************************//*!
\file TooltipAttribute.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 18, 2022
\brief Contains the definition of the functions of the managed Tooltip Attribute
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.
*//*************************************************************************************/
#include "SHpch.h"
#include "TooltipAttribute.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
System::String^ TooltipAttribute::Description::get()
{
return desc;
}
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
TooltipAttribute::TooltipAttribute(System::String^ description)
: desc { description }
{}
}

View File

@ -0,0 +1,53 @@
/************************************************************************************//*!
\file TooltipAttribute.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 18, 2022
\brief Contains the definition of the managed Tooltip Attribute 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
namespace SHADE
{
/// <summary>
/// Simple attribute to provide a field in a script with a tooltip.
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class TooltipAttribute : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Description that is to be shown in the Tooltip.
/// </summary>
property System::String^ Description
{
System::String^ get();
}
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Constructor for a Tooltip attribute that fills in the description.
/// </summary>
/// <param name="description">Text to be shown when a field is hovered.</param>
TooltipAttribute(System::String^ description);
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
System::String^ desc;
};
}

View File

@ -1,27 +1,29 @@
/************************************************************************************//*!
\file SerializeFieldAttribute.cxx
\file Time.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 5, 2021
\brief Contains the definition of the functions of the managed SerializeField
Attribute class.
\date Oct 19, 2022
\brief This file is present so that the properties in Time.hxx would be compiled
into the DLL.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
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 "SerializeFieldAttribute.hxx"
#include "Time.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructors */
/* Properties */
/*---------------------------------------------------------------------------------*/
SerializeField::SerializeField()
{}
double Time::DeltaTime::get()
{
return SHFrameRateController::GetRawDeltaTime();
}
}

View File

@ -0,0 +1,41 @@
/************************************************************************************//*!
\file Time.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 19, 2022
\brief Contains the definition of the Time static class and the definition of
its properties.
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
#include "FRC/SHFramerateController.h"
namespace SHADE
{
/// <summary>
/// Static class that contains the functions for working with time.
/// </summary>
public ref class Time abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Time taken to process the previous frame.
/// Note, is affected by TimeScale. Use UnscaledDeltaTime if you wish to retrieve
/// real world time. This is also affected by MaxDeltaTime clamping that
/// UnscaledDeltaTime is subject to.
/// </summary>
static property double DeltaTime
{
double get();
}
};
}

View File

@ -21,15 +21,6 @@ namespace SHADE
/// </summary>
[System::AttributeUsage(System::AttributeTargets::Field)]
public ref class SerializeField : public System::Attribute
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Default Constructor
/// </summary>
SerializeField();
};
{};
}

View File

@ -3,8 +3,16 @@ using System;
public class RaccoonShowcase : Script
{
public double RotateSpeed = 1.0;
public Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
[SerializeField]
[Tooltip("Speed of the rotation in radians per second.")]
[Range(-1.0f, 2.0f)]
private double RotateSpeed = 1.0;
//[SerializeField]
//[Range(-5, 20)]
//private int test = 5;
[SerializeField]
[Tooltip("Speed of the scaling in radians per second around each axis.")]
private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
private Transform Transform;
private double rotation = 0.0;
private Vector3 scale = Vector3.Zero;

View File

@ -3,7 +3,9 @@ using System;
public class RaccoonSpin : Script
{
public double RotateSpeed = 1.0;
[SerializeField]
[Tooltip("Speed of the rotation in radians per second.")]
private double RotateSpeed = 1.0;
private double rotation = 0.0;
private Transform Transform;
public RaccoonSpin(GameObject gameObj) : base(gameObj) { }