Reconfigured the solution.

Relocated the files to suite the Unity3D project folder structure.
This commit is contained in:
2014-06-23 01:08:01 +04:00
parent a043d3fc47
commit b69ba47ed1
45 changed files with 260 additions and 114 deletions

View File

@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Basic action class for subclassing. To inherit interval actions, consider using the ActionInterval as the base class.
/// </summary>
public class ActionInstant
{
protected Actor target;
protected Transform transform;
protected Renderer renderer;
protected bool is2d = false;
private float durationValue = 0;
private float dtrValue = 0;
private bool isRunning = false;
public ActionInstant()
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public virtual ActionInstant clone()
{
return new ActionInstant();
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public virtual ActionInstant reverse()
{
throw new Exception("Can reverse only the reversable interval actions");
}
/// <summary>
/// This method is called at the action start. Usable for instant and interval actions.
/// </summary>
public virtual void start()
{
if (target == null)
throw new Exception("Can start the action only after it's atached to the actor");
transform = target.transformCached;
renderer = target.rendererCached;
}
/// <summary>
/// This method is called at every frame update. Not usable for instant actions.
/// </summary>
public virtual void step(float dt)
{
if (target == null)
throw new Exception("Can update the action only after it's atached to the actor");
}
/// <summary>
/// This method is called after the interval action is stopped. Not usable for instant actions.
/// </summary>
public virtual void stop()
{
if (target == null)
throw new Exception("Can stop the action only after it's atached to the actor");
}
/// <summary>
/// This method sets the actor for the action.
/// </summary>
public void setActor(Actor actor)
{
target = actor;
}
/// <summary>
/// Readonly property. Shows the remaining time of the action.
/// </summary>
public float duration
{
get
{
return durationValue;
}
protected set
{
durationValue = value;
}
}
/// <summary>
/// Readonly property. Shows if the action is running or not.
/// </summary>
public bool running
{
get
{
return isRunning;
}
protected set
{
isRunning = value;
}
}
/// <summary>
/// Readonly property. Contains the remaining tick time after action finished.
/// </summary>
public float dtr
{
get
{
return dtrValue;
}
protected set
{
dtrValue = value;
}
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Interval action class for subclassing.
/// </summary>
public class ActionInterval : ActionInstant
{
protected float timer;
protected float timeScale;
private float dtrdata;
public ActionInterval(float tgtDuration)
: base()
{
duration = tgtDuration;
timeScale = 1F;
dtr = 0;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionInterval(duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
throw new Exception("Can reverse only the reversable interval actions");
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
running = true;
timer = 0F;
}
/// <summary>
/// This method is called after the interval action is stopped.
/// </summary>
public override void stop()
{
base.stop();
running = false;
}
/// <summary>
/// This method is called every frame update. Don't override this method, when inheriting, put your code in stepInterval instead.
/// </summary>
public override void step(float dt)
{
dt *= timeScale;
base.step(dt);
if (timer + dt > duration)
{
float odt = dt;
dt = duration - timer;
timer += odt;
}
else
{
timer += dt;
}
stepInterval(dt);
if (timer > duration)
{
stop();
dtr = timer - duration;
}
}
/// <summary>
/// This method is called every frame update. Put your code here.
/// </summary>
public virtual void stepInterval(float dt)
{
}
/// <summary>
/// Immediately changes the time scale for this action and all nested ones.
/// </summary>
public void setTimeScale(float ts)
{
timeScale = ts;
}
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Runs several actions at the same time.
/// </summary>
public class ActionParallel : ActionInterval
{
protected ActionInstant[] actions;
public ActionParallel(ActionInstant action1, ActionInstant action2)
: base(0)
{
actions = new ActionInstant[] { action1, action2 };
}
public ActionParallel(ActionInstant[] actionsList)
: base(0)
{
actions = actionsList;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[i] = actions[i].clone();
}
return new ActionSequence(aList);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[i] = actions[i].reverse();
}
return new ActionSequence(aList);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
for (int i = 0; i < actions.Length; i++)
{
actions[i].setActor(target);
actions[i].start();
}
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void step(float dt)
{
dt *= timeScale;
for (int i = 0; i < actions.Length; i++)
{
if (actions[i].running)
actions[i].step(dt);
}
bool canStopNow = true;
float dtrdata = 0;
for (int i = 0; i < actions.Length; i++)
{
if (actions[i].running)
{
canStopNow = false;
dtrdata = Math.Max(actions[i].dtr, dtrdata);
}
}
if (canStopNow)
{
stop();
dtr = dtrdata;
}
}
/// <summary>
/// This method is called after the interval action is stopped.
/// </summary>
public override void stop()
{
base.stop();
for (int i = 0; i < actions.Length; i++)
{
actions[i].stop();
}
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Runs one random action from the given list.
/// </summary>
class ActionRandom : ActionInterval
{
protected ActionInstant[] actions;
protected int index;
public ActionRandom(ActionInstant action1, ActionInstant action2)
: base(0)
{
actions = new ActionInstant[] { action1, action2 };
}
public ActionRandom(ActionInstant[] actionsList)
: base(0)
{
actions = actionsList;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[i] = actions[i].clone();
}
return new ActionRandom(aList);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[i] = actions[i].reverse();
}
return new ActionRandom(aList);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
index = UnityEngine.Random.Range(0, actions.Length);
actions[index].setActor(target);
actions[index].start();
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void step(float dt)
{
dt *= timeScale;
if (actions[index].running)
actions[index].step(dt);
if (!actions[index].running)
{
stop();
dtr = actions[index].dtr;
}
}
/// <summary>
/// This method is called after the interval action is stopped.
/// </summary>
public override void stop()
{
base.stop();
actions[index].stop();
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Runs the given action the several times. Also can repeat the action forever.
/// </summary>
class ActionRepeat : ActionInterval
{
protected ActionInterval action;
protected int count;
protected int counter;
protected bool forever;
public ActionRepeat(ActionInterval tgtAction, int tgtCount)
: base(0)
{
action = tgtAction;
count = tgtCount;
counter = 0;
forever = false;
}
public ActionRepeat(ActionInterval tgtAction)
: base(0)
{
action = tgtAction;
count = 0;
counter = 0;
forever = true;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionRepeat((ActionInterval)action.clone(), count);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionRepeat((ActionInterval)action.reverse(), count);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
action.setActor(target);
action.start();
counter = 0;
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void step(float dt)
{
dt *= timeScale;
if (action.running)
{
action.step(dt);
}
if (!action.running && (forever || counter < count - 1))
{
float dtrdata = action.dtr;
action.start();
if (dtrdata > 0)
action.step(dtrdata);
counter += 1;
}
else if (!action.running && counter >= count - 1)
{
dtr = action.dtr;
stop();
}
}
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Runs several actions in a sequence.
/// </summary>
class ActionSequence : ActionInterval
{
protected ActionInstant[] actions;
protected int index;
public ActionSequence(ActionInstant action1, ActionInstant action2)
: base(0)
{
actions = new ActionInstant[] { action1, action2 };
}
public ActionSequence(ActionInstant[] actionsList)
: base(0)
{
actions = actionsList;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[i] = actions[i].clone();
}
return new ActionSequence(aList);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
ActionInstant[] aList = new ActionInstant[actions.Length];
for (int i = 0; i < actions.Length; i++)
{
aList[actions.Length - 1 - i] = actions[i].reverse();
}
return new ActionSequence(aList);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
index = 0;
actions[0].setActor(target);
actions[0].start();
while (!actions[index].running && index < actions.Length)
{
index += 1;
actions[index].setActor(target);
actions[index].start();
}
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void step(float dt)
{
dt *= timeScale;
float dtrdata = 0;
if (actions[index].running)
{
actions[index].step(dt);
if (!actions[index].running)
dtrdata = actions[index].dtr;
}
while (!actions[index].running && index < actions.Length - 1)
{
index += 1;
actions[index].setActor(target);
actions[index].start();
if (actions[index].running && dtrdata > 0)
actions[index].step(dtrdata);
}
if (!actions[index].running)
{
stop();
dtr = dtrdata;
}
}
/// <summary>
/// This method is called after the interval action is stopped.
/// </summary>
public override void stop()
{
base.stop();
for (int i = 0; i < actions.Length; i++)
{
actions[i].stop();
}
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// This action stops all actions for the current target.
/// </summary>
class ActionStop : ActionInstant
{
public ActionStop()
: base()
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionStop();
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
target.StopAction();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly hides the target. This action does not require the transparency support in shaders.
/// </summary>
class ActionHide : ActionInstant
{
public ActionHide()
: base()
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionHide();
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionShow();
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
renderer.enabled = false;
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Prints a message in Unity debug console.
/// </summary>
class ActionLog : ActionInstant
{
string message;
public ActionLog(string tgtMessage)
: base()
{
message = tgtMessage;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionLog(message);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionLog(message);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
Debug.Log(message);
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Sends the message to the current target. First, it checks the Actor's methods cache.
/// If the receiving method found in cache, it will be called directly without passing the message to the GameObject.
/// If there's no listener in cache, message will be sent GameObject (and Unity does it VERY slow).
/// </summary>
class ActionSendMessage : ActionInstant
{
protected string message;
protected object param;
protected SendMessageOptions options = SendMessageOptions.DontRequireReceiver;
public ActionSendMessage(string tgtMessage)
: base()
{
message = tgtMessage;
}
public ActionSendMessage(string tgtMessage, object tgtParam)
: base()
{
message = tgtMessage;
param = tgtParam;
}
public ActionSendMessage(string tgtMessage, object tgtParam, SendMessageOptions tgtOptions)
: base()
{
message = tgtMessage;
param = tgtParam;
options = tgtOptions;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionSendMessage(message, param, options);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionSendMessage(message, param, options);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
if (param != null)
{
target.ReceiveMessage(message, param, options);
}
else
{
target.ReceiveMessage(message, options);
}
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly rotates the target to face the given point or actor.
/// </summary>
class ActionSetDirection : ActionInstant
{
protected Vector3 value;
protected Actor other;
public ActionSetDirection(Vector3 tgtValue)
: base()
{
value = tgtValue;
}
public ActionSetDirection(Vector2 tgtValue)
: this((Vector3)tgtValue)
{
is2d = true;
}
public ActionSetDirection(Actor tgtActor)
: base()
{
other = tgtActor;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionSetDirection(value);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
if (other != null)
{
value = other.transform.position;
}
if (is2d)
{
value.z = transform.position.z;
}
transform.rotation = Quaternion.LookRotation(transform.position - value);
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly moves the target to the given point.
/// </summary>
class ActionSetPlace : ActionInstant
{
protected Vector3 value;
public ActionSetPlace(Vector3 tgtPlace)
: base()
{
value = tgtPlace;
}
public ActionSetPlace(Vector2 tgtPlace)
: this((Vector3)tgtPlace)
{
is2d = true;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionSetPlace(value);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
if (is2d)
value.z = transform.position.z;
transform.position = value;
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly rotates the target.
/// </summary>
class ActionSetRotation : ActionInstant
{
protected Vector3 value;
public ActionSetRotation(Vector3 tgtValue)
: base()
{
value = tgtValue;
}
public ActionSetRotation(float angle)
: this(new Vector3(0, 0, angle))
{
is2d = true;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionSetRotation(value);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
transform.rotation = Quaternion.Euler(value);
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly tints the target to the given color.
/// </summary>
class ActionSetTint : ActionInstant
{
public Vector4 color;
protected const float coeff = 1F / 255F;
public ActionSetTint(Vector4 tgtColor)
: base()
{
color = tgtColor * coeff;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionSetTint(color * 255F);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
renderer.material.color = new Color(color[0], color[1], color[2], color[3]);
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly shows the hidden target. This action does not require the transparency support in shaders.
/// </summary>
class ActionShow : ActionInstant
{
public ActionShow()
: base()
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionShow();
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionHide();
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
renderer.enabled = true;
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Instantly hides the target or showes it, if it's hidden. This action does not require the transparency support in shaders.
/// </summary>
class ActionToggleVisibility : ActionInstant
{
public ActionToggleVisibility()
: base()
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionToggleVisibility();
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionToggleVisibility();
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
renderer.enabled = !renderer.enabled;
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Moves the target with a cubic Bezier in absolute coordinates (if the target is not in the start point, it'll be positioned there when the action starts).
/// </summary>
class ActionBezierAbs : ActionInterval
{
protected Vector3 startPoint;
protected Vector3 endPoint;
protected Vector3 startControlPoint;
protected Vector3 endControlPoint;
public ActionBezierAbs(Vector3 tgtStart, Vector3 tgtSCP, Vector3 tgtECP, Vector3 tgtEnd, float tgtDuration)
: base(tgtDuration)
{
startPoint = tgtStart;
endPoint = tgtEnd;
startControlPoint = tgtSCP;
endControlPoint = tgtECP;
}
public ActionBezierAbs(Vector2 tgtStart, Vector2 tgtSCP, Vector2 tgtECP, Vector2 tgtEnd, float tgtDuration)
: this((Vector3)tgtStart, (Vector3)tgtSCP, (Vector3)tgtECP, (Vector3)tgtEnd, tgtDuration)
{
is2d = true;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionBezierAbs(startPoint, startControlPoint, endControlPoint, endPoint, duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionBezierAbs(endPoint, endControlPoint, startControlPoint, startPoint, duration);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
float z = transform.position.z;
if (is2d)
{
startPoint.z = z;
endPoint.z = z;
startControlPoint.z = z;
endControlPoint.z = z;
}
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void stepInterval(float dt)
{
float t = timer / duration;
Vector3 newPosition = (((-startPoint
+ 3 * (startControlPoint - endControlPoint) + endPoint) * t
+ (3 * (startPoint + endControlPoint) - 6 * startControlPoint)) * t +
3 * (startControlPoint - startPoint)) * t + startPoint;
transform.position = newPosition;
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Moves the target with a cubic Bezier in relative coordinates.
/// </summary>
class ActionBezierRel : ActionInterval
{
protected Vector3 ep;
protected Vector3 cp1;
protected Vector3 cp2;
protected Vector3 startPoint;
protected Vector3 endPoint;
protected Vector3 startControlPoint;
protected Vector3 endControlPoint;
public ActionBezierRel(Vector3 tgtSCP, Vector3 tgtECP, Vector3 tgtEnd, float tgtDuration)
: base(tgtDuration)
{
ep = tgtEnd;
cp1 = tgtSCP;
cp2 = tgtECP;
}
public ActionBezierRel(Vector2 tgtSCP, Vector2 tgtECP, Vector2 tgtEnd, float tgtDuration)
: this((Vector3)tgtSCP, (Vector3)tgtECP, (Vector3)tgtEnd, tgtDuration)
{
is2d = true;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionBezierRel(startControlPoint, endControlPoint, endPoint, duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionBezierRel(-startControlPoint, -endControlPoint, -endPoint, duration);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
startPoint = target.transform.position;
endPoint = startPoint + ep;
startControlPoint = startPoint + cp1;
endControlPoint = startControlPoint + cp2;
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void stepInterval(float dt)
{
float t = timer / duration;
Vector3 newPosition = (((-startPoint
+ 3 * (startControlPoint - endControlPoint) + endPoint) * t
+ (3 * (startPoint + endControlPoint) - 6 * startControlPoint)) * t +
3 * (startControlPoint - startPoint)) * t + startPoint;
transform.position = newPosition;
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Blinks the target.
/// </summary>
class ActionBlink : ActionRepeat
{
protected bool randomDelay;
protected ActionDelay delay = new ActionDelay(0);
protected ActionInstant[] blinkSeq;
protected float durationMin;
protected float durationMax;
public ActionBlink(int tgtBlinks, float tgtDuration)
: base(null, 0)
{
durationMin = tgtDuration;
durationMax = tgtDuration;
count = (tgtBlinks) * 2;
blinkSeq = new ActionInstant[]
{
new ActionToggleVisibility(),
new ActionDelay(tgtDuration / tgtBlinks)
};
action = new ActionSequence(blinkSeq);
}
public ActionBlink(int tgtBlinks, float tgtDurationMin, float tgtDurationMax)
: base(null, 0)
{
durationMin = tgtDurationMin;
durationMax = tgtDurationMax;
count = (tgtBlinks) * 2;
blinkSeq = new ActionInstant[]
{
new ActionToggleVisibility(),
new ActionDelay(tgtDurationMin / tgtBlinks, tgtDurationMax / tgtBlinks)
};
action = new ActionSequence(blinkSeq);
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionBlink(count / 2 - 1, durationMin, durationMax);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionBlink(count / 2 - 1, durationMin, durationMax);
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Delays the action for the given amount of seconds.
/// </summary>
class ActionDelay : ActionInterval
{
protected float durationMin;
protected float durationMax;
public ActionDelay(float tgtDuration)
: base(tgtDuration)
{
durationMin = tgtDuration;
durationMax = tgtDuration;
}
public ActionDelay(float tgtDuration, float tgtDurationMax)
: base(tgtDuration)
{
durationMin = tgtDuration;
durationMax = tgtDurationMax;
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
if (durationMax != null)
{
duration = UnityEngine.Random.Range(durationMin, durationMax);
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Fades the target by the given alpha value. The tartet shaders should support transparency in order to use this action.
/// </summary>
class ActionFadeBy : ActionInterval
{
protected float delta;
public ActionFadeBy(float tgtDelta, float tgtDuration)
: base(tgtDuration)
{
delta = tgtDelta;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionFadeBy(delta, duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionFadeBy(-delta, duration);
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void stepInterval(float dt)
{
float d = dt / duration;
Color tgtColor = renderer.material.color;
tgtColor[3] += delta * d;
renderer.material.color = tgtColor;
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Fades in the target. The tartet shaders should support transparency in order to use this action.
/// </summary>
class ActionFadeIn : ActionFadeTo
{
public ActionFadeIn(float tgtDuration)
: base(1, tgtDuration)
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionFadeIn(duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionFadeOut(duration);
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Fades out the target. The tartet shaders should support transparency in order to use this action.
/// </summary>
class ActionFadeOut : ActionFadeTo
{
public ActionFadeOut(float tgtDuration)
: base(0, tgtDuration)
{
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionFadeOut(duration);
}
/// <summary>
/// Returns the reversed version of the action, if it is possible.
/// </summary>
public override ActionInstant reverse()
{
return new ActionFadeIn(duration);
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
/// <summary>
/// Fades the target to the given alpha value. The tartet shaders should support transparency in order to use this action.
/// </summary>
class ActionFadeTo : ActionInterval
{
protected float value;
protected float delta;
public ActionFadeTo(float tgtValue, float tgtDuration)
: base(tgtDuration)
{
value = tgtValue;
}
/// <summary>
/// Returns a copy of the action.
/// </summary>
public override ActionInstant clone()
{
return new ActionFadeTo(value, duration);
}
/// <summary>
/// This method is called at the action start.
/// </summary>
public override void start()
{
base.start();
delta = value - renderer.material.color.a;
}
/// <summary>
/// This method is called every frame update.
/// </summary>
public override void stepInterval(float dt)
{
float d = dt / duration;
Color tgtColor = renderer.material.color;
tgtColor[3] += delta * d;
renderer.material.color = tgtColor;
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionJumpBy : ActionSequence
{
protected Vector3 point;
float height;
int jumps;
public ActionJumpBy(Vector3 tgtPoint, float tgtHeight, int tgtJumps, float tgtDuration)
: base(new ActionInstant[tgtJumps])
{
point = tgtPoint;
jumps = tgtJumps;
height = tgtHeight;
duration = tgtDuration;
}
public ActionJumpBy(Vector2 tgtPoint, float tgtHeight, int tgtJumps, float tgtDuration)
: this((Vector3)tgtPoint, tgtHeight, tgtJumps, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionJumpBy(point, height, jumps, duration);
}
public override ActionInstant reverse()
{
return new ActionJumpBy(-point, height, jumps, duration);
}
public override void start()
{
float coeff = 1F / jumps;
Vector3 end = point * coeff;
Vector3 cp1 = Vector3.up * height;
Vector3 cp2 = end + cp1;
ActionBezierRel singleJump = new ActionBezierRel(cp1, cp2, end, duration * coeff);
for (int i = 0; i < jumps; i++)
{
actions[i] = singleJump;
}
base.start();
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionJumpTo : ActionSequence
{
protected Vector3 point;
float height;
int jumps;
public ActionJumpTo(Vector3 tgtPoint, float tgtHeight, int tgtJumps, float tgtDuration)
: base(new ActionInstant[tgtJumps])
{
point = tgtPoint;
jumps = tgtJumps;
height = tgtHeight;
duration = tgtDuration;
}
public ActionJumpTo(Vector2 tgtPoint, float tgtHeight, int tgtJumps, float tgtDuration)
: this((Vector3)tgtPoint, tgtHeight, tgtJumps, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionJumpTo(point, height, jumps, duration);
}
public override void start()
{
float coeff = 1F / jumps;
if (is2d)
point.z = transform.position.z;
Vector3 start = target.gameObject.transform.position;
Vector3 end = (point - start) * coeff;
Vector3 cp1 = Vector3.up * height;
Vector3 cp2 = end + cp1;
ActionBezierRel singleJump = new ActionBezierRel(cp1, cp2, end, duration * coeff);
for (int i = 0; i < jumps; i++)
{
actions[i] = singleJump;
}
base.start();
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionMoveBy : ActionInterval
{
protected Vector3 delta;
public ActionMoveBy(Vector3 tgtDelta, float tgtDuration)
: base(tgtDuration)
{
delta = tgtDelta;
}
public ActionMoveBy(Vector2 tgtValue, float tgtDuration)
: this((Vector3)tgtValue, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionMoveBy(delta, duration);
}
public override ActionInstant reverse()
{
return new ActionMoveBy(delta * -1F, duration);
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = delta * d;
transform.Translate(tgt, Space.World);
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionMoveTo : ActionInterval
{
protected Vector3 value;
protected Vector3 path;
public ActionMoveTo(Vector3 tgtValue, float tgtDuration)
: base(tgtDuration)
{
value = tgtValue;
}
public ActionMoveTo(Vector2 tgtValue, float tgtDuration)
: this((Vector3)tgtValue, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionMoveBy(value, duration);
}
public override void start()
{
base.start();
if (is2d)
value.z = transform.position.z;
path = value - transform.position;
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = path * d;
transform.Translate(tgt, Space.World);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionRotateBy : ActionInterval
{
protected Vector3 delta;
public ActionRotateBy(Vector3 tgtDelta, float tgtDuration)
: base(tgtDuration)
{
delta = tgtDelta;
}
public ActionRotateBy(float angle, float tgtDuration)
: this(new Vector3(0, 0, angle), tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionRotateBy(delta, duration);
}
public override ActionInstant reverse()
{
return new ActionRotateBy(delta * -1F, duration);
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = delta * d;
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + tgt);
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionRotateTo : ActionInterval
{
protected Vector3 value;
protected Vector3 path;
public ActionRotateTo(Vector3 tgtValue, float tgtDuration)
: base(tgtDuration)
{
value = tgtValue;
}
public ActionRotateTo(float angle, float tgtDuration)
: this(new Vector3(0, 0, angle), tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionRotateTo(value, duration);
}
public override void start()
{
base.start();
path = new Vector3();
for (int i = 0; i < 3; i++)
{
float t = value[i];
float f = transform.rotation.eulerAngles[i];
if (Math.Abs(t - f) < Math.Abs(t + 360 - f))
path[i] = t - f;
else
path[i] = t + 360 - f;
}
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = path * d;
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + tgt);
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionScaleBy : ActionInterval
{
protected Vector3 delta;
protected Vector3 path;
public ActionScaleBy(Vector3 tgtDelta, float tgtDuration)
: base(tgtDuration)
{
delta = tgtDelta;
}
public ActionScaleBy(Vector2 tgtValue, float tgtDuration)
: this((Vector3)tgtValue, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionScaleBy(delta, duration);
}
public override ActionInstant reverse()
{
return new ActionScaleBy(delta * -1F, duration);
}
public override void start()
{
base.start();
Vector3 scale = transform.localScale;
scale.x *= delta.x;
scale.y *= delta.y;
scale.z *= delta.z;
path = scale - transform.localScale;
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = path * d;
transform.localScale += tgt;
}
public override void stop()
{
base.stop();
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionScaleTo : ActionInterval
{
protected Vector3 value;
protected Vector3 path;
public ActionScaleTo(Vector3 tgtValue, float tgtDuration)
: base(tgtDuration)
{
value = tgtValue;
}
public ActionScaleTo(Vector2 tgtValue, float tgtDuration)
: this((Vector3)tgtValue, tgtDuration)
{
is2d = true;
}
public override ActionInstant clone()
{
return new ActionScaleTo(value, duration);
}
public override void start()
{
base.start();
if (is2d)
value.z = transform.localScale.z;
path = value - transform.localScale;
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = path * d;
transform.localScale += tgt;
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionSkewBy : ActionInterval
{
protected Vector3 skewAngles1;
protected Vector3 skewAngles2;
protected Mesh mesh;
public ActionSkewBy(Vector3 tgtAngles1, Vector3 tgtAngles2, float tgtDuration)
: base(tgtDuration)
{
skewAngles1 = tgtAngles1;
skewAngles2 = tgtAngles2;
}
public override ActionInstant clone()
{
return new ActionSkewBy(skewAngles1, skewAngles2, duration);
}
public override ActionInstant reverse()
{
return new ActionSkewBy(-skewAngles1, -skewAngles2, duration);
}
public override void start()
{
base.start();
if (!(target is Actor))
{
throw new Exception("You should use Actor class instead of Actor, if you want to skew your object.");
}
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector3 tgt = skewAngles1 * d;
((Actor)target).skewAngles1 += tgt;
tgt = skewAngles2 * d;
((Actor)target).skewAngles2 += tgt;
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionTintBy : ActionInterval
{
protected Vector4 color;
protected const float coeff = 1F / 255F;
public ActionTintBy(Vector4 tgtColor, float tgtDuration)
: base(tgtDuration)
{
color = tgtColor * coeff;
}
public ActionTintBy(Vector3 tgtColor, float tgtDuration)
: this(new Vector4(tgtColor.x, tgtColor.y, tgtColor.z), tgtDuration)
{
}
public override ActionInstant clone()
{
return new ActionTintBy(color / coeff, duration);
}
public override ActionInstant reverse()
{
return new ActionTintBy(-color / coeff, duration);
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector4 tgt = color * d;
Color tgtColor = renderer.material.color;
tgtColor[0] += tgt[0];
tgtColor[1] += tgt[1];
tgtColor[2] += tgt[2];
tgtColor[3] += tgt[3];
renderer.material.color = tgtColor;
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
class ActionTintTo : ActionInterval
{
protected Vector4 color;
protected Vector4 path;
protected const float coeff = 1F / 255F;
public ActionTintTo(Vector4 tgtColor, float tgtDuration)
: base(tgtDuration)
{
color = tgtColor * coeff;
path = Vector4.zero;
}
public ActionTintTo(Vector3 tgtColor, float tgtDuration)
: this(new Vector4(tgtColor.x, tgtColor.y, tgtColor.z), tgtDuration)
{
}
public override ActionInstant clone()
{
return new ActionTintTo(color / coeff, duration);
}
public override void start()
{
base.start();
Color tgtColor = renderer.material.color;
path[0] = color[0] - tgtColor[0];
path[1] = color[1] - tgtColor[1];
path[2] = color[2] - tgtColor[2];
path[3] = color[3] - tgtColor[3];
}
public override void stepInterval(float dt)
{
float d = dt / duration;
Vector4 tgt = path * d;
Color tgtColor = renderer.material.color;
tgtColor[0] += tgt[0];
tgtColor[1] += tgt[1];
tgtColor[2] += tgt[2];
tgtColor[3] += tgt[3];
renderer.material.color = tgtColor;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace coa4u
{
public class MethodHolder
{
protected Action method;
protected string methodName;
public MethodHolder()
{
}
public MethodHolder(Action tgtMethod)
{
method = tgtMethod;
methodName = tgtMethod.Method.Name;
}
public virtual void run(object param = null)
{
if (method != null)
method.Invoke();
}
public string name
{
get
{
return methodName;
}
}
}
public class MethodHolder<T> : MethodHolder
{
protected Action<T> methodParam;
public MethodHolder(Action<T> tgtMethod)
{
methodParam = tgtMethod;
methodName = tgtMethod.Method.Name;
}
public override void run(object param)
{
if (methodParam != null)
methodParam.Invoke((T)param);
}
}
}

View File

@@ -0,0 +1,167 @@
using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using coa4u;
/// <summary>
/// The default Actor class for the Action system.
/// </summary>
public class Actor : MonoBehaviour
{
protected Dictionary<string, MethodHolder> methodsCache = new Dictionary<string, MethodHolder>();
protected ActionInstant action;
private bool paused = false;
protected Vector3 angles1prev = Vector3.zero;
protected Vector3 angles2prev = Vector3.zero;
protected const float coeff = Mathf.PI / 180;
protected Vector3[] initialState;
public Transform transformCached;
public Renderer rendererCached;
public Mesh meshCached;
public Vector3 skewAngles1;
public Vector3 skewAngles2;
/// <summary>
/// This method is called when the script instance is being loaded.
/// </summary>
protected void Awake()
{
transformCached = gameObject.transform;
rendererCached = gameObject.renderer;
meshCached = gameObject.GetComponent<MeshFilter>().mesh;
initialState = meshCached.vertices;
}
/// <summary>
/// This method is called at every frame update.
/// </summary>
protected void Update()
{
if (paused || action == null)
return;
if (action.running)
action.step(Time.deltaTime);
if (skewAngles1 != angles1prev || skewAngles2 != angles2prev)
updateSkew();
}
/// <summary>
/// Updates the skew for the mesh.
/// </summary>
void updateSkew()
{
Matrix4x4 m = Matrix4x4.zero;
m[0, 0] = 1;
m[1, 1] = 1;
m[2, 2] = 1;
m[3, 3] = 1;
m[0, 1] = Mathf.Tan(skewAngles1.x * coeff); // skewing in xy
m[0, 2] = Mathf.Tan(skewAngles2.x * coeff); // skewing in xz
m[1, 0] = Mathf.Tan(skewAngles1.y * coeff); // skewing in yx
m[1, 2] = Mathf.Tan(skewAngles2.y * coeff); // skewing in yz
m[2, 0] = Mathf.Tan(skewAngles1.z * coeff); // skewing in zx
m[2, 1] = Mathf.Tan(skewAngles2.z * coeff); // skewing in zy
Vector3[] verts = new Vector3[initialState.Length];
int i = 0;
while (i < verts.Length)
{
verts[i] = m.MultiplyPoint3x4(initialState[i]);
i++;
}
meshCached.vertices = verts;
angles1prev = skewAngles1;
angles2prev = skewAngles2;
}
/// <summary>
/// Attaches and starts the action.
/// </summary>
public void AttachAction(ActionInstant tgtAction)
{
if (action != null)
{
action.stop();
}
action = tgtAction;
action.setActor(this);
action.start();
}
/// <summary>
/// Stops all running actions for this actor.
/// </summary>
public void StopAction()
{
if (action == null)
return;
if (action.running)
action.stop();
action = null;
}
/// <summary>
/// Pauses actions for this actor.
/// </summary>
public void PauseAction()
{
paused = true;
}
/// <summary>
/// Unpauses actions for this actor.
/// </summary>
public void UnpauseAction()
{
paused = false;
}
/// <summary>
/// Sets the timescale for current action.
/// </summary>
public void SetTimeScale(float ts)
{
if (action is ActionInterval)
{
((ActionInterval)action).setTimeScale(ts);
}
}
/// <summary>
/// Adds method to cache to speed-up
/// </summary>
public void AddMethodToCache(MethodHolder method)
{
methodsCache.Add(method.name, method);
}
public void RemoveMethodFromCache(string key)
{
if (methodsCache.ContainsKey(key))
{
methodsCache.Remove(key);
}
else
{
throw new Exception("Method " + key + " not found in cache.");
}
}
public void ReceiveMessage(string key, object param = null, SendMessageOptions options = SendMessageOptions.DontRequireReceiver)
{
if (methodsCache.ContainsKey(key))
{
if (param == null)
methodsCache[key].run();
else
methodsCache[key].run(param);
}
else
{
gameObject.SendMessage(key, param, options);
}
}
}

View File

@@ -0,0 +1,55 @@
using UnityEngine;
using System.Collections;
using coa4u;
public class ActorSampleActions : Actor
{
public void Start()
{
ActionInstant seq = new ActionRepeat (new ActionSequence(new ActionInstant[]
{
new ActionFadeIn(2),
new ActionParallel(new ActionInstant[] {
new ActionMoveBy(new Vector3(10, 10, 0), 1),
new ActionRotateBy(new Vector3(90, 90, 0), 1),
new ActionTintBy(new Vector4(-50, 50, -150), 1)
}),
new ActionScaleBy(new Vector3(2, 2, 1), 1),
new ActionScaleBy(new Vector3(0.5F, 0.5F, 2), 1),
new ActionDelay(1),
new ActionBlink(5, 0.1F, 0.4F),
new ActionDelay(1),
new ActionSkewBy(Vector3.zero, new Vector3(0, 30, 0), 1),
new ActionDelay(1),
new ActionJumpBy(new Vector3(-10, 0, 0), 1, 4, 1),
new ActionSkewBy(Vector3.zero, new Vector3(30, 0, 30), 1),
new ActionJumpTo(new Vector3(10, 10, 10), 1, 3, 1),
new ActionRotateBy(new Vector3(90, 0, 0), 1),
new ActionSkewBy(Vector3.zero, new Vector3(-30, 0, -30), 1),
new ActionJumpBy(new Vector3(-10, 0, 0), 1, 2, 1),
new ActionSkewBy(Vector3.zero, new Vector3(0, -30, 0), 1),
new ActionDelay(0.5F),
new ActionBezierRel(new Vector2 (5, 0), new Vector2(5, -10), new Vector2 (0, -10), 2),
new ActionScaleTo(new Vector3(2, 2, 2), 1),
new ActionRotateTo(new Vector3(0, 0, 0), 1),
new ActionFadeOut(2),
new ActionSetTint(new Vector4(67, 105, 181)),
new ActionSendMessage("msgHello"),
new ActionSendMessage("msgHelloTo", "world"),
}), 5);
this.AttachAction(seq);
AddMethodToCache(new MethodHolder(msgHello));
AddMethodToCache(new MethodHolder<string>(msgHelloTo));
}
void msgHello()
{
Debug.Log("Hello!");
}
void msgHelloTo(string who)
{
Debug.Log("Hello " + who.ToString() + "!");
}
}