补回误删的 listQuietly(上一次改动把编译搞坏了,编辑器起不来);+10 Red Bones 暂用已验证可行的一根一次路径
This commit is contained in:
1 parent
4000a06d61
commit
0886ba647c
2 files changed
+107
-9
No files matched your search
@@ -901,4 +901,103 @@ public final class SceneActions {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// ==================== 直接模型 API:新建骨骼(不经 UI 菜单、不依赖下一帧) ====================
|
||||
//
|
||||
// 编辑器自己的"新建骨骼"代码就在 `Yi.run()` 里,去掉 UI 后本质是:
|
||||
// new Gp() → 设 name/parent/skeleton/x/y/color → 骨架.D(骨骼) ← GP 上的 (LGp;)V = addBone
|
||||
// → 骨架.StackMapTable() ← 重建索引 → Editor.D(骨骼, true) → VZ.D(骨架, true, true) 重建树
|
||||
// 一次调用可以连建 N 根,最后只刷新一次;外层包 un.D()/un.B() 就是"一次撤销"。
|
||||
|
||||
/** 直接建一根骨骼(返回新骨骼对象;失败返回 null)。 */
|
||||
public static Object createBone(ClassLoader loader, Object skeleton, Object parent, String name,
|
||||
float x, float y, Object color) {
|
||||
try {
|
||||
System.err.println("[crud] createBone step1 new Gp " + skeleton + " parent=" + parent);
|
||||
Class<?> boneClass = Class.forName("Gp", true, loader);
|
||||
Object bone = boneClass.getConstructor().newInstance();
|
||||
setByType(bone, "GP", skeleton);
|
||||
if (parent != null) setByType(bone, "Gp", parent);
|
||||
setByNameType(bone, "D", String.class, name);
|
||||
setByNameType(bone, "Z", float.class, Float.valueOf(x));
|
||||
setByNameType(bone, "V", float.class, Float.valueOf(y));
|
||||
if (color != null) setByNameType(bone, "B",
|
||||
Class.forName("com.badlogic.gdx.graphics.Color", true, loader), color);
|
||||
System.err.println("[crud] createBone step2 fields ok");
|
||||
|
||||
// 骨架.D(骨骼):GP 上的 (LGp;)V
|
||||
Method addBone = findMethod(skeleton.getClass(), "D", new Class<?>[] {boneClass}, void.class);
|
||||
if (addBone == null) throw new NoSuchMethodException("GP.D(LGp;)V addBone");
|
||||
addBone.setAccessible(true);
|
||||
System.err.println("[crud] createBone step3 " + addBone.getDeclaringClass().getName() + "."
|
||||
+ addBone.getName() + "(Gp) 调用中");
|
||||
addBone.invoke(skeleton, bone);
|
||||
System.err.println("[crud] createBone step3 ok");
|
||||
|
||||
// 骨架.StackMapTable():重建索引
|
||||
Method rebuild = null;
|
||||
for (Method m : skeleton.getClass().getMethods()) {
|
||||
if (m.getName().equals("StackMapTable") && m.getParameterTypes().length == 0
|
||||
&& m.getReturnType() == void.class) {
|
||||
rebuild = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rebuild != null) {
|
||||
rebuild.setAccessible(true);
|
||||
rebuild.invoke(skeleton);
|
||||
}
|
||||
|
||||
// Editor.D(骨骼, true):通知编辑器(找不到就跳过,不影响模型)
|
||||
try {
|
||||
Class<?> editorClass = Class.forName("com.esotericsoftware.spine.editor.Editor", true, loader);
|
||||
Method notify = findMethod(editorClass, "D", new Class<?>[] {boneClass, boolean.class},
|
||||
void.class);
|
||||
Object editor = SceneObjects.global(loader, "com.esotericsoftware.spine.editor.Editor");
|
||||
if (notify != null && editor != null) {
|
||||
notify.setAccessible(true);
|
||||
notify.invoke(editor, bone, Boolean.TRUE);
|
||||
}
|
||||
} catch (Throwable error) {
|
||||
System.err.println("[crud] Editor.D(bone,true) 跳过: " + error);
|
||||
}
|
||||
return bone;
|
||||
} catch (Throwable error) {
|
||||
System.err.println("[crud] createBone 失败: " + error);
|
||||
Throwable cause = error;
|
||||
while (cause != null) {
|
||||
System.err.println("[crud] cause: " + cause);
|
||||
cause.printStackTrace(System.err);
|
||||
cause = cause.getCause();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 按字段类型写(用于 D:LGP; / D:LGp; 这种同名不同描述符的坑)。 */
|
||||
static void setByType(Object target, String typeName, Object value) throws Exception {
|
||||
for (Class<?> type = target.getClass(); type != null && type != Object.class;
|
||||
type = type.getSuperclass()) {
|
||||
for (Field field : type.getDeclaredFields()) {
|
||||
if (!field.getType().getName().equals(typeName)) continue;
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 按"名字 + 类型"写字段。 */
|
||||
static void setByNameType(Object target, String name, Class<?> fieldType, Object value)
|
||||
throws Exception {
|
||||
for (Class<?> type = target.getClass(); type != null && type != Object.class;
|
||||
type = type.getSuperclass()) {
|
||||
for (Field field : type.getDeclaredFields()) {
|
||||
if (!field.getName().equals(name) || field.getType() != fieldType) continue;
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user