备份CatanBuilding瘦身独立工程
This commit is contained in:
419
Assets/Scripts/EventWashing/Tools/BHitScreen.cs
Normal file
419
Assets/Scripts/EventWashing/Tools/BHitScreen.cs
Normal file
@@ -0,0 +1,419 @@
|
||||
using CW.Common;
|
||||
using PaintCore;
|
||||
using PaintIn3D;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class BHitScreen : BHitScreenBase
|
||||
{
|
||||
// This stores extra information for each finger unique to this component
|
||||
protected class Link : CwInputManager.Link
|
||||
{
|
||||
public float Age;
|
||||
public bool Down;
|
||||
public int State;
|
||||
public float Distance;
|
||||
public Vector2 ScreenDelta;
|
||||
public Vector2 ScreenOld;
|
||||
|
||||
public List<Vector2> History = new List<Vector2>();
|
||||
|
||||
public void Move(Vector2 screenNew)
|
||||
{
|
||||
if (State == 0)
|
||||
{
|
||||
ScreenOld = screenNew;
|
||||
State = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TryMove(screenNew) == true || State == 2)
|
||||
{
|
||||
State += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryMove(Vector2 screenNew)
|
||||
{
|
||||
var threshold = 2.0f;
|
||||
var distance = Vector2.Distance(ScreenOld, screenNew);
|
||||
|
||||
if (distance >= threshold)
|
||||
{
|
||||
ScreenOld = Vector2.MoveTowards(ScreenOld, screenNew, distance - threshold * 0.5f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
Age = 0.0f;
|
||||
Down = false;
|
||||
State = 0;
|
||||
Distance = 0.0f;
|
||||
ScreenDelta = Vector2.zero;
|
||||
ScreenOld = Vector2.zero;
|
||||
|
||||
History.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public enum FrequencyType
|
||||
{
|
||||
PixelInterval,
|
||||
ScaledPixelInterval,
|
||||
TimeInterval,
|
||||
OnceOnRelease,
|
||||
OnceOnPress,
|
||||
OnceEveryFrame
|
||||
}
|
||||
|
||||
/// <summary>This allows you to control how often the screen is painted.
|
||||
/// PixelInterval = Once every <b>Interval</b> pixels.
|
||||
/// ScaledPixelInterval = Like <b>PixelInterval</b>, but scaled to the screen DPI.
|
||||
/// TimeInterval = Once every <b>Interval</b> seconds.
|
||||
/// OnceOnRelease = When the finger/mouse goes down a preview will be shown, and when it goes up the paint will apply.
|
||||
/// OnceOnPress = When the finger/mouse goes down the paint will apply.
|
||||
/// OnceEveryFrame = Every frame the paint will apply.</summary>
|
||||
public FrequencyType Frequency { set { frequency = value; } get { return frequency; } }
|
||||
[SerializeField] private FrequencyType frequency = FrequencyType.OnceEveryFrame;
|
||||
|
||||
/// <summary>This allows you to set the pixels/seconds between each hit point based on the current <b>Frequency</b> setting.</summary>
|
||||
public float Interval { set { interval = value; } get { return interval; } }
|
||||
[SerializeField] private float interval = 10.0f;
|
||||
|
||||
/// <summary>This allows you to connect the hit points together to form lines.</summary>
|
||||
public CwPointConnector Connector { get { if (connector == null) connector = new CwPointConnector(); return connector; } }
|
||||
[SerializeField] private CwPointConnector connector;
|
||||
|
||||
[System.NonSerialized]
|
||||
private List<Link> links = new List<Link>();
|
||||
|
||||
/// <summary>This component sends hit events to a cached list of components that can receive them. If this list changes then you must manually call this method.</summary>
|
||||
[ContextMenu("Clear Hit Cache")]
|
||||
public void ClearHitCache()
|
||||
{
|
||||
Connector.ClearHitCache();
|
||||
}
|
||||
|
||||
/// <summary>If this GameObject has teleported and you have <b>ConnectHits</b> or <b>HitSpacing</b> enabled, then you can call this to prevent a line being drawn between the previous and current points.</summary>
|
||||
[ContextMenu("Reset Connections")]
|
||||
public void ResetConnections()
|
||||
{
|
||||
connector.ResetConnections();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
foreach (var link in links)
|
||||
{
|
||||
link.Clear();
|
||||
}
|
||||
|
||||
Connector.ResetConnections();
|
||||
|
||||
if (ShouldUpgradePointers() == true)
|
||||
{
|
||||
Debug.LogWarning("Upgrading CwHitScreen Controls - To remove this warning you can manually click the \"Upgrade\" button in the inspector of this component while outside of play mode.", gameObject);
|
||||
|
||||
TryUpgradePointers();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
connector.Update();
|
||||
}
|
||||
|
||||
public override void BreakFinger(CwInputManager.Finger finger)
|
||||
{
|
||||
var link = CwInputManager.Link.Find(links, finger);
|
||||
|
||||
if (link != null)
|
||||
{
|
||||
connector.BreakHits(link);
|
||||
}
|
||||
}
|
||||
|
||||
public override void HandleFingerUpdate(CwInputManager.Finger finger, bool down, bool up)
|
||||
{
|
||||
var link = CwInputManager.Link.Find(links, finger);
|
||||
var set = true;
|
||||
|
||||
if (finger.Index < 0) // Preview?
|
||||
{
|
||||
if (CwInputManager.PointOverGui(finger.ScreenPosition, GuiLayers) == true)
|
||||
{
|
||||
connector.BreakHits(link);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (down == true)
|
||||
{
|
||||
if (CwInputManager.PointOverGui(finger.ScreenPosition, GuiLayers) == true)
|
||||
{
|
||||
connector.BreakHits(link);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (link == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (link == null)
|
||||
{
|
||||
link = CwInputManager.Link.Create(ref links, finger);
|
||||
}
|
||||
|
||||
link.Move(finger.ScreenPosition);
|
||||
|
||||
if (finger.Index < 0) // Preview?
|
||||
{
|
||||
RecordAndPaintAt(link, finger.ScreenPosition, link.ScreenOld, true, 0.0f, link);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (NeedsDrawAngle == true)
|
||||
{
|
||||
down = link.State == 2;
|
||||
set = link.State >= 2;
|
||||
}
|
||||
|
||||
if (set == true)
|
||||
{
|
||||
switch (frequency)
|
||||
{
|
||||
case FrequencyType.PixelInterval: PaintSmooth(link, down, interval); break;
|
||||
case FrequencyType.ScaledPixelInterval: PaintSmooth(link, down, interval / CwInputManager.ScaleFactor); break;
|
||||
case FrequencyType.TimeInterval: PaintInterval(link, down); break;
|
||||
case FrequencyType.OnceOnRelease: PaintRelease(link, up); break;
|
||||
case FrequencyType.OnceOnPress: PaintPress(link, down); break;
|
||||
case FrequencyType.OnceEveryFrame: PaintEvery(link, down); break;
|
||||
}
|
||||
}
|
||||
|
||||
base.HandleFingerUpdate(finger, down, up);
|
||||
}
|
||||
|
||||
protected override void HandleFingerUp(CwInputManager.Finger finger)
|
||||
{
|
||||
var link = CwInputManager.Link.Find(links, finger);
|
||||
|
||||
if (link != null)
|
||||
{
|
||||
connector.BreakHits(link);
|
||||
|
||||
OnFingerUp(link);
|
||||
|
||||
link.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void PaintSmooth(Link link, bool down, float pixelSpacing)
|
||||
{
|
||||
var head = link.Finger.GetSmoothScreenPosition(0.0f);
|
||||
|
||||
if (down == true || link.History.Count == 0)
|
||||
{
|
||||
if (storeStates == true)
|
||||
{
|
||||
CwStateManager.PotentiallyStoreAllStates();
|
||||
}
|
||||
|
||||
RecordAndPaintAt(link, link.Finger.ScreenPosition, link.ScreenOld, false, link.Finger.Pressure, link);
|
||||
}
|
||||
|
||||
if (pixelSpacing > 0.0f)
|
||||
{
|
||||
var steps = Mathf.Max(1, Mathf.FloorToInt(link.Finger.SmoothScreenPositionDelta));
|
||||
var step = CwHelper.Reciprocal(steps);
|
||||
|
||||
for (var i = 0; i <= steps; i++)
|
||||
{
|
||||
var next = link.Finger.GetSmoothScreenPosition(Mathf.Clamp01(i * step));
|
||||
var dist = Vector2.Distance(head, next);
|
||||
var gaps = Mathf.FloorToInt((link.Distance + dist) / pixelSpacing);
|
||||
|
||||
for (var j = 0; j < gaps; j++)
|
||||
{
|
||||
var remainder = pixelSpacing - link.Distance;
|
||||
|
||||
head = Vector2.MoveTowards(head, next, remainder);
|
||||
|
||||
RecordAndPaintAt(link, head, link.History[link.History.Count - 1], false, link.Finger.Pressure, link);
|
||||
|
||||
dist -= remainder;
|
||||
|
||||
link.Distance = 0.0f;
|
||||
}
|
||||
|
||||
link.Distance += dist;
|
||||
head = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnFingerUp(Link link)
|
||||
{
|
||||
}
|
||||
|
||||
private void PaintInterval(Link link, bool down)
|
||||
{
|
||||
if (down == true)
|
||||
{
|
||||
if (storeStates == true)
|
||||
{
|
||||
CwStateManager.PotentiallyStoreAllStates();
|
||||
}
|
||||
|
||||
link.Age = interval;
|
||||
}
|
||||
|
||||
link.Age += Time.deltaTime;
|
||||
|
||||
if (link.Age >= interval)
|
||||
{
|
||||
if (interval > 0.0f)
|
||||
{
|
||||
link.Age %= interval;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.Age = 0.0f;
|
||||
}
|
||||
|
||||
RecordAndPaintAt(link, link.Finger.ScreenPosition, link.ScreenOld, false, link.Finger.Pressure, link);
|
||||
}
|
||||
}
|
||||
|
||||
private void PaintRelease(Link link, bool up)
|
||||
{
|
||||
var preview = true;
|
||||
|
||||
if (up == true)
|
||||
{
|
||||
preview = false;
|
||||
|
||||
if (storeStates == true)
|
||||
{
|
||||
CwStateManager.PotentiallyStoreAllStates();
|
||||
}
|
||||
}
|
||||
|
||||
RecordAndPaintAt(link, link.Finger.ScreenPosition, link.ScreenOld, preview, link.Finger.Pressure, link);
|
||||
}
|
||||
|
||||
private void PaintPress(Link link, bool down)
|
||||
{
|
||||
if (down == true)
|
||||
{
|
||||
if (storeStates == true)
|
||||
{
|
||||
CwStateManager.PotentiallyStoreAllStates();
|
||||
}
|
||||
|
||||
RecordAndPaintAt(link, link.Finger.ScreenPosition, link.ScreenOld, false, link.Finger.Pressure, link);
|
||||
}
|
||||
}
|
||||
|
||||
private void PaintEvery(Link link, bool down)
|
||||
{
|
||||
if (down == true)
|
||||
{
|
||||
if (storeStates == true)
|
||||
{
|
||||
CwStateManager.PotentiallyStoreAllStates();
|
||||
}
|
||||
}
|
||||
|
||||
RecordAndPaintAt(link, link.Finger.ScreenPosition, link.ScreenOld, false, link.Finger.Pressure, link);
|
||||
}
|
||||
|
||||
private void RecordAndPaintAt(Link link, Vector2 screenNew, Vector2 screenOld, bool preview, float pressure, object owner)
|
||||
{
|
||||
link.History.Add(screenNew);
|
||||
|
||||
PaintAt(connector, connector.HitCache, screenNew, screenOld, preview, pressure, owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace game
|
||||
{
|
||||
using UnityEditor;
|
||||
using TARGET = BHitScreen;
|
||||
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TARGET))]
|
||||
public class BHitScreen_Editor : CwHitScreenBase_Editor
|
||||
{
|
||||
protected override void OnInspector()
|
||||
{
|
||||
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
|
||||
|
||||
base.OnInspector();
|
||||
|
||||
Separator();
|
||||
|
||||
DrawBasic();
|
||||
|
||||
Separator();
|
||||
|
||||
DrawAdvancedFoldout();
|
||||
|
||||
Separator();
|
||||
|
||||
var point = tgt.Emit == BHitScreenBase.EmitType.PointsIn3D;
|
||||
var line = tgt.Emit == BHitScreenBase.EmitType.PointsIn3D && tgt.Connector.ConnectHits == true;
|
||||
var triangle = tgt.Emit == BHitScreenBase.EmitType.TrianglesIn3D;
|
||||
var coord = tgt.Emit == BHitScreenBase.EmitType.PointsOnUV;
|
||||
|
||||
tgt.Connector.HitCache.Inspector(tgt.gameObject, point: point, line: line, triangle: triangle, coord: coord);
|
||||
}
|
||||
|
||||
protected override void DrawBasic()
|
||||
{
|
||||
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
|
||||
|
||||
base.DrawBasic();
|
||||
|
||||
Draw("frequency", "This allows you to control how often the screen is painted.\n\nPixelInterval = Once every Interval pixels.\n\nScaledPixelInterval = Once every Interval scaled pixels.\n\nTimeInterval = Once every Interval seconds.\n\nOnceOnRelease = When the finger/mouse goes down a preview will be shown, and when it goes up the paint will apply.\n\nOnceOnPress = When the finger/mouse goes down the paint will apply.\n\nOnceEveryFrame = Every frame the paint will apply.");
|
||||
if (Any(tgts, t => t.Frequency == BHitScreen.FrequencyType.PixelInterval || t.Frequency == BHitScreen.FrequencyType.ScaledPixelInterval || t.Frequency == BHitScreen.FrequencyType.TimeInterval))
|
||||
{
|
||||
BeginIndent();
|
||||
BeginError(Any(tgts, t => t.Interval <= 0.0f));
|
||||
Draw("interval", "This allows you to set the pixels/seconds between each hit point based on the current Frequency setting.");
|
||||
EndError();
|
||||
EndIndent();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DrawAdvanced()
|
||||
{
|
||||
base.DrawAdvanced();
|
||||
|
||||
Separator();
|
||||
|
||||
CwPointConnector_Editor.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/Scripts/EventWashing/Tools/BHitScreen.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/BHitScreen.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 623b6c15fb081f3408bd04cbf9b5e520
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
360
Assets/Scripts/EventWashing/Tools/BHitScreenBase.cs
Normal file
360
Assets/Scripts/EventWashing/Tools/BHitScreenBase.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
using CW.Common;
|
||||
using PaintCore;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
/// <summary>This class contains common code for screen based mouse/finger hit components.</summary>
|
||||
public abstract class BHitScreenBase : CwHitPointers
|
||||
{
|
||||
public enum RotationType
|
||||
{
|
||||
Normal,
|
||||
World,
|
||||
ThisRotation,
|
||||
ThisLocalRotation,
|
||||
CustomRotation,
|
||||
CustomLocalRotation
|
||||
}
|
||||
|
||||
public enum RelativeType
|
||||
{
|
||||
WorldUp,
|
||||
CameraUp,
|
||||
DrawAngle
|
||||
}
|
||||
|
||||
public enum DirectionType
|
||||
{
|
||||
HitNormal,
|
||||
RayDirection,
|
||||
CameraDirection
|
||||
}
|
||||
|
||||
public enum EmitType
|
||||
{
|
||||
PointsIn3D = 0,
|
||||
PointsOnUV = 20,
|
||||
TrianglesIn3D = 30
|
||||
}
|
||||
|
||||
[System.Flags]
|
||||
public enum ButtonTypes
|
||||
{
|
||||
LeftMouse = 1 << 0,
|
||||
RightMouse = 1 << 1,
|
||||
MiddleMouse = 1 << 2,
|
||||
Touch = 1 << 5
|
||||
}
|
||||
|
||||
/// <summary>Orient to a specific camera?
|
||||
/// None = MainCamera.</summary>
|
||||
public Camera Camera { set { _camera = value; } get { return _camera; } }
|
||||
[SerializeField] private Camera _camera;
|
||||
|
||||
/// <summary>The layers you want the raycast to hit.</summary>
|
||||
public LayerMask Layers { set { layers = value; } get { return layers; } }
|
||||
[SerializeField] private LayerMask layers = Physics.DefaultRaycastLayers;
|
||||
|
||||
/// <summary>This allows you to control the hit data this component sends out.
|
||||
/// PointsIn3D = Point drawing in 3D.
|
||||
/// PointsOnUV = Point drawing on UV (requires non-convex <b>MeshCollider</b>).
|
||||
/// TrianglesIn3D = Triangle drawing in 3D (requires non-convex <b>MeshCollider</b>).</summary>
|
||||
public EmitType Emit { set { emit = value; } get { return emit; } }
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("draw")][SerializeField] private EmitType emit;
|
||||
|
||||
/// <summary>This allows you to control how the paint is rotated.
|
||||
/// Normal = The rotation will be based on a normal direction, and rolled relative to an up axis.
|
||||
/// World = The rotation will be aligned to the world, or given no rotation.
|
||||
/// ThisRotation = The current <b>Transform.rotation</b> will be used.
|
||||
/// ThisLocalRotation = The current <b>Transform.localRotation</b> will be used.
|
||||
/// CustomRotation = The specified <b>CustomTransform.rotation</b> will be used.
|
||||
/// CustomLocalRotation = The specified <b>CustomTransform.localRotation</b> will be used.</summary>
|
||||
public RotationType RotateTo { set { rotateTo = value; } get { return rotateTo; } }
|
||||
[SerializeField] private RotationType rotateTo;
|
||||
|
||||
/// <summary>Which direction should the hit point rotation be based on?</summary>
|
||||
public DirectionType NormalDirection { set { normalDirection = value; } get { return normalDirection; } }
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("normal")][SerializeField] private DirectionType normalDirection = DirectionType.CameraDirection;
|
||||
|
||||
/// <summary>Based on the normal direction, what should the rotation be rolled relative to?
|
||||
/// WorldUp = It will be rolled so the up vector is world up.
|
||||
/// CameraUp = It will be rolled so the up vector is camera up.
|
||||
/// DrawAngle = It will be rolled according to the mouse/finger movement on screen.</summary>
|
||||
public RelativeType NormalRelativeTo { set { normalRelativeTo = value; } get { return normalRelativeTo; } }
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("orientation")][SerializeField] private RelativeType normalRelativeTo = RelativeType.CameraUp;
|
||||
|
||||
/// <summary>This allows you to specify the <b>Transform</b> when using <b>RotateTo = CustomRotation/CustomLocalRotation</b>.</summary>
|
||||
public Transform CustomTransform { set { customTransform = value; } get { return customTransform; } }
|
||||
[SerializeField] private Transform customTransform;
|
||||
|
||||
/// <summary>Should painting triggered from this component be eligible for being undone?</summary>
|
||||
public bool StoreStates { set { storeStates = value; } get { return storeStates; } }
|
||||
[SerializeField] protected bool storeStates = true;
|
||||
|
||||
/// <summary>This allows you to override the order this paint gets applied to the object during the current frame.</summary>
|
||||
public int Priority { set { priority = value; } get { return priority; } }
|
||||
[SerializeField] private int priority;
|
||||
|
||||
/// <summary>If you want the raycast hit point to be offset from the surface a bit, this allows you to set by how much in world space.</summary>
|
||||
public float NormalOffset { set { normalOffset = value; } get { return normalOffset; } }
|
||||
[SerializeField] private float normalOffset;
|
||||
|
||||
// No longer used
|
||||
[SerializeField] private ButtonTypes requiredButtons;
|
||||
|
||||
// No longer used
|
||||
[SerializeField] private KeyCode requiredKey;
|
||||
|
||||
// No longer used
|
||||
[SerializeField] private float mouseOffset;
|
||||
|
||||
// No longer used
|
||||
[SerializeField] private float touchOffset;
|
||||
|
||||
// No longer used
|
||||
[SerializeField] private bool showPreview;
|
||||
|
||||
private static Transform m_TargetTransform = null;
|
||||
public static void SetTargetTransform(Transform targetTransform)
|
||||
{
|
||||
m_TargetTransform = targetTransform;
|
||||
}
|
||||
|
||||
public bool NeedsDrawAngle
|
||||
{
|
||||
get
|
||||
{
|
||||
return rotateTo == RotationType.Normal && normalRelativeTo == RelativeType.DrawAngle;
|
||||
}
|
||||
}
|
||||
|
||||
private bool m_IsAuthorizedDrawing = false;
|
||||
public void AuthorizedDrawing()
|
||||
{
|
||||
m_IsAuthorizedDrawing = true;
|
||||
}
|
||||
public void NotAuthorizedDrawing()
|
||||
{
|
||||
m_IsAuthorizedDrawing = false;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected virtual void Reset()
|
||||
{
|
||||
if (GetComponent<CwPointerMouse>() == null)
|
||||
{
|
||||
requiredButtons &= ~ButtonTypes.LeftMouse;
|
||||
requiredButtons &= ~ButtonTypes.RightMouse;
|
||||
requiredButtons &= ~ButtonTypes.MiddleMouse;
|
||||
|
||||
gameObject.AddComponent<CwPointerMouse>();
|
||||
}
|
||||
|
||||
if (GetComponent<CwPointerTouch>() == null)
|
||||
{
|
||||
requiredButtons &= ~ButtonTypes.Touch;
|
||||
|
||||
gameObject.AddComponent<CwPointerTouch>();
|
||||
}
|
||||
|
||||
if (GetComponent<CwPointerPen>() == null)
|
||||
{
|
||||
gameObject.AddComponent<CwPointerPen>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool ShouldUpgradePointers()
|
||||
{
|
||||
return (requiredButtons & ButtonTypes.LeftMouse) != 0
|
||||
|| (requiredButtons & ButtonTypes.RightMouse) != 0
|
||||
|| (requiredButtons & ButtonTypes.MiddleMouse) != 0
|
||||
|| (requiredButtons & ButtonTypes.Touch) != 0;
|
||||
}
|
||||
|
||||
public void TryUpgradePointers()
|
||||
{
|
||||
var lmb = (requiredButtons & ButtonTypes.LeftMouse) != 0;
|
||||
var rmb = (requiredButtons & ButtonTypes.RightMouse) != 0;
|
||||
var mmb = (requiredButtons & ButtonTypes.MiddleMouse) != 0;
|
||||
|
||||
if (lmb == true || rmb == true || mmb == true)
|
||||
{
|
||||
requiredButtons &= ~ButtonTypes.LeftMouse;
|
||||
requiredButtons &= ~ButtonTypes.RightMouse;
|
||||
requiredButtons &= ~ButtonTypes.MiddleMouse;
|
||||
|
||||
var pointerMouse = gameObject.AddComponent<CwPointerMouse>();
|
||||
|
||||
pointerMouse.Preview = showPreview;
|
||||
|
||||
if (lmb == true)
|
||||
{
|
||||
pointerMouse.TryAddKey(KeyCode.Mouse0);
|
||||
}
|
||||
|
||||
if (rmb == true)
|
||||
{
|
||||
pointerMouse.TryAddKey(KeyCode.Mouse1);
|
||||
}
|
||||
|
||||
if (mmb == true)
|
||||
{
|
||||
pointerMouse.TryAddKey(KeyCode.Mouse2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((requiredButtons & ButtonTypes.Touch) != 0)
|
||||
{
|
||||
requiredButtons &= ~ButtonTypes.Touch;
|
||||
|
||||
var pointerTouch = gameObject.AddComponent<CwPointerTouch>();
|
||||
|
||||
pointerTouch.Offset = touchOffset;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DoQuery(Vector2 screenPosition, ref Camera camera, ref Ray ray, ref CwHit hit3D, ref RaycastHit2D hit2D)
|
||||
{
|
||||
var hit = default(RaycastHit);
|
||||
|
||||
camera = CwHelper.GetCamera(_camera);
|
||||
ray = camera.ScreenPointToRay(screenPosition);
|
||||
hit2D = Physics2D.GetRayIntersection(ray, float.PositiveInfinity, layers);
|
||||
|
||||
Physics.Raycast(ray, out hit, float.PositiveInfinity, layers);
|
||||
|
||||
hit3D = new CwHit(hit);
|
||||
}
|
||||
|
||||
protected void PaintAt(CwPointConnector connector, CwHitCache hitCache, Vector2 screenPosition, Vector2 screenPositionOld, bool preview, float pressure, object owner)
|
||||
{
|
||||
var camera = default(Camera);
|
||||
var ray = default(Ray);
|
||||
var hit2D = default(RaycastHit2D);
|
||||
var hit3D = default(CwHit);
|
||||
var finalPosition = default(Vector3);
|
||||
var finalRotation = default(Quaternion);
|
||||
|
||||
DoQuery(screenPosition, ref camera, ref ray, ref hit3D, ref hit2D);
|
||||
|
||||
var valid2D = hit2D.distance > 0.0f;
|
||||
var valid3D = hit3D.Distance > 0.0f;
|
||||
|
||||
// Hit 3D?
|
||||
if (valid3D == true && (valid2D == false || hit3D.Distance < hit2D.distance))
|
||||
{
|
||||
CalcHitData(hit3D.Position, hit3D.Normal, ray, camera, screenPositionOld, ref finalPosition, ref finalRotation);
|
||||
|
||||
if (emit == EmitType.PointsIn3D)
|
||||
{
|
||||
if (connector != null)
|
||||
{
|
||||
if (m_TargetTransform != null && hit3D.Transform != m_TargetTransform) { return; }
|
||||
if (m_IsAuthorizedDrawing)
|
||||
{
|
||||
connector.SubmitPoint(gameObject, preview, priority, pressure, finalPosition, finalRotation, owner);
|
||||
}
|
||||
FishingYachtAct.Publish<EventWashingCleanerFollowPositionData>(new EventWashingCleanerFollowPositionData(finalPosition, hit3D.Normal));
|
||||
}
|
||||
else
|
||||
{
|
||||
hitCache.InvokePoint(gameObject, preview, priority, pressure, finalPosition, finalRotation);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (emit == EmitType.PointsOnUV)
|
||||
{
|
||||
hitCache.InvokeCoord(gameObject, preview, priority, pressure, hit3D, finalRotation);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (emit == EmitType.TrianglesIn3D)
|
||||
{
|
||||
hitCache.InvokeTriangle(gameObject, preview, priority, pressure, hit3D, finalRotation);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Hit 2D?
|
||||
else if (valid2D == true)
|
||||
{
|
||||
CalcHitData(hit2D.point, new Vector3(0.0f, 0.0f, -1.0f), ray, camera, screenPositionOld, ref finalPosition, ref finalRotation);
|
||||
|
||||
if (emit == EmitType.PointsIn3D)
|
||||
{
|
||||
if (connector != null)
|
||||
{
|
||||
connector.SubmitPoint(gameObject, preview, priority, pressure, finalPosition, finalRotation, owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
hitCache.InvokePoint(gameObject, preview, priority, pressure, finalPosition, finalRotation);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (connector != null)
|
||||
{
|
||||
connector.BreakHits(owner);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalcHitData(Vector3 hitPoint, Vector3 hitNormal, Ray ray, Camera camera, Vector2 screenPositionOld, ref Vector3 finalPosition, ref Quaternion finalRotation)
|
||||
{
|
||||
finalPosition = hitPoint + hitNormal * normalOffset;
|
||||
finalRotation = Quaternion.identity;
|
||||
|
||||
switch (rotateTo)
|
||||
{
|
||||
case RotationType.Normal:
|
||||
{
|
||||
var finalNormal = default(Vector3);
|
||||
|
||||
switch (normalDirection)
|
||||
{
|
||||
case DirectionType.HitNormal: finalNormal = hitNormal; break;
|
||||
case DirectionType.RayDirection: finalNormal = -ray.direction; break;
|
||||
case DirectionType.CameraDirection: finalNormal = -camera.transform.forward; break;
|
||||
}
|
||||
|
||||
var finalUp = Vector3.up;
|
||||
|
||||
switch (normalRelativeTo)
|
||||
{
|
||||
case RelativeType.CameraUp: finalUp = camera.transform.up; break;
|
||||
case RelativeType.DrawAngle:
|
||||
{
|
||||
var rayOld = camera.ScreenPointToRay(screenPositionOld);
|
||||
|
||||
if (camera.orthographic == true)
|
||||
{
|
||||
finalUp = Vector3.Cross(rayOld.GetPoint(1.0f) - ray.origin, ray.GetPoint(1.0f) - ray.origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
finalUp = Vector3.Cross(rayOld.direction, ray.direction);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
finalRotation = Quaternion.LookRotation(-finalNormal, finalUp);
|
||||
}
|
||||
break;
|
||||
case RotationType.World: finalRotation = Quaternion.identity; break;
|
||||
case RotationType.ThisRotation: finalRotation = transform.rotation; break;
|
||||
case RotationType.ThisLocalRotation: finalRotation = transform.localRotation; break;
|
||||
case RotationType.CustomRotation: if (customTransform != null) finalRotation = customTransform.rotation; break;
|
||||
case RotationType.CustomLocalRotation: if (customTransform != null) finalRotation = customTransform.localRotation; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/BHitScreenBase.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/BHitScreenBase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed4ded6cb8412cd49ad4d1b9ed2a5678
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
105
Assets/Scripts/EventWashing/Tools/BrushChannelCounterFill.cs
Normal file
105
Assets/Scripts/EventWashing/Tools/BrushChannelCounterFill.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using PaintCore;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace game
|
||||
{
|
||||
/// <summary>This component fills the attached UI Image based on the total amount of opaque pixels that have been painted in all active and enabled <b>CwChannelCounter</b> components in the scene.</summary>
|
||||
[RequireComponent(typeof(Image))]
|
||||
public class BrushChannelCounterFill : MonoBehaviour
|
||||
{
|
||||
public enum ChannelType
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Alpha
|
||||
}
|
||||
|
||||
/// <summary>This allows you to specify the counters that will be used.
|
||||
/// Zero = All active and enabled counters in the scene.</summary>
|
||||
public List<CwChannelCounter> Counters { get { if (counters == null) counters = new List<CwChannelCounter>(); return counters; } }
|
||||
[SerializeField] private List<CwChannelCounter> counters;
|
||||
|
||||
/// <summary>This allows you to choose which channel will be output to the UI Image.</summary>
|
||||
public ChannelType Channel { set { channel = value; } get { return channel; } }
|
||||
[SerializeField] private ChannelType channel;
|
||||
|
||||
/// <summary>Inverse the fill?</summary>
|
||||
public bool Inverse { set { inverse = value; } get { return inverse; } }
|
||||
[SerializeField] private bool inverse;
|
||||
|
||||
private static float m_OmitPercentage = 0.1f;
|
||||
|
||||
public static float OmitPercentage { get => m_OmitPercentage; set => m_OmitPercentage = value; }
|
||||
|
||||
private bool m_IsOver = false;
|
||||
|
||||
[System.NonSerialized]
|
||||
private Image cachedImage;
|
||||
|
||||
private bool m_IsStopping = false;
|
||||
|
||||
public void ResetData()
|
||||
{
|
||||
m_IsOver = false;
|
||||
}
|
||||
|
||||
public void StopCounting()
|
||||
{
|
||||
m_IsStopping = true;
|
||||
}
|
||||
public void StartCounting()
|
||||
{
|
||||
m_IsStopping = false;
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
cachedImage = GetComponent<Image>();
|
||||
m_IsOver = false;
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (m_IsStopping) return;
|
||||
var finalCounters = counters.Count > 0 ? counters : null;
|
||||
var ratio = 0.0f;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case ChannelType.Red: ratio = CwChannelCounter.GetRatioR(finalCounters); break;
|
||||
case ChannelType.Green: ratio = CwChannelCounter.GetRatioG(finalCounters); break;
|
||||
case ChannelType.Blue: ratio = CwChannelCounter.GetRatioB(finalCounters); break;
|
||||
case ChannelType.Alpha: ratio = CwChannelCounter.GetRatioA(finalCounters); break;
|
||||
}
|
||||
|
||||
if (inverse == true)
|
||||
{
|
||||
ratio = 1.0f - ratio;
|
||||
}
|
||||
|
||||
FishingYachtAct.Publish<EventWashingMonitoringFoamProgressData>(new EventWashingMonitoringFoamProgressData(ratio));
|
||||
|
||||
if (1 - ratio <= BrushChannelCounterFill.m_OmitPercentage)
|
||||
{
|
||||
if (m_IsOver == false)
|
||||
{
|
||||
FishingYachtAct.Publish<EventWashingConclusionData>(new EventWashingConclusionData());
|
||||
m_IsOver = true;
|
||||
}
|
||||
|
||||
cachedImage.fillAmount = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float tmp = 1f - BrushChannelCounterFill.m_OmitPercentage;
|
||||
float realProgress = ratio / tmp;
|
||||
|
||||
cachedImage.fillAmount = Mathf.Clamp01(realProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8fdfd5b58cbf79143a8b9f55919fe9b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
Assets/Scripts/EventWashing/Tools/BrushPointerMouse.cs
Normal file
136
Assets/Scripts/EventWashing/Tools/BrushPointerMouse.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using CW.Common;
|
||||
using PaintCore;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace game
|
||||
{
|
||||
[RequireComponent(typeof(CwHitPointers))]
|
||||
public class BrushPointerMouse : CwPointer
|
||||
{
|
||||
public Vector2 Offset { set { offset = value; } get { return offset; } }
|
||||
[SerializeField] private Vector2 offset = Vector2.zero;
|
||||
|
||||
/// <summary>If you enable this, then a paint preview will be shown under the mouse as long as the <b>RequiredKey</b> is not pressed.</summary>
|
||||
public bool Preview { set { preview = value; } get { return preview; } }
|
||||
[SerializeField] private bool preview;
|
||||
|
||||
/// <summary>This component will paint while any of the specified mouse buttons or keyboard keys are held.</summary>
|
||||
public List<KeyCode> Keys { get { if (keys == null) { keys = new List<KeyCode>(); } return keys; } }
|
||||
[SerializeField] private List<KeyCode> keys;
|
||||
|
||||
private readonly int PREVIEW_FINGER_INDEX = -1;
|
||||
|
||||
private readonly int PAINT_FINGER_INDEX = 1;
|
||||
|
||||
[System.NonSerialized]
|
||||
private bool oldHeld;
|
||||
|
||||
public bool TryAddKey(KeyCode key)
|
||||
{
|
||||
if (Keys.Contains(key) == false)
|
||||
{
|
||||
keys.Add(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetKeyHeld()
|
||||
{
|
||||
if (keys != null)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (CwInput.GetKeyIsHeld(key) == true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected virtual void Reset()
|
||||
{
|
||||
if (keys == null)
|
||||
{
|
||||
keys = new List<KeyCode>();
|
||||
}
|
||||
else
|
||||
{
|
||||
keys.Clear();
|
||||
}
|
||||
|
||||
keys.Add(KeyCode.Mouse0);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
var newHeld = false;
|
||||
var enablePreview = false;
|
||||
var enablePaint = false;
|
||||
|
||||
bool isFollowing = false;
|
||||
Vector2 screenPosition = Vector2.zero;
|
||||
|
||||
if (CwInput.GetMouseExists() == true)
|
||||
{
|
||||
CwInputManager.Finger finger;
|
||||
|
||||
newHeld = GetKeyHeld();
|
||||
enablePaint = newHeld == true || oldHeld == true;
|
||||
enablePreview = preview == true && enablePaint == false;
|
||||
|
||||
Vector2 position = CwInput.GetMousePosition();
|
||||
position += offset * CwInputManager.ScaleFactor;
|
||||
|
||||
if (enablePreview == true)
|
||||
{
|
||||
GetFinger(PREVIEW_FINGER_INDEX, position, 1.0f, true, out finger);
|
||||
|
||||
cachedHitPointers.HandleFingerUpdate(finger, false, false);
|
||||
|
||||
screenPosition = position;
|
||||
isFollowing = true;
|
||||
}
|
||||
|
||||
if (enablePaint == true)
|
||||
{
|
||||
if (EventSystem.current == null) return;
|
||||
|
||||
if (EventSystem.current.IsPointerOverGameObject()) return;
|
||||
|
||||
var down = GetFinger(PAINT_FINGER_INDEX, position, 1.0f, true, out finger);
|
||||
|
||||
cachedHitPointers.HandleFingerUpdate(finger, down, newHeld == false);
|
||||
|
||||
screenPosition = position;
|
||||
isFollowing = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFollowing) FishingYachtAct.Publish<EventWashingGestureFollowPositionData>(new EventWashingGestureFollowPositionData(screenPosition, true));
|
||||
else FishingYachtAct.Publish<EventWashingGestureFollowPositionData>(new EventWashingGestureFollowPositionData(screenPosition, false));
|
||||
|
||||
if (enablePreview == false)
|
||||
{
|
||||
TryNullFinger(PREVIEW_FINGER_INDEX);
|
||||
}
|
||||
|
||||
if (enablePaint == false)
|
||||
{
|
||||
TryNullFinger(PAINT_FINGER_INDEX);
|
||||
}
|
||||
|
||||
oldHeld = newHeld;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/BrushPointerMouse.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/BrushPointerMouse.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a76738f841592a4fb2fded5869f4534
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/Scripts/EventWashing/Tools/BrushPointerTouch.cs
Normal file
56
Assets/Scripts/EventWashing/Tools/BrushPointerTouch.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using CW.Common;
|
||||
using PaintCore;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace game
|
||||
{
|
||||
[RequireComponent(typeof(CwHitPointers))]
|
||||
public class BrushPointerTouch : CwPointer
|
||||
{
|
||||
/// <summary>If you want the paint to appear above the finger, then you can set this number to something positive.</summary>
|
||||
public Vector2 Offset { set { offset = value; } get { return offset; } }
|
||||
[SerializeField] private Vector2 offset = Vector2.zero;
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
CwInputManager.Finger finger;
|
||||
|
||||
bool isFollowing = false;
|
||||
Vector2 screenPosition = Vector2.zero;
|
||||
|
||||
for (var i = 0; i < CwInput.GetTouchCount(); i++)
|
||||
{
|
||||
int index;
|
||||
Vector2 position;
|
||||
float pressure;
|
||||
bool set;
|
||||
|
||||
if (EventSystem.current == null) return;
|
||||
|
||||
if (EventSystem.current.IsPointerOverGameObject()) return;
|
||||
|
||||
CwInput.GetTouch(i, out index, out position, out pressure, out set);
|
||||
|
||||
position += offset * CwInputManager.ScaleFactor;
|
||||
|
||||
var down = GetFinger(index, position, pressure, set, out finger);
|
||||
|
||||
cachedHitPointers.HandleFingerUpdate(finger, down, set == false);
|
||||
|
||||
screenPosition = position;
|
||||
isFollowing = true;
|
||||
|
||||
if (set == false)
|
||||
{
|
||||
TryNullFinger(index);
|
||||
}
|
||||
}
|
||||
|
||||
if (isFollowing) FishingYachtAct.Publish<EventWashingGestureFollowPositionData>(new EventWashingGestureFollowPositionData(screenPosition, true));
|
||||
else FishingYachtAct.Publish<EventWashingGestureFollowPositionData>(new EventWashingGestureFollowPositionData(screenPosition, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/BrushPointerTouch.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/BrushPointerTouch.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb3ec75e2f551f248a6e890b43a4be89
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,358 @@
|
||||
using Cinemachine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace game
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[DisallowMultipleComponent]
|
||||
public class CameraFollowPathMoveController : MonoBehaviour
|
||||
{
|
||||
/// <summary>The path to follow</summary>
|
||||
[Tooltip("The path to follow")]
|
||||
public CinemachinePath Path;
|
||||
|
||||
[Tooltip("路径停歇点索引,循环执行。eg:5个点,执行到最后一个位置会从移动到初始位置开始。")]
|
||||
public List<int> m_RestIndexList = new List<int>();
|
||||
|
||||
[Tooltip("磁性距离,距离目标点一定距离,即认为到达目标点。")]
|
||||
public float m_MagneticDistance = 0.01f;
|
||||
|
||||
[Tooltip("一直移动,可以查看整个移动过程,主要用于本地测试。发包时关闭。")]
|
||||
public bool IsAlwaysMoving = false;
|
||||
|
||||
[Tooltip("是否开启测试停歇点,配合TestRestIndex使用,主要用于本地测试。发包时关闭。")]
|
||||
public bool m_IsTestRest = false;
|
||||
[Tooltip("测试用停歇点索引,配合IsTestRest使用,默认为-1,在0-停歇点索引位之间生效。")]
|
||||
public int m_TestRestIndex = -1;
|
||||
|
||||
/// <summary>This enum defines the options available for the update method.</summary>
|
||||
public enum UpdateMethod
|
||||
{
|
||||
/// <summary>Updated in normal MonoBehaviour Update.</summary>
|
||||
Update,
|
||||
/// <summary>Updated in sync with the Physics module, in FixedUpdate</summary>
|
||||
FixedUpdate,
|
||||
/// <summary>Updated in normal MonoBehaviour LateUpdate</summary>
|
||||
LateUpdate
|
||||
};
|
||||
|
||||
/// <summary>When to move the cart, if Velocity is non-zero</summary>
|
||||
[Tooltip("When to move the cart, if Velocity is non-zero")]
|
||||
public UpdateMethod m_UpdateMethod = UpdateMethod.Update;
|
||||
|
||||
/// <summary>How to interpret the Path Position</summary>
|
||||
[Tooltip("How to interpret the Path Position. If set to Path Units, values are as follows: 0 represents the first waypoint on the path, 1 is the second, and so on. Values in-between are points on the path in between the waypoints. If set to Distance, then Path Position represents distance along the path.")]
|
||||
[HideInInspector] public CinemachinePathBase.PositionUnits m_PositionUnits = CinemachinePathBase.PositionUnits.Distance;
|
||||
|
||||
/// <summary>Move the cart with this speed</summary>
|
||||
[Tooltip("Move the cart with this speed along the path. The value is interpreted according to the Position Units setting.")]
|
||||
[FormerlySerializedAs("m_Velocity")]
|
||||
public float Speed;
|
||||
|
||||
/// <summary>The cart's current position on the path, in distance units</summary>
|
||||
[Tooltip("The position along the path at which the cart will be placed. This can be animated directly or, if the velocity is non-zero, will be updated automatically. The value is interpreted according to the Position Units setting.")]
|
||||
[FormerlySerializedAs("m_CurrentDistance")]
|
||||
[HideInInspector] public float m_Position;
|
||||
|
||||
private enum MoveState
|
||||
{
|
||||
Stationary,
|
||||
Moving
|
||||
}
|
||||
private MoveState m_State = MoveState.Stationary;
|
||||
private int m_MoveIndex = 0;
|
||||
private int m_CurPathIndex = 0;
|
||||
//private int m_MoveDirection = 0;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Path != null)
|
||||
{
|
||||
ResamplePath();
|
||||
JumpToRestIndex(0);
|
||||
SetCartPosition(0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
|
||||
if (m_UpdateMethod == UpdateMethod.FixedUpdate)
|
||||
SetCartPosition(m_Position + Speed * Time.deltaTime);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
CheckTestRest();
|
||||
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
|
||||
float speed = Application.isPlaying ? Speed : 0;
|
||||
if (m_UpdateMethod == UpdateMethod.Update)
|
||||
SetCartPosition(m_Position + speed * Time.deltaTime);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (m_State == MoveState.Stationary && !IsAlwaysMoving) return;
|
||||
if (!Application.isPlaying)
|
||||
SetCartPosition(m_Position);
|
||||
else if (m_UpdateMethod == UpdateMethod.LateUpdate)
|
||||
SetCartPosition(m_Position + Speed * Time.deltaTime);
|
||||
}
|
||||
|
||||
public void ResetAndInit(CinemachinePath followPath, List<int> restIndexList, float magneticDistance)
|
||||
{
|
||||
if (followPath == null || restIndexList == null) return;
|
||||
|
||||
if (Path)
|
||||
{
|
||||
Path = null;
|
||||
}
|
||||
|
||||
if (m_RestIndexList != null)
|
||||
{
|
||||
m_RestIndexList = null;
|
||||
}
|
||||
|
||||
m_MagneticDistance = magneticDistance;
|
||||
Path = followPath;
|
||||
m_RestIndexList = restIndexList;
|
||||
|
||||
ResamplePath();
|
||||
}
|
||||
|
||||
void SetCartPosition(float distanceAlongPath)
|
||||
{
|
||||
if (Path != null)
|
||||
{
|
||||
m_Position = Path.StandardizeUnit(distanceAlongPath, m_PositionUnits);
|
||||
if (!IsAlwaysMoving) m_Position = CheckPosition(distanceAlongPath, m_Position);
|
||||
transform.position = Path.EvaluatePositionAtUnit(m_Position, m_PositionUnits);
|
||||
transform.rotation = Path.EvaluateOrientationAtUnit(m_Position, m_PositionUnits);
|
||||
}
|
||||
}
|
||||
private void CheckTestRest()
|
||||
{
|
||||
if (m_IsTestRest)
|
||||
{
|
||||
if (m_TestRestIndex >= 0 && m_TestRestIndex < m_RestIndexList.Count)
|
||||
{
|
||||
m_MoveIndex = m_TestRestIndex;
|
||||
if (!IsEffective()) return;
|
||||
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector3[]> m_RestPointDistance = new List<Vector3[]>();
|
||||
private void ResamplePath()
|
||||
{
|
||||
int stepsPerSegment = Path.DistanceCacheSampleStepsPerSegment;
|
||||
float minPos = Path.MinPos;
|
||||
float maxPos = Path.MaxPos;
|
||||
float stepSize = 1f / Mathf.Max(1, stepsPerSegment);
|
||||
|
||||
// Sample the positions
|
||||
int numKeys = Mathf.RoundToInt((maxPos - minPos) / stepSize) + 1;
|
||||
float[] m_PosToDistance = new float[numKeys];
|
||||
|
||||
m_RestPointDistance.Clear();
|
||||
Vector3[] firstRestDistance = new Vector3[2];
|
||||
Vector3 firstDest = new Vector3(-m_MagneticDistance, 0f, m_MagneticDistance);
|
||||
firstRestDistance[0] = firstDest;
|
||||
m_RestPointDistance.Add(firstRestDistance);
|
||||
|
||||
int index = 0;
|
||||
float m_PathLength = 0f;
|
||||
Vector3 p0 = Path.EvaluatePosition(0);
|
||||
m_PosToDistance[0] = 0;
|
||||
float pos = minPos;
|
||||
for (int i = 1; i < numKeys; ++i)
|
||||
{
|
||||
pos += stepSize;
|
||||
Vector3 p = Path.EvaluatePosition(pos);
|
||||
float d = Vector3.Distance(p0, p);
|
||||
m_PathLength += d;
|
||||
p0 = p;
|
||||
m_PosToDistance[i] = m_PathLength;
|
||||
|
||||
if (i % stepsPerSegment == 0)
|
||||
{
|
||||
Vector3[] tmpArr = new Vector3[1];
|
||||
Vector3 tmp = new Vector3(m_PathLength - m_MagneticDistance, m_PathLength, m_PathLength + m_MagneticDistance);
|
||||
tmpArr[0] = tmp;
|
||||
m_RestPointDistance.Add(tmpArr);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
if (Path.Looped)
|
||||
m_RestPointDistance.RemoveAt(index);
|
||||
Vector3 lastDest = new Vector3(m_PathLength - m_MagneticDistance, m_PathLength, m_PathLength + m_MagneticDistance);
|
||||
firstRestDistance[1] = lastDest;
|
||||
}
|
||||
private bool IsEffective()
|
||||
{
|
||||
return (m_MoveIndex >= 0 && m_MoveIndex < m_RestIndexList.Count && m_RestIndexList.Count > 0) ? true : false;
|
||||
}
|
||||
|
||||
public int RestCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_RestIndexList == null) return 0;
|
||||
return m_RestIndexList.Count;
|
||||
}
|
||||
}
|
||||
public int MoveIndex
|
||||
{
|
||||
get => m_MoveIndex;
|
||||
}
|
||||
public int ForwardToNextRest()
|
||||
{
|
||||
m_MoveIndex++;
|
||||
|
||||
if (m_MoveIndex > m_RestIndexList.Count - 1)
|
||||
{
|
||||
if (Path.Looped)
|
||||
m_MoveIndex = 0;
|
||||
else
|
||||
m_MoveIndex = m_RestIndexList.Count - 1;
|
||||
}
|
||||
|
||||
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
|
||||
if (Speed < 0)
|
||||
{
|
||||
Speed = -Speed;
|
||||
}
|
||||
return m_MoveIndex;
|
||||
}
|
||||
public int BackwardToNextRest()
|
||||
{
|
||||
m_MoveIndex--;
|
||||
if (m_MoveIndex < 0)
|
||||
{
|
||||
if (Path.Looped)
|
||||
m_MoveIndex = m_RestIndexList.Count - 1;
|
||||
else
|
||||
m_MoveIndex = 0;
|
||||
}
|
||||
|
||||
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
|
||||
if (Speed > 0)
|
||||
{
|
||||
Speed = -Speed;
|
||||
}
|
||||
return m_MoveIndex;
|
||||
}
|
||||
public int JumpToNextRestForward()
|
||||
{
|
||||
JumpToRestIndex(++m_MoveIndex);
|
||||
return m_MoveIndex;
|
||||
}
|
||||
public int JumpToNextRestBackward()
|
||||
{
|
||||
JumpToRestIndex(--m_MoveIndex);
|
||||
return m_MoveIndex;
|
||||
}
|
||||
public int JumpToRestIndex(int index)
|
||||
{
|
||||
m_MoveIndex = index;
|
||||
|
||||
if (m_MoveIndex < 0)
|
||||
{
|
||||
if (Path.Looped)
|
||||
m_MoveIndex = m_RestIndexList.Count - 1;
|
||||
else
|
||||
m_MoveIndex = 0;
|
||||
}
|
||||
else if (m_MoveIndex > m_RestIndexList.Count - 1)
|
||||
{
|
||||
if (Path.Looped)
|
||||
m_MoveIndex = 0;
|
||||
else
|
||||
m_MoveIndex = m_RestIndexList.Count - 1;
|
||||
}
|
||||
|
||||
GoToPositionIndex(m_RestIndexList[m_MoveIndex]);
|
||||
|
||||
var tmpArr = m_RestPointDistance[m_CurPathIndex];
|
||||
|
||||
Vector3 boundary = tmpArr[0];
|
||||
float distanceAlongPath = boundary.y;
|
||||
|
||||
m_Position = Path.StandardizeUnit(distanceAlongPath, m_PositionUnits);
|
||||
|
||||
SetCartPosition(m_Position);
|
||||
|
||||
m_State = MoveState.Stationary;
|
||||
|
||||
return m_MoveIndex;
|
||||
}
|
||||
|
||||
public void GoToPositionIndex(int index)
|
||||
{
|
||||
m_CurPathIndex = index;
|
||||
m_State = MoveState.Moving;
|
||||
}
|
||||
float CheckPosition(float distanceAlongPath, float distance)
|
||||
{
|
||||
if (m_CurPathIndex < 0 || m_CurPathIndex >= m_RestPointDistance.Count) return distance;
|
||||
var tmpArr = m_RestPointDistance[m_CurPathIndex];
|
||||
int count = tmpArr.Length;
|
||||
if (count == 0) return distance;
|
||||
|
||||
if (m_CurPathIndex == 0)
|
||||
{
|
||||
if (Speed > 0f)
|
||||
{
|
||||
if (distanceAlongPath >= Path.PathLength)
|
||||
{
|
||||
m_State = MoveState.Stationary;
|
||||
m_IsTestRest = false;
|
||||
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
|
||||
return tmpArr[0].y;
|
||||
}
|
||||
}
|
||||
else if (Speed < 0f)
|
||||
{
|
||||
if (distanceAlongPath <= 0f)
|
||||
{
|
||||
m_State = MoveState.Stationary;
|
||||
m_IsTestRest = false;
|
||||
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
|
||||
return tmpArr[0].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Speed > 0f)
|
||||
{
|
||||
if (distance >= tmpArr[0].x)
|
||||
{
|
||||
m_State = MoveState.Stationary;
|
||||
m_IsTestRest = false;
|
||||
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
|
||||
return tmpArr[0].y;
|
||||
}
|
||||
}
|
||||
else if (Speed <= 0f)
|
||||
{
|
||||
if (distance <= tmpArr[0].z)
|
||||
{
|
||||
m_State = MoveState.Stationary;
|
||||
m_IsTestRest = false;
|
||||
FishingYachtAct.Publish<EventWashingCameraStopData>(new EventWashingCameraStopData());
|
||||
return tmpArr[0].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 425c3dabfac452a4e9fd1c91aa086545
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
241
Assets/Scripts/EventWashing/Tools/OperatingToolsBase.cs
Normal file
241
Assets/Scripts/EventWashing/Tools/OperatingToolsBase.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using cfg;
|
||||
using DG.Tweening;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class OperatingToolsBase : MonoBehaviour
|
||||
{
|
||||
[Tooltip("工具ID")]
|
||||
public int m_ID = 0;
|
||||
|
||||
[Tooltip("工具操作前的准备时间,常用于移到指定位置等。")]
|
||||
public float m_PreparationTime = 0.1f;
|
||||
|
||||
//[Tooltip("初始Transform")]
|
||||
[HideInInspector] public Transform InitTransfom;
|
||||
|
||||
#region Transform变换相关
|
||||
|
||||
/// <summary>
|
||||
/// 跳转到展示区(即:初始Transform : m_InitTransfom)
|
||||
/// </summary>
|
||||
public void JumpToExhibition()
|
||||
{
|
||||
if (InitTransfom is null) return;
|
||||
|
||||
this.transform.parent = InitTransfom.parent;
|
||||
this.transform.SetParent(InitTransfom.parent, false);
|
||||
|
||||
this.transform.localScale = InitTransfom.localScale;
|
||||
this.transform.rotation = InitTransfom.rotation;
|
||||
this.transform.position = InitTransfom.position;
|
||||
}
|
||||
/// <summary>
|
||||
/// 移动到指定 Transform
|
||||
/// </summary>
|
||||
/// <param name="transform"></param>
|
||||
public void MoveToTransform(Transform transform)
|
||||
{
|
||||
if (transform is null) return;
|
||||
this.transform.DOKill();
|
||||
this.transform.DOMove(transform.position, m_PreparationTime).SetEase(Ease.OutQuad);
|
||||
this.transform.DOScale(transform.localScale, m_PreparationTime).SetEase(Ease.Linear);
|
||||
this.transform.DORotateQuaternion(transform.rotation, m_PreparationTime).SetEase(Ease.Linear);
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回到展示区(即:初始Transform : m_InitTransfom)
|
||||
/// </summary>
|
||||
public virtual void MoveToExhibition()
|
||||
{
|
||||
// 停止播放操作动画
|
||||
StopPlayOperationAnimation();
|
||||
// 停止播放准备动画
|
||||
StopPlayPrepareAnimation();
|
||||
|
||||
if (InitTransfom == null) return;
|
||||
MoveToTransform(InitTransfom);
|
||||
|
||||
m_Status = EventWashingActionStatus.Invalid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 动画相关
|
||||
protected bool m_IsAuthorizedAnimation = true;
|
||||
public bool IsAuthorizedAnimation { get => m_IsAuthorizedAnimation; }
|
||||
public void AuthorizedAnimation()
|
||||
{
|
||||
m_IsAuthorizedAnimation = true;
|
||||
}
|
||||
public void NotAuthorizedAnimation()
|
||||
{
|
||||
m_IsAuthorizedAnimation = false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 播放工具操作动画
|
||||
/// </summary>
|
||||
protected virtual void PlayOperationAnimation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止播放工具操作动画
|
||||
/// </summary>
|
||||
protected virtual void StopPlayOperationAnimation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放准备动画
|
||||
/// </summary>
|
||||
protected virtual void PlayPrepareAnimation()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止播放准备动画
|
||||
/// </summary>
|
||||
protected virtual void StopPlayPrepareAnimation()
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 行为相关
|
||||
/// <summary>
|
||||
/// 开始工具操作行为
|
||||
/// </summary>
|
||||
/// <param name="overAction"></param>
|
||||
public virtual void StartExecuting()
|
||||
{
|
||||
m_Status = EventWashingActionStatus.Executing;
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
|
||||
// 播放操作动画
|
||||
if (m_IsAuthorizedAnimation) PlayOperationAnimation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作前的准备行为,如:移动等
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
public void PrepareAction(Transform transform, UnityAction<OperatingToolsBase> readyAction, params object[] args)
|
||||
{
|
||||
m_Status = EventWashingActionStatus.Preparing;
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
|
||||
m_ReadyAction = readyAction;
|
||||
|
||||
MoveToTransform(transform);
|
||||
if (m_IsAuthorizedAnimation) PlayPrepareAnimation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止操作行为
|
||||
/// </summary>
|
||||
public virtual void StopExecuting()
|
||||
{
|
||||
if (m_Status == EventWashingActionStatus.Executing)
|
||||
{
|
||||
MoveToExhibition();
|
||||
StopPlayOperationAnimation();
|
||||
}
|
||||
m_Status = EventWashingActionStatus.Stopping;
|
||||
}
|
||||
|
||||
public virtual void Enter1stStage()
|
||||
{
|
||||
|
||||
}
|
||||
public virtual void Exit1stStage()
|
||||
{
|
||||
|
||||
}
|
||||
public virtual void Enter2ndStage()
|
||||
{
|
||||
|
||||
}
|
||||
public virtual void Exit2ndStage()
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
/// <summary>
|
||||
/// 准备结束事件
|
||||
/// </summary>
|
||||
UnityAction<OperatingToolsBase> m_ReadyAction = null;
|
||||
#endregion
|
||||
|
||||
#region 状态&数据等
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
protected EventWashingActionStatus m_Status = EventWashingActionStatus.Invalid;
|
||||
|
||||
public EventWashingActionStatus Status
|
||||
{
|
||||
get { return m_Status; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 准备操作累计时间,用以本地计时
|
||||
/// </summary>
|
||||
protected float m_PrepareCumulativeTime = 0f;
|
||||
|
||||
protected EventWashingTool m_Type = EventWashingTool.None; // 工具类型
|
||||
|
||||
public EventWashingTool ToolType { get { return m_Type; } }
|
||||
|
||||
public int ToolID { get { return m_ID; } }
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
/// <summary>
|
||||
/// 初始化工具
|
||||
/// </summary>
|
||||
public virtual void InitTool()
|
||||
{
|
||||
m_Type = EventWashingTool.None;
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
m_Status = EventWashingActionStatus.Invalid;
|
||||
|
||||
JumpToExhibition();
|
||||
this.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Start is called before the first frame update
|
||||
protected virtual void Start()
|
||||
{
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
m_Status = EventWashingActionStatus.Invalid;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (m_Status == EventWashingActionStatus.Preparing)
|
||||
{
|
||||
m_PrepareCumulativeTime += Time.deltaTime;
|
||||
if (m_PrepareCumulativeTime >= m_PreparationTime)
|
||||
{
|
||||
if (m_ReadyAction != null)
|
||||
{
|
||||
m_ReadyAction.Invoke(this);
|
||||
}
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
m_Status = EventWashingActionStatus.Executing;
|
||||
StopPlayPrepareAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/OperatingToolsBase.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/OperatingToolsBase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a33d07ea5bd0aa94582860610152f412
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
309
Assets/Scripts/EventWashing/Tools/Outline.cs
Normal file
309
Assets/Scripts/EventWashing/Tools/Outline.cs
Normal file
@@ -0,0 +1,309 @@
|
||||
//
|
||||
// Outline.cs
|
||||
// QuickOutline
|
||||
//
|
||||
// Created by Chris Nolet on 3/30/18.
|
||||
// Copyright © 2018 Chris Nolet. All rights reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
|
||||
public class Outline : MonoBehaviour {
|
||||
private static HashSet<Mesh> registeredMeshes = new HashSet<Mesh>();
|
||||
|
||||
public enum Mode {
|
||||
OutlineAll,
|
||||
OutlineVisible,
|
||||
OutlineHidden,
|
||||
OutlineAndSilhouette,
|
||||
SilhouetteOnly
|
||||
}
|
||||
|
||||
public Mode OutlineMode {
|
||||
get { return outlineMode; }
|
||||
set {
|
||||
outlineMode = value;
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Color OutlineColor {
|
||||
get { return outlineColor; }
|
||||
set {
|
||||
outlineColor = value;
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
public float OutlineWidth {
|
||||
get { return outlineWidth; }
|
||||
set {
|
||||
outlineWidth = value;
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private class ListVector3 {
|
||||
public List<Vector3> data;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Mode outlineMode;
|
||||
|
||||
[SerializeField]
|
||||
private Color outlineColor = Color.white;
|
||||
|
||||
[SerializeField, Range(0f, 10f)]
|
||||
private float outlineWidth = 2f;
|
||||
|
||||
[Header("Optional")]
|
||||
|
||||
[SerializeField, Tooltip("Precompute enabled: Per-vertex calculations are performed in the editor and serialized with the object. "
|
||||
+ "Precompute disabled: Per-vertex calculations are performed at runtime in Awake(). This may cause a pause for large meshes.")]
|
||||
private bool precomputeOutline;
|
||||
|
||||
[SerializeField, HideInInspector]
|
||||
private List<Mesh> bakeKeys = new List<Mesh>();
|
||||
|
||||
[SerializeField, HideInInspector]
|
||||
private List<ListVector3> bakeValues = new List<ListVector3>();
|
||||
|
||||
private Renderer[] renderers;
|
||||
private Material outlineMaskMaterial;
|
||||
private Material outlineFillMaterial;
|
||||
|
||||
private bool needsUpdate;
|
||||
|
||||
void Awake() {
|
||||
|
||||
// Cache renderers
|
||||
renderers = GetComponentsInChildren<Renderer>();
|
||||
|
||||
// Instantiate outline materials
|
||||
outlineMaskMaterial = Instantiate(Resources.Load<Material>(@"Materials/OutlineMask"));
|
||||
outlineFillMaterial = Instantiate(Resources.Load<Material>(@"Materials/OutlineFill"));
|
||||
|
||||
outlineMaskMaterial.name = "OutlineMask (Instance)";
|
||||
outlineFillMaterial.name = "OutlineFill (Instance)";
|
||||
|
||||
// Retrieve or generate smooth normals
|
||||
LoadSmoothNormals();
|
||||
|
||||
// Apply material properties immediately
|
||||
needsUpdate = true;
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
foreach (var renderer in renderers) {
|
||||
|
||||
// Append outline shaders
|
||||
var materials = renderer.sharedMaterials.ToList();
|
||||
|
||||
materials.Add(outlineMaskMaterial);
|
||||
materials.Add(outlineFillMaterial);
|
||||
|
||||
renderer.materials = materials.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
void OnValidate() {
|
||||
|
||||
// Update material properties
|
||||
needsUpdate = true;
|
||||
|
||||
// Clear cache when baking is disabled or corrupted
|
||||
if (!precomputeOutline && bakeKeys.Count != 0 || bakeKeys.Count != bakeValues.Count) {
|
||||
bakeKeys.Clear();
|
||||
bakeValues.Clear();
|
||||
}
|
||||
|
||||
// Generate smooth normals when baking is enabled
|
||||
if (precomputeOutline && bakeKeys.Count == 0) {
|
||||
Bake();
|
||||
}
|
||||
}
|
||||
|
||||
void Update() {
|
||||
if (needsUpdate) {
|
||||
needsUpdate = false;
|
||||
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
foreach (var renderer in renderers) {
|
||||
|
||||
// Remove outline shaders
|
||||
var materials = renderer.sharedMaterials.ToList();
|
||||
|
||||
materials.Remove(outlineMaskMaterial);
|
||||
materials.Remove(outlineFillMaterial);
|
||||
|
||||
renderer.materials = materials.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy() {
|
||||
|
||||
// Destroy material instances
|
||||
Destroy(outlineMaskMaterial);
|
||||
Destroy(outlineFillMaterial);
|
||||
}
|
||||
|
||||
void Bake() {
|
||||
|
||||
// Generate smooth normals for each mesh
|
||||
var bakedMeshes = new HashSet<Mesh>();
|
||||
|
||||
foreach (var meshFilter in GetComponentsInChildren<MeshFilter>()) {
|
||||
|
||||
// Skip duplicates
|
||||
if (!bakedMeshes.Add(meshFilter.sharedMesh)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Serialize smooth normals
|
||||
var smoothNormals = SmoothNormals(meshFilter.sharedMesh);
|
||||
|
||||
bakeKeys.Add(meshFilter.sharedMesh);
|
||||
bakeValues.Add(new ListVector3() { data = smoothNormals });
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSmoothNormals() {
|
||||
|
||||
// Retrieve or generate smooth normals
|
||||
foreach (var meshFilter in GetComponentsInChildren<MeshFilter>()) {
|
||||
|
||||
// Skip if smooth normals have already been adopted
|
||||
if (!registeredMeshes.Add(meshFilter.sharedMesh)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve or generate smooth normals
|
||||
var index = bakeKeys.IndexOf(meshFilter.sharedMesh);
|
||||
var smoothNormals = (index >= 0) ? bakeValues[index].data : SmoothNormals(meshFilter.sharedMesh);
|
||||
|
||||
// Store smooth normals in UV3
|
||||
meshFilter.sharedMesh.SetUVs(3, smoothNormals);
|
||||
|
||||
// Combine submeshes
|
||||
var renderer = meshFilter.GetComponent<Renderer>();
|
||||
|
||||
if (renderer != null) {
|
||||
CombineSubmeshes(meshFilter.sharedMesh, renderer.sharedMaterials);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear UV3 on skinned mesh renderers
|
||||
foreach (var skinnedMeshRenderer in GetComponentsInChildren<SkinnedMeshRenderer>()) {
|
||||
|
||||
// Skip if UV3 has already been reset
|
||||
if (!registeredMeshes.Add(skinnedMeshRenderer.sharedMesh)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clear UV3
|
||||
skinnedMeshRenderer.sharedMesh.uv4 = new Vector2[skinnedMeshRenderer.sharedMesh.vertexCount];
|
||||
|
||||
// Combine submeshes
|
||||
CombineSubmeshes(skinnedMeshRenderer.sharedMesh, skinnedMeshRenderer.sharedMaterials);
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector3> SmoothNormals(Mesh mesh) {
|
||||
|
||||
// Group vertices by location
|
||||
var groups = mesh.vertices.Select((vertex, index) => new KeyValuePair<Vector3, int>(vertex, index)).GroupBy(pair => pair.Key);
|
||||
|
||||
// Copy normals to a new list
|
||||
var smoothNormals = new List<Vector3>(mesh.normals);
|
||||
|
||||
// Average normals for grouped vertices
|
||||
foreach (var group in groups) {
|
||||
|
||||
// Skip single vertices
|
||||
if (group.Count() == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate the average normal
|
||||
var smoothNormal = Vector3.zero;
|
||||
|
||||
foreach (var pair in group) {
|
||||
smoothNormal += smoothNormals[pair.Value];
|
||||
}
|
||||
|
||||
smoothNormal.Normalize();
|
||||
|
||||
// Assign smooth normal to each vertex
|
||||
foreach (var pair in group) {
|
||||
smoothNormals[pair.Value] = smoothNormal;
|
||||
}
|
||||
}
|
||||
|
||||
return smoothNormals;
|
||||
}
|
||||
|
||||
void CombineSubmeshes(Mesh mesh, Material[] materials) {
|
||||
|
||||
// Skip meshes with a single submesh
|
||||
if (mesh.subMeshCount == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip if submesh count exceeds material count
|
||||
if (mesh.subMeshCount > materials.Length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Append combined submesh
|
||||
mesh.subMeshCount++;
|
||||
mesh.SetTriangles(mesh.triangles, mesh.subMeshCount - 1);
|
||||
}
|
||||
|
||||
void UpdateMaterialProperties() {
|
||||
|
||||
// Apply properties according to mode
|
||||
outlineFillMaterial.SetColor("_OutlineColor", outlineColor);
|
||||
|
||||
switch (outlineMode) {
|
||||
case Mode.OutlineAll:
|
||||
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
|
||||
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
|
||||
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
|
||||
break;
|
||||
|
||||
case Mode.OutlineVisible:
|
||||
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
|
||||
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
|
||||
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
|
||||
break;
|
||||
|
||||
case Mode.OutlineHidden:
|
||||
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
|
||||
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
|
||||
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
|
||||
break;
|
||||
|
||||
case Mode.OutlineAndSilhouette:
|
||||
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
|
||||
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Always);
|
||||
outlineFillMaterial.SetFloat("_OutlineWidth", outlineWidth);
|
||||
break;
|
||||
|
||||
case Mode.SilhouetteOnly:
|
||||
outlineMaskMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual);
|
||||
outlineFillMaterial.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.Greater);
|
||||
outlineFillMaterial.SetFloat("_OutlineWidth", 0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/Outline.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/Outline.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7227527bced7eb64a8daf3095fd332d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
18
Assets/Scripts/EventWashing/Tools/ToolBubbleGun.cs
Normal file
18
Assets/Scripts/EventWashing/Tools/ToolBubbleGun.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using cfg;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolBubbleGun : ToolForResponsiveCleaner
|
||||
{
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
m_Type = EventWashingTool.FoamSprayer;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolBubbleGun.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolBubbleGun.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26a5ca7c43397254f8a5cdd4566291b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolCollection.cs
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolCollection.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolCollection : MonoBehaviour
|
||||
{
|
||||
public List<OperatingToolsBase> Tools = new List<OperatingToolsBase>();
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolCollection.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolCollection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0af65a08f04dedc4ab200eaff1bbc959
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
using DG.Tweening;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolForFollowerAndNormalPosition : OperatingToolsBase
|
||||
{
|
||||
[Tooltip("工具距离操作点位置, 吸尘器/水枪等 本身到吸嘴距离")]
|
||||
[SerializeField]
|
||||
private float m_DistanceToMouth = 0.1f;
|
||||
|
||||
[Tooltip("工具操作点距离操作区距离, 吸尘器/水枪等 吸嘴离地距离")]
|
||||
[SerializeField]
|
||||
private float m_DistanceFromMouthToGround = 0.4f;
|
||||
|
||||
[Tooltip("作用距离/覆盖范围")]
|
||||
[SerializeField]
|
||||
private float m_RangeCoverage = 0.8f;
|
||||
|
||||
[Tooltip("工具移动速度")]
|
||||
[SerializeField]
|
||||
private float m_ToolSpeed = 10f;
|
||||
|
||||
[Tooltip("工具移动耗时调整,按比例计算,正值为增加,负值为减少")]
|
||||
[SerializeField]
|
||||
private float m_ToolConsumedTimeAdjustedRatio = 0f;
|
||||
|
||||
public float DistanceFromMouthToGround { get => m_DistanceFromMouthToGround; }
|
||||
public float RangeCoverage { get => m_RangeCoverage; }
|
||||
|
||||
private Vector3 m_OperatingPoint = Vector3.zero;
|
||||
|
||||
public Vector3 OperatingPoint { get => m_OperatingPoint; }
|
||||
|
||||
public void Follow(Vector3 position, Vector3 normal)
|
||||
{
|
||||
Vector3 targetPosition = position + normal * (m_DistanceToMouth + m_DistanceFromMouthToGround);
|
||||
float distance = Vector3.Distance(targetPosition, this.transform.position);
|
||||
float time = distance / m_ToolSpeed;
|
||||
time += time * m_ToolConsumedTimeAdjustedRatio;
|
||||
m_OperatingPoint = position + normal * m_DistanceFromMouthToGround;
|
||||
|
||||
this.transform.DOKill();
|
||||
this.transform.DOMove(targetPosition, time).SetEase(Ease.OutQuad);
|
||||
this.transform.DORotateQuaternion(Quaternion.LookRotation(-normal), time).SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
#region Transform变换相关
|
||||
public override void MoveToExhibition()
|
||||
{
|
||||
// 停止播放操作动画
|
||||
StopPlayOperationAnimation();
|
||||
// 停止播放准备动画
|
||||
StopPlayPrepareAnimation();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b990b7047f8703f4d92bfbaee7dc7143
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolForResponsiveCleaner : ToolForFollowerAndNormalPosition
|
||||
{
|
||||
[Tooltip("喷涂动画")]
|
||||
[SerializeField]
|
||||
private SprayAnimation m_SprayAnimation = null;
|
||||
|
||||
#region 动画相关
|
||||
protected override void PlayOperationAnimation()
|
||||
{
|
||||
base.PlayOperationAnimation();
|
||||
if (m_SprayAnimation != null ) { m_SprayAnimation.PlayEffect(); }
|
||||
}
|
||||
|
||||
protected override void StopPlayOperationAnimation()
|
||||
{
|
||||
base.StopPlayOperationAnimation();
|
||||
if (m_SprayAnimation != null) { m_SprayAnimation.StopEffect(); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
|
||||
m_SprayAnimation.StopEffect();
|
||||
m_SprayAnimation.DisableEffect();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36d513f4aabe5d742b1d06e036c77af4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
124
Assets/Scripts/EventWashing/Tools/ToolShovel.cs
Normal file
124
Assets/Scripts/EventWashing/Tools/ToolShovel.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using cfg;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolShovel : OperatingToolsBase
|
||||
{
|
||||
[Tooltip("动画")]
|
||||
[SerializeField]
|
||||
private Animation m_Animation = null;
|
||||
|
||||
[Tooltip("循环动画")]
|
||||
[SerializeField]
|
||||
private string m_LoopAnimation = null;
|
||||
|
||||
[Tooltip("最后一击动画")]
|
||||
[SerializeField]
|
||||
private string m_FinalBlowAnimation = null;
|
||||
|
||||
[Tooltip("循环动画声音节点")]
|
||||
[SerializeField]
|
||||
private GameObject m_LoopAnimationNode = null;
|
||||
|
||||
[Tooltip("最后一击动画声音节点")]
|
||||
[SerializeField]
|
||||
private GameObject m_FinalBlowAnimationNode = null;
|
||||
|
||||
#region 行为相关
|
||||
public override void Enter1stStage()
|
||||
{
|
||||
base.Enter1stStage();
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Play(m_LoopAnimation);
|
||||
}
|
||||
if (m_LoopAnimationNode != null && m_LoopAnimationNode.activeSelf == false)
|
||||
{
|
||||
m_LoopAnimationNode.SetActive(true);
|
||||
}
|
||||
}
|
||||
public override void Exit1stStage()
|
||||
{
|
||||
base.Exit1stStage();
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Stop(m_LoopAnimation);
|
||||
m_Animation.transform.localPosition = Vector3.zero;
|
||||
m_Animation.transform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
|
||||
if (m_LoopAnimationNode != null && m_LoopAnimationNode.activeSelf == true)
|
||||
{
|
||||
m_LoopAnimationNode.SetActive(false);
|
||||
}
|
||||
}
|
||||
public override void Enter2ndStage()
|
||||
{
|
||||
base.Enter2ndStage();
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Play(m_FinalBlowAnimation);
|
||||
}
|
||||
|
||||
if (m_FinalBlowAnimationNode != null && m_FinalBlowAnimationNode.activeSelf == false)
|
||||
{
|
||||
m_FinalBlowAnimationNode.SetActive(true);
|
||||
}
|
||||
}
|
||||
public override void Exit2ndStage()
|
||||
{
|
||||
base.Exit2ndStage();
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.transform.localPosition = Vector3.zero;
|
||||
m_Animation.transform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
|
||||
if (m_FinalBlowAnimationNode != null && m_FinalBlowAnimationNode.activeSelf == true)
|
||||
{
|
||||
m_FinalBlowAnimationNode.SetActive(false);
|
||||
}
|
||||
}
|
||||
private void StopAllAnimation()
|
||||
{
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Stop();
|
||||
m_Animation.transform.localPosition = Vector3.zero;
|
||||
m_Animation.transform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
|
||||
if (m_LoopAnimationNode != null && m_LoopAnimationNode.activeSelf == true)
|
||||
{
|
||||
m_LoopAnimationNode.SetActive(false);
|
||||
}
|
||||
|
||||
if (m_FinalBlowAnimationNode != null && m_FinalBlowAnimationNode.activeSelf == true)
|
||||
{
|
||||
m_FinalBlowAnimationNode.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void StopExecuting()
|
||||
{
|
||||
base.StopExecuting();
|
||||
StopAllAnimation();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
m_Type = EventWashingTool.Shovel;
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
|
||||
StopAllAnimation();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolShovel.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolShovel.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d49af091646d384796cea1ce36df9ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
76
Assets/Scripts/EventWashing/Tools/ToolSpanner.cs
Normal file
76
Assets/Scripts/EventWashing/Tools/ToolSpanner.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using cfg;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolSpanner : OperatingToolsBase
|
||||
{
|
||||
[Tooltip("动画")]
|
||||
[SerializeField]
|
||||
private Animation m_Animation = null;
|
||||
|
||||
[Tooltip("循环动画")]
|
||||
[SerializeField]
|
||||
private string m_LoopAnimation = null;
|
||||
|
||||
[Tooltip("循环动画声音节点")]
|
||||
[SerializeField]
|
||||
private GameObject m_LoopAnimationNode = null;
|
||||
|
||||
#region 动画相关
|
||||
protected override void PlayOperationAnimation()
|
||||
{
|
||||
base.PlayOperationAnimation();
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Play(m_LoopAnimation);
|
||||
m_IsAuthorizedAnimation = true;
|
||||
}
|
||||
|
||||
if (m_LoopAnimationNode != null && m_LoopAnimationNode.activeSelf == false)
|
||||
{
|
||||
m_LoopAnimationNode.SetActive(true);
|
||||
}
|
||||
}
|
||||
protected override void StopPlayOperationAnimation()
|
||||
{
|
||||
base.StopPlayOperationAnimation();
|
||||
StopAllAnimation();
|
||||
}
|
||||
|
||||
private void StopAllAnimation()
|
||||
{
|
||||
if (m_Animation != null)
|
||||
{
|
||||
m_Animation.Stop();
|
||||
m_Animation.transform.localPosition = Vector3.zero;
|
||||
m_Animation.transform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
|
||||
if (m_LoopAnimationNode != null && m_LoopAnimationNode.activeSelf == true)
|
||||
{
|
||||
m_LoopAnimationNode.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void StopExecuting()
|
||||
{
|
||||
base.StopExecuting();
|
||||
StopAllAnimation();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
m_Type = EventWashingTool.Spanner;
|
||||
m_PrepareCumulativeTime = 0f;
|
||||
|
||||
StopAllAnimation();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolSpanner.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolSpanner.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f07ef0072122b9242a239e3d9e35bf13
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
Assets/Scripts/EventWashing/Tools/ToolVacuumCleaner.cs
Normal file
50
Assets/Scripts/EventWashing/Tools/ToolVacuumCleaner.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using cfg;
|
||||
using DG.Tweening;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolVacuumCleaner : ToolForFollowerAndNormalPosition
|
||||
{
|
||||
[Tooltip("循环特效")]
|
||||
[SerializeField]
|
||||
private ParticleSystem[] m_LoopEffects = null;
|
||||
|
||||
#region 行为相关
|
||||
private bool m_IsPlayingEffect = false;
|
||||
public override void StartExecuting()
|
||||
{
|
||||
if (m_LoopEffects == null || m_IsPlayingEffect == true) return;
|
||||
m_IsPlayingEffect = true;
|
||||
int count = m_LoopEffects.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
m_LoopEffects[i].gameObject.SetActive(true);
|
||||
m_LoopEffects[i].Play();
|
||||
}
|
||||
}
|
||||
public override void StopExecuting()
|
||||
{
|
||||
if (m_LoopEffects == null) return;
|
||||
m_IsPlayingEffect = false;
|
||||
int count = m_LoopEffects.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
m_LoopEffects[i].Stop();
|
||||
m_LoopEffects[i].gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
m_Type = EventWashingTool.Cleaner;
|
||||
m_IsPlayingEffect = false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolVacuumCleaner.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolVacuumCleaner.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9f93b21c65941e4ea6319d8ccbc287f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Scripts/EventWashing/Tools/ToolWaterGun.cs
Normal file
19
Assets/Scripts/EventWashing/Tools/ToolWaterGun.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using cfg;
|
||||
using DG.Tweening;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace game
|
||||
{
|
||||
public class ToolWaterGun : ToolForResponsiveCleaner
|
||||
{
|
||||
#region 生命周期
|
||||
public override void InitTool()
|
||||
{
|
||||
base.InitTool();
|
||||
m_Type = EventWashingTool.WaterSprayer;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/EventWashing/Tools/ToolWaterGun.cs.meta
Normal file
11
Assets/Scripts/EventWashing/Tools/ToolWaterGun.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 756bbf0cc789237458db69c086373380
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user