Added Feel plugin

This commit is contained in:
journaliciouz
2025-12-11 14:49:16 +01:00
parent 97dce4aaf6
commit 1942a531d4
2820 changed files with 257786 additions and 9 deletions

View File

@@ -0,0 +1,64 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
namespace MoreMountains.Tools
{
/// <summary>
/// A class to store ratio display info
/// </summary>
[Serializable]
public class Ratio
{
/// whether or not that ratio should be drawn
public bool DrawRatio = true;
/// the ratio's size (4:3, 16:9, etc)
public Vector2 Size;
/// the color of the handle to draw
public Color RatioColor;
public Ratio(bool drawRatio, Vector2 size, Color ratioColor)
{
DrawRatio = drawRatio;
Size = size;
RatioColor = ratioColor;
}
}
/// <summary>
/// A class to handle the automatic display of safe zones for the different ratios setup in the inspector
/// </summary>
[AddComponentMenu("More Mountains/Tools/Camera/MM Aspect Ratio Safe Zones")]
public class MMAspectRatioSafeZones : MonoBehaviour
{
[Header("Center")]
/// whether or not to draw the center crosshair
public bool DrawCenterCrosshair = true;
/// the size of the center crosshair
public float CenterCrosshairSize = 1f;
/// the color of the center crosshair
public Color CenterCrosshairColor = MMColors.Wheat;
[Header("Ratios")]
/// whether or not to draw any ratio
public bool DrawRatios = true;
/// the size of the projected ratios
public float CameraSize = 5f;
/// the opacity to apply to the dead zones
public float UnsafeZonesOpacity = 0.2f;
/// the list of ratios to draw
public List<Ratio> Ratios;
[MMInspectorButton("AutoSetup")]
public bool AutoSetupButton;
public virtual void AutoSetup()
{
Ratios.Clear();
Ratios.Add(new Ratio(true, new Vector2(16, 9), MMColors.DeepSkyBlue));
Ratios.Add(new Ratio(true, new Vector2(16, 10), MMColors.GreenYellow));
Ratios.Add(new Ratio(true, new Vector2(4, 3), MMColors.HotPink));
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1425f31c35afe2d43944511ec551d73b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMAspectRatioSafeZones.cs
uploadId: 830868

View File

@@ -0,0 +1,87 @@
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this class to an object (usually a sprite) and it'll face the camera at all times
/// </summary>
[AddComponentMenu("More Mountains/Tools/Camera/MM Billboard")]
public class MMBillboard : MonoBehaviour
{
/// the camera we're facing
public virtual Camera MainCamera { get; set; }
/// whether or not this object should automatically grab a camera on start
[Tooltip("whether or not this object should automatically grab a camera on start")]
public bool GrabMainCameraOnStart = true;
/// whether or not to nest this object below a parent container
[Tooltip("whether or not to nest this object below a parent container")]
public bool NestObject = true;
/// the Vector3 to offset the look at direction by
[Tooltip("the Vector3 to offset the look at direction by")]
public Vector3 OffsetDirection = Vector3.back;
/// the Vector3 to consider as "world up"
[Tooltip("the Vector3 to consider as 'world up'")]
public Vector3 Up = Vector3.up;
protected GameObject _parentContainer;
private Transform _transform;
/// <summary>
/// On awake we grab a camera if needed, and nest our object
/// </summary>
protected virtual void Awake()
{
_transform = transform;
if (GrabMainCameraOnStart == true)
{
GrabMainCamera ();
}
}
private void Start()
{
if (NestObject)
{
NestThisObject();
}
}
/// <summary>
/// Nests this object below a parent container
/// </summary>
protected virtual void NestThisObject()
{
_parentContainer = new GameObject();
SceneManager.MoveGameObjectToScene(_parentContainer, this.gameObject.scene);
_parentContainer.name = "Parent"+transform.gameObject.name;
_parentContainer.transform.position = transform.position;
transform.SetParent(_parentContainer.transform);
}
/// <summary>
/// Grabs the main camera.
/// </summary>
protected virtual void GrabMainCamera()
{
MainCamera = Camera.main;
}
/// <summary>
/// On update, we change our parent container's rotation to face the camera
/// </summary>
protected virtual void Update()
{
if (NestObject)
{
_parentContainer.transform.LookAt(_parentContainer.transform.position + MainCamera.transform.rotation * OffsetDirection, MainCamera.transform.rotation * Up);
}
else
{
_transform.LookAt(_transform.position + MainCamera.transform.rotation * OffsetDirection, MainCamera.transform.rotation * Up);
}
}
}
}

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 90e9b0613a9f9544580c1644719392dd
timeCreated: 1523900929
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMBillboard.cs
uploadId: 830868

View File

@@ -0,0 +1,95 @@
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace MoreMountains.Tools
{
[RequireComponent(typeof(Camera))]
/// <summary>
/// Forces an aspect ratio on a camera
/// </summary>
[AddComponentMenu("More Mountains/Tools/Camera/MM Camera Aspect Ratio")]
public class MMCameraAspectRatio : MonoBehaviour
{
public enum Modes { Fixed, ScreenRatio }
[Header("Camera")]
/// the camera to change the aspect ratio on
[Tooltip("the camera to change the aspect ratio on")]
public Camera TargetCamera;
/// the mode of choice, fixed will force a specified ratio, while ScreenRatio will adapt the camera's aspect to the current screen ratio
[Tooltip("the mode of choice, fixed will force a specified ratio, while ScreenRatio will adapt the camera's aspect to the current screen ratio")]
public Modes Mode = Modes.Fixed;
/// in fixed mode, the ratio to apply to the camera
[Tooltip("in fixed mode, the ratio to apply to the camera")]
[MMEnumCondition("Mode", (int)Modes.Fixed)]
public Vector2 FixedAspectRatio = Vector2.zero;
[Header("Automation")]
/// whether or not to apply the ratio automatically on Start
[Tooltip("whether or not to apply the ratio automatically on Start")]
public bool ApplyAspectRatioOnStart = true;
/// whether or not to apply the ratio automatically on enable
[Tooltip("whether or not to apply the ratio automatically on enable")]
public bool ApplyAspectRatioOnEnable = false;
[Header("Debug")]
[MMInspectorButton("ApplyAspectRatio")]
public bool ApplyAspectRatioButton;
protected float _defaultAspect = 16f / 9f;
/// <summary>
/// On enable we apply our aspect ratio if needed
/// </summary>
protected virtual void OnEnable()
{
if (ApplyAspectRatioOnEnable) { ApplyAspectRatio(); }
}
/// <summary>
/// On start we apply our aspect ratio if needed
/// </summary>
protected virtual void Start()
{
if (ApplyAspectRatioOnStart) { ApplyAspectRatio(); }
}
/// <summary>
/// Applies the specified aspect ratio
/// </summary>
public virtual void ApplyAspectRatio()
{
if (TargetCamera == null)
{
return;
}
float newAspectRatio = _defaultAspect;
float ratioX = 1f;
float ratioY = 1f;
switch (Mode)
{
case Modes.Fixed:
ratioX = FixedAspectRatio.x;
ratioY = FixedAspectRatio.y;
break;
case Modes.ScreenRatio:
#if UNITY_EDITOR
string[] res = UnityStats.screenRes.Split('x');
ratioX = int.Parse(res[0]);
ratioY = int.Parse(res[1]);
#else
ratioX = Screen.width;
ratioY = Screen.height;
#endif
break;
}
newAspectRatio = ratioY != 0f ? ratioX / ratioY : _defaultAspect;
TargetCamera.aspect = newAspectRatio;
}
}
}

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 6d09203129ac2e44a8fada3ae8c32667
timeCreated: 1523894079
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMCameraAspectRatio.cs
uploadId: 830868

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MoreMountains.Tools
{
/// <summary>
/// A simple class used to store fog properties
/// </summary>
[Serializable]
public class FogSettings
{
public bool FogEnabled = true;
public Color FogColor = Color.white;
public float FogDensity = 0.01f;
public UnityEngine.FogMode FogMode = FogMode.ExponentialSquared;
}
/// <summary>
/// Add this class to a camera and it will override fog settings when active
/// </summary>
[ExecuteAlways]
public class MMCameraFog : MonoBehaviour
{
/// the settings to use to override fog settings
public FogSettings Settings;
protected FogSettings _previousSettings;
protected void Awake()
{
_previousSettings = new FogSettings();
}
/// <summary>
/// On pre render we store our current fog settings and override them
/// </summary>
protected virtual void OnPreRender()
{
_previousSettings.FogEnabled = RenderSettings.fog;
_previousSettings.FogColor = RenderSettings.fogColor;
_previousSettings.FogDensity = RenderSettings.fogDensity;
_previousSettings.FogMode = RenderSettings.fogMode;
RenderSettings.fog = Settings.FogEnabled;
RenderSettings.fogColor = Settings.FogColor;
RenderSettings.fogDensity = Settings.FogDensity;
RenderSettings.fogMode = Settings.FogMode;
}
/// <summary>
/// On post render we restore fog settings
/// </summary>
protected virtual void OnPostRender()
{
RenderSettings.fog = _previousSettings.FogEnabled;
RenderSettings.fogColor = _previousSettings.FogColor;
RenderSettings.fogDensity = _previousSettings.FogDensity;
RenderSettings.fogMode = _previousSettings.FogMode;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 53e5d263afa31f84eba026d21225b8fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMCameraFog.cs
uploadId: 830868

View File

@@ -0,0 +1,242 @@
using UnityEngine;
using System.Collections;
using UnityEngine.Events;
namespace MoreMountains.Tools
{
/// <summary>
/// A class used to make a camera orbit around a target
/// </summary>
[AddComponentMenu("More Mountains/Tools/Camera/MM Orbital Camera")]
public class MMOrbitalCamera : MonoBehaviour
{
/// the possible input modes for this camera
public enum Modes { Mouse, Touch }
[Header("Setup")]
/// the selected input mode
public Modes Mode = Modes.Touch;
/// the object to orbit around
public Transform Target;
/// the offset to apply while orbiting
public Vector3 TargetOffset;
/// the current distance to target
[MMReadOnly]
public float DistanceToTarget = 5f;
[Header("Rotation")]
/// whether or not rotation is enabled
public bool RotationEnabled = true;
/// the speed of the rotation
public Vector2 RotationSpeed = new Vector2(200f, 200f);
/// the minimum vertical angle limit
public int MinVerticalAngleLimit = -80;
/// the maximum vertical angle limit
public int MaxVerticalAngleLimit = 80;
[Header("Zoom")]
/// whether or not zoom is enabled
public bool ZoomEnabled = true;
/// the minimum distance at which the user can zoom in
public float MinimumZoomDistance = 0.6f;
/// the max distance at which the user can zoom out
public float MaximumZoomDistance = 20;
/// the speed of the zoom interpolation
public int ZoomSpeed = 40;
/// the dampening to apply to the zoom
public float ZoomDampening = 5f;
[Header("Mouse Zoom")]
/// the speed at which scrolling the mouse wheel will zoom
public float MouseWheelSpeed = 10f;
/// the max value at which to clamp the mouse wheel
public float MaxMouseWheelClamp = 10f;
[Header("Steps")]
/// the distance after which to trigger a step
public float StepThreshold = 1;
/// an event to trigger when a step is met
public UnityEvent StepFeedback;
protected float _angleX = 0f;
protected float _angleY = 0f;
protected float _currentDistance;
protected float _desiredDistance;
protected Quaternion _currentRotation;
protected Quaternion _desiredRotation;
protected Quaternion _rotation;
protected Vector3 _position;
protected float _scrollWheelAmount = 0;
protected float _stepBuffer = 0f;
/// <summary>
/// On Start we initialize our orbital camera
/// </summary>
protected virtual void Start()
{
Initialization();
}
/// <summary>
/// On init we store our positions and rotations
/// </summary>
public virtual void Initialization()
{
// if no target is set, we throw an error and exit
if (Target == null)
{
Debug.LogError(this.gameObject.name + " : the MMOrbitalCamera doesn't have a target.");
return;
}
DistanceToTarget = Vector3.Distance(Target.position, transform.position);
_currentDistance = DistanceToTarget;
_desiredDistance = DistanceToTarget;
_position = transform.position;
_rotation = transform.rotation;
_currentRotation = transform.rotation;
_desiredRotation = transform.rotation;
_angleX = Vector3.Angle(Vector3.right, transform.right);
_angleY = Vector3.Angle(Vector3.up, transform.up);
}
/// <summary>
/// On late update we rotate, zoom, detect steps and finally apply our movement
/// </summary>
protected virtual void LateUpdate()
{
if (Target == null)
{
return;
}
Rotation();
Zoom();
StepDetection();
ApplyMovement();
}
/// <summary>
/// Rotates the camera around the object
/// </summary>
protected virtual void Rotation()
{
if (!RotationEnabled)
{
return;
}
if (Mode == Modes.Touch && (Input.touchCount > 0))
{
if ((Input.touches[0].phase == TouchPhase.Moved) && (Input.touchCount == 1))
{
float screenHeight = Screen.currentResolution.height;
if (Input.touches[0].position.y < screenHeight/4)
{
return;
}
float swipeSpeed = Input.touches[0].deltaPosition.magnitude / Input.touches[0].deltaTime;
_angleX += Input.touches[0].deltaPosition.x * RotationSpeed.x * Time.deltaTime * swipeSpeed * 0.00001f;
_angleY -= Input.touches[0].deltaPosition.y * RotationSpeed.y * Time.deltaTime * swipeSpeed * 0.00001f;
_stepBuffer += Input.touches[0].deltaPosition.x;
_angleY = MMMaths.ClampAngle(_angleY, MinVerticalAngleLimit, MaxVerticalAngleLimit);
_desiredRotation = Quaternion.Euler(_angleY, _angleX, 0);
_currentRotation = transform.rotation;
_rotation = Quaternion.Lerp(_currentRotation, _desiredRotation, Time.deltaTime * ZoomDampening);
transform.rotation = _rotation;
}
else if (Input.touchCount == 1 && Input.touches[0].phase == TouchPhase.Began)
{
_desiredRotation = transform.rotation;
}
if (transform.rotation != _desiredRotation)
{
_rotation = Quaternion.Lerp(transform.rotation, _desiredRotation, Time.deltaTime * ZoomDampening);
transform.rotation = _rotation;
}
}
else if (Mode == Modes.Mouse)
{
_angleX += Input.GetAxis("Mouse X") * RotationSpeed.x * Time.deltaTime;
_angleY += -Input.GetAxis("Mouse Y") * RotationSpeed.y * Time.deltaTime;
_angleY = Mathf.Clamp(_angleY, MinVerticalAngleLimit, MaxVerticalAngleLimit);
_desiredRotation = Quaternion.Euler(new Vector3(_angleY, _angleX, 0));
_currentRotation = transform.rotation;
_rotation = Quaternion.Lerp(_currentRotation, _desiredRotation, Time.deltaTime * ZoomDampening);
transform.rotation = _rotation;
}
}
/// <summary>
/// Detects steps
/// </summary>
protected virtual void StepDetection()
{
if (Mathf.Abs(_stepBuffer) > StepThreshold)
{
StepFeedback?.Invoke();
_stepBuffer = 0f;
}
}
/// <summary>
/// Zooms
/// </summary>
protected virtual void Zoom()
{
if (!ZoomEnabled)
{
return;
}
if (Mode == Modes.Touch && (Input.touchCount > 0))
{
if (Input.touchCount == 2)
{
Touch firstTouch = Input.GetTouch(0);
Touch secondTouch = Input.GetTouch(1);
Vector2 firstTouchPreviousPosition = firstTouch.position - firstTouch.deltaPosition;
Vector2 secondTouchPreviousPosition = secondTouch.position - secondTouch.deltaPosition;
float previousTouchDeltaMagnitude = (firstTouchPreviousPosition - secondTouchPreviousPosition).magnitude;
float thisTouchDeltaMagnitude = (firstTouch.position - secondTouch.position).magnitude;
float deltaMagnitudeDifference = previousTouchDeltaMagnitude - thisTouchDeltaMagnitude;
_desiredDistance += deltaMagnitudeDifference * Time.deltaTime * ZoomSpeed * Mathf.Abs(_desiredDistance) * 0.001f;
_desiredDistance = Mathf.Clamp(_desiredDistance, MinimumZoomDistance, MaximumZoomDistance);
_currentDistance = Mathf.Lerp(_currentDistance, _desiredDistance, Time.deltaTime * ZoomDampening);
}
}
else if (Mode == Modes.Mouse)
{
_scrollWheelAmount += - Input.GetAxis("Mouse ScrollWheel") * MouseWheelSpeed;
_scrollWheelAmount = Mathf.Clamp(_scrollWheelAmount, -MaxMouseWheelClamp, MaxMouseWheelClamp);
float deltaMagnitudeDifference = _scrollWheelAmount;
_desiredDistance += deltaMagnitudeDifference * Time.deltaTime * ZoomSpeed * Mathf.Abs(_desiredDistance) * 0.001f;
_desiredDistance = Mathf.Clamp(_desiredDistance, MinimumZoomDistance, MaximumZoomDistance);
_currentDistance = Mathf.Lerp(_currentDistance, _desiredDistance, Time.deltaTime * ZoomDampening);
}
}
/// <summary>
/// Moves the transform
/// </summary>
protected virtual void ApplyMovement()
{
_position = Target.position - (_rotation * Vector3.forward * _currentDistance + TargetOffset);
transform.position = _position;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6e8f18290b3c9ff499c82d3ff939754c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMOrbitalCamera.cs
uploadId: 830868

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this class to an object and it will automatically teleport to the other end of the screen when reaching the screen's edges
/// </summary>
public class MMViewportEdgeTeleporter : MonoBehaviour
{
[Header("Camera")]
/// whether or not to grab the Camera.main and store it on init
public bool AutoGrabMainCamera;
/// the camera used to compute viewport positions
public Camera MainCamera;
[Header("Viewport Bounds")]
/// the origin values of the viewport
[MMVector("X","Y")]
public Vector2 ViewportOrigin = new Vector2(0f, 0f);
/// the dimensions of the viewport
[MMVector("W","H")]
public Vector2 ViewportDimensions = new Vector2(1f, 1f);
[Header("Teleport Bounds")]
/// the origin of the teleport destination zone
[MMVector("X","Y")]
public Vector2 TeleportOrigin = new Vector2(0f, 0f);
/// the dimensions of the teleport destination zone
[MMVector("W","H")]
public Vector2 TeleportDimensions = new Vector2(1f, 1f);
[Header("Events")]
/// an event to trigger on teleport
public UnityEvent OnTeleport;
protected Vector3 _viewportPosition;
protected Vector3 _newViewportPosition;
/// <summary>
/// On Awake we initialize our teleporter
/// </summary>
protected virtual void Awake()
{
Initialization();
}
/// <summary>
/// Stores the main camera if needed
/// </summary>
protected virtual void Initialization()
{
if (AutoGrabMainCamera)
{
MainCamera = Camera.main;
}
}
/// <summary>
/// Sets a new camera
/// </summary>
/// <param name="newCamera"></param>
public virtual void SetCamera(Camera newCamera)
{
MainCamera = newCamera;
}
/// <summary>
/// On Update we check our position relative to the edges
/// </summary>
protected virtual void Update()
{
DetectEdges();
}
/// <summary>
/// Detects edges, compares with our object's position, and moves it if needed
/// </summary>
protected virtual void DetectEdges()
{
_viewportPosition = MainCamera.WorldToViewportPoint(this.transform.position);
bool teleport = false;
if (_viewportPosition.x < ViewportOrigin.x)
{
_newViewportPosition.x = TeleportDimensions.x;
_newViewportPosition.y = _viewportPosition.y;
_newViewportPosition.z = _viewportPosition.z;
teleport = true;
}
else if (_viewportPosition.x >= ViewportDimensions.x)
{
_newViewportPosition.x = TeleportOrigin.x;
_newViewportPosition.y = _viewportPosition.y;
_newViewportPosition.z = _viewportPosition.z;
teleport = true;
}
if (_viewportPosition.y < ViewportOrigin.y)
{
_newViewportPosition.x = _viewportPosition.x;
_newViewportPosition.y = TeleportDimensions.y;
_newViewportPosition.z = _viewportPosition.z;
teleport = true;
}
else if (_viewportPosition.y >= ViewportDimensions.y)
{
_newViewportPosition.x = _viewportPosition.x;
_newViewportPosition.y = TeleportOrigin.y;
_newViewportPosition.z = _viewportPosition.z;
teleport = true;
}
if (teleport)
{
OnTeleport?.Invoke();
this.transform.position = MainCamera.ViewportToWorldPoint(_newViewportPosition);
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a1fc9c7a40e1f2245a0a7c067509a2ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 183370
packageName: Feel
packageVersion: 5.9.1
assetPath: Assets/Feel/MMTools/Accessories/MMCamera/MMViewportEdgeTeleporter.cs
uploadId: 830868