Merge branch 'main' into SP3-141-Camera-System

This commit is contained in:
maverickdgg 2022-11-13 05:31:34 +08:00
commit 922d5b0996
132 changed files with 3320 additions and 1184 deletions

View File

@ -0,0 +1,8 @@
- VertexShader: 39210065
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 58303057
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: BagMaterial
ID: 123745521
Type: 7

View File

@ -50,7 +50,7 @@
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Type: Box Type: Box
Half Extents: {x: 0.0170898438, y: 0.00048828125, z: 0.0170898438} Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006 Friction: 0.400000006
Bounciness: 0 Bounciness: 0
Density: 1 Density: 1
@ -59,7 +59,7 @@
- EID: 2 - EID: 2
Name: Player Name: Player
IsActive: true IsActive: true
NumberOfChildren: 2 NumberOfChildren: 3
Components: Components:
Transform Component: Transform Component:
Translate: {x: -3.06177855, y: -2, z: -5} Translate: {x: -3.06177855, y: -2, z: -5}
@ -85,7 +85,7 @@
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Type: Box Type: Box
Half Extents: {x: 0.0009765625, y: 0.0009765625, z: 0.0009765625} Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006 Friction: 0.400000006
Bounciness: 0 Bounciness: 0
Density: 1 Density: 1
@ -111,47 +111,18 @@
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1} Scale: {x: 1, y: 1, z: 1}
Scripts: ~ Scripts: ~
- EID: 5 - EID: 9
Name: item Name: Default
IsActive: true IsActive: true
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 0, y: -2, z: -5} Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2} Scale: {x: 1, y: 1, z: 1}
Renderable Component: Renderable Component:
Mesh: 149697411 Mesh: 144838771
Material: 126974645 Material: 123745521
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.0009765625, y: 0.0009765625, z: 0.0009765625}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
- Is Trigger: true
Type: Box
Half Extents: {x: 0.001953125, y: 0.001953125, z: 0.001953125}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~ Scripts: ~
- EID: 6 - EID: 6
Name: AI Name: AI
@ -161,7 +132,7 @@
Transform Component: Transform Component:
Translate: {x: -8, y: -2, z: 2.5} Translate: {x: -8, y: -2, z: 2.5}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2} Scale: {x: 1, y: 1, z: 1}
Renderable Component: Renderable Component:
Mesh: 149697411 Mesh: 149697411
Material: 126974645 Material: 126974645
@ -182,7 +153,7 @@
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Type: Box Type: Box
Half Extents: {x: 0.0009765625, y: 0.0009765625, z: 0.0009765625} Half Extents: {x: 0.5, y: 0.5, z: 0.5}
Friction: 0.400000006 Friction: 0.400000006
Bounciness: 0 Bounciness: 0
Density: 1 Density: 1
@ -194,9 +165,9 @@
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 3, y: -1, z: -1} Translate: {x: 0, y: -16.8647861, z: -14.039052}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 5, y: 5, z: 5} Scale: {x: 28.1434975, y: 28.1434975, z: 28.1434975}
Renderable Component: Renderable Component:
Mesh: 149697411 Mesh: 149697411
Material: 126974645 Material: 126974645
@ -213,4 +184,46 @@
Color: {x: 1, y: 1, z: 1, w: 1} Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295 Layer: 4294967295
Strength: 0.25 Strength: 0.25
Scripts: ~
- EID: 5
Name: item
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -2, z: -5}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2}
Renderable Component:
Mesh: 144838771
Material: 123745521
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
- Is Trigger: true
Type: Box
Half Extents: {x: 2, y: 2, z: 2}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~ Scripts: ~

View File

@ -0,0 +1,72 @@
- EID: 0
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0.304069757, z: 1.73034382}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Camera Component:
Position: {x: 0, y: 0.304069757, z: 1.73034382}
Pitch: 0
Yaw: 0
Roll: 0
Width: 1200
Height: 1080
Near: 0.00999999978
Far: 10000
Perspective: true
Scripts: ~
- EID: 1
Name: Raccoon
IsActive: true
NumberOfChildren: 1
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Renderable Component:
Mesh: 149697411
Material: 126974645
Scripts: ~
- EID: 3
Name: Bag
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
Rotate: {x: -0, y: 2.79945588, z: 0}
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
Renderable Component:
Mesh: 144838771
Material: 123745521
Scripts: ~
- EID: 2
Name: DirectionalLight
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Directional
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0
Scripts: ~
- EID: 4
Name: AmbientLight
IsActive: true
NumberOfChildren: 0
Components:
Light Component:
Position: {x: 0, y: 0, z: 0}
Type: Ambient
Direction: {x: 0, y: 0, z: 1}
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0.600000024
Scripts: ~

View File

@ -0,0 +1,3 @@
Name: Scene2
ID: 87285316
Type: 5

View File

@ -15,7 +15,7 @@ public class PlayerController : Script
TOTAL TOTAL
} }
public RigidBody rb; public RigidBody rb { get; set; }
private Transform tranform; private Transform tranform;
private Camera cam; private Camera cam;
private PickAndThrow pat; private PickAndThrow pat;

View File

@ -27,6 +27,11 @@ public class RaccoonShowcase : Script
Debug.LogError("Transform is NULL!"); Debug.LogError("Transform is NULL!");
} }
foreach (var child in Owner)
{
Debug.Log(child.Name);
}
originalScale = Transform.LocalScale.z; originalScale = Transform.LocalScale.z;
} }
protected override void update() protected override void update()
@ -36,4 +41,10 @@ public class RaccoonShowcase : Script
//Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f); //Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
//Transform.LocalScale = new Vector3(System.Math.Abs(System.Math.Sin(scale.x)) * originalScale, System.Math.Abs(System.Math.Cos(scale.y)) * originalScale, System.Math.Abs(System.Math.Sin(scale.z)) * originalScale); //Transform.LocalScale = new Vector3(System.Math.Abs(System.Math.Sin(scale.x)) * originalScale, System.Math.Abs(System.Math.Cos(scale.y)) * originalScale, System.Math.Abs(System.Math.Sin(scale.z)) * originalScale);
} }
protected override void onDrawGizmos()
{
Gizmos.DrawLine(new Vector3(-1.0f, 0.0f, 0.0f), new Vector3(1.0f, 0.0f, 0.0f));
Gizmos.DrawLine(new Vector3(-1.0f, 1.0f, 0.0f), new Vector3(1.0f, 1.0f, 0.0f), Color.Red);
}
} }

View File

@ -8,14 +8,23 @@ public class RaccoonSpin : Script
private float RotateSpeed = 1.0f; private float RotateSpeed = 1.0f;
private float rotation = 0.0f; private float rotation = 0.0f;
[SerializeField] [SerializeField]
private CallbackEvent emptyEvent;
[SerializeField]
private CallbackEvent<int> testEvent; private CallbackEvent<int> testEvent;
[SerializeField] [SerializeField]
private CallbackEvent<int, double, Vector3> testEvent3 = new CallbackEvent<int, double, Vector3>(); private CallbackEvent<int, double, Vector3> testEvent3 = new CallbackEvent<int, double, Vector3>();
private Transform Transform; private Transform Transform;
public RaccoonSpin(GameObject gameObj) : base(gameObj) { } public RaccoonSpin(GameObject gameObj) : base(gameObj) { }
protected override void awake() protected override void awake()
{ {
emptyEvent = new CallbackEvent();
emptyEvent.RegisterAction(() => Debug.Log("Empty event action!"));
testEvent = new CallbackEvent<int>();
Action<int> action = (x) => Debug.Log($"{x}");
testEvent.RegisterAction(action);
Transform = GetComponent<Transform>(); Transform = GetComponent<Transform>();
if (Transform == null) if (Transform == null)
{ {

View File

@ -59,7 +59,7 @@ if %_e%==3 (goto :done) else (goto :ModelCompiler)
echo -----------------------ModelCompiler---------------------------- echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/ModelCompiler" /S /Q rmdir "Dependencies/ModelCompiler" /S /Q
git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler" git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler"
Dependencies/ModelCompiler/Dependencies.bat git clone https://github.com/SHADE-DP/assimp.git "Dependencies/ModelCompiler/Dependencies/assimp"
if %_e%==4 (goto :done) else (goto :spdlog) if %_e%==4 (goto :done) else (goto :spdlog)
@REM :ktx @REM :ktx

View File

@ -106,6 +106,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>(); SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>(); SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::GizmosDrawRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>(); SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();

View File

@ -92,7 +92,7 @@ namespace Sandbox
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
auto* floorBox = floorCollider.AddBoundingBox(); floorCollider.AddBoundingBox();
// Create blank entity with a script // Create blank entity with a script
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>(); //testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
@ -114,8 +114,8 @@ namespace Sandbox
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f }); racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
racoonCollider.AddBoundingBox(); racoonCollider.AddBoundingBox();
racoonCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
racoonCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>(); auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation); auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
@ -140,13 +140,13 @@ namespace Sandbox
itemCollider.AddBoundingBox(); itemCollider.AddBoundingBox();
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
itemCollider.GetCollider(1).SetIsTrigger(true); itemCollider.GetCollisionShape(1).SetIsTrigger(true);
itemCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
itemCollider.GetCollider(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
itemCollider.GetCollider(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
itemRigidBody.SetInterpolate(false); itemRigidBody.SetInterpolate(false);
itemRigidBody.SetFreezeRotationX(true); itemRigidBody.SetFreezeRotationX(true);
@ -168,8 +168,8 @@ namespace Sandbox
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f }); AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
AICollider.AddBoundingBox(); AICollider.AddBoundingBox();
AICollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
AICollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
AIRigidBody.SetInterpolate(false); AIRigidBody.SetInterpolate(false);
AIRigidBody.SetFreezeRotationX(true); AIRigidBody.SetFreezeRotationX(true);

View File

@ -34,6 +34,99 @@ namespace SHADE
Object TargetObject { get; } Object TargetObject { get; }
} }
/// <summary>
/// Represents a function call that can be serialised and put togetheer with scripts.
/// This variant accepts functions with 0 parameter.
/// </summary>
public class CallbackAction : ICallbackAction
{
#region Properties ------------------------------------------------------------
/// <inheritdoc/>
public Object TargetObject { get; private set; }
/// <inheritdoc/>
public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name;
/// <inheritdoc/>
public bool IsRuntimeAction => targetAction != null;
#endregion
#region Fields ------------------------------------------------------------------
private MethodInfo targetMethod;
private Action targetAction;
private Object[] parameters;
#endregion
#region Constructors ------------------------------------------------------------
/// <summary>
/// Constructs an empty Callback action.
/// </summary>
public CallbackAction() {}
/// <summary>
/// Constructs a CallbackAction that represents a call to the specified static
/// method.
/// </summary>
/// <param name="method">Method to call.</param>
/// <exception cref="ArgumentException">
/// Thrown if a method that is not compatible with the target is specified. The method's
/// source type must match the target's type.
/// </exception>
public CallbackAction(MethodInfo method)
{
// No errors, assign
targetMethod = method;
// Create storage for parameters for calling
parameters = new Object[0];
}
/// <summary>
/// Constructs a CallbackAction that represents a call to a specified member
/// method on the specified target.
/// </summary>
/// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param>
/// <exception cref="ArgumentException">
/// Thrown if a method that is not compatible with the target is specified. The method's
/// source type must match the target's type.
/// </exception>
public CallbackAction(Object target, MethodInfo method)
{
// Error Checks
if (method.DeclaringType != target.GetType())
throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method.");
// No errors, assign
TargetObject = target;
targetMethod = method;
// Create storage for parameters for calling
parameters = new Object[0];
}
/// <summary>
/// Constructs a Callback action based on an action.
/// </summary>
/// <param name="action">Action that wraps a function to be called.</param>
public CallbackAction(Action action)
{
targetAction = action;
}
#endregion
#region Usage Functions ---------------------------------------------------------
/// <summary>
/// Invokes the CallbackAction's stored method/action with the specified parameters.
/// </summary>
public void Invoke()
{
if (targetAction != null)
{
targetAction.Invoke();
}
else if (targetMethod != null)
{
_ = targetMethod.Invoke(TargetObject, parameters);
}
}
#endregion
}
/// <summary> /// <summary>
/// Represents a function call that can be serialised and put togetheer with scripts. /// Represents a function call that can be serialised and put togetheer with scripts.
/// This variant accepts functions with 1 parameter. /// This variant accepts functions with 1 parameter.

View File

@ -50,12 +50,12 @@ namespace SHADE
Object TargetObject { get; } Object TargetObject { get; }
} }
<# for (int i = 1; i <= max; ++i) { #> <# for (int i = 0; i <= max; ++i) { #>
/// <summary> /// <summary>
/// Represents a function call that can be serialised and put togetheer with scripts. /// Represents a function call that can be serialised and put togetheer with scripts.
/// This variant accepts functions with <#=i#> parameter<# if (i > 1) {#>s<#} #>. /// This variant accepts functions with <#=i#> parameter<# if (i > 1) {#>s<#} #>.
/// </summary> /// </summary>
public class CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackAction public class CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> : ICallbackAction
{ {
#region Properties ------------------------------------------------------------ #region Properties ------------------------------------------------------------
/// <inheritdoc/> /// <inheritdoc/>
@ -68,7 +68,7 @@ namespace SHADE
#region Fields ------------------------------------------------------------------ #region Fields ------------------------------------------------------------------
private MethodInfo targetMethod; private MethodInfo targetMethod;
private Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> targetAction; private Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> targetAction;
private Object[] parameters; private Object[] parameters;
#endregion #endregion
@ -121,7 +121,7 @@ namespace SHADE
/// Constructs a Callback action based on an action. /// Constructs a Callback action based on an action.
/// </summary> /// </summary>
/// <param name="action">Action that wraps a function to be called.</param> /// <param name="action">Action that wraps a function to be called.</param>
public CallbackAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) public CallbackAction(Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action)
{ {
targetAction = action; targetAction = action;
} }

View File

@ -45,6 +45,92 @@ namespace SHADE
IEnumerable<ICallbackAction> Actions { get; } IEnumerable<ICallbackAction> Actions { get; }
} }
/// <summary>
/// A container of CallbackActions that is correlated to a specific scenario as
/// specified by the user of this class.
/// This variant accepts CallbackEvents with 1 generic parameter.
/// </summary>
public class CallbackEvent : ICallbackEvent
{
#region Properties --------------------------------------------------------------
/// <inheritdoc/>
public IEnumerable<ICallbackAction> Actions => actions;
#endregion
#region Fields ------------------------------------------------------------------
private List<ICallbackAction> actions = new List<ICallbackAction>();
#endregion
#region Usage Functions ---------------------------------------------------------
/// <inheritdoc/>
public void RegisterAction()
{
actions.Add(new CallbackAction());
}
/// <inheritdoc/>
public void RegisterAction(ICallbackAction action)
{
// Check if valid action
if (action.GetType() != typeof(CallbackAction))
{
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
return;
}
actions.Add(action);
}
/// <summary>
/// Adds a CallbackAction into the event.
/// </summary>
/// <param name="action">CallbackAction to add.</param>
public void RegisterAction(CallbackAction action)
{
actions.Add(action);
}
/// <summary>
/// Constructs and adds a CallbackAction into the event.
/// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action action)
{
actions.Add(new CallbackAction(action));
}
/// <summary>
/// Constructs and adds a CallbackAction into the event.
/// </summary>
/// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param>
public void RegisterAction(Object target, MethodInfo method)
{
actions.Add(new CallbackAction(target, method));
}
/// <inheritdoc/>
public void DeregisterAction(ICallbackAction action)
{
if (!actions.Remove(action))
{
Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this);
}
}
/// <summary>
/// Invokes all stored CallbackActions with the specified parameters.
/// </summary>
public void Invoke()
{
foreach (CallbackAction action in actions)
{
try
{
action.Invoke();
}
catch (Exception e)
{
Debug.LogException(e, this);
}
}
}
#endregion
}
/// <summary> /// <summary>
/// A container of CallbackActions that is correlated to a specific scenario as /// A container of CallbackActions that is correlated to a specific scenario as
/// specified by the user of this class. /// specified by the user of this class.
@ -88,7 +174,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1> action) public void RegisterAction(Action<T1> action)
@ -96,7 +182,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1>(action)); actions.Add(new CallbackAction<T1>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -174,7 +260,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2> action) public void RegisterAction(Action<T1, T2> action)
@ -182,7 +268,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2>(action)); actions.Add(new CallbackAction<T1, T2>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -260,7 +346,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3> action) public void RegisterAction(Action<T1, T2, T3> action)
@ -268,7 +354,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3>(action)); actions.Add(new CallbackAction<T1, T2, T3>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -346,7 +432,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4> action) public void RegisterAction(Action<T1, T2, T3, T4> action)
@ -354,7 +440,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -432,7 +518,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5> action) public void RegisterAction(Action<T1, T2, T3, T4, T5> action)
@ -440,7 +526,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -518,7 +604,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6> action) public void RegisterAction(Action<T1, T2, T3, T4, T5, T6> action)
@ -526,7 +612,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -604,7 +690,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7> action) public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7> action)
@ -612,7 +698,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -690,7 +776,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8> action) public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
@ -698,7 +784,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -776,7 +862,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> action) public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> action)
@ -784,7 +870,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
@ -862,7 +948,7 @@ namespace SHADE
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action) public void RegisterAction(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> action)
@ -870,7 +956,7 @@ namespace SHADE
actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(action)); actions.Add(new CallbackAction<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>

View File

@ -61,13 +61,13 @@ namespace SHADE
IEnumerable<ICallbackAction> Actions { get; } IEnumerable<ICallbackAction> Actions { get; }
} }
<# for (int i = 1; i <= max; ++i) { #> <# for (int i = 0; i <= max; ++i) { #>
/// <summary> /// <summary>
/// A container of CallbackActions that is correlated to a specific scenario as /// A container of CallbackActions that is correlated to a specific scenario as
/// specified by the user of this class. /// specified by the user of this class.
/// This variant accepts CallbackEvents with 1 generic parameter. /// This variant accepts CallbackEvents with 1 generic parameter.
/// </summary> /// </summary>
public class CallbackEvent<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackEvent public class CallbackEvent<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> : ICallbackEvent
{ {
#region Properties -------------------------------------------------------------- #region Properties --------------------------------------------------------------
/// <inheritdoc/> /// <inheritdoc/>
@ -82,13 +82,13 @@ namespace SHADE
/// <inheritdoc/> /// <inheritdoc/>
public void RegisterAction() public void RegisterAction()
{ {
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>()); actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>());
} }
/// <inheritdoc/> /// <inheritdoc/>
public void RegisterAction(ICallbackAction action) public void RegisterAction(ICallbackAction action)
{ {
// Check if valid action // Check if valid action
if (action.GetType() != typeof(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>)) if (action.GetType() != typeof(CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>))
{ {
Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this); Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this);
return; return;
@ -100,26 +100,26 @@ namespace SHADE
/// Adds a CallbackAction into the event. /// Adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">CallbackAction to add.</param> /// <param name="action">CallbackAction to add.</param>
public void RegisterAction(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) public void RegisterAction(CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action)
{ {
actions.Add(action); actions.Add(action);
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="action">System.Action to add as a CallbackAction.</param> /// <param name="action">System.Action to add as a CallbackAction.</param>
public void RegisterAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) public void RegisterAction(Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action)
{ {
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(action)); actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>(action));
} }
/// <summary> /// <summary>
/// Constructs and adds a CallbackACtion into the event. /// Constructs and adds a CallbackAction into the event.
/// </summary> /// </summary>
/// <param name="target">Object to call the method on.</param> /// <param name="target">Object to call the method on.</param>
/// <param name="method">Method to call.</param> /// <param name="method">Method to call.</param>
public void RegisterAction(Object target, MethodInfo method) public void RegisterAction(Object target, MethodInfo method)
{ {
actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(target, method)); actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>(target, method));
} }
/// <inheritdoc/> /// <inheritdoc/>
public void DeregisterAction(ICallbackAction action) public void DeregisterAction(ICallbackAction action)
@ -132,9 +132,9 @@ namespace SHADE
/// <summary> /// <summary>
/// Invokes all stored CallbackActions with the specified parameters. /// Invokes all stored CallbackActions with the specified parameters.
/// </summary> /// </summary>
public void Invoke(<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } #>) public void Invoke(<# if (i != 0) { for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } } #>)
{ {
foreach (CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action in actions) foreach (CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action in actions)
{ {
try try
{ {

View File

@ -52,6 +52,8 @@ enum class AssetType : AssetTypeMeta
PREFAB, PREFAB,
MATERIAL, MATERIAL,
MESH, MESH,
SCRIPT,
FONT,
MAX_COUNT MAX_COUNT
}; };
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) }; constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
@ -85,32 +87,39 @@ constexpr std::string_view SCENE_EXTENSION {".shade"};
constexpr std::string_view PREFAB_EXTENSION {".shprefab"}; constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
constexpr std::string_view MODEL_EXTENSION {".shmodel"}; constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
constexpr std::string_view EXTENSIONS[] = { constexpr std::string_view EXTENSIONS[] = {
AUDIO_EXTENSION, AUDIO_EXTENSION,
SHADER_EXTENSION, SHADER_EXTENSION,
SHADER_BUILT_IN_EXTENSION, SHADER_BUILT_IN_EXTENSION,
MATERIAL_EXTENSION, TEXTURE_EXTENSION,
TEXTURE_EXTENSION,
MODEL_EXTENSION, MODEL_EXTENSION,
SCRIPT_EXTENSION, SCENE_EXTENSION,
SCENE_EXTENSION,
PREFAB_EXTENSION, PREFAB_EXTENSION,
MATERIAL_EXTENSION,
"dummy",
SCRIPT_EXTENSION,
FONT_EXTENSION,
AUDIO_WAV_EXTENSION, AUDIO_WAV_EXTENSION,
}; };
constexpr size_t EXTENSIONS_COUNT{ 11 };
// EXTERNAL EXTENSIONS // EXTERNAL EXTENSIONS
constexpr std::string_view GLSL_EXTENSION{ ".glsl" }; constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
constexpr std::string_view DDS_EXTENSION{ ".dds" }; constexpr std::string_view DDS_EXTENSION{ ".dds" };
constexpr std::string_view FBX_EXTENSION{ ".fbx" }; constexpr std::string_view FBX_EXTENSION{ ".fbx" };
constexpr std::string_view GLTF_EXTENSION{ ".gltf" }; constexpr std::string_view GLTF_EXTENSION{ ".gltf" };
constexpr std::string_view TTF_EXTENSION{ ".ttf" };
constexpr std::string_view EXTERNALS[] = { constexpr std::string_view EXTERNALS[] = {
GLSL_EXTENSION, GLSL_EXTENSION,
DDS_EXTENSION, DDS_EXTENSION,
FBX_EXTENSION, FBX_EXTENSION,
GLTF_EXTENSION GLTF_EXTENSION,
TTF_EXTENSION
}; };
// SHADER IDENTIFIERS // SHADER IDENTIFIERS
@ -125,11 +134,4 @@ constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[
}; };
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 }; constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };
// Error flags
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
#endif // !SH_ASSET_MACROS_H #endif // !SH_ASSET_MACROS_H

View File

