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

This commit is contained in:
Diren D Bharwani 2022-11-25 12:16:13 +08:00
commit 7f9f2bd194
23 changed files with 9113 additions and 190 deletions

View File

@ -1,4 +1,4 @@
Start in Fullscreen: false Start in Fullscreen: false
Starting Scene ID: 97158628 Starting Scene ID: 86098106
Window Size: {x: 1920, y: 1080} Window Size: {x: 1920, y: 1080}
Window Title: SHADE Engine Window Title: SHADE Engine

View File

@ -8599,6 +8599,7 @@
Arm Length: 1 Arm Length: 1
Look At Camera Origin: true Look At Camera Origin: true
Target Offset: {x: 0, y: 0, z: 0} Target Offset: {x: 0, y: 0, z: 0}
Camera Collision: true
IsActive: true IsActive: true
Scripts: Scripts:
- Type: SHADE_Scripting.ThirdPersonCamera - Type: SHADE_Scripting.ThirdPersonCamera
@ -8675,15 +8676,7 @@
Scripts: Scripts:
- Type: Homeowner1 - Type: Homeowner1
Enabled: true Enabled: true
player: 2 waypointsPool: 51000
waypoints:
- [2.70000005, 0, -2]
- [-0.300000012, 0, -2.70000005]
- [-2, 0, -3.79999995]
- [-4, 0, -2.0999999]
- [-2.9000001, 0, 2.4000001]
- [-1, 0, 4]
- [2.70000005, 0, 4]
patrolSpeed: 1 patrolSpeed: 1
chaseSpeed: 2 chaseSpeed: 2
turningSpeed: 5 turningSpeed: 5

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
Name: MainGameWithAIFixed
ID: 89830755
Type: 5

View File

@ -40,15 +40,7 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree
//awake and update functions //awake and update functions
//the only segment in the entire AI that is dependent on the engine //the only segment in the entire AI that is dependent on the engine
private bool test = false;
protected override void awake() protected override void awake()
{
AwakeCall();
}
protected override void start()
{ {
_root = CreateTree(); _root = CreateTree();
_root.InitialiseNode(this); _root.InitialiseNode(this);
@ -59,7 +51,7 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree
_root?.Evaluate(); _root?.Evaluate();
Tick(); Tick();
} }
protected abstract void AwakeCall();
protected abstract void Initialise(); protected abstract void Initialise();
protected abstract void Tick(); protected abstract void Tick();
} }

View File

