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

This commit is contained in:
Diren D Bharwani 2022-11-17 00:21:18 +08:00
commit 503f32c3a6
15 changed files with 399 additions and 69 deletions

View File

@ -7,7 +7,7 @@
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "ECS_Base/SHECSMacros.h"
#include "Math/SHMath.h"
#include "Math/Vector/SHVec3.h"
#include <optional>
#include <FMOD/fmod_studio.hpp>
#include "SH_API.h"

View File

@ -220,6 +220,87 @@ namespace SHADE
}
template<>
static void DrawComponent(SHRigidBodyComponent* component)
{
if(!component)
return;
ImGui::PushID(SHFamilyID<SHComponent>::GetID<SHRigidBodyComponent>());
const auto componentType = rttr::type::get<SHRigidBodyComponent>();
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
SHRigidBodyComponent::Type rbType = component->GetType();
auto enumAlign = rttr::type::get<SHRigidBodyComponent::Type>().get_enumeration();
auto names = enumAlign.get_names();
std::vector<const char*> list;
for (auto const& name : names)
list.push_back(name.data());
SHEditorWidgets::ComboBox("Type", list, [component] {return static_cast<int>(component->GetType()); }, [component, enumAlign](int const& idx)
{
auto values = enumAlign.get_values();
auto it = std::next(values.begin(), idx);
component->SetType((*it).convert<SHRigidBodyComponent::Type>());
}, "RigidBody Type");
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity");
SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
}
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
{
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag");
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag");
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
SHEditorWidgets::BeginPanel(std::format("{} Constraints", ICON_FA_LOCK).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::TextLabel("Freeze Position");
SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezePositionX(); }, [component](bool const& value) {component->SetFreezePositionX(value); }, "Freeze Position - X"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezePositionY(); }, [component](bool const& value) {component->SetFreezePositionY(value); }, "Freeze Position - Y"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezePositionZ(); }, [component](bool const& value) {component->SetFreezePositionZ(value); }, "Freeze Position - Z");
SHEditorWidgets::TextLabel("Freeze Rotation");
SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezeRotationX(); }, [component](bool const& value) {component->SetFreezeRotationX(value); }, "Freeze Rotation - X"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezeRotationY(); }, [component](bool const& value) {component->SetFreezeRotationY(value); }, "Freeze Rotation - Y"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezeRotationZ(); }, [component](bool const& value) {component->SetFreezeRotationZ(value); }, "Freeze Rotation - Z");
SHEditorWidgets::EndPanel();
}
//Debug Info (Read-Only)
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
{
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
{
SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Angular\nVelocity", { "X", "Y", "Z" }, [component] {return component->GetAngularVelocity(); }, [](SHVec3 const& value) {}, false, "Angular Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
}
if (rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{
SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
}
}
}
else
{
DrawContextMenu(component);
}
ImGui::PopID();
}
template<>
static void DrawComponent(SHColliderComponent* component)
{
@ -278,21 +359,12 @@ namespace SHADE
[&collider]
{
auto offset = collider->GetRotationOffset();
offset.x = SHMath::RadiansToDegrees(offset.x);
offset.y = SHMath::RadiansToDegrees(offset.y);
offset.z = SHMath::RadiansToDegrees(offset.z);
return offset;
},
[&collider](SHVec3 const& vec)
{
const SHVec3 vecInRad
{
SHMath::DegreesToRadians(vec.x)
, SHMath::DegreesToRadians(vec.y)
, SHMath::DegreesToRadians(vec.z)
};
collider->SetRotationOffset(vecInRad);
});
collider->SetRotationOffset(vec);
}, true);
SHEditorWidgets::EndPanel();
}

View File