@ -338,7 +338,7 @@ namespace SHADE
return result; return result;
} }
void SHAssetManager::CompileAsset(AssetPath const& path) noexcept void SHAssetManager::CompileAsset(AssetPath const& path, bool genMeta) noexcept
{ {
if (!std::filesystem::exists(path)) if (!std::filesystem::exists(path))
{ {
@ -360,10 +360,12 @@ namespace SHADE
std::string modelPath = path.string().substr(0, path.string().find_last_of('.')); std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
modelPath += MODEL_EXTENSION; modelPath += MODEL_EXTENSION;
newPath = modelPath; newPath = modelPath;
GenerateNewMeta(newPath);
} }
if (genMeta)
{
GenerateNewMeta(newPath);
}
} }
FolderPointer SHAssetManager::GetRootFolder() noexcept FolderPointer SHAssetManager::GetRootFolder() noexcept
@ -371,6 +373,13 @@ namespace SHADE
return folderRoot; return folderRoot;
} }
void SHAssetManager::RefreshDirectory() noexcept
{
SHFileSystem::DestroyDirectory(folderRoot);
assetCollection.clear();
BuildAssetCollection();
}
bool SHAssetManager::IsRecognised(char const* ext) noexcept bool SHAssetManager::IsRecognised(char const* ext) noexcept
{ {
for (auto const& e : EXTENSIONS) for (auto const& e : EXTENSIONS)
@ -396,51 +405,6 @@ namespace SHADE
return result; return result;
} }
void SHAssetManager::CompileAll() noexcept
{
std::vector<AssetPath> paths;
for (auto const& dir : std::filesystem::recursive_directory_iterator{ ASSET_ROOT })
{
if (dir.is_regular_file())
{
for (auto const& ext : EXTERNALS)
{
if (dir.path().extension().string() == ext.data())
{
paths.push_back(dir.path());
}
}
}
}
for (auto const& path : paths)
{
AssetPath newPath;
auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data())
{
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
}
else if (ext == DDS_EXTENSION.data())
{
newPath = SHTextureCompiler::CompileTextureAsset(path).value();
}
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{
std::string command = MODEL_COMPILER_EXE.data();
command += " " + path.string();
std::system(command.c_str());
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
modelPath += MODEL_EXTENSION;
newPath = modelPath;
}
GenerateNewMeta(newPath);
}
}
bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept bool SHAssetManager::DeleteLocalFile(AssetPath path) noexcept
{ {
//TODO Move this to dedicated library //TODO Move this to dedicated library

View File

@ -87,9 +87,10 @@ namespace SHADE
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept; static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept; static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
static void CompileAsset(AssetPath const& path) noexcept; static void CompileAsset(AssetPath const& path, bool genMeta) noexcept;
static FolderPointer GetRootFolder() noexcept; static FolderPointer GetRootFolder() noexcept;
static void RefreshDirectory() noexcept;
private: private:
@ -106,8 +107,6 @@ namespace SHADE
static SHAsset CreateAssetFromPath(AssetPath path) noexcept; static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
static void CompileAll() noexcept;
static bool DeleteLocalFile(AssetPath path) noexcept; static bool DeleteLocalFile(AssetPath path) noexcept;
//TODO use this function to create asset data internall at all calls to generate id //TODO use this function to create asset data internall at all calls to generate id

View File

@ -38,7 +38,7 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
AssetType SHAssetMetaHandler::GetTypeFromExtension(AssetExtension ext) noexcept AssetType SHAssetMetaHandler::GetTypeFromExtension(AssetExtension ext) noexcept
{ {
for (int i{0}; i < EXTENSIONS->size(); ++i) for (auto i{0}; i < EXTENSIONS_COUNT; ++i)
{ {
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0) if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
{ {
@ -98,6 +98,7 @@ namespace SHADE
meta.type = static_cast<AssetType>(type); meta.type = static_cast<AssetType>(type);
meta.isSubAsset = false; meta.isSubAsset = false;
meta.parent = 0;
// Burn Line // Burn Line
if (std::getline(metaFile, line)) if (std::getline(metaFile, line))

View File

@ -17,6 +17,8 @@
#include <FMOD/fmod_studio.hpp> #include <FMOD/fmod_studio.hpp>
#include <SDL_keyboard.h> #include <SDL_keyboard.h>
const std::string AUDIO_FOLDER_PATH{ std::string(ASSET_ROOT)+ "/Audio/" };
namespace SHADE namespace SHADE
{ {
SHAudioSystem::SHAudioSystem() SHAudioSystem::SHAudioSystem()
@ -79,10 +81,10 @@ namespace SHADE
//SHResourceManager::LoadAllAudio(system, soundList); //SHResourceManager::LoadAllAudio(system, soundList);
LoadBank("../../Assets/Audio/Master.bank"); LoadBank((AUDIO_FOLDER_PATH + "Master.bank").data());
LoadBank("../../Assets/Audio/Master.strings.bank"); LoadBank((AUDIO_FOLDER_PATH + "Master.strings.bank").data());
//LoadBank("../../Assets/Audio/Music.bank"); //LoadBank((AUDIO_FOLDER_PATH + "Music.bank").data());
LoadBank("../../Assets/Audio/footsteps.bank"); LoadBank((AUDIO_FOLDER_PATH + "footsteps.bank").data());
//auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human"); //auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human");
//clip->Play(); //clip->Play();

View File

@ -10,63 +10,102 @@
namespace SHADE namespace SHADE
{ {
SHCommandManager::CommandStack SHCommandManager::undoStack{};
SHCommandManager::CommandStack SHCommandManager::redoStack{}; SHCommandManager::CommandStack SHCommandManager::undoStack(defaultStackSize);
SHCommandManager::CommandStack SHCommandManager::redoStack(defaultStackSize);
SHCommandManager::CommandStack SHCommandManager::secondaryUndoStack(defaultStackSize);
SHCommandManager::CommandStack SHCommandManager::secondaryRedoStack(defaultStackSize);
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue) void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
{ {
redoStack = CommandStack(); *pCurrRedoStack = CommandStack(defaultStackSize);
commandPtr->Execute(); commandPtr->Execute();
if (overrideValue && !undoStack.empty()) if (overrideValue && !pCurrUndoStack->Empty())
{ {
undoStack.top()->Merge(commandPtr); pCurrUndoStack->Top()->Merge(commandPtr);
} }
else else
{ {
undoStack.push(commandPtr); pCurrUndoStack->Push(commandPtr);
} }
} }
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr) void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
{ {
undoStack.push(commandPtr); pCurrUndoStack->Push(commandPtr);
} }
void SHCommandManager::UndoCommand() void SHCommandManager::UndoCommand()
{ {
if (undoStack.empty()) if (pCurrUndoStack->Empty())
return; return;
undoStack.top()->Undo(); pCurrUndoStack->Top()->Undo();
redoStack.push(undoStack.top()); pCurrRedoStack->Push(pCurrUndoStack->Top());
undoStack.pop(); pCurrUndoStack->Pop();
} }
void SHCommandManager::RedoCommand() void SHCommandManager::RedoCommand()
{ {
if (redoStack.empty()) if (pCurrRedoStack->Empty())
return; return;
redoStack.top()->Execute(); pCurrRedoStack->Top()->Execute();
undoStack.push(redoStack.top()); pCurrUndoStack->Push(pCurrRedoStack->Top());
redoStack.pop(); pCurrRedoStack->Pop();
} }
std::size_t SHCommandManager::GetUndoStackSize() std::size_t SHCommandManager::GetUndoStackSize()
{ {
return undoStack.size(); return pCurrUndoStack->Size();
} }
std::size_t SHCommandManager::GetRedoStackSize() std::size_t SHCommandManager::GetRedoStackSize()
{ {
return redoStack.size(); return pCurrRedoStack->Size();
} }
void SHCommandManager::PopLatestCommandFromRedoStack() void SHCommandManager::PopLatestCommandFromRedoStack()
{ {
redoStack.pop(); pCurrRedoStack->Pop();
} }
void SHCommandManager::PopLatestCommandFromUndoStack() void SHCommandManager::PopLatestCommandFromUndoStack()
{ {
undoStack.pop(); pCurrUndoStack->Pop();
} }
void SHCommandManager::SwapStacks()
{
if (pCurrUndoStack == &undoStack)
{
pCurrUndoStack = &secondaryUndoStack;
}
else
{
secondaryUndoStack.Clear();
pCurrUndoStack = &undoStack;
}
if (pCurrRedoStack == &redoStack)
{
pCurrRedoStack = &secondaryRedoStack;
}
else
{
secondaryRedoStack.Clear();
pCurrRedoStack = &redoStack;
}
}
void SHCommandManager::ClearAll()
{
undoStack.Clear();
redoStack.Clear();
secondaryUndoStack.Clear();
secondaryRedoStack.Clear();
}
}//namespace SHADE }//namespace SHADE

View File

@ -10,6 +10,7 @@
//#==============================================================# //#==============================================================#
#include "SHCommand.hpp" #include "SHCommand.hpp"
#include "SH_API.h" #include "SH_API.h"
#include "Tools/SHDeque.h"
namespace SHADE namespace SHADE
{ {
@ -22,7 +23,8 @@ namespace SHADE
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>; using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
template<typename T> template<typename T>
using SHCommandPtr = std::shared_ptr<SHCommand<T>>; using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
using CommandStack = std::stack<BaseCommandPtr>; using CommandStack = SHDeque<BaseCommandPtr>;
using CommandStackPtr = CommandStack*;
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false); static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(BaseCommandPtr commandPtr); static void RegisterCommand(BaseCommandPtr commandPtr);
@ -34,8 +36,17 @@ namespace SHADE
static void PopLatestCommandFromRedoStack(); static void PopLatestCommandFromRedoStack();
static void PopLatestCommandFromUndoStack(); static void PopLatestCommandFromUndoStack();
static void SwapStacks();
static void ClearAll();
static constexpr CommandStack::SizeType defaultStackSize = 100;
private: private:
static CommandStackPtr pCurrUndoStack;
static CommandStackPtr pCurrRedoStack;
static CommandStack undoStack; static CommandStack undoStack;
static CommandStack secondaryUndoStack;
static CommandStack redoStack; static CommandStack redoStack;
static CommandStack secondaryRedoStack;
}; };
}//namespace SHADE }//namespace SHADE

View File

@ -17,7 +17,7 @@
namespace SHADE namespace SHADE
{ {
SHAssetBrowser::SHAssetBrowser() SHAssetBrowser::SHAssetBrowser()
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder), assetBeingCreated(std::nullopt) :SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder)
{ {
} }
@ -34,23 +34,48 @@ namespace SHADE
RecursivelyDrawTree(rootFolder); RecursivelyDrawTree(rootFolder);
DrawMenuBar(); DrawMenuBar();
DrawCurrentFolder(); DrawCurrentFolder();
DrawAssetBeingCreated();
} }
ImGui::End(); ImGui::End();
if(refreshQueued)
Refresh();
}
void SHAssetBrowser::QueueRefresh() noexcept
{
refreshQueued = true;
}
void SHAssetBrowser::Refresh() noexcept
{
SHAssetManager::RefreshDirectory();
rootFolder = SHAssetManager::GetRootFolder();
refreshQueued = false;
} }
void SHAssetBrowser::DrawMenuBar() void SHAssetBrowser::DrawMenuBar()
{ {
if (ImGui::BeginMenuBar()) if (ImGui::BeginMenuBar())
{ {
if(ImGui::SmallButton(ICON_MD_SYNC))
{
QueueRefresh();
}
if(ImGui::SmallButton(ICON_FA_CIRCLE_PLUS))
{
isAssetBeingCreated = true;
}
ImGui::EndMenuBar(); ImGui::EndMenuBar();
} }
} }
//if !compiled, set genMeta to true
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder) ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
{ {
auto const& subFolders = folder->subFolders; auto const& subFolders = folder->subFolders;
auto const& files = folder->files; auto files = folder->files;
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end(); const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow; ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
if (isSelected) if (isSelected)
@ -62,21 +87,10 @@ namespace SHADE
ImGuiID folderID = ImGui::GetItemID(); ImGuiID folderID = ImGui::GetItemID();
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (ImGui::BeginPopupContextItem()) //if (ImGui::BeginPopupContextItem())
{ //{
if (ImGui::BeginMenu("Create Asset")) // ImGui::EndPopup();
{ //}
//TODO: Change to rttr type enum align
if (ImGui::Selectable("Material"))
{
assetBeingCreated = { folder, AssetType::MATERIAL, "New Material" };
ImGui::TreeNodeSetOpen(folderID, true);
isOpen = true;
}
ImGui::EndMenu();
}
ImGui::EndPopup();
}
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
{ {
@ -100,7 +114,7 @@ namespace SHADE
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint; vertLineEnd.y = midPoint;
} }
for (auto const& file : files) for (auto& file : files)
{ {
const float horizontalLineSize = 25.0f; const float horizontalLineSize = 25.0f;
const ImRect childRect = DrawFile(file); const ImRect childRect = DrawFile(file);
@ -109,8 +123,6 @@ namespace SHADE
vertLineEnd.y = midPoint; vertLineEnd.y = midPoint;
} }
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
DrawAssetBeingCreated();
ImGui::TreePop(); ImGui::TreePop();
} }
@ -146,47 +158,74 @@ namespace SHADE
//} //}
} }
ImRect SHAssetBrowser::DrawFile(SHFile const& file) noexcept ImRect SHAssetBrowser::DrawFile(SHFile& file) noexcept
{ {
if (file.assetMeta == nullptr) if(file.compilable)
{
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
ImGui::PushID(file.name.data());
bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if(ImGui::BeginPopupContextItem())
{
if(ImGui::Selectable("Compile"))
{
SHAssetManager::CompileAsset(file.path, !file.compiled);
QueueRefresh();
}
ImGui::EndPopup();
}
ImGui::TreePop();
ImGui::PopID();
return nodeRect;
}
if(file.assetMeta)
DrawAsset(file.assetMeta, file.ext);
}
ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept
{
if (asset == nullptr)
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end(); const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
if (isSelected) if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected; flags |= ImGuiTreeNodeFlags_Selected;
std::string icon{}; std::string icon{};
switch (file.assetMeta->type) switch (asset->type)
{ {
case AssetType::INVALID: break; case AssetType::INVALID: break;
case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break; case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break;
case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break; case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break;
case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break; case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break;
case AssetType::MESH: icon = ICON_FA_CUBES; break; case AssetType::MODEL: icon = ICON_FA_CUBES_STACKED; break;
case AssetType::SCENE: icon = ICON_MD_IMAGE; break; case AssetType::SCENE: icon = ICON_MD_IMAGE; break;
case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break; case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break;
case AssetType::MATERIAL: break; case AssetType::MATERIAL: break;
case AssetType::MESH: icon = ICON_FA_CUBES; break;
case AssetType::MAX_COUNT: break; case AssetType::MAX_COUNT: break;
default:; default:;
} }
ImGui::TreeNodeEx(file.assetMeta, flags, "%s %s", icon.data(), file.assetMeta->name.data()); bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
auto id = file.assetMeta->id; auto id = asset->id;
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id); ImGui::Text("Moving Asset: %s [%zu]", asset->name.data(), asset->id);
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id); SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource(); SHDragDrop::EndSource();
} }
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
{ {
selectedAssets.clear(); selectedAssets.clear();
selectedAssets.push_back(file.assetMeta->id); selectedAssets.push_back(asset->id);
} }
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{ {
switch (file.assetMeta->type) switch (asset->type)
{ {
case AssetType::INVALID: break; case AssetType::INVALID: break;
case AssetType::SHADER: break; case AssetType::SHADER: break;
@ -196,40 +235,92 @@ namespace SHADE
case AssetType::SCENE: case AssetType::SCENE:
if(auto editor = SHSystemManager::GetSystem<SHEditor>()) if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{ {
editor->LoadScene(file.assetMeta->id); editor->LoadScene(asset->id);
} }
break; break;
case AssetType::PREFAB: break; case AssetType::PREFAB: break;
case AssetType::MATERIAL: case AssetType::MATERIAL:
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>()) if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
{ {
matInspector->OpenMaterial(file.assetMeta->id); matInspector->OpenMaterial(asset->id);
} }
break; break;
case AssetType::MAX_COUNT: break; case AssetType::MAX_COUNT: break;
default:; default:;
} }
} }
ImGui::TreePop();
//TODO: Combine Draw asset and Draw Folder recursive drawing
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
const float horizontalOffset = 0.0f;
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
vertLineStart.x += horizontalOffset;
ImVec2 vertLineEnd = vertLineStart;
if(isOpen)
{
for(auto const& subAsset : asset->subAssets)
{
const float horizontalLineSize = 25.0f;
const ImRect childRect = DrawAsset(subAsset);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint;
}
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
ImGui::TreePop();
}
return nodeRect; return nodeRect;
} }
void SHAssetBrowser::DrawAssetBeingCreated() noexcept void SHAssetBrowser::DrawAssetBeingCreated() noexcept
{ {
if (!assetBeingCreated.has_value()) if(isAssetBeingCreated)
return; ImGui::OpenPopup(newAssetPopup.data());
auto& path = std::get<0>(assetBeingCreated.value());
auto& type = std::get<1>(assetBeingCreated.value()); if(ImGui::BeginPopupModal(newAssetPopup.data(), &isAssetBeingCreated))
auto& assetName = std::get<2>(assetBeingCreated.value());
if (ImGui::InputText("##newAssetname", &assetName, ImGuiInputTextFlags_EnterReturnsTrue))
{ {
AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName); ImGui::RadioButton("Material", true);
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>()) ImGui::SameLine();
if (ImGui::InputText("##newAssetName", &nameOfAssetBeingCreated, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
{ {
matInspector->OpenMaterial(assetId, true); AssetID assetId = SHAssetManager::CreateNewAsset(AssetType::MATERIAL, nameOfAssetBeingCreated);
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
{
matInspector->OpenMaterial(assetId, true);
}
nameOfAssetBeingCreated.clear();
QueueRefresh();
isAssetBeingCreated = false;
ImGui::CloseCurrentPopup();
} }
assetBeingCreated.reset(); ImGui::EndPopup();
} }
//if (ImGui::BeginMenu("Create Asset"))
//{
// //TODO: Change to rttr type enum align
// if (ImGui::Selectable("Material"))
// {
// assetBeingCreated = { folder, AssetType::MATERIAL, "NewMaterial" };
// ImGui::TreeNodeSetOpen(folderID, true);
// isOpen = true;
// }
// ImGui::EndMenu();
//}
//if (!assetBeingCreated.has_value())
// return;
//auto& path = std::get<0>(assetBeingCreated.value());
//auto& type = std::get<1>(assetBeingCreated.value());
//auto& assetName = std::get<2>(assetBeingCreated.value());
//if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
//{
// AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
// if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
// {
// matInspector->OpenMaterial(assetId, true);
// }
// assetBeingCreated.reset();
// QueueRefresh();
//}
} }
} }

View File

@ -10,24 +10,29 @@ namespace SHADE
class SHAssetBrowser final : public SHEditorWindow class SHAssetBrowser final : public SHEditorWindow
{ {
public: public:
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
SHAssetBrowser(); SHAssetBrowser();
void Init(); void Init();
void Update(); void Update();
void Refresh(); void QueueRefresh() noexcept;
private: private:
void DrawMenuBar(); void DrawMenuBar();
ImRect RecursivelyDrawTree(FolderPointer folder); ImRect RecursivelyDrawTree(FolderPointer folder);
void DrawCurrentFolder(); void DrawCurrentFolder();
ImRect DrawFile(SHFile const& file) noexcept; ImRect DrawFile(SHFile& file) noexcept;
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
void DrawAssetBeingCreated() noexcept; void DrawAssetBeingCreated() noexcept;
void Refresh() noexcept;
FolderPointer rootFolder, prevFolder, currentFolder; FolderPointer rootFolder, prevFolder, currentFolder;
std::optional<AssetEntry> assetBeingCreated;
std::vector<FolderPointer> selectedFolders; std::vector<FolderPointer> selectedFolders;
std::vector<AssetID> selectedAssets; std::vector<AssetID> selectedAssets;
static constexpr float tileWidth = 50.0f; static constexpr float tileWidth = 50.0f;
bool refreshQueued = false;
bool isAssetBeingCreated = false;
static constexpr std::string_view newAssetPopup = "Create New Asset";
std::string nameOfAssetBeingCreated;
}; };
} }

View File

@ -419,7 +419,7 @@ namespace SHADE
void SHEntityParentCommand::Execute() void SHEntityParentCommand::Execute()
{ {
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for (auto const& eid : entities) for (auto const& eid : entities)
{ {
if (entityParentData[eid].newParentEID == MAX_EID) if (entityParentData[eid].newParentEID == MAX_EID)
@ -431,7 +431,7 @@ namespace SHADE
void SHEntityParentCommand::Undo() void SHEntityParentCommand::Undo()
{ {
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph(); auto& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
for (auto const& eid : entities) for (auto const& eid : entities)
{ {
if (entityParentData[eid].oldParentEID == MAX_EID) if (entityParentData[eid].oldParentEID == MAX_EID)

View File

@ -224,9 +224,6 @@ namespace SHADE
if (!component) if (!component)
return; return;
// Get transform component for extrapolating relative sizes
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(component->GetEID());
const auto componentType = rttr::type::get(*component); const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine(); ImGui::SameLine();
@ -234,46 +231,39 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
auto& colliders = component->GetColliders(); auto& colliders = component->GetCollisionShapes();
int const size = static_cast<int>(colliders.size()); int const size = static_cast<int>(colliders.size());
ImGui::BeginChild("Colliders", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true); ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true);
std::optional<int> colliderToDelete{ std::nullopt }; std::optional<int> colliderToDelete{ std::nullopt };
for (int i{}; i < size; ++i) for (int i{}; i < size; ++i)
{ {
ImGui::PushID(i); ImGui::PushID(i);
SHCollider* collider = &component->GetCollider(i); SHCollisionShape* collider = &component->GetCollisionShape(i);
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
//collider->IsTrigger //collider->IsTrigger
if (collider->GetType() == SHCollider::Type::BOX) if (collider->GetType() == SHCollisionShape::Type::BOX)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape()); auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
SHEditorWidgets::DragVec3 SHEditorWidgets::DragVec3
( (
"Half Extents", { "X", "Y", "Z" }, "Half Extents", { "X", "Y", "Z" },
[box, transformComponent] { return (box->GetHalfExtents() * 2.0f) / transformComponent->GetWorldScale(); }, [box] { return box->GetRelativeExtents(); },
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
} }
else if (collider->GetType() == SHCollider::Type::SPHERE) else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape()); auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
SHEditorWidgets::DragFloat SHEditorWidgets::DragFloat
( (
"Radius", "Radius",
[sphere, transformComponent] [sphere] { return sphere->GetRelativeRadius(); },
{
const SHVec3& TF_WORLD_SCALE = transformComponent->GetWorldScale();
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
return (sphere->GetRadius() / MAX_SCALE) * 2.0f;
},
[collider](float const& value) { collider->SetBoundingSphere(value); }); [collider](float const& value) { collider->SetBoundingSphere(value); });
} }
else if (collider->GetType() == SHCollider::Type::CAPSULE) else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
{ {
} }

View File

@ -93,13 +93,14 @@ namespace SHADE
{ {
EntityID const& eid = editor->selectedEntities[0]; EntityID const& eid = editor->selectedEntities[0];
SHEntity* entity = SHEntityManager::GetEntityByID(eid); SHEntity* entity = SHEntityManager::GetEntityByID(eid);
if(!entity) SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
if(!entity || !entityNode)
{ {
ImGui::End(); ImGui::End();
return; return;
} }
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid); ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); }); SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputText("##EntityName", &entity->name); ImGui::InputText("##EntityName", &entity->name);

View File

@ -24,6 +24,9 @@
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include "Serialization/Configurations/SHConfigurationManager.h" #include "Serialization/Configurations/SHConfigurationManager.h"
const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" };
namespace SHADE namespace SHADE
{ {
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
@ -43,8 +46,7 @@ namespace SHADE
void SHEditorMenuBar::Init() void SHEditorMenuBar::Init()
{ {
SHEditorWindow::Init(); SHEditorWindow::Init();
constexpr std::string_view path = "../../Assets/Editor/Layouts"; for(auto const& entry : std::filesystem::directory_iterator(LAYOUT_FOLDER_PATH))
for(auto const& entry : std::filesystem::directory_iterator(path))
{ {
layoutPaths.push_back(entry.path()); layoutPaths.push_back(entry.path());
} }
@ -117,16 +119,22 @@ namespace SHADE
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile(); scriptEngine->GenerateScriptsCsProjFile();
} }
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
if (ImGui::Selectable("Build Scripts - Debug")) if (ImGui::Selectable("Build Scripts - Debug"))
{ {
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(true, true); scriptEngine->BuildScriptAssembly(true, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
} }
if (ImGui::Selectable("Build Scripts - Release")) if (ImGui::Selectable("Build Scripts - Release"))
{ {
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->BuildScriptAssembly(false, true); SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(false, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
} }
ImGui::EndDisabled();
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -215,39 +223,20 @@ namespace SHADE
{ {
if(editor->SaveScene()) if(editor->SaveScene())
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT editor->Play();
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PLAY;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
} }
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE)) if(ImGui::SmallButton(ICON_MD_PAUSE))
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT editor->Pause();
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::PAUSE;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP); ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
if(ImGui::SmallButton(ICON_MD_STOP)) if(ImGui::SmallButton(ICON_MD_STOP))
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT editor->Stop();
{
.previousState = editor->editorState
};
editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenuBar(); ImGui::EndMenuBar();

View File

@ -40,6 +40,7 @@ namespace SHADE
shouldUpdateCamera = false; shouldUpdateCamera = false;
} }
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
if (Begin()) if (Begin())
{ {
@ -51,7 +52,6 @@ namespace SHADE
beginCursorPos = ImGui::GetCursorScreenPos(); beginCursorPos = ImGui::GetCursorScreenPos();
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y }; viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos); gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y }); ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right)) if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
@ -64,24 +64,25 @@ namespace SHADE
shouldUpdateCamera = true; shouldUpdateCamera = true;
} }
if (ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) if (editor->editorState != SHEditor::State::PLAY && ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
{ {
if (ImGui::IsKeyReleased(ImGuiKey_Q)) if (ImGui::IsKeyReleased(ImGuiKey_W))
{ {
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE; transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
} }
if (ImGui::IsKeyReleased(ImGuiKey_W)) if (ImGui::IsKeyReleased(ImGuiKey_E))
{ {
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE; transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
} }
if (ImGui::IsKeyReleased(ImGuiKey_E)) if (ImGui::IsKeyReleased(ImGuiKey_R))
{ {
transformGizmo.operation = SHTransformGizmo::Operation::SCALE; transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
} }
} }
} }
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y); ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
transformGizmo.Draw(); if(editor->editorState != SHEditor::State::PLAY)
transformGizmo.Draw();
ImGui::End(); ImGui::End();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} }

