upd: sync local changes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b8ddf1f0df
commit
a9d4417fce
27 files changed
+3446
-1148
No files matched your search
@@ -5,20 +5,29 @@ using Godot;
|
||||
namespace Cthangover.Live2D.Cubism.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the 2D transformation (scale, translation, alignment) for a
|
||||
/// Cubism model rendered inside a Godot <see cref="Node2D"/>.
|
||||
///
|
||||
/// Works with two coordinate systems:
|
||||
/// Port of CubismModelMatrix.cpp (Cubism SDK for Native 5-r.5).
|
||||
/// Manages the 2D transformation (scale, translation, alignment) of a Cubism
|
||||
/// model inside its logical coordinate space.
|
||||
///
|
||||
/// SDK semantics to be aware of:
|
||||
/// <list type="bullet">
|
||||
/// <item>Cubism canvas coordinates (the model's native coordinate space)</item>
|
||||
/// <item>Godot node local coordinates (where the model is placed)</item>
|
||||
/// <item><see cref="SetWidth"/> and <see cref="SetHeight"/> MULTIPLY the
|
||||
/// current scale by target / canvas-size (they do not assign it),
|
||||
/// exactly like the C++ original.</item>
|
||||
/// <item>The (width, height) constructor performs
|
||||
/// <c>SetHeight(2.0f)</c> like the SDK, i.e. the model is initially
|
||||
/// scaled to occupy 2 logical units of height.</item>
|
||||
/// <item>Translation methods are INCREMENTAL in the SDK: SetX/SetY,
|
||||
/// SetPosition, Top, Left (via TranslateX/Y) add to the current
|
||||
/// translation. SetupFromLayout is unaffected because it starts from a
|
||||
/// fresh matrix (translation 0).</item>
|
||||
/// <item>CenterX/CenterY/Bottom/Right compute their offset from the full
|
||||
/// scaled size (canvas size × current scale).</item>
|
||||
/// </list>
|
||||
///
|
||||
/// The scale is computed relative to the canvas dimensions stored at construction.
|
||||
/// <see cref="SetWidth"/> and <see cref="SetHeight"/> set a uniform scale based
|
||||
/// on the ratio of target size to canvas size. <see cref="SetupFromLayout"/> reads
|
||||
/// positioning keys from a Cubism .model3.json "Layout" section.
|
||||
/// <see cref="ApplyToNode"/> writes the final transform to a Godot Node2D.
|
||||
///
|
||||
/// <see cref="SetupFromLayout"/> reads positioning keys from a Cubism
|
||||
/// .model3.json "Layout" section; <see cref="ApplyToNode"/> writes the final
|
||||
/// transform to a Godot <see cref="Node2D"/>.
|
||||
/// </summary>
|
||||
public class CubismModelMatrix
|
||||
{
|
||||
@@ -33,68 +42,80 @@ namespace Cthangover.Live2D.Cubism.Framework
|
||||
public CubismModelMatrix() { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a matrix referenced to the given canvas pixel dimensions.
|
||||
/// Subsequent calls to <see cref="SetWidth"/> and <see cref="SetHeight"/>
|
||||
/// will compute scale as target / canvas.
|
||||
/// Creates a matrix referenced to the given canvas dimensions.
|
||||
/// Like the SDK constructor, this calls <see cref="SetHeight"/>(2.0f),
|
||||
/// so the model initially occupies 2 logical units of height.
|
||||
/// </summary>
|
||||
public CubismModelMatrix(float width, float height)
|
||||
{
|
||||
_width = width;
|
||||
_height = height;
|
||||
|
||||
SetHeight(2.0f);
|
||||
}
|
||||
|
||||
/// <summary>Current uniform scale on the X axis.</summary>
|
||||
/// <summary>Current scale on the X axis.</summary>
|
||||
public float ScaleX => _scaleX;
|
||||
|
||||
/// <summary>Current uniform scale on the Y axis.</summary>
|
||||
/// <summary>Current scale on the Y axis.</summary>
|
||||
public float ScaleY => _scaleY;
|
||||
|
||||
/// <summary>Current X translation offset in Godot local coordinates.</summary>
|
||||
/// <summary>Current X translation offset.</summary>
|
||||
public float TranslateX => _translateX;
|
||||
|
||||
/// <summary>Current Y translation offset in Godot local coordinates.</summary>
|
||||
/// <summary>Current Y translation offset.</summary>
|
||||
public float TranslateY => _translateY;
|
||||
|
||||
/// <summary>SDK CubismModelMatrix::Scale — multiplies the current scale.</summary>
|
||||
public void Scale(float scaleX, float scaleY)
|
||||
{
|
||||
_scaleX *= scaleX;
|
||||
_scaleY *= scaleY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets uniform scale to match the given width. Scale = targetWidth / canvasWidth.
|
||||
/// Does nothing if canvas width is zero or unknown.
|
||||
/// SDK SetWidth: multiplies the current uniform scale by w / canvasWidth.
|
||||
/// Ignored when the canvas width is zero or unknown (the SDK would divide by zero).
|
||||
/// </summary>
|
||||
public void SetWidth(float w)
|
||||
{
|
||||
if (_width > 0f)
|
||||
{
|
||||
var scale = w / _width;
|
||||
_scaleX = scale;
|
||||
_scaleY = scale;
|
||||
}
|
||||
if (_width <= 0f) return;
|
||||
|
||||
var scaleX = w / _width;
|
||||
var scaleY = scaleX;
|
||||
Scale(scaleX, scaleY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets uniform scale to match the given height. Scale = targetHeight / canvasHeight.
|
||||
/// Does nothing if canvas height is zero or unknown.
|
||||
/// SDK SetHeight: multiplies the current uniform scale by h / canvasHeight.
|
||||
/// Ignored when the canvas height is zero or unknown (the SDK would divide by zero).
|
||||
/// </summary>
|
||||
public void SetHeight(float h)
|
||||
{
|
||||
if (_height > 0f)
|
||||
{
|
||||
var scale = h / _height;
|
||||
_scaleX = scale;
|
||||
_scaleY = scale;
|
||||
}
|
||||
if (_height <= 0f) return;
|
||||
|
||||
var scaleX = h / _height;
|
||||
var scaleY = scaleX;
|
||||
Scale(scaleX, scaleY);
|
||||
}
|
||||
|
||||
/// <summary>Sets absolute translation position.</summary>
|
||||
public void SetPosition(float x, float y)
|
||||
/// <summary>SDK Translate — adds x and y to the current translation
|
||||
/// (the SDK's TranslateX/TranslateY helpers are folded in here; the
|
||||
/// TranslateX/TranslateY properties above are the read accessors).</summary>
|
||||
public void Translate(float x, float y)
|
||||
{
|
||||
_translateX = x;
|
||||
_translateY = y;
|
||||
_translateX += x;
|
||||
_translateY += y;
|
||||
}
|
||||
|
||||
/// <summary>Sets absolute X translation.</summary>
|
||||
public void SetX(float x) => _translateX = x;
|
||||
/// <summary>SDK SetPosition — incremental (adds to the current translation).</summary>
|
||||
public void SetPosition(float x, float y) => Translate(x, y);
|
||||
|
||||
/// <summary>Sets absolute Y translation.</summary>
|
||||
public void SetY(float y) => _translateY = y;
|
||||
/// <summary>SDK SetX — incremental (adds to the current X translation).</summary>
|
||||
public void SetX(float x) => _translateX += x;
|
||||
|
||||
/// <summary>SDK SetY — incremental (adds to the current Y translation).</summary>
|
||||
public void SetY(float y) => _translateY += y;
|
||||
|
||||
/// <summary>
|
||||
/// Centers the model horizontally and vertically at the given point.
|
||||
@@ -106,34 +127,45 @@ namespace Cthangover.Live2D.Cubism.Framework
|
||||
CenterY(y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Centers horizontally: translateX = x - (width * scaleX) / 2.
|
||||
/// </summary>
|
||||
public void CenterX(float x) => _translateX = x - (_width * _scaleX) / 2f;
|
||||
/// <summary>SDK CenterX — adds x - (width × scaleX) / 2 to the X translation.</summary>
|
||||
public void CenterX(float x)
|
||||
{
|
||||
var w = _width * _scaleX;
|
||||
_translateX += x - (w / 2f);
|
||||
}
|
||||
|
||||
/// <summary>SDK CenterY — adds y - (height × scaleY) / 2 to the Y translation.</summary>
|
||||
public void CenterY(float y)
|
||||
{
|
||||
var h = _height * _scaleY;
|
||||
_translateY += y - (h / 2f);
|
||||
}
|
||||
|
||||
/// <summary>SDK Top — adds y to the Y translation (via SetY).</summary>
|
||||
public void Top(float y) => SetY(y);
|
||||
|
||||
/// <summary>SDK Bottom — adds y - (height × scaleY) to the Y translation.</summary>
|
||||
public void Bottom(float y)
|
||||
{
|
||||
var h = _height * _scaleY;
|
||||
_translateY += y - h;
|
||||
}
|
||||
|
||||
/// <summary>SDK Left — adds x to the X translation (via SetX).</summary>
|
||||
public void Left(float x) => SetX(x);
|
||||
|
||||
/// <summary>SDK Right — adds x - (width × scaleX) to the X translation.</summary>
|
||||
public void Right(float x)
|
||||
{
|
||||
var w = _width * _scaleX;
|
||||
_translateX += x - w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Centers vertically: translateY = y - (height * scaleY) / 2.
|
||||
/// </summary>
|
||||
public void CenterY(float y) => _translateY = y - (_height * _scaleY) / 2f;
|
||||
|
||||
/// <summary>Aligns the top edge of the model to y.</summary>
|
||||
public void Top(float y) => _translateY = y;
|
||||
|
||||
/// <summary>Aligns the bottom edge of the model to y.</summary>
|
||||
public void Bottom(float y) => _translateY = y - _height * _scaleY;
|
||||
|
||||
/// <summary>Aligns the left edge of the model to x.</summary>
|
||||
public void Left(float x) => _translateX = x;
|
||||
|
||||
/// <summary>Aligns the right edge of the model to x.</summary>
|
||||
public void Right(float x) => _translateX = x - _width * _scaleX;
|
||||
|
||||
/// <summary>
|
||||
/// Configures scale and position from a layout dictionary.
|
||||
/// Supported keys: "width", "height", "x", "y", "center_x", "center_y",
|
||||
/// "top", "bottom", "left", "right".
|
||||
/// Width/height are applied first (since they affect scale),
|
||||
/// then position keys are applied.
|
||||
/// SDK SetupFromLayout — configures scale and position from a layout
|
||||
/// dictionary (lowercased keys). Width/height are applied first (they
|
||||
/// affect scale), then the position keys: "x", "y", "center_x",
|
||||
/// "center_y", "top", "bottom", "left", "right".
|
||||
/// </summary>
|
||||
public void SetupFromLayout(Dictionary<string, float> layout)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user