@ -28,14 +28,13 @@ public partial class Homeowner1 : BehaviourTree
private BehaviourTreeEvents _events { get; set; } private BehaviourTreeEvents _events { get; set; }
public override BehaviourTreeEvents events { get => _events; } public override BehaviourTreeEvents events { get => _events; }
[Tooltip("The player the AI should chase and attempt to capture")]
public GameObject player;
//PATROL FIELDS/////////////////////////////////////////////////////////////// //PATROL FIELDS///////////////////////////////////////////////////////////////
[SerializeField] [SerializeField]
[Tooltip("The list of waypoints for the AI to cycle around")] [Tooltip("The list of waypoints for the AI to cycle around")]
private List<Vector3> waypoints = new List<Vector3>(); private GameObject waypointsPool;
private List<GameObject> waypoints;
[SerializeField] [SerializeField]
[Tooltip("The AI will patrol at this speed")] [Tooltip("The AI will patrol at this speed")]
@ -79,32 +78,18 @@ public partial class Homeowner1 : BehaviourTree
//AI tree //AI tree
public partial class Homeowner1 : BehaviourTree public partial class Homeowner1 : BehaviourTree
{ {
Transform _thisTransform = null;
RigidBody _thisRigidbody = null;
GameObject _playerObject;
private LeafPatrol leafPatrol;
protected override void AwakeCall()
{
_thisTransform = GetComponent<Transform>();
if (!_thisTransform)
Debug.LogError("EMPTY TRANSFORM");
_thisRigidbody = GetComponent<RigidBody>();
if (!_thisRigidbody)
Debug.LogError("EMPTY RIGIDBODY");
if (!player)
Debug.Log("PLAYER MISSING!");
//_playerObject = GameObject.Find("Player").GetValueOrDefault();
}
//Called at the start //Called at the start
protected override void Initialise() protected override void Initialise()
{ {
_events = new Homeowner1Events(this); _events = new Homeowner1Events(this);
events.Initialise(); events.Initialise();
//Initialise the waypoints here
if (waypointsPool)
{
waypoints = (List<GameObject>)waypointsPool.GetChildren();
SetData("waypoints", waypoints);
}
} }
//Called every tick //Called every tick
@ -112,8 +97,8 @@ public partial class Homeowner1 : BehaviourTree
{ {
events.Tick(); events.Tick();
//Footsteps SFX, move them somewhere else soon
float velocity = GetComponent<RigidBody>().LinearVelocity.GetMagnitude(); float velocity = GetComponent<RigidBody>().LinearVelocity.GetMagnitude();
leafPatrol.waypoints = waypoints;
footstepTimeRemaining -= velocity * Time.DeltaTimeF; footstepTimeRemaining -= velocity * Time.DeltaTimeF;
if (footstepTimeRemaining < 0.0f) if (footstepTimeRemaining < 0.0f)
@ -128,22 +113,20 @@ public partial class Homeowner1 : BehaviourTree
//The tree is called from the root every tick //The tree is called from the root every tick
protected override BehaviourTreeNode CreateTree() protected override BehaviourTreeNode CreateTree()
{ {
leafPatrol = new LeafPatrol("Patrol", _thisTransform, waypoints, patrolSpeed, turningSpeed, _thisRigidbody);
//Start from the root, structure it like this to make it look like a tree //Start from the root, structure it like this to make it look like a tree
BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List<BehaviourTreeNode> BehaviourTreeNode root = new BehaviourTreeSelector("Root", new List<BehaviourTreeNode>
{ {
/* new BehaviourTreeSequence("Alerted", new List<BehaviourTreeNode> new BehaviourTreeSequence("Alerted", new List<BehaviourTreeNode>
{ {
new LeafSearch("SearchFOV", _thisTransform, eyeOffset, sightDistance), new LeafSearch("SearchFOV", GetComponent<Transform>(), eyeOffset, sightDistance),
new BehaviourTreeSequence("CatchPlayer", new List<BehaviourTreeNode> new BehaviourTreeSequence("CatchPlayer", new List<BehaviourTreeNode>
{ {
new LeafChase("Chasing", _thisTransform, _thisRigidbody, chaseSpeed, turningSpeed, distanceToCapture, captureTime), new LeafChase("Chasing", GetComponent<Transform>(), GetComponent<RigidBody>(), chaseSpeed, turningSpeed, distanceToCapture, captureTime),
new LeafAttack("Attacking") new LeafAttack("Attacking", GameObject.Find("Player").GetValueOrDefault())
}) })
}),*/ }),
leafPatrol new LeafPatrol("Patrol", GetComponent<Transform>(), patrolSpeed, turningSpeed, GetComponent<RigidBody>())
}); });
return root; return root;
} }
} }

View File