View File

@ -65,6 +65,10 @@ RTTR_REGISTRATION
); );
} }
const std::string USER_LAYOUT_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts/UserLayout.ini" };
const std::string DEFAULT_LAYOUT_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts/Default.ini" };
const std::string FONT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Fonts/"};
namespace SHADE namespace SHADE
{ {
@ -106,7 +110,7 @@ namespace SHADE
io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //Enable for Multi-Viewports
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
io->IniFilename = "../../Assets/Editor/Layouts/UserLayout.ini"; io->IniFilename = USER_LAYOUT_PATH.data();
io->ConfigWindowsMoveFromTitleBarOnly = true; io->ConfigWindowsMoveFromTitleBarOnly = true;
InitLayout(); InitLayout();
@ -164,7 +168,19 @@ namespace SHADE
{ {
SHCommandManager::UndoCommand(); SHCommandManager::UndoCommand();
} }
if(ImGui::IsKeyReleased(ImGuiKey_F5))
{
Play();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
{
Pause();
}
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
{
Stop();
}
Render(); Render();
} }
@ -236,20 +252,20 @@ namespace SHADE
{ {
if(!std::filesystem::exists(io->IniFilename)) if(!std::filesystem::exists(io->IniFilename))
{ {
std::filesystem::copy_file("../../Assets/Editor/Layouts/Default.ini", io->IniFilename); std::filesystem::copy_file(DEFAULT_LAYOUT_PATH.data(), io->IniFilename);
} }
//eventually load preferred layout here //eventually load preferred layout here
} }
void SHEditor::InitFonts() noexcept void SHEditor::InitFonts() noexcept
{ {
ImFont* mainFont = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/Segoe UI.ttf", 20.f);//TODO: Change to config based assets path ImFont* mainFont = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "Segoe UI.ttf").data(), 20.f);//TODO: Change to config based assets path
ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f; ImFontConfig icons_config{}; icons_config.MergeMode = true; icons_config.GlyphOffset.y = 5.f;
constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; constexpr ImWchar icon_ranges_fa[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/fa-solid-900.ttf", 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path ImFont* UIFontFA = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "fa-solid-900.ttf").data(), 20.f, &icons_config, icon_ranges_fa); //TODO: Change to config based assets path
constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 }; constexpr ImWchar icon_ranges_md[] = { ICON_MIN_MD, ICON_MAX_16_MD, 0 };
ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF("../../Assets/Editor/Fonts/MaterialIcons-Regular.ttf", 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path ImFont* UIFontMD = io->Fonts->AddFontFromFileTTF(std::string(FONT_FOLDER_PATH + "MaterialIcons-Regular.ttf").data(), 20.f, &icons_config, icon_ranges_md); //TODO: Change to config based assets path
io->Fonts->Build(); io->Fonts->Build();
} }
@ -501,9 +517,12 @@ namespace SHADE
ImGui_ImplVulkan_DestroyFontUploadObjects(); ImGui_ImplVulkan_DestroyFontUploadObjects();
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) { renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd)
{
cmd->BeginLabeledSegment("ImGui Draw");
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer()); ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
}); cmd->EndLabeledSegment();
});
#endif #endif
} }
@ -590,6 +609,48 @@ namespace SHADE
} }
} }
void SHEditor::Play()
{
if(editorState == State::PLAY)
return;
if (SaveScene())
{
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editorState
};
editorState = State::PLAY;
SHCommandManager::SwapStacks();
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
}
}
void SHEditor::Pause()
{
if (editorState == State::PAUSE)
return;
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editorState
};
editorState = State::PAUSE;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
}
void SHEditor::Stop()
{
if (editorState == State::STOP)
return;
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{
.previousState = editorState
};
editorState = SHEditor::State::STOP;
SHCommandManager::SwapStacks();
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
}
void SHEditor::NewFrame() void SHEditor::NewFrame()
{ {
SDL_Event event; SDL_Event event;

View File

@ -184,6 +184,10 @@ namespace SHADE
void LoadScene(AssetID const& assetID) noexcept; void LoadScene(AssetID const& assetID) noexcept;
void Play();
void Pause();
void Stop();
// List of selected entities // List of selected entities
std::vector<EntityID> selectedEntities; std::vector<EntityID> selectedEntities;

View File

@ -288,7 +288,7 @@ namespace SHADE
return CHANGED; return CHANGED;
} }
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered) bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered, bool alwaysNull)
{ {
ImGui::Text(label.c_str()); ImGui::Text(label.c_str());
if (isHovered) if (isHovered)
@ -296,7 +296,7 @@ namespace SHADE
ImGui::SameLine(); ImGui::SameLine();
SHEntity* entity = SHEntityManager::GetEntityByID(value); SHEntity* entity = SHEntityManager::GetEntityByID(value);
std::ostringstream oss; std::ostringstream oss;
if (entity) if (!alwaysNull && entity)
{ {
oss << value << ": " << entity->name; oss << value << ": " << entity->name;
} }
@ -314,6 +314,13 @@ namespace SHADE
SHDragDrop::EndTarget(); SHDragDrop::EndTarget();
} }
} }
ImGui::SameLine();
if (ImGui::Button("Clear"))
{
value = MAX_EID;
changed = true;
}
return changed; return changed;
} }

View File

@ -313,8 +313,12 @@ namespace SHADE
/// <param name="label">Label used to identify this widget.</param> /// <param name="label">Label used to identify this widget.</param>
/// <param name="value">Reference to the variable to store the result.</param> /// <param name="value">Reference to the variable to store the result.</param>
/// <param name="isHovered>If set, stores the hover state of this widget.</param> /// <param name="isHovered>If set, stores the hover state of this widget.</param>
/// <param name="alwaysNull>
/// If set, the field displayed will always be blank regardless of specified
/// GameObject.
/// </param>
/// <returns>True if the value was changed.</returns> /// <returns>True if the value was changed.</returns>
static bool InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered = nullptr); static bool InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered = nullptr, bool alwaysNull = false);
/// <summary> /// <summary>
/// Creates a combo box for enumeration input. /// Creates a combo box for enumeration input.
/// </summary> /// </summary>

View File

@ -11,9 +11,11 @@ constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 }; constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 }; constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 6 }; constexpr SHEventIdentifier SH_SCENEGRAPH_ADD_CHILD_EVENT { 6 };
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 7 }; constexpr SHEventIdentifier SH_SCENEGRAPH_REMOVE_CHILD_EVENT { 7 };
constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 8 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_ADDED_EVENT { 8 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 9 }; constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_REMOVED_EVENT { 9 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 10 }; constexpr SHEventIdentifier SH_EDITOR_ON_PLAY_EVENT { 10 };
constexpr SHEventIdentifier SH_EDITOR_ON_PAUSE_EVENT { 11 };
constexpr SHEventIdentifier SH_EDITOR_ON_STOP_EVENT { 12 };

View File

@ -12,6 +12,7 @@
#include "SHFileSystem.h" #include "SHFileSystem.h"
#include <filesystem> #include <filesystem>
#include <queue> #include <queue>
#include <stack>
#include "Assets/SHAssetMetaHandler.h" #include "Assets/SHAssetMetaHandler.h"
@ -24,29 +25,77 @@ namespace SHADE
return true; return true;
} }
void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept bool SHFileSystem::IsCompilable(std::string ext) noexcept
{
for (auto const& external : EXTERNALS)
{
if (ext == external)
{
return true;
}
}
return false;
}
bool SHFileSystem::MatchExtention(FileExt raw, FileExt compiled) noexcept
{
if (raw == GLSL_EXTENSION)
{
if (compiled == SHADER_EXTENSION ||
compiled == SHADER_BUILT_IN_EXTENSION)
{
return true;
}
}
else if (raw == DDS_EXTENSION)
{
if (compiled == TEXTURE_EXTENSION)
{
return true;
}
}
else if (raw == FBX_EXTENSION)
{
if (compiled == MODEL_EXTENSION)
{
return true;
}
}
else if (raw == GLTF_EXTENSION)
{
if (compiled == MODEL_EXTENSION)
{
return true;
}
}
return false;
}
void SHFileSystem::BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept
{ {
std::queue<FolderPointer> folderQueue; std::stack<FolderPointer> folderStack;
root = new SHFolder("root"); root = new SHFolder("root");
root->path = path; root->path = path;
folderQueue.push(root); folderStack.push(root);
while (!folderQueue.empty()) while (!folderStack.empty())
{ {
auto const folder = folderQueue.front(); auto const folder = folderStack.top();
folderQueue.pop(); folderStack.pop();
std::vector<SHAsset> assets; std::vector<SHAsset> assets;
for (auto const& dirEntry : std::filesystem::directory_iterator(folder->path)) // Get all subfolders/files in this current folder
for (auto& dirEntry : std::filesystem::directory_iterator(folder->path))
{ {
auto const& path = dirEntry.path(); auto path = dirEntry.path();
path.make_preferred();
if (!dirEntry.is_directory()) if (!dirEntry.is_directory())
{ {
if (path.extension().string() == META_EXTENSION) if (path.extension().string() == META_EXTENSION)
{ {
//auto asset = SHAssetMetaHandler::RetrieveMetaData(path);
//assetCollection.insert({ asset.id, asset });
assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path)); assets.push_back(SHAssetMetaHandler::RetrieveMetaData(path));
} }
else else
@ -55,14 +104,17 @@ namespace SHADE
path.stem().string(), path.stem().string(),
path.string(), path.string(),
path.extension().string(), path.extension().string(),
nullptr nullptr,
IsCompilable(path.extension().string()),
false
); );
} }
continue; continue;
} }
// If item is folder
auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) }; auto newFolder{ folder->CreateSubFolderHere(path.stem().string()) };
folderQueue.push(newFolder); folderStack.push(newFolder);
} }
for (auto const& asset : assets) for (auto const& asset : assets)
@ -72,11 +124,58 @@ namespace SHADE
{ {
if (file.name == asset.name) if (file.name == asset.name)
{ {
file.assetMeta = &assetCollection[asset.id]; AssetPath path{ file.path };
break; if (SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()) == asset.type)
{
file.assetMeta = &assetCollection[asset.id];
break;
}
}
}
}
for (auto i {0}; i < folder->files.size(); ++i)
{
auto& file = folder->files[i];
if (file.compilable)
{
for (auto j{ 0 }; j < folder->files.size(); ++j)
{
auto& check = folder->files[j];
if (i == j || check.compilable)
{
continue;
}
if (file.name == check.name)
{
if (MatchExtention(file.ext, check.ext))
{
file.compiled = true;
}
}
} }
} }
} }
} }
} }
void SHFileSystem::DestroyDirectory(FolderPointer root) noexcept
{
std::stack<FolderPointer> folderStack;
folderStack.push(root);
while(!folderStack.empty())
{
auto const folder = folderStack.top();
folderStack.pop();
for (auto const& ptr : folder->subFolders)
{
folderStack.push(ptr);
}
delete folder;
}
}
} }

View File

@ -20,9 +20,10 @@ namespace SHADE
{ {
public: public:
static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept; static void BuildDirectory(FolderPath path, FolderPointer& root, std::unordered_map<AssetID, SHAsset>& assetCollection) noexcept;
static void DestroyDirectory(FolderPointer root) noexcept;
private: private:
static bool DeleteFolder(FolderPointer location) noexcept; static bool DeleteFolder(FolderPointer location) noexcept;
static bool IsCompilable(std::string ext) noexcept;
static bool MatchExtention(FileExt raw, FileExt compiled) noexcept;
}; };
} }

View File

@ -33,6 +33,8 @@ namespace SHADE
FilePath path; FilePath path;
FileExt ext; FileExt ext;
SHAsset const* assetMeta; SHAsset const* assetMeta;
bool compilable;
bool compiled;
}; };
class SHFolder class SHFolder

View File

@ -217,9 +217,11 @@ namespace SHADE
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use RenderDoc to check buffer variables?) &bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use RenderDoc to check buffer variables?)
&allocCreateInfo, &allocCreateInfo,
&tempBuffer, &stagingAlloc, &allocInfo); &tempBuffer, &stagingAlloc, &allocInfo);
SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eDeviceMemory, allocInfo.deviceMemory, "[Memory] Staging - " + name);
// then assign it to the hpp version // then assign it to the hpp version
stagingBuffer = tempBuffer; stagingBuffer = tempBuffer;
SET_VK_OBJ_NAME(device, vk::ObjectType::eBuffer, stagingBuffer, "[Buffer] Staging - " + name);
// Just map, copy then unmap // Just map, copy then unmap
void* stagingBufferMappedPtr = nullptr; void* stagingBufferMappedPtr = nullptr;
@ -251,7 +253,11 @@ namespace SHADE
auto result = vmaCreateBuffer(vmaAllocator, auto result = vmaCreateBuffer(vmaAllocator,
&bufferCreateInfo.operator VkBufferCreateInfo & (), &bufferCreateInfo.operator VkBufferCreateInfo & (),
&allocCreateInfo, &allocCreateInfo,
&tempBuffer, &alloc, &allocInfo); &tempBuffer, &alloc, &allocInfo);
#ifdef _DEBUG
if (!name.empty())
SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eDeviceMemory, allocInfo.deviceMemory, "[Memory] " + name);
#endif
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan buffer. "); SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan buffer. ");
@ -269,7 +275,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkBuffer::SHVkBuffer(std::reference_wrapper<VmaAllocator const> allocator) noexcept SHVkBuffer::SHVkBuffer(Handle<SHVkLogicalDevice> logicalDevice, std::reference_wrapper<VmaAllocator const> allocator) noexcept
: vkBuffer{} : vkBuffer{}
, stagingBuffer{} , stagingBuffer{}
, sizeStored{ 0 } , sizeStored{ 0 }
@ -277,19 +283,23 @@ namespace SHADE
, alloc {nullptr} , alloc {nullptr}
, randomAccessOptimized{false} , randomAccessOptimized{false}
, vmaAllocator{allocator} , vmaAllocator{allocator}
, device { logicalDevice }
{} {}
SHVkBuffer::SHVkBuffer( SHVkBuffer::SHVkBuffer(
Handle<SHVkLogicalDevice> logicalDevice,
uint32_t inSize, uint32_t inSize,
void* data, void* data,
uint32_t srcSize, uint32_t srcSize,
std::reference_wrapper<VmaAllocator const> allocator, std::reference_wrapper<VmaAllocator const> allocator,
vk::BufferUsageFlags bufferUsage, vk::BufferUsageFlags bufferUsage,
const std::string& name,
VmaMemoryUsage memUsage, VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags VmaAllocationCreateFlags allocFlags
) noexcept ) noexcept
: SHVkBuffer(allocator) : SHVkBuffer(logicalDevice, allocator)
{ {
this->name = name;
Init(inSize, data, srcSize, bufferUsage, memUsage, allocFlags); Init(inSize, data, srcSize, bufferUsage, memUsage, allocFlags);
} }
@ -304,6 +314,8 @@ namespace SHADE
, bufferUsageFlags {rhs.bufferUsageFlags} , bufferUsageFlags {rhs.bufferUsageFlags}
, bufferCreateInfo { rhs.bufferCreateInfo } , bufferCreateInfo { rhs.bufferCreateInfo }
, allocCreateInfo { rhs.allocCreateInfo } , allocCreateInfo { rhs.allocCreateInfo }
, name { std::move(rhs.name) }
, device { rhs.device }
{ {
rhs.vkBuffer = VK_NULL_HANDLE; rhs.vkBuffer = VK_NULL_HANDLE;
@ -325,6 +337,8 @@ namespace SHADE
bufferCreateInfo = rhs.bufferCreateInfo; bufferCreateInfo = rhs.bufferCreateInfo;
allocCreateInfo = rhs.allocCreateInfo; allocCreateInfo = rhs.allocCreateInfo;
bufferUsageFlags = rhs.bufferUsageFlags; bufferUsageFlags = rhs.bufferUsageFlags;
name = std::move(rhs.name);
device = rhs.device;
return *this; return *this;
} }
@ -402,6 +416,8 @@ namespace SHADE
auto [tempBuffer, allocInfo] = createBuffer(sizeStored); auto [tempBuffer, allocInfo] = createBuffer(sizeStored);
vkBuffer = tempBuffer; vkBuffer = tempBuffer;
if (!name.empty())
SET_VK_OBJ_NAME(device, vk::ObjectType::eBuffer, vkBuffer, "[Buffer] " + name);
// This probably means that a HOST_CACHED memory type is used on allocation // This probably means that a HOST_CACHED memory type is used on allocation
if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)

View File

@ -12,6 +12,7 @@ namespace SHADE
//using SHVkBufferUsageBits = vk::BufferUsageFlagBits; //using SHVkBufferUsageBits = vk::BufferUsageFlagBits;
class SHVkCommandBuffer; class SHVkCommandBuffer;
class SHVkLogicalDevice;
class SHVkBuffer class SHVkBuffer
{ {
@ -51,6 +52,11 @@ namespace SHADE
//VmaAllocator const& vmaAllocator; //VmaAllocator const& vmaAllocator;
std::reference_wrapper<VmaAllocator const> vmaAllocator; std::reference_wrapper<VmaAllocator const> vmaAllocator;
//! Name of this buffer if any
std::string name;
//! Handle to the logical device that created this buffer
Handle<SHVkLogicalDevice> device;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -62,13 +68,15 @@ namespace SHADE
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHVkBuffer (void) noexcept = delete; SHVkBuffer (void) noexcept = delete;
SHVkBuffer (std::reference_wrapper<VmaAllocator const> allocator) noexcept; SHVkBuffer (Handle<SHVkLogicalDevice> logicalDevice, std::reference_wrapper<VmaAllocator const> allocator) noexcept;
SHVkBuffer ( SHVkBuffer (
Handle<SHVkLogicalDevice> logicalDevice,
uint32_t inSize, uint32_t inSize,
void* data, void* data,
uint32_t srcSize, uint32_t srcSize,
std::reference_wrapper<VmaAllocator const> allocator, std::reference_wrapper<VmaAllocator const> allocator,
vk::BufferUsageFlags bufferUsage, vk::BufferUsageFlags bufferUsage,
const std::string& name = "",
VmaMemoryUsage memUsage = VMA_MEMORY_USAGE_AUTO, VmaMemoryUsage memUsage = VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlags allocFlags = {} VmaAllocationCreateFlags allocFlags = {}
) noexcept; ) noexcept;
@ -84,7 +92,7 @@ namespace SHADE
uint32_t inSize, uint32_t inSize,
void* data, void* data,
uint32_t srcSize, uint32_t srcSize,
vk::BufferUsageFlags bufferUsage, vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage, VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags VmaAllocationCreateFlags allocFlags
) noexcept; ) noexcept;

View File

@ -105,6 +105,9 @@ namespace SHADE
// Set the state to recording if the call above succeeded. // Set the state to recording if the call above succeeded.
cmdBufferState = SH_CMD_BUFFER_STATE::RECORDING; cmdBufferState = SH_CMD_BUFFER_STATE::RECORDING;
// Reset segment count
segmentDepth = 0;
} }
/***************************************************************************/ /***************************************************************************/
@ -507,6 +510,41 @@ namespace SHADE
SetState(SH_CMD_BUFFER_STATE::PENDING); SetState(SH_CMD_BUFFER_STATE::PENDING);
} }
void SHVkCommandBuffer::BeginLabeledSegment(const std::string& label) noexcept
{
#ifdef _DEBUG
static const std::array SEGMENT_COLOURS =
{
SHColour::LIGHTPINK,
SHColour::LIGHTBLUE,
SHColour::LIGHTGREEN,
SHColour::YELLOW,
SHColour::PINK,
SHColour::TEAL,
SHColour::LIME,
SHColour::ORANGE,
SHColour::VIOLET,
SHColour::MAROON,
SHColour::DARKGREEN,
SHColour::SANDYBROWN
};
const SHColour COLOR = SEGMENT_COLOURS[segmentDepth];
++segmentDepth;
if (segmentDepth >= static_cast<int>(SEGMENT_COLOURS.size()))
segmentDepth = 0;
vkCommandBuffer.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT().setPLabelName(label.data()).setColor({ COLOR.x, COLOR.y, COLOR.z, COLOR.w }));
#endif
}
void SHVkCommandBuffer::EndLabeledSegment() noexcept
{
#ifdef _DEBUG
vkCommandBuffer.endDebugUtilsLabelEXT();
segmentDepth = std::max(segmentDepth - 1, 0);
#endif
}
//void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept //void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept
//{ //{
// //vkCommandBuffer.pipelineBarrier() // //vkCommandBuffer.pipelineBarrier()

View File