@ -166,14 +166,14 @@ namespace SHADE
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
static constexpr float defaultLabelColWidth = 80.0f;
const ImGuiContext& g = *GImGui;
bool valueChanged = false;
ImGui::BeginGroup();
ImGui::PushID(label.c_str());
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
ImGui::SetColumnWidth(-1, 80.0f);
ImGui::SetColumnWidth(-1, defaultLabelColWidth);
ImGui::Text(label.c_str());
if (isHovered)
*isHovered |= ImGui::IsItemHovered();
@ -219,7 +219,7 @@ namespace SHADE
}
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
static bool startRecording = false;
if (changed)
if (!(flags & ImGuiSliderFlags_ReadOnly) && changed)
{
if(isAnAngleInRad)
{
@ -255,7 +255,7 @@ namespace SHADE
bool isHovered = false;
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags, &isHovered);
static bool startRecording = false;
if (changed)
if (!(flags & ImGuiSliderFlags_ReadOnly) && changed)
{
SHVec3 old = get();
if(isAnAngleInRad)
@ -293,7 +293,7 @@ namespace SHADE
}
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
static bool startRecording = false;
if (changed)
if (!(flags & ImGuiSliderFlags_ReadOnly) && changed)
{
if(isAnAngleInRad)
{

View File

@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes
#include "Resource/SHHandle.h"
#include "SHCommonTypes.h"
#include "SH_API.h"
namespace SHADE
{
@ -35,7 +36,7 @@ namespace SHADE
Describes a Pipeline along with it's associated properties for this instance.
*/
/***********************************************************************************/
class SHMaterial
class SH_API SHMaterial
{
public:
/*-----------------------------------------------------------------------------*/

View File

@ -43,9 +43,9 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
struct OverrideData
{
size_t Index;
size_t DataSize;
size_t StoredDataOffset;
uint32_t Index;
uint32_t DataSize;
uint32_t StoredDataOffset;
};
/*-----------------------------------------------------------------------------*/

View File

@ -11,6 +11,7 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
#include "SHMaterialInstance.h"
#include "SHMaterial.h"
namespace SHADE
{
@ -34,9 +35,20 @@ namespace SHADE
dataStore.reset(new char[dataStoreSize]);
}
// Check if this was stored before
const uint32_t VAR_IDX = SHADER_INFO->GetVariableIndex(key);
auto existingOverride = std::find_if(overrideData.begin(), overrideData.end(), [&](const OverrideData& od)
{
return od.Index == VAR_IDX;
});
// Otherwise, create it
if (existingOverride == overrideData.end())
{
OverrideData od;
od.Index = SHADER_INFO->GetVariableIndex(key);
od.Index = VAR_IDX;
od.DataSize = sizeof(T);
if (overrideData.empty())
{
od.StoredDataOffset = 0;
@ -47,12 +59,14 @@ namespace SHADE
od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize;
}
// Get offset and modify the memory directly
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + od.StoredDataOffset);
*dataPtr = value;
// Save the override data information
overrideData.emplace_back(std::move(od));
existingOverride = overrideData.end() - 1;
}
// Get offset and modify the memory directly
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + existingOverride->StoredDataOffset);
*dataPtr = value;
// Flag
dataWasChanged = true;
@ -73,8 +87,19 @@ namespace SHADE
{
return PROP_IDX == data.Index;
});
// No overrides, we get from the base material instead
if (prop == overrideData.end())
{
if (baseMaterial)
{
return baseMaterial->GetProperty<T>(key);
}
else
{
throw std::invalid_argument("Attempted to get an property that was not set previously!");
}
}
// Get offset and return the memory directly
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + prop->StoredDataOffset);

View File

@ -91,6 +91,7 @@ namespace SHADE
{
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
material = gfxSystem->AddMaterialInstanceCopy(sharedMaterial);
matChanged = true;
}
return material;

View File

@ -483,6 +483,16 @@ namespace SHADE
return result;
}
SHMatrix SHMatrix::Transform(const SHVec3& pos, const SHVec3& eulerAngles, const SHVec3& scale) noexcept
{
return Scale(scale) * Rotate(eulerAngles) * Translate(pos);
}
SHMatrix SHMatrix::Transform(const SHVec3& pos, const SHQuaternion& rot, const SHVec3& scale) noexcept
{
return Scale(scale) * Rotate(rot) * Translate(pos);
}
SHMatrix SHMatrix::LookAtRH(const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept
{
SHMatrix result;

View File

@ -149,6 +149,9 @@ namespace SHADE
[[nodiscard]] static SHMatrix Scale (float x, float y, float z) noexcept;
[[nodiscard]] static SHMatrix Scale (const SHVec3& scale) noexcept;
[[nodiscard]] static SHMatrix Transform (const SHVec3& pos, const SHVec3& eulerAngles, const SHVec3& scale) noexcept;
[[nodiscard]] static SHMatrix Transform (const SHVec3& pos, const SHQuaternion& rot, const SHVec3& scale) noexcept;
[[nodiscard]] static SHMatrix LookAtRH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept;
[[nodiscard]] static SHMatrix LookAtLH (const SHVec3& eye, const SHVec3& target, const SHVec3& up) noexcept;
[[nodiscard]] static SHMatrix CamToWorldRH (const SHVec3& pos, const SHVec3& forward, const SHVec3& up) noexcept;

View File

@ -179,7 +179,9 @@ namespace SHADE
{
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
{
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = YAML::convert<ComponentType>::encode(*component);
auto componentNode = YAML::convert<ComponentType>::encode(*component);
componentNode[IsActive.data()] = component->isActive;
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = componentNode;
}
}

View File

@ -14,6 +14,8 @@
namespace SHADE
{
static constexpr std::string_view IsActive = "IsActive";
using AssetQueue = std::unordered_map<AssetID, AssetType>;
struct SHSerializationHelper
{
@ -118,9 +120,9 @@ namespace SHADE
YAML::Node node{};
if (!component)
return node;
auto componentType = rttr::type::get<ComponentType>();
node = RTTRToNode(*component);
node[IsActive.data()] = component->isActive;
return node;
}
@ -198,6 +200,9 @@ namespace SHADE
auto componentNode = componentsNode[rttrType.get_name().data()];
if (!componentNode.IsDefined())
return;
if(componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
auto properties = rttrType.get_properties();
for (auto const& prop : properties)
{
@ -227,8 +232,10 @@ namespace SHADE
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
YAML::convert<ComponentType>::decode(GetComponentNode<ComponentType>(componentsNode, eid), *component);
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid);
if (componentNode[IsActive.data()].IsDefined())
component->isActive = componentNode[IsActive.data()].as<bool>();
YAML::convert<ComponentType>::decode(componentNode, *component);
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>

View File

@ -39,13 +39,15 @@ project "SHADE_Managed"
"%{IncludeDir.dotnet}\\include",
"%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.VULKAN}\\include",
"%{IncludeDir.fmod}\\include",
"%{wks.location}/SHADE_Engine/src"
}
libdirs
{
"%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib"
"%{IncludeDir.SDL}/lib",
"%{IncludeDir.fmod}/lib"
}
links
@ -93,16 +95,19 @@ project "SHADE_Managed"
symbols "On"
defines {"_DEBUG"}
links{"librttr_core_d.lib"}
links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
filter "configurations:Release"
optimize "On"
defines{"_RELEASE"}
links{"librttr_core.lib"}
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE"}
links{"librttr_core.lib"}
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
require "vstudio"

View File

@ -0,0 +1,101 @@
/************************************************************************************//*!
\file Audio.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 16, 2022
\brief Contains the function definitions of the managed Audio 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 Header
#include "SHpch.h"
// Primary Header
#include "Audio.hxx"
// External Dependencies
#include "AudioSystem/SHAudioSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Utility/Convert.hxx"
namespace SHADE
{
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
float Audio::BGMVolume::get()
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
return audioSys->GetBgmVolume();
}
void Audio::BGMVolume::set(float value)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->SetBgmVolume(System::Math::Clamp(value, 0.0f, 1.0f));
}
float Audio::SFXVolume::get()
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
return audioSys->GetSfxVolume();
}
void Audio::SFXVolume::set(float value)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->SetSfxVolume(System::Math::Clamp(value, 0.0f, 1.0f));
}
float Audio::MasterVolume::get()
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
return audioSys->GetMasterVolume();
}
void Audio::MasterVolume::set(float value)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->SetMasterVolume(System::Math::Clamp(value, 0.0f, 1.0f));
}
bool Audio::IsPaused::get()
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
return audioSys->GetPaused();
}
void Audio::IsPaused::set(bool value)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->SetPaused(value);
}
/*-----------------------------------------------------------------------------*/
/* Playback Control Functions */
/*-----------------------------------------------------------------------------*/
void Audio::PlaySFXOnce2D(System::String^ path)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->PlayEventOnce(Convert::ToNative(path).data());
}
void Audio::PlaySFXOnce3D(System::String^ path, GameObject gameObject)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->PlayEventOnce(Convert::ToNative(path).data(), true, gameObject.GetEntity(), true);
}
void Audio::PlayBGMOnce2D(System::String^ path)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->PlayEventOnce(Convert::ToNative(path).data(), false);
}
void Audio::PlayBGMOnce3D(System::String^ path, GameObject gameObject)
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->PlayEventOnce(Convert::ToNative(path).data(), false, gameObject.GetEntity(), true);
}
void Audio::StopAllSounds()
{
auto audioSys = SHSystemManager::GetSystem<SHAudioSystem>();
audioSys->StopAllSounds();
}
}

