mirror of
https://github.com/originalnicodr/CinematicUnityExplorer.git
synced 2026-10-10 04:53:15 +08:00
Refactored the follow object feature to let the user choose if they want to follow the object position only or if they also want the camera to follow its rotation.
This commit is contained in:
@@ -134,7 +134,9 @@ The original Unity Explorer had a Freecam feature, but even if it was useful at
|
||||
- Blocked rotation from going further when looking directly up or directly down.
|
||||
|
||||
### Follow Object
|
||||
You can click on the "Follow object" button on the panel and select the object you want to follow on screen or click on the "Follow object" button in the inspector screen for more granularity. Should be useful for creating motion blur, or to use alongside the [camera paths](#camera-paths).
|
||||
You can click on the "Follow object" button on the panel and select the object you want the camera to follow or click on the "Follow object" button in the inspector screen for more granularity. This can be used as it is, but it's even more useful when playing with [camera paths](#camera-paths), as you can create a path for the camera to walk relative to the object
|
||||
|
||||
By default the camera only follows the object's position, but you can also make it follow its rotation as if the camera was physically bound to the object by checking the "Follow Object Rotation" toggle. Should be useful for mimicking a car camera, a character POV, or creating motion blur.
|
||||
|
||||
### Game input block for Unity's legacy system
|
||||
Added game input block for Unity's legacy system. You can now block (or unblock) the game's input when using the freecam, as long as the game is using the Unity Legacy Input system. If the game uses a custom solution or the latest Unity system then this won't work. Implementing this for Unity's new system is in the backlog, so if you find a game using it (should say "Initialized new InputSystem support." on the logs) then please let me know so I can implement it using that game!
|
||||
@@ -322,6 +324,10 @@ Building individual configurations from your IDE is fine, though note that the i
|
||||
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], the ScriptEvaluator from RUE's REPL console was used as the base for UnityExplorer's C# console.
|
||||
* [Geoffrey Horsington](https://github.com/ghorsington) for [mcs-unity](https://github.com/sinai-dev/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
|
||||
|
||||
# Crediting
|
||||
|
||||
Even tho it's not necessary, if you happen to use this mod in the marketing campaign of a game and find it useful please consider including it in the credits!
|
||||
|
||||
# Support
|
||||
|
||||
If you have found this project fun or useful in any capacity please consider [supporting me on Ko-fi](https://ko-fi.com/originalnicodr). And please also consider donating to the people in the acknowledgments above! As well as the mod loader maintainers.
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace UnityExplorer.UI.Panels
|
||||
ButtonRef moveToCameraButton = UIFactory.CreateButton(UIRoot, "Copy Camera pos and rot", "Copy Camera pos and rot");
|
||||
UIFactory.SetLayoutElement(moveToCameraButton.GameObject, minWidth: 130, minHeight: 25, flexibleWidth: 9999);
|
||||
moveToCameraButton.OnClick += () => {
|
||||
point.position = GetCamPathsPanel().followObject != null ? FreeCamPanel.ourCamera.transform.localPosition : FreeCamPanel.ourCamera.transform.position;
|
||||
point.rotation = GetCamPathsPanel().followObject != null ? FreeCamPanel.ourCamera.transform.localRotation : FreeCamPanel.ourCamera.transform.rotation;
|
||||
point.rotation = FreeCamPanel.GetCameraRotation();
|
||||
point.position = FreeCamPanel.GetCameraPosition();
|
||||
GetCamPathsPanel().controlPoints[index] = point;
|
||||
|
||||
GetCamPathsPanel().MaybeRedrawPath();
|
||||
@@ -50,13 +50,8 @@ namespace UnityExplorer.UI.Panels
|
||||
ButtonRef moveToPointButton = UIFactory.CreateButton(UIRoot, "Move Cam to Node", "Move Cam to Node");
|
||||
UIFactory.SetLayoutElement(moveToPointButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999);
|
||||
moveToPointButton.OnClick += () => {
|
||||
if (GetCamPathsPanel().followObject != null){
|
||||
FreeCamPanel.ourCamera.transform.localPosition = point.position;
|
||||
FreeCamPanel.ourCamera.transform.localRotation = point.rotation;
|
||||
} else {
|
||||
FreeCamPanel.ourCamera.transform.position = point.position;
|
||||
FreeCamPanel.ourCamera.transform.rotation = point.rotation;
|
||||
}
|
||||
FreeCamPanel.SetCameraRotation(point.rotation);
|
||||
FreeCamPanel.SetCameraPosition(point.position);
|
||||
FreeCamPanel.ourCamera.fieldOfView = point.fov;
|
||||
};
|
||||
|
||||
|
||||
+111
-24
@@ -22,7 +22,7 @@ namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
controlPoints = new List<CatmullRom.CatmullRomPoint>();
|
||||
followObject = null;
|
||||
pathVisualizer = new GameObject("PathVisualizer");
|
||||
pathVisualizer = null;
|
||||
time = 10;
|
||||
|
||||
// Timer setup
|
||||
@@ -69,6 +69,8 @@ namespace UnityExplorer.UI.Panels
|
||||
public int ItemCount => controlPoints.Count;
|
||||
private static bool DoneScrollPoolInit;
|
||||
|
||||
CamPointsUpdater camPointsUpdater;
|
||||
|
||||
public override void SetActive(bool active)
|
||||
{
|
||||
base.SetActive(active);
|
||||
@@ -248,10 +250,9 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
private void ToggleVisualizePath(bool enable){
|
||||
// Had to include this check because the pathVisualizer was null for some reason
|
||||
if (pathVisualizer == null) pathVisualizer = new GameObject("PathVisualizer");
|
||||
if (enable){
|
||||
if (controlPoints.Count > 2){
|
||||
if (followObject != null) pathVisualizer.transform.SetParent(followObject.transform, true);
|
||||
CreateAndMovePathVisualizer();
|
||||
|
||||
UpdateCatmullRomMoverData();
|
||||
List<CatmullRom.CatmullRomPoint> lookaheadPoints = GetCameraPathsManager().GetLookaheadPoints();
|
||||
@@ -265,9 +266,16 @@ namespace UnityExplorer.UI.Panels
|
||||
}
|
||||
|
||||
Vector3 arrowPos = lookaheadPoints[i].position;
|
||||
if (followObject != null) arrowPos = followObject.transform.TransformPoint(arrowPos);
|
||||
if (followObject != null){
|
||||
if (!FreeCamPanel.followRotationToggle.isOn){
|
||||
arrowPos = Quaternion.Inverse(FreeCamPanel.followObject.transform.rotation) * arrowPos;
|
||||
}
|
||||
// TODO: Avoid using TransformPoint
|
||||
arrowPos = followObject.transform.TransformPoint(arrowPos);
|
||||
}
|
||||
Quaternion arrowRot = lookaheadPoints[i].rotation;
|
||||
if (followObject != null) arrowRot = followObject.transform.rotation * arrowRot;
|
||||
if (followObject != null && FreeCamPanel.followRotationToggle.isOn) arrowRot = followObject.transform.rotation * arrowRot;
|
||||
|
||||
// We could expose the color of the arrow to a setting
|
||||
GameObject arrow = ArrowGenerator.CreateArrow(arrowPos, arrowRot, Color.green);
|
||||
arrow.transform.SetParent(pathVisualizer.transform, true);
|
||||
@@ -278,7 +286,8 @@ namespace UnityExplorer.UI.Panels
|
||||
else {
|
||||
if (pathVisualizer) {
|
||||
UnityEngine.Object.Destroy(pathVisualizer);
|
||||
pathVisualizer = new GameObject("PathVisualizer");
|
||||
pathVisualizer = null;
|
||||
CreateAndMovePathVisualizer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,11 +362,10 @@ namespace UnityExplorer.UI.Panels
|
||||
void AddNode_OnClick(){
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
Camera freeCam = FreeCamPanel.ourCamera;
|
||||
CatmullRom.CatmullRomPoint point = new CatmullRom.CatmullRomPoint(
|
||||
followObject != null ? freeCam.transform.localPosition : freeCam.transform.position,
|
||||
followObject != null ? freeCam.transform.localRotation : freeCam.transform.rotation,
|
||||
freeCam.fieldOfView
|
||||
FreeCamPanel.GetCameraPosition(),
|
||||
FreeCamPanel.GetCameraRotation(),
|
||||
FreeCamPanel.ourCamera.fieldOfView
|
||||
);
|
||||
|
||||
controlPoints.Add(point);
|
||||
@@ -387,38 +395,67 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
public void UpdatedFollowObject(GameObject obj){
|
||||
// Had to include this check because the pathVisualizer was null for some reason
|
||||
if (pathVisualizer == null) pathVisualizer = new GameObject("PathVisualizer");
|
||||
if (followObject != null){
|
||||
TranslatePointsToGlobal();
|
||||
pathVisualizer.transform.SetParent(null, true);
|
||||
// destroy the obhject from the parent
|
||||
GameObject.Destroy(camPointsUpdater);
|
||||
camPointsUpdater = null;
|
||||
}
|
||||
followObject = obj;
|
||||
if (obj != null){
|
||||
TranslatePointsToLocal();
|
||||
pathVisualizer.transform.SetParent(obj.transform, true);
|
||||
// create the component on the object itself
|
||||
camPointsUpdater = RuntimeHelper.AddComponent<CamPointsUpdater>(obj, typeof(CamPointsUpdater));
|
||||
//camPointsUpdater = obj.AddComponent<CamPointsUpdater>();
|
||||
|
||||
camPointsUpdater.SetFollowObject(obj);
|
||||
}
|
||||
//nodesScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
void TranslatePointsToGlobal() {
|
||||
public void CreateAndMovePathVisualizer(){
|
||||
if (pathVisualizer == null)
|
||||
pathVisualizer = new GameObject("PathVisualizer");
|
||||
|
||||
if (followObject != null){
|
||||
pathVisualizer.transform.position = followObject.transform.position;
|
||||
if (FreeCamPanel.followRotationToggle.isOn){
|
||||
Vector3 offset = pathVisualizer.transform.position - followObject.transform.position;
|
||||
pathVisualizer.transform.position = pathVisualizer.transform.position - offset + followObject.transform.rotation * offset;
|
||||
pathVisualizer.transform.rotation = followObject.transform.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TranslatePointsPositionToGlobal(){
|
||||
List<CatmullRom.CatmullRomPoint> newControlPoints = new List<CatmullRom.CatmullRomPoint>();
|
||||
foreach(CatmullRom.CatmullRomPoint point in controlPoints){
|
||||
Vector3 newPos = point.position + followObject.transform.position;
|
||||
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, point.rotation, point.fov);
|
||||
newControlPoints.Add(newPoint);
|
||||
}
|
||||
|
||||
controlPoints = newControlPoints;
|
||||
}
|
||||
|
||||
// Also changes position based on rotation
|
||||
public void TranslatePointsRotationToGlobal(){
|
||||
List<CatmullRom.CatmullRomPoint> newControlPoints = new List<CatmullRom.CatmullRomPoint>();
|
||||
foreach(CatmullRom.CatmullRomPoint point in controlPoints){
|
||||
Vector3 newPos = followObject.transform.TransformPoint(point.position);
|
||||
Quaternion newRot = followObject.transform.rotation * point.rotation;
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, newRot, point.fov);
|
||||
Vector3 newPos = followObject.transform.rotation * point.position;
|
||||
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, newRot, point.fov);
|
||||
newControlPoints.Add(newPoint);
|
||||
}
|
||||
|
||||
controlPoints = newControlPoints;
|
||||
}
|
||||
|
||||
void TranslatePointsToLocal() {
|
||||
public void TranslatePointsPositionToLocal(){
|
||||
List<CatmullRom.CatmullRomPoint> newControlPoints = new List<CatmullRom.CatmullRomPoint>();
|
||||
foreach(CatmullRom.CatmullRomPoint point in controlPoints){
|
||||
Vector3 newPos = followObject.transform.InverseTransformPoint(point.position);
|
||||
Quaternion newRot = Quaternion.Inverse(followObject.transform.rotation) * point.rotation;
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, newRot, point.fov);
|
||||
Vector3 newPos = point.position - followObject.transform.position;
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, point.rotation, point.fov);
|
||||
|
||||
newControlPoints.Add(newPoint);
|
||||
}
|
||||
@@ -426,9 +463,22 @@ namespace UnityExplorer.UI.Panels
|
||||
controlPoints = newControlPoints;
|
||||
}
|
||||
|
||||
void UpdateCatmullRomMoverData(){
|
||||
// Also changes position based on rotation
|
||||
public void TranslatePointsRotationToLocal(){
|
||||
List<CatmullRom.CatmullRomPoint> newControlPoints = new List<CatmullRom.CatmullRomPoint>();
|
||||
foreach(CatmullRom.CatmullRomPoint point in controlPoints){
|
||||
Quaternion newRot = Quaternion.Inverse(followObject.transform.rotation) * point.rotation;
|
||||
Vector3 newPos = Quaternion.Inverse(followObject.transform.rotation) * point.position;
|
||||
|
||||
CatmullRom.CatmullRomPoint newPoint = new CatmullRom.CatmullRomPoint(newPos, newRot, point.fov);
|
||||
newControlPoints.Add(newPoint);
|
||||
}
|
||||
|
||||
controlPoints = newControlPoints;
|
||||
}
|
||||
|
||||
void UpdateCatmullRomMoverData() {
|
||||
GetCameraPathsManager().setClosedLoop(closedLoop);
|
||||
GetCameraPathsManager().setLocalPoints(followObject != null);
|
||||
GetCameraPathsManager().setSplinePoints(controlPoints.ToArray());
|
||||
GetCameraPathsManager().setTime(time);
|
||||
GetCameraPathsManager().setCatmullRomVariables(alphaCatmullRomValue, tensionCatmullRomValue);
|
||||
@@ -436,4 +486,41 @@ namespace UnityExplorer.UI.Panels
|
||||
GetCameraPathsManager().CalculateLookahead();
|
||||
}
|
||||
}
|
||||
|
||||
public class CamPointsUpdater : MonoBehaviour
|
||||
{
|
||||
GameObject followObject;
|
||||
|
||||
#if CPP
|
||||
static CamPointsUpdater()
|
||||
{
|
||||
ClassInjector.RegisterTypeInIl2Cpp<CamPointsUpdater>();
|
||||
}
|
||||
|
||||
public CamPointsUpdater(IntPtr ptr) : base(ptr) { }
|
||||
#endif
|
||||
|
||||
internal void SetFollowObject(GameObject obj){
|
||||
followObject = obj;
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
if (followObject == null)
|
||||
return;
|
||||
|
||||
//CamPathsPanel.MaybeRedrawPath();
|
||||
|
||||
CamPaths CamPathsPanel = UIManager.GetPanel<CamPaths>(UIManager.Panels.CamPaths);
|
||||
|
||||
if (CamPathsPanel.pathVisualizer){
|
||||
CamPathsPanel.pathVisualizer.transform.position = followObject.transform.position;
|
||||
if (FreeCamPanel.followRotationToggle.isOn){
|
||||
Vector3 offset = CamPathsPanel.pathVisualizer.transform.position - FreeCamPanel.followObject.transform.position;
|
||||
CamPathsPanel.pathVisualizer.transform.position = CamPathsPanel.pathVisualizer.transform.position - offset + FreeCamPanel.followObject.transform.rotation * offset;
|
||||
CamPathsPanel.pathVisualizer.transform.rotation = followObject.transform.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+221
-126
@@ -57,6 +57,7 @@ namespace UnityExplorer.UI.Panels
|
||||
static InputFieldRef moveSpeedInput;
|
||||
static Text followObjectLabel;
|
||||
static ButtonRef inspectButton;
|
||||
public static Toggle followRotationToggle;
|
||||
static bool disabledCinemachine;
|
||||
|
||||
public static bool supportedInput => InputManager.CurrentType == InputType.Legacy;
|
||||
@@ -70,6 +71,8 @@ namespace UnityExplorer.UI.Panels
|
||||
static float farClipPlaneValue;
|
||||
|
||||
public static GameObject followObject = null;
|
||||
public static Vector3 followObjectLastPosition = Vector3.zero;
|
||||
public static Quaternion followObjectLastRotation = Quaternion.identity;
|
||||
|
||||
private static FreecamCursorUnlocker freecamCursorUnlocker = null;
|
||||
|
||||
@@ -225,7 +228,7 @@ namespace UnityExplorer.UI.Panels
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCameraPosition(Vector3 pos)
|
||||
static void SetCameraPositionInput(Vector3 pos)
|
||||
{
|
||||
if (!ourCamera || lastSetCameraPosition == pos)
|
||||
return;
|
||||
@@ -285,6 +288,22 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
GameObject togglesRow = UIFactory.CreateHorizontalGroup(ContentRoot, "TogglesRow", false, false, true, true, 3, default, new(1, 1, 1, 0));
|
||||
|
||||
GameObject blockFreecamMovement = UIFactory.CreateToggle(togglesRow, "blockFreecamMovement", out blockFreecamMovementToggle, out Text blockFreecamMovementText);
|
||||
UIFactory.SetLayoutElement(blockFreecamMovement, minHeight: 25, flexibleWidth: 9999);
|
||||
blockFreecamMovementToggle.isOn = false;
|
||||
blockFreecamMovementText.text = "Block Freecam movement";
|
||||
|
||||
if (supportedInput){
|
||||
GameObject blockGamesInputOnFreecam = UIFactory.CreateToggle(togglesRow, "blockGamesInputOnFreecam", out blockGamesInputOnFreecamToggle, out Text blockGamesInputOnFreecamText);
|
||||
UIFactory.SetLayoutElement(blockGamesInputOnFreecam, minHeight: 25, flexibleWidth: 9999);
|
||||
blockGamesInputOnFreecamToggle.isOn = true;
|
||||
blockGamesInputOnFreecamText.text = "Block games input on Freecam";
|
||||
}
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
GameObject nearCameraClipGroup = AddInputField("NearClipPlane", "Near clip plane:", "0", out nearClipPlaneInput, NearClipInput_OnEndEdit);
|
||||
nearClipPlaneInput.Text = nearClipPlaneValue.ToString();
|
||||
|
||||
@@ -325,7 +344,6 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
|
||||
followObjectLabel = UIFactory.CreateLabel(ContentRoot, "CurrentFollowObject", "Not following any object.");
|
||||
UIFactory.SetLayoutElement(followObjectLabel.gameObject, minWidth: 100, minHeight: 25);
|
||||
|
||||
@@ -339,24 +357,26 @@ namespace UnityExplorer.UI.Panels
|
||||
UIFactory.SetLayoutElement(releaseFollowButton.GameObject, minWidth: 150, minHeight: 25, flexibleWidth: 9999);
|
||||
releaseFollowButton.OnClick += ReleaseFollowButton_OnClick;
|
||||
|
||||
GameObject followRotationGameObject = UIFactory.CreateToggle(ContentRoot, "followRotationToggle", out followRotationToggle, out Text followRotationText);
|
||||
UIFactory.SetLayoutElement(followRotationGameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
followRotationToggle.isOn = false;
|
||||
followRotationText.text = "Follow Object Rotation";
|
||||
followRotationToggle.onValueChanged.AddListener((value) => {
|
||||
if (followObject != null){
|
||||
CamPaths CamPathsPanel = UIManager.GetPanel<CamPaths>(UIManager.Panels.CamPaths);
|
||||
if (value){
|
||||
CamPathsPanel.TranslatePointsRotationToLocal();
|
||||
}
|
||||
else {
|
||||
CamPathsPanel.TranslatePointsRotationToGlobal();
|
||||
}
|
||||
|
||||
CamPathsPanel.MaybeRedrawPath();
|
||||
}
|
||||
});
|
||||
|
||||
AddSpacer(5);
|
||||
|
||||
GameObject togglesRow = UIFactory.CreateHorizontalGroup(ContentRoot, "TogglesRow", false, false, true, true, 3, default, new(1, 1, 1, 0));
|
||||
|
||||
GameObject blockFreecamMovement = UIFactory.CreateToggle(togglesRow, "blockFreecamMovement", out blockFreecamMovementToggle, out Text blockFreecamMovementText);
|
||||
UIFactory.SetLayoutElement(blockFreecamMovement, minHeight: 25, flexibleWidth: 9999);
|
||||
blockFreecamMovementToggle.isOn = false;
|
||||
blockFreecamMovementText.text = "Block Freecam movement";
|
||||
|
||||
if (supportedInput){
|
||||
GameObject blockGamesInputOnFreecam = UIFactory.CreateToggle(togglesRow, "blockGamesInputOnFreecam", out blockGamesInputOnFreecamToggle, out Text blockGamesInputOnFreecamText);
|
||||
UIFactory.SetLayoutElement(blockGamesInputOnFreecam, minHeight: 25, flexibleWidth: 9999);
|
||||
blockGamesInputOnFreecamToggle.isOn = true;
|
||||
blockGamesInputOnFreecamText.text = "Block games input on Freecam";
|
||||
|
||||
AddSpacer(5);
|
||||
}
|
||||
|
||||
string instructions = "Controls:\n" +
|
||||
$"- {ConfigManager.Forwards_1.Value},{ConfigManager.Backwards_1.Value},{ConfigManager.Left_1.Value},{ConfigManager.Right_1.Value} / {ConfigManager.Forwards_2.Value},{ConfigManager.Backwards_2.Value},{ConfigManager.Left_2.Value},{ConfigManager.Right_2.Value}: Movement\n" +
|
||||
$"- {ConfigManager.Up.Value}: Move up\n" +
|
||||
@@ -425,10 +445,24 @@ namespace UnityExplorer.UI.Panels
|
||||
}
|
||||
|
||||
public static void FollowObjectAction(GameObject obj){
|
||||
followObject = obj;
|
||||
followObjectLabel.text = $"Following: {obj.name}";
|
||||
CamPaths CamPathsPanel = UIManager.GetPanel<CamPaths>(UIManager.Panels.CamPaths);
|
||||
|
||||
if (followObject != null){
|
||||
if (followRotationToggle.isOn) CamPathsPanel.TranslatePointsRotationToGlobal();
|
||||
CamPathsPanel.TranslatePointsPositionToGlobal();
|
||||
}
|
||||
|
||||
followObject = obj;
|
||||
followObjectLastPosition = followObject.transform.position;
|
||||
followObjectLastRotation = followObject.transform.rotation;
|
||||
followObjectLabel.text = $"Following: {obj.name}";
|
||||
|
||||
CamPathsPanel.UpdatedFollowObject(obj);
|
||||
|
||||
CamPathsPanel.TranslatePointsPositionToLocal();
|
||||
if (followRotationToggle.isOn) CamPathsPanel.TranslatePointsRotationToLocal();
|
||||
|
||||
CamPathsPanel.MaybeRedrawPath();
|
||||
}
|
||||
|
||||
void FollowButton_OnClick()
|
||||
@@ -438,12 +472,17 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
void ReleaseFollowButton_OnClick()
|
||||
{
|
||||
if (followObject && ourCamera.transform.IsChildOf(followObject.transform)){
|
||||
ourCamera.transform.SetParent(null, true);
|
||||
if (followObject){
|
||||
followObject = null;
|
||||
followObjectLastPosition = Vector3.zero;
|
||||
followObjectLastRotation = Quaternion.identity;
|
||||
followObjectLabel.text = "Not following any object";
|
||||
}
|
||||
CamPaths CamPathsPanel = UIManager.GetPanel<CamPaths>(UIManager.Panels.CamPaths);
|
||||
|
||||
if (followRotationToggle.isOn) CamPathsPanel.TranslatePointsRotationToGlobal();
|
||||
CamPathsPanel.TranslatePointsPositionToGlobal();
|
||||
|
||||
CamPathsPanel.UpdatedFollowObject(null);
|
||||
}
|
||||
|
||||
@@ -463,11 +502,6 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
void OnUseGameCameraToggled(bool value)
|
||||
{
|
||||
// If the previous camera is following a game object we remove it from tis childs.
|
||||
if (followObject && ourCamera.transform.IsChildOf(followObject.transform)){
|
||||
ourCamera.transform.SetParent(null, true);
|
||||
}
|
||||
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
if (!inFreeCamMode)
|
||||
@@ -484,8 +518,8 @@ namespace UnityExplorer.UI.Panels
|
||||
|
||||
if (inFreeCamMode && ourCamera)
|
||||
{
|
||||
ourCamera.transform.position = (Vector3)currentUserCameraPosition;
|
||||
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation;
|
||||
SetCameraPosition((Vector3)currentUserCameraPosition, true);
|
||||
SetCameraRotation((Quaternion)currentUserCameraRotation, true);
|
||||
ourCamera.fieldOfView = originalCameraFOV;
|
||||
}
|
||||
|
||||
@@ -503,7 +537,7 @@ namespace UnityExplorer.UI.Panels
|
||||
return;
|
||||
}
|
||||
|
||||
SetCameraPosition(parsed);
|
||||
SetCameraPositionInput(parsed);
|
||||
}
|
||||
|
||||
void MoveSpeedInput_OnEndEdit(string input)
|
||||
@@ -557,6 +591,55 @@ namespace UnityExplorer.UI.Panels
|
||||
public static bool ShouldOverrideInput(){
|
||||
return inFreeCamMode && blockGamesInputOnFreecamToggle.isOn;
|
||||
}
|
||||
|
||||
// Getters and Setters for camera position and rotation
|
||||
public static Vector3 GetCameraPosition(bool isAbsolute = false){
|
||||
if (isAbsolute) return ourCamera.transform.position;
|
||||
if (followObject){
|
||||
if (followRotationToggle.isOn){
|
||||
return Quaternion.Inverse(followObject.transform.rotation) * (ourCamera.transform.position - followObject.transform.position);
|
||||
}
|
||||
else {
|
||||
return ourCamera.transform.position - followObject.transform.position;
|
||||
}
|
||||
}
|
||||
return ourCamera.transform.position;
|
||||
}
|
||||
|
||||
public static Quaternion GetCameraRotation(bool isAbsolute = false){
|
||||
if (isAbsolute) return ourCamera.transform.rotation;
|
||||
if (followObject && followRotationToggle.isOn) return Quaternion.Inverse(followObjectLastRotation) * ourCamera.transform.rotation;
|
||||
return ourCamera.transform.rotation;
|
||||
}
|
||||
|
||||
public static void SetCameraPosition(Vector3 newPosition, bool isAbsolute = false){
|
||||
if (isAbsolute){
|
||||
ourCamera.transform.position = newPosition;
|
||||
}
|
||||
else if (followObject){
|
||||
if (followRotationToggle.isOn){
|
||||
ourCamera.transform.position = followObject.transform.rotation * newPosition + followObject.transform.position;
|
||||
}
|
||||
else {
|
||||
ourCamera.transform.position = newPosition + followObject.transform.position;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ourCamera.transform.position = newPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetCameraRotation(Quaternion newRotation, bool isAbsolute = false){
|
||||
if (isAbsolute){
|
||||
ourCamera.transform.rotation = newRotation;
|
||||
}
|
||||
else if (followObject && followRotationToggle.isOn){
|
||||
ourCamera.transform.rotation = followObjectLastRotation * newRotation;
|
||||
}
|
||||
else {
|
||||
ourCamera.transform.rotation = newRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class FreeCamBehaviour : MonoBehaviour
|
||||
@@ -580,113 +663,125 @@ namespace UnityExplorer.UI.Panels
|
||||
return;
|
||||
}
|
||||
|
||||
if (FreeCamPanel.followObject && !FreeCamPanel.ourCamera.transform.IsChildOf(FreeCamPanel.followObject.transform)){
|
||||
FreeCamPanel.ourCamera.transform.SetParent(FreeCamPanel.followObject.transform, true);
|
||||
}
|
||||
|
||||
// ------------- Handle input ----------------
|
||||
|
||||
if (FreeCamPanel.blockFreecamMovementToggle.isOn || FreeCamPanel.cameraPathMover.playingPath){
|
||||
return;
|
||||
}
|
||||
|
||||
Transform transform = FreeCamPanel.ourCamera.transform;
|
||||
|
||||
FreeCamPanel.currentUserCameraPosition = transform.position;
|
||||
FreeCamPanel.currentUserCameraRotation = transform.rotation;
|
||||
|
||||
float moveSpeed = FreeCamPanel.desiredMoveSpeed * 0.01665f; //"0.01665f" (60fps) in place of Time.DeltaTime. DeltaTime causes issues when game is paused.
|
||||
float speedModifier = 1;
|
||||
if (IInputManager.GetKey(ConfigManager.Speed_Up_Movement.Value))
|
||||
speedModifier = 10f;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Speed_Down_Movement.Value))
|
||||
speedModifier = 0.1f;
|
||||
|
||||
moveSpeed *= speedModifier;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Left_1.Value) || IInputManager.GetKey(ConfigManager.Left_2.Value))
|
||||
transform.position += transform.right * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Right_1.Value) || IInputManager.GetKey(ConfigManager.Right_2.Value))
|
||||
transform.position += transform.right * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Forwards_1.Value) || IInputManager.GetKey(ConfigManager.Forwards_2.Value))
|
||||
transform.position += transform.forward * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Backwards_1.Value) || IInputManager.GetKey(ConfigManager.Backwards_2.Value))
|
||||
transform.position += transform.forward * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Up.Value))
|
||||
transform.position += transform.up * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Down.Value))
|
||||
transform.position += transform.up * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Left.Value))
|
||||
transform.Rotate(0, 0, moveSpeed, Space.Self);
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Right.Value))
|
||||
transform.Rotate(0, 0, - moveSpeed, Space.Self);
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Reset.Value)){
|
||||
// Extract the forward direction of the original quaternion
|
||||
Vector3 forwardDirection = transform.rotation * Vector3.forward;
|
||||
// Reset the tilt by creating a new quaternion with no tilt
|
||||
Quaternion newRotation = Quaternion.LookRotation(forwardDirection, Vector3.up);
|
||||
|
||||
transform.rotation = newRotation;
|
||||
if (!FreeCamPanel.blockFreecamMovementToggle.isOn && !FreeCamPanel.cameraPathMover.playingPath){
|
||||
ProcessInput();
|
||||
}
|
||||
|
||||
if (IInputManager.GetMouseButton(1))
|
||||
{
|
||||
Vector3 mouseDelta = IInputManager.MousePosition - FreeCamPanel.previousMousePosition;
|
||||
|
||||
float newRotationX = transform.localEulerAngles.y + mouseDelta.x * 0.3f;
|
||||
float newRotationY = transform.localEulerAngles.x - mouseDelta.y * 0.3f;
|
||||
if (FreeCamPanel.followObject != null){
|
||||
// position update
|
||||
transform.position += FreeCamPanel.followObject.transform.position - FreeCamPanel.followObjectLastPosition;
|
||||
|
||||
// Block the camera rotation to not go further than looking directly up or down.
|
||||
// We give a little extra to the [0, 90] rotation segment to not get the camera rotation stuck.
|
||||
// If it doesn't work in some game we should revisit this.
|
||||
newRotationY = newRotationY > 180f ? Mathf.Clamp(newRotationY, 270f, 360f) : Mathf.Clamp(newRotationY, -1f, 90.0f);
|
||||
if (FreeCamPanel.followRotationToggle.isOn){
|
||||
// rotation update
|
||||
Quaternion deltaRotation = FreeCamPanel.followObject.transform.rotation * Quaternion.Inverse(FreeCamPanel.followObjectLastRotation);
|
||||
Vector3 offset = transform.position - FreeCamPanel.followObject.transform.position;
|
||||
transform.position = transform.position - offset + deltaRotation * offset;
|
||||
transform.rotation = deltaRotation * transform.rotation;
|
||||
}
|
||||
|
||||
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, transform.localEulerAngles.z);
|
||||
|
||||
// Apply the rotation changes while maintaining the camera's current roll.
|
||||
// Not using this method as it can easily modify the tilt, which is undesired.
|
||||
|
||||
/*float pitch = -mouseDelta.y * speedModifier * Time.deltaTime;
|
||||
float yaw = mouseDelta.x * speedModifier * Time.deltaTime;
|
||||
|
||||
Vector3 forwardDirection = transform.rotation * Vector3.forward;
|
||||
Vector3 rightDirection = transform.rotation * Vector3.right;
|
||||
Vector3 upDirection = transform.rotation * Vector3.up;
|
||||
|
||||
Quaternion pitchRotation = Quaternion.AngleAxis(pitch, rightDirection);
|
||||
Quaternion yawRotation = Quaternion.AngleAxis(yaw, upDirection);
|
||||
|
||||
transform.rotation = pitchRotation * yawRotation * transform.rotation;*/
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Decrease_FOV.Value))
|
||||
{
|
||||
FreeCamPanel.ourCamera.fieldOfView -= moveSpeed;
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Increase_FOV.Value))
|
||||
{
|
||||
FreeCamPanel.ourCamera.fieldOfView += moveSpeed;
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Reset_FOV.Value)){
|
||||
FreeCamPanel.ourCamera.fieldOfView = FreeCamPanel.usingGameCamera ? FreeCamPanel.originalCameraFOV : 60;
|
||||
FreeCamPanel.followObjectLastPosition = FreeCamPanel.followObject.transform.position;
|
||||
FreeCamPanel.followObjectLastRotation = FreeCamPanel.followObject.transform.rotation;
|
||||
}
|
||||
|
||||
FreeCamPanel.UpdatePositionInput();
|
||||
|
||||
FreeCamPanel.previousMousePosition = IInputManager.MousePosition;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ProcessInput(){
|
||||
FreeCamPanel.currentUserCameraPosition = transform.position;
|
||||
FreeCamPanel.currentUserCameraRotation = transform.rotation;
|
||||
|
||||
float moveSpeed = FreeCamPanel.desiredMoveSpeed * 0.01665f; //"0.01665f" (60fps) in place of Time.DeltaTime. DeltaTime causes issues when game is paused.
|
||||
float speedModifier = 1;
|
||||
if (IInputManager.GetKey(ConfigManager.Speed_Up_Movement.Value))
|
||||
speedModifier = 10f;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Speed_Down_Movement.Value))
|
||||
speedModifier = 0.1f;
|
||||
|
||||
moveSpeed *= speedModifier;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Left_1.Value) || IInputManager.GetKey(ConfigManager.Left_2.Value))
|
||||
transform.position += transform.right * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Right_1.Value) || IInputManager.GetKey(ConfigManager.Right_2.Value))
|
||||
transform.position += transform.right * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Forwards_1.Value) || IInputManager.GetKey(ConfigManager.Forwards_2.Value))
|
||||
transform.position += transform.forward * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Backwards_1.Value) || IInputManager.GetKey(ConfigManager.Backwards_2.Value))
|
||||
transform.position += transform.forward * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Up.Value))
|
||||
transform.position += transform.up * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Down.Value))
|
||||
transform.position += transform.up * -1 * moveSpeed;
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Left.Value))
|
||||
transform.Rotate(0, 0, moveSpeed, Space.Self);
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Right.Value))
|
||||
transform.Rotate(0, 0, - moveSpeed, Space.Self);
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Tilt_Reset.Value)){
|
||||
// Extract the forward direction of the original quaternion
|
||||
Vector3 forwardDirection = transform.rotation * Vector3.forward;
|
||||
// Reset the tilt by creating a new quaternion with no tilt
|
||||
Quaternion newRotation = Quaternion.LookRotation(forwardDirection, Vector3.up);
|
||||
|
||||
transform.rotation = newRotation;
|
||||
}
|
||||
|
||||
if (IInputManager.GetMouseButton(1))
|
||||
{
|
||||
Vector3 mouseDelta = IInputManager.MousePosition - FreeCamPanel.previousMousePosition;
|
||||
|
||||
float newRotationX = transform.localEulerAngles.y + mouseDelta.x * 0.3f;
|
||||
float newRotationY = transform.localEulerAngles.x - mouseDelta.y * 0.3f;
|
||||
|
||||
// Block the camera rotation to not go further than looking directly up or down.
|
||||
// We give a little extra to the [0, 90] rotation segment to not get the camera rotation stuck.
|
||||
// If it doesn't work in some game we should revisit this.
|
||||
newRotationY = newRotationY > 180f ? Mathf.Clamp(newRotationY, 270f, 360f) : Mathf.Clamp(newRotationY, -1f, 90.0f);
|
||||
|
||||
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, transform.localEulerAngles.z);
|
||||
|
||||
// Apply the rotation changes while maintaining the camera's current roll.
|
||||
// Not using this method as it can easily modify the tilt, which is undesired.
|
||||
|
||||
/*float pitch = -mouseDelta.y * speedModifier * Time.deltaTime;
|
||||
float yaw = mouseDelta.x * speedModifier * Time.deltaTime;
|
||||
|
||||
Vector3 forwardDirection = transform.rotation * Vector3.forward;
|
||||
Vector3 rightDirection = transform.rotation * Vector3.right;
|
||||
Vector3 upDirection = transform.rotation * Vector3.up;
|
||||
|
||||
Quaternion pitchRotation = Quaternion.AngleAxis(pitch, rightDirection);
|
||||
Quaternion yawRotation = Quaternion.AngleAxis(yaw, upDirection);
|
||||
|
||||
transform.rotation = pitchRotation * yawRotation * transform.rotation;*/
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Decrease_FOV.Value))
|
||||
{
|
||||
FreeCamPanel.ourCamera.fieldOfView -= moveSpeed;
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Increase_FOV.Value))
|
||||
{
|
||||
FreeCamPanel.ourCamera.fieldOfView += moveSpeed;
|
||||
}
|
||||
|
||||
if (IInputManager.GetKey(ConfigManager.Reset_FOV.Value)){
|
||||
FreeCamPanel.ourCamera.fieldOfView = FreeCamPanel.usingGameCamera ? FreeCamPanel.originalCameraFOV : 60;
|
||||
}
|
||||
|
||||
FreeCamPanel.previousMousePosition = IInputManager.MousePosition;
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy UI class to unlock the cursor when freecam is active but the UI is hidden
|
||||
|
||||
@@ -109,8 +109,6 @@ namespace UnityExplorer.CatmullRom
|
||||
// Current position in the path, from 0 to 1
|
||||
float delta;
|
||||
|
||||
bool arePointsLocal;
|
||||
|
||||
float tension = 0;
|
||||
float alpha = 0.5f;
|
||||
|
||||
@@ -161,9 +159,6 @@ namespace UnityExplorer.CatmullRom
|
||||
closedLoop = newClosedLoop;
|
||||
}
|
||||
|
||||
public void setLocalPoints(bool newArePointsLocal){
|
||||
arePointsLocal = newArePointsLocal;
|
||||
}
|
||||
#if CPP
|
||||
[HideFromIl2Cpp]
|
||||
#endif
|
||||
@@ -185,8 +180,8 @@ namespace UnityExplorer.CatmullRom
|
||||
}
|
||||
|
||||
private CatmullRomPoint GetCurrentPoint(){
|
||||
Vector3 camPos = arePointsLocal ? FreeCamPanel.ourCamera.transform.localPosition : FreeCamPanel.ourCamera.transform.position;
|
||||
Quaternion camRot = arePointsLocal ? FreeCamPanel.ourCamera.transform.localRotation : FreeCamPanel.ourCamera.transform.rotation;
|
||||
Vector3 camPos = FreeCamPanel.GetCameraPosition();
|
||||
Quaternion camRot = FreeCamPanel.GetCameraRotation();
|
||||
|
||||
return new CatmullRomPoint(camPos, camRot, FreeCamPanel.ourCamera.fieldOfView);
|
||||
}
|
||||
@@ -216,7 +211,7 @@ namespace UnityExplorer.CatmullRom
|
||||
// While ends, need another lookaheadDelta for the next Update
|
||||
// It will do, at most, 2 iterations
|
||||
// We check a very small number instead of zero because if not it can get stuck in an infinite loop
|
||||
while (room <= 0.0001f) {
|
||||
while (room <= 0.0002f) {
|
||||
// If the camera reached the last lookAhead we stop it
|
||||
if (delta >= 1){
|
||||
PathFinished();
|
||||
@@ -241,25 +236,14 @@ namespace UnityExplorer.CatmullRom
|
||||
Vector4 newRot = ra + rb;
|
||||
newRot.Normalize();
|
||||
|
||||
if (arePointsLocal){
|
||||
FreeCamPanel.ourCamera.transform.localPosition += direction.position;
|
||||
FreeCamPanel.ourCamera.transform.localRotation = CatmullRomPoint.Vector4ToQuaternion(newRot);
|
||||
} else {
|
||||
FreeCamPanel.ourCamera.transform.position += direction.position;
|
||||
FreeCamPanel.ourCamera.transform.rotation = CatmullRomPoint.Vector4ToQuaternion(newRot);
|
||||
}
|
||||
|
||||
FreeCamPanel.SetCameraRotation(CatmullRomPoint.Vector4ToQuaternion(newRot));
|
||||
FreeCamPanel.SetCameraPosition(FreeCamPanel.GetCameraPosition() + direction.position);
|
||||
FreeCamPanel.ourCamera.fieldOfView += direction.fov * actual / room;
|
||||
}
|
||||
|
||||
public void MoveCameraToPoint(CatmullRomPoint newPoint){
|
||||
if (arePointsLocal){
|
||||
FreeCamPanel.ourCamera.transform.localPosition = newPoint.position;
|
||||
FreeCamPanel.ourCamera.transform.localRotation = newPoint.rotation;
|
||||
} else {
|
||||
FreeCamPanel.ourCamera.transform.position = newPoint.position;
|
||||
FreeCamPanel.ourCamera.transform.rotation = newPoint.rotation;
|
||||
}
|
||||
FreeCamPanel.SetCameraRotation(newPoint.rotation);
|
||||
FreeCamPanel.SetCameraPosition(newPoint.position);
|
||||
|
||||
FreeCamPanel.ourCamera.fieldOfView = newPoint.fov;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user