Code structure cleanup.

This commit is contained in:
2023-08-24 15:47:34 +08:00
parent e40c98ae1b
commit 1f58390298
137 changed files with 439 additions and 362 deletions

View File

@@ -0,0 +1,66 @@
using System;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
[DisallowMultipleComponent]
public abstract class MeshBase : SkinComponent {
public MeshBase() {
SubmitProperty("color", new PropOp.Color(v => Color = v));
SubmitProperty("opacity", new PropOp.Float(v => {
var c = Color;
c.a *= v;
Color = c;
}));
SubmitProperty("zindex", new PropOp.Integer(v => ZIndex = (short)v));
}
protected MeshWrapper mesh = new MeshWrapper();
protected Material[] materials;
short _zindex;
public short ZIndex {
get {
return _zindex;
}
set {
if (value < 0 || value > 5000)
throw new ArgumentOutOfRangeException("value", "Z-index must be in [0..5000]");
_zindex = value;
UpdateZIndex();
}
}
protected void UpdateZIndex() {
if (!mesh.Initialized) return;
foreach (var mat in materials) {
mat.renderQueue = _zindex;
}
}
Color _color = Color.white;
public Color Color {
get { return _color; }
set {
_color = value;
UpdateColor();
}
}
protected virtual void UpdateColor() {
if (!mesh.Initialized) return;
foreach (var mat in materials) {
mat.color = _color;
}
}
protected override void OnDestroy() {
DestroyMaterials();
mesh.Destroy();
}
protected void DestroyMaterials() {
if (materials == null) return;
foreach (var mat in materials) {
Material.Destroy(mat);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75daba44e5811b943a08e6f137cc2b0c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class MeshWrapper {
public GameObject MeshObject {
get;
private set;
}
public MeshFilter MeshFilter {
get;
private set;
}
Mesh m_mesh;
public Mesh Mesh {
get { return m_mesh; }
set { MeshFilter.sharedMesh = m_mesh = value; }
}
public Transform MeshTransform {
get;
private set;
}
public Renderer Renderer {
get;
private set;
}
public bool Initialized {
get;
private set;
}
public static Material NewMaterial() {
return Material.Instantiate(BuiltinResources.Materials["-SpriteMat"]);
}
public void Init(Transform parent) {
MeshObject = new GameObject("__mesh__");
MeshTransform = MeshObject.transform;
MeshTransform.SetParent(parent, false);
if (MeshObject.GetComponent<MeshFilter>() == null)
MeshObject.AddComponent<MeshFilter>();
if (MeshObject.GetComponent<MeshRenderer>() == null)
MeshObject.AddComponent<MeshRenderer>();
MeshFilter = MeshObject.GetComponent<MeshFilter>();
Renderer = MeshObject.GetComponent<Renderer>();
Initialized = true;
}
public void Destroy() {
Mesh.Destroy(m_mesh);
m_mesh = null;
GameObject.Destroy(MeshObject);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 39e842e4379944f46ae46577bd5f51d4
timeCreated: 1636616568
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,227 @@
using Cryville.Common.Buffers;
using Cryville.Common.Pdt;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class PolygonSGO : SectionalGameObject {
static readonly SimpleObjectPool<List<Vector3>> _ptPool = new SimpleObjectPool<List<Vector3>>(1024);
static readonly SimpleObjectPool<List<float>> _lPool = new SimpleObjectPool<List<float>>(1024);
static readonly ListPool<int> _indexPool = new ListPool<int>();
static readonly ListPool<Vector3> _vertPool = new ListPool<Vector3>();
static readonly ListPool<Vector2> _uvPool = new ListPool<Vector2>();
static readonly ArrayPool<Vector2> _shapePool = new ArrayPool<Vector2>(0x100, 0x10000);
public PolygonSGO() {
SubmitProperty("head", new PropOp.String(v => head.FrameName = v));
SubmitProperty("body", new PropOp.String(v => body.FrameName = v));
SubmitProperty("tail", new PropOp.String(v => tail.FrameName = v));
SubmitProperty("shape", new op_set_shape(this), 2);
}
#pragma warning disable IDE1006
public class op_set_shape : PdtOperator {
readonly PolygonSGO _self;
public op_set_shape(PolygonSGO self) : base(1) {
_self = self;
}
protected override unsafe void Execute() {
var o = GetOperand(0);
if (o.Type != PdtInternalType.Vector) throw new ArgumentException("Not a vector");
_self._shapeLength = (o.Length - sizeof(int)) / sizeof(Vector2);
if (_self._shape != null) _shapePool.Return(_self._shape);
_self._shape = _shapePool.Rent(_self._shapeLength);
for (int i = 0; i < _self._shapeLength; i++) {
_self._shape[i] = o.As<Vector2>(i * sizeof(Vector2));
}
}
}
#pragma warning restore IDE1006
int _shapeLength = 0;
Vector2[] _shape = null;
float GetWidth() {
float r = 0;
for (int i = 1; i < _shapeLength; i++) {
r += (_shape[i] - _shape[i-1]).magnitude;
}
return r;
}
public SpriteInfo head = new SpriteInfo();
public SpriteInfo body = new SpriteInfo();
public SpriteInfo tail = new SpriteInfo();
List<Vector3> vertices;
List<float> lengths;
float sumLength = 0;
public override void Init() {
mesh.Init(transform);
mesh.Mesh = new Mesh();
mesh.Renderer.sharedMaterials = materials = new Material[] {
MeshWrapper.NewMaterial(),
MeshWrapper.NewMaterial(),
MeshWrapper.NewMaterial(),
};
head.Bind(materials[0]);
body.Bind(materials[1]);
tail.Bind(materials[2]);
base.Init();
}
protected override void OnDestroy() {
if (_shape != null) _shapePool.Return(_shape);
if (vertices != null) {
_ptPool.Return(vertices);
_lPool.Return(lengths);
}
base.OnDestroy();
}
protected override void AppendPointInternal(Vector3 p, Quaternion r) {
if (vertices == null) {
vertices = _ptPool.Rent();
lengths = _lPool.Rent();
}
for (int i = 0; i < _shapeLength; i++) {
Vector2 sp = r * _shape[i];
vertices.Add(p + (Vector3)sp);
}
if (prevpt != null) {
float len = (p - prevpt.Value).magnitude;
lengths.Add(len);
sumLength += len;
}
}
List<Vector3> verts;
List<Vector2> uvs;
List<int> trih = null, trib = null, trit = null;
static readonly List<int> _emptyTris = new List<int>();
public override void Seal() {
if (vertCount <= 1 || sumLength == 0) return;
int vcpsec = _shapeLength; // Vertex Count Per Section
float width = GetWidth();
float headLength = 0;
if (head.Frame != null) headLength = width / head.Ratio;
float tailLength = 0;
if (tail.Frame != null) tailLength = width / tail.Ratio;
float endLength = headLength + tailLength;
if (sumLength <= endLength) {
// The total length of the two ends is longer than the whole mesh, squeeze the two ends
float ratio = sumLength / endLength;
headLength *= ratio;
tailLength *= ratio;
}
// Find the vertex counts needed for the three parts from the head
float l0 = 0;
int hvc = 0;
for (; l0 < headLength && hvc < lengths.Count; hvc++)
l0 += lengths[hvc];
int bvc = 0;
for (; l0 < sumLength - tailLength && hvc + bvc < lengths.Count; bvc++)
l0 += lengths[hvc + bvc];
int tvc = lengths.Count - hvc - bvc + 1;
if (hvc > 0) {
hvc++;
bvc++;
}
bvc++;
int vc = hvc + bvc + tvc;
verts = _vertPool.Rent(vc * vcpsec);
uvs = _uvPool.Rent(vc * vcpsec);
int i = 0; int t = 0; float l = 0;
if (head.Frame != null) { GenerateMeshTo(verts, uvs, out trih, head, ref i, ref t, ref l, 0, headLength, vcpsec, hvc); }
GenerateMeshTo(verts, uvs, out trib, body, ref i, ref t, ref l, headLength, sumLength - tailLength, vcpsec, hvc + bvc);
if (tail.Frame != null) { GenerateMeshTo(verts, uvs, out trit, tail, ref i, ref t, ref l, sumLength - tailLength, sumLength, vcpsec, vc); }
mesh.Mesh.subMeshCount = 3;
int m = 0;
mesh.Mesh.SetVertices(verts);
mesh.Mesh.SetUVs(0, uvs);
mesh.Mesh.SetTriangles(head.Frame == null ? _emptyTris : trih, m++);
mesh.Mesh.SetTriangles(trib, m++);
mesh.Mesh.SetTriangles(tail.Frame == null ? _emptyTris : trit, m++);
mesh.Mesh.RecalculateNormals();
_vertPool.Return(verts); verts = null;
_uvPool.Return(uvs); uvs = null;
if (trih != null) { _indexPool.Return(trih); trih = null; }
if (trib != null) { _indexPool.Return(trib); trib = null; }
if (trit != null) { _indexPool.Return(trit); trit = null; }
}
void GenerateMeshTo(List<Vector3> verts, List<Vector2> uvs, out List<int> tris, SpriteInfo info, ref int i, ref int t, ref float l, float startl, float endl, int vcpsec, int vend) {
if (i > lengths.Count) {
tris = _indexPool.Rent(0);
return;
}
int t0 = t;
var frame = info.Frame;
if (startl != 0) {
float pl2 = l - lengths[i - 1];
float fr2 = (startl - pl2) / (l - pl2);
for (int j = 0; j < vcpsec; j++, t++) {
verts[t] =
vertices[vcpsec*(i-1)+j] * (1-fr2)
+ vertices[vcpsec*i+j] * fr2;
var u = j / (vcpsec - 1);
if (frame != null) uvs[t] = frame.GetUV(u, 0);
}
}
for (; t / vcpsec < vend - 1; i++) {
var v = (l - startl) / (endl - startl);
for (int j = 0; j < vcpsec; j++, t++) {
verts[t] = vertices[vcpsec*i+j];
var u = j / (vcpsec - 1);
if (frame != null) uvs[t] = frame.GetUV(u, v);
}
l += lengths[i];
}
float pl = l - lengths[i - 1];
float fr = (endl - pl) / (l - pl);
for (int j = 0; j < vcpsec; j++, t++) {
verts[t] =
vertices[vcpsec*(i-1)+j] * (1-fr)
+ vertices[vcpsec*i+j] * fr;
var u = j / (vcpsec - 1);
if (frame != null) uvs[t] = frame.GetUV(u, 1);
}
tris = _indexPool.Rent((vend - t0 / vcpsec - 1) * (vcpsec - 1) * 6);
int i3 = 0;
for (int i1 = t0 + vcpsec + 1; i1 < t; i1++) {
if (i1 % vcpsec == 0) continue;
int i2 = i1 - vcpsec;
tris[i3++] = i1 - 1;
tris[i3++] = i2;
tris[i3++] = i2 - 1;
tris[i3++] = i1 - 1;
tris[i3++] = i1;
tris[i3++] = i2;
}
}
public override void Reset() {
base.Reset();
if (mesh.Initialized) mesh.Mesh.Clear();
if (vertices != null) {
vertices.Clear();
lengths.Clear();
}
sumLength = 0;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed3932875286a2947b9c600ba47f1066
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public abstract class SectionalGameObject : MeshBase {
protected Vector3? prevpt;
protected Quaternion? prevrot;
protected int vertCount = 0;
Part part = Part.whole;
enum Part {
whole = 0,
idle = 1,
start = 2,
end = 3,
}
public SectionalGameObject() {
SubmitProperty("partial", new PropOp.Boolean(v => part = Part.idle));
SubmitProperty("part", new PropOp.Enum<Part>(v => part = v, v => (Part)v), 2);
}
public override void Init() {
UpdateZIndex();
UpdateColor();
Reset();
}
public void AppendPoint(Vector3 p) {
AppendPoint(p, Quaternion.identity);
}
public void AppendPoint(Vector3 p, Quaternion r) {
if (prevpt == p && prevrot == r || ((int)part & 1) == 1) return;
AppendPointInternal(p, r);
// if (!headGenerated) Logger.Log("main", 0, "Skin/Polysec", "{0}", r);
prevpt = p;
prevrot = r;
vertCount++;
}
protected abstract void AppendPointInternal(Vector3 wp, Quaternion r);
public abstract void Seal();
public virtual void Reset() {
vertCount = 0;
prevpt = null;
prevrot = null;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5f2666d577419bd43aec55ad614a43f4
timeCreated: 1596633346
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using Cryville.Common;
using System;
using UnityEngine;
using Logger = Cryville.Common.Logging.Logger;
namespace Cryville.Crtr.Skin.Components {
public class SkinAnimation : SkinComponent {
public SkinAnimation() {
SubmitProperty("name", new PropOp.Identifier(v => Name = v));
SubmitProperty("duration", new PropOp.Float(v => Duration = v));
SubmitProperty("iteration", new PropOp.Float(v => Iteration = v));
SubmitProperty("direction", new PropOp.Enum<AnimationDirection>(v => Direction = v, v => (AnimationDirection)v));
SubmitProperty("delay", new PropOp.Float(v => Delay = v));
Iteration = 1;
}
SkinContext _skinContext;
Transform _writeTransform;
AnimationSpan _anim;
int _name;
public int Name {
set {
if (_name == value) return;
_name = value;
if (value == 0) {
_anim = null;
}
else {
var id = new Identifier(value);
AnimationSpan anim;
if (!ChartPlayer.pskin.animations.TryGetValue(id, out anim)) {
Logger.Log("main", 4, "Skin", "Animation {0} not found", id.Name);
_anim = null;
return;
}
_anim = anim;
}
}
}
public float Duration { get; private set; }
public float Iteration { get; private set; }
public AnimationDirection Direction { get; private set; }
public float Delay { get; private set; }
double _startTime;
public override void Init() {
_skinContext = new SkinContext(transform);
}
public override void Rewind(double time, Transform target) {
_startTime = time;
if (target == null) target = transform;
_writeTransform = target;
}
public override void Tick(SkinContainer c, double time) {
float _rtime = (float)(time - _startTime - Delay) / Duration;
if (_rtime < 0) _rtime = 0;
else if (_rtime > Iteration) {
if (Direction.HasFlag(AnimationDirection.alternate)) {
_rtime = Iteration % 2;
if (_rtime > 1) _rtime = 2 - _rtime;
}
else {
_rtime = Iteration % 1;
if (_rtime == 0) _rtime = 1;
}
}
else {
if (Direction.HasFlag(AnimationDirection.alternate)) {
_rtime %= 2;
if (_rtime > 1) _rtime = 2 - _rtime;
}
else {
_rtime %= 1;
}
}
if (Direction.HasFlag(AnimationDirection.reverse)) _rtime = 1 - _rtime;
if (_anim != null) c.MatchAnimation(_anim, _rtime, new RuntimeSkinContext(_skinContext, _writeTransform));
}
protected override void OnDestroy() { }
}
[Flags]
public enum AnimationDirection {
normal = 0,
reverse = 1,
alternate = 2,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80318e36af5412345871bdbf80d49ef2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using Cryville.Common;
using Cryville.Common.Collections.Specialized;
using Cryville.Common.Pdt;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public abstract class SkinComponent : MonoBehaviour {
/// <summary>
/// The property operators of the component.
/// </summary>
public IntKeyedDictionary<SkinProperty> Properties { get; private set; }
/// <summary>
/// Submits a property.
/// </summary>
/// <param name="name">The name of the property.</param>
/// <param name="property">The property.</param>
protected void SubmitProperty(string name, PdtOperator property, int udl = 1) {
Properties.Add(IdentifierManager.Shared.Request(name), new SkinProperty(property, udl));
}
/// <summary>
/// Creates a skin component.
/// </summary>
protected SkinComponent() {
Properties = new IntKeyedDictionary<SkinProperty>();
}
public virtual void Init() { }
public virtual void Rewind(double time, Transform target) { }
public virtual void Tick(SkinContainer c, double time) { }
protected abstract void OnDestroy();
}
public struct SkinProperty {
public PdtOperator Operator { get; set; }
public int UpdateDynamicLevel { get; set; }
public SkinProperty(PdtOperator op, int udl = 0) {
Operator = op;
UpdateDynamicLevel = udl;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a54d8e3558a89f8499fc049afd84e959
timeCreated: 1623576806
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using Cryville.Common.Pdt;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public abstract class SpriteBase : MeshBase {
public SpriteBase() {
SubmitProperty("bound", new op_set_bound(this));
SubmitProperty("pivot", new PropOp.Vector2(v => Pivot = v));
SubmitProperty("scale", new PropOp.Vector2(v => Scale = v));
SubmitProperty("ui", new PropOp.Boolean(v => UI = v));
}
#pragma warning disable IDE1006
class op_set_bound : PdtOperator {
readonly SpriteBase _self;
public op_set_bound(SpriteBase self) : base(2) {
_self = self;
}
protected override void Execute() {
_self.SetBound(
GetOperand(0).As<Vector2>(),
GetOperand(1).As<Vector3>()
);
}
}
#pragma warning restore IDE1006
Vector2 _scale = Vector2.one;
public Vector2 Scale {
get { return _scale; }
set {
_scale = value;
UpdateScale();
}
}
protected virtual void UpdateScale() {
if (!mesh.Initialized) return;
var s = BaseScale;
var ss = new Vector3(_scale.x, 1, _scale.y);
s.Scale(ss);
mesh.MeshTransform.localScale = s;
OnPivotUpdate();
}
protected abstract Vector3 BaseScale {
get;
}
protected virtual Vector3 BaseSize {
get { return Vector3.one; }
}
Vector2 _pivot;
public Vector2 Pivot {
get { return _pivot; }
set {
_pivot = value;
OnPivotUpdate();
}
}
protected void OnPivotUpdate() {
if (!mesh.Initialized) return;
var r = new Vector3(_pivot.x - BasePivot.x, 0, _pivot.y - BasePivot.y);
r.Scale(mesh.MeshTransform.localScale);
r.Scale(BaseSize);
mesh.MeshTransform.localPosition = -r;
}
protected virtual Vector2 BasePivot {
get { return Vector2.zero; }
}
public void SetBound(Vector2 piv, Vector3 pos) {
var r = Quaternion.Inverse(transform.rotation);
var da = piv - Pivot;
var dp = r * (pos - transform.localPosition);
if (da.x != 0) _scale.x = dp.x / da.x;
if (da.y != 0) _scale.y = dp.z / da.y;
}
static readonly Quaternion uirot
= Quaternion.Euler(new Vector3(-90, 0, 0));
bool _ui;
public bool UI {
get { return _ui; }
set {
_ui = value;
if (_ui) transform.localRotation = uirot;
}
}
protected void InternalInit(string meshName = "quad") {
mesh.Init(transform);
mesh.Renderer.sharedMaterials = materials = new Material[] { MeshWrapper.NewMaterial() };
mesh.Mesh = Mesh.Instantiate(BuiltinResources.Meshes[meshName]);
UpdateColor();
UpdateScale();
UpdateZIndex();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 248ab93b20a0ac9439afaee32357ed5c
timeCreated: 1614907140
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,188 @@
using System;
using UnityEngine;
using Logger = Cryville.Common.Logging.Logger;
namespace Cryville.Crtr.Skin.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; }
}
/// <summary>
/// The ratio of width divided by height.
/// </summary>
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 => Frame = v));
SubmitProperty("frames", new PropOp.StringArray(v => Frames = v));
SubmitProperty("index", new PropOp.Integer(v => Index = v));
SubmitProperty("fit", new PropOp.Enum<FitMode>(v => Fit = v, v => (FitMode)v));
SubmitProperty("shader", new PropOp.String(v => Shader = v));
}
static Vector2[] _origuv;
protected static Vector2[] OriginalUV {
get {
if (_origuv == null) {
var m = BuiltinResources.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[] { new SpriteInfo() };
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();
}
}
public string Frame {
set {
if (value == CurrentFrame.FrameName) return;
CurrentFrame.FrameName = value;
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.sharedMaterial.mainTexture = frame.Frame.Texture;
UpdateUV();
UpdateScale();
}
Shader m_shader;
public string Shader {
set {
m_shader = BuiltinResources.Shaders[value];
UpdateShader();
}
}
void UpdateShader() {
if (!mesh.Initialized) return;
if (m_shader == null) m_shader = BuiltinResources.Shaders["default"];
mesh.Renderer.sharedMaterial.shader = m_shader;
UpdateZIndex();
}
readonly Vector2[] _uvs = new Vector2[4];
protected virtual void UpdateUV() {
var frame = CurrentFrame;
if (SpriteInfo.IsNullOrEmpty(frame)) return;
Vector2[] muv = OriginalUV;
for (int i = 0; i < _uvs.Length; i++) {
_uvs[i] = frame.Frame.GetUV(muv[i]);
}
mesh.Mesh.uv = _uvs;
}
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();
UpdateShader();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 76053cf6896b7304fb0ec26546de1ace
timeCreated: 1609142271
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class SpriteRect : SpriteBase {
public SpriteRect() { }
protected override Vector3 BaseScale {
get { return Vector3.one; }
}
public override void Init() {
InternalInit();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a902fb77646e6eb4eb96d8ac86b3ee0e
timeCreated: 1614821846
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class SpriteScale3 : SpritePlane {
public SpriteScale3() {
SubmitProperty("border", new PropOp.Vector2(v => Border = v));
}
static readonly Dictionary<float, int> uvrefl
= new Dictionary<float, int>() {
{-0.5f, 0}, {-0.4f, 1}, {0.4f, 2}, {0.5f, 3},
};
static Vector2[] _origuv;
protected static new Vector2[] OriginalUV {
get {
if (_origuv == null) {
var m = BuiltinResources.Meshes["quad_scale3h"];
Vector2[] uv = new Vector2[m.vertices.Length];
for (int i = 0; i < uv.Length; i++) {
uv[i] = new Vector2(
uvrefl[m.vertices[i].x],
uvrefl[m.vertices[i].z]
);
}
_origuv = uv;
}
return _origuv;
}
}
Vector2 _border = new Vector2(0, 1);
public Vector2 Border {
get { return _border; }
set {
_border = value;
UpdateScale();
}
}
protected override void UpdateScale() {
base.UpdateScale();
if (!mesh.Initialized) return;
UpdateUV();
}
readonly Vector2[] _uvs = new Vector2[8];
readonly Vector3[] _verts = new Vector3[8];
protected override void UpdateUV() {
var frame = CurrentFrame;
if (SpriteInfo.IsNullOrEmpty(frame)) return;
Vector2[] muv = OriginalUV;
var or = frame.Ratio;
var sr = Scale.x / Scale.y;
var rr = or / sr;
var b1 = rr * _border.x;
var b2 = 1 - rr * (1 - _border.y);
for (int i = 0; i < muv.Length; i++) {
float x; float bx;
switch ((int)muv[i].x) {
case 0: x = 0; bx = 0; break;
case 1: x = _border.x; bx = b1; break;
case 2: x = _border.y; bx = b2; break;
case 3: x = 1; bx = 1; break;
default: throw new NotSupportedException("Built-in resource corrupted");
}
float y;
switch ((int)muv[i].y) {
case 0: y = 0; break;
case 3: y = 1; break;
default: throw new NotSupportedException("Built-in resource corrupted");
}
_uvs[i] = frame.Frame.GetUV(x, y);
bx -= 0.5f; y -= 0.5f;
_verts[i] = new Vector3(bx, 0, y);
}
mesh.Mesh.uv = _uvs;
mesh.Mesh.vertices = _verts;
}
public override void Init() {
InternalInit("quad_scale3h");
OnFrameUpdate();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 31dc4a947b5c7c645aa8fc2b82b4fba7
timeCreated: 1615333501
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,175 @@
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);
int arrtype; int len;
values.GetArraySuffix(out arrtype, out 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 TargetString();
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 Dictionary<Texture2D, MeshWrapper>();
readonly Dictionary<Texture2D, List<Vector3>> verts = new Dictionary<Texture2D, List<Vector3>>();
readonly Dictionary<Texture2D, List<Vector2>> uvs = new Dictionary<Texture2D, List<Vector2>>();
readonly Dictionary<Texture2D, List<int>> tris = new Dictionary<Texture2D, List<int>>();
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) {
var f = m_frames[c];
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.OnUpdate += UpdateScale;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6c3781c012a298849b9276df00b6f59c
timeCreated: 1636509150
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class TrackLine : SectionalGameObject {
readonly List<Vector3> vertices = new List<Vector3>();
LineRenderer lineRenderer;
public TrackLine() {
SubmitProperty("width", new PropOp.Float(v => Width = v));
}
private float m_width;
public float Width {
get { return m_width; }
set {
m_width = value;
if (lineRenderer != null) {
lineRenderer.startWidth = value;
lineRenderer.endWidth = value;
}
}
}
public override void Init() {
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.materials = materials = new Material[] { MeshWrapper.NewMaterial() };
Width = Width;
base.Init();
}
protected override void UpdateColor() {
base.UpdateColor();
if (lineRenderer != null) {
lineRenderer.startColor = Color;
lineRenderer.endColor = Color;
}
}
protected override void AppendPointInternal(Vector3 p, Quaternion r) {
vertices.Add(p);
}
public override void Seal() {
#if UNITY_5_6_OR_NEWER
lineRenderer.positionCount = vertices.Count;
#else
lineRenderer.SetVertexCount(vertices.Count);
#endif
for (int i = 0; i < vertices.Count; i++) lineRenderer.SetPosition(i, vertices[i]);
}
public override void Reset() {
base.Reset();
vertices.Clear();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7806feaea6d6c2540b2cb950286d379c
timeCreated: 1596635435
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Cryville.Crtr.Skin.Components {
public class TransformInterface : SkinComponent {
public TransformInterface() {
SubmitProperty("pos", new PropOp.Vector3(v => transform.localPosition = v));
SubmitProperty("rot", new PropOp.Vector3(v => transform.localRotation = Quaternion.Euler(v)));
SubmitProperty("scale", new PropOp.Vector3(v => transform.localScale = v));
}
protected override void OnDestroy() { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a8a184616fd97d4a877c59c2ff76ba3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: