mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-05 06:44:56 +08:00
[libgdx] Added mapping a bone property to a slider.
This commit is contained in:
parent
6da9ac59b7
commit
bbc6c2e37e
@ -303,42 +303,40 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
FromProperty[] froms = data.properties.setSize(nn = flags >> 5);
|
||||
for (int ii = 0, tn; ii < nn; ii++) {
|
||||
float fromScale = 1;
|
||||
FromProperty from;
|
||||
switch (input.readByte()) {
|
||||
case 0 -> from = new FromRotate();
|
||||
FromProperty from = switch (input.readByte()) {
|
||||
case 0 -> new FromRotate();
|
||||
case 1 -> {
|
||||
from = new FromX();
|
||||
fromScale = scale;
|
||||
yield new FromX();
|
||||
}
|
||||
case 2 -> {
|
||||
from = new FromY();
|
||||
fromScale = scale;
|
||||
yield new FromY();
|
||||
}
|
||||
case 3 -> from = new FromScaleX();
|
||||
case 4 -> from = new FromScaleY();
|
||||
case 5 -> from = new FromShearY();
|
||||
default -> from = null;
|
||||
}
|
||||
case 3 -> new FromScaleX();
|
||||
case 4 -> new FromScaleY();
|
||||
case 5 -> new FromShearY();
|
||||
default -> null;
|
||||
};
|
||||
from.offset = input.readFloat() * fromScale;
|
||||
ToProperty[] tos = from.to.setSize(tn = input.readByte());
|
||||
for (int t = 0; t < tn; t++) {
|
||||
float toScale = 1;
|
||||
ToProperty to;
|
||||
switch (input.readByte()) {
|
||||
case 0 -> to = new ToRotate();
|
||||
ToProperty to = switch (input.readByte()) {
|
||||
case 0 -> new ToRotate();
|
||||
case 1 -> {
|
||||
to = new ToX();
|
||||
toScale = scale;
|
||||
yield new ToX();
|
||||
}
|
||||
case 2 -> {
|
||||
to = new ToY();
|
||||
toScale = scale;
|
||||
yield new ToY();
|
||||
}
|
||||
case 3 -> to = new ToScaleX();
|
||||
case 4 -> to = new ToScaleY();
|
||||
case 5 -> to = new ToShearY();
|
||||
default -> to = null;
|
||||
}
|
||||
case 3 -> new ToScaleX();
|
||||
case 4 -> new ToScaleY();
|
||||
case 5 -> new ToShearY();
|
||||
default -> null;
|
||||
};
|
||||
to.offset = input.readFloat() * toScale;
|
||||
to.max = input.readFloat() * toScale;
|
||||
to.scale = input.readFloat() * toScale / fromScale;
|
||||
@ -347,12 +345,12 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
froms[ii] = from;
|
||||
}
|
||||
flags = input.read();
|
||||
if ((flags & 1) != 0) data.offsetRotation = input.readFloat();
|
||||
if ((flags & 2) != 0) data.offsetX = input.readFloat() * scale;
|
||||
if ((flags & 4) != 0) data.offsetY = input.readFloat() * scale;
|
||||
if ((flags & 8) != 0) data.offsetScaleX = input.readFloat();
|
||||
if ((flags & 16) != 0) data.offsetScaleY = input.readFloat();
|
||||
if ((flags & 32) != 0) data.offsetShearY = input.readFloat();
|
||||
if ((flags & 1) != 0) data.offsets[0] = input.readFloat();
|
||||
if ((flags & 2) != 0) data.offsets[1] = input.readFloat() * scale;
|
||||
if ((flags & 4) != 0) data.offsets[2] = input.readFloat() * scale;
|
||||
if ((flags & 8) != 0) data.offsets[3] = input.readFloat();
|
||||
if ((flags & 16) != 0) data.offsets[4] = input.readFloat();
|
||||
if ((flags & 32) != 0) data.offsets[5] = input.readFloat();
|
||||
flags = input.read();
|
||||
TransformConstraintPose setup = data.setup;
|
||||
if ((flags & 1) != 0) setup.mixRotate = input.readFloat();
|
||||
@ -422,6 +420,28 @@ public class SkeletonBinary extends SkeletonLoader {
|
||||
data.additive = (nn & 4) != 0;
|
||||
if ((nn & 8) != 0) data.setup.time = input.readFloat();
|
||||
if ((nn & 16) != 0) data.setup.mix = (nn & 32) != 0 ? input.readFloat() : 1;
|
||||
if ((nn & 64) != 0) {
|
||||
data.local = (nn & 128) != 0;
|
||||
data.bone = bones[input.readInt(true)];
|
||||
float offset = input.readFloat();
|
||||
data.property = switch (input.readByte()) {
|
||||
case 0 -> new FromRotate();
|
||||
case 1 -> {
|
||||
offset *= scale;
|
||||
yield new FromX();
|
||||
}
|
||||
case 2 -> {
|
||||
offset *= scale;
|
||||
yield new FromY();
|
||||
}
|
||||
case 3 -> new FromScaleX();
|
||||
case 4 -> new FromScaleY();
|
||||
case 5 -> new FromShearY();
|
||||
default -> null;
|
||||
};
|
||||
data.property.offset = offset;
|
||||
data.scale = input.readFloat();
|
||||
}
|
||||
constraints[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,23 +268,8 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
|
||||
boolean rotate = false, x = false, y = false, scaleX = false, scaleY = false, shearY = false;
|
||||
for (JsonValue fromEntry = constraintMap.getChild("properties"); fromEntry != null; fromEntry = fromEntry.next) {
|
||||
float fromScale = 1;
|
||||
FromProperty from;
|
||||
switch (fromEntry.name) {
|
||||
case "rotate" -> from = new FromRotate();
|
||||
case "x" -> {
|
||||
from = new FromX();
|
||||
fromScale = scale;
|
||||
}
|
||||
case "y" -> {
|
||||
from = new FromY();
|
||||
fromScale = scale;
|
||||
}
|
||||
case "scaleX" -> from = new FromScaleX();
|
||||
case "scaleY" -> from = new FromScaleY();
|
||||
case "shearY" -> from = new FromShearY();
|
||||
default -> throw new SerializationException("Invalid transform constraint from property: " + fromEntry.name);
|
||||
}
|
||||
FromProperty from = fromProperty(fromEntry.name);
|
||||
float fromScale = propertyScale(fromEntry.name, scale);
|
||||
from.offset = fromEntry.getFloat("offset", 0) * fromScale;
|
||||
for (JsonValue toEntry = fromEntry.getChild("to"); toEntry != null; toEntry = toEntry.next) {
|
||||
float toScale = 1;
|
||||
@ -326,12 +311,12 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
if (from.to.notEmpty()) data.properties.add(from);
|
||||
}
|
||||
|
||||
data.offsetRotation = constraintMap.getFloat("rotation", 0);
|
||||
data.offsetX = constraintMap.getFloat("x", 0) * scale;
|
||||
data.offsetY = constraintMap.getFloat("y", 0) * scale;
|
||||
data.offsetScaleX = constraintMap.getFloat("scaleX", 0);
|
||||
data.offsetScaleY = constraintMap.getFloat("scaleY", 0);
|
||||
data.offsetShearY = constraintMap.getFloat("shearY", 0);
|
||||
data.offsets[0] = constraintMap.getFloat("rotation", 0);
|
||||
data.offsets[1] = constraintMap.getFloat("x", 0) * scale;
|
||||
data.offsets[2] = constraintMap.getFloat("y", 0) * scale;
|
||||
data.offsets[3] = constraintMap.getFloat("scaleX", 0);
|
||||
data.offsets[4] = constraintMap.getFloat("scaleY", 0);
|
||||
data.offsets[5] = constraintMap.getFloat("shearY", 0);
|
||||
|
||||
TransformConstraintPose setup = data.setup;
|
||||
if (rotate) setup.mixRotate = constraintMap.getFloat("mixRotate", 1);
|
||||
@ -408,10 +393,22 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
case "slider" -> {
|
||||
var data = new SliderData(name);
|
||||
data.skinRequired = skinRequired;
|
||||
data.loop = constraintMap.getBoolean("loop", false);
|
||||
data.additive = constraintMap.getBoolean("additive", false);
|
||||
data.loop = constraintMap.getBoolean("loop", false);
|
||||
data.setup.time = constraintMap.getFloat("time", 0);
|
||||
data.setup.mix = constraintMap.getFloat("mix", 1);
|
||||
|
||||
String boneName = constraintMap.getString("bone", null);
|
||||
if (boneName != null) {
|
||||
data.bone = skeletonData.findBone(boneName);
|
||||
if (data.bone == null) throw new SerializationException("Slider bone not found: " + boneName);
|
||||
String property = constraintMap.getString("property");
|
||||
data.property = fromProperty(property);
|
||||
data.property.offset = constraintMap.getFloat("offset", 0) * propertyScale(property, scale);
|
||||
data.scale = constraintMap.getFloat("scale");
|
||||
data.local = constraintMap.getBoolean("local", false);
|
||||
}
|
||||
|
||||
skeletonData.constraints.add(data);
|
||||
}
|
||||
}
|
||||
@ -523,6 +520,25 @@ public class SkeletonJson extends SkeletonLoader {
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
private FromProperty fromProperty (String type) {
|
||||
return switch (type) {
|
||||
case "rotate" -> new FromRotate();
|
||||
case "x" -> new FromX();
|
||||
case "y" -> new FromY();
|
||||
case "scaleX" -> new FromScaleX();
|
||||
case "scaleY" -> new FromScaleY();
|
||||
case "shearY" -> new FromShearY();
|
||||
default -> throw new SerializationException("Invalid from property: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
private float propertyScale (String type, float scale) {
|
||||
return switch (type) {
|
||||
case "x", "y" -> scale;
|
||||
default -> 1;
|
||||
};
|
||||
}
|
||||
|
||||
private Attachment readAttachment (JsonValue map, Skin skin, int slotIndex, String name, SkeletonData skeletonData) {
|
||||
float scale = this.scale;
|
||||
name = map.getString("name", name);
|
||||
|
||||
@ -41,12 +41,19 @@ import com.esotericsoftware.spine.Animation.Timeline;
|
||||
* <p>
|
||||
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
||||
public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
public Slider (SliderData data) {
|
||||
static private final float[] offsets = new float[6];
|
||||
|
||||
Bone bone;
|
||||
|
||||
public Slider (SliderData data, Skeleton skeleton) {
|
||||
super(data, new SliderPose(), new SliderPose());
|
||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||
|
||||
if (data.bone != null) bone = skeleton.bones.items[data.bone.index];
|
||||
}
|
||||
|
||||
public Slider copy (Skeleton skeleton) {
|
||||
var copy = new Slider(data);
|
||||
var copy = new Slider(data, skeleton);
|
||||
copy.pose.set(pose);
|
||||
return copy;
|
||||
}
|
||||
@ -54,9 +61,18 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
public void update (Skeleton skeleton, Physics physics) {
|
||||
if (pose.mix == 0) return;
|
||||
|
||||
Animation animation = data.animation;
|
||||
if (bone != null && bone.active) {
|
||||
pose.time = (data.property.value(bone.applied, data.local, offsets) - data.property.offset) * data.scale;
|
||||
if (data.loop)
|
||||
pose.time = animation.duration + (pose.time % animation.duration);
|
||||
else
|
||||
pose.time = Math.max(0, pose.time);
|
||||
}
|
||||
|
||||
SliderData data = this.data;
|
||||
Timeline[] timelines = data.animation.timelines.items;
|
||||
int timelineCount = data.animation.timelines.size;
|
||||
Timeline[] timelines = animation.timelines.items;
|
||||
int timelineCount = animation.timelines.size;
|
||||
Bone[] bones = skeleton.bones.items;
|
||||
if (pose.mix == 1) {
|
||||
for (int i = 0; i < timelineCount; i++)
|
||||
@ -72,8 +88,8 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
}
|
||||
|
||||
SliderPose pose = applied;
|
||||
data.animation.apply(skeleton, pose.time, pose.time, data.loop, null, pose.mix,
|
||||
data.additive ? MixBlend.add : MixBlend.replace, MixDirection.in, true);
|
||||
animation.apply(skeleton, pose.time, pose.time, data.loop, null, pose.mix, data.additive ? MixBlend.add : MixBlend.replace,
|
||||
MixDirection.in, true);
|
||||
}
|
||||
|
||||
void sort (Skeleton skeleton) {
|
||||
@ -108,4 +124,12 @@ public class Slider extends Constraint<Slider, SliderData, SliderPose> {
|
||||
skeleton.resetCache(constraints[timeline.getConstraintIndex()]);
|
||||
}
|
||||
}
|
||||
|
||||
public Bone getBone () {
|
||||
return bone;
|
||||
}
|
||||
|
||||
public void setBone (Bone bone) {
|
||||
this.bone = bone;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,19 +29,27 @@
|
||||
|
||||
package com.esotericsoftware.spine;
|
||||
|
||||
import com.badlogic.gdx.utils.Null;
|
||||
|
||||
import com.esotericsoftware.spine.TransformConstraintData.FromProperty;
|
||||
|
||||
/** Stores the setup pose for a {@link PhysicsConstraint}.
|
||||
* <p>
|
||||
* See <a href="https://esotericsoftware.com/spine-physics-constraints">Physics constraints</a> in the Spine User Guide. */
|
||||
public class SliderData extends ConstraintData<Slider, SliderPose> {
|
||||
Animation animation;
|
||||
boolean additive, loop;
|
||||
@Null BoneData bone;
|
||||
@Null FromProperty property;
|
||||
float scale;
|
||||
boolean local;
|
||||
|
||||
public SliderData (String name) {
|
||||
super(name, new SliderPose());
|
||||
}
|
||||
|
||||
public Slider create (Skeleton skeleton) {
|
||||
return new Slider(this);
|
||||
return new Slider(this, skeleton);
|
||||
}
|
||||
|
||||
public Animation getAnimation () {
|
||||
@ -67,4 +75,36 @@ public class SliderData extends ConstraintData<Slider, SliderPose> {
|
||||
public void setLoop (boolean loop) {
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
public @Null BoneData getBone () {
|
||||
return bone;
|
||||
}
|
||||
|
||||
public void setBone (@Null BoneData bone) {
|
||||
this.bone = bone;
|
||||
}
|
||||
|
||||
public @Null FromProperty getProperty () {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty (@Null FromProperty property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public float getScale () {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public void setScale (float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
public boolean getLocal () {
|
||||
return local;
|
||||
}
|
||||
|
||||
public void setLocal (boolean local) {
|
||||
this.local = local;
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +69,7 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
|
||||
TransformConstraintData data = this.data;
|
||||
boolean localSource = data.localSource, localTarget = data.localTarget, additive = data.additive, clamp = data.clamp;
|
||||
float[] offsets = data.offsets;
|
||||
BonePose source = this.source.applied;
|
||||
int update = skeleton.update;
|
||||
if (localSource && source.local == skeleton.update) source.updateLocalTransform(skeleton);
|
||||
@ -80,7 +81,7 @@ public class TransformConstraint extends Constraint<TransformConstraint, Transfo
|
||||
if (localTarget && bone.local == update) bone.updateLocalTransform(skeleton);
|
||||
for (int f = 0; f < fn; f++) {
|
||||
FromProperty from = fromItems[f];
|
||||
float value = from.value(data, source, localSource) - from.offset;
|
||||
float value = from.value(source, localSource, offsets) - from.offset;
|
||||
ToProperty[] toItems = from.to.items;
|
||||
for (int t = 0, tn = from.to.size; t < tn; t++) {
|
||||
ToProperty to = toItems[t];
|
||||
|
||||
@ -39,7 +39,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
public class TransformConstraintData extends ConstraintData<TransformConstraint, TransformConstraintPose> {
|
||||
final Array<BoneData> bones = new Array(true, 0, BoneData[]::new);
|
||||
BoneData source;
|
||||
float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
|
||||
float[] offsets = new float[6];
|
||||
boolean localSource, localTarget, additive, clamp;
|
||||
final Array<FromProperty> properties = new Array(true, 1, FromProperty[]::new);
|
||||
|
||||
@ -68,56 +68,56 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
|
||||
/** An offset added to the constrained bone rotation. */
|
||||
public float getOffsetRotation () {
|
||||
return offsetRotation;
|
||||
return offsets[0];
|
||||
}
|
||||
|
||||
public void setOffsetRotation (float offsetRotation) {
|
||||
this.offsetRotation = offsetRotation;
|
||||
offsets[0] = offsetRotation;
|
||||
}
|
||||
|
||||
/** An offset added to the constrained bone X translation. */
|
||||
public float getOffsetX () {
|
||||
return offsetX;
|
||||
return offsets[1];
|
||||
}
|
||||
|
||||
public void setOffsetX (float offsetX) {
|
||||
this.offsetX = offsetX;
|
||||
offsets[1] = offsetX;
|
||||
}
|
||||
|
||||
/** An offset added to the constrained bone Y translation. */
|
||||
public float getOffsetY () {
|
||||
return offsetY;
|
||||
return offsets[2];
|
||||
}
|
||||
|
||||
public void setOffsetY (float offsetY) {
|
||||
this.offsetY = offsetY;
|
||||
offsets[2] = offsetY;
|
||||
}
|
||||
|
||||
/** An offset added to the constrained bone scaleX. */
|
||||
public float getOffsetScaleX () {
|
||||
return offsetScaleX;
|
||||
return offsets[3];
|
||||
}
|
||||
|
||||
public void setOffsetScaleX (float offsetScaleX) {
|
||||
this.offsetScaleX = offsetScaleX;
|
||||
offsets[3] = offsetScaleX;
|
||||
}
|
||||
|
||||
/** An offset added to the constrained bone scaleY. */
|
||||
public float getOffsetScaleY () {
|
||||
return offsetScaleY;
|
||||
return offsets[4];
|
||||
}
|
||||
|
||||
public void setOffsetScaleY (float offsetScaleY) {
|
||||
this.offsetScaleY = offsetScaleY;
|
||||
offsets[4] = offsetScaleY;
|
||||
}
|
||||
|
||||
/** An offset added to the constrained bone shearY. */
|
||||
public float getOffsetShearY () {
|
||||
return offsetShearY;
|
||||
return offsets[5];
|
||||
}
|
||||
|
||||
public void setOffsetShearY (float offsetShearY) {
|
||||
this.offsetShearY = offsetShearY;
|
||||
offsets[5] = offsetShearY;
|
||||
}
|
||||
|
||||
/** Reads the source bone's local transform instead of its world transform. */
|
||||
@ -170,7 +170,7 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
public final Array<ToProperty> to = new Array(true, 1, ToProperty[]::new);
|
||||
|
||||
/** Reads this property from the specified bone. */
|
||||
abstract public float value (TransformConstraintData data, BonePose source, boolean local);
|
||||
abstract public float value (BonePose source, boolean local, float[] offsets);
|
||||
}
|
||||
|
||||
/** Constrained property for a {@link TransformConstraint}. */
|
||||
@ -192,10 +192,10 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromRotate extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
if (local) return source.rotation + data.offsetRotation;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
if (local) return source.rotation + offsets[0];
|
||||
float value = atan2(source.c, source.a) * radDeg
|
||||
+ (source.a * source.d - source.b * source.c > 0 ? data.offsetRotation : -data.offsetRotation);
|
||||
+ (source.a * source.d - source.b * source.c > 0 ? offsets[0] : -offsets[0]);
|
||||
if (value < 0) value += 360;
|
||||
return value;
|
||||
}
|
||||
@ -229,8 +229,8 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromX extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
return local ? source.x + data.offsetX : data.offsetX * source.a + data.offsetY * source.b + source.worldX;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
return local ? source.x + offsets[1] : offsets[1] * source.a + offsets[2] * source.b + source.worldX;
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,8 +251,8 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromY extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
return local ? source.y + data.offsetY : data.offsetX * source.c + data.offsetY * source.d + source.worldY;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
return local ? source.y + offsets[2] : offsets[1] * source.c + offsets[2] * source.d + source.worldY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,8 +273,8 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromScaleX extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
return (local ? source.scaleX : (float)Math.sqrt(source.a * source.a + source.c * source.c)) + data.offsetScaleX;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
return (local ? source.scaleX : (float)Math.sqrt(source.a * source.a + source.c * source.c)) + offsets[3];
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,8 +304,8 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromScaleY extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
return (local ? source.scaleY : (float)Math.sqrt(source.b * source.b + source.d * source.d)) + data.offsetScaleY;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
return (local ? source.scaleY : (float)Math.sqrt(source.b * source.b + source.d * source.d)) + offsets[4];
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,9 +335,8 @@ public class TransformConstraintData extends ConstraintData<TransformConstraint,
|
||||
}
|
||||
|
||||
static public class FromShearY extends FromProperty {
|
||||
public float value (TransformConstraintData data, BonePose source, boolean local) {
|
||||
return (local ? source.shearY : (atan2(source.d, source.b) - atan2(source.c, source.a)) * radDeg - 90)
|
||||
+ data.offsetShearY;
|
||||
public float value (BonePose source, boolean local, float[] offsets) {
|
||||
return (local ? source.shearY : (atan2(source.d, source.b) - atan2(source.c, source.a)) * radDeg - 90) + offsets[5];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user