@ -7,6 +7,7 @@
#include "Resource/SHResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Pipeline/SHPipelineType.h" #include "Graphics/Pipeline/SHPipelineType.h"
#include "Math/SHColour.h"
namespace SHADE namespace SHADE
{ {
@ -78,7 +79,10 @@ namespace SHADE
std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData; std::array<PipelineBindPointData, static_cast<uint32_t>(SH_PIPELINE_TYPE::NUM_TYPES)> bindPointData;
//! The push constant data for the command buffer //! The push constant data for the command buffer
uint8_t pushConstantData[PUSH_CONSTANT_SIZE]; uint8_t pushConstantData[PUSH_CONSTANT_SIZE];
//! Depth of segmenting of the command buffer (used for debug data)
int segmentDepth;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
@ -107,7 +111,7 @@ namespace SHADE
void Reset(void); void Reset(void);
// Begins and Ends // Begins and Ends
void BeginRecording (void) noexcept; void BeginRecording () noexcept;
void EndRecording (void) noexcept; void EndRecording (void) noexcept;
void BeginRenderpass (Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept; void BeginRenderpass (Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept;
void EndRenderpass (void) noexcept; void EndRenderpass (void) noexcept;
@ -148,6 +152,10 @@ namespace SHADE
bool IsReadyToSubmit (void) const noexcept; bool IsReadyToSubmit (void) const noexcept;
void HandlePostSubmit (void) noexcept; void HandlePostSubmit (void) noexcept;
// Debugging
void BeginLabeledSegment(const std::string& label) noexcept;
void EndLabeledSegment() noexcept;
// Push Constant variable setting // Push Constant variable setting
template <typename T> template <typename T>
void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept void SetPushConstantVariable(std::string variableName, T const& data, SH_PIPELINE_TYPE bindPoint) noexcept

View File

@ -220,6 +220,7 @@ namespace SHADE
else else
{ {
SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Logical Device. "); SHVulkanDebugUtil::ReportVkSuccess("Successfully created a Logical Device. ");
SET_VK_OBJ_NAME(this, vk::ObjectType::eDevice, vkLogicalDevice, "Logical Device");
} }
InitializeVMA(); InitializeVMA();
@ -419,9 +420,9 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHVkBuffer> SHVkLogicalDevice::CreateBuffer(uint32_t inSize, void* data, uint32_t srcSize, vk::BufferUsageFlags bufferUsage, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) const noexcept Handle<SHVkBuffer> SHVkLogicalDevice::CreateBuffer(uint32_t inSize, void* data, uint32_t srcSize, vk::BufferUsageFlags bufferUsage, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags, const std::string& name) const noexcept
{ {
return SHVkInstance::GetResourceManager().Create<SHVkBuffer>(inSize, data, srcSize, std::cref(vmaAllocator), bufferUsage, memUsage, allocFlags); return SHVkInstance::GetResourceManager().Create<SHVkBuffer>(GetHandle(), inSize, data, srcSize, std::cref(vmaAllocator), bufferUsage, name, memUsage, allocFlags);
} }
/***************************************************************************/ /***************************************************************************/
@ -455,12 +456,12 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
Handle<SHVkImage> SHVkLogicalDevice::CreateImage(uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) const noexcept Handle<SHVkImage> SHVkLogicalDevice::CreateImage(uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) const noexcept
{ {
return SHVkInstance::GetResourceManager().Create<SHVkImage>(&vmaAllocator, w, h, levels, format, usage, create); return SHVkInstance::GetResourceManager().Create<SHVkImage>(GetHandle(), &vmaAllocator, w, h, levels, format, usage, create);
} }
Handle<SHVkImage> SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::span<uint32_t> inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept Handle<SHVkImage> SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::span<uint32_t> inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept
{ {
return SHVkInstance::GetResourceManager().Create<SHVkImage>(&vmaAllocator, imageDetails, data, dataSize, inMipOffsets, memUsage, allocFlags); return SHVkInstance::GetResourceManager().Create<SHVkImage>(GetHandle(), &vmaAllocator, imageDetails, data, dataSize, inMipOffsets, memUsage, allocFlags);
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -1,5 +1,4 @@
#ifndef SH_LOGICAL_DEVICE_H #pragma once
#define SH_LOGICAL_DEVICE_H
#include <optional> #include <optional>
#include <array> #include <array>
@ -67,7 +66,6 @@ namespace SHADE
class SHVkLogicalDevice : public ISelfHandle<SHVkLogicalDevice> class SHVkLogicalDevice : public ISelfHandle<SHVkLogicalDevice>
{ {
private: private:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -147,7 +145,8 @@ namespace SHADE
uint32_t srcSize, uint32_t srcSize,
vk::BufferUsageFlags bufferUsage, vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage, VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags VmaAllocationCreateFlags allocFlags,
const std::string& name = ""
) const noexcept; ) const noexcept;
Handle<SHVkImage> CreateImage ( Handle<SHVkImage> CreateImage (
@ -202,7 +201,33 @@ namespace SHADE
Handle<SHVkSemaphore> CreateSemaphore (void) const noexcept; Handle<SHVkSemaphore> CreateSemaphore (void) const noexcept;
void UpdateDescriptorSets(std::vector<vk::WriteDescriptorSet> const& writeDescSets) noexcept; void UpdateDescriptorSets(std::vector<vk::WriteDescriptorSet> const& writeDescSets) noexcept;
void UpdateDescriptorSet (vk::WriteDescriptorSet const& writeDescSet) noexcept; void UpdateDescriptorSet(vk::WriteDescriptorSet const& writeDescSet) noexcept;
/*-----------------------------------------------------------------------*/
/* Debug Tools */
/*-----------------------------------------------------------------------*/
#ifdef _DEBUG
/// <summary>
/// Sets a Vulkan HPP object's name for debugging purposes. This function will not be
/// compiled outside of Debug configurations. Hence, it is advised to use provided
/// macro function SET_VK_OBJ_NAME() instead of using this function directly.
/// </summary>
/// <param name="objType">Type of the object.</param>
/// <param name="objHandle">Handle to the Vulkan Object to name.</param>
/// <param name="objName">Object's name.</param>
template<typename T>
inline void SetVulkanObjectName(vk::ObjectType objType, T objHandle, const std::string& objName);
/// <summary>
/// Sets a Vulkan object's name for debugging purposes. This function will not be
/// compiled outside of Debug configurations. Hence, it is advised to use provided
/// macro function SET_VK_OBJ_NAME_VK() instead of using this function directly.
/// </summary>
/// <param name="objType">Type of the object.</param>
/// <param name="objHandle">Handle to the Vulkan Object to name.</param>
/// <param name="objName">Object's name.</param>
template<typename T>
inline void SetVulkanObjectNameVk(vk::ObjectType objType, T objVkHandle, const std::string& objName);
#endif
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
@ -220,4 +245,4 @@ namespace SHADE
}; };
} }
#endif #include "SHVkLogicalDevice.hpp"

View File

@ -0,0 +1,61 @@
/************************************************************************************//*!
\file SHVkLogicalDevice.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 4, 2022
\brief Contains implementation of inline and template functions of
SHVkLogicalDevice.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
#include "SHVkLogicalDevice.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Debug Tools */
/*-----------------------------------------------------------------------------------*/
#ifdef _DEBUG
template<typename T>
void SHVkLogicalDevice::SetVulkanObjectName(vk::ObjectType objType, T objHandle, const std::string& objName)
{
if (objName.empty())
return;
vk::DebugUtilsObjectNameInfoEXT info;
info.objectType = objType;
info.objectHandle = (uint64_t) static_cast<typename T::NativeType>(objHandle);
info.pObjectName = objName.data();
vkLogicalDevice.setDebugUtilsObjectNameEXT(info);
}
template<typename T>
void SHVkLogicalDevice::SetVulkanObjectNameVk(vk::ObjectType objType, T objVkHandle, const std::string& objName)
{
if (objName.empty())
return;
vk::DebugUtilsObjectNameInfoEXT info;
info.objectType = objType;
info.objectHandle = (uint64_t) objVkHandle;
info.pObjectName = objName.data();
vkLogicalDevice.setDebugUtilsObjectNameEXT(info);
}
#endif
}
/*-------------------------------------------------------------------------------------*/
/* Macro Definitions */
/*-------------------------------------------------------------------------------------*/
#ifdef _DEBUG
#define SET_VK_OBJ_NAME(DEVICE, OBJ_TYPE, OBJ_HDL, OBJ_NAME) \
DEVICE->SetVulkanObjectName(OBJ_TYPE, OBJ_HDL, OBJ_NAME);
#define SET_VK_OBJ_NAME_VK(DEVICE, OBJ_TYPE, OBJ_HDL, OBJ_NAME) \
DEVICE->SetVulkanObjectNameVk(OBJ_TYPE, OBJ_HDL, OBJ_NAME);
#else
#define SET_VK_OBJ_NAME(DEVICE, OBJ_TYPE, OBJ_HDL, OBJ_NAME)
#define SET_VK_OBJ_NAME_VK(DEVICE, OBJ_TYPE, OBJ_HDL, OBJ_NAME)
#endif

View File

@ -61,6 +61,7 @@ namespace SHADE
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?) &bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?)
&allocCreateInfo, &allocCreateInfo,
&tempBuffer, &stagingAlloc, &allocInfo); &tempBuffer, &stagingAlloc, &allocInfo);
SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eDeviceMemory, allocInfo.deviceMemory, "[Memory] Staging Buffer for Image");
// then assign it to the hpp version // then assign it to the hpp version
stagingBuffer = tempBuffer; stagingBuffer = tempBuffer;
@ -107,6 +108,8 @@ namespace SHADE
VkImage tempImage; VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo); auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage; vkImage = tempImage;
//SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eImage, vkImage, "[Image] ");
SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eDeviceMemory, allocInfo.deviceMemory, "[Device Memory] Image Memory");
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. "); SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
@ -115,7 +118,8 @@ namespace SHADE
} }
SHVkImage::SHVkImage( SHVkImage::SHVkImage(
VmaAllocator const* allocator, Handle<SHVkLogicalDevice> logicalDeviceHdl,
VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
const unsigned char* data, const unsigned char* data,
uint32_t dataSize, uint32_t dataSize,
@ -137,6 +141,7 @@ namespace SHADE
, boundToCoherent{false} , boundToCoherent{false}
, randomAccessOptimized {false} , randomAccessOptimized {false}
, mappedPtr{nullptr} , mappedPtr{nullptr}
, device { logicalDeviceHdl }
{ {
usageFlags = imageDetails.usageFlags; usageFlags = imageDetails.usageFlags;
createFlags = imageDetails.createFlags; createFlags = imageDetails.createFlags;
@ -175,7 +180,9 @@ namespace SHADE
VmaAllocationInfo allocInfo{}; VmaAllocationInfo allocInfo{};
VkImage tempImage; VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo&(), &allocCreateInfo, &tempImage, &alloc, &allocInfo); auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
//SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eImage, vkImage, "[Image] ");
SET_VK_OBJ_NAME_VK(device, vk::ObjectType::eDeviceMemory, allocInfo.deviceMemory, "[Device Memory] Image Memory");
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. "); SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
@ -220,7 +227,7 @@ namespace SHADE
//} //}
} }
SHVkImage::SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept SHVkImage::SHVkImage(Handle<SHVkLogicalDevice> logicalDeviceHdl, VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept
: width {w} : width {w}
, height{h} , height{h}
, depth {1} , depth {1}
@ -230,11 +237,12 @@ namespace SHADE
, usageFlags{usage} , usageFlags{usage}
, createFlags {create} , createFlags {create}
, vmaAllocator {allocator} , vmaAllocator {allocator}
, device { logicalDeviceHdl }
{ {
CreateFramebufferImage(); CreateFramebufferImage();
} }
Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept
{ {
return SHVkInstance::GetResourceManager().Create<SHVkImageView>(inLogicalDeviceHdl, parent, createParams); return SHVkInstance::GetResourceManager().Create<SHVkImageView>(inLogicalDeviceHdl, parent, createParams);
} }

View File

@ -104,6 +104,9 @@ namespace SHADE
//! Mipmap offsets for initializing the vk::BufferImageCopy during transfer to GPU resource //! Mipmap offsets for initializing the vk::BufferImageCopy during transfer to GPU resource
std::span<uint32_t> mipOffsets; std::span<uint32_t> mipOffsets;
//! Handle to the device that creates these images
Handle<SHVkLogicalDevice> device;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -117,6 +120,7 @@ namespace SHADE
SHVkImage(void) noexcept = default; SHVkImage(void) noexcept = default;
SHVkImage( SHVkImage(
Handle<SHVkLogicalDevice> logicalDeviceHdl,
VmaAllocator const* allocator, VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
const unsigned char* data, const unsigned char* data,
@ -126,7 +130,7 @@ namespace SHADE
VmaAllocationCreateFlags allocFlags VmaAllocationCreateFlags allocFlags
) noexcept; ) noexcept;
SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept; SHVkImage(Handle<SHVkLogicalDevice> logicalDeviceHdl, VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept;
SHVkImage(SHVkImage&& rhs) noexcept = default; SHVkImage(SHVkImage&& rhs) noexcept = default;
SHVkImage& operator=(SHVkImage && rhs) noexcept = default; SHVkImage& operator=(SHVkImage && rhs) noexcept = default;
@ -134,7 +138,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept; Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept; void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept; void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept;

View File

@ -392,20 +392,23 @@ namespace SHADE
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer BuffUsage::eIndirectBuffer,
"Batch Draw Data Buffer"
); );
// - Transform Buffer // - Transform Buffer
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)); const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Batch Transform Buffer"
); );
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)); const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES, device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Batch Instance Data Buffer"
); );
// - Material Properties Buffer // - Material Properties Buffer
rebuildMaterialBuffers(frameIndex, descPool); rebuildMaterialBuffers(frameIndex, descPool);
@ -427,6 +430,7 @@ namespace SHADE
// Bind all required objects before drawing // Bind all required objects before drawing
static std::array<uint32_t, 1> dynamicOffset{ 0 }; static std::array<uint32_t, 1> dynamicOffset{ 0 };
cmdBuffer->BeginLabeledSegment("SHBatch");
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
@ -441,6 +445,7 @@ namespace SHADE
); );
} }
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size())); cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
cmdBuffer->EndLabeledSegment();
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -460,7 +465,8 @@ namespace SHADE
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize), device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
vk::BufferUsageFlagBits::eStorageBuffer vk::BufferUsageFlagBits::eStorageBuffer,
"Batch Material Data"
); );
if (!matPropsDescSet[frameIndex]) if (!matPropsDescSet[frameIndex])
@ -470,6 +476,13 @@ namespace SHADE
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] }, { SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
{ 0 } { 0 }
); );
#ifdef _DEBUG
const auto& DESC_SETS = matPropsDescSet[frameIndex]->GetVkHandle();
for (auto descSet : DESC_SETS)
{
SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, descSet, "[Descriptor Set] Batch Material Data");
}
#endif
} }
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] }; std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer matPropsDescSet[frameIndex]->ModifyWriteDescBuffer

View File

@ -13,14 +13,13 @@ namespace SHADE
/* Static Definitions */ /* Static Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsGlobalData::globalDescSetLayouts; std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsGlobalData::globalDescSetLayouts;
Handle<SHVkDescriptorSetGroup> SHGraphicsGlobalData::globalDescSets;
SHVertexInputState SHGraphicsGlobalData::defaultVertexInputState; SHVertexInputState SHGraphicsGlobalData::defaultVertexInputState;
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::dummyPipelineLayout; Handle<SHVkPipelineLayout> SHGraphicsGlobalData::dummyPipelineLayout;
void SHGraphicsGlobalData::InitHighFrequencyGlobalData(void) noexcept void SHGraphicsGlobalData::InitHighFrequencyGlobalData(void) noexcept
{ {
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Function Definitions */ /* Function Definitions */
@ -45,7 +44,8 @@ namespace SHADE
}; };
// For global data (generic data and textures) // For global data (generic data and textures)
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding }); Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS, { genericDataBinding, texturesBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, staticGlobalLayout->GetVkHandle(), "[Descriptor Set Layout] Static Globals");
std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{}; std::vector<SHVkDescriptorSetLayout::Binding> lightBindings{};
@ -71,11 +71,11 @@ namespace SHADE
}); });
} }
// For Dynamic global data (lights) // For Dynamic global data (lights)
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings); Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings);
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, dynamicGlobalLayout->GetVkHandle(), "[Descriptor Set Layout] Dynamic Globals");
// For High frequency global data (camera)
SHVkDescriptorSetLayout::Binding cameraDataBinding SHVkDescriptorSetLayout::Binding cameraDataBinding
{ {
.Type = vk::DescriptorType::eUniformBufferDynamic, .Type = vk::DescriptorType::eUniformBufferDynamic,
@ -83,10 +83,10 @@ namespace SHADE
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };
// For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, { cameraDataBinding }); Handle<SHVkDescriptorSetLayout> cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, { cameraDataBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, cameraDataGlobalLayout->GetVkHandle(), "[Descriptor Set Layout] High Frequency Globals");
// For per instance data (transforms, materials, etc.)
SHVkDescriptorSetLayout::Binding materialDataBinding SHVkDescriptorSetLayout::Binding materialDataBinding
{ {
.Type = vk::DescriptorType::eStorageBufferDynamic, .Type = vk::DescriptorType::eStorageBufferDynamic,
@ -94,9 +94,8 @@ namespace SHADE
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };
// For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, { materialDataBinding }); Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, { materialDataBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material Globals");
globalDescSetLayouts.push_back(staticGlobalLayout); globalDescSetLayouts.push_back(staticGlobalLayout);
globalDescSetLayouts.push_back(dynamicGlobalLayout); globalDescSetLayouts.push_back(dynamicGlobalLayout);

View File

@ -17,9 +17,6 @@ namespace SHADE
//! Global descriptor set layouts. Used to allocate descriptor sets //! Global descriptor set layouts. Used to allocate descriptor sets
static std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts; static std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
//! Global Descriptor sets
static Handle<SHVkDescriptorSetGroup> globalDescSets;
//! Default vertex input state (used by everything). //! Default vertex input state (used by everything).
static SHVertexInputState defaultVertexInputState; static SHVertexInputState defaultVertexInputState;

View File

@ -98,6 +98,7 @@ namespace SHADE
// Don't draw if no points // Don't draw if no points
if (numPoints[FRAME_IDX] > 0) if (numPoints[FRAME_IDX] > 0)
{ {
cmdBuffer->BeginLabeledSegment("SHDebugDraw");
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline()); cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline());
cmdBuffer->SetLineWidth(LineWidth); cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0); cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0);
@ -113,10 +114,12 @@ namespace SHADE
// Don't draw if no points // Don't draw if no points
if (numPersistentPoints[FRAME_IDX] > 0) if (numPersistentPoints[FRAME_IDX] > 0)
{ {
cmdBuffer->BeginLabeledSegment("SHDebugDraw (Persistent)");
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawDepthPipeline()); cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawDepthPipeline());
cmdBuffer->SetLineWidth(LineWidth); cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, persistentVertexBuffers[FRAME_IDX], 0); cmdBuffer->BindVertexBuffer(0, persistentVertexBuffers[FRAME_IDX], 0);
cmdBuffer->DrawArrays(numPersistentPoints[FRAME_IDX], 1, 0, 0); cmdBuffer->DrawArrays(numPersistentPoints[FRAME_IDX], 1, 0, 0);
cmdBuffer->EndLabeledSegment();
} }
}); });
@ -138,7 +141,8 @@ namespace SHADE
0, 0,
vk::BufferUsageFlagBits::eVertexBuffer, vk::BufferUsageFlagBits::eVertexBuffer,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT,
"Debug Draw Non-Persistent Vertex Buffer"
); );
} }
// - Persistent Draws // - Persistent Draws
@ -151,7 +155,8 @@ namespace SHADE
0, 0,
vk::BufferUsageFlagBits::eVertexBuffer, vk::BufferUsageFlagBits::eVertexBuffer,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT,
"Debug Draw Persistent Vertex Buffer"
); );
} }
} }
@ -318,7 +323,7 @@ namespace SHADE
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere(); static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
for (const auto& idx : SPHERE.Indices) for (const auto& idx : SPHERE.Indices)
{ {
spherePoints.emplace_back(SPHERE.VertexPositions[idx]); spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius);
} }
} }
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end()); drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());

View File

