mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 17:26:01 +08:00
[unity] SpineVisualElement improvements. Now supports settings reference mesh bounds via a different bounds animation.
This commit is contained in:
parent
d769c1a930
commit
54e463048a
@ -149,10 +149,20 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
|
newPropertyPath = propertyPath.Remove(propertyPath.Length - localPathLength, localPathLength) + propertyName;
|
||||||
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
|
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
|
||||||
}
|
}
|
||||||
|
// If this fails as well, try at any base property up the hierarchy
|
||||||
|
if (relativeProperty == null) {
|
||||||
|
int dotIndex = propertyPath.Length - property.name.Length - 1;
|
||||||
|
while (relativeProperty == null) {
|
||||||
|
dotIndex = propertyPath.LastIndexOf('.', dotIndex - 1);
|
||||||
|
if (dotIndex < 0)
|
||||||
|
break;
|
||||||
|
newPropertyPath = propertyPath.Remove(dotIndex + 1) + propertyName;
|
||||||
|
relativeProperty = property.serializedObject.FindProperty(newPropertyPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return relativeProperty;
|
return relativeProperty;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "com.esotericsoftware.spine.spine-unity",
|
"name": "com.esotericsoftware.spine.spine-unity",
|
||||||
"displayName": "spine-unity Runtime",
|
"displayName": "spine-unity Runtime",
|
||||||
"description": "This plugin provides the spine-unity runtime core.",
|
"description": "This plugin provides the spine-unity runtime core.",
|
||||||
"version": "4.2.81",
|
"version": "4.2.82",
|
||||||
"unity": "2018.3",
|
"unity": "2018.3",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Esoteric Software",
|
"name": "Esoteric Software",
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 020c4dfc4cd28f8409ea82818e31d040
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated July 28, 2023. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2024, Esoteric Software LLC
|
||||||
|
*
|
||||||
|
* Integration of the Spine Runtimes into software or otherwise creating
|
||||||
|
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||||
|
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||||
|
* http://esotericsoftware.com/spine-editor-license
|
||||||
|
*
|
||||||
|
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
|
||||||
|
* otherwise create derivative works of the Spine Runtimes (collectively,
|
||||||
|
* "Products"), provided that each user of the Products must obtain their own
|
||||||
|
* Spine Editor license and redistribution of the Products in any form must
|
||||||
|
* include this license and copyright notice.
|
||||||
|
*
|
||||||
|
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||||
|
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
|
||||||
|
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
//#define CHANGE_BOUNDS_ON_ANIMATION_CHANGE
|
||||||
|
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace Spine.Unity.Editor {
|
||||||
|
|
||||||
|
[CustomPropertyDrawer(typeof(BoundsFromAnimationAttribute))]
|
||||||
|
public class BoundsFromAnimationAttributeDrawer : PropertyDrawer {
|
||||||
|
|
||||||
|
protected BoundsFromAnimationAttribute TargetAttribute { get { return (BoundsFromAnimationAttribute)attribute; } }
|
||||||
|
|
||||||
|
public override VisualElement CreatePropertyGUI (SerializedProperty boundsProperty) {
|
||||||
|
var container = new VisualElement();
|
||||||
|
PropertyField referenceMeshBounds = new PropertyField();
|
||||||
|
referenceMeshBounds.BindProperty(boundsProperty);
|
||||||
|
|
||||||
|
var parentPropertyPath = boundsProperty.propertyPath.Substring(0, boundsProperty.propertyPath.LastIndexOf('.'));
|
||||||
|
var parent = boundsProperty.serializedObject.FindProperty(parentPropertyPath);
|
||||||
|
SerializedProperty animationProperty = parent.FindPropertyRelative(TargetAttribute.animationField);
|
||||||
|
SerializedProperty skeletonDataProperty = parent.FindPropertyRelative(TargetAttribute.dataField);
|
||||||
|
SerializedProperty skinProperty = parent.FindPropertyRelative(TargetAttribute.skinField);
|
||||||
|
|
||||||
|
#if !CHANGE_BOUNDS_ON_ANIMATION_CHANGE
|
||||||
|
Button updateBoundsButton = new Button(() => {
|
||||||
|
UpdateMeshBounds(boundsProperty, animationProperty.stringValue,
|
||||||
|
(SkeletonDataAsset)skeletonDataProperty.objectReferenceValue, skinProperty.stringValue);
|
||||||
|
});
|
||||||
|
updateBoundsButton.text = "Update Bounds";
|
||||||
|
container.Add(updateBoundsButton);
|
||||||
|
#else
|
||||||
|
referenceMeshBounds.TrackPropertyValue(animationProperty, prop => {
|
||||||
|
UpdateMeshBounds(boundsProperty, animationProperty.stringValue,
|
||||||
|
(SkeletonDataAsset)skeletonDataProperty.objectReferenceValue, skinProperty.stringValue);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
container.Add(referenceMeshBounds);
|
||||||
|
|
||||||
|
container.Bind(boundsProperty.serializedObject);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateMeshBounds (SerializedProperty boundsProperty, string boundsAnimation,
|
||||||
|
SkeletonDataAsset skeletonDataAsset, string skin) {
|
||||||
|
if (!skeletonDataAsset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bounds bounds = CalculateMeshBounds(boundsAnimation, skeletonDataAsset, skin);
|
||||||
|
if (bounds.extents.x == 0 || bounds.extents.y == 0) {
|
||||||
|
Debug.LogWarning("Please select different Initial Skin and Bounds Animation. Not setting reference " +
|
||||||
|
"bounds as current combination (likely no attachments visible) leads to zero Mesh bounds.");
|
||||||
|
bounds.center = Vector3.zero;
|
||||||
|
bounds.extents = Vector3.one * 2f;
|
||||||
|
}
|
||||||
|
boundsProperty.boundsValue = bounds;
|
||||||
|
boundsProperty.serializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Bounds CalculateMeshBounds (string animationName, SkeletonDataAsset skeletonDataAsset, string skin) {
|
||||||
|
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
|
||||||
|
Skeleton skeleton = new Skeleton(skeletonData);
|
||||||
|
if (!string.IsNullOrEmpty(skin) && !string.Equals(skin, "default", System.StringComparison.Ordinal))
|
||||||
|
skeleton.SetSkin(skin);
|
||||||
|
skeleton.SetSlotsToSetupPose();
|
||||||
|
|
||||||
|
Spine.Animation animation = skeletonData.FindAnimation(animationName);
|
||||||
|
if (animation != null)
|
||||||
|
animation.Apply(skeleton, -1, 0, false, null, 1.0f, MixBlend.First, MixDirection.In);
|
||||||
|
|
||||||
|
skeleton.Update(0f);
|
||||||
|
skeleton.UpdateWorldTransform(Skeleton.Physics.Update);
|
||||||
|
|
||||||
|
float x, y, width, height;
|
||||||
|
SkeletonClipping clipper = new SkeletonClipping();
|
||||||
|
float[] vertexBuffer = null;
|
||||||
|
skeleton.GetBounds(out x, out y, out width, out height, ref vertexBuffer, clipper);
|
||||||
|
if (x == int.MaxValue) {
|
||||||
|
return new Bounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
Bounds bounds = new Bounds();
|
||||||
|
Vector2 halfSize = new Vector2(width * 0.5f, height * 0.5f);
|
||||||
|
bounds.center = new Vector3(x + halfSize.x, -y - halfSize.y, 0.0f);
|
||||||
|
bounds.extents = new Vector3(halfSize.x, halfSize.y, 0.0f);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eb5762c450311694e84304e790546805
|
||||||
@ -29,17 +29,42 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Profiling;
|
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
using UIVertex = UnityEngine.UIElements.Vertex;
|
using UIVertex = UnityEngine.UIElements.Vertex;
|
||||||
|
|
||||||
namespace Spine.Unity {
|
namespace Spine.Unity {
|
||||||
|
|
||||||
|
public class BoundsFromAnimationAttribute : PropertyAttribute {
|
||||||
|
|
||||||
|
public readonly string animationField;
|
||||||
|
public readonly string dataField;
|
||||||
|
public readonly string skinField;
|
||||||
|
|
||||||
|
public BoundsFromAnimationAttribute (string animationField, string skinField, string dataField = "skeletonDataAsset") {
|
||||||
|
this.animationField = animationField;
|
||||||
|
this.skinField = skinField;
|
||||||
|
this.dataField = dataField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[UxmlElement]
|
[UxmlElement]
|
||||||
public partial class SpineVisualElement : VisualElement {
|
public partial class SpineVisualElement : VisualElement {
|
||||||
|
|
||||||
|
[UxmlAttribute]
|
||||||
|
public SkeletonDataAsset SkeletonDataAsset {
|
||||||
|
get { return skeletonDataAsset; }
|
||||||
|
set {
|
||||||
|
if (skeletonDataAsset == value) return;
|
||||||
|
skeletonDataAsset = value;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
Initialize(true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public SkeletonDataAsset skeletonDataAsset;
|
||||||
|
|
||||||
[SpineAnimation(dataField: "SkeletonDataAsset", avoidGenericMenu: true)]
|
[SpineAnimation(dataField: "SkeletonDataAsset", avoidGenericMenu: true)]
|
||||||
[UxmlAttribute]
|
[UxmlAttribute]
|
||||||
public string StartingAnimation {
|
public string StartingAnimation {
|
||||||
@ -55,7 +80,7 @@ namespace Spine.Unity {
|
|||||||
}
|
}
|
||||||
public string startingAnimation = "";
|
public string startingAnimation = "";
|
||||||
|
|
||||||
[SpineSkin(dataField: "SkeletonDataAsset", avoidGenericMenu: true)]
|
[SpineSkin(dataField: "SkeletonDataAsset", defaultAsEmptyString: true, avoidGenericMenu: true)]
|
||||||
[UxmlAttribute]
|
[UxmlAttribute]
|
||||||
public string InitialSkinName {
|
public string InitialSkinName {
|
||||||
get { return initialSkinName; }
|
get { return initialSkinName; }
|
||||||
@ -73,19 +98,42 @@ namespace Spine.Unity {
|
|||||||
[UxmlAttribute] public bool startingLoop { get; set; } = true;
|
[UxmlAttribute] public bool startingLoop { get; set; } = true;
|
||||||
[UxmlAttribute] public float timeScale { get; set; } = 1.0f;
|
[UxmlAttribute] public float timeScale { get; set; } = 1.0f;
|
||||||
|
|
||||||
|
[SpineAnimation(dataField: "SkeletonDataAsset", avoidGenericMenu: true)]
|
||||||
[UxmlAttribute]
|
[UxmlAttribute]
|
||||||
public SkeletonDataAsset SkeletonDataAsset {
|
public string BoundsAnimation {
|
||||||
get { return skeletonDataAsset; }
|
get { return boundsAnimation; }
|
||||||
set {
|
set {
|
||||||
if (skeletonDataAsset == value) return;
|
boundsAnimation = value;
|
||||||
skeletonDataAsset = value;
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (!Application.isPlaying)
|
if (!Application.isPlaying) {
|
||||||
|
if (!this.IsValid)
|
||||||
Initialize(true);
|
Initialize(true);
|
||||||
|
else {
|
||||||
|
UpdateAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public SkeletonDataAsset skeletonDataAsset;
|
public string boundsAnimation = "";
|
||||||
|
|
||||||
|
[UxmlAttribute]
|
||||||
|
[BoundsFromAnimation(animationField: "BoundsAnimation",
|
||||||
|
skinField: "InitialSkinName", dataField: "SkeletonDataAsset")]
|
||||||
|
public Bounds ReferenceBounds {
|
||||||
|
get { return referenceMeshBounds; }
|
||||||
|
set {
|
||||||
|
if (referenceMeshBounds == value) return;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!Application.isPlaying && (value.size.x == 0 || value.size.y == 0)) return;
|
||||||
|
#endif
|
||||||
|
referenceMeshBounds = value;
|
||||||
|
if (!this.IsValid) return;
|
||||||
|
|
||||||
|
AdjustOffsetScaleToMeshBounds(rendererElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Bounds referenceMeshBounds;
|
||||||
|
|
||||||
public AnimationState AnimationState {
|
public AnimationState AnimationState {
|
||||||
get {
|
get {
|
||||||
@ -93,21 +141,22 @@ namespace Spine.Unity {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[UxmlAttribute]
|
||||||
public bool freeze { get; set; }
|
public bool freeze { get; set; }
|
||||||
|
[UxmlAttribute]
|
||||||
public bool unscaledTime { get; set; }
|
public bool unscaledTime { get; set; }
|
||||||
|
|
||||||
/// <summary>Update mode to optionally limit updates to e.g. only apply animations but not update the mesh.</summary>
|
/// <summary>Update mode to optionally limit updates to e.g. only apply animations but not update the mesh.</summary>
|
||||||
public UpdateMode UpdateMode { get { return updateMode; } set { updateMode = value; } }
|
public UpdateMode UpdateMode { get { return updateMode; } set { updateMode = value; } }
|
||||||
protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
||||||
|
|
||||||
protected AnimationState state;
|
protected AnimationState state = null;
|
||||||
protected Skeleton skeleton;
|
protected Skeleton skeleton = null;
|
||||||
protected SkeletonRendererInstruction currentInstructions = new();// to match existing code better
|
protected SkeletonRendererInstruction currentInstructions = new();// to match existing code better
|
||||||
protected Spine.Unity.MeshGeneratorUIElements meshGenerator = new MeshGeneratorUIElements();
|
protected Spine.Unity.MeshGeneratorUIElements meshGenerator = new MeshGeneratorUIElements();
|
||||||
|
|
||||||
protected VisualElement rendererElement;
|
protected VisualElement rendererElement;
|
||||||
IVisualElementScheduledItem scheduledItem;
|
IVisualElementScheduledItem scheduledItem;
|
||||||
protected Bounds referenceMeshBounds;
|
|
||||||
protected float scale = 100;
|
protected float scale = 100;
|
||||||
protected float offsetX, offsetY;
|
protected float offsetX, offsetY;
|
||||||
|
|
||||||
@ -131,6 +180,10 @@ namespace Spine.Unity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnGeometryChanged (GeometryChangedEvent evt) {
|
void OnGeometryChanged (GeometryChangedEvent evt) {
|
||||||
|
if (!this.IsValid) return;
|
||||||
|
if (referenceMeshBounds.size.x == 0 || referenceMeshBounds.size.y == 0) {
|
||||||
|
AdjustReferenceMeshBounds();
|
||||||
|
}
|
||||||
AdjustOffsetScaleToMeshBounds(rendererElement);
|
AdjustOffsetScaleToMeshBounds(rendererElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +207,6 @@ namespace Spine.Unity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (freeze) return;
|
if (freeze) return;
|
||||||
Update(unscaledTime ? Time.unscaledDeltaTime : Time.deltaTime);
|
Update(unscaledTime ? Time.unscaledDeltaTime : Time.deltaTime);
|
||||||
rendererElement.MarkDirtyRepaint();
|
rendererElement.MarkDirtyRepaint();
|
||||||
@ -212,17 +264,44 @@ namespace Spine.Unity {
|
|||||||
if (!string.IsNullOrEmpty(initialSkinName))
|
if (!string.IsNullOrEmpty(initialSkinName))
|
||||||
skeleton.SetSkin(initialSkinName);
|
skeleton.SetSkin(initialSkinName);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(startingAnimation)) {
|
string displayedAnimation = Application.isPlaying ? startingAnimation : boundsAnimation;
|
||||||
var animationObject = SkeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation);
|
if (!string.IsNullOrEmpty(displayedAnimation)) {
|
||||||
|
var animationObject = skeletonData.FindAnimation(displayedAnimation);
|
||||||
if (animationObject != null) {
|
if (animationObject != null) {
|
||||||
state.SetAnimation(0, animationObject, startingLoop);
|
state.SetAnimation(0, animationObject, startingLoop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (referenceMeshBounds.size.x == 0 || referenceMeshBounds.size.y == 0) {
|
||||||
AdjustReferenceMeshBounds();
|
AdjustReferenceMeshBounds();
|
||||||
|
AdjustOffsetScaleToMeshBounds(rendererElement);
|
||||||
|
}
|
||||||
|
|
||||||
if (scheduledItem == null)
|
if (scheduledItem == null)
|
||||||
scheduledItem = schedule.Execute(Update).Every(1);
|
scheduledItem = schedule.Execute(Update).Every(1);
|
||||||
|
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
Update(0.0f);
|
||||||
|
|
||||||
|
rendererElement.MarkDirtyRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateAnimation () {
|
||||||
|
this.state.ClearTracks();
|
||||||
|
skeleton.SetToSetupPose();
|
||||||
|
|
||||||
|
string displayedAnimation = Application.isPlaying ? startingAnimation : boundsAnimation;
|
||||||
|
if (!string.IsNullOrEmpty(displayedAnimation)) {
|
||||||
|
var animationObject = SkeletonDataAsset.GetSkeletonData(false).FindAnimation(displayedAnimation);
|
||||||
|
if (animationObject != null) {
|
||||||
|
state.SetAnimation(0, animationObject, startingLoop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (referenceMeshBounds.size.x == 0 || referenceMeshBounds.size.y == 0) {
|
||||||
|
AdjustReferenceMeshBounds();
|
||||||
|
AdjustOffsetScaleToMeshBounds(rendererElement);
|
||||||
|
}
|
||||||
|
Update(0.0f);
|
||||||
|
|
||||||
rendererElement.MarkDirtyRepaint();
|
rendererElement.MarkDirtyRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +399,8 @@ namespace Spine.Unity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void AdjustReferenceMeshBounds () {
|
public void AdjustReferenceMeshBounds () {
|
||||||
|
if (skeleton == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Need one update to obtain valid mesh bounds
|
// Need one update to obtain valid mesh bounds
|
||||||
Update(0.0f);
|
Update(0.0f);
|
||||||
@ -332,12 +413,18 @@ namespace Spine.Unity {
|
|||||||
var submeshInstructionItem = currentInstructions.submeshInstructions.Items[i];
|
var submeshInstructionItem = currentInstructions.submeshInstructions.Items[i];
|
||||||
meshGenerator.AddSubmesh(submeshInstructionItem);
|
meshGenerator.AddSubmesh(submeshInstructionItem);
|
||||||
}
|
}
|
||||||
|
Bounds meshBounds = meshGenerator.GetMeshBounds();
|
||||||
referenceMeshBounds = meshGenerator.GetMeshBounds();
|
if (meshBounds.extents.x == 0 || meshBounds.extents.y == 0) {
|
||||||
|
ReferenceBounds = new Bounds(Vector3.zero, Vector3.one * 2f);
|
||||||
|
} else {
|
||||||
|
ReferenceBounds = meshBounds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustOffsetScaleToMeshBounds (VisualElement visualElement) {
|
void AdjustOffsetScaleToMeshBounds (VisualElement visualElement) {
|
||||||
Rect targetRect = visualElement.layout;
|
Rect targetRect = visualElement.layout;
|
||||||
|
if (float.IsNaN(targetRect.width)) return;
|
||||||
|
|
||||||
float xScale = targetRect.width / referenceMeshBounds.size.x;
|
float xScale = targetRect.width / referenceMeshBounds.size.x;
|
||||||
float yScale = targetRect.height / referenceMeshBounds.size.y;
|
float yScale = targetRect.height / referenceMeshBounds.size.y;
|
||||||
this.scale = Math.Min(xScale, yScale);
|
this.scale = Math.Min(xScale, yScale);
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "com.esotericsoftware.spine.ui-toolkit",
|
"name": "com.esotericsoftware.spine.ui-toolkit",
|
||||||
"displayName": "Spine UI Toolkit [Experimental]",
|
"displayName": "Spine UI Toolkit [Experimental]",
|
||||||
"description": "This plugin provides UI Toolkit integration for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.2.75 or newer.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
|
"description": "This plugin provides UI Toolkit integration for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.2.82 or newer and Unity 6000.0.16 or newer (requires [this bugfix](https://issuetracker.unity3d.com/issues/some-default-uxmlconverters-are-dependent-on-the-current-culture)).\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
|
||||||
"version": "4.2.0-preview.1",
|
"version": "4.2.0-preview.2",
|
||||||
"unity": "2023.2",
|
"unity": "6000.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Esoteric Software",
|
"name": "Esoteric Software",
|
||||||
"email": "contact@esotericsoftware.com",
|
"email": "contact@esotericsoftware.com",
|
||||||
@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.modules.uielements": "1.0.0",
|
"com.unity.modules.uielements": "1.0.0",
|
||||||
"com.esotericsoftware.spine.spine-unity": "4.2.75"
|
"com.esotericsoftware.spine.spine-unity": "4.2.82"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"spine",
|
"spine",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user