View File

@ -0,0 +1,103 @@
/************************************************************************************//*!
\file Audio.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 16, 2022
\brief Contains the definitions of the managed Audio 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
#include "Engine/GameObject.hxx"
namespace SHADE
{
/// <summary>
/// Static class that contains the functions for interfacing with the Audio system.
/// </summary>
public ref class Audio abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Volume of background music playback. Clamped between 0.0 and 1.0.
/// </summary>
static property float BGMVolume
{
float get();
void set(float value);
}
/// <summary>
/// Volume of sound effects playback. Clamped between 0.0 and 1.0.
/// </summary>
static property float SFXVolume
{
float get();
void set(float value);
}
/// <summary>
/// Overall volume for all audio playback. Clamped between 0.0 and 1.0.
/// </summary>
static property float MasterVolume
{
float get();
void set(float value);
}
/// <summary>
/// Whether or not all audio playback is paused.
/// </summary>
static property bool IsPaused
{
bool get();
void set(bool value);
}
/*-----------------------------------------------------------------------------*/
/* Playback Control Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Plays a sound effect without looping without spatial attenuation.
/// </summary>
/// <param name="path">
/// Path to the audio file relative to the working directory.
/// </param>
static void PlaySFXOnce2D(System::String^ path);
/// <summary>
/// Plays a sound effect without looping with spatial attenuation.
/// </summary>
/// <param name="path">
/// Path to the audio file relative to the working directory.
/// </param>
/// <param name="gameObject">
/// Object whose position is used to play the sound effect.
/// </param>
static void PlaySFXOnce3D(System::String^ path, GameObject gameObject);
/// <summary>
/// Plays background music without looping without spatial attenuation.
/// </summary>
/// <param name="path">
/// Path to the audio file relative to the working directory.
/// </param>
static void PlayBGMOnce2D(System::String^ path);
/// <summary>
/// Plays background music without looping with spatial attenuation.
/// </summary>
/// <param name="path">
/// Path to the audio file relative to the working directory.
/// </param>
/// <param name="gameObject">
/// Object whose position is used to play the background music.
/// </param>
static void PlayBGMOnce3D(System::String^ path, GameObject gameObject);
/// <summary>
/// Stops playback of all sound effects and music.
/// </summary>
static void StopAllSounds();
};
}

View File

@ -52,7 +52,7 @@ namespace SHADE
Vector3 Vector3::GetNormalised()
{
return *this / GetSqrMagnitude();
return *this / GetMagnitude();
}
float Vector3::GetMagnitude()