@ -1,5 +1,5 @@
/************************************************************************************//*! /************************************************************************************//*!
\file SHGraphicsSystem.cpp \file SHGrphicsSystem.cpp
\author Tng Kah Wei, kahwei.tng, 390009620 \author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu \par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022 \date Aug 21, 2022
@ -41,6 +41,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h" #include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "../Meshes/SHPrimitiveGenerator.h"
namespace SHADE namespace SHADE
{ {
@ -164,7 +165,7 @@ namespace SHADE
/* SCENE RENDER GRAPH RESOURCES */ /* SCENE RENDER GRAPH RESOURCES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); worldRenderGraph->Init("World Render Graph", device, swapchain);
worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); //worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
@ -212,6 +213,7 @@ namespace SHADE
ssaoStorage = resourceManager.Create<SHSSAO>(); ssaoStorage = resourceManager.Create<SHSSAO>();
ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
SET_VK_OBJ_NAME(device, vk::ObjectType::eCommandBuffer, ssaoTransferCmdBuffer->GetVkCommandBuffer(), "[Command Buffer] SSAO Pass (Graphics)");
ssaoTransferCmdBuffer->BeginRecording(); ssaoTransferCmdBuffer->BeginRecording();
ssaoStorage->Init(device, ssaoTransferCmdBuffer); ssaoStorage->Init(device, ssaoTransferCmdBuffer);
@ -233,7 +235,7 @@ namespace SHADE
ssaoStorage->PrepareRotationVectorsVkData(device); ssaoStorage->PrepareRotationVectorsVkData(device);
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"}); Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute("SSAO", ssaoShader, { "Position", "Normals", "SSAO" });
auto ssaoDataBuffer = ssaoStorage->GetBuffer(); auto ssaoDataBuffer = ssaoStorage->GetBuffer();
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored()); ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored());
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout(); auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
@ -241,12 +243,12 @@ namespace SHADE
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1}); ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"}); Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute("SSAO Blur Step", ssaoBlurShader, {"SSAO", "SSAO Blur"});
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */ /* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" }); gBufferNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene"});
// Dummy Node // Dummy Node
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
@ -259,7 +261,6 @@ namespace SHADE
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */ /* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -269,20 +270,13 @@ namespace SHADE
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector()); worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// Create default materials
std::array<SHTexture::PixelChannel, 4> defaultTexture = { 255, 255, 255, 255 };
std::vector<uint32_t> mipOffsets{};
mipOffsets.push_back(0);
auto tex = AddTexture(4, defaultTexture.data(), 1, 1, SHTexture::TextureFormat::eR8G8B8A8Unorm, mipOffsets);
BuildTextures();
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
defaultMaterial->SetProperty("data.textureIndex", tex->TextureArrayIndex);
// Create debug draw pipeline // Create debug draw pipeline
debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass); debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipeline, debugDrawPipeline->GetVkPipeline(), "[Pipeline] Debug Draw");
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipelineLayout, debugDrawPipeline->GetPipelineLayout()->GetVkPipelineLayout(), "[Pipeline Layout] Debug Draw Pipeline Layout");
debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass); debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipeline, debugDrawDepthPipeline->GetVkPipeline(), "[Pipeline Layout] Debug Draw with Depth Test");
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipelineLayout, debugDrawDepthPipeline->GetPipelineLayout()->GetVkPipelineLayout(), "[Pipeline] Debug Draw with Depth Test Pipeline Layout");
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -321,7 +315,29 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>(); lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool); lightingSubSystem->Init(device, descPool);
}
void SHGraphicsSystem::InitBuiltInResources(void)
{
// Create default texture
std::array<SHTexture::PixelChannel, 4> defaultTextureData = { 255, 255, 255, 255 };
std::vector<uint32_t> mipOffsets{};
mipOffsets.push_back(0);
defaultTexture = AddTexture(4, defaultTextureData.data(), 1, 1, SHTexture::TextureFormat::eR8G8B8A8Unorm, mipOffsets);
BuildTextures();
// Create default meshes
primitiveMeshes[static_cast<int>(PrimitiveType::Cube)] = SHPrimitiveGenerator::Cube(meshLibrary);
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
BuildMeshBuffers();
// Create default materials
defaultMaterial = AddMaterial
(
defaultVertShader, defaultFragShader,
worldRenderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
);
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
} }
#ifdef SHEDITOR #ifdef SHEDITOR
@ -339,7 +355,7 @@ namespace SHADE
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i) for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0]; renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
editorRenderGraph->Init(device, swapchain); editorRenderGraph->Init("Editor Render Graph", device, swapchain);
editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second); editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
@ -364,8 +380,7 @@ namespace SHADE
InitBoilerplate(); InitBoilerplate();
InitMiddleEnd(); InitMiddleEnd();
InitSubsystems(); InitSubsystems();
InitBuiltInResources();
} }
void SHGraphicsSystem::Exit(void) void SHGraphicsSystem::Exit(void)
@ -667,6 +682,8 @@ namespace SHADE
auto renderGraphNode = subpass->GetParentNode(); auto renderGraphNode = subpass->GetParentNode();
auto pipeline = renderGraphNode->GetOrCreatePipeline(std::make_pair(vertShader, fragShader), subpass); auto pipeline = renderGraphNode->GetOrCreatePipeline(std::make_pair(vertShader, fragShader), subpass);
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipeline, pipeline->GetVkPipeline(), "[Pipeline] Custom Pipeline");
SET_VK_OBJ_NAME(device, vk::ObjectType::ePipelineLayout, pipeline->GetPipelineLayout()->GetVkPipelineLayout(), "[Pipeline] Custom Pipeline Layout");
mat->SetPipeline(pipeline); mat->SetPipeline(pipeline);
@ -690,7 +707,7 @@ namespace SHADE
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst) SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst)
{ {
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial()); return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
} }
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance) void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
@ -703,24 +720,37 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices) SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices)
{ {
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices); return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices);
} }
void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh) void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)
{ {
meshLibrary.RemoveMesh(mesh); meshLibrary.RemoveMesh(mesh);
} }
void SHGraphicsSystem::BuildMeshBuffers() void SHGraphicsSystem::BuildMeshBuffers()
{ {
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
device->WaitIdle(); SET_VK_OBJ_NAME(device, vk::ObjectType::eCommandBuffer, transferCmdBuffer->GetVkCommandBuffer(), "[Command Buffer] Mesh Buffer Building (Transfer)");
transferCmdBuffer->BeginRecording(); device->WaitIdle();
meshLibrary.BuildBuffers(device, transferCmdBuffer); transferCmdBuffer->BeginRecording();
transferCmdBuffer->EndRecording(); meshLibrary.BuildBuffers(device, transferCmdBuffer);
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer }); transferCmdBuffer->EndRecording();
device->WaitIdle(); graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
transferCmdBuffer.Free(); transferCmdBuffer = {}; device->WaitIdle();
transferCmdBuffer.Free(); transferCmdBuffer = {};
}
Handle<SHMesh> SHGraphicsSystem::GetMeshPrimitive(PrimitiveType type) const noexcept
{
switch (type)
{
case PrimitiveType::Cube:
case PrimitiveType::Sphere:
return primitiveMeshes[static_cast<int>(type)];
default:
return {};
}
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -728,14 +758,18 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset) Handle<SHTexture> SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset)
{ {
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) }); const int MIPS = texAsset.mipOffsets.size();
return texLibrary.Add(texAsset, sampler); auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(MIPS) });
SET_VK_OBJ_NAME(device, vk::ObjectType::eSampler, sampler->GetVkSampler(), "[Sampler] Mips " + std::to_string(MIPS));
return texLibrary.Add(texAsset, sampler);
} }
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets) SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
{ {
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) }); const int MIPS = mipOffsets.size();
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler); auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(MIPS) });
SET_VK_OBJ_NAME(device, vk::ObjectType::eSampler, sampler->GetVkSampler(), "[Sampler] Mips " + std::to_string(MIPS));
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
} }
void SHGraphicsSystem::RemoveTexture(Handle<SHTexture> tex) void SHGraphicsSystem::RemoveTexture(Handle<SHTexture> tex)
@ -746,6 +780,7 @@ namespace SHADE
void SHGraphicsSystem::BuildTextures() void SHGraphicsSystem::BuildTextures()
{ {
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
SET_VK_OBJ_NAME(device, vk::ObjectType::eCommandBuffer, graphicsTexCmdBuffer->GetVkCommandBuffer(), "[Command Buffer] Texture Building (Graphics)");
device->WaitIdle(); device->WaitIdle();
texLibrary.BuildTextures texLibrary.BuildTextures
( (
@ -809,7 +844,7 @@ namespace SHADE
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{ {
auto& renderables = SHComponentManager::GetDense<SHRenderable>(); auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables) for (auto& renderable : renderables)
{ {
if (!renderable.HasChanged()) if (!renderable.HasChanged())

View File

@ -58,6 +58,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Type of built-in primitive meshes that are available.
*/
/***********************************************************************************/
enum class PrimitiveType
{
Cube,
Sphere
};
static constexpr int MAX_PRIMITIVE_TYPES = 2;
/***********************************************************************************/ /***********************************************************************************/
/*! /*!
\brief \brief
@ -72,6 +85,7 @@ namespace SHADE
void InitSceneRenderGraph (void) noexcept; void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept; void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept; void InitSubsystems (void) noexcept;
void InitBuiltInResources (void);
#ifdef SHEDITOR #ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept; void InitEditorRenderGraph (void) noexcept;
@ -81,25 +95,25 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine class SH_API BeginRoutine final : public SHSystemRoutine
{ {
public: public:
BeginRoutine(); BeginRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API RenderRoutine final : public SHSystemRoutine class SH_API RenderRoutine final : public SHSystemRoutine
{ {
public: public:
RenderRoutine(); RenderRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API EndRoutine final : public SHSystemRoutine class SH_API EndRoutine final : public SHSystemRoutine
{ {
public: public:
EndRoutine(); EndRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{ {
public: public:
BatcherDispatcherRoutine(); BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final; virtual void Execute(double dt) noexcept override final;
}; };
@ -152,34 +166,34 @@ namespace SHADE
/*******************************************************************************/ /*******************************************************************************/
/*! /*!
\brief \brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU. meshes into the GPU.
\param vertexCount \param vertexCount
Number of vertices in this Mesh. Number of vertices in this Mesh.
\param positions \param positions
Pointer to the first in a contiguous array of SHMathVec3s that define vertex Pointer to the first in a contiguous array of SHMathVec3s that define vertex
positions. positions.
\param texCoords \param texCoords
Pointer to the first in a contiguous array of SHMathVec2s that define vertex Pointer to the first in a contiguous array of SHMathVec2s that define vertex
texture coordinates. texture coordinates.
\param tangents \param tangents
Pointer to the first in a contiguous array of SHMathVec3s that define vertex Pointer to the first in a contiguous array of SHMathVec3s that define vertex
tangents. tangents.
\param normals \param normals
Pointer to the first in a contiguous array of SHMathVec3s that define vertex Pointer to the first in a contiguous array of SHMathVec3s that define vertex
normals. normals.
\param indexCount \param indexCount
Number of indices in this mesh. Number of indices in this mesh.
\param indices \param indices
Pointer to the first in a contiguous array of uint32_ts that define mesh Pointer to the first in a contiguous array of uint32_ts that define mesh
indices. indices.
\return \return
Handle to the created Mesh. This is not valid to be used until a call to Handle to the created Mesh. This is not valid to be used until a call to
BuildBuffers(). BuildBuffers().
*/ */
/*******************************************************************************/ /*******************************************************************************/
@ -188,9 +202,9 @@ namespace SHADE
/*! /*!
\brief \brief
Removes a mesh from the MeshLibrary. But this does not mean that the meshes Removes a mesh from the MeshLibrary. But this does not mean that the meshes
have been removed yet. A call to "BuildBuffers()" is required to finalise all have been removed yet. A call to "BuildBuffers()" is required to finalise all
changes. changes.
\param mesh \param mesh
Handle to the mesh to remove. Handle to the mesh to remove.
@ -207,6 +221,21 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildMeshBuffers(); void BuildMeshBuffers();
/*******************************************************************************/
/*!
\brief
Retrieves the built-in mesh specified.
\param type
Type of built-in mesh to retrieve.
\returns
Handle to the mesh that was specfied. However, if an invalid type is specified,
a null Handle will be returned.
*/
/*******************************************************************************/
Handle<SHMesh> GetMeshPrimitive(PrimitiveType type) const noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Texture Registration Functions */ /* Texture Registration Functions */
@ -278,6 +307,18 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const; Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const;
/***************************************************************************/
/*!
*
\brief
Retrieves the handle to the default texture. A white 1x1 texture.
\returns
Handle to the default texture.
*/
/***************************************************************************/
Handle<SHTexture> GetDefaultTexture() const noexcept { return defaultTexture; }
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept; void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept; void HandleResize(void) noexcept;
@ -378,6 +419,13 @@ namespace SHADE
Handle<SHVkPipeline> debugDrawPipeline; Handle<SHVkPipeline> debugDrawPipeline;
Handle<SHVkPipeline> debugDrawDepthPipeline; Handle<SHVkPipeline> debugDrawDepthPipeline;
// Built-In Textures
Handle<SHTexture> defaultTexture;
// Built-In Meshes
std::array<Handle<SHMesh>, MAX_PRIMITIVE_TYPES> primitiveMeshes;
// Render Graphs
Handle<SHRenderGraph> worldRenderGraph; Handle<SHRenderGraph> worldRenderGraph;
// Sub systems // Sub systems

View File

@ -165,35 +165,40 @@ namespace SHADE
device, cmdBuffer, vertPosBuffer, device, cmdBuffer, vertPosBuffer,
vertPosStorage.data(), vertPosStorage.data(),
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition), static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition),
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Mesh Library Vertex Positions"
); );
SHVkUtil::EnsureBufferAndCopyData SHVkUtil::EnsureBufferAndCopyData
( (
device, cmdBuffer, vertTexCoordBuffer, device, cmdBuffer, vertTexCoordBuffer,
vertTexCoordStorage.data(), vertTexCoordStorage.data(),
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord), static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Mesh Library Vertex TexCoords"
); );
SHVkUtil::EnsureBufferAndCopyData SHVkUtil::EnsureBufferAndCopyData
( (
device, cmdBuffer, vertTangentBuffer, device, cmdBuffer, vertTangentBuffer,
vertTangentStorage.data(), vertTangentStorage.data(),
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent), static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Mesh Library Vertex Tangents"
); );
SHVkUtil::EnsureBufferAndCopyData SHVkUtil::EnsureBufferAndCopyData
( (
device, cmdBuffer, vertNormalBuffer, device, cmdBuffer, vertNormalBuffer,
vertNormalStorage.data(), vertNormalStorage.data(),
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal), static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer,
"Mesh Library Vertex Normals"
); );
SHVkUtil::EnsureBufferAndCopyData SHVkUtil::EnsureBufferAndCopyData
( (
device, cmdBuffer, indexBuffer, device, cmdBuffer, indexBuffer,
indexStorage.data(), indexStorage.data(),
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index), static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
BuffUsage::eIndexBuffer BuffUsage::eIndexBuffer,
"Mesh Library Indices"
); );
isDirty = false; isDirty = false;

View File

@ -76,7 +76,7 @@ namespace SHADE
uint32_t bufferSize = entityIDAttachment->GetWidth() * entityIDAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat()); uint32_t bufferSize = entityIDAttachment->GetWidth() * entityIDAttachment->GetHeight() * SHVkUtil::GetBytesPerPixelFromFormat(entityIDAttachment->GetResourceFormat());
// Create the buffer // Create the buffer
imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); imageDataDstBuffer = logicalDevice->CreateBuffer(bufferSize, nullptr, bufferSize, vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, "Mouse Pick Image Data Destination");
} }
void SHMousePickSystem::SetViewportMousePos(SHVec2 vpMousePos) noexcept void SHMousePickSystem::SetViewportMousePos(SHVec2 vpMousePos) noexcept

View File

@ -39,9 +39,15 @@ namespace SHADE
cameraDescriptorSet = descriptorPool->Allocate({ cameraDescLayout }, { 1 }); cameraDescriptorSet = descriptorPool->Allocate({ cameraDescLayout }, { 1 });
#ifdef _DEBUG
const auto& CAM_DESC_SETS = cameraDescriptorSet->GetVkHandle();
for (int i = 0; i < static_cast<int>(CAM_DESC_SETS.size()); ++i)
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSet, CAM_DESC_SETS[i], "[Descriptor Set] Camera Data Frame #" + std::to_string(i));
#endif
cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData)); cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData));
cameraBuffer = logicalDevice->CreateBuffer(cameraDataAlignedSize * numFrames, nullptr, cameraDataAlignedSize * numFrames, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); cameraBuffer = logicalDevice->CreateBuffer(cameraDataAlignedSize * numFrames, nullptr, cameraDataAlignedSize * numFrames, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, "Camera Data");
std::array cameraBufferArray{cameraBuffer}; std::array cameraBufferArray{cameraBuffer};

View File

@ -134,7 +134,7 @@ namespace SHADE
lightDataTotalAlignedSize = logicalDevice->PadSSBOSize(lightDataAlignedSize * maxLights); lightDataTotalAlignedSize = logicalDevice->PadSSBOSize(lightDataAlignedSize * maxLights);
// We want to initialize 3 times the amount of data required. // We want to initialize 3 times the amount of data required.
dataBuffer = logicalDevice->CreateBuffer(lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); dataBuffer = logicalDevice->CreateBuffer(lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightDataTotalAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, "Light Data");
} }
else else
{ {
@ -385,8 +385,12 @@ namespace SHADE
std::fill (variableSizes.begin(), variableSizes.end(), 1); std::fill (variableSizes.begin(), variableSizes.end(), 1);
// Create the descriptor set // Create the descriptor set
lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes); lightingDataDescSet = descPool->Allocate({ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS] }, variableSizes);
#ifdef _DEBUG
const auto& CAM_DESC_SETS = lightingDataDescSet->GetVkHandle();
for (int i = 0; i < static_cast<int>(CAM_DESC_SETS.size()); ++i)
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSet, CAM_DESC_SETS[i], "[Descriptor Set] Light Data Frame #" + std::to_string(i));
#endif
for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i) for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i)
{ {
@ -402,7 +406,7 @@ namespace SHADE
lightCountsAlignedSize = logicalDevice->PadUBOSize(lightCountsAlignedSize); lightCountsAlignedSize = logicalDevice->PadUBOSize(lightCountsAlignedSize);
// Create the GPU buffer to hold light count // Create the GPU buffer to hold light count
lightCountsBuffer = logicalDevice->CreateBuffer(lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); lightCountsBuffer = logicalDevice->CreateBuffer(lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, lightCountsAlignedSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, "Light Count Data");
lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT, {&lightCountsBuffer, 1}, 0, sizeof (uint32_t) * NUM_LIGHT_TYPES); lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT, {&lightCountsBuffer, 1}, 0, sizeof (uint32_t) * NUM_LIGHT_TYPES);
lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT); lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::LIGHTING_COUNT);

View File

@ -26,7 +26,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHPerFrameData::Recreate(Handle<SHVkLogicalDevice> const& logicalDeviceHdl) noexcept void SHPerFrameData::Recreate(Handle<SHVkLogicalDevice> logicalDeviceHdl) noexcept
{ {
// Swapchain recreation means the images are just relinked to SHVkImages. Handles will remain the same. There is no need for this line. // Swapchain recreation means the images are just relinked to SHVkImages. Handles will remain the same. There is no need for this line.
//swapchainImageHdl = params.swapchainHdl->GetSwapchainImage(frameIndex); //swapchainImageHdl = params.swapchainHdl->GetSwapchainImage(frameIndex);
@ -44,14 +44,17 @@ namespace SHADE
// Create image views for the swapchain // Create image views for the swapchain
swapchainImageViewHdl = swapchainImageHdl->CreateImageView(logicalDeviceHdl, swapchainImageHdl, viewDetails); swapchainImageViewHdl = swapchainImageHdl->CreateImageView(logicalDeviceHdl, swapchainImageHdl, viewDetails);
SET_VK_OBJ_NAME(logicalDeviceHdl, vk::ObjectType::eImageView, swapchainImageViewHdl->GetImageView(), "[Image View] Swap Chain");
// Create a fence // Create a fence
fenceHdl = logicalDeviceHdl->CreateFence(); fenceHdl = logicalDeviceHdl->CreateFence();
SET_VK_OBJ_NAME(logicalDeviceHdl, vk::ObjectType::eFence, fenceHdl->GetVkFence(), "[Fence] Swap Chain");
// scope makes it easier to navigate // scope makes it easier to navigate
semImgAvailableHdl = logicalDeviceHdl->SHVkLogicalDevice::CreateSemaphore(); semImgAvailableHdl = logicalDeviceHdl->SHVkLogicalDevice::CreateSemaphore();
SET_VK_OBJ_NAME(logicalDeviceHdl, vk::ObjectType::eSemaphore, semImgAvailableHdl->GetVkSem(), "[Semaphore] Swap Chain Image Available");
semRenderFinishHdl = logicalDeviceHdl->SHVkLogicalDevice::CreateSemaphore(); semRenderFinishHdl = logicalDeviceHdl->SHVkLogicalDevice::CreateSemaphore();
SET_VK_OBJ_NAME(logicalDeviceHdl, vk::ObjectType::eSemaphore, semRenderFinishHdl->GetVkSem(), "[Semaphore] Swap Chain Render Finish");
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -63,7 +63,7 @@ namespace SHADE
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// These are made into functions (instead of ctor and dtor) because we want to call these functions again when we resize the window // These are made into functions (instead of ctor and dtor) because we want to call these functions again when we resize the window
void Recreate (Handle<SHVkLogicalDevice> const& logicalDeviceHdl) noexcept; void Recreate (Handle<SHVkLogicalDevice> logicalDeviceHdl) noexcept;
void Destroy (void); void Destroy (void);
friend class SHRenderContext; friend class SHRenderContext;

View File

@ -50,7 +50,13 @@ namespace SHADE
for (uint32_t j = 0; j < params.numThreads; ++j) for (uint32_t j = 0; j < params.numThreads; ++j)
{ {
frameData[i].cmdPoolHdls.push_back(logicalDeviceHdl->CreateCommandPool(params.cmdPoolQueueFamilyType, params.cmdPoolResetMode, params.cmdBufferTransient)); auto cmdPool = logicalDeviceHdl->CreateCommandPool(params.cmdPoolQueueFamilyType, params.cmdPoolResetMode, params.cmdBufferTransient);
SET_VK_OBJ_NAME
(
logicalDeviceHdl, vk::ObjectType::eCommandPool, cmdPool->GetVkCommandPool(),
"[Command Pool] Render Context #" + std::to_string(i) + " Pool #" + std::to_string(j)
);
frameData[i].cmdPoolHdls.push_back(cmdPool);
} }
} }

View File

@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImage.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHTextureAsset.h"
@ -78,6 +79,7 @@ namespace SHADE
{ {
job.Image = resourceManager.Create<SHVkImage> job.Image = resourceManager.Create<SHVkImage>
( (
device,
&device->GetVMAAllocator(), &device->GetVMAAllocator(),
SHImageCreateParams SHImageCreateParams
{ {
@ -142,6 +144,7 @@ namespace SHADE
.layerCount = 1 .layerCount = 1
}; };
job.TextureHandle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS); job.TextureHandle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
SET_VK_OBJ_NAME(device, vk::ObjectType::eImageView, job.TextureHandle->ImageView->GetImageView(), "[Image View] Texture Library Texture #" + std::to_string(job.TextureHandle->TextureArrayIndex));
} }
// Add Textures // Add Textures
@ -150,6 +153,9 @@ namespace SHADE
texOrder.emplace_back(job.TextureHandle); texOrder.emplace_back(job.TextureHandle);
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal)); combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
job.TextureHandle->TextureArrayIndex = static_cast<uint32_t>(texOrder.size()) - 1U; job.TextureHandle->TextureArrayIndex = static_cast<uint32_t>(texOrder.size()) - 1U;
SET_VK_OBJ_NAME(device, vk::ObjectType::eImage, job.Image->GetVkImage(), "[Image] Texture Library Texture #" + std::to_string(job.TextureHandle->TextureArrayIndex));
SET_VK_OBJ_NAME(device, vk::ObjectType::eImageView, job.TextureHandle->ImageView->GetImageView(), "[Image View] Texture Library Texture #" + std::to_string(job.TextureHandle->TextureArrayIndex));
} }
addJobs.clear(); addJobs.clear();
@ -165,6 +171,10 @@ namespace SHADE
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] }, { SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
{ static_cast<uint32_t>(texOrder.size()) } { static_cast<uint32_t>(texOrder.size()) }
); );
#ifdef _DEBUG
for (auto set : texDescriptors->GetVkHandle())
SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] Static Globals");
#endif
texDescriptors->ModifyWriteDescImage texDescriptors->ModifyWriteDescImage
( (
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS, SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,

View File

@ -59,7 +59,8 @@ namespace SHADE
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format; format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
} }
renderGraphStorage->graphResources->try_emplace(resourceName, resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags)); auto resource = resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags);
renderGraphStorage->graphResources->try_emplace(resourceName, resource);
} }
/***************************************************************************/ /***************************************************************************/
@ -353,7 +354,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept void SHRenderGraph::Init(std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
{ {
resourceManager = std::make_shared<SHResourceHub>(); resourceManager = std::make_shared<SHResourceHub>();
@ -365,6 +366,8 @@ namespace SHADE
renderGraphStorage->resourceManager = resourceManager; renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools(); renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
name = std::move(graphName);
} }
/***************************************************************************/ /***************************************************************************/
@ -390,6 +393,7 @@ namespace SHADE
, nodeIndexing{ std::move(rhs.nodeIndexing) } , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) } , nodes{ std::move(rhs.nodes) }
, resourceManager{ std::move(rhs.resourceManager) } , resourceManager{ std::move(rhs.resourceManager) }
, name { std::move(rhs.name) }
{ {
} }
@ -403,6 +407,7 @@ namespace SHADE
nodeIndexing = std::move(rhs.nodeIndexing); nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes); nodes = std::move(rhs.nodes);
resourceManager = std::move(rhs.resourceManager); resourceManager = std::move(rhs.resourceManager);
name = std::move(rhs.name);
return *this; return *this;
} }
@ -467,9 +472,9 @@ namespace SHADE
} }
} }
nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(renderGraphStorage, std::move(descInitParams), std::move(predecessors))); auto node = nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u); nodeIndexing.emplace(std::move(nodeName), static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]); return node;
} }
/***************************************************************************/ /***************************************************************************/
@ -516,8 +521,10 @@ namespace SHADE
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
{ {
cmdBuffer->BeginLabeledSegment(name);
for (auto& node : nodes) for (auto& node : nodes)
node->Execute(cmdBuffer, descPool, frameIndex); node->Execute(cmdBuffer, descPool, frameIndex);
cmdBuffer->EndLabeledSegment();
} }
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) void SHRenderGraph::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)

View File

@ -69,6 +69,9 @@ namespace SHADE
//! Resource library for graph handles //! Resource library for graph handles
std::shared_ptr<SHResourceHub> resourceManager; std::shared_ptr<SHResourceHub> resourceManager;
//! Name of the RenderGraph
std::string name;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
@ -81,7 +84,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept; void Init (std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {}); void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;

View File

