Fixed transform updates to clear dirty flags appropriately #280
|
@ -1,4 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 97158628
|
||||
Starting Scene ID: 86098106
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
|
@ -8599,6 +8599,7 @@
|
|||
Arm Length: 1
|
||||
Look At Camera Origin: true
|
||||
Target Offset: {x: 0, y: 0, z: 0}
|
||||
Camera Collision: true
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: SHADE_Scripting.ThirdPersonCamera
|
||||
|
@ -8675,15 +8676,7 @@
|
|||
Scripts:
|
||||
- Type: Homeowner1
|
||||
Enabled: true
|
||||
player: 2
|
||||
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]
|
||||
waypointsPool: 51000
|
||||
patrolSpeed: 1
|
||||
chaseSpeed: 2
|
||||
turningSpeed: 5
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
Name: MainGameWithAIFixed
|
||||
ID: 89830755
|
||||
Type: 5
|
|
@ -40,15 +40,7 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree
|
|||
|
||||
//awake and update functions
|
||||
//the only segment in the entire AI that is dependent on the engine
|
||||
|
||||
private bool test = false;
|
||||
|
||||
protected override void awake()
|
||||
{
|
||||
AwakeCall();
|
||||
}
|
||||
|
||||
protected override void start()
|
||||
{
|
||||
_root = CreateTree();
|
||||
_root.InitialiseNode(this);
|
||||
|
@ -59,7 +51,7 @@ namespace SHADE_Scripting.AIBehaviour.BehaviourTree
|
|||
_root?.Evaluate();
|
||||
Tick();
|
||||
}
|
||||
protected abstract void AwakeCall();
|
||||
|
||||
protected abstract void Initialise();
|
||||
protected abstract void Tick();
|
||||
}
|
||||
|
|
|
@ -28,14 +28,13 @@ public partial class Homeowner1 : BehaviourTree
|
|||
private BehaviourTreeEvents _events { get; set; }
|
||||
public override BehaviourTreeEvents events { get => _events; }
|
||||
|
||||
[Tooltip("The player the AI should chase and attempt to capture")]
|
||||
public GameObject player;
|
||||
|
||||
//PATROL FIELDS///////////////////////////////////////////////////////////////
|
||||
|
||||
[SerializeField]
|
||||
[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]
|
||||
[Tooltip("The AI will patrol at this speed")]
|
||||
|
@ -79,32 +78,18 @@ public partial class Homeowner1 : BehaviourTree
|
|||
//AI tree
|
||||
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
|
||||
protected override void Initialise()
|
||||
{
|
||||
_events = new Homeowner1Events(this);
|
||||
events.Initialise();
|
||||
|
||||
//Initialise the waypoints here
|
||||
if (waypointsPool)
|
||||
{
|
||||
waypoints = (List<GameObject>)waypointsPool.GetChildren();
|
||||
SetData("waypoints", waypoints);
|
||||
}
|
||||
}
|
||||
|
||||
//Called every tick
|
||||
|
@ -112,8 +97,8 @@ public partial class Homeowner1 : BehaviourTree
|
|||
{
|
||||
events.Tick();
|
||||
|
||||
//Footsteps SFX, move them somewhere else soon
|
||||
float velocity = GetComponent<RigidBody>().LinearVelocity.GetMagnitude();
|
||||
leafPatrol.waypoints = waypoints;
|
||||
|
||||
footstepTimeRemaining -= velocity * Time.DeltaTimeF;
|
||||
if (footstepTimeRemaining < 0.0f)
|
||||
|
@ -128,22 +113,20 @@ public partial class Homeowner1 : BehaviourTree
|
|||
//The tree is called from the root every tick
|
||||
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
|
||||
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 LeafChase("Chasing", _thisTransform, _thisRigidbody, chaseSpeed, turningSpeed, distanceToCapture, captureTime),
|
||||
new LeafAttack("Attacking")
|
||||
new LeafChase("Chasing", GetComponent<Transform>(), GetComponent<RigidBody>(), chaseSpeed, turningSpeed, distanceToCapture, captureTime),
|
||||
new LeafAttack("Attacking", GameObject.Find("Player").GetValueOrDefault())
|
||||
})
|
||||
}),*/
|
||||
leafPatrol
|
||||
}),
|
||||
new LeafPatrol("Patrol", GetComponent<Transform>(), patrolSpeed, turningSpeed, GetComponent<RigidBody>())
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
|
@ -28,28 +28,25 @@ public partial class LeafAttack : BehaviourTreeNode
|
|||
//FUNCTIONS
|
||||
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()
|
||||
{
|
||||
{
|
||||
if (!player)
|
||||
{
|
||||
player = GameObject.Find("Player").GetValueOrDefault();
|
||||
Debug.Log("HERE2");
|
||||
if (!player) { return BehaviourTreeNodeStatus.FAILURE; }
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.LogWarning("LeafAttack");
|
||||
//Fail if no target in blackboard?
|
||||
|
||||
onEnter(BehaviourTreeNodeStatus.RUNNING);
|
||||
|
||||
//Succeed when stand in hurt box for long enough
|
||||
object timeObj = GetNodeData("captureTimeLeft");
|
||||
if (timeObj == null)
|
||||
{
|
||||
return BehaviourTreeNodeStatus.FAILURE;
|
||||
}
|
||||
|
||||
float captureTime = (float)GetNodeData("captureTimeLeft");
|
||||
captureTime -= Time.DeltaTimeF;
|
||||
SetNodeData("captureTimeLeft", captureTime);
|
||||
|
|
|
@ -22,10 +22,10 @@ public partial class LeafPatrol : BehaviourTreeNode
|
|||
{
|
||||
//Waypoints and movement
|
||||
private Transform transform;
|
||||
public List<Vector3> waypoints;
|
||||
private List<GameObject> waypoints;
|
||||
private RigidBody rb;
|
||||
private float patrolSpeed = 1.0f;
|
||||
private float turningSpeed = 5.0f;
|
||||
private float patrolSpeed;
|
||||
private float turningSpeed;
|
||||
private float retreatTimer = 0.0f;
|
||||
private int currentWaypointIndex = 0;
|
||||
private bool retreatState = false;
|
||||
|
@ -42,10 +42,9 @@ public partial class LeafPatrol : BehaviourTreeNode
|
|||
//Constructor, establish values here
|
||||
//Despite inheriting from BehaviourTreeNode, we don't have children to this
|
||||
//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;
|
||||
waypoints = wps;
|
||||
this.patrolSpeed = patrolSpeed;
|
||||
turningSpeed = turnSpeed;
|
||||
this.rb = rb;
|
||||
|
@ -59,6 +58,10 @@ public partial class LeafPatrol : BehaviourTreeNode
|
|||
{
|
||||
//Debug.LogWarning("LeafPatrol");
|
||||
onEnter(BehaviourTreeNodeStatus.RUNNING);
|
||||
if(GetNodeData("currentWaypointIndex") == null)
|
||||
{
|
||||
SetNodeData("currentWaypointIndex", 0);
|
||||
}
|
||||
if (isWaiting) DelayAtWaypoint();
|
||||
else MoveToWaypoint();
|
||||
|
||||
|
@ -80,27 +83,31 @@ public partial class LeafPatrol : BehaviourTreeNode
|
|||
return;
|
||||
}
|
||||
|
||||
Vector3 remainingDistance = Vector3.Zero;
|
||||
Debug.Log($"{waypoints.Count}");
|
||||
if (currentWaypointIndex > 0)
|
||||
object waypoint = GetNodeData("waypoints");
|
||||
if (waypoint == null)
|
||||
{
|
||||
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
|
||||
//Do not consider Y of waypoints yet
|
||||
remainingDistance = targetPosition - transform.GlobalPosition;
|
||||
Vector3 remainingDistance = targetPosition - transform.GlobalPosition;
|
||||
remainingDistance.y = 0.0f;
|
||||
}
|
||||
|
||||
//Reached waypoint, cycle
|
||||
if (remainingDistance.GetSqrMagnitude() < 0.1f)
|
||||
{
|
||||
//Cycle waypoints
|
||||
++currentWaypointIndex;
|
||||
if (currentWaypointIndex >= waypoints.Count)
|
||||
if (currentWaypointIndex >= waypoints.Count())
|
||||
currentWaypointIndex = 0;
|
||||
|
||||
//Write to blackboard
|
||||
SetNodeData("currentWaypointIndex", currentWaypointIndex);
|
||||
|
||||
waitCounter = 0.0f;
|
||||
isWaiting = true;
|
||||
}
|
||||
|
@ -115,7 +122,7 @@ public partial class LeafPatrol : BehaviourTreeNode
|
|||
//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("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 /= normalisedDifference.GetMagnitude();
|
||||
//Debug.Log("Normalised Difference x " + normalisedDifference.x.ToString() + " z " + normalisedDifference.z.ToString());
|
||||
|
|
|
@ -21,11 +21,10 @@ using System.Threading.Tasks;
|
|||
//VARIABLES HERE
|
||||
public partial class LeafSearch : BehaviourTreeNode
|
||||
{
|
||||
private GameObject player;
|
||||
private Transform transform;
|
||||
private Vector3 eyeOffset;
|
||||
private float sightDistance;
|
||||
|
||||
private GameObject? player; //To be searched for and marked
|
||||
}
|
||||
|
||||
//FUNCTIONS HERE
|
||||
|
@ -33,29 +32,57 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
{
|
||||
public LeafSearch(string name, Transform t, Vector3 eo, float sDist) : base(name)
|
||||
{
|
||||
Debug.Log($"===============================PLAYER: {t}");
|
||||
// player = p;
|
||||
transform = t;
|
||||
eyeOffset = eo;
|
||||
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()
|
||||
{
|
||||
{
|
||||
if (!player)
|
||||
{
|
||||
player = GameObject.Find("Player").GetValueOrDefault();
|
||||
if (!player) { Debug.Log("HERE1"); return BehaviourTreeNodeStatus.FAILURE; }
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.LogWarning("LeafSearch");
|
||||
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
|
||||
//Get player's transform
|
||||
Transform plrT = player.GetComponent<Transform>();
|
||||
Transform plrT = player.GetValueOrDefault().GetComponent<Transform>();
|
||||
|
||||
//DELETE THIS
|
||||
//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)
|
||||
{
|
||||
Debug.Log("AI play unalert hmm");
|
||||
reevaluateWaypoint();
|
||||
}
|
||||
SetNodeData("isAlert", false);
|
||||
status = BehaviourTreeNodeStatus.FAILURE;
|
||||
|
@ -89,6 +117,7 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true)
|
||||
{
|
||||
Debug.Log("AI play unalert hmm");
|
||||
reevaluateWaypoint();
|
||||
}
|
||||
SetNodeData("isAlert", false);
|
||||
status = BehaviourTreeNodeStatus.FAILURE;
|
||||
|
@ -114,6 +143,7 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
if (GetNodeData("isAlert") != null && (bool)GetNodeData("isAlert") == true)
|
||||
{
|
||||
Debug.Log("AI play unalert hmm");
|
||||
reevaluateWaypoint();
|
||||
}
|
||||
SetNodeData("isAlert", false);
|
||||
status = BehaviourTreeNodeStatus.FAILURE;
|
||||
|
@ -141,3 +171,4 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
return status;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ public class MainMenu : Script
|
|||
if (Input.GetKey(Input.KeyCode.Space))
|
||||
{
|
||||
Audio.PlaySFXOnce2D("event:/UI/mouse_down_element");
|
||||
SceneManager.ChangeScene(86098106);
|
||||
SceneManager.ChangeScene(89830755);
|
||||
Audio.StopAllSounds();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ namespace SHADE
|
|||
{
|
||||
|
||||
SHCameraArmComponent::SHCameraArmComponent()
|
||||
:pitch(0.0f), yaw(0.0f), armLength(1.0f),offset(), dirty(true), lookAtCameraOrigin(true)
|
||||
, targetOffset(0.0f)
|
||||
:pitch(0.0f), yaw(0.0f), armLength(1.0f), offset(), enableCameraCollision(false), lookAtCameraOrigin(true)
|
||||
, targetOffset(0.0f),ray()
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -39,22 +39,23 @@ namespace SHADE
|
|||
return targetOffset;
|
||||
}
|
||||
|
||||
|
||||
void SHCameraArmComponent::SetPitch(float pitch) noexcept
|
||||
{
|
||||
this->pitch = pitch;
|
||||
dirty = true;
|
||||
|
||||
}
|
||||
|
||||
void SHCameraArmComponent::SetYaw(float yaw) noexcept
|
||||
{
|
||||
this->yaw = yaw;
|
||||
dirty = true;
|
||||
//dirty = true;
|
||||
}
|
||||
|
||||
void SHCameraArmComponent::SetArmLength(float length) noexcept
|
||||
{
|
||||
this->armLength = length;
|
||||
dirty = true;
|
||||
//dirty = true;
|
||||
}
|
||||
|
||||
void SHCameraArmComponent::SetTargetOffset(SHVec3 offset) noexcept
|
||||
|
@ -62,6 +63,8 @@ namespace SHADE
|
|||
this->targetOffset = offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}//namespace SHADE
|
||||
|
||||
|
||||
|
@ -76,6 +79,7 @@ RTTR_REGISTRATION
|
|||
.property("Arm Length", &SHCameraArmComponent::GetArmLength, &SHCameraArmComponent::SetArmLength)
|
||||
.property("Look At Camera Origin", &SHCameraArmComponent::lookAtCameraOrigin)
|
||||
.property("Target Offset", &SHCameraArmComponent::GetTargetOffset, &SHCameraArmComponent::SetTargetOffset)
|
||||
.property("Camera Collision", &SHCameraArmComponent::enableCameraCollision)
|
||||
;
|
||||
|
||||
}
|
|
@ -5,9 +5,14 @@
|
|||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "SH_API.h"
|
||||
#include "Math/SHRay.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
class SHBox;
|
||||
class SHRay;
|
||||
|
||||
class SH_API SHCameraArmComponent final: public SHComponent
|
||||
{
|
||||
private:
|
||||
|
@ -15,15 +20,18 @@ namespace SHADE
|
|||
float yaw;
|
||||
float armLength;
|
||||
|
||||
bool dirty;
|
||||
|
||||
SHVec3 offset;
|
||||
SHVec3 targetOffset;
|
||||
SHRay ray;
|
||||
|
||||
public:
|
||||
friend class SHCameraSystem;
|
||||
SHCameraArmComponent();
|
||||
virtual ~SHCameraArmComponent() = default;
|
||||
|
||||
bool lookAtCameraOrigin;
|
||||
bool enableCameraCollision;
|
||||
//Getters
|
||||
//SHMatrix const& GetMatrix() const noexcept;
|
||||
SHVec3 const& GetOffset() const noexcept;
|
||||
|
@ -32,12 +40,14 @@ namespace SHADE
|
|||
float GetArmLength() const noexcept;
|
||||
SHVec3 GetTargetOffset() const noexcept;
|
||||
|
||||
|
||||
//Setters
|
||||
void SetPitch(float pitch) noexcept;
|
||||
void SetYaw(float yaw) noexcept;
|
||||
void SetArmLength(float length) noexcept;
|
||||
void SetTargetOffset(SHVec3 offset) noexcept;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include "Scene/SHSceneManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Math/Geometry/SHBox.h"
|
||||
#include "Math/SHRay.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -96,7 +100,7 @@ namespace SHADE
|
|||
if (editorCameraArm.armLength < 1.0f)
|
||||
editorCameraArm.armLength = 1.0f;
|
||||
|
||||
UpdatePivotArmComponent(editorCameraArm);
|
||||
UpdateCameraArmComponent(editorCameraArm);
|
||||
|
||||
editorCamera.offset = editorCameraArm.GetOffset();
|
||||
|
||||
|
@ -132,11 +136,13 @@ namespace SHADE
|
|||
return &editorCamera;
|
||||
}
|
||||
|
||||
void SHCameraSystem::UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept
|
||||
{
|
||||
if (pivot.dirty)
|
||||
void SHCameraSystem::UpdateCameraArmComponent(SHCameraArmComponent& pivot) noexcept
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SHVec3 offset{ 0.0f,0.0f, pivot.GetArmLength() };
|
||||
offset = SHVec3::RotateX(offset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
|
||||
offset = SHVec3::RotateY(offset, (SHMath::DegreesToRadians(pivot.GetYaw())));
|
||||
|
@ -145,10 +151,61 @@ namespace SHADE
|
|||
//pivot.rtMatrix = SHMatrix::RotateX(SHMath::DegreesToRadians(pivot.GetPitch()))
|
||||
// * SHMatrix::RotateY(SHMath::DegreesToRadians(pivot.GetYaw()))
|
||||
// * SHMatrix::Translate(SHVec3(0.0f , 0.0f, pivot.GetArmLength()));
|
||||
|
||||
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)
|
||||
{
|
||||
if(SHSceneManager::CheckNodeAndComponentsActive<SHCameraArmComponent>(pivot.GetEID()))
|
||||
system->UpdatePivotArmComponent(pivot);
|
||||
system->UpdateCameraArmComponent(pivot);
|
||||
}
|
||||
|
||||
for (auto& cam : dense)
|
||||
|
@ -390,7 +447,9 @@ namespace SHADE
|
|||
}
|
||||
void SHCameraSystem::SetCameraViewMatrix(SHCameraComponent& camera, SHMatrix const& viewMatrix) noexcept
|
||||
{
|
||||
SHVec3 pos;
|
||||
DecomposeViewMatrix(viewMatrix, camera.pitch, camera.yaw, camera.roll, camera.position);
|
||||
|
||||
camera.dirtyView = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SHADE
|
|||
|
||||
|
||||
void UpdateCameraComponent(SHCameraComponent& camera) noexcept;
|
||||
void UpdatePivotArmComponent(SHCameraArmComponent& pivot) noexcept;
|
||||
void UpdateCameraArmComponent(SHCameraArmComponent& pivot) noexcept;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -197,12 +197,18 @@ namespace SHADE
|
|||
if (BUILD_SUCCESS)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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 << ")!";
|
||||
|
@ -591,6 +597,19 @@ namespace SHADE
|
|||
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)
|
||||
{
|
||||
STARTUPINFOW startInfo;
|
||||
|
|
|
@ -319,6 +319,7 @@ namespace SHADE
|
|||
/// <param name="filePath">File path to the file to check.</param>
|
||||
/// <returns> True if the file exists </returns>
|
||||
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 std::wstring generateBuildCommand(bool debug);
|
||||
};
|
||||
|
|
|
@ -49,6 +49,16 @@ namespace SHADE
|
|||
GetNativeComponent()->lookAtCameraOrigin = val;
|
||||
}
|
||||
|
||||
bool CameraArm::EnableCameraCollision::get()
|
||||
{
|
||||
return GetNativeComponent()->enableCameraCollision;
|
||||
}
|
||||
|
||||
void CameraArm::EnableCameraCollision::set(bool val)
|
||||
{
|
||||
GetNativeComponent()->enableCameraCollision = val;
|
||||
}
|
||||
|
||||
Vector3 CameraArm::TargetOffset::get()
|
||||
{
|
||||
return Convert::ToCLI(GetNativeComponent()->GetTargetOffset());
|
||||
|
|
|
@ -36,6 +36,12 @@ namespace SHADE
|
|||
void set(bool val);
|
||||
}
|
||||
|
||||
property bool EnableCameraCollision
|
||||
{
|
||||
bool get();
|
||||
void set(bool val);
|
||||
}
|
||||
|
||||
property Vector3 TargetOffset
|
||||
{
|
||||
Vector3 get();
|
||||
|
|
|
@ -200,7 +200,16 @@ namespace SHADE
|
|||
{
|
||||
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);
|
||||
registerUndoListAddAction(listType, iList, iList->Count - 1, obj);
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace SHADE
|
|||
// Add the script in
|
||||
script->Initialize(GameObject(entity));
|
||||
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
|
||||
script->Awake();
|
||||
|
@ -423,6 +423,8 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
void ScriptStore::Init()
|
||||
{
|
||||
isDeserialising = false;
|
||||
|
||||
// Create an enumerable list of script types
|
||||
refreshScriptTypeList();
|
||||
// Get stored methods for interop variants of functions
|
||||
|
@ -724,6 +726,10 @@ namespace SHADE
|
|||
bool ScriptStore::DeserialiseScripts(Entity entity, System::IntPtr yamlNodePtr)
|
||||
{
|
||||
SAFE_NATIVE_CALL_BEGIN
|
||||
|
||||
// Flag that deserialization processs is ongoing
|
||||
isDeserialising = true;
|
||||
|
||||
// Convert to pointer
|
||||
YAML::Node* yamlNode = reinterpret_cast<YAML::Node*>(yamlNodePtr.ToPointer());
|
||||
|
||||
|
@ -765,9 +771,16 @@ namespace SHADE
|
|||
Debug::LogWarning("[ScriptStore] Script with unloaded type detected, skipping.");
|
||||
}
|
||||
}
|
||||
|
||||
// Unset flag for deserialization process
|
||||
isDeserialising = false;
|
||||
|
||||
return true;
|
||||
|
||||
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
|
||||
|
||||
// Unset flag for deserialization process
|
||||
isDeserialising = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -337,6 +337,7 @@ namespace SHADE
|
|||
static ScriptSet disposalQueue;
|
||||
static System::Collections::Generic::IEnumerable<System::Type^>^ scriptTypeList;
|
||||
static System::Reflection::MethodInfo^ addScriptMethod;
|
||||
static bool isDeserialising;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
|
|
|
@ -279,7 +279,15 @@ namespace SHADE
|
|||
for (int i = 0; i < LIST_SIZE; ++i)
|
||||
{
|
||||
// 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
|
||||
if (varAssignYaml(obj, node[i]))
|
||||
|
|
|
@ -167,6 +167,10 @@ namespace SHADE
|
|||
{
|
||||
valueObj = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -181,6 +185,10 @@ namespace SHADE
|
|||
valueObj = FieldType();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue