面板增删改查 + Inspector + 可识别源码版(src-named)

面板(viewpanel/src/com/spineview/)
- ObjectPanel:Refresh / New Bone / New Slot / New BBox / New Path / Delete / Rename / Inspect + 名字输入框 + 对象列表(点行=选中)+ 状态行,全英文。
- SceneObjects:查(Tree 控件按层级/扁平列全部对象)、选中(VZ.D(Tree.Node,boolean) —— VZ.D(Object) 内部只是 Selection.L(),不真选中)、读当前选择(VZ.B())。
- SceneActions:增/删/改 + 撤销包装(un.D()/un.B())+ 树节点重建(VZ.D(GP,true,true));
  统一在编辑器渲染线程执行(OG.B(Runnable);OG.I() 有线程断言,非渲染线程会抛 RuntimeException);
  输入名字对话框自动化:找到『有 TextField 字段 + L(Object)V 回调』的对话框对象 → 填名字 → 调 L(true)。
- 实测:骨骼新建自动编号(bone7/bone8);模型层允许重名、按名字查只返回第一个;删父骨骼连子节点一起删;
  不能在渲染线程里 sleep(有些创建是下一帧做的)。
- 探针:-Dspine.probe=objects|panels|select|crud|matrix|panel。

可识别源码版(工具)
- tools/deobf/Renamer.java:ASM Remapper 只改成员名不改类名(indy 运行时要用加密串里的类名反射查)。
- tools/deobf/anchors.tsv(手动 14 条有证据的锚点)+ anchors-libgdx.tsv(MapMethods 对 gdx-1.11.0 指纹自动生成 178 条)→ names.tsv 192 条。
- 产物 ~/Desktop/spine398/src-named(4176 类全量,原 src-readable 不动);已验证 Table.add/clearChildren、SelectBox.getSelected/setSelected/setSelectedIndex、Gp.name。
- 文档:混淆名对照表.md 新增第六节(工具链 + 已验证 + 已知限制)。
This commit is contained in:
tianmo committed 2026-10-16 15:25:02 +08:00
1 parent 7fbb042aa6
commit d9ea449b64
10 files changed
+2225 -43

No files matched your search

+2 -39
View File
@@ -197,45 +197,8 @@ public final class ViewInstaller {
* 少判一个条件就会调到别的方法上。名字出处见 {@link Obf}。
*/
private static Object buildPanel(ClassLoader loader, Object skin) throws Exception {
Class<?> skinClass = Class.forName(SKIN, true, loader);
Class<?> tableClass = Class.forName(Obf.TABLE, true, loader);
Class<?> cellClass = Class.forName(Obf.CELL, true, loader);
Class<?> actorClass = Class.forName(Obf.ACTOR, true, loader);
Class<?> buttonClass = Class.forName(TEXT_BUTTON, true, loader);
Class<?> labelClass = Class.forName(LABEL, true, loader);
Object table = tableClass.getConstructor().newInstance();
Object button = buttonClass.getConstructor(String.class, skinClass)
.newInstance("Read Scene Objects", skin);
Object label = labelClass.getConstructor(CharSequence.class, skinClass)
.newInstance("Click the button to list scene objects.", skin);
// 读出来的东西会很长,包进 ScrollPane 才能滚动查看。
Object scrollBody = label;
try {
Class<?> scrollClass = Class.forName(SCROLL_PANE, true, loader);
scrollBody = scrollClass.getConstructor(actorClass, skinClass).newInstance(label, skin);
System.err.println("[view] 文字区已包进 ScrollPane");
} catch (Throwable error) {
System.err.println("[view] ScrollPane 建不出来,直接用 Label: " + error);
}
// 让面板铺满停靠框(WidgetGroup.setFillParent)。
// 注意别调成 setDebug(boolean) —— 名字都是单字母,调错只会给单元格描上彩色边框。
call(table, Obf.TABLE_SET_FILL_PARENT, new Class<?>[] {boolean.class}, void.class,
Boolean.TRUE);
// 第一行:按钮,靠左。
Object buttonCell = call(table, Obf.TABLE_ADD, new Class<?>[] {actorClass}, cellClass, button);
layoutCell(buttonCell, Obf.CELL_LEFT);
// 换行:不调 row() 的话按钮和文字会并排挤在同一行。
call(table, Obf.TABLE_ROW, new Class<?>[0], cellClass);
// 第二行:文字区,占满剩余空间并撑开单元格。
Object textCell = call(table, Obf.TABLE_ADD, new Class<?>[] {actorClass}, cellClass, scrollBody);
layoutCell(textCell, Obf.CELL_EXPAND, Obf.CELL_FILL, Obf.CELL_TOP);
System.err.println("[view] 面板已按两行布局:按钮 / 可滚动文字区");
Scene2dPanel.wireButton(button, label, loader);
return table;
// 面板内容(增删改查)在 ObjectPanel 里,这里只负责把它建出来。
return ObjectPanel.build(loader, skin);
}
/**