@ -25,6 +25,7 @@ namespace SHADE
void SHRenderGraphNode::CreateRenderpass(void) noexcept void SHRenderGraphNode::CreateRenderpass(void) noexcept
{ {
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps); renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
} }
/***************************************************************************/ /***************************************************************************/
@ -57,6 +58,7 @@ namespace SHADE
framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight); framebuffers[i] = graphStorage->logicalDevice->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
} }
} }
@ -116,7 +118,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept SHRenderGraphNode::SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept
: graphStorage{ renderGraphStorage} : graphStorage{ renderGraphStorage}
, renderpass{} , renderpass{}
, framebuffers{} , framebuffers{}
@ -128,6 +130,7 @@ namespace SHADE
, executed{ false } , executed{ false }
, configured{ false } , configured{ false }
, nodeComputes{} , nodeComputes{}
, name { std::move(nodeName) }
{ {
// pipeline library initialization // pipeline library initialization
pipelineLibrary.Init(graphStorage->logicalDevice); pipelineLibrary.Init(graphStorage->logicalDevice);
@ -189,6 +192,7 @@ namespace SHADE
, spDescs{ std::move(rhs.spDescs) } , spDescs{ std::move(rhs.spDescs) }
, spDeps{ std::move(rhs.spDeps) } , spDeps{ std::move(rhs.spDeps) }
, nodeComputes{ std::move(rhs.nodeComputes) } , nodeComputes{ std::move(rhs.nodeComputes) }
, name { std::move(rhs.name) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
@ -213,7 +217,7 @@ namespace SHADE
spDescs = std::move(rhs.spDescs); spDescs = std::move(rhs.spDescs);
spDeps = std::move(rhs.spDeps); spDeps = std::move(rhs.spDeps);
nodeComputes = std::move(rhs.nodeComputes); nodeComputes = std::move(rhs.nodeComputes);
name = std::move(rhs.name);
rhs.renderpass = {}; rhs.renderpass = {};
@ -263,7 +267,7 @@ namespace SHADE
return subpass; return subpass;
} }
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept
{ {
// Look for the required resources in the graph // Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{}; std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
@ -276,7 +280,7 @@ namespace SHADE
} }
// Create the subpass compute with the resources // Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty()); auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(std::move(nodeName), graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
nodeComputes.push_back(nodeCompute); nodeComputes.push_back(nodeCompute);
return nodeCompute; return nodeCompute;

View File

@ -78,8 +78,11 @@ namespace SHADE
//! Whether or not the node has been configured already or not //! Whether or not the node has been configured already or not
bool configured; bool configured;
//! Manages batching for this RenderPass
SHBatcher batcher; SHBatcher batcher;
//! Name of this node
std::string name;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
@ -92,7 +95,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHRenderGraphNode(Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept; SHRenderGraphNode(std::string nodeName, Handle<SHRenderGraphStorage> renderGraphStorage, std::vector<SHAttachmentDescInitParams> attDescInitParams, std::vector<Handle<SHRenderGraphNode>> predecessors) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept; SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
@ -100,7 +103,7 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept; Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
void AddDummySubpassIfNeeded (void) noexcept; void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()

View File

@ -13,7 +13,7 @@
namespace SHADE namespace SHADE
{ {
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
: computePipeline{} : computePipeline{}
, pipelineLayout{} , pipelineLayout{}
, resources{} , resources{}
@ -22,6 +22,7 @@ namespace SHADE
, followingEndRenderpass {followingEndRP} , followingEndRenderpass {followingEndRP}
, numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)} , numWorkGroupScale {std::clamp(inNumWorkGroupScale, 0.0f, 1.0f)}
, computeResource{} , computeResource{}
, name { std::move(nodeName) }
{ {
SHPipelineLayoutParams pipelineLayoutParams SHPipelineLayoutParams pipelineLayoutParams
{ {
@ -31,13 +32,15 @@ namespace SHADE
}; };
// Create pipeline layout from parameters // Create pipeline layout from parameters
pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout (pipelineLayoutParams); pipelineLayout = graphStorage->logicalDevice->CreatePipelineLayout(pipelineLayoutParams);
// Create the compute pipeline // Create the compute pipeline
computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout); computePipeline = graphStorage->logicalDevice->CreateComputePipeline(pipelineLayout);
// and construct it // and construct it
computePipeline->ConstructPipeline(); computePipeline->ConstructPipeline();
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::ePipelineLayout, pipelineLayout->GetVkPipelineLayout(), "[Compute Pipeline Layout] " + name);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::ePipeline, computePipeline->GetVkPipeline(), "[Compute Pipeline] " + name);
// save the resources // save the resources
resources = std::move (subpassComputeResources); resources = std::move (subpassComputeResources);
@ -50,6 +53,10 @@ namespace SHADE
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{ {
graphResourceDescSets[i] = graphStorage->descriptorPool->Allocate({graphResourceLayout}, { 1 }); graphResourceDescSets[i] = graphStorage->descriptorPool->Allocate({graphResourceLayout}, { 1 });
#ifdef _DEBUG
for (auto set : graphResourceDescSets[i]->GetVkHandle())
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] " + name + " #" + std::to_string(i));
#endif
} }
@ -61,6 +68,10 @@ namespace SHADE
computeResource = graphStorage->resourceManager->Create<ComputeResource>(); computeResource = graphStorage->resourceManager->Create<ComputeResource>();
auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE]; auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE];
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 }); computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
#ifdef _DEBUG
for (auto set : computeResource->descSet->GetVkHandle())
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] " + name + " Resources");
#endif
// Allocate for descriptor offsets // Allocate for descriptor offsets
for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)

View File

@ -65,8 +65,11 @@ namespace SHADE
std::array<std::vector<vk::ImageMemoryBarrier>, SHGraphicsConstants::NUM_FRAME_BUFFERS> memoryBarriers; std::array<std::vector<vk::ImageMemoryBarrier>, SHGraphicsConstants::NUM_FRAME_BUFFERS> memoryBarriers;
//! Name of this node
std::string name;
public: public:
SHRenderGraphNodeCompute(Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept; SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept; void HandleResize (void) noexcept;

View File

@ -82,6 +82,7 @@ namespace SHADE
{ {
images[i] = graphStorage->swapchain->GetSwapchainImage(i); images[i] = graphStorage->swapchain->GetSwapchainImage(i);
imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails); imageViews[i] = images[i]->CreateImageView(graphStorage->logicalDevice, images[i], viewDetails);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eImageView, imageViews[i]->GetImageView(), "[Image View] " + resourceName + " #" + std::to_string(i));
} }
} }
else // if swapchain image resource else // if swapchain image resource
@ -129,7 +130,9 @@ namespace SHADE
} }
// The resource is not a swapchain image, just use the first slot of the vector // The resource is not a swapchain image, just use the first slot of the vector
images.push_back(graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags)); auto image = graphStorage->logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eImage, image->GetVkImage(), "[Image] " + resourceName);
images.push_back(image);
// prepare image view details // prepare image view details
SHImageViewDetails viewDetails SHImageViewDetails viewDetails
@ -144,7 +147,9 @@ namespace SHADE
}; };
// just 1 image view created // just 1 image view created
imageViews.push_back(images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails)); auto imageView = images[0]->CreateImageView(graphStorage->logicalDevice, images[0], viewDetails);
imageViews.push_back(imageView);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eImageView, imageView->GetImageView(), "[Image View] " + resourceName);
} }
} }

View File

@ -201,6 +201,7 @@ namespace SHADE
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{ {
commandBuffer->BeginLabeledSegment(name);
// Ensure correct transforms are provided // Ensure correct transforms are provided
superBatch->UpdateBuffers(frameIndex, descPool); superBatch->UpdateBuffers(frameIndex, descPool);
@ -212,7 +213,7 @@ namespace SHADE
{ {
drawCall(commandBuffer); drawCall(commandBuffer);
} }
commandBuffer->EndLabeledSegment();
} }
void SHSubpass::HandleResize(void) noexcept void SHSubpass::HandleResize(void) noexcept
@ -301,6 +302,11 @@ namespace SHADE
group.Free(); group.Free();
group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts); group = graphStorage->descriptorPool->Allocate({ inputDescriptorLayout }, variableCounts);
#ifdef _DEBUG
const auto& GROUP_HANDLES = group->GetVkHandle();
for (int i = 0; i < static_cast<int>(GROUP_HANDLES.size()); ++i)
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eDescriptorSet, GROUP_HANDLES[i], "[Descriptor Set] " + name + " #" + std::to_string(i));
#endif
uint32_t i = 0; uint32_t i = 0;
for (auto& binding : bindings) for (auto& binding : bindings)

View File

@ -82,7 +82,7 @@ namespace SHADE
} }
} }
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage, const std::string& name)
{ {
if (bufferHandle) if (bufferHandle)
{ {
@ -100,7 +100,8 @@ namespace SHADE
size, size,
usage | BuffUsage::eTransferDst, usage | BuffUsage::eTransferDst,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
name
); );
} }
@ -108,7 +109,7 @@ namespace SHADE
bufferHandle->TransferToDeviceResource(cmdBuffer); bufferHandle->TransferToDeviceResource(cmdBuffer);
} }
void SHVkUtil::EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage) void SHVkUtil::EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage, const std::string& name)
{ {
if (bufferHandle) if (bufferHandle)
{ {
@ -126,7 +127,8 @@ namespace SHADE
size, size,
usage, usage,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT,
name
); );
} }
} }

View File

@ -54,7 +54,7 @@ namespace SHADE
*/ */
/***********************************************************************************/ /***********************************************************************************/
static void EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage); static void EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage, const std::string& name = "");
/***********************************************************************************/ /***********************************************************************************/
/*! /*!
@ -80,7 +80,7 @@ namespace SHADE
*/ */
/***********************************************************************************/ /***********************************************************************************/
static void EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage); static void EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage, const std::string& name = "");
static BindingAndSetHash GenBindingSetHash (uint32_t set, uint32_t binding) noexcept; static BindingAndSetHash GenBindingSetHash (uint32_t set, uint32_t binding) noexcept;
}; };

View File

@ -25,11 +25,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHBoundingBox::SHBoundingBox() noexcept SHBoundingBox::SHBoundingBox() noexcept
: RelativeExtents { SHVec3::One }
{ {
type = Type::BOX; type = Type::BOX;
} }
SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept SHBoundingBox::SHBoundingBox(const SHVec3& c, const SHVec3& hE) noexcept
: RelativeExtents { SHVec3::One }
{ {
type = Type::BOX; type = Type::BOX;
@ -45,16 +47,18 @@ namespace SHADE
type = Type::BOX; type = Type::BOX;
Center = rhs.Center; Center = rhs.Center;
Extents = rhs.Extents; Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
} }
SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept SHBoundingBox::SHBoundingBox(SHBoundingBox&& rhs) noexcept
{ {
type = Type::BOX; type = Type::BOX;
Center = rhs.Center; Center = rhs.Center;
Extents = rhs.Extents; Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -69,8 +73,9 @@ namespace SHADE
} }
else if (this != &rhs) else if (this != &rhs)
{ {
Center = rhs.Center; Center = rhs.Center;
Extents = rhs.Extents; Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
} }
return *this; return *this;
@ -84,8 +89,9 @@ namespace SHADE
} }
else else
{ {
Center = rhs.Center; Center = rhs.Center;
Extents = rhs.Extents; Extents = rhs.Extents;
RelativeExtents = rhs.RelativeExtents;
} }
return *this; return *this;
@ -100,11 +106,16 @@ namespace SHADE
return Center; return Center;
} }
SHVec3 SHBoundingBox::GetHalfExtents() const noexcept SHVec3 SHBoundingBox::GetWorldExtents() const noexcept
{ {
return Extents; return Extents;
} }
const SHVec3& SHBoundingBox::GetRelativeExtents() const noexcept
{
return RelativeExtents;
}
SHVec3 SHBoundingBox::GetMin() const noexcept SHVec3 SHBoundingBox::GetMin() const noexcept
{ {
return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z };
@ -124,9 +135,14 @@ namespace SHADE
Center = newCenter; Center = newCenter;
} }
void SHBoundingBox::SetHalfExtents(const SHVec3& newHalfExtents) noexcept void SHBoundingBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept
{ {
Extents = newHalfExtents; Extents = newWorldExtents;
}
void SHBoundingBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept
{
RelativeExtents = newRelativeExtents;
} }
void SHBoundingBox::SetMin(const SHVec3& min) noexcept void SHBoundingBox::SetMin(const SHVec3& min) noexcept

View File

