riversong code showcase
This commit is contained in:
126
Source/Riversong/Game/EditTools/BuildTool/BuildToolPreview.cs
Normal file
126
Source/Riversong/Game/EditTools/BuildTool/BuildToolPreview.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class BuildToolPreview
|
||||
{
|
||||
private readonly GameConfig.UIConfig.BuildToolConfig _config;
|
||||
|
||||
private readonly ITileSpace _tileSpace;
|
||||
|
||||
private BuildingDefinition _building;
|
||||
|
||||
private Vector3 _tilt;
|
||||
|
||||
private Vector3 _tiltVelocity;
|
||||
|
||||
private float _yaw;
|
||||
|
||||
private float _yawVelocity;
|
||||
|
||||
public BuildToolPreview(GameConfig.UIConfig.BuildToolConfig config, ITileSpace tileSpace)
|
||||
{
|
||||
_config = config;
|
||||
_tileSpace = tileSpace;
|
||||
}
|
||||
|
||||
public GameObject PreviewObject { get; private set; }
|
||||
|
||||
public bool IsVisible => PreviewObject && PreviewObject.activeSelf;
|
||||
|
||||
public float3 Position => PreviewObject ? PreviewObject.transform.position : Vector3.zero;
|
||||
|
||||
public void PrepareForBuilding(BuildingDefinition building)
|
||||
{
|
||||
_building = building;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
ClearPreviewObject();
|
||||
}
|
||||
|
||||
public void Update(bool isValid, Vector3 pointer, Directions orientation)
|
||||
{
|
||||
if (!PreviewObject)
|
||||
{
|
||||
if (_building.Visualization.IsDone)
|
||||
CreatePreviewObject();
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
var snap = !PreviewObject.activeSelf && isValid;
|
||||
if (snap)
|
||||
{
|
||||
_tilt = Vector3.zero;
|
||||
_tiltVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
PreviewObject.SetActive(isValid);
|
||||
if (!isValid) return;
|
||||
|
||||
var rect = TileMath.GetBuildingRect(_tileSpace.WorldToTile(pointer), orientation, _building.Width, _building.Height);
|
||||
var position = _tileSpace.GetRectWorldCenter(rect);
|
||||
position.y += _config.Height;
|
||||
|
||||
var dt = Time.unscaledDeltaTime;
|
||||
|
||||
position = snap ? position : Vector3.Lerp(PreviewObject.transform.position, position, _config.LerpFactor * dt);
|
||||
|
||||
var yaw = orientation.ToQuaternion().eulerAngles.y;
|
||||
_yaw = snap ? yaw : Mathf.SmoothDampAngle(_yaw, yaw, ref _yawVelocity, 0.1f, Mathf.Infinity, dt);
|
||||
var rotation = Quaternion.Euler(0, _yaw, 0);
|
||||
if (!snap) rotation = SimulateSpring(position, dt) * rotation;
|
||||
|
||||
PreviewObject.transform.SetPositionAndRotation(position, rotation);
|
||||
}
|
||||
|
||||
private Quaternion SimulateSpring(Vector3 targetPosition, float dt)
|
||||
{
|
||||
var positionDelta = targetPosition - PreviewObject.transform.position;
|
||||
|
||||
_tilt -= positionDelta * _config.ImpulseScale;
|
||||
_tilt = _tilt.normalized * Mathf.Min(_tilt.magnitude, _config.MaxTilt);
|
||||
|
||||
_tiltVelocity -= _tilt * (_config.Elasticity * dt);
|
||||
_tiltVelocity *= Mathf.Pow(1 - _config.Damping, dt);
|
||||
|
||||
_tilt += _tiltVelocity * dt;
|
||||
|
||||
if (_tilt.sqrMagnitude > 0.001f)
|
||||
{
|
||||
var axis = Vector3.Cross(Vector3.down, _tilt.normalized);
|
||||
var angle = _tilt.magnitude / _config.MaxTilt * _config.MaxTiltAngle;
|
||||
return Quaternion.AngleAxis(angle, axis);
|
||||
}
|
||||
|
||||
return Quaternion.identity;
|
||||
}
|
||||
|
||||
private void CreatePreviewObject()
|
||||
{
|
||||
PreviewObject = Object.Instantiate((GameObject)_building.Visualization.Asset);
|
||||
PreviewObject.SetLayerRecursively<Renderer>(GameObjectLayers.IgnoreAoE);
|
||||
|
||||
using var _ = ListPool<HideOnBuildingPreview>.Get(out var hide);
|
||||
PreviewObject.GetComponentsInChildren(hide);
|
||||
foreach (var obj in hide) obj.gameObject.SetActive(false);
|
||||
|
||||
// Start the preview in the disabled state, causes the position to be snapped when enabled
|
||||
PreviewObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void ClearPreviewObject()
|
||||
{
|
||||
if (PreviewObject)
|
||||
{
|
||||
Object.Destroy(PreviewObject);
|
||||
PreviewObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user