You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.5 KiB
C#
159 lines
4.5 KiB
C#
using Duality;
|
|
using Duality.Components;
|
|
using Duality.Components.Renderers;
|
|
using Duality.Drawing;
|
|
using Duality.Resources;
|
|
|
|
namespace BasicMenu
|
|
{
|
|
[RequiredComponent(typeof(SpriteRenderer))]
|
|
public abstract class MenuComponent : Component, ICmpUpdatable
|
|
{
|
|
private static readonly float MAX_FADE_TIME = .5f;
|
|
|
|
private ColorRgba hoverTint;
|
|
|
|
[DontSerialize]
|
|
private ColorRgba originalTint;
|
|
[DontSerialize]
|
|
private SpriteRenderer sprite;
|
|
|
|
[DontSerialize]
|
|
private ColorRgba targetTint;
|
|
[DontSerialize]
|
|
private Vector4 startingTint;
|
|
[DontSerialize]
|
|
private Vector4 tintDelta;
|
|
[DontSerialize]
|
|
private float timeToFade;
|
|
[DontSerialize]
|
|
private float fadingTime;
|
|
[DontSerialize]
|
|
private bool isFadingOut;
|
|
|
|
public MenuComponent()
|
|
{
|
|
this.hoverTint = ColorRgba.Red;
|
|
this.fadingTime = MAX_FADE_TIME;
|
|
}
|
|
|
|
/// <summary>
|
|
/// [GET/SET] The color tint that will be used when the mouse is hovering
|
|
/// on the GameObject
|
|
/// </summary>
|
|
public ColorRgba HoverTint
|
|
{
|
|
get { return this.hoverTint; }
|
|
set { this.hoverTint = value; }
|
|
}
|
|
|
|
public virtual void DoAction() { }
|
|
|
|
/// <summary>
|
|
/// This returns the area on screen that is currently occupied by the SpriteRenderer.
|
|
/// For simplicity, this works only if it is set with the ScreenOverlay flag.
|
|
///
|
|
/// A full 2.5D implementation (no ScreenOverlay) would require more complex calculations.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Rect GetAreaOnScreen()
|
|
{
|
|
if (this.sprite == null)
|
|
this.sprite = this.GameObj.GetComponent<SpriteRenderer>();
|
|
|
|
// Determine position and scale of this menu button on the screen
|
|
Camera mainCamera = this.GameObj.ParentScene.FindComponent<Camera>();
|
|
Vector3 screenBasePos = mainCamera.GetScreenCoord(this.GameObj.Transform.Pos);
|
|
float screenScale = mainCamera.GetScaleAtZ(this.GameObj.Transform.Pos.Z);
|
|
|
|
Rect result = this.sprite.Rect
|
|
.Scaled(screenScale, screenScale)
|
|
.WithOffset(screenBasePos.Xy);
|
|
|
|
return result;
|
|
}
|
|
|
|
void ICmpUpdatable.OnUpdate()
|
|
{
|
|
// get the milliseconds elapsed since the last frame
|
|
float lastDelta = Time.TimeMult * Time.MsPFMult / 1000;
|
|
|
|
if (this.fadingTime < this.timeToFade)
|
|
{
|
|
// I'm still fading...
|
|
if (this.fadingTime + lastDelta >= this.timeToFade)
|
|
{
|
|
// ... but after this frame, I will stop. I can simply set the color as the target.
|
|
this.sprite.ColorTint = this.targetTint;
|
|
|
|
if (this.isFadingOut)
|
|
{
|
|
// since it was a fade out, I set fadingTime as the maximum allowed,
|
|
// so that the following fade in can take all the time it needs.
|
|
this.fadingTime = MAX_FADE_TIME;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ... and after this frame I will still be fading. Get the correct color.
|
|
Vector4 newTint = this.startingTint + (this.tintDelta * (this.fadingTime + lastDelta));
|
|
this.sprite.ColorTint = this.VectorToColor(newTint);
|
|
}
|
|
}
|
|
|
|
this.fadingTime = MathF.Min(this.fadingTime + lastDelta, MAX_FADE_TIME);
|
|
}
|
|
|
|
public void MouseEnter()
|
|
{
|
|
if (this.sprite != null)
|
|
{
|
|
if (this.originalTint == default(ColorRgba))
|
|
{
|
|
this.originalTint = this.sprite.ColorTint;
|
|
}
|
|
|
|
this.FadeTo(this.hoverTint, false);
|
|
}
|
|
}
|
|
|
|
public void MouseLeave()
|
|
{
|
|
if (this.originalTint != default(ColorRgba) && this.sprite != null)
|
|
{
|
|
this.FadeTo(this.originalTint, true);
|
|
}
|
|
}
|
|
|
|
protected void FadeTo(ColorRgba targetColor, bool fadeOut)
|
|
{
|
|
this.targetTint = targetColor;
|
|
this.isFadingOut = fadeOut;
|
|
|
|
this.startingTint = this.ColorToVector(this.sprite.ColorTint);
|
|
|
|
Vector4 delta = this.ColorToVector(this.targetTint) - this.startingTint;
|
|
|
|
// Here I use the time taken for the last fade operation as the time available for the new one.
|
|
// This is because if I am fading in and move out the mouse before the fading is complete,
|
|
// I want to take the same amount of time to revert back and not take MAX_FADE_TIME regardless
|
|
// of the previous situation. If I'm fading out, I can revert it to MAX_FADE_TIME (see OnUpdate)
|
|
this.timeToFade = this.fadingTime;
|
|
this.fadingTime = 0;
|
|
|
|
this.tintDelta = delta / this.timeToFade;
|
|
}
|
|
|
|
// Utility method to convert a ColorRgba to a Vector4 with values [0-1]
|
|
private Vector4 ColorToVector(ColorRgba color)
|
|
{
|
|
return new Vector4(color.R, color.G, color.B, color.A) / 255f;
|
|
}
|
|
|
|
// Utility method to convert a Vector4 with values [0-1] to a ColorRgba
|
|
private ColorRgba VectorToColor(Vector4 vector)
|
|
{
|
|
return new ColorRgba(vector.X, vector.Y, vector.Z, vector.W);
|
|
}
|
|
}
|
|
} |