@ -54,21 +54,23 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetCenter () const noexcept; [[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] SHVec3 GetHalfExtents() const noexcept; [[nodiscard]] SHVec3 GetWorldExtents () const noexcept;
[[nodiscard]] SHVec3 GetMin () const noexcept; [[nodiscard]] const SHVec3& GetRelativeExtents () const noexcept;
[[nodiscard]] SHVec3 GetMax () const noexcept; [[nodiscard]] SHVec3 GetMin () const noexcept;
[[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept; [[nodiscard]] SHVec3 GetMax () const noexcept;
[[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetCenter (const SHVec3& newCenter) noexcept; void SetCenter (const SHVec3& newCenter) noexcept;
void SetHalfExtents (const SHVec3& newHalfExtents) noexcept; void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
void SetMin (const SHVec3& min) noexcept; void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
void SetMax (const SHVec3& max) noexcept; void SetMin (const SHVec3& min) noexcept;
void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept; void SetMax (const SHVec3& max) noexcept;
void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
@ -89,6 +91,13 @@ namespace SHADE
[[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept; [[nodiscard]] static bool Intersect (const SHBoundingBox& lhs, const SHBoundingBox& rhs) noexcept;
[[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept; [[nodiscard]] static SHBoundingBox BuildFromBoxes (const SHBoundingBox* boxes, size_t numBoxes) noexcept;
[[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; [[nodiscard]] static SHBoundingBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHVec3 RelativeExtents;
}; };

View File

@ -25,11 +25,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHBoundingSphere::SHBoundingSphere() noexcept SHBoundingSphere::SHBoundingSphere() noexcept
: RelativeRadius { 1.0f }
{ {
type = Type::SPHERE; type = Type::SPHERE;
} }
SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept SHBoundingSphere::SHBoundingSphere(const SHVec3& center, float radius) noexcept
: RelativeRadius { 1.0f }
{ {
type = Type::SPHERE; type = Type::SPHERE;
@ -44,16 +46,18 @@ namespace SHADE
type = Type::SPHERE; type = Type::SPHERE;
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept SHBoundingSphere::SHBoundingSphere(SHBoundingSphere&& rhs) noexcept
{ {
type = Type::SPHERE; type = Type::SPHERE;
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -68,8 +72,9 @@ namespace SHADE
} }
else if (this != &rhs) else if (this != &rhs)
{ {
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
return *this; return *this;
@ -83,8 +88,9 @@ namespace SHADE
} }
else else
{ {
Center = rhs.Center; Center = rhs.Center;
Radius = rhs.Radius; Radius = rhs.Radius;
RelativeRadius = rhs.RelativeRadius;
} }
return *this; return *this;
@ -99,11 +105,16 @@ namespace SHADE
return Center; return Center;
} }
float SHBoundingSphere::GetRadius() const noexcept float SHBoundingSphere::GetWorldRadius() const noexcept
{ {
return Radius; return Radius;
} }
float SHBoundingSphere::GetRelativeRadius() const noexcept
{
return RelativeRadius;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -113,9 +124,14 @@ namespace SHADE
Center = center; Center = center;
} }
void SHBoundingSphere::SetRadius(float radius) noexcept void SHBoundingSphere::SetWorldRadius(float newWorldRadius) noexcept
{ {
Radius = radius; Radius = newWorldRadius;
}
void SHBoundingSphere::SetRelativeRadius(float newRelativeRadius) noexcept
{
RelativeRadius = newRelativeRadius;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -48,15 +48,17 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] SHVec3 GetCenter () const noexcept; [[nodiscard]] SHVec3 GetCenter () const noexcept;
[[nodiscard]] float GetRadius () const noexcept; [[nodiscard]] float GetWorldRadius () const noexcept;
[[nodiscard]] float GetRelativeRadius () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetCenter (const SHVec3& center) noexcept; void SetCenter (const SHVec3& center) noexcept;
void SetRadius (float radius) noexcept; void SetWorldRadius (float newWorldRadius) noexcept;
void SetRelativeRadius (float newRelativeRadius) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
@ -79,5 +81,12 @@ namespace SHADE
[[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept; [[nodiscard]] static SHBoundingSphere BuildFromSpheres (const SHBoundingSphere* spheres, size_t numSpheres) noexcept;
[[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; [[nodiscard]] static SHBoundingSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
float RelativeRadius;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -231,12 +231,12 @@ namespace SHADE
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
// Set the orientation // Set the orientation
// Wrap rotations between -360 and 360 and convert to radians // Wrap rotations between -720 and 720 and convert to radians
SHVec3 worldRotRad, localRotRad; SHVec3 worldRotRad, localRotRad;
for (size_t i = 0; i < SHVec3::SIZE; ++i) for (size_t i = 0; i < SHVec3::SIZE; ++i)
{ {
worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -2.0f * SHMath::TWO_PI, 2.0f * SHMath::TWO_PI);
localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -2.0f * SHMath::TWO_PI, 2.0f * SHMath::TWO_PI);
} }
tf.world.orientation = SHQuaternion::FromEuler(worldRotRad); tf.world.orientation = SHQuaternion::FromEuler(worldRotRad);

View File

@ -48,17 +48,22 @@ namespace SHADE
return orientation.ToEuler(); return orientation.ToEuler();
} }
const SHColliderComponent::Colliders& SHColliderComponent::GetColliders() const noexcept const SHVec3& SHColliderComponent::GetScale() const noexcept
{ {
return colliders; return scale;
} }
SHCollider& SHColliderComponent::GetCollider(int index) const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
{ {
if (index < 0 || static_cast<size_t>(index) >= colliders.size()) return collisionShapes;
}
SHCollisionShape& SHColliderComponent::GetCollisionShape(int index)
{
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
throw std::invalid_argument("Out-of-range access!"); throw std::invalid_argument("Out-of-range access!");
return colliders[index]; return collisionShapes[index];
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -75,39 +80,74 @@ namespace SHADE
} }
SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept void SHColliderComponent::RecomputeCollisionShapes() noexcept
{
for (auto& collisionShape : collisionShapes)
{
switch (collisionShape.GetType())
{
case SHCollisionShape::Type::BOX:
{
auto* box = reinterpret_cast<SHBoundingBox*>(collisionShape.GetShape());
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
// Recompute world extents based on new scale and fixed relative extents
const SHVec3 WORLD_EXTENTS = RELATIVE_EXTENTS * (scale * 0.5f);
box->SetWorldExtents(WORLD_EXTENTS);
continue;
}
case SHCollisionShape::Type::SPHERE:
{
auto* sphere = reinterpret_cast<SHBoundingSphere*>(collisionShape.GetShape());
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
// Recompute world radius based on new scale and fixed radius
const float MAX_SCALE = SHMath::Max({ scale.x, scale.y, scale.z });
const float WORLD_RADIUS = RELATIVE_RADIUS * MAX_SCALE * 0.5f;
sphere->SetWorldRadius(WORLD_RADIUS);
continue;
}
default: continue;
}
}
}
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept
{ {
if (!system) if (!system)
{ {
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!") SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
return nullptr; return -1;
} }
static constexpr auto TYPE = SHCollider::Type::BOX; static constexpr auto TYPE = SHCollisionShape::Type::BOX;
auto& collider = colliders.emplace_back(SHCollider{ GetEID(), TYPE }); auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
collider.entityID = GetEID(); collider.entityID = GetEID();
collider.SetPositionOffset(posOffset); collider.SetPositionOffset(posOffset);
collider.SetRotationOffset(rotOffset);
collider.SetBoundingBox(halfExtents); collider.SetBoundingBox(halfExtents);
// Notify Physics System // Notify Physics System
system->AddCollisionShape(GetEID(), &collider); system->AddCollisionShape(GetEID(), &collider);
return reinterpret_cast<SHBoundingBox*>(collider.GetShape()); return static_cast<int>(collisionShapes.size()) - 1;
} }
SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
{ {
if (!system) if (!system)
{ {
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
return nullptr; return -1;
} }
static constexpr auto TYPE = SHCollider::Type::SPHERE; static constexpr auto TYPE = SHCollisionShape::Type::SPHERE;
auto& collider = colliders.emplace_back(SHCollider{ GetEID(), TYPE }); auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
collider.entityID = GetEID(); collider.entityID = GetEID();
collider.SetPositionOffset(posOffset); collider.SetPositionOffset(posOffset);
@ -116,17 +156,17 @@ namespace SHADE
// Notify Physics System // Notify Physics System
system->AddCollisionShape(GetEID(), &collider); system->AddCollisionShape(GetEID(), &collider);
return reinterpret_cast<SHBoundingSphere*>(collider.GetShape()); return static_cast<int>(collisionShapes.size()) - 1;
} }
void SHColliderComponent::RemoveCollider(int index) void SHColliderComponent::RemoveCollider(int index)
{ {
if (index < 0 || static_cast<size_t>(index) >= colliders.size()) if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
throw std::invalid_argument("Out-of-range access!"); throw std::invalid_argument("Out-of-range access!");
int idx = 0; int idx = 0;
auto it = colliders.begin(); auto it = collisionShapes.begin();
for (; it != colliders.end(); ++it) for (; it != collisionShapes.end(); ++it)
{ {
if (idx == index) if (idx == index)
break; break;
@ -134,7 +174,7 @@ namespace SHADE
++idx; ++idx;
} }
it = colliders.erase(it); it = collisionShapes.erase(it);
// Notify Physics System // Notify Physics System
if (!system) if (!system)

View File

@ -14,7 +14,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Physics/SHCollider.h" #include "Physics/SHCollisionShape.h"
#include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingBox.h"
#include "Math/Geometry/SHBoundingSphere.h" #include "Math/Geometry/SHBoundingSphere.h"
@ -43,7 +43,7 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
using Colliders = std::vector<SHCollider>; using CollisionShapes = std::vector<SHCollisionShape>;
public: public:
@ -67,26 +67,29 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool HasChanged () const noexcept; [[nodiscard]] bool HasChanged () const noexcept;
[[nodiscard]] const SHVec3& GetPosition () const noexcept; [[nodiscard]] const SHVec3& GetPosition () const noexcept;
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept; [[nodiscard]] SHVec3 GetRotation () const noexcept;
[[nodiscard]] const SHVec3& GetScale () const noexcept;
[[nodiscard]] const Colliders& GetColliders () const noexcept; [[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept;
[[nodiscard]] SHCollider& GetCollider (int index); [[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void OnCreate () override; void OnCreate () override;
void OnDestroy () override; void OnDestroy () override;
void RemoveCollider (int index); void RecomputeCollisionShapes () noexcept;
SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept; void RemoveCollider (int index);
SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
int AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero) noexcept;
int AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
private: private:
@ -98,7 +101,8 @@ namespace SHADE
SHVec3 position; SHVec3 position;
SHQuaternion orientation; SHQuaternion orientation;
Colliders colliders; SHVec3 scale;
CollisionShapes collisionShapes;
RTTR_ENABLE() RTTR_ENABLE()
}; };

View File

@ -11,12 +11,12 @@
#include <SHpch.h> #include <SHpch.h>
// Primary Header // Primary Header
#include "SHCollider.h" #include "SHCollisionShape.h"
// Project Headers // Project Headers
#include "Math/Geometry/SHBoundingBox.h" #include "Math/Geometry/SHBoundingBox.h"
#include "Math/Geometry/SHBoundingSphere.h" #include "Math/Geometry/SHBoundingSphere.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Math/SHMathHelpers.h" #include "Math/SHMathHelpers.h"
#include "Physics/Components/SHColliderComponent.h"
#include "Reflection/SHReflectionMetadata.h" #include "Reflection/SHReflectionMetadata.h"
namespace SHADE namespace SHADE
@ -25,7 +25,7 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHCollider::SHCollider(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial) SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial)
: type { colliderType } : type { colliderType }
, entityID { eid } , entityID { eid }
, isTrigger { false } , isTrigger { false }
@ -49,7 +49,7 @@ namespace SHADE
} }
} }
SHCollider::SHCollider(const SHCollider& rhs) noexcept SHCollisionShape::SHCollisionShape(const SHCollisionShape& rhs) noexcept
: type { rhs.type} : type { rhs.type}
, entityID { rhs.entityID } , entityID { rhs.entityID }
, isTrigger { rhs.isTrigger } , isTrigger { rhs.isTrigger }
@ -61,7 +61,7 @@ namespace SHADE
CopyShape(rhs.shape); CopyShape(rhs.shape);
} }
SHCollider::SHCollider(SHCollider&& rhs) noexcept SHCollisionShape::SHCollisionShape(SHCollisionShape&& rhs) noexcept
: type { rhs.type} : type { rhs.type}
, entityID { rhs.entityID } , entityID { rhs.entityID }
, isTrigger { rhs.isTrigger } , isTrigger { rhs.isTrigger }
@ -73,7 +73,7 @@ namespace SHADE
CopyShape(rhs.shape); CopyShape(rhs.shape);
} }
SHCollider::~SHCollider() noexcept SHCollisionShape::~SHCollisionShape() noexcept
{ {
shape = nullptr; shape = nullptr;
} }
@ -82,7 +82,7 @@ namespace SHADE
/* Operator Overload Definitions */ /* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept SHCollisionShape& SHCollisionShape::operator=(const SHCollisionShape& rhs) noexcept
{ {
if (this == &rhs) if (this == &rhs)
return *this; return *this;
@ -100,7 +100,7 @@ namespace SHADE
return *this; return *this;
} }
SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept SHCollisionShape& SHCollisionShape::operator=(SHCollisionShape&& rhs) noexcept
{ {
type = rhs.type; type = rhs.type;
entityID = rhs.entityID; entityID = rhs.entityID;
@ -119,52 +119,52 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollider::HasChanged() const noexcept bool SHCollisionShape::HasChanged() const noexcept
{ {
return dirty; return dirty;
} }
bool SHCollider::IsTrigger() const noexcept bool SHCollisionShape::IsTrigger() const noexcept
{ {
return isTrigger; return isTrigger;
} }
SHCollider::Type SHCollider::GetType() const noexcept SHCollisionShape::Type SHCollisionShape::GetType() const noexcept
{ {
return type; return type;
} }
float SHCollider::GetFriction() const noexcept float SHCollisionShape::GetFriction() const noexcept
{ {
return material.GetFriction(); return material.GetFriction();
} }
float SHCollider::GetBounciness() const noexcept float SHCollisionShape::GetBounciness() const noexcept
{ {
return material.GetBounciness(); return material.GetBounciness();
} }
float SHCollider::GetDensity() const noexcept float SHCollisionShape::GetDensity() const noexcept
{ {
return material.GetDensity(); return material.GetDensity();
} }
const SHPhysicsMaterial& SHCollider::GetMaterial() const noexcept const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept
{ {
return material; return material;
} }
const SHVec3& SHCollider::GetPositionOffset() const noexcept const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept
{ {
return positionOffset; return positionOffset;
} }
const SHVec3& SHCollider::GetRotationOffset() const noexcept const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept
{ {
return rotationOffset; return rotationOffset;
} }
SHShape* SHCollider::GetShape() noexcept SHShape* SHCollisionShape::GetShape() noexcept
{ {
dirty = true; dirty = true;
return shape; return shape;
@ -174,93 +174,80 @@ namespace SHADE
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHCollider::SetBoundingBox(const SHVec3& halfExtents) void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents)
{ {
dirty = true; dirty = true;
// Set the half extents relative to transform const auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
SHVec3 worldHalfExtents = halfExtents; // Set the half extents relative to world scale
const SHVec3 WORLD_EXTENTS = halfExtents * colliderComponent->GetScale() * 0.5f;
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID); if (type != Type::BOX)
if (transformComponent != nullptr)
worldHalfExtents *= (transformComponent->GetWorldScale() * 0.5f);
if (type == Type::BOX)
{
auto* box = reinterpret_cast<SHBoundingBox*>(shape);
box->SetHalfExtents(worldHalfExtents);
}
else
{ {
type = Type::BOX; type = Type::BOX;
delete shape; delete shape;
shape = new SHBoundingBox{ positionOffset, worldHalfExtents }; shape = new SHBoundingBox{ positionOffset, WORLD_EXTENTS };
} }
auto* box = reinterpret_cast<SHBoundingBox*>(shape);
box->SetWorldExtents(WORLD_EXTENTS);
box->SetRelativeExtents(halfExtents);
} }
void SHCollider::SetBoundingSphere(float radius) void SHCollisionShape::SetBoundingSphere(float radius)
{ {
dirty = true; dirty = true;
// Set the radius relative to transform const auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
float worldRadius = radius; // Set the radius relative to world scale
const SHVec3 WORLD_SCALE = colliderComponent->GetScale();
const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z });
const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f;
const auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID); if (type != Type::SPHERE)
if (transformComponent != nullptr)
{
const SHVec3 TF_WORLD_SCALE = transformComponent->GetWorldScale();
const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z });
worldRadius *= MAX_SCALE * 0.5f;
}
if (type == Type::SPHERE)
{
auto* sphere = reinterpret_cast<SHBoundingSphere*>(shape);
sphere->SetRadius(worldRadius);
}
else
{ {
type = Type::SPHERE; type = Type::SPHERE;
delete shape; delete shape;
shape = new SHBoundingSphere{ positionOffset, worldRadius }; shape = new SHBoundingSphere{ positionOffset, WORLD_RADIUS };
} }
auto* sphere = reinterpret_cast<SHBoundingSphere*>(shape);
sphere->SetWorldRadius(WORLD_RADIUS);
} }
void SHCollider::SetIsTrigger(bool trigger) noexcept void SHCollisionShape::SetIsTrigger(bool trigger) noexcept
{ {
dirty = true; dirty = true;
isTrigger = trigger; isTrigger = trigger;
} }
void SHCollider::SetFriction(float friction) noexcept void SHCollisionShape::SetFriction(float friction) noexcept
{ {
dirty = true; dirty = true;
material.SetFriction(friction); material.SetFriction(friction);
} }
void SHCollider::SetBounciness(float bounciness) noexcept void SHCollisionShape::SetBounciness(float bounciness) noexcept
{ {
dirty = true; dirty = true;
material.SetBounciness(bounciness); material.SetBounciness(bounciness);
} }
void SHCollider::SetDensity(float density) noexcept void SHCollisionShape::SetDensity(float density) noexcept
{ {
dirty = true; dirty = true;
material.SetDensity(density); material.SetDensity(density);
} }
void SHCollider::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept
{ {
dirty = true; dirty = true;
material = newMaterial; material = newMaterial;
} }
void SHCollider::SetPositionOffset(const SHVec3& posOffset) noexcept void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept
{ {
dirty = true; dirty = true;
positionOffset = posOffset; positionOffset = posOffset;
@ -281,7 +268,7 @@ namespace SHADE
} }
} }
void SHCollider::SetRotationOffset(const SHVec3& rotOffset) noexcept void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept
{ {
dirty = true; dirty = true;
rotationOffset = rotOffset; rotationOffset = rotOffset;
@ -291,7 +278,7 @@ namespace SHADE
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHCollider::CopyShape(const SHShape* rhs) void SHCollisionShape::CopyShape(const SHShape* rhs)
{ {
switch (type) switch (type)
{ {
@ -299,14 +286,14 @@ namespace SHADE
{ {
const auto* RHS_BOX = reinterpret_cast<const SHBoundingBox*>(rhs); const auto* RHS_BOX = reinterpret_cast<const SHBoundingBox*>(rhs);
shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetHalfExtents() }; shape = new SHBoundingBox{ positionOffset, RHS_BOX->GetWorldExtents() };
break; break;
} }
case Type::SPHERE: case Type::SPHERE:
{ {
const auto* RHS_SPHERE = reinterpret_cast<const SHBoundingSphere*>(rhs); const auto* RHS_SPHERE = reinterpret_cast<const SHBoundingSphere*>(rhs);
shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetRadius() }; shape = new SHBoundingSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() };
break; break;
} }
default: break; default: break;
@ -320,14 +307,14 @@ RTTR_REGISTRATION
using namespace SHADE; using namespace SHADE;
using namespace rttr; using namespace rttr;
registration::enumeration<SHCollider::Type>("Collider Type") registration::enumeration<SHCollisionShape::Type>("Collider Type")
( (
value("Box", SHCollider::Type::BOX), value("Box", SHCollisionShape::Type::BOX),
value("Sphere", SHCollider::Type::SPHERE) value("Sphere", SHCollisionShape::Type::SPHERE)
// TODO(Diren): Add More Shapes // TODO(Diren): Add More Shapes
); );
registration::class_<SHCollider>("Collider") registration::class_<SHCollisionShape>("Collider")
.property("Position Offset", &SHCollider::GetPositionOffset, &SHCollider::SetPositionOffset) .property("Position Offset", &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset)
.property("Rotation Offset", &SHCollider::GetRotationOffset, &SHCollider::SetRotationOffset) (metadata(META::angleInRad, true)); .property("Rotation Offset", &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true));
} }

View File

@ -24,7 +24,7 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHCollider class SH_API SHCollisionShape
{ {
private: private:
@ -51,18 +51,18 @@ namespace SHADE
/* Constructors & Destructor */ /* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHCollider (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT); SHCollisionShape (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT);
SHCollider (const SHCollider& rhs) noexcept; SHCollisionShape (const SHCollisionShape& rhs) noexcept;
SHCollider (SHCollider&& rhs) noexcept; SHCollisionShape (SHCollisionShape&& rhs) noexcept;
~SHCollider () noexcept; ~SHCollisionShape () noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Operator Overloads */ /* Operator Overloads */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHCollider& operator=(const SHCollider& rhs) noexcept; SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept;
SHCollider& operator=(SHCollider&& rhs) noexcept; SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */

View File

@ -128,24 +128,24 @@ namespace SHADE
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
int SHPhysicsObject::AddCollider(SHCollider* collider) int SHPhysicsObject::AddCollider(SHCollisionShape* collider)
{ {
const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() }; const rp3d::Transform OFFSETS{ collider->GetPositionOffset(), collider->GetRotationOffset() };
switch (collider->GetType()) switch (collider->GetType())
{ {
case SHCollider::Type::BOX: case SHCollisionShape::Type::BOX:
{ {
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape()); const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents()); rp3d::BoxShape* newBox = factory->createBoxShape(box->GetWorldExtents());
rp3dBody->addCollider(newBox, OFFSETS); rp3dBody->addCollider(newBox, OFFSETS);
break; break;
} }
case SHCollider::Type::SPHERE: case SHCollisionShape::Type::SPHERE:
{ {
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape()); const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetRadius()); rp3d::SphereShape* newSphere = factory->createSphereShape(sphere->GetWorldRadius());
rp3dBody->addCollider(newSphere, OFFSETS); rp3dBody->addCollider(newSphere, OFFSETS);
break; break;
@ -173,7 +173,7 @@ namespace SHADE
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
{ {
int index = 0; int index = 0;
for (auto& collider : c->colliders) for (auto& collider : c->collisionShapes)
{ {
if (!collider.dirty) if (!collider.dirty)
continue; continue;
@ -188,21 +188,21 @@ namespace SHADE
switch (collider.GetType()) switch (collider.GetType())
{ {
case SHCollider::Type::BOX: case SHCollisionShape::Type::BOX:
{ {
const auto* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape()); const auto* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape()); auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
rp3dBoxShape->setHalfExtents(box->GetHalfExtents()); rp3dBoxShape->setHalfExtents(box->GetWorldExtents());
break; break;
} }
case SHCollider::Type::SPHERE: case SHCollisionShape::Type::SPHERE:
{ {
const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape()); const auto* sphere = reinterpret_cast<SHBoundingSphere*>(collider.GetShape());
auto* rp3dSphereShape = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape()); auto* rp3dSphereShape = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
rp3dSphereShape->setRadius(sphere->GetRadius()); rp3dSphereShape->setRadius(sphere->GetWorldRadius());
break; break;
} }

View File

@ -69,7 +69,7 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
int AddCollider (SHCollider* collider); int AddCollider (SHCollisionShape* collider);
void RemoveCollider (int index); void RemoveCollider (int index);
void SyncColliders (SHColliderComponent* c) const noexcept; void SyncColliders (SHColliderComponent* c) const noexcept;

View File

@ -348,7 +348,7 @@ namespace SHADE
factory.destroyPhysicsWorld(world); factory.destroyPhysicsWorld(world);
} }
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollisionShape* collider)
{ {
auto* physicsObject = GetPhysicsObject(entityID); auto* physicsObject = GetPhysicsObject(entityID);
@ -395,6 +395,7 @@ namespace SHADE
{ {
const auto WORLD_POS = transformComponent->GetWorldPosition(); const auto WORLD_POS = transformComponent->GetWorldPosition();
const auto WORLD_ROT = transformComponent->GetWorldOrientation(); const auto WORLD_ROT = transformComponent->GetWorldOrientation();
const auto WORLD_SCL = transformComponent->GetWorldScale();
physicsObject.SetPosition(WORLD_POS); physicsObject.SetPosition(WORLD_POS);
physicsObject.SetOrientation(WORLD_ROT); physicsObject.SetOrientation(WORLD_ROT);
@ -409,8 +410,11 @@ namespace SHADE
if (colliderComponent) if (colliderComponent)
{ {
colliderComponent->position = WORLD_POS; colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT; colliderComponent->orientation = WORLD_ROT;
colliderComponent->scale = WORLD_SCL;
colliderComponent->RecomputeCollisionShapes();
} }
} }
@ -605,7 +609,6 @@ namespace SHADE
if (rigidBodyComponent != nullptr) if (rigidBodyComponent != nullptr)
{ {
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
continue; continue;
@ -658,8 +661,10 @@ namespace SHADE
{ {
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e) const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionEvent& e)
{ {
const bool ENTITY_MATCH = e.value[0] == collisionEvent.value[0]; const bool ENTITY_MATCH = (e.ids[0] == collisionEvent.ids[0] && e.ids[1] == collisionEvent.ids[1])
const bool COLLIDERS_MATCH = e.value[1] == collisionEvent.value[1]; || (e.ids[0] == collisionEvent.ids[1] && e.ids[1] == collisionEvent.ids[0]);
const bool COLLIDERS_MATCH = (e.ids[2] == collisionEvent.ids[2] && e.ids[3] == collisionEvent.ids[3])
|| (e.ids[2] == collisionEvent.ids[3] && e.ids[3] == collisionEvent.ids[2]);
return ENTITY_MATCH && COLLIDERS_MATCH; return ENTITY_MATCH && COLLIDERS_MATCH;
}); });
@ -734,7 +739,7 @@ namespace SHADE
// Add collision shapes back into the body // Add collision shapes back into the body
if (colliderComponent != nullptr) if (colliderComponent != nullptr)
{ {
for (auto& collider : colliderComponent->colliders) for (auto& collider : colliderComponent->collisionShapes)
physicsObject->AddCollider(&collider); physicsObject->AddCollider(&collider);
} }
} }
@ -743,8 +748,9 @@ namespace SHADE
{ {
SHASSERT(colliderComponent != nullptr, "Collider Component was not added to Entity " + std::to_string(ENTITY_ID) + "!"); SHASSERT(colliderComponent != nullptr, "Collider Component was not added to Entity " + std::to_string(ENTITY_ID) + "!");
colliderComponent->position = transformComponent->GetWorldPosition(); colliderComponent->position = transformComponent->GetWorldPosition();
colliderComponent->orientation = transformComponent->GetWorldOrientation(); colliderComponent->orientation = transformComponent->GetWorldOrientation();
colliderComponent->scale = transformComponent->GetWorldScale();
if (physicsObject->rp3dBody == nullptr) if (physicsObject->rp3dBody == nullptr)
{ {
@ -755,7 +761,7 @@ namespace SHADE
} }
// Add Collision Shapes // Add Collision Shapes
for (auto& collider : colliderComponent->colliders) for (auto& collider : colliderComponent->collisionShapes)
physicsObject->AddCollider(&collider); physicsObject->AddCollider(&collider);
} }
} }
@ -800,7 +806,7 @@ namespace SHADE
rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } rp3d::Transform{ colliderComponent->position, colliderComponent->orientation }
); );
for (auto& collider : colliderComponent->colliders) for (auto& collider : colliderComponent->collisionShapes)
physicsObject->AddCollider(&collider); physicsObject->AddCollider(&collider);
} }
} }

View File

@ -114,7 +114,7 @@ namespace SHADE
void Init () override; void Init () override;
void Exit () override; void Exit () override;
void AddCollisionShape (EntityID entityID, SHCollider* collider); void AddCollisionShape (EntityID entityID, SHCollisionShape* collider);
void RemoveCollisionShape (EntityID entityID, int index); void RemoveCollisionShape (EntityID entityID, int index);
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override; void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
@ -183,24 +183,24 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept; SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept;
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
void DestroyPhysicsObject (EntityID entityID) noexcept; void DestroyPhysicsObject (EntityID entityID) noexcept;
static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept; static void SyncActiveStates (SHPhysicsObject& physicsObject, bool componentActive) noexcept;
void SyncTransforms () noexcept; void SyncTransforms () noexcept;
static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept; static void UpdateEventContainers (const SHCollisionEvent& collisionEvent, CollisionEvents& container) noexcept;
void ClearInvalidCollisions () noexcept; void ClearInvalidCollisions () noexcept;
SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent); SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent);
SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent); SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent);
SHEventHandle ResetWorld (SHEventPtr editorStopEvent); SHEventHandle ResetWorld (SHEventPtr editorStopEvent);
template <typename RP3DCollisionPair, typename = std::enable_if_t template <typename RP3DCollisionPair, typename = std::enable_if_t
<std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair> <std::is_same_v<RP3DCollisionPair, rp3d::CollisionCallback::ContactPair>
|| std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>> || std::is_same_v<RP3DCollisionPair, rp3d::OverlapCallback::OverlapPair>>>
SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept; SHCollisionEvent GenerateCollisionEvent (const RP3DCollisionPair& cp) noexcept;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -75,14 +75,14 @@ namespace SHADE
return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]); return SHComponentManager::GetComponent_s<SHRigidBodyComponent>(ids[ENTITY_B]);
} }
const SHCollider* SHCollisionEvent::GetColliderA() const noexcept const SHCollisionShape* SHCollisionEvent::GetColliderA() const noexcept
{ {
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollider(ids[COLLIDER_A]); return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_A])->GetCollisionShape(ids[COLLIDER_A]);
} }
const SHCollider* SHCollisionEvent::GetColliderB() const noexcept const SHCollisionShape* SHCollisionEvent::GetColliderB() const noexcept
{ {
return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollider(ids[COLLIDER_B]); return &SHComponentManager::GetComponent<SHColliderComponent>(ids[ENTITY_B])->GetCollisionShape(ids[COLLIDER_B]);
} }
SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept SHCollisionEvent::State SHCollisionEvent::GetCollisionState() const noexcept

View File