@ -28,28 +28,25 @@ public partial class LeafAttack : BehaviourTreeNode
//FUNCTIONS //FUNCTIONS
public partial class LeafAttack : BehaviourTreeNode public partial class LeafAttack : BehaviourTreeNode
{ {
public LeafAttack(string name) : base (name) public LeafAttack(string name, GameObject p) : base (name)
{ {
//player = p; player = p;
} }
public override BehaviourTreeNodeStatus Evaluate() public override BehaviourTreeNodeStatus Evaluate()
{ {
{
if (!player)
{
player = GameObject.Find("Player").GetValueOrDefault();
Debug.Log("HERE2");
if (!player) { return BehaviourTreeNodeStatus.FAILURE; }
}
}
//Debug.LogWarning("LeafAttack"); //Debug.LogWarning("LeafAttack");
//Fail if no target in blackboard? //Fail if no target in blackboard?
onEnter(BehaviourTreeNodeStatus.RUNNING); onEnter(BehaviourTreeNodeStatus.RUNNING);
//Succeed when stand in hurt box for long enough //Succeed when stand in hurt box for long enough
object timeObj = GetNodeData("captureTimeLeft");
if (timeObj == null)
{
return BehaviourTreeNodeStatus.FAILURE;
}
float captureTime = (float)GetNodeData("captureTimeLeft"); float captureTime = (float)GetNodeData("captureTimeLeft");
captureTime -= Time.DeltaTimeF; captureTime -= Time.DeltaTimeF;
SetNodeData("captureTimeLeft", captureTime); SetNodeData("captureTimeLeft", captureTime);

View File

@ -22,10 +22,10 @@ public partial class LeafPatrol : BehaviourTreeNode
{ {
//Waypoints and movement //Waypoints and movement
private Transform transform; private Transform transform;
public List<Vector3> waypoints; private List<GameObject> waypoints;
private RigidBody rb; private RigidBody rb;
private float patrolSpeed = 1.0f; private float patrolSpeed;
private float turningSpeed = 5.0f; private float turningSpeed;
private float retreatTimer = 0.0f; private float retreatTimer = 0.0f;
private int currentWaypointIndex = 0; private int currentWaypointIndex = 0;
private bool retreatState = false; private bool retreatState = false;
@ -42,10 +42,9 @@ public partial class LeafPatrol : BehaviourTreeNode
//Constructor, establish values here //Constructor, establish values here
//Despite inheriting from BehaviourTreeNode, we don't have children to this //Despite inheriting from BehaviourTreeNode, we don't have children to this
//node, and hence we do not need to inherit its constructors //node, and hence we do not need to inherit its constructors
public LeafPatrol(string name, Transform t, List<Vector3> wps, float patrolSpeed, float turnSpeed, RigidBody rb) : base(name) public LeafPatrol(string name, Transform t, float patrolSpeed, float turnSpeed, RigidBody rb) : base(name)
{ {
transform = t; transform = t;
waypoints = wps;
this.patrolSpeed = patrolSpeed; this.patrolSpeed = patrolSpeed;
turningSpeed = turnSpeed; turningSpeed = turnSpeed;
this.rb = rb; this.rb = rb;
@ -59,6 +58,10 @@ public partial class LeafPatrol : BehaviourTreeNode
{ {
//Debug.LogWarning("LeafPatrol"); //Debug.LogWarning("LeafPatrol");
onEnter(BehaviourTreeNodeStatus.RUNNING); onEnter(BehaviourTreeNodeStatus.RUNNING);
if(GetNodeData("currentWaypointIndex") == null)
{
SetNodeData("currentWaypointIndex", 0);
}
if (isWaiting) DelayAtWaypoint(); if (isWaiting) DelayAtWaypoint();
else MoveToWaypoint(); else MoveToWaypoint();
@ -80,27 +83,31 @@ public partial class LeafPatrol : BehaviourTreeNode
return; return;
} }
Vector3 remainingDistance = Vector3.Zero; object waypoint = GetNodeData("waypoints");
Debug.Log($"{waypoints.Count}"); if (waypoint == null)
if (currentWaypointIndex > 0)
{ {
return;
}
Vector3 targetPosition = waypoints[currentWaypointIndex]; waypoints = (List<GameObject>)waypoint;
Vector3 targetPosition = waypoints[currentWaypointIndex].GetComponent<Transform>().GlobalPosition;
//Reach waypoint by X and Z being near enough //Reach waypoint by X and Z being near enough
//Do not consider Y of waypoints yet //Do not consider Y of waypoints yet
remainingDistance = targetPosition - transform.GlobalPosition; Vector3 remainingDistance = targetPosition - transform.GlobalPosition;
remainingDistance.y = 0.0f; remainingDistance.y = 0.0f;
}
//Reached waypoint, cycle //Reached waypoint, cycle
if (remainingDistance.GetSqrMagnitude() < 0.1f) if (remainingDistance.GetSqrMagnitude() < 0.1f)
{ {
//Cycle waypoints //Cycle waypoints
++currentWaypointIndex; ++currentWaypointIndex;
if (currentWaypointIndex >= waypoints.Count) if (currentWaypointIndex >= waypoints.Count())
currentWaypointIndex = 0; currentWaypointIndex = 0;
//Write to blackboard
SetNodeData("currentWaypointIndex", currentWaypointIndex);
waitCounter = 0.0f; waitCounter = 0.0f;
isWaiting = true; isWaiting = true;
} }
@ -115,7 +122,7 @@ public partial class LeafPatrol : BehaviourTreeNode
//Get the difference vector to the waypoint //Get the difference vector to the waypoint
//Debug.Log("Current Waypoint " + waypoints[currentWaypointIndex].x.ToString() + " " + waypoints[currentWaypointIndex].y.ToString() + " " + waypoints[currentWaypointIndex].z.ToString()); //Debug.Log("Current Waypoint " + waypoints[currentWaypointIndex].x.ToString() + " " + waypoints[currentWaypointIndex].y.ToString() + " " + waypoints[currentWaypointIndex].z.ToString());
//Debug.Log("AI is at " + transform.GlobalPosition.x.ToString() + " " + transform.GlobalPosition.y.ToString() + " " + transform.GlobalPosition.z.ToString()); //Debug.Log("AI is at " + transform.GlobalPosition.x.ToString() + " " + transform.GlobalPosition.y.ToString() + " " + transform.GlobalPosition.z.ToString());
Vector3 normalisedDifference = waypoints[currentWaypointIndex] - transform.GlobalPosition; Vector3 normalisedDifference = targetPosition - transform.GlobalPosition;
normalisedDifference.y = 0.0f; //Do not move vertically normalisedDifference.y = 0.0f; //Do not move vertically
normalisedDifference /= normalisedDifference.GetMagnitude(); normalisedDifference /= normalisedDifference.GetMagnitude();
//Debug.Log("Normalised Difference x " + normalisedDifference.x.ToString() + " z " + normalisedDifference.z.ToString()); //Debug.Log("Normalised Difference x " + normalisedDifference.x.ToString() + " z " + normalisedDifference.z.ToString());

View File

@ -21,11 +21,10 @@ using System.Threading.Tasks;
//VARIABLES HERE //VARIABLES HERE
public partial class LeafSearch : BehaviourTreeNode public partial class LeafSearch : BehaviourTreeNode
{ {
private GameObject player;
private Transform transform; private Transform transform;
private Vector3 eyeOffset; private Vector3 eyeOffset;
private float sightDistance; private float sightDistance;
private GameObject? player; //To be searched for and marked
} }
//FUNCTIONS HERE //FUNCTIONS HERE
@ -33,29 +32,57 @@ public partial class LeafSearch : BehaviourTreeNode
{ {
public LeafSearch(string name, Transform t, Vector3 eo, float sDist) : base(name) public LeafSearch(string name, Transform t, Vector3 eo, float sDist) : base(name)
{ {
Debug.Log($"===============================PLAYER: {t}");
// player = p;
transform = t; transform = t;
eyeOffset = eo; eyeOffset = eo;
sightDistance = sDist; sightDistance = sDist;
player = null;
}
//Helper, find the nearest unobstructed waypoint to return to when chase is over
private void reevaluateWaypoint()
{
Debug.Log("Reevaluating Waypoints");
List<GameObject> waypoints = (List<GameObject>)GetNodeData("waypoints");
if (waypoints == null)
{
SetNodeData("currentWaypointIndex", 0);
return;
}
int nearestWaypointIndex = 0;
for (int i = 0; i < waypoints.Count; ++i)
{
if ((transform.GlobalPosition - waypoints[i].GetComponent<Transform>().GlobalPosition).GetSqrMagnitude() <
(transform.GlobalPosition - waypoints[nearestWaypointIndex].GetComponent<Transform>().GlobalPosition).GetSqrMagnitude())
{
nearestWaypointIndex = i;
}
}
SetNodeData("currentWaypointIndex", nearestWaypointIndex);
} }
public override BehaviourTreeNodeStatus Evaluate() public override BehaviourTreeNodeStatus Evaluate()
{ {
{
if (!player)
{
player = GameObject.Find("Player").GetValueOrDefault();
if (!player) { Debug.Log("HERE1"); return BehaviourTreeNodeStatus.FAILURE; }
}
}
//Debug.LogWarning("LeafSearch"); //Debug.LogWarning("LeafSearch");
onEnter(BehaviourTreeNodeStatus.RUNNING); onEnter(BehaviourTreeNodeStatus.RUNNING);
//Search for player
player = GameObject.Find("Player");
//Automatically fail if no player is found
if (player == null)
{
SetNodeData("isAlert", false);
status = BehaviourTreeNodeStatus.FAILURE;
onExit(BehaviourTreeNodeStatus.FAILURE);
return status;
}
else
{
//Fail if unable to find a player //Fail if unable to find a player
//Get player's transform //Get player's transform
Transform plrT = player.GetComponent<Transform>(); Transform plrT = player.GetValueOrDefault().GetComponent<Transform>();
//DELETE THIS //DELETE THIS
//Debug.Log("X " + MathF.Sin(transform.LocalEulerAngles.y).ToString() + " Z " + MathF.Cos(transform.LocalEulerAngles.y).ToString()); //Debug.Log("X " + MathF.Sin(transform.LocalEulerAngles.y).ToString() + " Z " + MathF.Cos(transform.LocalEulerAngles.y).ToString());
@ -70,6 +97,7 @@ public partial class LeafSearch : BehaviourTreeNode
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true)
{ {
Debug.Log("AI play unalert hmm"); Debug.Log("AI play unalert hmm");
reevaluateWaypoint();
} }
SetNodeData("isAlert", false); SetNodeData("isAlert", false);
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
@ -89,6 +117,7 @@ public partial class LeafSearch : BehaviourTreeNode
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true)
{ {
Debug.Log("AI play unalert hmm"); Debug.Log("AI play unalert hmm");
reevaluateWaypoint();
} }
SetNodeData("isAlert", false); SetNodeData("isAlert", false);
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
@ -114,6 +143,7 @@ public partial class LeafSearch : BehaviourTreeNode
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true) if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true)
{ {
Debug.Log("AI play unalert hmm"); Debug.Log("AI play unalert hmm");
reevaluateWaypoint();
} }
SetNodeData("isAlert", false); SetNodeData("isAlert", false);
status = BehaviourTreeNodeStatus.FAILURE; status = BehaviourTreeNodeStatus.FAILURE;
@ -140,4 +170,5 @@ public partial class LeafSearch : BehaviourTreeNode
onExit(BehaviourTreeNodeStatus.SUCCESS); onExit(BehaviourTreeNodeStatus.SUCCESS);
return status; return status;
} }
}
} }

View File

@ -12,7 +12,7 @@ public class MainMenu : Script
if (Input.GetKey(Input.KeyCode.Space)) if (Input.GetKey(Input.KeyCode.Space))
{ {
Audio.PlaySFXOnce2D("event:/UI/mouse_down_element"); Audio.PlaySFXOnce2D("event:/UI/mouse_down_element");
SceneManager.ChangeScene(86098106); SceneManager.ChangeScene(89830755);
Audio.StopAllSounds(); Audio.StopAllSounds();
} }

View File

@ -7,8 +7,8 @@ namespace SHADE
{ {
SHCameraArmComponent::SHCameraArmComponent() SHCameraArmComponent::SHCameraArmComponent()
:pitch(0.0f), yaw(0.0f), armLength(1.0f),offset(), dirty(true), lookAtCameraOrigin(true) :pitch(0.0f), yaw(0.0f), armLength(1.0f), offset(), enableCameraCollision(false), lookAtCameraOrigin(true)
, targetOffset(0.0f) , targetOffset(0.0f),ray()
{ {
} }
@ -39,22 +39,23 @@ namespace SHADE
return targetOffset; return targetOffset;
} }
void SHCameraArmComponent::SetPitch(float pitch) noexcept void SHCameraArmComponent::SetPitch(float pitch) noexcept
{ {
this->pitch = pitch; this->pitch = pitch;
dirty = true;
} }
void SHCameraArmComponent::SetYaw(float yaw) noexcept void SHCameraArmComponent::SetYaw(float yaw) noexcept
{ {
this->yaw = yaw; this->yaw = yaw;
dirty = true; //dirty = true;
} }
void SHCameraArmComponent::SetArmLength(float length) noexcept void SHCameraArmComponent::SetArmLength(float length) noexcept
{ {
this->armLength = length; this->armLength = length;
dirty = true; //dirty = true;
} }
void SHCameraArmComponent::SetTargetOffset(SHVec3 offset) noexcept void SHCameraArmComponent::SetTargetOffset(SHVec3 offset) noexcept
@ -62,6 +63,8 @@ namespace SHADE
this->targetOffset = offset; this->targetOffset = offset;
} }
}//namespace SHADE }//namespace SHADE
@ -76,6 +79,7 @@ RTTR_REGISTRATION
.property("Arm Length", &SHCameraArmComponent::GetArmLength, &SHCameraArmComponent::SetArmLength) .property("Arm Length", &SHCameraArmComponent::GetArmLength, &SHCameraArmComponent::SetArmLength)
.property("Look At Camera Origin", &SHCameraArmComponent::lookAtCameraOrigin) .property("Look At Camera Origin", &SHCameraArmComponent::lookAtCameraOrigin)
.property("Target Offset", &SHCameraArmComponent::GetTargetOffset, &SHCameraArmComponent::SetTargetOffset) .property("Target Offset", &SHCameraArmComponent::GetTargetOffset, &SHCameraArmComponent::SetTargetOffset)
.property("Camera Collision", &SHCameraArmComponent::enableCameraCollision)
; ;
} }

