178 lines
5.2 KiB
C#
178 lines
5.2 KiB
C#
using Cryville.Common.Buffers;
|
|
using Cryville.Common.Pdt;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Cryville.Crtr.Skin.Components {
|
|
public class SpriteText : SpriteBase {
|
|
public SpriteText() {
|
|
SubmitProperty("frames", new op_set_frames(this));
|
|
SubmitProperty("value", new PropOp.TargetString(() => Value));
|
|
SubmitProperty("size", new PropOp.Float(v => Size = v));
|
|
SubmitProperty("spacing", new PropOp.Float(v => Spacing = v));
|
|
}
|
|
|
|
#pragma warning disable IDE1006
|
|
class op_set_frames : PdtOperator {
|
|
readonly SpriteText _self;
|
|
public op_set_frames(SpriteText self) : base(2) {
|
|
_self = self;
|
|
}
|
|
protected override unsafe void Execute() {
|
|
var keys = GetOperand(0).AsString();
|
|
var values = GetOperand(1);
|
|
values.GetArraySuffix(out int arrtype, out int len);
|
|
if (arrtype != PdtInternalType.String) throw new InvalidCastException("Not an array of strings");
|
|
if (len != keys.Length) throw new ArgumentException("Length of key not equal to frame count");
|
|
var result = new Dictionary<char, SpriteInfo>(len);
|
|
int o = 0;
|
|
for (int i = 0; i < len; i++) {
|
|
string v = values.AsString(o);
|
|
o += v.Length * sizeof(char) + sizeof(int);
|
|
result.Add(keys[i], new SpriteInfo { FrameName = v });
|
|
}
|
|
_self.Frames = result;
|
|
}
|
|
}
|
|
#pragma warning restore IDE1006
|
|
|
|
protected override void OnDestroy() {
|
|
base.OnDestroy();
|
|
foreach (var m in meshes) m.Value.Destroy();
|
|
}
|
|
|
|
Dictionary<char, SpriteInfo> m_frames;
|
|
public Dictionary<char, SpriteInfo> Frames {
|
|
get { return m_frames; }
|
|
set { m_frames = value; UpdateFrames(); }
|
|
}
|
|
|
|
readonly TargetString m_value = new();
|
|
public TargetString Value { get { return m_value; } }
|
|
|
|
public float m_size;
|
|
public float Size {
|
|
get { return m_size; }
|
|
set { m_size = value; UpdateScale(); }
|
|
}
|
|
|
|
public float m_spacing;
|
|
public float Spacing {
|
|
get { return m_spacing; }
|
|
set { m_spacing = value; UpdateScale(); }
|
|
}
|
|
|
|
protected override void UpdateScale() {
|
|
if (!mesh.Initialized) return;
|
|
UpdateMeshes();
|
|
base.UpdateScale();
|
|
}
|
|
|
|
void UpdateFrames() {
|
|
if (!mesh.Initialized) return;
|
|
float frameHeight = 0;
|
|
foreach (var m in meshes) m.Value.Destroy();
|
|
meshes.Clear();
|
|
verts.Clear();
|
|
uvs.Clear();
|
|
DestroyMaterials();
|
|
materials = new Material[m_frames.Count];
|
|
int i = 0;
|
|
foreach (var f in m_frames) {
|
|
if (SpriteInfo.IsNullOrEmpty(f.Value)) continue;
|
|
if (frameHeight == 0) frameHeight = f.Value.Rect.height;
|
|
else if (frameHeight != f.Value.Rect.height) throw new Exception("Inconsistent frame height for text component");
|
|
var tex = f.Value.Frame.Texture;
|
|
if (!meshes.ContainsKey(tex)) {
|
|
var m = new MeshWrapper();
|
|
m.Init(mesh.MeshTransform);
|
|
m.Mesh = new Mesh();
|
|
var mat = MeshWrapper.NewMaterial();
|
|
mat.mainTexture = tex;
|
|
m.Renderer.sharedMaterial = materials[i++] = mat;
|
|
meshes.Add(tex, m);
|
|
verts.Add(tex, new List<Vector3>());
|
|
uvs.Add(tex, new List<Vector2>());
|
|
tris.Add(tex, new List<int>());
|
|
}
|
|
}
|
|
UpdateColor();
|
|
UpdateScale();
|
|
}
|
|
|
|
float sum_x;
|
|
readonly Dictionary<Texture2D, MeshWrapper> meshes = new();
|
|
readonly Dictionary<Texture2D, List<Vector3>> verts = new();
|
|
readonly Dictionary<Texture2D, List<Vector2>> uvs = new();
|
|
readonly Dictionary<Texture2D, List<int>> tris = new();
|
|
void UpdateMeshes() {
|
|
if (meshes.Count == 0) return;
|
|
sum_x = 0;
|
|
foreach (var t in meshes) {
|
|
var key = t.Key;
|
|
verts[key].Clear();
|
|
uvs[key].Clear();
|
|
tris[key].Clear();
|
|
}
|
|
foreach (var c in m_value) {
|
|
if (!m_frames.TryGetValue(c, out SpriteInfo f)) {
|
|
Game.MainLogger.Log(3, "Skin", "Could not render the character '{0}' in the string \"{1}\" on the text component because no image is assigned to that character.", c, m_value);
|
|
continue;
|
|
}
|
|
var t = f.Frame.Texture;
|
|
float w = f.Ratio * m_size;
|
|
verts[t].Add(new Vector3(sum_x , 0, 0));
|
|
verts[t].Add(new Vector3(sum_x + w, 0, 0));
|
|
verts[t].Add(new Vector3(sum_x + w, 0, m_size));
|
|
verts[t].Add(new Vector3(sum_x , 0, m_size));
|
|
uvs[t].Add(f.Frame.GetUV(new Vector2(0, 0)));
|
|
uvs[t].Add(f.Frame.GetUV(new Vector2(1, 0)));
|
|
uvs[t].Add(f.Frame.GetUV(new Vector2(1, 1)));
|
|
uvs[t].Add(f.Frame.GetUV(new Vector2(0, 1)));
|
|
sum_x += w + m_spacing;
|
|
}
|
|
foreach (var t in meshes) {
|
|
var key = t.Key;
|
|
var m = meshes[key].Mesh;
|
|
m.Clear();
|
|
int cc = verts[key].Count / 4;
|
|
var _tris = tris[key];
|
|
for (int i = 0; i < cc; i++) {
|
|
_tris.Add(i * 4);
|
|
_tris.Add(i * 4 + 3);
|
|
_tris.Add(i * 4 + 1);
|
|
_tris.Add(i * 4 + 1);
|
|
_tris.Add(i * 4 + 3);
|
|
_tris.Add(i * 4 + 2);
|
|
}
|
|
m.SetVertices(verts[key]);
|
|
m.SetUVs(0, uvs[key]);
|
|
m.SetTriangles(tris[key], 0);
|
|
m.RecalculateNormals();
|
|
}
|
|
sum_x -= m_spacing;
|
|
}
|
|
|
|
protected override Vector3 BaseSize {
|
|
get { return new Vector3(sum_x, 1, m_size); }
|
|
}
|
|
protected override Vector3 BaseScale {
|
|
get {
|
|
return Vector3.one;
|
|
}
|
|
}
|
|
protected override Vector2 BasePivot {
|
|
get { return new Vector2(-0.5f, -0.5f); }
|
|
}
|
|
|
|
public override void Init() {
|
|
InternalInit();
|
|
UpdateFrames();
|
|
mesh.Mesh.Clear();
|
|
UpdateScale();
|
|
Value.Updated += UpdateScale;
|
|
}
|
|
}
|
|
}
|