@ -24,7 +24,7 @@ namespace SHADE
struct SHPhysicsColliderAddedEvent struct SHPhysicsColliderAddedEvent
{ {
EntityID entityID; EntityID entityID;
SHCollider::Type colliderType; SHCollisionShape::Type colliderType;
int colliderIndex; int colliderIndex;
}; };
@ -88,8 +88,8 @@ namespace SHADE
[[nodiscard]] EntityID GetEntityB () const noexcept; [[nodiscard]] EntityID GetEntityB () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept; [[nodiscard]] const SHRigidBodyComponent* GetRigidBodyA () const noexcept;
[[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept; [[nodiscard]] const SHRigidBodyComponent* GetRigidBodyB () const noexcept;
[[nodiscard]] const SHCollider* GetColliderA () const noexcept; [[nodiscard]] const SHCollisionShape* GetColliderA () const noexcept;
[[nodiscard]] const SHCollider* GetColliderB () const noexcept; [[nodiscard]] const SHCollisionShape* GetColliderB () const noexcept;
[[nodiscard]] State GetCollisionState () const noexcept; [[nodiscard]] State GetCollisionState () const noexcept;
private: private:

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHSceneGraph.cpp * \file SHSceneGraph.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Scene Graph & Scene Nodes. * \brief Implementation for a Scene Graph.
* *
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -16,8 +16,6 @@
// Project Headers // Project Headers
#include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHEntityManager.h"
#include "Events/SHEventManager.hpp" #include "Events/SHEventManager.hpp"
#include "Tools/SHLogger.h"
#include "Tools/SHException.h"
namespace SHADE namespace SHADE
{ {
@ -25,56 +23,6 @@ namespace SHADE
/* Constructors & Destructor Definitions */ /* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
: active { true }
, entityID { eid }
, parent { parent }
{}
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
}
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
}
SHSceneNode& SHSceneNode::operator=(const SHSceneNode& rhs) noexcept
{
if (this == &rhs)
return *this;
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
return *this;
}
SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept
{
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
return *this;
}
SHSceneGraph::SHSceneGraph() noexcept SHSceneGraph::SHSceneGraph() noexcept
: root { nullptr } : root { nullptr }
{ {
@ -110,56 +58,6 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHSceneNode::IsActive() const noexcept
{
return active;
}
EntityID SHSceneNode::GetEntityID() const noexcept
{
return entityID;
}
SHSceneNode* SHSceneNode::GetParent() const noexcept
{
return parent;
}
const std::vector<SHSceneNode*>& SHSceneNode::GetChildren() const noexcept
{
return children;
}
SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(childID))
{
SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID)
return nullptr;
}
if (children.empty())
{
SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr;
}
////////////////////////////////////////
// Find child
const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; };
const auto CHILD_ITER = std::ranges::find_if(children.begin(), children.end(),ENTITY_MATCH);
if (CHILD_ITER == children.end())
{
SHLOG_WARNING("Entity {} is not a child of Entity {}! Unable to retrieve child node!", childID, entityID)
return nullptr;
}
return *CHILD_ITER;
}
const SHSceneNode* SHSceneGraph::GetRoot() const noexcept const SHSceneNode* SHSceneGraph::GetRoot() const noexcept
{ {
if (root != nullptr) if (root != nullptr)
@ -313,41 +211,7 @@ namespace SHADE
/* Setter Function Definitions */ /* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHSceneNode::SetParent(SHSceneNode* parentNode) noexcept void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* newParent) noexcept
{
if (parentNode == nullptr)
{
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
if (parent)
parent->RemoveChild(this);
return;
}
// Handle self assignment
if (parent && parentNode->entityID == parent->entityID)
return;
if (parent)
parent->RemoveChild(this);
parent = parentNode;
// Update parent's children
parent->AddChild(this);
}
void SHSceneNode::SetActive(bool newActiveState) noexcept
{
active = newActiveState;
for (auto* child : children)
{
SetActive(newActiveState);
}
}
void SHSceneGraph::SetParent(EntityID entityID, SHSceneNode* parent) const noexcept
{ {
//////////////////////////////////////// ////////////////////////////////////////
// Error Handling // Error Handling
@ -369,30 +233,31 @@ namespace SHADE
{ {
.node = NODE_ITER->second .node = NODE_ITER->second
, .oldParent = NODE_ITER->second->GetParent() , .oldParent = NODE_ITER->second->GetParent()
, .newParent = parent ? parent : root , .newParent = newParent ? newParent : root
}; };
if (parent == nullptr) if (newParent == nullptr)
parent = root; newParent = root;
NODE_ITER->second->SetParent(parent); ChangeParent(NODE_ITER->second, newParent);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept void SHSceneGraph::SetParent(EntityID entityID, EntityID newParent) noexcept
{ {
//////////////////////////////////////// ////////////////////////////////////////
// Error Handling // Error Handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID) SHLOG_ERROR("Entity {} is invalid! Unable to set parent of an invalid entity!", entityID)
return; return;
} }
if (!SHEntityManager::IsValidEID(parent)) if (!SHEntityManager::IsValidEID(newParent))
{ {
SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", parent, entityID) SHLOG_ERROR("Parent Entity {} is invalid! Unable to set Entity {}'s parent!", newParent, entityID)
return; return;
} }
@ -403,10 +268,10 @@ namespace SHADE
return; return;
} }
auto PARENT_ITER = entityNodeMap.find(parent); auto PARENT_ITER = entityNodeMap.find(newParent);
if (PARENT_ITER == entityNodeMap.end()) if (PARENT_ITER == entityNodeMap.end())
{ {
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", parent, entityID) SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to parent to Entity {}", newParent, entityID)
return; return;
} }
//////////////////////////////////////// ////////////////////////////////////////
@ -419,7 +284,7 @@ namespace SHADE
}; };
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
currentNode->SetParent(PARENT_ITER->second); ChangeParent(currentNode, PARENT_ITER->second);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
@ -428,84 +293,6 @@ namespace SHADE
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHSceneNode::AddChild(SHSceneNode* newChild) noexcept
{
////////////////////////////////////////
// Error Handling
if (newChild == nullptr)
{
SHLOG_WARNING("Attempting to add a non-existent child to an entity!")
return;
}
////////////////////////////////////////
if (newChild->parent)
newChild->parent->RemoveChild(newChild);
newChild->parent = this;
children.emplace_back(newChild);
}
bool SHSceneNode::RemoveChild(EntityID childID) noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(childID))
{
SHLOG_ERROR("Entity {} is invalid!", childID)
return false;
}
////////////////////////////////////////
auto childIter = std::find_if(children.begin(), children.end(), [&](SHSceneNode* node)
{
return node->GetEntityID() == childID;
});
if (childIter == children.end())
{
SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childID, entityID)
return false;
}
(*childIter)->parent = nullptr;
childIter = children.erase(childIter);
return true;
}
bool SHSceneNode::RemoveChild(SHSceneNode* childToRemove) noexcept
{
////////////////////////////////////////
// Error Handling
if (childToRemove == nullptr)
{
SHLOG_WARNING("Attempting to remove non-existent child from Entity {}", entityID)
return false;
}
////////////////////////////////////////
auto childIter = std::find(children.begin(), children.end(), childToRemove);
if (childIter == children.end())
{
SHLOG_WARNING("Unable to remove Entity {} from Entity {} since it is not it's child!", childToRemove->entityID, entityID)
return false;
}
childIter = children.erase(childIter);
childToRemove->parent = nullptr;
return true;
}
void SHSceneNode::RemoveAllChildren() noexcept
{
for (const auto child : children)
child->parent = nullptr;
children.clear();
}
SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent) SHSceneNode* SHSceneGraph::AddNode(EntityID entityID, SHSceneNode* parent)
{ {
//////////////////////////////////////// ////////////////////////////////////////
@ -528,13 +315,12 @@ namespace SHADE
if (parent == nullptr) if (parent == nullptr)
{ {
// Specific handling for root to avoid a warning when removing a non-existent child // Specific handling for root to avoid a warning when removing a non-existent child
parent = root;
newNode->parent = root; newNode->parent = root;
root->children.emplace_back(newNode); root->children.emplace_back(newNode);
} }
else else
{ {
newNode->SetParent(parent); ChangeParent(newNode, parent);
} }
return newNode; return newNode;
@ -542,6 +328,8 @@ namespace SHADE
bool SHSceneGraph::RemoveNode(EntityID entityID) noexcept bool SHSceneGraph::RemoveNode(EntityID entityID) noexcept
{ {
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID)) if (!SHEntityManager::IsValidEID(entityID))
{ {
SHLOG_ERROR("Entity {} is invalid!", entityID) SHLOG_ERROR("Entity {} is invalid!", entityID)
@ -554,12 +342,12 @@ namespace SHADE
SHLOG_ERROR("Entity {} does not exist in the scene!", entityID) SHLOG_ERROR("Entity {} does not exist in the scene!", entityID)
return false; return false;
} }
////////////////////////////////////////
// Remove reference of current node from parent // Remove reference of current node from parent
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
SHSceneNode* parent = currentNode->GetParent(); if (currentNode->parent != nullptr)
if (parent != nullptr) RemoveChild(currentNode->parent, currentNode);
parent->RemoveChild(currentNode);
ReleaseNode(currentNode); ReleaseNode(currentNode);
return true; return true;
@ -568,9 +356,8 @@ namespace SHADE
bool SHSceneGraph::RemoveNode(SHSceneNode* nodeToRemove) noexcept bool SHSceneGraph::RemoveNode(SHSceneNode* nodeToRemove) noexcept
{ {
// Remove reference of current node from parent // Remove reference of current node from parent
SHSceneNode* parent = nodeToRemove->GetParent(); if (nodeToRemove->parent != nullptr)
if (parent != nullptr) RemoveChild(nodeToRemove->parent, nodeToRemove);
parent->RemoveChild(nodeToRemove);
ReleaseNode(nodeToRemove); ReleaseNode(nodeToRemove);
return true; return true;
@ -582,6 +369,91 @@ namespace SHADE
ReleaseNode(node); ReleaseNode(node);
} }
bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
return false;
}
auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID)
return false;
}
////////////////////////////////////////
// Handle self-checks
if (NODE_ITER->second == targetNode)
{
SHLOG_WARNING("Entity {} cannot be a child of itself!", entityID)
return false;
}
// Search for a matching target until the root
const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent;
while (CURRENT_TARGET != root)
{
if (CURRENT_TARGET == targetNode)
return true;
CURRENT_TARGET = CURRENT_TARGET->parent;
}
return false;
}
bool SHSceneGraph::IsChildOf(EntityID entityID, EntityID targetID) noexcept
{
////////////////////////////////////////
// Error Handling
if (!SHEntityManager::IsValidEID(entityID))
{
SHLOG_ERROR("Entity {} is invalid!", entityID)
return false;
}
if (!SHEntityManager::IsValidEID(targetID))
{
SHLOG_ERROR("Entity {} is invalid!", targetID)
return false;
}
auto NODE_ITER = entityNodeMap.find(entityID);
if (NODE_ITER == entityNodeMap.end())
{
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", entityID)
return false;
}
auto TARGET_ITER = entityNodeMap.find(targetID);
if (TARGET_ITER == entityNodeMap.end())
{
SHLOG_ERROR("Entity {} cannot be found in the scene! Unable to check child!", targetID)
return false;
}
////////////////////////////////////////
const SHSceneNode* CURRENT_TARGET = NODE_ITER->second->parent;
while (CURRENT_TARGET != root)
{
if (CURRENT_TARGET == TARGET_ITER->second)
return true;
CURRENT_TARGET = CURRENT_TARGET->parent;
}
return false;
}
void SHSceneGraph::Traverse (const UnaryFunction& function) const void SHSceneGraph::Traverse (const UnaryFunction& function) const
{ {
TraverseAndInvokeFunction(root, function); TraverseAndInvokeFunction(root, function);
@ -594,11 +466,6 @@ namespace SHADE
SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID) SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID)
{ {
SHSceneNode* newNode = new SHSceneNode{entityID}; SHSceneNode* newNode = new SHSceneNode{entityID};
//#ifdef _DEBUG
// SHLOG_INFO("Allocated a new Scene Node for Entity {}!", entityID)
//#endif
entityNodeMap.emplace(entityID, newNode); entityNodeMap.emplace(entityID, newNode);
return newNode; return newNode;
} }
@ -608,19 +475,81 @@ namespace SHADE
SHASSERT(node != nullptr, "Attempting to release Invalid Node!") SHASSERT(node != nullptr, "Attempting to release Invalid Node!")
// Remove parent's reference to this node if there is a parent // Remove parent's reference to this node if there is a parent
if (node->GetParent() != nullptr) if (node->parent != nullptr)
node->GetParent()->RemoveChild(node); RemoveChild(node->parent, node);
// Remove child's references to this node. Children end up as floating nodes. // Remove child's references to this node. Children end up as floating nodes.
for (auto* child : node->GetChildren()) for (auto* child : node->GetChildren())
{ {
child->SetParent(nullptr); ChangeParent(child, nullptr);
} }
entityNodeMap.erase(node->GetEntityID()); entityNodeMap.erase(node->GetEntityID());
delete node; delete node;
} }
void SHSceneGraph::ChangeParent(SHSceneNode* node, SHSceneNode* newParent)
{
// Handle self assignment
if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID)
return;
// Remove child
if (node->parent)
RemoveChild(node->parent, node);
if (newParent == nullptr)
{
SHLOG_WARNING("Removing Entity {}'s parent", node->entityID)
return;
}
node->parent = newParent;
// Update parent's children
AddChild(newParent, node);
}
void SHSceneGraph::AddChild(SHSceneNode* node, SHSceneNode* newChild)
{
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
SHASSERT(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!")
if (newChild->parent)
RemoveChild(newChild->parent, newChild);
newChild->parent = node;
node->children.emplace_back(newChild);
const SHSceneGraphAddChildEvent EVENT_DATA
{
.parent = node
, .childAdded = newChild
};
SHEventManager::BroadcastEvent<SHSceneGraphAddChildEvent>(EVENT_DATA, SH_SCENEGRAPH_ADD_CHILD_EVENT);
}
void SHSceneGraph::RemoveChild(SHSceneNode* node, SHSceneNode* childToRemove)
{
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
SHASSERT(childToRemove != nullptr, "Attempting to remove a non-existent child from a SceneNode!")
auto childIter = std::find(node->children.begin(), node->children.end(), childToRemove);
if (childIter == node->children.end())
return;
childIter = node->children.erase(childIter);
childToRemove->parent = nullptr;
const SHSceneGraphRemoveChildEvent EVENT_DATA
{
.parent = node
, .childRemoved = childToRemove
};
SHEventManager::BroadcastEvent<SHSceneGraphRemoveChildEvent>(EVENT_DATA, SH_SCENEGRAPH_REMOVE_CHILD_EVENT);
}
void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function) void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function)
{ {
for (auto* child : node->children) for (auto* child : node->children)

View File

@ -1,7 +1,7 @@
/**************************************************************************************** /****************************************************************************************
* \file SHSceneGraph.h * \file SHSceneGraph.h
* \author Diren D Bharwani, diren.dbharwani, 390002520 * \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Scene Graph & Scene Nodes. * \brief Interface for a Scene Graph.
* *
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent * disclosure of this file or its contents without the prior written consent
@ -15,81 +15,15 @@
// Project Headers // Project Headers
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h" #include "SH_API.h"
#include "SHSceneNode.h"
#include "SHSceneGraphEvents.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHSceneGraph;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SH_API SHSceneNode
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHSceneGraph;
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
~SHSceneNode () = default;
SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept;
SHSceneNode (const SHSceneNode& rhs) noexcept;
SHSceneNode (SHSceneNode&& rhs) noexcept;
SHSceneNode& operator= (const SHSceneNode& rhs) noexcept;
SHSceneNode& operator= (SHSceneNode&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool IsActive () const noexcept;
[[nodiscard]] EntityID GetEntityID () const noexcept;
[[nodiscard]] SHSceneNode* GetParent () const noexcept;
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren () const noexcept;
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetParent (SHSceneNode* parentNode) noexcept;
void SetActive (bool newActiveState) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
void AddChild (SHSceneNode* newChild) noexcept;
bool RemoveChild (EntityID childID) noexcept;
bool RemoveChild (SHSceneNode* childToRemove) noexcept;
void RemoveAllChildren () noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
bool active;
EntityID entityID;
SHSceneNode* parent;
std::vector<SHSceneNode*> children;
};
class SH_API SHSceneGraph class SH_API SHSceneGraph
{ {
public: public:
@ -130,19 +64,22 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetParent (EntityID entityID, SHSceneNode* parent) const noexcept; void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept;
void SetParent (EntityID entityID, EntityID parent) const noexcept; void SetParent (EntityID entityID, EntityID newParent) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
bool RemoveNode (EntityID entityID) noexcept; bool RemoveNode (EntityID entityID) noexcept;
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept; void Reset () noexcept;
void Traverse (const UnaryFunction& function) const; bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept;
bool IsChildOf (EntityID entityID, EntityID targetID) noexcept;
void Traverse (const UnaryFunction& function) const;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -156,20 +93,14 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneNode* AllocateNode (EntityID entityID); SHSceneNode* AllocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept; void ReleaseNode (SHSceneNode* node) noexcept;
static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function);
};
/*-----------------------------------------------------------------------------------*/ void ChangeParent (SHSceneNode* node, SHSceneNode* newParent);
/* Event Data Definitions */ void AddChild (SHSceneNode* node, SHSceneNode* newChild);
/*-----------------------------------------------------------------------------------*/ void RemoveChild (SHSceneNode* node, SHSceneNode* childToRemove);
struct SHSceneGraphChangeParentEvent static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function);
{
SHSceneNode* node;
SHSceneNode* oldParent;
SHSceneNode* newParent;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -0,0 +1,41 @@
/****************************************************************************************
* \file SHSceneGraphEvents.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Scene Graph Events.
*
* \copyright 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 Headers
#include "SHSceneNode.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Event Data Definitions */
/*-----------------------------------------------------------------------------------*/
struct SHSceneGraphChangeParentEvent
{
SHSceneNode* node;
SHSceneNode* oldParent;
SHSceneNode* newParent;
};
struct SHSceneGraphAddChildEvent
{
SHSceneNode* parent;
SHSceneNode* childAdded;
};
struct SHSceneGraphRemoveChildEvent
{
SHSceneNode* parent;
SHSceneNode* childRemoved;
};
} // namespace SHADE

View File

@ -0,0 +1,143 @@
/****************************************************************************************
* \file SHSceneNode.c[[
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a Scene Node.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHSceneNode.h"
// Project Headers
#include "ECS_Base/Managers/SHEntityManager.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHSceneNode::SHSceneNode(EntityID eid, SHSceneNode* parent) noexcept
: active { true }
, entityID { eid }
, parent { parent }
{}
SHSceneNode::SHSceneNode(const SHSceneNode& rhs) noexcept
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
}
SHSceneNode::SHSceneNode(SHSceneNode&& rhs) noexcept
: active { rhs.active }
, entityID { rhs.entityID }
, parent { rhs.parent }
{
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
}
SHSceneNode& SHSceneNode::operator=(const SHSceneNode& rhs) noexcept
{
if (this == &rhs)
return *this;
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
return *this;
}
SHSceneNode& SHSceneNode::operator=(SHSceneNode&& rhs) noexcept
{
active = rhs.active;
entityID = rhs.entityID;
parent = rhs.parent;
children.clear();
std::ranges::copy(rhs.children.begin(), rhs.children.end(), std::back_inserter(children));
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHSceneNode::IsActive() const noexcept
{
return active;
}
EntityID SHSceneNode::GetEntityID() const noexcept
{
return entityID;
}
SHSceneNode* SHSceneNode::GetParent() const noexcept
{
return parent;
}
const std::vector<SHSceneNode*>& SHSceneNode::GetChildren() const noexcept
{
return children;
}
SHSceneNode* SHSceneNode::GetChild(EntityID childID) const noexcept
{
////////////////////////////////////////
// Error handling
if (!SHEntityManager::IsValidEID(childID))
{
SHLOG_ERROR("Child Entity {} is invalid! Unable to get child from Entity {}", childID, entityID)
return nullptr;
}
if (children.empty())
{
SHLOG_WARNING("Entity {} has no children!", entityID)
return nullptr;
}
////////////////////////////////////////
// Find child
const auto ENTITY_MATCH = [&](const SHSceneNode* node) { return node->GetEntityID() == childID; };
const auto CHILD_ITER = std::ranges::find_if(children.begin(), children.end(),ENTITY_MATCH);
if (CHILD_ITER == children.end())
{
SHLOG_WARNING("Entity {} is not a child of Entity {}! Unable to retrieve child node!", childID, entityID)
return nullptr;
}
return *CHILD_ITER;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHSceneNode::SetActive(bool newActiveState) noexcept
{
active = newActiveState;
for (auto* child : children)
{
child->SetActive(newActiveState);
}
}
} // namespace SHADE

View File

@ -0,0 +1,82 @@
/****************************************************************************************
* \file SHSceneNode.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Scene Node.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
#include <vector>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h"
#include "SHSceneGraph.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHSceneGraph;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHSceneNode
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHSceneGraph;
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
~SHSceneNode () = default;
SHSceneNode (EntityID eid, SHSceneNode* parent = nullptr) noexcept;
SHSceneNode (const SHSceneNode& rhs) noexcept;
SHSceneNode (SHSceneNode&& rhs) noexcept;
SHSceneNode& operator= (const SHSceneNode& rhs) noexcept;
SHSceneNode& operator= (SHSceneNode&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] bool IsActive () const noexcept;
[[nodiscard]] EntityID GetEntityID () const noexcept;
[[nodiscard]] SHSceneNode* GetParent () const noexcept;
[[nodiscard]] const std::vector<SHSceneNode*>& GetChildren () const noexcept;
[[nodiscard]] SHSceneNode* GetChild (EntityID childID) const noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetActive (bool newActiveState) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
bool active;
EntityID entityID;
SHSceneNode* parent;
std::vector<SHSceneNode*> children;
};
} // namespace SHADE

View File

@ -26,13 +26,15 @@ of DigiPen Institute of Technology is prohibited.
#include "Events/SHEventManager.hpp" #include "Events/SHEventManager.hpp"
#include "Physics/SHPhysicsSystem.h" #include "Physics/SHPhysicsSystem.h"
#include "Assets/SHAssetMacros.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Definitions */ /* Static Definitions */
/*----------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------*/
const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE"); const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE");
const std::string SHScriptEngine::CSPROJ_DIR = "..\\..\\TempScriptsFolder"; const std::string SHScriptEngine::CSPROJ_DIR = std::string(ASSET_ROOT) + "/Scripts";
const std::string SHScriptEngine::CSPROJ_PATH = std::string(CSPROJ_DIR) + "\\SHADE_Scripting.csproj"; const std::string SHScriptEngine::CSPROJ_PATH = std::string(CSPROJ_DIR) + "\\SHADE_Scripting.csproj";
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -262,18 +264,18 @@ namespace SHADE
</ItemGroup>\n\ </ItemGroup>\n\
<ItemGroup>\n\ <ItemGroup>\n\
<Reference Include=\"SHADE_Managed\">\n\ <Reference Include=\"SHADE_Managed\">\n\
<HintPath Condition=\"Exists('..\\bin\\Debug\\SHADE_Managed.dll')\">..\\bin\\Debug\\SHADE_Managed.dll</HintPath>\n\ <HintPath Condition=\"Exists('..\\..\\bin\\Debug\\SHADE_Managed.dll')\">..\\..\\bin\\Debug\\SHADE_Managed.dll</HintPath>\n\
<HintPath Condition=\"Exists('..\\bin\\Release\\SHADE_Managed.dll')\">..\\bin\\Release\\SHADE_Managed.dll</HintPath>\n\ <HintPath Condition=\"Exists('..\\..\\bin\\Release\\SHADE_Managed.dll')\">..\\..\\bin\\Release\\SHADE_Managed.dll</HintPath>\n\
</Reference>\n\ </Reference>\n\
<Reference Include=\"SHADE_CSharp\">\n\ <Reference Include=\"SHADE_CSharp\">\n\
<HintPath Condition=\"Exists('..\\bin\\Debug\\SHADE_Managed.dll')\">..\\bin\\Debug\\SHADE_CSharp.dll</HintPath>\n\ <HintPath Condition=\"Exists('..\\..\\bin\\Debug\\SHADE_Managed.dll')\">..\\..\\bin\\Debug\\SHADE_CSharp.dll</HintPath>\n\
<HintPath Condition=\"Exists('..\\bin\\Release\\SHADE_Managed.dll')\">..\\bin\\Release\\SHADE_CSharp.dll</HintPath>\n\ <HintPath Condition=\"Exists('..\\..\\bin\\Release\\SHADE_Managed.dll')\">..\\..\\bin\\Release\\SHADE_CSharp.dll</HintPath>\n\
</Reference>\n\ </Reference>\n\
</ItemGroup>\n\ </ItemGroup>\n\
</Project>"; </Project>";
// Attempt to create the file // Attempt to create the file
std::ofstream file(path); std::ofstream file(path, std::ios::out | std::ios::trunc);
if (!file.is_open()) if (!file.is_open())
throw std::runtime_error("Unable to create CsProj file!"); throw std::runtime_error("Unable to create CsProj file!");
@ -316,6 +318,20 @@ namespace SHADE
return eventData->handle; return eventData->handle;
} }
SHEventHandle SHScriptEngine::onSceneNodeChildrenAdded(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphAddChildEvent>*>(eventPtr.get());
csSceneNodeChildrenChanged(eventData->data->parent->GetEntityID());
return eventData->handle;
}
SHEventHandle SHScriptEngine::onSceneNodeChildrenRemoved(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphRemoveChildEvent>*>(eventPtr.get());
csSceneNodeChildrenChanged(eventData->data->parent->GetEntityID());
return eventData->handle;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -379,6 +395,12 @@ namespace SHADE
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore", DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"ExecuteLateUpdate" "ExecuteLateUpdate"
);
csScriptsExecuteDrawGizmos = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"ExecuteOnDrawGizmos"
); );
csScriptsExecutePhysicsEvents = dotNet.GetFunctionPtr<CsFuncPtr> csScriptsExecutePhysicsEvents = dotNet.GetFunctionPtr<CsFuncPtr>
( (
@ -434,6 +456,12 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".Collider", DEFAULT_CSHARP_NAMESPACE + ".Collider",
"OnCollisionShapeRemoved" "OnCollisionShapeRemoved"
); );
csSceneNodeChildrenChanged = dotNet.GetFunctionPtr<CsEventRelayFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".ChildListCache",
"OnChildrenChanged"
);
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr> csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
( (
DEFAULT_CSHARP_LIB_NAME, DEFAULT_CSHARP_LIB_NAME,
@ -456,6 +484,7 @@ namespace SHADE
void SHScriptEngine::registerEvents() void SHScriptEngine::registerEvents()
{ {
/* Entity */
// Register for entity destroyed event // Register for entity destroyed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> destroyedEventReceiver std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> destroyedEventReceiver
{ {
@ -463,26 +492,39 @@ namespace SHADE
}; };
SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(destroyedEventReceiver)); SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(destroyedEventReceiver));
/* Colliders */
// Register for collider added event // Register for collider added event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> addedColliderEventReceiver std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> addedColliderEventReceiver
{ {
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderAdded) std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderAdded)
}; };
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_ADDED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(addedColliderEventReceiver)); SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_ADDED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(addedColliderEventReceiver));
// Register for collider removed event // Register for collider removed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removedColliderEventReceiver std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removedColliderEventReceiver
{ {
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderRemoved) std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderRemoved)
}; };
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_REMOVED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removedColliderEventReceiver)); SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_REMOVED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removedColliderEventReceiver));
// Register for collider component removed event // Register for collider component removed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removedColliderComponentEventReceiver std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removedColliderComponentEventReceiver
{ {
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderComponentRemoved) std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderComponentRemoved)
}; };
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removedColliderComponentEventReceiver)); SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removedColliderComponentEventReceiver));
/* SceneGraph */
// Register for SceneNode child added event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> addChildEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onSceneNodeChildrenAdded)
};
SHEventManager::SubscribeTo(SH_SCENEGRAPH_ADD_CHILD_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(addChildEventReceiver));
// Register for SceneNode child removed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removeChildEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onSceneNodeChildrenRemoved)
};
SHEventManager::SubscribeTo(SH_SCENEGRAPH_REMOVE_CHILD_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removeChildEventReceiver));
} }
void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath) void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath)

View File

@ -55,6 +55,12 @@ namespace SHADE
LateUpdateRoutine(); LateUpdateRoutine();
void Execute(double dt) noexcept override final; void Execute(double dt) noexcept override final;
}; };
class SH_API GizmosDrawRoutine final : public SHSystemRoutine
{
public:
GizmosDrawRoutine();
void Execute(double dt) noexcept override final;
};
class SH_API FrameCleanUpRoutine final : public SHSystemRoutine class SH_API FrameCleanUpRoutine final : public SHSystemRoutine
{ {
public: public:
@ -250,6 +256,7 @@ namespace SHADE
CsFuncPtr csScriptsExecuteFixedUpdate = nullptr; CsFuncPtr csScriptsExecuteFixedUpdate = nullptr;
CsFuncPtr csScriptsExecuteUpdate = nullptr; CsFuncPtr csScriptsExecuteUpdate = nullptr;
CsFuncPtr csScriptsExecuteLateUpdate = nullptr; CsFuncPtr csScriptsExecuteLateUpdate = nullptr;
CsFuncPtr csScriptsExecuteDrawGizmos = nullptr;
CsFuncPtr csScriptsExecutePhysicsEvents = nullptr; CsFuncPtr csScriptsExecutePhysicsEvents = nullptr;
CsFuncPtr csScriptsFrameCleanUp = nullptr; CsFuncPtr csScriptsFrameCleanUp = nullptr;
CsScriptManipFuncPtr csScriptsAdd = nullptr; CsScriptManipFuncPtr csScriptsAdd = nullptr;
@ -260,6 +267,7 @@ namespace SHADE
// - Events // - Events
CsEventRelayFuncPtr csColliderOnListChanged = nullptr; CsEventRelayFuncPtr csColliderOnListChanged = nullptr;
CsEventRelayFuncPtr csColliderOnRemoved = nullptr; CsEventRelayFuncPtr csColliderOnRemoved = nullptr;
CsEventRelayFuncPtr csSceneNodeChildrenChanged = nullptr;
// - Editor // - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
CsFuncPtr csEditorUndo = nullptr; CsFuncPtr csEditorUndo = nullptr;
@ -272,6 +280,8 @@ namespace SHADE
SHEventHandle onColliderAdded(SHEventPtr eventPtr); SHEventHandle onColliderAdded(SHEventPtr eventPtr);
SHEventHandle onColliderRemoved(SHEventPtr eventPtr); SHEventHandle onColliderRemoved(SHEventPtr eventPtr);
SHEventHandle onColliderComponentRemoved(SHEventPtr eventPtr); SHEventHandle onColliderComponentRemoved(SHEventPtr eventPtr);
SHEventHandle onSceneNodeChildrenAdded(SHEventPtr eventPtr);
SHEventHandle onSceneNodeChildrenRemoved(SHEventPtr eventPtr);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

Some files were not shown because too many files have changed in this diff Show More