View File

@ -5,9 +5,14 @@
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "SH_API.h" #include "SH_API.h"
#include "Math/SHRay.h"
namespace SHADE namespace SHADE
{ {
class SHBox;
class SHRay;
class SH_API SHCameraArmComponent final: public SHComponent class SH_API SHCameraArmComponent final: public SHComponent
{ {
private: private:
@ -15,15 +20,18 @@ namespace SHADE
float yaw; float yaw;
float armLength; float armLength;
bool dirty;
SHVec3 offset; SHVec3 offset;
SHVec3 targetOffset; SHVec3 targetOffset;
SHRay ray;
public: public:
friend class SHCameraSystem; friend class SHCameraSystem;
SHCameraArmComponent(); SHCameraArmComponent();
virtual ~SHCameraArmComponent() = default; virtual ~SHCameraArmComponent() = default;
bool lookAtCameraOrigin; bool lookAtCameraOrigin;
bool enableCameraCollision;
//Getters //Getters
//SHMatrix const& GetMatrix() const noexcept; //SHMatrix const& GetMatrix() const noexcept;
SHVec3 const& GetOffset() const noexcept; SHVec3 const& GetOffset() const noexcept;
@ -32,11 +40,13 @@ namespace SHADE
float GetArmLength() const noexcept; float GetArmLength() const noexcept;
SHVec3 GetTargetOffset() const noexcept; SHVec3 GetTargetOffset() const noexcept;
//Setters //Setters
void SetPitch(float pitch) noexcept; void SetPitch(float pitch) noexcept;
void SetYaw(float yaw) noexcept; void SetYaw(float yaw) noexcept;
void SetArmLength(float length) noexcept; void SetArmLength(float length) noexcept;
void SetTargetOffset(SHVec3 offset)noexcept; void SetTargetOffset(SHVec3 offset) noexcept;
protected: protected:

View File

@ -10,6 +10,10 @@
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "Math/Geometry/SHBox.h"
#include "Math/SHRay.h"
#include "Physics/System/SHPhysicsSystem.h"
namespace SHADE namespace SHADE
{ {
@ -96,7 +100,7 @@ namespace SHADE
if (editorCameraArm.armLength < 1.0f) if (editorCameraArm.armLength < 1.0f)
editorCameraArm.armLength = 1.0f; editorCameraArm.armLength = 1.0f;
UpdatePivotArmComponent(editorCameraArm); UpdateCameraArmComponent(editorCameraArm);
editorCamera.offset = editorCameraArm.GetOffset(); editorCamera.offset = editorCameraArm.GetOffset();
@ -132,11 +136,13 @@ namespace SHADE
return &editorCamera; return &editorCamera;
} }
void SHCameraSystem::UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept void SHCameraSystem::UpdateCameraArmComponent(SHCameraArmComponent& pivot) noexcept
{
if (pivot.dirty)
{ {
SHVec3 offset{ 0.0f,0.0f, pivot.GetArmLength() }; SHVec3 offset{ 0.0f,0.0f, pivot.GetArmLength() };
offset = SHVec3::RotateX(offset, -(SHMath::DegreesToRadians(pivot.GetPitch()))); offset = SHVec3::RotateX(offset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
offset = SHVec3::RotateY(offset, (SHMath::DegreesToRadians(pivot.GetYaw()))); offset = SHVec3::RotateY(offset, (SHMath::DegreesToRadians(pivot.GetYaw())));
@ -145,10 +151,61 @@ namespace SHADE
//pivot.rtMatrix = SHMatrix::RotateX(SHMath::DegreesToRadians(pivot.GetPitch())) //pivot.rtMatrix = SHMatrix::RotateX(SHMath::DegreesToRadians(pivot.GetPitch()))
// * SHMatrix::RotateY(SHMath::DegreesToRadians(pivot.GetYaw())) // * SHMatrix::RotateY(SHMath::DegreesToRadians(pivot.GetYaw()))
// * SHMatrix::Translate(SHVec3(0.0f , 0.0f, pivot.GetArmLength())); // * SHMatrix::Translate(SHVec3(0.0f , 0.0f, pivot.GetArmLength()));
pivot.offset = offset; pivot.offset = offset;
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); if (!pivot.enableCameraCollision)
{
return;
} }
SHCameraComponent* camera = SHComponentManager::GetComponent_s<SHCameraComponent>(pivot.GetEID());
SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(pivot.GetEID());
auto physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (camera == nullptr || transform == nullptr)
return;
/*if (SHComponentManager::HasComponent<SHTransformComponent>(camera->GetEID()) == true && camera != &editorCamera)
{
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(camera->GetEID());
SHVec3 rotation = transform->GetWorldRotation();
camera->pitch = SHMath::RadiansToDegrees(rotation.x);
camera->yaw = SHMath::RadiansToDegrees(rotation.y);
camera->roll = SHMath::RadiansToDegrees(rotation.z);
camera->position = transform->GetWorldPosition();
camera->dirtyView = true;
}*/
pivot.ray.position = camera->GetPosition() + pivot.targetOffset;
pivot.ray.direction = SHVec3::Normalise((camera->position + offset)- pivot.ray.position);
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
auto result = physicsSystem->Raycast(pivot.ray );
if (result && result.distance < pivot.GetArmLength())
{
SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
pivot.offset = newOffset;
//SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
}
else
{
//SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
}
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix);
} }
@ -291,7 +348,7 @@ namespace SHADE
for (auto& pivot : pivotDense) for (auto& pivot : pivotDense)
{ {
if(SHSceneManager::CheckNodeAndComponentsActive<SHCameraArmComponent>(pivot.GetEID())) if(SHSceneManager::CheckNodeAndComponentsActive<SHCameraArmComponent>(pivot.GetEID()))
system->UpdatePivotArmComponent(pivot); system->UpdateCameraArmComponent(pivot);
} }
for (auto& cam : dense) for (auto& cam : dense)
@ -390,7 +447,9 @@ namespace SHADE
} }
void SHCameraSystem::SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept void SHCameraSystem::SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept
{ {
SHVec3 pos;
DecomposeViewMatrix(viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position); DecomposeViewMatrix(viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
camera.dirtyView = true; camera.dirtyView = true;
} }

View File

@ -26,7 +26,7 @@ namespace SHADE
void UpdateCameraComponent(SHCameraComponent& camera) noexcept; void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
void UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept; void UpdateCameraArmComponent(SHCameraArmComponent& pivot) noexcept;

View File

@ -197,12 +197,18 @@ namespace SHADE
if (BUILD_SUCCESS) if (BUILD_SUCCESS)
{ {
// Copy to built dll to the working directory and replace // Copy to built dll to the working directory and replace
std::filesystem::copy_file("./tmp/SHADE_Scripting.dll", "SHADE_Scripting.dll", std::filesystem::copy_options::overwrite_existing); if (!copyFile("./tmp/SHADE_Scripting.dll", "SHADE_Scripting.dll", std::filesystem::copy_options::overwrite_existing))
{
SHLOG_ERROR("[ScriptEngine] Failed to replace scripts assembly. Scripts will remain outdated.");
}
// If debug, we want to copy the PDB so that we can do script debugging // If debug, we want to copy the PDB so that we can do script debugging
if (debug) if (debug)
{ {
std::filesystem::copy_file("./tmp/SHADE_Scripting.pdb", "SHADE_Scripting.pdb", std::filesystem::copy_options::overwrite_existing); if (!copyFile("./tmp/SHADE_Scripting.pdb", "SHADE_Scripting.pdb", std::filesystem::copy_options::overwrite_existing))
{
SHLOG_WARNING("[ScriptEngine] Breakpoint debugging will not work as PDB cannot be updated. If you are currently debugging, stop the debugger first.");
}
} }
oss << "[ScriptEngine] Successfully built Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!"; oss << "[ScriptEngine] Successfully built Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
@ -591,6 +597,19 @@ namespace SHADE
return false; return false;
} }
bool SHScriptEngine::copyFile(const std::filesystem::path& from, const std::filesystem::path& to, const std::filesystem::copy_options options) noexcept
{
try
{
return std::filesystem::copy_file(from, to, options);
}
catch (std::exception& e)
{
SHLOG_ERROR("[ScriptEngine] Failed to copy file {} ({})", to.string(), std::string(e.what()));
return false;
}
}
DWORD SHScriptEngine::execProcess(const std::wstring& path, const std::wstring& args) DWORD SHScriptEngine::execProcess(const std::wstring& path, const std::wstring& args)
{ {
STARTUPINFOW startInfo; STARTUPINFOW startInfo;

View File

@ -319,6 +319,7 @@ namespace SHADE
/// <param name="filePath">File path to the file to check.</param> /// <param name="filePath">File path to the file to check.</param>
/// <returns> True if the file exists </returns> /// <returns> True if the file exists </returns>
static bool fileExists(const std::filesystem::path& filePath); static bool fileExists(const std::filesystem::path& filePath);
static bool copyFile(const std::filesystem::path& from, const std::filesystem::path& to, const std::filesystem::copy_options options) noexcept;
static DWORD execProcess(const std::wstring& path, const std::wstring& args); static DWORD execProcess(const std::wstring& path, const std::wstring& args);
static std::wstring generateBuildCommand(bool debug); static std::wstring generateBuildCommand(bool debug);
}; };

View File

@ -49,6 +49,16 @@ namespace SHADE
GetNativeComponent()->lookAtCameraOrigin = val; GetNativeComponent()->lookAtCameraOrigin = val;
} }
bool CameraArm::EnableCameraCollision::get()
{
return GetNativeComponent()->enableCameraCollision;
}
void CameraArm::EnableCameraCollision::set(bool val)
{
GetNativeComponent()->enableCameraCollision = val;
}
Vector3 CameraArm::TargetOffset::get() Vector3 CameraArm::TargetOffset::get()
{ {
return Convert::ToCLI(GetNativeComponent()->GetTargetOffset()); return Convert::ToCLI(GetNativeComponent()->GetTargetOffset());

View File

@ -36,6 +36,12 @@ namespace SHADE
void set(bool val); void set(bool val);
} }
property bool EnableCameraCollision
{
bool get();
void set(bool val);
}
property Vector3 TargetOffset property Vector3 TargetOffset
{ {
Vector3 get(); Vector3 get();

View File

@ -200,7 +200,16 @@ namespace SHADE
{ {
if (SHEditorUI::Button("Add Item")) if (SHEditorUI::Button("Add Item"))
{ {
System::Object^ obj = System::Activator::CreateInstance(listType); System::Object^ obj;
if (listType == System::String::typeid)
{
// Special case for string
obj = gcnew System::String("");
}
else
{
obj = System::Activator::CreateInstance(listType);
}
iList->Add(obj); iList->Add(obj);
registerUndoListAddAction(listType, iList, iList->Count - 1, obj); registerUndoListAddAction(listType, iList, iList->Count - 1, obj);
} }

View File

@ -74,7 +74,7 @@ namespace SHADE
// Add the script in // Add the script in
script->Initialize(GameObject(entity)); script->Initialize(GameObject(entity));
entityScriptList->Insert(System::Math::Clamp(index, 0, entityScriptList->Count), script); entityScriptList->Insert(System::Math::Clamp(index, 0, entityScriptList->Count), script);
if (Application::IsPlaying && !SHSceneManager::HasSceneChanged()) if (Application::IsPlaying && !isDeserialising)
{ {
// Only call immediately if we are in game and is not loading another scene // Only call immediately if we are in game and is not loading another scene
script->Awake(); script->Awake();
@ -423,6 +423,8 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void ScriptStore::Init() void ScriptStore::Init()
{ {
isDeserialising = false;
// Create an enumerable list of script types // Create an enumerable list of script types
refreshScriptTypeList(); refreshScriptTypeList();
// Get stored methods for interop variants of functions // Get stored methods for interop variants of functions
@ -724,6 +726,10 @@ namespace SHADE
bool ScriptStore::DeserialiseScripts(Entity entity, System::IntPtr yamlNodePtr) bool ScriptStore::DeserialiseScripts(Entity entity, System::IntPtr yamlNodePtr)
{ {
SAFE_NATIVE_CALL_BEGIN SAFE_NATIVE_CALL_BEGIN
// Flag that deserialization processs is ongoing
isDeserialising = true;
// Convert to pointer // Convert to pointer
YAML::Node* yamlNode = reinterpret_cast<YAML::Node*>(yamlNodePtr.ToPointer()); YAML::Node* yamlNode = reinterpret_cast<YAML::Node*>(yamlNodePtr.ToPointer());
@ -765,9 +771,16 @@ namespace SHADE
Debug::LogWarning("[ScriptStore] Script with unloaded type detected, skipping."); Debug::LogWarning("[ScriptStore] Script with unloaded type detected, skipping.");
} }
} }
// Unset flag for deserialization process
isDeserialising = false;
return true; return true;
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore") SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
// Unset flag for deserialization process
isDeserialising = false;
return false; return false;
} }

View File

@ -337,6 +337,7 @@ namespace SHADE
static ScriptSet disposalQueue; static ScriptSet disposalQueue;
static System::Collections::Generic::IEnumerable<System::Type^>^ scriptTypeList; static System::Collections::Generic::IEnumerable<System::Type^>^ scriptTypeList;
static System::Reflection::MethodInfo^ addScriptMethod; static System::Reflection::MethodInfo^ addScriptMethod;
static bool isDeserialising;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -279,7 +279,15 @@ namespace SHADE
for (int i = 0; i < LIST_SIZE; ++i) for (int i = 0; i < LIST_SIZE; ++i)
{ {
// Create the object // Create the object
System::Object^ obj = System::Activator::CreateInstance(elemType); System::Object^ obj;
if (elemType == System::String::typeid)
{
obj = gcnew System::String("");
}
else
{
obj = System::Activator::CreateInstance(elemType);
}
// Set it's value // Set it's value
if (varAssignYaml(obj, node[i])) if (varAssignYaml(obj, node[i]))

View File

@ -167,6 +167,10 @@ namespace SHADE
{ {
valueObj = 0; valueObj = 0;
} }
else
{
return false;
}
} }
else else
{ {
@ -181,6 +185,10 @@ namespace SHADE
valueObj = FieldType(); valueObj = FieldType();
} }
} }
else
{
return false;
}
} }
} }