using System; using UnityEngine; using Logger = Cryville.Common.Logger; namespace Cryville.Crtr.Components { public class SpriteInfo { string m_frameName; public string FrameName { get { return m_frameName; } set { m_frameName = value; Reload(); } } public SpriteFrame Frame { get; private set; } public Rect Rect { get { return Frame.Frame; } } /// /// The ratio of width divided by height. /// public float Ratio { get { return Rect.width / Rect.height; } } Material _mat; public void Bind(Material mat) { _mat = mat; Reload(); } public void Reload() { if (!string.IsNullOrEmpty(FrameName)) { if (ChartPlayer.frames.ContainsKey(FrameName)) { Frame = ChartPlayer.frames[FrameName]; } else { Logger.Log("main", 4, "Skin", "Texture {0} not found", FrameName); Frame = null; } } else Frame = null; if (_mat != null) { _mat.mainTexture = Frame == null ? null : Frame.Texture; } } public static bool IsNullOrEmpty(SpriteInfo sprite) { return sprite == null || sprite.Frame == null; } } public class SpritePlane : SpriteBase { public SpritePlane() { SubmitProperty("frame", new PropOp.String(v => { Frames = new string[] { v }; Index = 0; })); SubmitProperty("frames", new PropOp.StringArray(v => Frames = v)); SubmitProperty("index", new PropOp.Integer(v => Index = v)); SubmitProperty("fit", new PropOp.Enum(v => Fit = v, v => (FitMode)v)); SubmitProperty("opacity", new PropOp.Float(v => Opacity = v)); } static Vector2[] _origuv; protected static Vector2[] OriginalUV { get { if (_origuv == null) { var m = GenericResources.Meshes["quad"]; Vector2[] uv = new Vector2[m.vertices.Length]; for (int i = 0; i < uv.Length; i++) { uv[i] = new Vector2( m.vertices[i].x == 0.5 ? 1 : 0, m.vertices[i].z == 0.5 ? 1 : 0 ); } _origuv = uv; } return _origuv; } } int m_index; public int Index { get { return m_index; } set { m_index = value; OnFrameUpdate(); } } SpriteInfo[] m_frames = new SpriteInfo[0]; public string[] Frames { set { m_frames = new SpriteInfo[value.Length]; for (int i = 0; i < value.Length; i++) { m_frames[i] = new SpriteInfo() { FrameName = value[i] }; } OnFrameUpdate(); } } protected SpriteInfo CurrentFrame { get { if (m_frames.Length == 0) return null; if (m_index < 0) m_index = 0; else if (m_index >= m_frames.Length) m_index = m_frames.Length - 1; return m_frames[m_index]; } } protected void OnFrameUpdate() { if (!mesh.Initialized) return; var frame = CurrentFrame; if (SpriteInfo.IsNullOrEmpty(frame)) { mesh.Renderer.enabled = false; return; } mesh.Renderer.enabled = true; mesh.Renderer.material.mainTexture = frame.Frame.Texture; UpdateUV(); UpdateScale(); UpdateZIndex(); } protected virtual void UpdateUV() { var frame = CurrentFrame; if (SpriteInfo.IsNullOrEmpty(frame)) return; Vector2[] muv = OriginalUV; Vector2[] uv = new Vector2[muv.Length]; for (int i = 0; i < uv.Length; i++) { uv[i] = frame.Frame.GetUV(muv[i]); } mesh.Mesh.uv = uv; } float _opacity = 1; public float Opacity { get { return _opacity; } set { _opacity = value; UpdateOpacity(); } } protected void UpdateOpacity() { if (!mesh.Initialized) return; var c = mesh.Renderer.material.color; c.a = _opacity; mesh.Renderer.material.color = c; } private FitMode m_fit = FitMode.height; public FitMode Fit { get { return m_fit; } set { m_fit = value; if (m_fit != FitMode.none && Scale.x != Scale.y) m_fit = FitMode.none; } } public enum FitMode { none, width, height } protected override void UpdateScale() { if (SpriteInfo.IsNullOrEmpty(CurrentFrame)) return; base.UpdateScale(); if (m_fit != FitMode.none && Scale.x != Scale.y) m_fit = FitMode.none; } protected override Vector3 BaseScale { get { switch (m_fit) { case FitMode.none: return Vector3.one; case FitMode.width: return new Vector3(1, 1, 1 / CurrentFrame.Ratio); case FitMode.height: return new Vector3(CurrentFrame.Ratio, 1, 1); default: throw new NotSupportedException("Unsupported fit mode"); } } } public override void Init() { InternalInit(); OnFrameUpdate(); UpdateOpacity(); } } }