420 lines
14 KiB
C#
420 lines
14 KiB
C#
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
|