Fixed shadows with animations #419
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
Name: MD_RigTest01_SkinningTestAnims
|
||||
ID: 203438081
|
||||
Type: 12
|
||||
Sub Assets:
|
||||
Name: Full
|
||||
ID: 231416496
|
||||
Type: 13
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,40 @@
|
|||
Name: racoonAnims
|
||||
ID: 201804216
|
||||
Type: 12
|
||||
Sub Assets:
|
||||
Name: TPose
|
||||
ID: 231493784
|
||||
Type: 13
|
||||
Name: Idle
|
||||
ID: 227450439
|
||||
Type: 13
|
||||
Name: Run
|
||||
ID: 229125027
|
||||
Type: 13
|
||||
Name: Pickup
|
||||
ID: 219605278
|
||||
Type: 13
|
||||
Name: Carry_Idle
|
||||
ID: 231128260
|
||||
Type: 13
|
||||
Name: Carry_Run
|
||||
ID: 227671720
|
||||
Type: 13
|
||||
Name: Throw
|
||||
ID: 223399345
|
||||
Type: 13
|
||||
Name: Sprint
|
||||
ID: 228149757
|
||||
Type: 13
|
||||
Name: Jump_Start
|
||||
ID: 223009573
|
||||
Type: 13
|
||||
Name: Jump_Loop
|
||||
ID: 230974023
|
||||
Type: 13
|
||||
Name: Jump_End
|
||||
ID: 228134756
|
||||
Type: 13
|
||||
Name: Full
|
||||
ID: 223752972
|
||||
Type: 13
|
|
@ -10,6 +10,7 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 1
|
||||
Casting Shadows: false
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
|
@ -18,16 +19,64 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Translate: {x: -0.291508496, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 148542784
|
||||
Material: 121518381
|
||||
Mesh: 149697411
|
||||
Material: 128805346
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 76586906
|
||||
Clip: 76586906
|
||||
Rig: 77816045
|
||||
AnimationController: 0
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
Scripts:
|
||||
- Type: SHADE.Test.AnimTest
|
||||
Enabled: true
|
||||
fullClip: 223752972
|
||||
idleClip: 227450439
|
||||
runClip: 229125027
|
||||
pickUpClip: 219605278
|
||||
- EID: 1
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0.5, z: 0.699999988}
|
||||
Pitch: 0
|
||||
Yaw: 0
|
||||
Roll: 0
|
||||
Width: 1920
|
||||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
FOV: 90
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Leg
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0.332949668, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 0.0710000023, y: 0.0710000023, z: 0.0710000023}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141097368
|
||||
Material: 128805346
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 72178939
|
||||
AnimationController: 0
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: SHADE.Test.AnimTest
|
||||
Enabled: true
|
||||
fullClip: 231416496
|
||||
idleClip: 0
|
||||
runClip: 0
|
||||
pickUpClip: 0
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
|
||||
namespace SHADE.Test
|
||||
{
|
||||
public class AnimTest : Script
|
||||
{
|
||||
#region Serialized Fields
|
||||
[SerializeField]
|
||||
private AnimationClipAsset fullClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset idleClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset runClip;
|
||||
[SerializeField]
|
||||
private AnimationClipAsset pickUpClip;
|
||||
#endregion
|
||||
|
||||
#region Components
|
||||
public Animator Animator { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Lifecycle Functions
|
||||
protected override void awake()
|
||||
{
|
||||
Animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
protected override void update()
|
||||
{
|
||||
// Play loop if shift is held
|
||||
Action<AnimationClipAsset> playFunc = Input.GetKey(Input.KeyCode.LeftShift) ? (x) => Animator.Play(x)
|
||||
: (x) => Animator.PlayOneShot(x);
|
||||
|
||||
// Play animations
|
||||
if (Input.GetKeyUp(Input.KeyCode.Equals))
|
||||
{
|
||||
playFunc(fullClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha1))
|
||||
{
|
||||
playFunc(idleClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha2))
|
||||
{
|
||||
playFunc(runClip);
|
||||
}
|
||||
else if (Input.GetKeyUp(Input.KeyCode.Alpha3))
|
||||
{
|
||||
playFunc(pickUpClip);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Name: AnimTest
|
||||
ID: 165676130
|
||||
Type: 9
|
|
@ -179,6 +179,9 @@ namespace Sandbox
|
|||
|
||||
// Link up SHDebugDraw
|
||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||
|
||||
auto clip = SHResourceManager::LoadOrGet<SHRawAnimation>(77816045);
|
||||
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
|
||||
}
|
||||
|
||||
void SBApplication::Update(void)
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
\file SHAnimationClip.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 20, 2022
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the function definitions of the SHAnimationClip class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Copyright (C) 2023 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.
|
||||
*//*************************************************************************************/
|
||||
|
@ -13,61 +13,26 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHAnimationClip.h"
|
||||
#include "SHRawAnimation.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
||||
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
||||
: rawAnim { rawAnimHandle }
|
||||
, startFrameIndex { firstFrame }
|
||||
, endFrameIndex { lastFrame }
|
||||
, duration { 0.0f }
|
||||
, startTimeStamp { 0.0f }
|
||||
{
|
||||
// Populate keyframes
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
for (const auto& channel : asset.nodeChannels)
|
||||
{
|
||||
// Create a channel
|
||||
Channel newChannel;
|
||||
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||
|
||||
// Populate Keyframes
|
||||
for (const auto& posKey : channel.positionKeys)
|
||||
{
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
||||
}
|
||||
for (const auto& rotKey : channel.rotationKeys)
|
||||
{
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
|
||||
}
|
||||
for (const auto& scaleKey : channel.scaleKeys)
|
||||
{
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value });
|
||||
}
|
||||
|
||||
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||
|
||||
// Compute max frames
|
||||
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
|
||||
|
||||
// Compute total time
|
||||
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
|
||||
|
||||
// Insert the channel
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
}
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
if (!rawAnim)
|
||||
return;
|
||||
|
||||
const float SECS_PER_TICK = 1.0f / static_cast<float>(rawAnim->GetTicksPerSecond());
|
||||
const int ONE_PAST_LAST_FRAME = lastFrame + 1;
|
||||
duration = static_cast<float>(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK;
|
||||
startTimeStamp = static_cast<float>(firstFrame) * SECS_PER_TICK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
\file SHAnimationClip.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Dec 12, 2022
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the definition of the SHAnimationClip struct and related types.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Copyright (C) 2023 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.
|
||||
*//*************************************************************************************/
|
||||
|
@ -14,71 +14,52 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SH_API.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHRawAnimation;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines a single key frame in an animation for a specific type of data.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a animation clip of a 3D animation that is made for a specific model
|
||||
/// rig.
|
||||
/// Represents a snippet of 3D animation that is stored in a SHRawAnimation object.
|
||||
/// </summary>
|
||||
class SH_API SHAnimationClip
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines the animations of a single bone in a rig.
|
||||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
int MaxFrames;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||
/// Constructs an animation clip that contains the following parameters.
|
||||
/// </summary>
|
||||
/// <param name="asset">Animation asset to load.</param>
|
||||
explicit SHAnimationClip(const SHAnimAsset& asset);
|
||||
|
||||
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
|
||||
/// <param name="firstFrame">First frame to be played.</param>
|
||||
/// <param name="lastFrame">Last frame to be played.</param>
|
||||
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||
float GetTotalTime() const noexcept { return totalTime; }
|
||||
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
|
||||
inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
|
||||
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
|
||||
inline float GetTotalDuration() const noexcept { return duration; }
|
||||
inline float GetStartTimeStamp() const noexcept { return startTimeStamp; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::vector<Channel> channels;
|
||||
int ticksPerSecond;
|
||||
float totalTime;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
Handle<SHRawAnimation> rawAnim;
|
||||
int startFrameIndex; // First Frame
|
||||
int endFrameIndex; // Last Frame (inclusive)
|
||||
float duration; // Total playback time
|
||||
float startTimeStamp; // Starting time stamp of the raw anim
|
||||
};
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 22, 2023
|
||||
\brief Contains the definition of SHAnimationController's functions.
|
||||
|
||||
|
||||
Copyright (C) 2023 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 "SHAnimationController.h"
|
||||
#include "SHAnimationSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* AnimParam Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationController::AnimParam::AnimParam(Type type)
|
||||
: ParamType { type }
|
||||
, Value { 0.0f }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Transition - Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHAnimationController::Transition::EvaluateCondition(const AnimParam& testParam) const noexcept
|
||||
{
|
||||
// Don't match, instant fail
|
||||
if (testParam.ParamType != Param.ParamType)
|
||||
return false;
|
||||
|
||||
// Evaluate them accordingly
|
||||
switch (Param.ParamType)
|
||||
{
|
||||
case AnimParam::Type::Bool:
|
||||
case AnimParam::Type::Trigger:
|
||||
return evaluateCondition<bool>(testParam.Value != 0.0f);
|
||||
case AnimParam::Type::Float:
|
||||
return evaluateCondition<float>(testParam.Value);
|
||||
break;
|
||||
case AnimParam::Type::Int:
|
||||
return evaluateCondition<int>(static_cast<int>(testParam.Value));
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationController::Update(InstanceData& instData, float dt)
|
||||
{
|
||||
// Is there a valid node
|
||||
if (!instData.CurrentNode)
|
||||
return;
|
||||
|
||||
// Update the current playback
|
||||
instData.ClipPlaybackTime += dt;
|
||||
|
||||
// Check if we finished playing
|
||||
const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp();
|
||||
if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration())
|
||||
{
|
||||
// Clamp
|
||||
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration();
|
||||
|
||||
// Go to next state
|
||||
bool stateChanged = false;
|
||||
for (const auto& transition : instData.CurrentNode->Transitions)
|
||||
{
|
||||
// Check for no condition special case
|
||||
if (transition.Condition == Transition::ConditionType::None)
|
||||
{
|
||||
changeNode(instData, transition.Target);
|
||||
stateChanged = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we have the parameter
|
||||
if (!instData.Params.contains(transition.ParamName))
|
||||
continue;
|
||||
|
||||
// If evaluation success, we transition
|
||||
AnimParam& param = instData.Params[transition.ParamName];
|
||||
if (transition.EvaluateCondition(param))
|
||||
{
|
||||
changeNode(instData, transition.Target);
|
||||
stateChanged = true;
|
||||
|
||||
// If trigger, we need to unset it
|
||||
if (param.ParamType == AnimParam::Type::Trigger)
|
||||
{
|
||||
param.Value = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle if there is no next state, we repeat
|
||||
if (!stateChanged)
|
||||
{
|
||||
instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationController::Node> SHAnimationController::CreateNode()
|
||||
{
|
||||
// Get system
|
||||
auto system = SHSystemManager::GetSystem<SHAnimationSystem>();
|
||||
if (system == nullptr)
|
||||
throw std::runtime_error("[SHAnimationController] No SHAnimationSystem found!");
|
||||
|
||||
// Construct
|
||||
auto node = system->GetResourceHub().Create<Node>();
|
||||
nodes.emplace_back(node);
|
||||
|
||||
// If there is no start node, this is the first node so make it the starting node
|
||||
if (!StartingNode)
|
||||
StartingNode = node;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void SHAnimationController::DestroyNode(Handle<Node> node)
|
||||
{
|
||||
// Remove from storage
|
||||
auto iter = std::find(nodes.begin(), nodes.end(), node);
|
||||
if (iter == nodes.end())
|
||||
throw std::invalid_argument("[SHAnimationController] Attempted to delete a node that doesn't belong.");
|
||||
|
||||
// Remove if it is a start node
|
||||
if (StartingNode == node)
|
||||
StartingNode = {};
|
||||
|
||||
// Remove from nodes
|
||||
nodes.erase(iter);
|
||||
|
||||
// Clear node
|
||||
node.Free();
|
||||
}
|
||||
|
||||
void SHAnimationController::AddTransition(Handle<Node> source, const Transition& transition)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add transition from an invalid node.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!transition.Target)
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add transition to an invalid node.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (transition.Condition != Transition::ConditionType::None && !parameters.contains(transition.ParamName))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a conditional transition for an invalid parameter.");
|
||||
return;
|
||||
}
|
||||
|
||||
source->Transitions.emplace_back(transition);
|
||||
}
|
||||
void SHAnimationController::AddParameter(const std::string& name, AnimParam::Type type)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a parameter with no name.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameters.contains(name))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to add a parameter with the same name.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert
|
||||
parameters.emplace(name, type);
|
||||
}
|
||||
void SHAnimationController::RemoveParameter(const std::string& name)
|
||||
{
|
||||
if (!parameters.contains(name))
|
||||
{
|
||||
SHLOG_ERROR("[SHAnimationController] Attempted to reemove a parameter that does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.erase(name);
|
||||
}
|
||||
|
||||
void SHAnimationController::SetTrigger(InstanceData& instData, const std::string& paramName)
|
||||
{
|
||||
// Invalid param
|
||||
if (!parameters.contains(paramName))
|
||||
return;
|
||||
|
||||
// Not a trigger
|
||||
if (parameters[paramName] != AnimParam::Type::Trigger)
|
||||
return;
|
||||
|
||||
// Set the flag
|
||||
instData.Params[paramName].Value = true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationController::changeNode(InstanceData& instData, Handle<Node> newNode)
|
||||
{
|
||||
instData.CurrentNode = newNode;
|
||||
instData.ClipPlaybackTime = 0.0f;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 22, 2023
|
||||
\brief Contains the definition of SHAnimationController.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// STL Includes
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
// Project Includes
|
||||
#include "SH_API.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHAnimationClip;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Object that controls the animation that is played by an animator through the use
|
||||
/// of an internal state machine.
|
||||
/// This should never be modified once it has been attached to a SHAnimatorComponent!
|
||||
/// </summary>
|
||||
class SH_API SHAnimationController
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
struct Node;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Describes a parameter for the AnimationController that can be used to control
|
||||
/// the flow of animations.
|
||||
/// </summary>
|
||||
struct SH_API AnimParam
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Type of animation parameter.
|
||||
/// </summary>
|
||||
enum class Type
|
||||
{
|
||||
Bool,
|
||||
Trigger, // Variant of bool that can only be set to true and will be unset when consumed.
|
||||
Float,
|
||||
Int
|
||||
};
|
||||
using ValueType = float;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an AnimParam with the default value set for the Value field based
|
||||
/// on the specified type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of AnimParam.</param>
|
||||
explicit AnimParam(Type type = Type::Int);
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
Type ParamType;
|
||||
ValueType Value;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a transition between nodes of the animation controller.
|
||||
/// </summary>
|
||||
struct Transition
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Types of conditions for the transition.
|
||||
/// </summary>
|
||||
enum class ConditionType
|
||||
{
|
||||
None,
|
||||
Equals,
|
||||
NotEquals,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
Handle<Node> Target;
|
||||
ConditionType Condition = ConditionType::None;
|
||||
AnimParam Param;
|
||||
std::string ParamName;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Checks the condition of this Transition against an animation paramter.
|
||||
/// </summary>
|
||||
/// <param name="testParam">Parameter to test with.</param>
|
||||
/// <returns>Whether the condition passed.</returns>
|
||||
bool EvaluateCondition(const AnimParam& testParam) const noexcept;
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
template<typename T>
|
||||
bool evaluateCondition(T value) const noexcept;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a node in the animation controller.
|
||||
/// </summary>
|
||||
struct Node
|
||||
{
|
||||
std::string Name = "Unnamed Node";
|
||||
Handle<SHAnimationClip> Clip;
|
||||
std::vector<Transition> Transitions;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Describes a node in the animation controller.
|
||||
/// </summary>
|
||||
struct InstanceData
|
||||
{
|
||||
Handle<Node> CurrentNode;
|
||||
std::unordered_map<std::string, AnimParam> Params;
|
||||
float ClipPlaybackTime;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<Node> StartingNode;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Runs a single update for the animation controller.
|
||||
/// </summary>
|
||||
void Update(InstanceData& instData, float dt);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a node in the state machine. Created nodes must be destroyed using
|
||||
/// DestroyNode().
|
||||
/// </summary>
|
||||
/// <returns>Node that was created.</returns>
|
||||
Handle<Node> CreateNode();
|
||||
/// <summary>
|
||||
/// Destroys the node that was created in the state machine.
|
||||
/// </summary>
|
||||
/// <param name="node">Node to destroy.</param>
|
||||
void DestroyNode(Handle<Node> node);
|
||||
/// <summary>
|
||||
/// Links two nodes together with a Transition. This performs some additional
|
||||
/// checking to ensure parameters are valid.
|
||||
/// </summary>
|
||||
/// <param name="source">Source node to transition from.</param>
|
||||
/// <param name="transition">Describes the transition to add.</param>
|
||||
void AddTransition(Handle<Node> source, const Transition& transition);
|
||||
/// <summary>
|
||||
/// Registers a parameter to the animation controller.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the parameter.</param>
|
||||
/// <param name="type">Type of the parameter.</param>
|
||||
void AddParameter(const std::string& name, AnimParam::Type type);
|
||||
/// <summary>
|
||||
/// Removes a parameter from the animation controller.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the parameter.</param>
|
||||
void RemoveParameter(const std::string& name);
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
template<typename T>
|
||||
void SetParameter(InstanceData& instData, const std::string& paramName, T value);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the string. Types are checked and will not return
|
||||
/// a value if there is nothing.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
template<typename T>
|
||||
std::optional<T> GetParameter(InstanceData& instData, const std::string& paramName);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="instData">Data of the instance to update.</param>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(InstanceData& instData, const std::string& paramName);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getters */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::unordered_map<std::string, AnimParam::Type>& GetParams() const noexcept { return parameters; }
|
||||
const std::vector<Handle<Node>>& GetNodes() const noexcept { return nodes; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// State machine
|
||||
std::vector<Handle<Node>> nodes;
|
||||
std::unordered_map<std::string, AnimParam::Type> parameters;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void changeNode(InstanceData& instData, Handle<Node> newNode);
|
||||
};
|
||||
}
|
||||
|
||||
#include "SHAnimationController.hpp"
|
|
@ -0,0 +1,121 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationController.hpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of template functions SHAnimationController.
|
||||
|
||||
Copyright (C) 2023 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 "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T>
|
||||
bool SHAnimationController::Transition::evaluateCondition(T value) const noexcept
|
||||
{
|
||||
// Get the value
|
||||
const T PARAM_VAL = [&]()
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
return Param.Value;
|
||||
else
|
||||
return Param.Value != 0.0f;
|
||||
}();
|
||||
|
||||
// Handle condition type
|
||||
switch (Condition)
|
||||
{
|
||||
case SHAnimationController::Transition::ConditionType::None:
|
||||
return true;
|
||||
case SHAnimationController::Transition::ConditionType::Equals:
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
{
|
||||
static constexpr T EPSILON = static_cast<T>(0.001);
|
||||
return std::abs(std::abs(value) - std::abs(PARAM_VAL)) < EPSILON;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value == PARAM_VAL;
|
||||
}
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::NotEquals:
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
{
|
||||
static constexpr T EPSILON = static_cast<T>(0.001);
|
||||
return std::abs(std::abs(value) - std::abs(PARAM_VAL)) > EPSILON;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value != PARAM_VAL;
|
||||
}
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::LessThan:
|
||||
return PARAM_VAL < value;
|
||||
case SHAnimationController::Transition::ConditionType::LessThanOrEqual:
|
||||
return PARAM_VAL <= value;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThan:
|
||||
return PARAM_VAL > value;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThanOrEqual:
|
||||
return PARAM_VAL >= value;
|
||||
}
|
||||
|
||||
// Neither of the existing cases
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SHAnimationController::SetParameter(InstanceData& instData, const std::string& paramName, T value)
|
||||
{
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, int>, "Only works with bool, float or ints.");
|
||||
|
||||
// Invalid param
|
||||
if (parameters.find(paramName) == parameters.end())
|
||||
return;
|
||||
|
||||
// Set the value
|
||||
instData.Params[paramName].Value = value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::optional<T> SHAnimationController::GetParameter(InstanceData& instData, const std::string& paramName)
|
||||
{
|
||||
static_assert(std::is_same_v<T, bool> || std::is_same_v<T, float> || std::is_same_v<T, int>, "Only works with bool, float or ints.");
|
||||
|
||||
// Invalid param
|
||||
if (parameters.find(paramName) == parameters.end())
|
||||
return {};
|
||||
|
||||
// Check if the type matches
|
||||
const auto TYPE = parameters[paramName];
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
if (TYPE != AnimParam::Type::Bool && TYPE != AnimParam::Type::Trigger)
|
||||
return {};
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, float>)
|
||||
{
|
||||
if (parameters[paramName] != AnimParam::Type::Float)
|
||||
return {};
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, int>)
|
||||
{
|
||||
if (parameters[paramName] != AnimParam::Type::Int)
|
||||
return {};
|
||||
}
|
||||
|
||||
// Return the correct value
|
||||
auto paramIter = instData.Params.find(paramName);
|
||||
if (paramIter != instData.Params.end())
|
||||
{
|
||||
return paramIter->second.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return T(); // Default constructed value
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SH_API.h"
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Resource/SHResourceLibrary.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -51,5 +52,16 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
virtual void Init(void) override final;
|
||||
virtual void Exit(void) override final;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getters */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHResourceHub& GetResourceHub() { return resources; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHResourceHub resources;
|
||||
};
|
||||
}
|
|
@ -33,18 +33,62 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Play()
|
||||
{
|
||||
isPlaying = false;
|
||||
isPlaying = true;
|
||||
playOnce = false;
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
|
||||
{
|
||||
// Ignore if nothing is specified
|
||||
if (!clip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to play an null SHAnimationClip. Use Stop() if stopping animation instead.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove animation controller as we switch to manual play mode
|
||||
animController = {};
|
||||
animInstanceData.CurrentNode = {};
|
||||
animInstanceData.Params.clear();
|
||||
animInstanceData.ClipPlaybackTime = 0.0f;
|
||||
|
||||
// Set accordingly
|
||||
currClip = clip;
|
||||
currPlaybackTime = 0.0f;
|
||||
Play();
|
||||
auto RAW_ANIM = clip->GetRawAnimation();
|
||||
|
||||
// Set up if valid
|
||||
if (currClip && RAW_ANIM)
|
||||
{
|
||||
// Calculate secs for the clip
|
||||
secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond();
|
||||
currPlaybackTime = currClip->GetStartTimeStamp();
|
||||
|
||||
// Start playback
|
||||
Play();
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode())
|
||||
{
|
||||
updateCurrentAnimatorState(currClip, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::PlayOneShot(Handle<SHAnimationClip> clip)
|
||||
{
|
||||
Play(clip);
|
||||
playOnce = true;
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::PlayFromStart()
|
||||
{
|
||||
if (!currClip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to restart a clip but there is no existing clip. Ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
isPlaying = true;
|
||||
currPlaybackTime = 0.0f;
|
||||
}
|
||||
|
@ -56,10 +100,47 @@ namespace SHADE
|
|||
|
||||
void SHAnimatorComponent::Stop()
|
||||
{
|
||||
if (!currClip)
|
||||
{
|
||||
SHLOG_WARNING("[SHAnimatorComponent] Attempted to stop a clip but there is no existing clip. Ignored.");
|
||||
return;
|
||||
}
|
||||
|
||||
isPlaying = false;
|
||||
currPlaybackTime = 0.0f;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Update(float dt)
|
||||
{
|
||||
// Reset matrices
|
||||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
||||
|
||||
// Do not do anything if is not playing or there's nothing to animate
|
||||
if (!isPlaying || !rig || !rig->GetRootNode())
|
||||
return;
|
||||
|
||||
// Update the animation controller if any, this will set the currClip
|
||||
if (animController)
|
||||
{
|
||||
updateAnimController(dt);
|
||||
|
||||
// Only update the animation state if there is a clip
|
||||
if (animInstanceData.CurrentNode && animInstanceData.CurrentNode->Clip)
|
||||
{
|
||||
updateCurrentAnimatorState(animInstanceData.CurrentNode->Clip, animInstanceData.ClipPlaybackTime);
|
||||
}
|
||||
}
|
||||
// Otherwise, a single clip was provided, then we'll use it
|
||||
else if (currClip)
|
||||
{
|
||||
updateManualClipState(dt);
|
||||
updateCurrentAnimatorState(currClip, currPlaybackTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -79,60 +160,118 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
|
||||
void SHAnimatorComponent::SetAnimationController(Handle<SHAnimationController> ac)
|
||||
{
|
||||
// No change
|
||||
if (currClip == newClip)
|
||||
if (animController == ac)
|
||||
return;
|
||||
|
||||
// Set parameters
|
||||
currClip = newClip;
|
||||
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||
// Set the controller
|
||||
animController = ac;
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode() && currClip)
|
||||
// If valid, we want to initialize it
|
||||
if (animController)
|
||||
{
|
||||
updatePoseWithClip(0.0f);
|
||||
// Parameters
|
||||
animInstanceData.Params.clear();
|
||||
for (auto param : animController->GetParams())
|
||||
{
|
||||
animInstanceData.Params.emplace(param.first, SHAnimationController::AnimParam(param.second));
|
||||
}
|
||||
// First Node
|
||||
animInstanceData.CurrentNode = animController->StartingNode;
|
||||
// Playback Time
|
||||
animInstanceData.ClipPlaybackTime = 0.0f;
|
||||
|
||||
// Get set of unique SHRawAnimation used by the animController
|
||||
std::unordered_set<Handle<SHRawAnimation>> rawAnims;
|
||||
for (auto node : animController->GetNodes())
|
||||
{
|
||||
// Ensure no null handles
|
||||
if (!node)
|
||||
continue;
|
||||
const Handle<SHAnimationClip> CLIP = node->Clip;
|
||||
if (!CLIP)
|
||||
continue;
|
||||
const Handle<SHRawAnimation> RAW_ANIM = CLIP->GetRawAnimation();
|
||||
if (!RAW_ANIM)
|
||||
continue;
|
||||
|
||||
// Store
|
||||
rawAnims.emplace(RAW_ANIM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::Update(float dt)
|
||||
|
||||
void SHAnimatorComponent::SetTrigger(const std::string& paramName)
|
||||
{
|
||||
//Reset matrices
|
||||
std::fill(boneMatrices.begin(), boneMatrices.end(), SHMatrix::Identity);
|
||||
|
||||
// Nothing to animate
|
||||
if (!currClip || !isPlaying || !rig || !rig->GetRootNode())
|
||||
if (!animController)
|
||||
return;
|
||||
|
||||
// Update time on the playback
|
||||
currPlaybackTime += dt;
|
||||
if (currPlaybackTime > currClip->GetTotalTime())
|
||||
{
|
||||
currPlaybackTime = currPlaybackTime - currClip->GetTotalTime();
|
||||
}
|
||||
|
||||
// Play the clip
|
||||
updatePoseWithClip(currPlaybackTime);
|
||||
return animController->SetTrigger(animInstanceData, paramName);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/* Helper Functions - Update */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
||||
void SHAnimatorComponent::updateAnimController(float dt)
|
||||
{
|
||||
updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
||||
// No animation controller
|
||||
if (!animInstanceData.CurrentNode)
|
||||
return;
|
||||
|
||||
// Update the animation controller
|
||||
animController->Update(animInstanceData, dt);
|
||||
|
||||
// Get current clip
|
||||
currClip = animInstanceData.CurrentNode->Clip;
|
||||
if (currClip && currClip->GetRawAnimation())
|
||||
{
|
||||
secsPerTick = 1.0f / currClip->GetRawAnimation();
|
||||
}
|
||||
}
|
||||
void SHAnimatorComponent::updateManualClipState(float dt)
|
||||
{
|
||||
currPlaybackTime += dt;
|
||||
const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp();
|
||||
if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration())
|
||||
{
|
||||
if (playOnce)
|
||||
{
|
||||
playOnce = false;
|
||||
isPlaying = false;
|
||||
currPlaybackTime = currClip->GetStartTimeStamp() + currClip->GetTotalDuration();
|
||||
}
|
||||
else
|
||||
{
|
||||
currPlaybackTime = currClip->GetStartTimeStamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
void SHAnimatorComponent::updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime)
|
||||
{
|
||||
// Nothing to animate
|
||||
if (!clip || !isPlaying || !rig || !rig->GetRootNode())
|
||||
return;
|
||||
|
||||
// Check that we have animation data
|
||||
if (!clip->GetRawAnimation())
|
||||
return;
|
||||
|
||||
// Play the clip
|
||||
updatePoseWithClip(clip, playbackTime);
|
||||
}
|
||||
void SHAnimatorComponent::updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime)
|
||||
{
|
||||
updatePoseWithClip(poseTime, clip->GetRawAnimation(), rig->GetRootNode(), SHMatrix::Identity);
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
{
|
||||
// Check if there is a channel for this node
|
||||
SHMatrix transformMatrix = node->TransformMatrix;
|
||||
const int BONE_IDX = rig->GetNodeIndex(node);
|
||||
const auto& CHANNELS = currClip->GetChannels();
|
||||
const auto& CHANNELS = rawAnimData->GetChannels();
|
||||
if (BONE_IDX < CHANNELS.size())
|
||||
{
|
||||
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
||||
|
@ -149,16 +288,15 @@ namespace SHADE
|
|||
|
||||
// Apply transformations to this node
|
||||
const int BONE_MTX_IDX = rig->GetNodeIndex(node);
|
||||
std::optional<SHVec3> position;
|
||||
if (BONE_MTX_IDX >= 0)
|
||||
{
|
||||
boneMatrices[BONE_MTX_IDX] = node->OffsetMatrix * transformMatrix;
|
||||
}
|
||||
|
||||
// Apply pose to children
|
||||
for (auto& child : node->Children)
|
||||
for (auto child : node->Children)
|
||||
{
|
||||
updatePoseWithClip(poseTime, child, transformMatrix);
|
||||
updatePoseWithClip(poseTime, rawAnimData, child, transformMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Math/SHMatrix.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
#include "SHAnimationClip.h"
|
||||
#include "SHRawAnimation.h"
|
||||
#include "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -32,7 +33,6 @@ namespace SHADE
|
|||
class SHRig;
|
||||
struct SHRigNode;
|
||||
class SHAnimationClip;
|
||||
class SHVkBuffer;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -52,12 +52,20 @@ namespace SHADE
|
|||
/// </summary>
|
||||
void Play();
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start.
|
||||
/// Plays the specified animation clip from the start. This will unset any
|
||||
/// SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip"></param>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void Play(Handle<SHAnimationClip> clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start.
|
||||
/// Plays the specified animation clip from the start one time only. This will unset
|
||||
/// any SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void PlayOneShot(Handle<SHAnimationClip> clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start. Note that this only
|
||||
/// works when using manual playback mode.
|
||||
/// </summary>
|
||||
void PlayFromStart();
|
||||
/// <summary>
|
||||
|
@ -65,10 +73,22 @@ namespace SHADE
|
|||
/// </summary>
|
||||
void Pause();
|
||||
/// <summary>
|
||||
/// Stops the animation and resets the play time back to 0.
|
||||
/// Stops the animation and resets the play time back to 0. Note that this only
|
||||
/// works when using manual playback mode. This is not supported when using an
|
||||
/// Animation Controller.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Updates the current state of the animation if one is specified based on the
|
||||
/// current animation clip and frames. This will update the bone matrices.
|
||||
/// </summary>
|
||||
/// <param name="dt">Time passed since the last frame.</param>
|
||||
void Update(float dt);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -78,12 +98,44 @@ namespace SHADE
|
|||
/// <param name="newRig">Rig to use.</param>
|
||||
void SetRig(Handle<SHRig> newRig);
|
||||
/// <summary>
|
||||
/// Sets the animation clip of this animator without playing it.
|
||||
/// This will set the pose of the model to it's initial pose.
|
||||
/// If the clip is the same as the current clip, nothing happens.
|
||||
/// Sets the animation controller to use for this animator.
|
||||
/// </summary>
|
||||
/// <param name="newClip">Clip to use.</param>
|
||||
void SetClip(Handle<SHAnimationClip> newClip);
|
||||
/// <param name="newRig">Animation controller to use.</param>
|
||||
void SetAnimationController(Handle<SHAnimationController> ac);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked. Also does nothing if no
|
||||
/// animation controller is specified.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
template<typename T>
|
||||
void SetParameter(const std::string& paramName, T value);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the string. Types are checked and will not return
|
||||
/// a value if there is nothing. Returns nothing if there is no animation controller
|
||||
/// specified either.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
template<typename T>
|
||||
std::optional<T> GetParameter(const std::string& paramName);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(const std::string& paramName);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
@ -99,38 +151,42 @@ namespace SHADE
|
|||
/// <returns>Handle to the currently set rig.</returns>
|
||||
Handle<SHRig> GetRig() const noexcept { return rig; }
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Retrieve the currently set animation clip.
|
||||
/// </summary>
|
||||
/// <returns>Handle to the currently set animation clip.</returns>
|
||||
Handle<SHAnimationClip> GetCurrentClip() const noexcept { return currClip; }
|
||||
/// <summary>
|
||||
/// Checks if an animation is currently playing.
|
||||
/// </summary>
|
||||
/// <returns>True if an animation clip is currently playing.</returns>
|
||||
bool IsPlaying() const { return isPlaying; }
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Update Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Updates the current state of the animation if one is specified based on the
|
||||
/// current animation clip and frames. This will update the bone matrices.
|
||||
/// Retrieves the current node for the Animation Controller. This returns a null
|
||||
/// if there is no Animation Controller currently set.
|
||||
/// </summary>
|
||||
/// <param name="dt">Time passed since the last frame.</param>
|
||||
void Update(float dt);
|
||||
/// <returns>Handle to the current Animation Controller node.</returns>
|
||||
Handle<SHAnimationController::Node> GetCurrentNode() const noexcept { return animInstanceData.CurrentNode; }
|
||||
/// <summary>
|
||||
/// Retrieves the currently set animation controller.
|
||||
/// </summary>
|
||||
/// <returnsHandle to the currently set animtion controller.</returns>
|
||||
Handle<SHAnimationController> GetAnimationController() const noexcept { return animController; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using ChannelMap = std::unordered_map<std::string, const SHRawAnimation::Channel*>;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
Handle<SHRig> rig;
|
||||
// Playback Tracking for Animation Controller Mode
|
||||
Handle<SHAnimationController> animController;
|
||||
SHAnimationController::InstanceData animInstanceData;
|
||||
// Playback Tracking for Manual Mode
|
||||
Handle<SHAnimationClip> currClip;
|
||||
// Playback Tracking
|
||||
float currPlaybackTime = 0.0f;
|
||||
bool playOnce = false;
|
||||
// Shared Tracking
|
||||
bool isPlaying = true;
|
||||
// Useful Cached Data
|
||||
float secsPerTick = 0.0f;
|
||||
// Buffer
|
||||
std::vector<SHMatrix> boneMatrices;
|
||||
|
@ -138,8 +194,11 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void updatePoseWithClip(float poseTime);
|
||||
void updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
void updateAnimController(float dt);
|
||||
void updateManualClipState(float dt);
|
||||
void updateCurrentAnimatorState(Handle<SHAnimationClip> clip, float playbackTime);
|
||||
void updatePoseWithClip(Handle<SHAnimationClip> clip, float poseTime);
|
||||
void updatePoseWithClip(float poseTime, Handle<SHRawAnimation> rawAnimData, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
template<typename T>
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
||||
|
||||
|
|
|
@ -15,13 +15,31 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SHRig.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "SHAnimationClip.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "SHRawAnimation.h"
|
||||
#include "SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
template<typename T>
|
||||
std::optional<T> SHAnimatorComponent::GetParameter(const std::string& paramName)
|
||||
{
|
||||
if (!animController)
|
||||
return {};
|
||||
|
||||
return animController->GetParameter<T>(animInstanceData, paramName);
|
||||
}
|
||||
template<typename T>
|
||||
void SHAnimatorComponent::SetParameter(const std::string& paramName, T value)
|
||||
{
|
||||
if (!animController)
|
||||
return;
|
||||
|
||||
return animController->SetParameter(animInstanceData, paramName, value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimation.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 20, 2022
|
||||
\brief Contains the function definitions of the SHRawAnimation class.
|
||||
|
||||
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.
|
||||
*//*************************************************************************************/
|
||||
// Pre-compiled Header
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHRawAnimation.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset)
|
||||
{
|
||||
// Populate keyframes
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
for (const auto& channel : asset.nodeChannels)
|
||||
{
|
||||
// Create a channel
|
||||
Channel newChannel;
|
||||
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
|
||||
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
|
||||
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
|
||||
|
||||
// Populate Keyframes
|
||||
for (const auto& posKey : channel.positionKeys)
|
||||
{
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
||||
}
|
||||
for (const auto& rotKey : channel.rotationKeys)
|
||||
{
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
|
||||
}
|
||||
for (const auto& scaleKey : channel.scaleKeys)
|
||||
{
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value});
|
||||
}
|
||||
|
||||
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||
|
||||
// Compute max frames
|
||||
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
|
||||
|
||||
// Compute total time
|
||||
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
|
||||
|
||||
// Insert the channel
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
}
|
||||
|
||||
totalFrames = maxFrames;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimation.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Dec 12, 2022
|
||||
\brief Contains the definition of the SHRawAnimation struct and related types.
|
||||
|
||||
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 "SH_API.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Assets/Asset Types/Models/SHAnimationAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines a single key frame in an animation for a specific type of data.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents the raw 3D animation data for a rigged 3D model.
|
||||
/// </summary>
|
||||
class SH_API SHRawAnimation
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Defines the animations of a single bone in a rig.
|
||||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
int MaxFrames;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
|
||||
/// </summary>
|
||||
/// <param name="asset">Animation asset to load.</param>
|
||||
explicit SHRawAnimation(const SHAnimAsset& asset);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
|
||||
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
|
||||
float GetTotalTime() const noexcept { return totalTime; }
|
||||
int GetTotalFrames() const noexcept { return totalFrames; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::vector<Channel> channels;
|
||||
int ticksPerSecond;
|
||||
float totalTime;
|
||||
int totalFrames;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
};
|
||||
}
|
|
@ -10,8 +10,10 @@
|
|||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Math/SHMath.h"
|
||||
#include "Assets/Asset Types/SHAssetData.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimClipAsset.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Feb 27, 2023
|
||||
\brief Contains the definition of the SHAnimationClip struct and related types.
|
||||
|
||||
Copyright (C) 2023 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 "SH_API.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAnimClipAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
uint32_t firstIndex;
|
||||
uint32_t lastIndex;
|
||||
AssetID animRawDataAssetId; // Not serialised, only populated during runtime from parent asset
|
||||
};
|
||||
|
||||
struct SH_API SHAnimClipContainerAsset final : SHAssetData
|
||||
{
|
||||
AssetID animRawDataAssetId;
|
||||
std::vector<SHAnimClipAsset> clips{};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimControllerAsset.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of the SHAnimControllerAsset struct and related
|
||||
types.
|
||||
|
||||
Copyright (C) 2023 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 <string>
|
||||
|
||||
#include "SH_API.h"
|
||||
#include "SHAssetData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SH_API SHAnimControllerAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
// TODO
|
||||
};
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHBinaryLoader.h"
|
||||
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHAssetData* SHBinaryLoader::Load(AssetPath path)
|
||||
{
|
||||
std::ifstream file{ path, std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Binary Loader] Unable to open file for reading: {}", path.string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
SHAssetData* result{nullptr};
|
||||
|
||||
if (extension == ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
LoadAnimClipContainer(file, result, path);
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHBinaryLoader::Write(SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
std::ofstream file{ path, std::ios::out | std::ios::binary };
|
||||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Binary Loader] Unable to open file for writing: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
|
||||
if (extension == ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
WriteAnimClipContainer(file, data, path);
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHBinaryLoader::WriteAnimClipContainer(std::ofstream& file, SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
auto const& anim = *dynamic_cast<SHAnimClipContainerAsset const*>(data);
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&anim.animRawDataAssetId),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
uint32_t const size {static_cast<uint32_t>(anim.clips.size())};
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&size),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
for (auto const& clip : anim.clips)
|
||||
{
|
||||
uint32_t charCount {static_cast<uint32_t>(clip.name.size())};
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&charCount),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
clip.name.data(),
|
||||
charCount
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&clip.firstIndex),
|
||||
sizeof(uint32_t) * 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void SHBinaryLoader::LoadAnimClipContainer(std::ifstream& file, SHAssetData*& result, AssetPath path)
|
||||
{
|
||||
auto const data = new SHAnimClipContainerAsset();
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data->animRawDataAssetId),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
uint32_t size;
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&size),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
for (auto i{0}; i < size; ++i)
|
||||
{
|
||||
auto& clip {data->clips.emplace_back()};
|
||||
uint32_t charCount;
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&charCount),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
clip.name.resize(charCount);
|
||||
file.read(
|
||||
clip.name.data(),
|
||||
charCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&clip.firstIndex),
|
||||
sizeof(uint32_t) * 2
|
||||
);
|
||||
|
||||
clip.animRawDataAssetId = data->animRawDataAssetId;
|
||||
}
|
||||
|
||||
result = data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHBinaryLoader : SHAssetLoader
|
||||
{
|
||||
SHAssetData* Load(AssetPath path) override;
|
||||
void Write(SHAssetData const* data, AssetPath path) override;
|
||||
|
||||
private:
|
||||
//Individual functions to write files
|
||||
void WriteAnimClipContainer(std::ofstream& file,SHAssetData const* data, AssetPath path);
|
||||
void LoadAnimClipContainer(std::ifstream& file,SHAssetData*& result, AssetPath path);
|
||||
};
|
||||
}
|
|
@ -35,32 +35,32 @@ namespace SHADE
|
|||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string());
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text file for reading: {}", path.string());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::stringstream stream;
|
||||
|
||||
stream << file.rdbuf();
|
||||
|
||||
std::string content = stream.str();
|
||||
|
||||
auto const extension = path.extension().string();
|
||||
SHAssetData* result;
|
||||
|
||||
if (path.extension().string() == SCENE_EXTENSION)
|
||||
if (extension == SCENE_EXTENSION)
|
||||
{
|
||||
auto data = new SHSceneAsset();
|
||||
data->name = path.stem().string();
|
||||
data->data = std::move(content);
|
||||
result = data;
|
||||
}
|
||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||
else if (extension == PREFAB_EXTENSION)
|
||||
{
|
||||
auto data = new SHPrefabAsset();
|
||||
data->name = path.stem().string();
|
||||
data->data = std::move(content);
|
||||
result = data;
|
||||
}
|
||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||
else if (extension == MATERIAL_EXTENSION)
|
||||
{
|
||||
auto data = new SHMaterialAsset();
|
||||
data->name = path.stem().string();
|
||||
|
@ -79,21 +79,23 @@ namespace SHADE
|
|||
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text File: {}", path.string());
|
||||
SHLOG_ERROR("[Text Loader] Unable to open text file for writing: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.extension().string() == SCENE_EXTENSION)
|
||||
auto const extension = path.extension().string();
|
||||
|
||||
if (extension == SCENE_EXTENSION)
|
||||
{
|
||||
auto scene = dynamic_cast<SHSceneAsset const*>(data);
|
||||
file << scene->data;
|
||||
}
|
||||
else if (path.extension().string() == PREFAB_EXTENSION)
|
||||
else if (extension == PREFAB_EXTENSION)
|
||||
{
|
||||
auto prefab = dynamic_cast<SHPrefabAsset const*>(data);
|
||||
file << prefab->data;
|
||||
}
|
||||
else if (path.extension().string() == MATERIAL_EXTENSION)
|
||||
else if (extension == MATERIAL_EXTENSION)
|
||||
{
|
||||
auto material = dynamic_cast<SHMaterialAsset const*>(data);
|
||||
file << material->data;
|
||||
|
|
|
@ -11,10 +11,6 @@
|
|||
#pragma once
|
||||
#include "SHAssetLoader.h"
|
||||
|
||||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextBasedLoader : SHAssetLoader
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* or disclosure of this file or its contents without the prior
|
||||
* written consent of Digipen Institute of Technology is prohibited
|
||||
******************************************************************************/
|
||||
// ReSharper disable All
|
||||
#ifndef SH_ASSET_MACROS_H
|
||||
#define SH_ASSET_MACROS_H
|
||||
|
||||
|
@ -18,22 +19,22 @@
|
|||
// FMOD Fwd Declare
|
||||
namespace FMOD
|
||||
{
|
||||
class Sound;
|
||||
class System;
|
||||
class ChannelGroup;
|
||||
class Channel;
|
||||
class Sound;
|
||||
class System;
|
||||
class ChannelGroup;
|
||||
class Channel;
|
||||
}
|
||||
enum FMOD_RESULT : int;
|
||||
enum FMOD_SPEAKERMODE : int;
|
||||
|
||||
// Typedefs
|
||||
typedef uint32_t AssetID;
|
||||
typedef std::string AssetName;
|
||||
using AssetName = std::string;
|
||||
typedef std::filesystem::path AssetPath;
|
||||
typedef unsigned char* AssetData;
|
||||
typedef std::string AssetMetaVersion;
|
||||
typedef std::string AssetExtension;
|
||||
typedef size_t AssetTypeMeta;
|
||||
typedef size_t AssetTypeMeta;
|
||||
|
||||
typedef FMOD::Sound* SHSound;
|
||||
|
||||
|
@ -45,9 +46,9 @@ constexpr AssetID INVALID_ASSET_ID {0};
|
|||
// Asset type enum
|
||||
enum class AssetType : AssetTypeMeta
|
||||
{
|
||||
INVALID,
|
||||
SHADER,
|
||||
SHADER_BUILT_IN,
|
||||
INVALID,
|
||||
SHADER,
|
||||
SHADER_BUILT_IN,
|
||||
TEXTURE,
|
||||
MODEL,
|
||||
SCENE,
|
||||
|
@ -57,7 +58,10 @@ enum class AssetType : AssetTypeMeta
|
|||
SCRIPT,
|
||||
FONT,
|
||||
AUDIO_BANK,
|
||||
MAX_COUNT
|
||||
ANIM_CONTAINER,
|
||||
ANIM_CLIP,
|
||||
ANIM_CONTROLLER,
|
||||
MAX_COUNT
|
||||
};
|
||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
||||
|
@ -78,6 +82,8 @@ constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" };
|
|||
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
|
||||
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
||||
constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
|
||||
constexpr std::string_view ANIM_CLIP_FOLDER{ "/Animation Clips/" };
|
||||
constexpr std::string_view ANIM_CONTROLLER_FOLDER{ "/Animation Controllers/" };
|
||||
|
||||
|
||||
// ASSET EXTENSIONS
|
||||
|
@ -94,20 +100,26 @@ constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
|||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||
constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
|
||||
constexpr std::string_view ANIM_CONTAINER_EXTENSION{ ".shanimcontainer" };
|
||||
constexpr std::string_view ANIM_CONTROLLER_EXTENSION{ ".shanimcontroller" };
|
||||
constexpr std::string_view FILLER_EXTENSION{"dummy"};
|
||||
|
||||
constexpr std::string_view EXTENSIONS[] = {
|
||||
AUDIO_EXTENSION,
|
||||
SHADER_EXTENSION,
|
||||
SHADER_BUILT_IN_EXTENSION,
|
||||
AUDIO_EXTENSION,
|
||||
SHADER_EXTENSION,
|
||||
SHADER_BUILT_IN_EXTENSION,
|
||||
TEXTURE_EXTENSION,
|
||||
MODEL_EXTENSION,
|
||||
SCENE_EXTENSION,
|
||||
PREFAB_EXTENSION,
|
||||
PREFAB_EXTENSION,
|
||||
MATERIAL_EXTENSION,
|
||||
"dummy",
|
||||
FILLER_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
FONT_EXTENSION,
|
||||
AUDIO_BANK_EXTENSION
|
||||
AUDIO_BANK_EXTENSION,
|
||||
ANIM_CONTAINER_EXTENSION,
|
||||
ANIM_CONTROLLER_EXTENSION,
|
||||
FILLER_EXTENSION
|
||||
};
|
||||
|
||||
constexpr size_t EXTENSIONS_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
@ -120,10 +132,10 @@ constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
|
|||
constexpr std::string_view TTF_EXTENSION{ ".ttf" };
|
||||
|
||||
constexpr std::string_view EXTERNALS[] = {
|
||||
GLSL_EXTENSION,
|
||||
DDS_EXTENSION,
|
||||
FBX_EXTENSION,
|
||||
GLTF_EXTENSION,
|
||||
GLSL_EXTENSION,
|
||||
DDS_EXTENSION,
|
||||
FBX_EXTENSION,
|
||||
GLTF_EXTENSION,
|
||||
TTF_EXTENSION
|
||||
};
|
||||
|
||||
|
@ -133,9 +145,9 @@ constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
|
|||
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
|
||||
|
||||
constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[] = {
|
||||
std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
|
||||
std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
|
||||
std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
|
||||
std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
|
||||
std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
|
||||
std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
|
||||
};
|
||||
|
||||
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
|
||||
|
|
|
@ -21,8 +21,13 @@
|
|||
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
||||
#include "Libraries/Loaders/SHFontLoader.h"
|
||||
#include "Libraries/Loaders/SHBinaryLoader.h"
|
||||
|
||||
#include "Asset Types/SHPrefabAsset.h"
|
||||
#include "Asset Types/SHMaterialAsset.h"
|
||||
#include "Asset Types/SHSceneAsset.h"
|
||||
#include "Asset Types/SHAnimClipContainerAsset.h"
|
||||
|
||||
//#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||
|
||||
|
@ -159,14 +164,24 @@ namespace SHADE
|
|||
return AssetType::INVALID;
|
||||
}
|
||||
|
||||
std::optional<SHADE::SHAsset> SHAssetManager::GetAsset(AssetID id) noexcept
|
||||
SHAsset* SHAssetManager::GetAsset(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
{
|
||||
return assetCollection[id];
|
||||
return &assetCollection[id];
|
||||
}
|
||||
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SHAsset const* SHAssetManager::GetAssetConst(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
{
|
||||
return &assetCollection[id];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::GetAssetIDFromPath(AssetPath const& path) noexcept
|
||||
|
@ -233,8 +248,19 @@ namespace SHADE
|
|||
}
|
||||
break;
|
||||
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
newPath += ANIM_CLIP_FOLDER;
|
||||
newPath += name;
|
||||
newPath += ANIM_CONTAINER_EXTENSION;
|
||||
|
||||
{
|
||||
auto animClip = new SHAnimClipContainerAsset();
|
||||
data = animClip;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal asset type, cannot be created", name);
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal parent asset type, cannot be created", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -249,13 +275,13 @@ namespace SHADE
|
|||
|
||||
auto result = assetCollection.emplace(
|
||||
id,
|
||||
SHAsset(
|
||||
name,
|
||||
id,
|
||||
type,
|
||||
newPath,
|
||||
false
|
||||
)
|
||||
SHAsset(
|
||||
name,
|
||||
id,
|
||||
type,
|
||||
newPath,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
assetData.emplace(id, data);
|
||||
|
@ -266,6 +292,41 @@ namespace SHADE
|
|||
return id;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::CreateNewSubAsset(AssetType type, AssetName name, AssetID parent)
|
||||
{
|
||||
if (!assetData.contains(parent))
|
||||
{
|
||||
SHLOG_ERROR("[Asset Manager] Failed to create new sub asset, parent does not exist: {}", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case AssetType::ANIM_CLIP:
|
||||
{
|
||||
auto const animContainer {dynamic_cast<SHAnimClipContainerAsset*>(assetData[parent])};
|
||||
auto id = GenerateAssetID(type);
|
||||
SHAsset asset{
|
||||
.name = name,
|
||||
.id = id,
|
||||
.type = type,
|
||||
.isSubAsset = true,
|
||||
.parent = parent
|
||||
};
|
||||
auto& newClip {animContainer->clips.emplace_back()};
|
||||
newClip.name = name;
|
||||
assetCollection.emplace(id, asset);
|
||||
assetCollection[parent].subAssets.push_back(&assetCollection[id]);
|
||||
assetData.emplace(id, &newClip);
|
||||
return id;
|
||||
}
|
||||
|
||||
default:
|
||||
SHLOG_ERROR("[Asset Manager] Asset type of {} not an internal sub asset type, cannot be created", name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SHAssetManager::SaveAsset(AssetID id) noexcept
|
||||
{
|
||||
if (assetCollection.contains(id))
|
||||
|
@ -274,7 +335,8 @@ namespace SHADE
|
|||
if (
|
||||
asset.type == AssetType::SCENE ||
|
||||
asset.type == AssetType::PREFAB ||
|
||||
asset.type == AssetType::MATERIAL
|
||||
asset.type == AssetType::MATERIAL ||
|
||||
asset.type == AssetType::ANIM_CONTAINER
|
||||
)
|
||||
{
|
||||
if (assetData.contains(id))
|
||||
|
@ -467,9 +529,9 @@ namespace SHADE
|
|||
|
||||
//Reload data
|
||||
auto result = GetAsset(target);
|
||||
if (result.has_value())
|
||||
if (result)
|
||||
{
|
||||
auto const& asset{ result.value() };
|
||||
auto const& asset{ *result };
|
||||
auto newData = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
delete assetData[target];
|
||||
assetData[target] = newData;
|
||||
|
@ -533,6 +595,8 @@ namespace SHADE
|
|||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
||||
loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader());
|
||||
loaders[static_cast<size_t>(AssetType::AUDIO_BANK)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||
loaders[static_cast<size_t>(AssetType::ANIM_CONTAINER)] = dynamic_cast<SHAssetLoader*>(new SHBinaryLoader());
|
||||
loaders[static_cast<size_t>(AssetType::ANIM_CLIP)] = nullptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -590,16 +654,37 @@ namespace SHADE
|
|||
else
|
||||
{
|
||||
assetData.emplace(parent.id, parentData);
|
||||
if (parent.type == AssetType::MODEL)
|
||||
switch(parent.type)
|
||||
{
|
||||
auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
case AssetType::MODEL:
|
||||
{
|
||||
assetData.emplace(
|
||||
parent.subAssets[i]->id,
|
||||
parentModel->meshes[i]
|
||||
);
|
||||
const auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
parent.subAssets[i]->id,
|
||||
parentModel->meshes[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
{
|
||||
const auto parentContainer = reinterpret_cast<SHAnimClipContainerAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
parent.subAssets[i]->id,
|
||||
&parentContainer->clips[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SHLOG_WARNING("[Asset Manager] Parent type not supported to load sub assets, aborting...");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return assetData[asset.id];
|
||||
|
@ -757,6 +842,38 @@ namespace SHADE
|
|||
|
||||
return newAsset.id;
|
||||
}
|
||||
else if(ext==ANIM_CONTAINER_EXTENSION)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::ANIM_CONTAINER),
|
||||
AssetType::ANIM_CONTAINER,
|
||||
path,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
|
||||
SHAnimClipContainerAsset* const data = reinterpret_cast<SHAnimClipContainerAsset*>(LoadData(newAsset));
|
||||
assetData.emplace(newAsset.id, data);
|
||||
for(auto& clip : data->clips)
|
||||
{
|
||||
SHAsset subAsset{
|
||||
.name = clip.name,
|
||||
.id = GenerateAssetID(AssetType::ANIM_CLIP),
|
||||
.type = AssetType::ANIM_CLIP,
|
||||
.isSubAsset = true,
|
||||
.parent = newAsset.id
|
||||
};
|
||||
|
||||
assetCollection.emplace(subAsset.id, subAsset);
|
||||
assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]);
|
||||
|
||||
assetData.emplace(subAsset.id, &clip);
|
||||
}
|
||||
|
||||
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
|
||||
}
|
||||
}
|
||||
|
||||
void SHAssetManager::BuildAssetCollection() noexcept
|
||||
|
@ -813,7 +930,9 @@ namespace rttr
|
|||
value("Material", AssetType::MATERIAL),
|
||||
value("Mesh", AssetType::MESH),
|
||||
value("Script", AssetType::SCRIPT),
|
||||
value("Font", AssetType::FONT)
|
||||
value("Font", AssetType::FONT),
|
||||
value("Animation Container", AssetType::ANIM_CONTAINER),
|
||||
value("Animation Clip", AssetType::ANIM_CLIP)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ namespace SHADE
|
|||
* \return const& to unordered_map<AssetName, AssetID>
|
||||
****************************************************************************/
|
||||
static std::vector<SHAsset> GetAllAssets() noexcept;
|
||||
static std::optional<SHAsset> GetAsset(AssetID id) noexcept;
|
||||
static SHAsset* GetAsset(AssetID id) noexcept;
|
||||
static SHAsset const* GetAssetConst(AssetID id) noexcept;
|
||||
|
||||
static AssetType GetType(AssetID id) noexcept;
|
||||
|
||||
|
@ -63,6 +64,7 @@ namespace SHADE
|
|||
* \return resource id generated for new asset
|
||||
****************************************************************************/
|
||||
static AssetID CreateNewAsset(AssetType type, AssetName name) noexcept;
|
||||
static AssetID CreateNewSubAsset(AssetType type, AssetName name, AssetID parent);
|
||||
static bool SaveAsset(AssetID id) noexcept;
|
||||
static bool DeleteAsset(AssetID id) noexcept;
|
||||
|
||||
|
|
|
@ -0,0 +1,951 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationControllerEditor.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHAnimationControllerEditor's functions.
|
||||
|
||||
|
||||
Copyright (C) 2023 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 "SHAnimationControllerEditor.h"
|
||||
|
||||
// STL Includes
|
||||
#include <format>
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include <imnodes.h>
|
||||
// Project Includes
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
#include "Editor/SHEditorUI.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Editor/Command/SHCommand.hpp"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||
#include "Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor::SHAnimationControllerEditor()
|
||||
: SHEditorWindow("Animation Controller Editor", ImGuiWindowFlags_MenuBar)
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationControllerEditor::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
|
||||
// Set up caches
|
||||
conditionsList =
|
||||
{
|
||||
"None",
|
||||
"=",
|
||||
"!=",
|
||||
"<",
|
||||
"<=",
|
||||
">",
|
||||
">="
|
||||
};
|
||||
typesList =
|
||||
{
|
||||
"Boolean",
|
||||
"Trigger",
|
||||
"Float",
|
||||
"Integer"
|
||||
};
|
||||
|
||||
// Set up sample animation controller for testing
|
||||
SHAnimationController controller;
|
||||
auto n1 = controller.CreateNode();
|
||||
auto n2 = controller.CreateNode();
|
||||
auto n3 = controller.CreateNode();
|
||||
|
||||
n1->Name = "N1";
|
||||
n2->Name = "N2";
|
||||
n3->Name = "N3";
|
||||
|
||||
SHAnimationController::Transition t;
|
||||
t.Target = n3;
|
||||
|
||||
n1->Transitions.emplace_back(t);
|
||||
n2->Transitions.emplace_back(t);
|
||||
t.Target = n1;
|
||||
n3->Transitions.emplace_back(t);
|
||||
|
||||
Open(controller);
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
if (Begin())
|
||||
{
|
||||
// Only render the node editor if there is controller data
|
||||
if (controllerData.has_value())
|
||||
{
|
||||
// Calculate size of each portion
|
||||
const float WINDOW_WIDTH = ImGui::GetWindowSize().x;
|
||||
const float MAIN_PANEL_COLUMN_WIDTH = WINDOW_WIDTH * 0.7f;
|
||||
const float SIDE_PANELS_COLUMN_WIDTH = (WINDOW_WIDTH - MAIN_PANEL_COLUMN_WIDTH) * 0.5f;
|
||||
|
||||
// Draw
|
||||
drawActiveMenuBar();
|
||||
ImGui::BeginTable("base_table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable);
|
||||
{
|
||||
// Set up Columns
|
||||
ImGui::TableSetupColumn(" Parameters", ImGuiTableColumnFlags_WidthStretch, SIDE_PANELS_COLUMN_WIDTH);
|
||||
ImGui::TableSetupColumn("State Machine", ImGuiTableColumnFlags_WidthFixed, MAIN_PANEL_COLUMN_WIDTH);
|
||||
ImGui::TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthStretch, SIDE_PANELS_COLUMN_WIDTH);
|
||||
|
||||
// Header
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Render menu bars
|
||||
ImGui::TableNextRow();
|
||||
{
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
drawParamsMenuBar();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
drawNodeEditorMenuBar();
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
drawPropertiesMenuBar();
|
||||
}
|
||||
|
||||
// Render contents
|
||||
ImGui::TableNextRow();
|
||||
{
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
drawParamsPanel();
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
drawNodeEditor();
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
drawPropertiesPanel();
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorUI::CenteredText("No animation controller is selected.");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::Open(SHAnimationController& controllerHandle)
|
||||
{
|
||||
controller = controllerHandle;
|
||||
controllerData = deserialise(controller);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimationControllerEditor::drawActiveMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
// Save Button
|
||||
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
controller = serialise(controllerData.value()); // TODO: Actually save the resource
|
||||
}
|
||||
// Discard Button
|
||||
if (ImGui::Button(std::format("{} Discard Changes", ICON_MD_CANCEL).data()))
|
||||
{
|
||||
Open(controller); // TODO: Actually load the resource
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawParamsMenuBar()
|
||||
{
|
||||
// Add Parameter Button
|
||||
if (ImGui::BeginCombo("##Type", std::format("{} Add Parameter", ICON_MD_ADD).data(), ImGuiComboFlags_None))
|
||||
{
|
||||
// All other options
|
||||
for (int i = 0; i < static_cast<int>(typesList.size()); ++i)
|
||||
{
|
||||
if (ImGui::Selectable(typesList[i].c_str()))
|
||||
{
|
||||
int count = 0;
|
||||
std::string paramName = "New Param";
|
||||
while (controllerData->Params.contains(paramName))
|
||||
{
|
||||
paramName = "New Param " + std::to_string(++count);
|
||||
}
|
||||
controllerData->Params.emplace(paramName, static_cast<SHAnimationController::AnimParam::Type>(i));
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawParamsPanel()
|
||||
{
|
||||
int paramId = 0;
|
||||
for (const auto& param : controllerData->Params)
|
||||
{
|
||||
ImGui::PushID(paramId++);
|
||||
if (SHEditorWidgets::InputText
|
||||
(
|
||||
"",
|
||||
[&]() { return param.first; },
|
||||
[&](const std::string& val)
|
||||
{
|
||||
// Remove from previous
|
||||
const SHAnimationController::AnimParam::Type TYPE = param.second;
|
||||
controllerData->Params.erase(param.first);
|
||||
// Put into the new
|
||||
controllerData->Params[val] = TYPE;
|
||||
|
||||
// Update all links
|
||||
for (auto& link : controllerData->Links)
|
||||
{
|
||||
link.second.ParamName = val;
|
||||
}
|
||||
},
|
||||
{}, ImGuiInputTextFlags_EnterReturnsTrue
|
||||
))
|
||||
{
|
||||
ImGui::PopID();
|
||||
break; // Map was modified
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##Type", typesList[static_cast<int>(param.second)].c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
// All other options
|
||||
for (int i = 0; i < static_cast<int>(typesList.size()); ++i)
|
||||
{
|
||||
const bool IS_SELECTED = static_cast<int>(param.second) == i;
|
||||
|
||||
if (ImGui::Selectable(typesList[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<SHAnimationController::AnimParam::Type>>
|
||||
(
|
||||
param.second,
|
||||
static_cast<SHAnimationController::AnimParam::Type>(i),
|
||||
[&](SHAnimationController::AnimParam::Type val)
|
||||
{
|
||||
controllerData->Params[param.first] = val;
|
||||
|
||||
// TODO: This needs to be handled in a custom command
|
||||
// For changing to boolean, we need to change inequalities to not equal, etc.
|
||||
if (val == SHAnimationController::AnimParam::Type::Bool)
|
||||
{
|
||||
for (auto& link : controllerData->Links)
|
||||
{
|
||||
switch (link.second.Condition)
|
||||
{
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThan:
|
||||
case SHAnimationController::Transition::ConditionType::LessThan:
|
||||
link.second.Condition = SHAnimationController::Transition::ConditionType::NotEquals;
|
||||
break;
|
||||
case SHAnimationController::Transition::ConditionType::GreaterThanOrEqual:
|
||||
case SHAnimationController::Transition::ConditionType::LessThanOrEqual:
|
||||
link.second.Condition = SHAnimationController::Transition::ConditionType::Equals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawNodeEditorMenuBar()
|
||||
{
|
||||
// Add Node Button
|
||||
if (ImGui::Button(std::format("{} Add Node", ICON_MD_ADD).data()))
|
||||
{
|
||||
createNode(controllerData.value());
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
// Delete Node Button
|
||||
ImGui::BeginDisabled((ImNodes::NumSelectedNodes() + ImNodes::NumSelectedLinks()) < 1);
|
||||
if (ImGui::Button(std::format("{} Delete Objects", ICON_MD_DELETE).data()))
|
||||
{
|
||||
deleteSelectedLinks();
|
||||
deleteSelectedNodes();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Set Starting Node Button
|
||||
ImGui::BeginDisabled(ImNodes::NumSelectedNodes() != 1);
|
||||
if (ImGui::Button(std::format("{} Set Starting Node", ICON_MD_HOME).data()))
|
||||
{
|
||||
// Get id of selected node
|
||||
int selectedNode = 0;
|
||||
ImNodes::GetSelectedNodes(&selectedNode);
|
||||
controllerData->StartingNode = selectedNode; // We can do this as the ImNodes node index is the same
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawNodeEditor()
|
||||
{
|
||||
static constexpr float NODE_WIDTH = 80.0f;
|
||||
static constexpr float TEXT_FIELD_PADDING = 15.0f;
|
||||
|
||||
ImNodes::BeginNodeEditor();
|
||||
{
|
||||
/* Draw Nodes */
|
||||
for (auto& node : controllerData->Nodes)
|
||||
{
|
||||
// Draw the node
|
||||
ImNodes::BeginNode(node.Index);
|
||||
{
|
||||
// Title
|
||||
ImNodes::BeginNodeTitleBar();
|
||||
{
|
||||
// Starting node marker
|
||||
if (node.Index == controllerData->StartingNode)
|
||||
{
|
||||
const float INDENT = NODE_WIDTH * 0.6f;
|
||||
ImGui::Indent(INDENT);
|
||||
ImGui::Text(ICON_MD_HOME);
|
||||
ImGui::Unindent(INDENT);
|
||||
}
|
||||
|
||||
if (node.EditingName)
|
||||
{
|
||||
if (ImGui::Button(ICON_MD_DONE))
|
||||
{
|
||||
node.EditingName = false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(std::max(ImGui::CalcTextSize(node.Name.c_str()).x + TEXT_FIELD_PADDING, NODE_WIDTH));
|
||||
|
||||
SHEditorUI::InputTextField("", node.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Button(ICON_MD_EDIT))
|
||||
{
|
||||
node.EditingName = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(node.Name.c_str());
|
||||
}
|
||||
}
|
||||
ImNodes::EndNodeTitleBar();
|
||||
|
||||
// Body
|
||||
const auto CLIP_NAME = SHResourceManager::GetAssetName<SHAnimationClip>(node.Clip).value_or("");
|
||||
ImGui::SetNextItemWidth(NODE_WIDTH);
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Clip", CLIP_NAME,
|
||||
[&]()
|
||||
{
|
||||
return SHResourceManager::GetAssetID<SHAnimationClip>(node.Clip).value_or(0);
|
||||
},
|
||||
[&](AssetID id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::ANIM_CLIP)
|
||||
return;
|
||||
node.Clip = SHResourceManager::LoadOrGet<SHAnimationClip>(id);
|
||||
SHResourceManager::FinaliseChanges();
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE, {}, NODE_WIDTH
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (node.Clip)
|
||||
{
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(node.Clip).value_or(0);
|
||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
|
||||
// Input Nodes
|
||||
for (auto inputAttrib : node.InputAttribs)
|
||||
{
|
||||
drawInputNode(inputAttrib.Raw, ImNodesPinShape_CircleFilled);
|
||||
}
|
||||
|
||||
// Render an extra input
|
||||
drawInputNode(getExtraInputAttrib(node.Index).Raw, ImNodesPinShape_Circle);
|
||||
|
||||
// Output Nodes
|
||||
for (auto outputAttrib : node.OutputAttribs)
|
||||
{
|
||||
drawOutputNode(outputAttrib.Raw, node.Index, ImNodesPinShape_TriangleFilled);
|
||||
}
|
||||
|
||||
// Render an extra output
|
||||
drawOutputNode(getExtraOutputAttrib(node.Index).Raw, node.Index, ImNodesPinShape_Triangle);
|
||||
}
|
||||
ImNodes::EndNode();
|
||||
}
|
||||
|
||||
// Draw links
|
||||
for (auto link : controllerData->Links)
|
||||
{
|
||||
ImNodes::Link(link.first, link.second.SourceAttrib.Raw, link.second.DestAttrib.Raw);
|
||||
}
|
||||
}
|
||||
|
||||
ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_BottomRight);
|
||||
ImNodes::EndNodeEditor();
|
||||
|
||||
int sourceAttrib, destAttrib;
|
||||
if (ImNodes::IsLinkCreated(&sourceAttrib, &destAttrib))
|
||||
{
|
||||
// Get the two indices
|
||||
NodeAttributeIndex sourceAttribIndex, destAttribIndex;
|
||||
sourceAttribIndex.Raw = static_cast<uint16_t>(sourceAttrib);
|
||||
destAttribIndex.Raw = static_cast<uint16_t>(destAttrib);
|
||||
|
||||
// Ensure that we can access the nodes
|
||||
if (controllerData->IndexToNodeMap.contains(sourceAttribIndex.OwnerNodeIndex) &&
|
||||
controllerData->IndexToNodeMap.contains(destAttribIndex.OwnerNodeIndex))
|
||||
{
|
||||
// Retrieve the nodes
|
||||
auto inputNodeIter = controllerData->IndexToNodeMap[sourceAttribIndex.OwnerNodeIndex];
|
||||
auto outputNodeIter = *controllerData->IndexToNodeMap[destAttribIndex.OwnerNodeIndex];
|
||||
|
||||
// Create link
|
||||
createLink
|
||||
(
|
||||
controllerData.value(),
|
||||
controllerData->IndexToNodeMap[sourceAttribIndex.OwnerNodeIndex],
|
||||
controllerData->IndexToNodeMap[destAttribIndex.OwnerNodeIndex]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::DEL))
|
||||
{
|
||||
deleteSelectedLinks();
|
||||
deleteSelectedNodes();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawPropertiesMenuBar()
|
||||
{
|
||||
// Set Starting Node Button
|
||||
const int SELECTED_LINKS_COUNT = ImNodes::NumSelectedLinks();
|
||||
ImGui::BeginDisabled(SELECTED_LINKS_COUNT < 1);
|
||||
if (ImGui::Button(std::format("{} Reset Conditions", ICON_MD_SETTINGS_BACKUP_RESTORE).data()))
|
||||
{
|
||||
std::vector<int> selectedLinks(SELECTED_LINKS_COUNT);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
for (auto& link : selectedLinks)
|
||||
{
|
||||
// Get LinkData
|
||||
NodeLinkIndex nodeLinkIndex;
|
||||
nodeLinkIndex.Raw = link;
|
||||
if (!controllerData->Links.contains(nodeLinkIndex.Raw))
|
||||
continue;
|
||||
|
||||
LinkData& linkData = controllerData->Links[nodeLinkIndex.Raw];
|
||||
|
||||
// Ensure that the link is valid
|
||||
if (!controllerData->IndexToNodeMap.contains(nodeLinkIndex.SourceAttribute.OwnerNodeIndex) ||
|
||||
!controllerData->IndexToNodeMap.contains(nodeLinkIndex.DestinationAttribute.OwnerNodeIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
linkData.ParamName = "";
|
||||
linkData.Condition = SHAnimationController::Transition::ConditionType::None;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void SHAnimationControllerEditor::drawPropertiesPanel()
|
||||
{
|
||||
const int SELECTED_LINKS_COUNT = ImNodes::NumSelectedLinks();
|
||||
|
||||
if (SELECTED_LINKS_COUNT > 0)
|
||||
{
|
||||
std::vector<int> selectedLinks(SELECTED_LINKS_COUNT);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
|
||||
// Go through all links and display them
|
||||
int index = 0;
|
||||
for (int link : selectedLinks)
|
||||
{
|
||||
// Get LinkData
|
||||
NodeLinkIndex nodeLinkIndex;
|
||||
nodeLinkIndex.Raw = link;
|
||||
if (!controllerData->Links.contains(nodeLinkIndex.Raw))
|
||||
continue;
|
||||
|
||||
LinkData& linkData = controllerData->Links[nodeLinkIndex.Raw];
|
||||
|
||||
// Ensure that the link is valid
|
||||
if (!controllerData->IndexToNodeMap.contains(nodeLinkIndex.SourceAttribute.OwnerNodeIndex) ||
|
||||
!controllerData->IndexToNodeMap.contains(nodeLinkIndex.DestinationAttribute.OwnerNodeIndex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create name of the link
|
||||
std::ostringstream oss;
|
||||
oss << controllerData->IndexToNodeMap[nodeLinkIndex.SourceAttribute.OwnerNodeIndex]->Name
|
||||
<< " " << ICON_MD_ARROW_RIGHT_ALT << " "
|
||||
<< controllerData->IndexToNodeMap[nodeLinkIndex.DestinationAttribute.OwnerNodeIndex]->Name;
|
||||
|
||||
ImGui::PushID(index++);
|
||||
|
||||
// Display each link
|
||||
if (SHEditorUI::CollapsingHeader(oss.str()))
|
||||
{
|
||||
const bool IS_PARAM_SET = !linkData.ParamName.empty();
|
||||
|
||||
// Anim Parameter
|
||||
ImGui::Text("Parameter");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##Parameter", IS_PARAM_SET ? linkData.ParamName.c_str() : "None", ImGuiComboFlags_None))
|
||||
{
|
||||
// Initial "None" option
|
||||
if (ImGui::Selectable("None", !IS_PARAM_SET))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<std::string>>
|
||||
(
|
||||
linkData.ParamName,
|
||||
std::string{},
|
||||
[&](const std::string& val) { linkData.ParamName = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
if (!IS_PARAM_SET)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
// All other options
|
||||
for (const auto& param : controllerData->Params)
|
||||
{
|
||||
const bool IS_SELECTED = param.first == linkData.ParamName;
|
||||
if (ImGui::Selectable(param.first.c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<std::string>>
|
||||
(
|
||||
linkData.ParamName,
|
||||
param.first,
|
||||
[&](const std::string& val) { linkData.ParamName = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// Properties for an Animation Parameter
|
||||
if (IS_PARAM_SET && controllerData->Params.contains(linkData.ParamName))
|
||||
{
|
||||
const SHAnimationController::AnimParam::Type PARAM_TYPE = controllerData->Params[linkData.ParamName];
|
||||
|
||||
if (PARAM_TYPE != SHAnimationController::AnimParam::Type::Trigger)
|
||||
{
|
||||
// Comparison Type
|
||||
const auto& CURR_COMPARISON = conditionsList[static_cast<int>(linkData.Condition)];
|
||||
ImGui::Text("Condition Type");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##ConditionType", CURR_COMPARISON.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
// We only show equal and not equal for bool
|
||||
const int LAST_ELEM = PARAM_TYPE == SHAnimationController::AnimParam::Type::Bool ? static_cast<int>(SHAnimationController::Transition::ConditionType::NotEquals)
|
||||
: static_cast<int>(conditionsList.size() - 1);
|
||||
// Comparisons
|
||||
for (int i = 0; i <= LAST_ELEM; ++i)
|
||||
{
|
||||
const bool IS_SELECTED = i == static_cast<int>(linkData.Condition);
|
||||
if (ImGui::Selectable(conditionsList[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
SHCommandManager::PerformCommand
|
||||
(
|
||||
std::reinterpret_pointer_cast<SHBaseCommand>
|
||||
(
|
||||
std::make_shared<SHCommand<SHAnimationController::Transition::ConditionType>>
|
||||
(
|
||||
linkData.Condition,
|
||||
static_cast<SHAnimationController::Transition::ConditionType>(i),
|
||||
[&](SHAnimationController::Transition::ConditionType val) { linkData.Condition = val; }
|
||||
)
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// Parameter Value
|
||||
if (linkData.Condition != SHAnimationController::Transition::ConditionType::None)
|
||||
{
|
||||
switch (PARAM_TYPE)
|
||||
{
|
||||
case SHAnimationController::AnimParam::Type::Bool:
|
||||
SHEditorWidgets::CheckBox
|
||||
(
|
||||
"Required State",
|
||||
[&]() { return linkData.ParamThresholdValue != 0.0f; },
|
||||
[&](bool val) { linkData.ParamThresholdValue = static_cast<float>(val); }
|
||||
);
|
||||
break;
|
||||
case SHAnimationController::AnimParam::Type::Float:
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
"Threshold",
|
||||
[&]() { return linkData.ParamThresholdValue; },
|
||||
[&](float val) { linkData.ParamThresholdValue = val; }
|
||||
);
|
||||
break;
|
||||
case SHAnimationController::AnimParam::Type::Int:
|
||||
SHEditorWidgets::DragInt
|
||||
(
|
||||
"Threshold",
|
||||
[&]() { return static_cast<int>(linkData.ParamThresholdValue); },
|
||||
[&](int val) { linkData.ParamThresholdValue = static_cast<float>(val); }
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Select an object to view properties.");
|
||||
}
|
||||
}
|
||||
|
||||
SHAnimationControllerEditor::NodeAttributeIndex SHAnimationControllerEditor::getExtraInputAttrib(uint32_t nodeIndex)
|
||||
{
|
||||
NodeAttributeIndex extraInputAttrib;
|
||||
extraInputAttrib.OwnerNodeIndex = nodeIndex;
|
||||
extraInputAttrib.AttributeIndex = std::numeric_limits<int8_t>::lowest();
|
||||
return extraInputAttrib;
|
||||
}
|
||||
SHAnimationControllerEditor::NodeAttributeIndex SHAnimationControllerEditor::getExtraOutputAttrib(uint32_t nodeIndex)
|
||||
{
|
||||
NodeAttributeIndex extraOutputAttrib;
|
||||
extraOutputAttrib.OwnerNodeIndex = nodeIndex;
|
||||
extraOutputAttrib.AttributeIndex = std::numeric_limits<int8_t>::max();
|
||||
return extraOutputAttrib;
|
||||
}
|
||||
void SHAnimationControllerEditor::drawInputNode(int id, ImNodesPinShape_ pinShape)
|
||||
{
|
||||
ImNodes::BeginInputAttribute(id, pinShape);
|
||||
ImGui::Text("Input");
|
||||
ImNodes::EndInputAttribute();
|
||||
}
|
||||
void SHAnimationControllerEditor::drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape)
|
||||
{
|
||||
static char const* TITLE = "Output";
|
||||
static float RIGHT_PADDING = 20.0f;
|
||||
|
||||
ImNodes::BeginOutputAttribute(id, ImNodesPinShape_TriangleFilled);
|
||||
ImGui::Indent(ImNodes::GetNodeDimensions(parentNodeId).x - ImGui::CalcTextSize(TITLE).x - RIGHT_PADDING);
|
||||
ImGui::Text(TITLE);
|
||||
ImNodes::EndOutputAttribute();
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteSelectedNodes()
|
||||
{
|
||||
const int NUM_SELECTED_NODES= ImNodes::NumSelectedNodes();
|
||||
if (NUM_SELECTED_NODES > 0)
|
||||
{
|
||||
std::vector<int> selectedNodes(NUM_SELECTED_NODES);
|
||||
ImNodes::GetSelectedNodes(selectedNodes.data());
|
||||
|
||||
for (auto nodeId : selectedNodes)
|
||||
{
|
||||
deleteNode(controllerData.value(), nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteSelectedLinks()
|
||||
{
|
||||
const int NUM_SELECTED_LINKS = ImNodes::NumSelectedLinks();
|
||||
if (NUM_SELECTED_LINKS > 0)
|
||||
{
|
||||
std::vector<int> selectedLinks(NUM_SELECTED_LINKS);
|
||||
ImNodes::GetSelectedLinks(selectedLinks.data());
|
||||
|
||||
for (auto linkId : selectedLinks)
|
||||
{
|
||||
deleteLink(controllerData.value(), linkId);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::list<SHAnimationControllerEditor::Node>::iterator SHAnimationControllerEditor::createNode(AnimControllerData& data)
|
||||
{
|
||||
const NodeIndex NEW_NODE_IDX = data.NextNodeIndex++;
|
||||
|
||||
Node localNode;
|
||||
localNode.Index = NEW_NODE_IDX;
|
||||
data.Nodes.emplace_back(std::move(localNode));
|
||||
|
||||
// Update the node map
|
||||
auto nodeIter = --data.Nodes.end();
|
||||
data.IndexToNodeMap[NEW_NODE_IDX] = nodeIter;
|
||||
|
||||
return nodeIter;
|
||||
}
|
||||
SHAnimationControllerEditor::LinkMap::iterator SHAnimationControllerEditor::createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode)
|
||||
{
|
||||
// Update source node's output attributes
|
||||
NodeAttributeIndex attribIndex;
|
||||
attribIndex.OwnerNodeIndex = sourceNode->Index;
|
||||
attribIndex.AttributeIndex = static_cast<int8_t>(sourceNode->OutputAttribs.size() + 1);
|
||||
sourceNode->OutputAttribs.emplace_back(attribIndex);
|
||||
|
||||
// Update target node's input attributes
|
||||
attribIndex.OwnerNodeIndex = destNode->Index;
|
||||
attribIndex.AttributeIndex = static_cast<int8_t>(-(destNode->InputAttribs.size() + 1));
|
||||
destNode->InputAttribs.emplace_back(attribIndex);
|
||||
|
||||
// Create link
|
||||
LinkData link;
|
||||
link.SourceNode = sourceNode;
|
||||
link.TargetNode = destNode;
|
||||
link.SourceAttrib = sourceNode->OutputAttribs.back();
|
||||
link.DestAttrib = destNode->InputAttribs.back();
|
||||
NodeLinkIndex linkIdx;
|
||||
linkIdx.SourceAttribute = link.SourceAttrib;
|
||||
linkIdx.DestinationAttribute = link.DestAttrib;
|
||||
|
||||
const auto EMPLACE_DATA = data.Links.emplace(linkIdx.Raw, std::move(link));
|
||||
sourceNode->Transitions.emplace_back(linkIdx);
|
||||
|
||||
return EMPLACE_DATA.first;
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteLink(AnimControllerData& data, LinkIndex link)
|
||||
{
|
||||
const NodeLinkIndex LINK_IDX { link };
|
||||
|
||||
// Error check, don't do anything if they don't exist
|
||||
if (!data.IndexToNodeMap.contains(LINK_IDX.SourceAttribute.OwnerNodeIndex) ||
|
||||
!data.IndexToNodeMap.contains(LINK_IDX.DestinationAttribute.OwnerNodeIndex))
|
||||
return;
|
||||
|
||||
// Get source node and attributes
|
||||
auto& sourceNode = *data.IndexToNodeMap[LINK_IDX.SourceAttribute.OwnerNodeIndex];
|
||||
auto& destNode = *data.IndexToNodeMap[LINK_IDX.DestinationAttribute.OwnerNodeIndex];
|
||||
|
||||
// Remove attributes
|
||||
std::erase(sourceNode.OutputAttribs, LINK_IDX.SourceAttribute);
|
||||
std::erase(destNode.InputAttribs, LINK_IDX.DestinationAttribute);
|
||||
|
||||
// Remove link
|
||||
std::erase(sourceNode.Transitions, LINK_IDX);
|
||||
data.Links.erase(link);
|
||||
}
|
||||
void SHAnimationControllerEditor::deleteNode(AnimControllerData& data, NodeIndex nodeIndex)
|
||||
{
|
||||
// Get node to delete
|
||||
if (!data.IndexToNodeMap.contains(nodeIndex))
|
||||
return;
|
||||
auto nodeToDeleteIter = data.IndexToNodeMap[nodeIndex];
|
||||
|
||||
// Remove all links to other nodes
|
||||
for (auto link : nodeToDeleteIter->Transitions)
|
||||
{
|
||||
deleteLink(data, link.Raw);
|
||||
}
|
||||
|
||||
// Remove all links from other nodes
|
||||
for (auto node : data.Nodes)
|
||||
{
|
||||
for (NodeLinkIndex link : node.Transitions)
|
||||
{
|
||||
if (link.DestinationAttribute.OwnerNodeIndex == nodeIndex)
|
||||
{
|
||||
deleteLink(data, link.Raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then finally, delete this node
|
||||
data.IndexToNodeMap.erase(nodeIndex);
|
||||
data.Nodes.erase(nodeToDeleteIter);
|
||||
|
||||
// If the starting node was this node, we need to reassign
|
||||
if (data.StartingNode == nodeIndex)
|
||||
{
|
||||
data.StartingNode = data.Nodes.empty() ? data.NextNodeIndex : data.Nodes.front().Index;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor::AnimControllerData SHAnimationControllerEditor::deserialise(const SHAnimationController& controller)
|
||||
{
|
||||
AnimControllerData data;
|
||||
|
||||
// Maps controller nodes to data nodes
|
||||
std::unordered_map<Handle<SHAnimationController::Node>, std::list<Node>::iterator> nodeMap;
|
||||
|
||||
// Load anim parameters
|
||||
data.Params = controller.GetParams();
|
||||
|
||||
// Load nodes and links
|
||||
for (auto node : controller.GetNodes())
|
||||
{
|
||||
auto localNode = createNode(data);
|
||||
localNode->Name = node->Name;
|
||||
localNode->Clip = node->Clip;
|
||||
nodeMap.emplace(node, localNode);
|
||||
}
|
||||
|
||||
// Load links
|
||||
for (auto node : controller.GetNodes())
|
||||
{
|
||||
// Get the corresponding data node
|
||||
auto dataNodeIter = nodeMap[node];
|
||||
|
||||
for (auto transition : node->Transitions)
|
||||
{
|
||||
// Invalid node check
|
||||
if (!nodeMap.contains(transition.Target))
|
||||
continue;
|
||||
|
||||
// Get the target node
|
||||
auto targetNodeIter = nodeMap[transition.Target];
|
||||
|
||||
// Create link
|
||||
auto& linkData = createLink(data, dataNodeIter, targetNodeIter)->second;
|
||||
linkData.Condition = transition.Condition;
|
||||
linkData.ParamName = transition.ParamName;
|
||||
linkData.ParamThresholdValue = transition.Param.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark starting node
|
||||
if (nodeMap.contains(controller.StartingNode))
|
||||
{
|
||||
data.StartingNode = nodeMap[controller.StartingNode]->Index;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
SHAnimationController SHAnimationControllerEditor::serialise(const AnimControllerData& data)
|
||||
{
|
||||
SHAnimationController controller;
|
||||
|
||||
// Maps data nodes to controller nodes
|
||||
std::unordered_map<NodeIndex, Handle<SHAnimationController::Node>> nodeMap;
|
||||
|
||||
// Create all nodes first
|
||||
for (const auto& node : data.Nodes)
|
||||
{
|
||||
auto newNode = controller.CreateNode();
|
||||
newNode->Name = node.Name;
|
||||
newNode->Clip = node.Clip;
|
||||
|
||||
nodeMap[node.Index] = newNode;
|
||||
}
|
||||
|
||||
// Create links
|
||||
for (const auto& node : data.Nodes)
|
||||
{
|
||||
// Get controller node
|
||||
auto controllerNode = nodeMap[node.Index];
|
||||
|
||||
for (auto link : node.Transitions)
|
||||
{
|
||||
// Ignore invalid link
|
||||
if (!nodeMap.contains(link.SourceAttribute.OwnerNodeIndex) || !nodeMap.contains(link.DestinationAttribute.OwnerNodeIndex))
|
||||
continue;
|
||||
|
||||
// Get link data
|
||||
const LinkData& LINK_DATA = data.Links.at(link.Raw);
|
||||
|
||||
SHAnimationController::Transition transition;
|
||||
transition.Target = nodeMap[link.DestinationAttribute.OwnerNodeIndex];
|
||||
|
||||
if (data.Params.contains(LINK_DATA.ParamName))
|
||||
{
|
||||
transition.Condition = LINK_DATA.Condition;
|
||||
transition.ParamName = LINK_DATA.ParamName;
|
||||
transition.Param.ParamType = data.Params.at(LINK_DATA.ParamName);
|
||||
transition.Param.Value = LINK_DATA.ParamThresholdValue;
|
||||
}
|
||||
|
||||
controllerNode->Transitions.emplace_back(std::move(transition));
|
||||
}
|
||||
}
|
||||
|
||||
// Starting Node
|
||||
if (nodeMap.contains(data.StartingNode))
|
||||
{
|
||||
controller.StartingNode = nodeMap[data.StartingNode];
|
||||
}
|
||||
|
||||
// Parameters
|
||||
for (auto param : data.Params)
|
||||
{
|
||||
controller.AddParameter(param.first, param.second);
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHAnimationControllerEditor.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHAnimationControllerEditor.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
// External Dependencies
|
||||
#include <imnodes.h>
|
||||
// Project Includes
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor for modifying the Animation Controller state machine.
|
||||
/// </summary>
|
||||
class SHAnimationControllerEditor final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimationControllerEditor();
|
||||
~SHAnimationControllerEditor() = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Open(SHAnimationController& controller);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using NodeIndex = uint8_t;
|
||||
using LinkIndex = int32_t;
|
||||
union NodeAttributeIndex
|
||||
{
|
||||
uint16_t Raw;
|
||||
struct
|
||||
{
|
||||
NodeIndex OwnerNodeIndex;
|
||||
int8_t AttributeIndex; // Negative is input, positive is output
|
||||
};
|
||||
|
||||
bool operator==(NodeAttributeIndex rhs) const noexcept { return Raw == rhs.Raw; }
|
||||
};
|
||||
union NodeLinkIndex
|
||||
{
|
||||
LinkIndex Raw;
|
||||
struct
|
||||
{
|
||||
NodeAttributeIndex SourceAttribute;
|
||||
NodeAttributeIndex DestinationAttribute;
|
||||
};
|
||||
|
||||
bool operator==(NodeLinkIndex rhs) const noexcept { return Raw != rhs.Raw; }
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
NodeIndex Index;
|
||||
std::string Name = "Unnamed Node";
|
||||
Handle<SHAnimationClip> Clip;
|
||||
std::vector<NodeAttributeIndex> InputAttribs;
|
||||
std::vector<NodeAttributeIndex> OutputAttribs;
|
||||
std::vector<NodeLinkIndex> Transitions;
|
||||
bool EditingName = false;
|
||||
};
|
||||
|
||||
struct LinkData
|
||||
{
|
||||
// Source/Dest Data
|
||||
std::list<Node>::iterator SourceNode;
|
||||
std::list<Node>::iterator TargetNode;
|
||||
NodeAttributeIndex SourceAttrib;
|
||||
NodeAttributeIndex DestAttrib;
|
||||
// Conditional Data
|
||||
SHAnimationController::Transition::ConditionType Condition = SHAnimationController::Transition::ConditionType::None;
|
||||
std::string ParamName;
|
||||
SHAnimationController::AnimParam::ValueType ParamThresholdValue;
|
||||
};
|
||||
|
||||
using LinkMap = std::unordered_map<LinkIndex, LinkData>;
|
||||
|
||||
struct AnimControllerData
|
||||
{
|
||||
NodeIndex StartingNode = 0;
|
||||
std::list<Node> Nodes;
|
||||
std::unordered_map<std::string, SHAnimationController::AnimParam::Type> Params;
|
||||
LinkMap Links;
|
||||
int NextNodeIndex = 0; // Index to use for newly created nodes
|
||||
std::unordered_map<NodeIndex, std::list<Node>::iterator> IndexToNodeMap;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimationController controller;
|
||||
std::optional<AnimControllerData> controllerData;
|
||||
// Persistent Cached Data
|
||||
std::vector<std::string> conditionsList;
|
||||
std::vector<std::string> typesList;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void drawActiveMenuBar();
|
||||
void drawParamsMenuBar();
|
||||
void drawParamsPanel();
|
||||
void drawNodeEditorMenuBar();
|
||||
void drawNodeEditor();
|
||||
void drawPropertiesMenuBar();
|
||||
void drawPropertiesPanel();
|
||||
NodeAttributeIndex getExtraInputAttrib(uint32_t nodeIndex);
|
||||
NodeAttributeIndex getExtraOutputAttrib(uint32_t nodeIndex);
|
||||
void drawInputNode(int id, ImNodesPinShape_ pinShape);
|
||||
void drawOutputNode(int id, int parentNodeId, ImNodesPinShape_ pinShape);
|
||||
void deleteSelectedNodes();
|
||||
void deleteSelectedLinks();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static std::list<Node>::iterator createNode(AnimControllerData& data);
|
||||
static LinkMap::iterator createLink(AnimControllerData& data, std::list<Node>::iterator sourceNode, std::list<Node>::iterator destNode);
|
||||
static void deleteLink(AnimControllerData& data, LinkIndex link);
|
||||
static void deleteNode(AnimControllerData& data, NodeIndex nodeIndex);
|
||||
static AnimControllerData deserialise(const SHAnimationController& controller);
|
||||
static SHAnimationController serialise(const AnimControllerData& data);
|
||||
};
|
||||
}
|
|
@ -22,7 +22,11 @@
|
|||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Serialization/SHSerialization.h"
|
||||
#include <Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.h>
|
||||
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||
#include "Serialization/Prefab/SHPrefabManager.h"
|
||||
#include "Editor/EditorWindow/RawAnimationInspector/SHRawAnimInspector.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -367,11 +371,12 @@ namespace SHADE
|
|||
{
|
||||
switch (asset->type)
|
||||
{
|
||||
case AssetType::INVALID: break;
|
||||
case AssetType::SHADER: break;
|
||||
case AssetType::SHADER_BUILT_IN: break;
|
||||
case AssetType::TEXTURE: break;
|
||||
case AssetType::MESH: break;
|
||||
case AssetType::INVALID: break;
|
||||
case AssetType::SHADER: break;
|
||||
case AssetType::SHADER_BUILT_IN: break;
|
||||
case AssetType::TEXTURE: break;
|
||||
case AssetType::MODEL: break;
|
||||
case AssetType::MESH: break;
|
||||
case AssetType::SCENE:
|
||||
{
|
||||
if(editor->LoadScene(asset->id))
|
||||
|
@ -382,7 +387,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
break;
|
||||
case AssetType::PREFAB: break;
|
||||
case AssetType::PREFAB: break;
|
||||
case AssetType::MATERIAL:
|
||||
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||
{
|
||||
|
@ -395,6 +400,12 @@ namespace SHADE
|
|||
scriptEngine->OpenFile(asset->path);
|
||||
}
|
||||
break;
|
||||
case AssetType::ANIM_CONTAINER:
|
||||
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
|
||||
{
|
||||
animInspector->Open(asset->id);
|
||||
}
|
||||
break;
|
||||
case AssetType::MAX_COUNT: break;
|
||||
default:;
|
||||
}
|
||||
|
@ -480,6 +491,48 @@ namespace SHADE
|
|||
isAssetBeingCreated = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
{
|
||||
auto const models {SHAssetManager::GetAllRecordOfType(AssetType::MODEL)};
|
||||
|
||||
ImGui::RadioButton("Animation Clip Container", true);
|
||||
ImGui::SameLine();
|
||||
static char const* const modelPrompt = "Select a model with animations";
|
||||
char const* currentItem = modelPrompt;
|
||||
AssetID selected {0};
|
||||
if (ImGui::BeginCombo("##combo", currentItem, ImGuiComboFlags_None))
|
||||
{
|
||||
for (auto const& model : models)
|
||||
{
|
||||
bool isSelected = currentItem == model.name;
|
||||
if (ImGui::Selectable(model.name.data(), isSelected))
|
||||
{
|
||||
auto const data {SHAssetManager::GetConstData<SHModelAsset>(model.id)};
|
||||
if (!data->anims.empty())
|
||||
{
|
||||
const auto animContainerId = SHAssetManager::CreateNewAsset(AssetType::ANIM_CONTAINER, model.name + "Anims");
|
||||
auto data = SHAssetManager::GetData<SHAnimClipContainerAsset>(animContainerId);
|
||||
data->animRawDataAssetId = model.id;
|
||||
SHAssetManager::SaveAsset(animContainerId);
|
||||
if (auto animInspector = SHEditorWindowManager::GetEditorWindow<SHRawAnimInspector>())
|
||||
{
|
||||
animInspector->Open(animContainerId);
|
||||
}
|
||||
QueueRefresh();
|
||||
isAssetBeingCreated = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
//if (ImGui::BeginMenu("Create Asset"))
|
||||
|
|
|
@ -454,7 +454,8 @@ namespace SHADE
|
|||
{
|
||||
if(auto entityTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f));
|
||||
SHVec3 scale = entityTransform->GetLocalScale();
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + scale * 0.5f);
|
||||
camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition());
|
||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../SHEditorWindowManager.h"
|
||||
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||
#include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderableComponent.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -273,8 +274,8 @@ namespace SHADE
|
|||
}
|
||||
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::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag", 0.1f, 0.0001f, std::numeric_limits<float>::infinity());
|
||||
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag", 0.1f, 0.0001f, std::numeric_limits<float>::infinity());
|
||||
|
||||
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
|
||||
|
||||
|
@ -377,7 +378,8 @@ namespace SHADE
|
|||
(
|
||||
"Radius",
|
||||
[sphereShape] { return sphereShape->GetRelativeRadius(); },
|
||||
[sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }
|
||||
[sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
}
|
||||
else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||
|
@ -388,13 +390,15 @@ namespace SHADE
|
|||
(
|
||||
"Radius",
|
||||
[capsuleShape] { return capsuleShape->GetRelativeRadius(); },
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); }
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeRadius(value); }, "Collider Radius", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
"Height",
|
||||
[capsuleShape] { return capsuleShape->GetRelativeHeight(); },
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); }
|
||||
[capsuleShape](float const& value) { capsuleShape->SetRelativeHeight(value); }, "Collider Height", 0.1f,
|
||||
0.0001f, std::numeric_limits<float>::infinity()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -639,23 +643,29 @@ namespace SHADE
|
|||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||
{
|
||||
DrawContextMenu(component);
|
||||
|
||||
/* Animation Rig */
|
||||
Handle<SHRig> const& rig = component->GetRig();
|
||||
const auto RIG_NAME = rig ? SHResourceManager::GetAssetName<SHRig>(rig).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Rig", RIG_NAME, [component]()
|
||||
{
|
||||
Handle<SHRig> const& rig = component->GetRig();
|
||||
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Rig", RIG_NAME, [component]()
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||
return;
|
||||
}
|
||||
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
Handle<SHRig> const& rig = component->GetRig();
|
||||
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non mesh rig asset to Animator Rig property!")
|
||||
return;
|
||||
}
|
||||
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (Handle<SHRig> const& rig = component->GetRig())
|
||||
|
@ -664,28 +674,34 @@ namespace SHADE
|
|||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
||||
[component]()
|
||||
{
|
||||
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
|
||||
return SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::MODEL)
|
||||
|
||||
/* Animation Controller */
|
||||
Handle<SHAnimationController> animController = component->GetAnimationController();
|
||||
const auto AC_NAME = animController ? SHResourceManager::GetAssetName<SHAnimationController>(animController).value_or("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Animation Controller", AC_NAME, [component]()
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||
return;
|
||||
}
|
||||
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
Handle<SHAnimationController> ac = component->GetAnimationController();
|
||||
return SHResourceManager::GetAssetID<SHAnimationController>(ac).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
if (SHAssetManager::GetType(id) != AssetType::ANIM_CONTROLLER)
|
||||
{
|
||||
SHLOG_WARNING("Attempted to assign non animation controller asset to Animator Animation Controller property!")
|
||||
return;
|
||||
}
|
||||
component->SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
},
|
||||
SHDragDrop::DRAG_RESOURCE
|
||||
);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
if (Handle<SHAnimationClip> const& clip = component->GetCurrentClip())
|
||||
if (Handle<SHAnimationController> ac = component->GetAnimationController())
|
||||
{
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
|
||||
AssetID assetID = SHResourceManager::GetAssetID<SHAnimationController>(ac).value_or(0);
|
||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "SHEditorComponentView.h"
|
||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||
#include "Camera/SHCameraSystem.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -106,6 +108,7 @@ namespace SHADE
|
|||
{
|
||||
if (editor && !editor->selectedEntities.empty())
|
||||
{
|
||||
DrawMenuBar();
|
||||
EntityID const& eid = editor->selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||
|
@ -114,6 +117,7 @@ namespace SHADE
|
|||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
||||
ImGui::SameLine();
|
||||
|
@ -222,4 +226,36 @@ namespace SHADE
|
|||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
void SHEditorInspector::DrawMenuBar()
|
||||
{
|
||||
if(ImGui::BeginMenuBar())
|
||||
{
|
||||
EntityID const& eid = editor->selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||
if (!entity || !entityNode)
|
||||
{
|
||||
ImGui::EndMenuBar();
|
||||
return;
|
||||
}
|
||||
if (ImGui::SmallButton("Look At"))
|
||||
{
|
||||
editor->selectedEntities.clear();
|
||||
editor->selectedEntities.push_back(eid);
|
||||
if (auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>())
|
||||
{
|
||||
if (auto editorCam = camSystem->GetEditorCamera())
|
||||
{
|
||||
if (auto entityTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
editorCam->SetPosition(entityTransform->GetWorldPosition() + SHVec3(0.5f));
|
||||
camSystem->CameraLookAt(*editorCam, entityTransform->GetWorldPosition());
|
||||
camSystem->UpdateEditorCamera(SHFrameRateController::GetRawDeltaTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ namespace SHADE
|
|||
void Exit() override;
|
||||
|
||||
private:
|
||||
|
||||
void DrawMenuBar();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -358,6 +358,7 @@ namespace SHADE
|
|||
|
||||
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
|
||||
{
|
||||
ImGui::SetNextWindowSize({400.0f, 0.0f});
|
||||
if (ImGui::BeginMenu("Physics Settings"))
|
||||
{
|
||||
if (auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>())
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimInspector.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 1, 2023
|
||||
\brief Contains the definition of SHRawAnimInspector's functions.
|
||||
|
||||
Copyright (C) 2023 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 "SHRawAnimInspector.h"
|
||||
|
||||
// STL Includes
|
||||
#include <format>
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include <misc/cpp/imgui_stdlib.h>
|
||||
// Project Includes
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||
#include "Editor/SHEditorUI.h"
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* SHAnimClipCreatePrompt - Constructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimClipCreatePrompt::SHAnimClipCreatePrompt()
|
||||
: SHPopUpWindow("Create Animation Clip", true, 0, 0) {}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHAnimClipCreatePrompt - Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHAnimClipCreatePrompt::Init(
|
||||
SHAsset* contAsset,
|
||||
SHAnimClipContainerAsset* cont,
|
||||
Handle<SHRawAnimation> rawAnim,
|
||||
std::function<void(AssetID)> onClose
|
||||
)
|
||||
{
|
||||
containerAsset = contAsset;
|
||||
container = cont;
|
||||
rawAnimation = rawAnim;
|
||||
|
||||
// Set default parameters
|
||||
if (rawAnimation)
|
||||
{
|
||||
newAssetName.clear();
|
||||
firstIndex = 0;
|
||||
lastIndex = rawAnimation->GetTotalFrames();
|
||||
}
|
||||
|
||||
// Assign callback
|
||||
this->onClose = onClose;
|
||||
}
|
||||
|
||||
void SHAnimClipCreatePrompt::Draw()
|
||||
{
|
||||
if (Begin())
|
||||
{
|
||||
// Properties
|
||||
SHEditorUI::InputTextField("Name", newAssetName);
|
||||
SHEditorUI::PushID(0);
|
||||
SHEditorUI::InputUnsignedInt("First Frame Index", firstIndex);
|
||||
SHEditorUI::PopID();
|
||||
SHEditorUI::PushID(1);
|
||||
SHEditorUI::InputUnsignedInt("Last Frame Index", lastIndex);
|
||||
SHEditorUI::PopID();
|
||||
|
||||
// Invalid values
|
||||
const bool INVALID_CONFIG = newAssetName.empty() || firstIndex > lastIndex;
|
||||
|
||||
// Buttons
|
||||
ImGui::BeginDisabled(INVALID_CONFIG);
|
||||
{
|
||||
if (ImGui::Button("Save"))
|
||||
{
|
||||
// Generate new asset
|
||||
const AssetID NEW_ASSET_ID = SHAssetManager::CreateNewSubAsset(AssetType::ANIM_CLIP, newAssetName, containerAsset->id);
|
||||
auto animClip = SHAssetManager::GetData<SHAnimClipAsset>(NEW_ASSET_ID);
|
||||
animClip->name = newAssetName;
|
||||
animClip->firstIndex = firstIndex;
|
||||
animClip->lastIndex = lastIndex;
|
||||
animClip->animRawDataAssetId = SHResourceManager::GetAssetID<SHRawAnimation>(rawAnimation).value_or(0);
|
||||
SHAssetManager::SaveAsset(containerAsset->id);
|
||||
|
||||
// Close
|
||||
isOpen = false;
|
||||
if (onClose)
|
||||
onClose(NEW_ASSET_ID);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel"))
|
||||
{
|
||||
// Close
|
||||
isOpen = false;
|
||||
if (onClose)
|
||||
onClose(INVALID_ASSET_ID);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Cosntructors/Destructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHRawAnimInspector::SHRawAnimInspector()
|
||||
: SHEditorWindow("Animation Editor", ImGuiWindowFlags_MenuBar)
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
|
||||
SHEditorWindowManager::CreatePopupWindow<SHAnimClipCreatePrompt>();
|
||||
}
|
||||
|
||||
void SHRawAnimInspector::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
// Draw
|
||||
if (Begin())
|
||||
{
|
||||
// Ignore if no asset
|
||||
if (container)
|
||||
{
|
||||
drawMenuBar();
|
||||
|
||||
// Button to add a new clip
|
||||
if (ImGui::Button(std::format("{} Create Animation Clip", ICON_MD_ADD).data()))
|
||||
{
|
||||
auto prompt = SHEditorWindowManager::GetPopupWindow<SHAnimClipCreatePrompt>();
|
||||
prompt->Init(containerAsset, container, currRawAnim, [this](AssetID createdAssetId)
|
||||
{
|
||||
if (createdAssetId != INVALID_ASSET_ID)
|
||||
{
|
||||
childAnimClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(createdAssetId));
|
||||
}
|
||||
});
|
||||
prompt->isOpen = true;
|
||||
}
|
||||
|
||||
// Render all animation clips
|
||||
if (SHEditorUI::CollapsingHeader("Existing Animation Clips"))
|
||||
{
|
||||
ImGui::Indent();
|
||||
for (auto animClip : childAnimClips)
|
||||
{
|
||||
bool changed = false;
|
||||
std::optional<std::string> animClipName = SHResourceManager::GetAssetName<SHAnimationClip>(animClip);
|
||||
|
||||
int firstIndex = animClip->GetStartFrameIndex();
|
||||
int endIndex = animClip->GetEndFrameIndex();
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text(animClipName.has_value() ? animClipName.value().c_str() : "");
|
||||
changed |= SHEditorWidgets::SliderInt
|
||||
(
|
||||
"Start", 0, currRawAnim->GetTotalFrames(),
|
||||
[&]() { return firstIndex; },
|
||||
[&](int i) { firstIndex = i; }
|
||||
);
|
||||
changed |= SHEditorWidgets::SliderInt
|
||||
(
|
||||
"End", 0, currRawAnim->GetTotalFrames(),
|
||||
[&]() { return endIndex; },
|
||||
[&](int i) { endIndex = i; }
|
||||
);
|
||||
|
||||
// If there's a change we need to commit changes
|
||||
if (changed && firstIndex < endIndex)
|
||||
{
|
||||
// Update runtime asset
|
||||
*animClip = SHAnimationClip(currRawAnim, firstIndex, endIndex);
|
||||
|
||||
// Update serialized asset
|
||||
auto assetId = SHResourceManager::GetAssetID(animClip);
|
||||
if (assetId.has_value())
|
||||
{
|
||||
auto animAsset = SHAssetManager::GetData<SHAnimClipAsset>(assetId.value());
|
||||
animAsset->firstIndex = firstIndex;
|
||||
animAsset->lastIndex = endIndex;
|
||||
SHAssetManager::SaveAsset(assetId.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extra separator if there is more than one
|
||||
if (!childAnimClips.empty())
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Unindent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorUI::CenteredText("Double click on a model file to inspect its animations here.");
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SHRawAnimInspector::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::Open(AssetID assetId)
|
||||
{
|
||||
containerAsset = SHAssetManager::GetAsset(assetId);
|
||||
container = SHAssetManager::GetData<SHAnimClipContainerAsset>(assetId);
|
||||
|
||||
// Load anim clips
|
||||
if (container)
|
||||
{
|
||||
currRawAnim = SHResourceManager::LoadOrGet<SHRawAnimation>(container->animRawDataAssetId);
|
||||
childAnimClips = getChildAnimClips(assetId);
|
||||
}
|
||||
else
|
||||
{
|
||||
childAnimClips.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRawAnimInspector::drawMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const std::string& ASSET_NAME = SHResourceManager::GetAssetName<SHRawAnimation>(currRawAnim).value_or("Unnamed Asset");
|
||||
ImGui::Text(ASSET_NAME.c_str());
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Handle<SHAnimationClip>> SHRawAnimInspector::getChildAnimClips(AssetID containerId)
|
||||
{
|
||||
auto const containerAsset {*SHAssetManager::GetAsset(containerId)};
|
||||
std::vector<Handle<SHAnimationClip>> animClips;
|
||||
|
||||
for (auto const& asset : containerAsset.subAssets)
|
||||
{
|
||||
animClips.emplace_back(SHResourceManager::LoadOrGet<SHAnimationClip>(asset->id));
|
||||
}
|
||||
|
||||
return animClips;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimInspector.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 2, 2023
|
||||
\brief Contains the definition of SHRawAnimInspector.
|
||||
|
||||
Copyright (C) 2023 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 "Assets/SHAssetMacros.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHRawAnimation.h"
|
||||
#include "Assets/SHAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Editor/EditorWindow/SHPopUpWindow.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
struct SHAnimClipAsset;
|
||||
class SHRawAnimation;
|
||||
class SHAnimationClip;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Prompt for creating an animation clip. Init() must be called to pass in the correct
|
||||
/// SHRawAnimation that the created clip will use.
|
||||
/// </summary>
|
||||
class SHAnimClipCreatePrompt : public SHPopUpWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAnimClipCreatePrompt();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init(
|
||||
SHAsset* contAsset,
|
||||
SHAnimClipContainerAsset* cont,
|
||||
Handle<SHRawAnimation> rawAnim,
|
||||
std::function<void(AssetID)> onClose = nullptr
|
||||
);
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
std::string newAssetName;
|
||||
uint32_t firstIndex = 0;
|
||||
uint32_t lastIndex = 0;
|
||||
Handle<SHRawAnimation> rawAnimation;
|
||||
SHAsset* containerAsset{nullptr};
|
||||
SHAnimClipContainerAsset* container{nullptr};
|
||||
std::function<void(AssetID)> onClose;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Editor for generating SHAnimationClips from a single SHRawAnimation object.
|
||||
/// </summary>
|
||||
class SHRawAnimInspector final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHRawAnimInspector();
|
||||
~SHRawAnimInspector() = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Lifecycle Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Open(AssetID assetId);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHAsset* containerAsset{nullptr};
|
||||
SHAnimClipContainerAsset* container {nullptr};
|
||||
Handle<SHRawAnimation> currRawAnim;
|
||||
std::vector<Handle<SHAnimationClip>> childAnimClips;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void drawMenuBar();
|
||||
std::vector<Handle<SHAnimationClip>> getChildAnimClips(AssetID containerId);
|
||||
};
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
#pragma once
|
||||
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
|
||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
||||
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
|
||||
#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel
|
||||
#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings
|
||||
#include "MenuBar/SHEditorMenuBar.h" // Menu Bar
|
||||
#include "HierarchyPanel/SHHierarchyPanel.h" // Hierarchy Panel
|
||||
#include "Inspector/SHEditorInspector.h" // Inspector
|
||||
#include "Profiling/SHEditorProfiler.h" // Profiler
|
||||
#include "ViewportWindow/SHEditorViewport.h" // Editor Viewport
|
||||
#include "AssetBrowser/SHAssetBrowser.h" // Asset Browser
|
||||
#include "MaterialInspector/SHMaterialInspector.h" // Material Inspector
|
||||
#include "ColliderTagPanel/SHColliderTagPanel.h" // Collider Tag Panel
|
||||
#include "InputBindings/SHInputBindingsPanel.h" // Input Bindings
|
||||
#include "EditorWindow/Animation/SHAnimationControllerEditor.h" // Animation Controller Editor
|
||||
#include "EditorWindow/RawAnimationInspector/SHRawAnimInspector.h" // Raw Animation Inspector
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
//|| Library Includes ||
|
||||
//#==============================================================#
|
||||
#include <imgui.h>
|
||||
#include <imnodes.h>
|
||||
#include <SDL.h>
|
||||
#include <rttr/registration>
|
||||
#include <ImGuizmo.h>
|
||||
|
@ -97,6 +98,10 @@ namespace SHADE
|
|||
SHLOG_CRITICAL("Failed to create ImGui Context")
|
||||
}
|
||||
}
|
||||
if (ImNodes::CreateContext() == nullptr)
|
||||
{
|
||||
SHLOG_CRITICAL("Failed to create ImNodes Context")
|
||||
}
|
||||
|
||||
#ifdef SHEDITOR
|
||||
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
||||
|
@ -113,6 +118,8 @@ namespace SHADE
|
|||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHAnimationControllerEditor>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHRawAnimInspector>();
|
||||
|
||||
//Add popup windows
|
||||
SHEditorWindowManager::CreatePopupWindow<SHSceneSavePrompt>();
|
||||
|
@ -340,6 +347,7 @@ namespace SHADE
|
|||
{
|
||||
window->Init();
|
||||
}
|
||||
ImNodes::DestroyContext();
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
@ -669,6 +677,12 @@ namespace SHADE
|
|||
SaveScene();
|
||||
}
|
||||
}
|
||||
if(editorState == State::PLAY && ImGui::IsKeyReleased(ImGuiKey_LeftAlt))
|
||||
{
|
||||
SHInputManager::SetMouseCentering(!SHInputManager::GetMouseCentering());
|
||||
SHWindow::SetMouseVisible(!SHWindow::GetMouseVisible());
|
||||
|
||||
}
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
{
|
||||
SHCommandManager::RedoCommand();
|
||||
|
|
|
@ -137,6 +137,15 @@ namespace SHADE
|
|||
{
|
||||
ImGui::Text(title.c_str());
|
||||
}
|
||||
void SHEditorUI::CenteredText(const std::string& text)
|
||||
{
|
||||
const auto WINDOW_SIZE = ImGui::GetWindowSize();
|
||||
const auto TEXT_SIZE = ImGui::CalcTextSize(text.c_str());
|
||||
|
||||
ImGui::SetCursorPosX((WINDOW_SIZE.x - TEXT_SIZE.x) * 0.5f);
|
||||
ImGui::SetCursorPosY((WINDOW_SIZE.y - TEXT_SIZE.y) * 0.5f);
|
||||
ImGui::Text(text.c_str());
|
||||
}
|
||||
bool SHEditorUI::SmallButton(const std::string& title)
|
||||
{
|
||||
return ImGui::SmallButton(title.c_str());
|
||||
|
@ -369,9 +378,9 @@ namespace SHADE
|
|||
// Attempt to get the asset's data for rendering editor
|
||||
auto asset = SHAssetManager::GetAsset(value);
|
||||
std::string assetName;
|
||||
if (asset.has_value())
|
||||
if (asset)
|
||||
{
|
||||
assetName = asset.value().name;
|
||||
assetName = asset->name;
|
||||
}
|
||||
|
||||
// Editor
|
||||
|
@ -382,9 +391,9 @@ namespace SHADE
|
|||
{
|
||||
// Check if type matches
|
||||
auto draggedAsset = SHAssetManager::GetAsset(*payload);
|
||||
if (draggedAsset.has_value() && draggedAsset.value().type == type)
|
||||
if (draggedAsset && draggedAsset->type == type)
|
||||
{
|
||||
value = draggedAsset.value().id;
|
||||
value = draggedAsset->id;
|
||||
changed = true;
|
||||
}
|
||||
SHDragDrop::EndTarget();
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace SHADE
|
|||
/// <returns>True if the header is open, false otherwise.</returns>
|
||||
static bool CollapsingHeader(const std::string& title, bool* isHovered = nullptr);
|
||||
static void SameLine();
|
||||
static void Separator();
|
||||
static void Separator();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Queries */
|
||||
|
@ -98,9 +98,9 @@ namespace SHADE
|
|||
static bool IsItemHovered();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Menu */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static bool BeginMenu(const std::string& label);
|
||||
/* 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();
|
||||
|
@ -150,6 +150,12 @@ namespace SHADE
|
|||
/// <param name="title">Text to display.</param>
|
||||
static void Text(const std::string& title);
|
||||
/// <summary>
|
||||
/// Renders a text widget that is vertically and horizontally centered in the current
|
||||
/// window.
|
||||
/// </summary>
|
||||
/// <param name="text">Text to display.</param>
|
||||
static void CenteredText(const std::string& text);
|
||||
/// <summary>
|
||||
/// Creates a small inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::SmallButton().
|
||||
|
@ -164,8 +170,8 @@ namespace SHADE
|
|||
/// </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 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.
|
||||
|
|
|
@ -418,12 +418,16 @@ namespace SHADE
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {})
|
||||
static bool DragDropReadOnlyField(std::string const& label, std::string_view const& fieldVTextValue, std::function<T (void)> const& get, std::function<void(T const&)> const& set, SHDragDrop::DragDropTag const& dragDropTag, std::string_view const& tooltip = {}, float customWidth = -1.0f)
|
||||
{
|
||||
std::string text = fieldVTextValue.data();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(label.data());
|
||||
TextLabel(label);
|
||||
if (customWidth > 0.0f)
|
||||
{
|
||||
ImGui::SetNextItemWidth(customWidth);
|
||||
}
|
||||
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_AutoSelectAll, nullptr, nullptr);
|
||||
if(SHDragDrop::BeginTarget())
|
||||
{
|
||||
|
|
|
@ -127,8 +127,8 @@ namespace SHADE
|
|||
if (assetId.has_value())
|
||||
{
|
||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||
if (ASSET_INFO.has_value())
|
||||
return ASSET_INFO.value().name;
|
||||
if (ASSET_INFO)
|
||||
return ASSET_INFO->name;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimClipContainerAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimControllerAsset.h"
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||
|
@ -28,7 +30,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
#include "Animation/SHRawAnimation.h"
|
||||
#include "Animation/SHRig.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -38,6 +40,8 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHMaterial;
|
||||
struct SHRigNode;
|
||||
class SHAnimationClip;
|
||||
class SHAnimationController;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -46,15 +50,17 @@ namespace SHADE
|
|||
/// Template structs that maps a resource to their loaded asset representation type.
|
||||
/// </summary>
|
||||
template<typename T = void>
|
||||
struct SHResourceLoader { using AssetType = void; };
|
||||
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
|
||||
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
|
||||
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||
struct SHResourceLoader { using AssetType = void; };
|
||||
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshAsset; };
|
||||
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
|
||||
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
||||
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationController> { using AssetType = SHAnimControllerAsset; };
|
||||
|
||||
/// <summary>
|
||||
/// Static class responsible for loading and caching runtime resources from their
|
||||
|
|
|
@ -25,6 +25,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Serialization/SHYAMLConverters.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -35,14 +36,16 @@ namespace SHADE
|
|||
Handle<ResourceType> SHResourceManager::LoadOrGet(AssetID assetId)
|
||||
{
|
||||
// Check if it is an unsupported type
|
||||
if (!std::is_same_v<ResourceType, SHMesh> &&
|
||||
!std::is_same_v<ResourceType, SHTexture> &&
|
||||
!std::is_same_v<ResourceType, SHVkShaderModule> &&
|
||||
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
||||
!std::is_same_v<ResourceType, SHFont> &&
|
||||
!std::is_same_v<ResourceType, SHMaterial> &&
|
||||
!std::is_same_v<ResourceType, SHAnimationClip> &&
|
||||
!std::is_same_v<ResourceType, SHRig>
|
||||
if (!std::is_same_v<ResourceType, SHMesh> &&
|
||||
!std::is_same_v<ResourceType, SHTexture> &&
|
||||
!std::is_same_v<ResourceType, SHVkShaderModule> &&
|
||||
!std::is_same_v<ResourceType, SHMaterialSpec> &&
|
||||
!std::is_same_v<ResourceType, SHFont> &&
|
||||
!std::is_same_v<ResourceType, SHMaterial> &&
|
||||
!std::is_same_v<ResourceType, SHRawAnimation> &&
|
||||
!std::is_same_v<ResourceType, SHRig> &&
|
||||
!std::is_same_v<ResourceType, SHAnimationClip> &&
|
||||
!std::is_same_v<ResourceType, SHAnimationController>
|
||||
)
|
||||
{
|
||||
static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
|
||||
|
@ -159,8 +162,8 @@ namespace SHADE
|
|||
if (assetId.has_value())
|
||||
{
|
||||
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
|
||||
if (ASSET_INFO.has_value())
|
||||
return ASSET_INFO.value().name;
|
||||
if (ASSET_INFO)
|
||||
return ASSET_INFO->name;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -355,10 +358,30 @@ namespace SHADE
|
|||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>(assetData.rig, rigNodeStore);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHRawAnimation>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
if (assetData.anims.empty())
|
||||
return {};
|
||||
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHAnimationClip>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
|
||||
return resourceHub.Create<ResourceType>
|
||||
(
|
||||
LoadOrGet<SHRawAnimation>(assetData.animRawDataAssetId),
|
||||
assetData.firstIndex,
|
||||
assetData.lastIndex
|
||||
);
|
||||
}
|
||||
else if constexpr (std::is_same_v<ResourceType, SHAnimationController>)
|
||||
{
|
||||
loadedAssetData.emplace_back(assetId);
|
||||
return resourceHub.Create<ResourceType>
|
||||
(
|
||||
// TODO
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,21 @@ namespace SHADE
|
|||
return SHResourceManager::LoadOrGet<SHFont>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHAnimationClip> SHResourceManagerInterface::LoadOrGetAnimationClip(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHAnimationClip>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHAnimationController> SHResourceManagerInterface::LoadOrGetAnimationController(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHAnimationController>(assetId);
|
||||
}
|
||||
|
||||
Handle<SHRig> SHResourceManagerInterface::LoadOrGetRig(AssetID assetId)
|
||||
{
|
||||
return SHResourceManager::LoadOrGet<SHRig>(assetId);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Query Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace SHADE
|
|||
struct SHMaterialSpec;
|
||||
class SHMaterial;
|
||||
class SHFont;
|
||||
class SHAnimationClip;
|
||||
class SHRig;
|
||||
class SHAnimationController;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -80,6 +83,24 @@ namespace SHADE
|
|||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHFont> LoadOrGetFont(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHAnimationClip>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHAnimationClip> LoadOrGetAnimationClip(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHAnimationController>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHAnimationController> LoadOrGetAnimationController(AssetID assetId);
|
||||
/// <summary>
|
||||
/// Wrapper for SHResourceManager::LoadOrGet<SHRig>().
|
||||
/// </summary>
|
||||
/// <param name="assetId">Asset ID of the resource to load.</param>
|
||||
/// <returns>Handle to the resource to retrieve.</returns>
|
||||
static Handle<SHRig> LoadOrGetRig(AssetID assetId);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Query Functions */
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace SHADE
|
|||
#else
|
||||
static constexpr int EXCESS_CHARS_COUNT = 2;
|
||||
|
||||
const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -first 1", true, true);
|
||||
const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,21.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -last 1", true, true);
|
||||
if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT)
|
||||
{
|
||||
SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work.");
|
||||
|
|
|
@ -428,13 +428,13 @@ namespace YAML
|
|||
struct convert<SHAnimatorComponent>
|
||||
{
|
||||
static constexpr std::string_view RIG_YAML_TAG = "Rig";
|
||||
static constexpr std::string_view CLIP_YAML_TAG = "Clip";
|
||||
static constexpr std::string_view AC_YAML_TAG = "AnimationController";
|
||||
|
||||
static YAML::Node encode(SHAnimatorComponent const& rhs)
|
||||
{
|
||||
YAML::Node node;
|
||||
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
|
||||
node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationClip>(rhs.GetCurrentClip()).value_or(0);
|
||||
node[AC_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationController>(rhs.GetAnimationController()).value_or(0);
|
||||
return node;
|
||||
}
|
||||
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
||||
|
@ -443,9 +443,9 @@ namespace YAML
|
|||
{
|
||||
rhs.SetRig(SHResourceManager::LoadOrGet<SHRig>(node[RIG_YAML_TAG.data()].as<AssetID>()));
|
||||
}
|
||||
if (node[CLIP_YAML_TAG.data()].IsDefined())
|
||||
if (node[AC_YAML_TAG.data()].IsDefined())
|
||||
{
|
||||
rhs.SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(node[CLIP_YAML_TAG.data()].as<AssetID>()));
|
||||
rhs.SetAnimationController(SHResourceManager::LoadOrGet<SHAnimationController>(node[AC_YAML_TAG.data()].as<AssetID>()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationClipAsset.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationClip class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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 "AnimationClipAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationClip> AnimationClipAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetAnimationClip(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHAnimationClip>();
|
||||
}
|
||||
AssetID AnimationClipAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::AnimationClipAsset(AssetID AnimationClipId)
|
||||
: asset{ AnimationClipId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::operator bool(AnimationClipAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationClipAsset::operator Asset(AnimationClipAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationClipAsset::operator AnimationClipAsset(Asset asset)
|
||||
{
|
||||
return AnimationClipAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationClipAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationClipAsset class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native Animation Clip object that specifies a range of
|
||||
/// animation frames that can be specified to an Animator component to play an
|
||||
/// animation.
|
||||
/// </summary>
|
||||
public value struct AnimationClipAsset
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHAnimationClip> NativeObject
|
||||
{
|
||||
Handle<SHAnimationClip> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationClip.
|
||||
/// </summary>
|
||||
/// <param name="AnimationClipId">AssetID to the AnimationClip asset.</param>
|
||||
AnimationClipAsset(AssetID AnimationClipId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationClip is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationClipAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationClip to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationClipAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationClip.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationClipAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationController.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationController class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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 "AnimationControllerAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHAnimationController> AnimationControllerAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetAnimationController(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHAnimationController>();
|
||||
}
|
||||
AssetID AnimationControllerAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::AnimationControllerAsset(AssetID AnimationControllerId)
|
||||
: asset{ AnimationControllerId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::operator bool(AnimationControllerAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset::operator Asset(AnimationControllerAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationControllerAsset::operator AnimationControllerAsset(Asset asset)
|
||||
{
|
||||
return AnimationControllerAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationControllerAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationController 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
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHAnimationController.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native AnimationController object containing the
|
||||
/// state machine for controlling what AnimationClips that an Animator should play.
|
||||
/// </summary>
|
||||
public value struct AnimationControllerAsset
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHAnimationController> NativeObject
|
||||
{
|
||||
Handle<SHAnimationController> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationController.
|
||||
/// </summary>
|
||||
/// <param name="AnimationControllerId">AssetID to the AnimationController asset.</param>
|
||||
AnimationControllerAsset(AssetID AnimationControllerId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationController is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationControllerAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationController to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationControllerAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationController.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationControllerAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationRigAsset.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the implementation of the functions of the managed
|
||||
AnimationRig class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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 "AnimationRigAsset.hxx"
|
||||
// External Dependencies
|
||||
#include "Resource/SHResourceManagerInterface.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHRig> AnimationRigAsset::NativeObject::get()
|
||||
try
|
||||
{
|
||||
return SHResourceManagerInterface::LoadOrGetRig(asset.NativeAssetID);
|
||||
}
|
||||
catch (const BadHandleCastException&)
|
||||
{
|
||||
return Handle<SHRig>();
|
||||
}
|
||||
AssetID AnimationRigAsset::NativeAssetID::get()
|
||||
{
|
||||
return asset.NativeAssetID;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::AnimationRigAsset(AssetID AnimationRigId)
|
||||
: asset{ AnimationRigId }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::operator bool(AnimationRigAsset asset)
|
||||
{
|
||||
return asset.asset;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationRigAsset::operator Asset(AnimationRigAsset nativeAsset)
|
||||
{
|
||||
return nativeAsset.asset;
|
||||
}
|
||||
|
||||
AnimationRigAsset::operator AnimationRigAsset(Asset asset)
|
||||
{
|
||||
return AnimationRigAsset(asset.NativeAssetID);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/************************************************************************************//*!
|
||||
\file AnimationRigAsset.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed AnimationRigAsset class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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
|
||||
|
||||
// External Dependencies
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Animation/SHRig.h"
|
||||
// Project Includes
|
||||
#include "NativeAsset.hxx"
|
||||
#include "Engine/GenericHandle.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Managed counterpart of the native Animation Rig object that specifies how an
|
||||
/// Animation Clip affects the model that this Rig is attached to.
|
||||
/// </summary>
|
||||
public value struct AnimationRigAsset
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Copy of the Handle to the native object.
|
||||
/// </summary>
|
||||
property Handle<SHRig> NativeObject
|
||||
{
|
||||
Handle<SHRig> get();
|
||||
}
|
||||
/// <summary>
|
||||
/// The raw asset ID of the asset.
|
||||
/// </summary>
|
||||
property AssetID NativeAssetID
|
||||
{
|
||||
AssetID get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors/Destructor */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructor for the AnimationRig.
|
||||
/// </summary>
|
||||
/// <param name="AnimationRigId">AssetID to the AnimationRig asset.</param>
|
||||
AnimationRigAsset(AssetID AnimationRigId);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Implicit conversion operator to enable checking if a AnimationRig is valid.
|
||||
/// </summary>
|
||||
/// <param name="gameObj">Asset to check.</param>
|
||||
/// <returns>True if the Asset is valid.</returns>
|
||||
static operator bool(AnimationRigAsset asset);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Conversion Operators */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a AnimationRig to an Asset.
|
||||
/// </summary>
|
||||
/// <param name="vec">Vector3 to convert from.</param>
|
||||
static explicit operator Asset(AnimationRigAsset nativeAsset);
|
||||
/// <summary>
|
||||
/// Conversion operator to enable casting from a Asset to a AnimationRig.
|
||||
/// </summary>
|
||||
/// <param name="asset"></param>
|
||||
static explicit operator AnimationRigAsset(Asset asset);
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Asset asset;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/************************************************************************************//*!
|
||||
\file Animator.cxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the functions of the managed Animator class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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 "Animator.hxx"
|
||||
#include "Assets/NativeAsset.hxx"
|
||||
#include "Utility/Convert.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Animator::Animator(Entity entity)
|
||||
: Component(entity)
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
AnimationControllerAsset Animator::AnimationController::get()
|
||||
{
|
||||
auto controller = GetNativeComponent()->GetAnimationController();
|
||||
return controller ? AnimationControllerAsset(controller) : AnimationControllerAsset();
|
||||
}
|
||||
void Animator::AnimationController::set(AnimationControllerAsset value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
GetNativeComponent()->SetAnimationController(Handle<SHAnimationController>());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeComponent()->SetAnimationController(value.NativeObject);
|
||||
}
|
||||
}
|
||||
AnimationRigAsset Animator::Rig::get()
|
||||
{
|
||||
auto rig = GetNativeComponent()->GetRig();
|
||||
return rig ? AnimationRigAsset(rig) : AnimationRigAsset();
|
||||
}
|
||||
void Animator::Rig::set(AnimationRigAsset value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
GetNativeComponent()->SetRig(Handle<SHRig>());
|
||||
}
|
||||
else
|
||||
{
|
||||
GetNativeComponent()->SetRig(Handle<SHRig>(value.NativeObject));
|
||||
}
|
||||
}
|
||||
System::String^ Animator::CurrentNodeName::get()
|
||||
{
|
||||
const auto CURR_NODE = GetNativeComponent()->GetCurrentNode();
|
||||
if (CURR_NODE)
|
||||
return Convert::ToCLI(CURR_NODE->Name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void Animator::Play()
|
||||
{
|
||||
GetNativeComponent()->Play();
|
||||
}
|
||||
|
||||
void Animator::Play(AnimationClipAsset clip)
|
||||
{
|
||||
GetNativeComponent()->Play(clip.NativeObject);
|
||||
}
|
||||
|
||||
void Animator::PlayOneShot(AnimationClipAsset clip)
|
||||
{
|
||||
GetNativeComponent()->PlayOneShot(clip.NativeObject);
|
||||
}
|
||||
|
||||
void Animator::PlayFromStart()
|
||||
{
|
||||
GetNativeComponent()->Play();
|
||||
}
|
||||
|
||||
void Animator::Pause()
|
||||
{
|
||||
GetNativeComponent()->Pause();
|
||||
}
|
||||
|
||||
void Animator::Stop()
|
||||
{
|
||||
GetNativeComponent()->Stop();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
generic<typename T>
|
||||
void Animator::SetParameter(System::String^ paramName, T value)
|
||||
{
|
||||
if (T::typeid == int::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<int>(Convert::ToNative(paramName), static_cast<int>(value));
|
||||
}
|
||||
else if (T::typeid == float::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<float>(Convert::ToNative(paramName), static_cast<float>(value));
|
||||
}
|
||||
else if (T::typeid == bool::typeid)
|
||||
{
|
||||
GetNativeComponent()->SetParameter<bool>(Convert::ToNative(paramName), static_cast<bool>(value));
|
||||
}
|
||||
}
|
||||
|
||||
void Animator::SetTrigger(System::String^ paramName)
|
||||
{
|
||||
GetNativeComponent()->SetTrigger(Convert::ToNative(paramName));
|
||||
}
|
||||
|
||||
System::Nullable<int> Animator::GetIntParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<int>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<int>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<float> Animator::GetFloatParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<float>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<float>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<bool> Animator::GetBoolParameter(System::String^ paramName)
|
||||
{
|
||||
auto val = GetNativeComponent()->GetParameter<bool>(Convert::ToNative(paramName));
|
||||
if (val.has_value())
|
||||
return System::Nullable<bool>(val.value());
|
||||
return {};
|
||||
}
|
||||
|
||||
System::Nullable<bool> Animator::GetTriggerState(System::String^ paramName)
|
||||
{
|
||||
return GetBoolParameter(paramName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/************************************************************************************//*!
|
||||
\file Animator.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 8, 2023
|
||||
\brief Contains the definition of the managed Animator class with the
|
||||
declaration of functions for working with it.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2023 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"
|
||||
// External Dependencies
|
||||
#include "Animation/SHAnimatorComponent.h"
|
||||
// Project Includes
|
||||
#include "Assets/AnimationClipAsset.hxx"
|
||||
#include "Assets/AnimationControllerAsset.hxx"
|
||||
#include "Assets/AnimationRigAsset.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// CLR version of the SHADE Engine's SHAnimatorComponent.
|
||||
/// </summary>
|
||||
public ref class Animator : public Component<SHAnimatorComponent>
|
||||
{
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Constructs a Animator Component that represents a native Animator
|
||||
/// component tied to the specified Entity.
|
||||
/// </summary>
|
||||
/// <param name="entity">Entity that this Component will be tied to.</param>
|
||||
Animator(Entity entity);
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Animation Controller used to controller the animation of this Animator.
|
||||
/// </summary>
|
||||
property AnimationControllerAsset AnimationController
|
||||
{
|
||||
AnimationControllerAsset get();
|
||||
void set(AnimationControllerAsset value);
|
||||
}
|
||||
/// <summary>
|
||||
/// The shared Material used to render this Animator and other Animators
|
||||
/// using the same base Material.
|
||||
/// </summary>
|
||||
property AnimationRigAsset Rig
|
||||
{
|
||||
AnimationRigAsset get();
|
||||
void set(AnimationRigAsset value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Name of the current node if there is an animation controller attached. If
|
||||
/// there is none, null is returned.
|
||||
/// </summary>
|
||||
property System::String^ CurrentNodeName
|
||||
{
|
||||
System::String^ get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation from the last time.
|
||||
/// </summary>
|
||||
void Play();
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start. This will unset any
|
||||
/// SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void Play(AnimationClipAsset clip);
|
||||
/// <summary>
|
||||
/// Plays the specified animation clip from the start one time only. This will unset
|
||||
/// any SHAnimationControllers that have been set.
|
||||
/// </summary>
|
||||
/// <param name="clip">Animation clip to play.</param>
|
||||
void PlayOneShot(AnimationClipAsset clip);
|
||||
/// <summary>
|
||||
/// Plays the currently loaded animation clip from the start. Note that this only
|
||||
/// works when using manual playback mode.
|
||||
/// </summary>
|
||||
void PlayFromStart();
|
||||
/// <summary>
|
||||
/// Pauses the animation at the current time.
|
||||
/// </summary>
|
||||
void Pause();
|
||||
/// <summary>
|
||||
/// Stops the animation and resets the play time back to 0. Note that this only
|
||||
/// works when using manual playback mode. This is not supported when using an
|
||||
/// Animation Controller.
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Parameter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Sets the parameter of the for the string. Does nothing if an invalid param name
|
||||
/// is provided. Type of the parameter is not checked. Also does nothing if no
|
||||
/// animation controller is specified.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
/// Type of parameter. Only bool, int, floats are supported.
|
||||
/// </typeparam>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <param name="value">Value to set the parameter to.</param>
|
||||
generic<typename T>
|
||||
void SetParameter(System::String^ paramName, T value);
|
||||
/// <summary>
|
||||
/// Sets the flag for a trigger parameter. Does nothing if an invalid param name is
|
||||
/// provided or if the param name refers to a parameter that is not a trigger.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
void SetTrigger(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type int. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<int> GetIntParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type float. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<float> GetFloatParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Gets the parameter of the for the named parameter of type bool. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>The value of the parameter or nothing if invalid.</returns>
|
||||
System::Nullable<bool> GetBoolParameter(System::String^ paramName);
|
||||
/// <summary>
|
||||
/// Checks if the trigger flag for the named trigger parameter is set. Types are
|
||||
/// checked and will not return a value if there is nothing. Returns nothing if
|
||||
/// there is no animation controller specified either.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Name of the parameter.</param>
|
||||
/// <returns>True if the trigger is set.</returns>
|
||||
System::Nullable<bool> GetTriggerState(System::String^ paramName);
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Collider.hxx"
|
||||
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Physics/Collision/Shapes/SHCapsule.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Utility/Debug.hxx"
|
||||
|
||||
|
@ -118,6 +119,29 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 SphereCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetWorldCentroid());
|
||||
}
|
||||
float SphereCollider::Radius::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
}
|
||||
void SphereCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity)
|
||||
: CollisionShape{ arrayIndex, attachedEntity }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* BoxCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -147,53 +171,33 @@ namespace SHADE
|
|||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* BoxCollider - Usage Functions */
|
||||
/* CapsuleCollider - Properties */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
bool BoxCollider::TestPoint(Vector3 point)
|
||||
Vector3 CapsuleCollider::Center::get()
|
||||
{
|
||||
//return getNativeCollisionShape<SHAABB>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHCapsule>().GetWorldCentroid());
|
||||
}
|
||||
bool BoxCollider::Raycast(Ray ray, float maxDistance)
|
||||
float CapsuleCollider::Radius::get()
|
||||
{
|
||||
//return getNativeCollisionShape<SHAABB>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
return getNativeCollisionShape<SHCapsule>().GetWorldRadius();
|
||||
}
|
||||
void CapsuleCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHCapsule>().SetWorldRadius(value);
|
||||
}
|
||||
float CapsuleCollider::Height::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHCapsule>().GetWorldHeight();
|
||||
}
|
||||
void CapsuleCollider::Height::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHCapsule>().SetWorldHeight(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Properties */
|
||||
/* CapsuleCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 SphereCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetWorldCentroid());
|
||||
}
|
||||
float SphereCollider::Radius::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
}
|
||||
void SphereCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
bool SphereCollider::TestPoint(Vector3 point)
|
||||
{
|
||||
//return getNativeCollisionShape<SHSphere>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
}
|
||||
bool SphereCollider::Raycast(Ray ray, float maxDistance)
|
||||
{
|
||||
//return getNativeCollisionShape<SHSphere>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* SphereCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity)
|
||||
CapsuleCollider::CapsuleCollider(int arrayIndex, Entity attachedEntity)
|
||||
: CollisionShape{ arrayIndex, attachedEntity }
|
||||
{}
|
||||
|
||||
|
@ -303,18 +307,18 @@ namespace SHADE
|
|||
int i = 0;
|
||||
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
|
||||
{
|
||||
CollisionShape^ bound = nullptr;
|
||||
CollisionShape^ shape = nullptr;
|
||||
switch (collider->GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::BOX:
|
||||
bound = gcnew BoxCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
bound = gcnew SphereCollider(i, Owner.GetEntity());
|
||||
shape = gcnew SphereCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::BOX:
|
||||
shape = gcnew BoxCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::CAPSULE:
|
||||
shape = gcnew CapsuleCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
//case SHCollisionShape::Type::CAPSULE:
|
||||
// // TODO
|
||||
// break;
|
||||
default:
|
||||
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
|
||||
break;
|
||||
|
@ -322,7 +326,7 @@ namespace SHADE
|
|||
++i;
|
||||
|
||||
// Add into list
|
||||
subColliderList->Add(bound);
|
||||
subColliderList->Add(shape);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// Primary Include
|
||||
#include "Component.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename CollisionShapeType>
|
||||
|
@ -28,7 +29,7 @@ namespace SHADE
|
|||
try
|
||||
{
|
||||
auto& shape = collider->GetCollisionShape(arrayIndex);
|
||||
if (shape.GetType() != SHCollisionShape::Type::BOX)
|
||||
if (shape.GetType() == SHCollisionShape::Type::INVALID)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
return dynamic_cast<CollisionShapeType&>(shape);
|
||||
|
|
|
@ -87,23 +87,6 @@ namespace SHADE
|
|||
void set(float value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Checks if the specified point is within this shape's bounds.
|
||||
/// </summary>
|
||||
/// <param name="point">Point to test with.</param>
|
||||
/// <returns>True if the point is in the shape's bounds.</returns>
|
||||
virtual bool TestPoint(Vector3 point) = 0;
|
||||
/// <summary>
|
||||
/// Computes a Raycast and checks if there is a collision with any object.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <param name="maxDistance">Maximum distance for the raycast check.</param>
|
||||
/// <returns>True if the ray intersects with an object in the scene.</returns>
|
||||
virtual bool Raycast(Ray ray, float maxDistance) = 0;
|
||||
|
||||
protected:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
|
@ -135,7 +118,39 @@ namespace SHADE
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// Box-shaped Collider Bound.
|
||||
/// A Sphere Collider
|
||||
/// </summary>
|
||||
public ref class SphereCollider : public CollisionShape
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the sphere.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
}
|
||||
/// <summary>
|
||||
/// Radius of the sphere/
|
||||
/// </summary>
|
||||
property float Radius
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
SphereCollider(int arrayIndex, Entity attachedEntity);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A Box Collider
|
||||
/// </summary>
|
||||
public ref class BoxCollider : public CollisionShape
|
||||
{
|
||||
|
@ -166,14 +181,6 @@ namespace SHADE
|
|||
Quaternion get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ColliderBound Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <inheritdoc/>
|
||||
bool TestPoint(Vector3 point) override;
|
||||
/// <inheritdoc/>
|
||||
bool Raycast(Ray ray, float maxDistance) override;
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
|
@ -182,44 +189,45 @@ namespace SHADE
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// Sphere-shaped Collider Bound.
|
||||
/// A Capsule Collider
|
||||
/// </summary>
|
||||
public ref class SphereCollider : public CollisionShape
|
||||
public ref class CapsuleCollider : public CollisionShape
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the sphere.
|
||||
/// Center of the capsule.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
}
|
||||
/// <summary>
|
||||
/// Radius of the Bounding Sphere formed by this bound.
|
||||
/// Radius of the capsule.
|
||||
/// </summary>
|
||||
property float Radius
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ColliderBound Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <inheritdoc/>
|
||||
bool TestPoint(Vector3 point) override;
|
||||
/// <inheritdoc/>
|
||||
bool Raycast(Ray ray, float maxDistance) override;
|
||||
/// <summary>
|
||||
/// Height of the capsule.
|
||||
/// </summary>
|
||||
property float Height
|
||||
{
|
||||
float get();
|
||||
void set(float value);
|
||||
}
|
||||
|
||||
internal:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
SphereCollider(int arrayIndex, Entity attachedEntity);
|
||||
CapsuleCollider(int arrayIndex, Entity attachedEntity);
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// CLR version of the the SHADE Engine's SHColliderComponent.
|
||||
|
|
|
@ -18,6 +18,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Editor/Editor.hxx"
|
||||
// STL Includes
|
||||
#include <memory>
|
||||
#include <string>
|
||||
// Project Headers
|
||||
#include "Components/Component.hxx"
|
||||
#include "Scripts/ScriptStore.hxx"
|
||||
|
@ -30,7 +31,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "RangeAttribute.hxx"
|
||||
#include "Math/Vector2.hxx"
|
||||
#include "Math/Vector3.hxx"
|
||||
#include <string>
|
||||
#include "Assets/AnimationClipAsset.hxx"
|
||||
#include "Assets/AnimationControllerAsset.hxx"
|
||||
#include "Assets/AnimationRigAsset.hxx"
|
||||
|
||||
// Using Directives
|
||||
using namespace System;
|
||||
|
@ -163,24 +166,27 @@ namespace SHADE
|
|||
bool isHovered = false;
|
||||
|
||||
const bool MODIFIED_PRIMITIVE =
|
||||
renderSpecificField<int , Int16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Int32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Int64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Byte >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<bool , bool >(field, object, SHEditorUI::InputCheckbox, &isHovered) ||
|
||||
renderSpecificField<float , float >(field, object, SHEditorUI::InputFloat , &isHovered) ||
|
||||
renderSpecificField<double , double >(field, object, SHEditorUI::InputDouble , &isHovered) ||
|
||||
renderSpecificField<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
|
||||
renderSpecificField<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
|
||||
renderSpecificField<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<std::string, System::String^>(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<int , System::Enum >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , FontAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , MeshAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , MaterialAsset >(field, object, nullptr , &isHovered);
|
||||
renderSpecificField<int , Int16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Int32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Int64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , UInt64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<int , Byte >(field, object, SHEditorUI::InputInt , &isHovered) ||
|
||||
renderSpecificField<bool , bool >(field, object, SHEditorUI::InputCheckbox, &isHovered) ||
|
||||
renderSpecificField<float , float >(field, object, SHEditorUI::InputFloat , &isHovered) ||
|
||||
renderSpecificField<double , double >(field, object, SHEditorUI::InputDouble , &isHovered) ||
|
||||
renderSpecificField<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
|
||||
renderSpecificField<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
|
||||
renderSpecificField<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<std::string, System::String^ >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<int , System::Enum >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , FontAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , MeshAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , MaterialAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , AnimationClipAsset >(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , AnimationControllerAsset>(field, object, nullptr , &isHovered) ||
|
||||
renderSpecificField<AssetID , AnimationRigAsset >(field, object, nullptr , &isHovered);
|
||||
|
||||
if (!MODIFIED_PRIMITIVE)
|
||||
{
|
||||
|
@ -324,24 +330,27 @@ namespace SHADE
|
|||
bool modified;
|
||||
|
||||
const bool RENDERED =
|
||||
renderFieldEditor<int , Int16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Int32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Int64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Byte >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<bool , bool >(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<float , float >(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<double , double >(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<std::string, System::String^>(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , FontAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , MeshAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , MaterialAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified);
|
||||
renderFieldEditor<int , Int16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Int32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Int64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , UInt64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , Byte >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<bool , bool >(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<float , float >(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<double , double >(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<std::string, System::String^ >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , FontAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , MeshAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , MaterialAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , AnimationClipAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , AnimationControllerAsset>(fieldName, object, nullptr , nullptr, rangeAttrib, modified) ||
|
||||
renderFieldEditor<AssetID , AnimationRigAsset >(fieldName, object, nullptr , nullptr, rangeAttrib, modified);
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/FontAsset.hxx"
|
||||
#include "Assets/MeshAsset.hxx"
|
||||
#include "Assets/MaterialAsset.hxx"
|
||||
#include "Assets/AnimationClipAsset.hxx"
|
||||
#include "Assets/AnimationControllerAsset.hxx"
|
||||
#include "Assets/AnimationRigAsset.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -237,6 +240,42 @@ namespace SHADE
|
|||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template<>
|
||||
bool Editor::renderFieldEditorInternal<AssetID, AnimationClipAsset>(const std::string& fieldName, interior_ptr<AnimationClipAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||
{
|
||||
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::ANIM_CLIP, isHovered))
|
||||
{
|
||||
*managedValPtr = AnimationClipAsset(assetId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template<>
|
||||
bool Editor::renderFieldEditorInternal<AssetID, AnimationControllerAsset>(const std::string& fieldName, interior_ptr<AnimationControllerAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||
{
|
||||
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::ANIM_CONTROLLER, isHovered))
|
||||
{
|
||||
*managedValPtr = AnimationControllerAsset(assetId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template<>
|
||||
bool Editor::renderFieldEditorInternal<AssetID, AnimationRigAsset>(const std::string& fieldName, interior_ptr<AnimationRigAsset> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
|
||||
{
|
||||
uint32_t assetId = managedValPtr->NativeAssetID;
|
||||
if (SHEditorUI::InputAssetField(fieldName, assetId, AssetType::MODEL, isHovered))
|
||||
{
|
||||
*managedValPtr = AnimationRigAsset(assetId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "UI\SHUIComponent.h"
|
||||
#include "UI\SHSliderComponent.h"
|
||||
#include "UI\SHCanvasComponent.h"
|
||||
#include "Animation\SHAnimatorComponent.h"
|
||||
#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h"
|
||||
// Project Headers
|
||||
#include "Utility/Convert.hxx"
|
||||
#include "Utility/Debug.hxx"
|
||||
|
@ -47,7 +49,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Components\Canvas.hxx"
|
||||
#include "Components\Slider.hxx"
|
||||
#include "Components\TrajectoryRenderable.hxx"
|
||||
#include "Graphics\MiddleEnd\TrajectoryRendering\SHTrajectoryRenderableComponent.h"
|
||||
#include "Components\Animator.hxx"
|
||||
|
||||
|
||||
|
||||
|
@ -338,6 +340,7 @@ namespace SHADE
|
|||
componentMap.Add(createComponentSet<SHCanvasComponent, Canvas>());
|
||||
componentMap.Add(createComponentSet<SHSliderComponent, Slider>());
|
||||
componentMap.Add(createComponentSet<SHTrajectoryRenderableComponent, TrajectoryRenderable>());
|
||||
componentMap.Add(createComponentSet<SHAnimatorComponent, Animator>());
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -23,6 +23,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/MeshAsset.hxx"
|
||||
#include "Scripts/Script.hxx"
|
||||
#include "Scripts/ScriptStore.hxx"
|
||||
#include "Assets/AnimationClipAsset.hxx"
|
||||
#include "Assets/AnimationControllerAsset.hxx"
|
||||
#include "Assets/AnimationRigAsset.hxx"
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* File-Level Constants */
|
||||
|
@ -164,24 +167,27 @@ namespace SHADE
|
|||
YAML::Node fieldNode;
|
||||
|
||||
// Retrieve string for the YAML
|
||||
const bool PRIMITIVE_SERIALIZED = fieldInsertYaml<System::Int16 >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Int32 >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Int64 >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt16>(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt32>(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt64>(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Byte >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<bool >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<float >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<double >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Enum >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::String>(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<Vector2 >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<Vector3 >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<GameObject >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<FontAsset >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<MaterialAsset >(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<MeshAsset >(fieldInfo, object, fieldNode);
|
||||
const bool PRIMITIVE_SERIALIZED = fieldInsertYaml<System::Int16 > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Int32 > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Int64 > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt16> (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt32> (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::UInt64> (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Byte > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<bool > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<float > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<double > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::Enum > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<System::String> (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<Vector2 > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<Vector3 > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<GameObject > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<FontAsset > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<MaterialAsset > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<MeshAsset > (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<AnimationClipAsset> (fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<AnimationControllerAsset>(fieldInfo, object, fieldNode) ||
|
||||
fieldInsertYaml<AnimationRigAsset> (fieldInfo, object, fieldNode);
|
||||
|
||||
// Serialization of more complex types
|
||||
if (!PRIMITIVE_SERIALIZED)
|
||||
|
@ -228,24 +234,27 @@ namespace SHADE
|
|||
bool SerialisationUtilities::varInsertYaml(System::Object^ object, YAML::Node& fieldNode)
|
||||
{
|
||||
const bool INSERTED =
|
||||
varInsertYamlInternal<System::Int16 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Int32 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Int64 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt16>(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt32>(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt64>(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Byte >(object, fieldNode) ||
|
||||
varInsertYamlInternal<bool >(object, fieldNode) ||
|
||||
varInsertYamlInternal<float >(object, fieldNode) ||
|
||||
varInsertYamlInternal<double >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Enum >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::String>(object, fieldNode) ||
|
||||
varInsertYamlInternal<Vector2 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<Vector3 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<GameObject >(object, fieldNode) ||
|
||||
varInsertYamlInternal<FontAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<MaterialAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<MeshAsset >(object, fieldNode);
|
||||
varInsertYamlInternal<System::Int16 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Int32 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Int64 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt16 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt32 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::UInt64 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Byte >(object, fieldNode) ||
|
||||
varInsertYamlInternal<bool >(object, fieldNode) ||
|
||||
varInsertYamlInternal<float >(object, fieldNode) ||
|
||||
varInsertYamlInternal<double >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::Enum >(object, fieldNode) ||
|
||||
varInsertYamlInternal<System::String >(object, fieldNode) ||
|
||||
varInsertYamlInternal<Vector2 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<Vector3 >(object, fieldNode) ||
|
||||
varInsertYamlInternal<GameObject >(object, fieldNode) ||
|
||||
varInsertYamlInternal<FontAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<MaterialAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<MeshAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<AnimationClipAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<AnimationRigAsset >(object, fieldNode) ||
|
||||
varInsertYamlInternal<AnimationControllerAsset>(object, fieldNode);
|
||||
return INSERTED;
|
||||
}
|
||||
|
||||
|
@ -255,24 +264,27 @@ namespace SHADE
|
|||
bool SerialisationUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
|
||||
{
|
||||
const bool ASSIGNED =
|
||||
fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt16>(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt32>(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt64>(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Byte> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<bool> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<float> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<double> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Enum> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::String>(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<Vector2> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<Vector3> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<GameObject> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<FontAsset> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<MaterialAsset> (fieldInfo, object, node) ||
|
||||
fieldAssignYaml<MeshAsset> (fieldInfo, object, node);
|
||||
fieldAssignYaml<System::Int16 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Int32 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Int64 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt16 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt32 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::UInt64 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Byte >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<bool >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<float >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<double >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::Enum >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<System::String >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<Vector2 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<Vector3 >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<GameObject >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<FontAsset >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<MaterialAsset >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<MeshAsset >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<AnimationClipAsset >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<AnimationRigAsset >(fieldInfo, object, node) ||
|
||||
fieldAssignYaml<AnimationControllerAsset>(fieldInfo, object, node);
|
||||
if (!ASSIGNED)
|
||||
{
|
||||
if (ReflectionUtilities::FieldIsList(fieldInfo))
|
||||
|
@ -329,24 +341,27 @@ namespace SHADE
|
|||
bool SerialisationUtilities::varAssignYaml(System::Object^% object, YAML::Node& node)
|
||||
{
|
||||
const bool DESERIALISED =
|
||||
varAssignYamlInternal<System::Int16> (object, node) ||
|
||||
varAssignYamlInternal<System::Int32> (object, node) ||
|
||||
varAssignYamlInternal<System::Int64> (object, node) ||
|
||||
varAssignYamlInternal<System::UInt16>(object, node) ||
|
||||
varAssignYamlInternal<System::UInt32>(object, node) ||
|
||||
varAssignYamlInternal<System::UInt64>(object, node) ||
|
||||
varAssignYamlInternal<System::Byte> (object, node) ||
|
||||
varAssignYamlInternal<bool> (object, node) ||
|
||||
varAssignYamlInternal<float> (object, node) ||
|
||||
varAssignYamlInternal<double> (object, node) ||
|
||||
varAssignYamlInternal<System::Enum> (object, node) ||
|
||||
varAssignYamlInternal<System::String>(object, node) ||
|
||||
varAssignYamlInternal<Vector2> (object, node) ||
|
||||
varAssignYamlInternal<Vector3> (object, node) ||
|
||||
varAssignYamlInternal<GameObject> (object, node) ||
|
||||
varAssignYamlInternal<FontAsset> (object, node) ||
|
||||
varAssignYamlInternal<MaterialAsset> (object, node) ||
|
||||
varAssignYamlInternal<MeshAsset> (object, node);
|
||||
varAssignYamlInternal<System::Int16 >(object, node) ||
|
||||
varAssignYamlInternal<System::Int32 >(object, node) ||
|
||||
varAssignYamlInternal<System::Int64 >(object, node) ||
|
||||
varAssignYamlInternal<System::UInt16 >(object, node) ||
|
||||
varAssignYamlInternal<System::UInt32 >(object, node) ||
|
||||
varAssignYamlInternal<System::UInt64 >(object, node) ||
|
||||
varAssignYamlInternal<System::Byte >(object, node) ||
|
||||
varAssignYamlInternal<bool >(object, node) ||
|
||||
varAssignYamlInternal<float >(object, node) ||
|
||||
varAssignYamlInternal<double >(object, node) ||
|
||||
varAssignYamlInternal<System::Enum >(object, node) ||
|
||||
varAssignYamlInternal<System::String >(object, node) ||
|
||||
varAssignYamlInternal<Vector2 >(object, node) ||
|
||||
varAssignYamlInternal<Vector3 >(object, node) ||
|
||||
varAssignYamlInternal<GameObject >(object, node) ||
|
||||
varAssignYamlInternal<FontAsset >(object, node) ||
|
||||
varAssignYamlInternal<MaterialAsset >(object, node) ||
|
||||
varAssignYamlInternal<MeshAsset >(object, node) ||
|
||||
varAssignYamlInternal<AnimationClipAsset >(object, node) ||
|
||||
varAssignYamlInternal<AnimationRigAsset >(object, node) ||
|
||||
varAssignYamlInternal<AnimationControllerAsset>(object, node);
|
||||
return DESERIALISED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,9 +60,12 @@ namespace SHADE
|
|||
{
|
||||
fieldNode = MAX_EID;
|
||||
}
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset>)
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset> ||
|
||||
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||
{
|
||||
fieldNode = INVALID_ASSET_ID;
|
||||
}
|
||||
|
@ -128,9 +131,12 @@ namespace SHADE
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset>)
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset> ||
|
||||
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||
{
|
||||
if (object->GetType() == FieldType::typeid)
|
||||
{
|
||||
|
@ -254,9 +260,12 @@ namespace SHADE
|
|||
const uint32_t EID = node.as<uint32_t>();
|
||||
object = (EID == MAX_EID ? GameObject() : GameObject(EID));
|
||||
}
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset>)
|
||||
else if constexpr (std::is_same_v<FieldType, FontAsset> ||
|
||||
std::is_same_v<FieldType, MaterialAsset> ||
|
||||
std::is_same_v<FieldType, MeshAsset> ||
|
||||
std::is_same_v<FieldType, AnimationClipAsset> ||
|
||||
std::is_same_v<FieldType, AnimationControllerAsset> ||
|
||||
std::is_same_v<FieldType, AnimationRigAsset>)
|
||||
{
|
||||
if (object->GetType() == FieldType::typeid)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue