阶段四:Spine 3.8.99 编辑器里挂上自建视图面板

目标:在 Spine 编辑器窗口内部加一个自己的视图面板(按钮 + 文字显示),
点击读取场景对象,并像原生面板一样出现在 Views 菜单、可停靠可折叠。

本轮打通:
1. 编辑器在我们自己的进程里完整启动
   - 类加载器必须是 URLClassLoader 本身(自检要求)
   - Editor.main 必须在 AWT EDT 上调用
   - jvm.cfg 第 21 行要以两个空格结尾 + -DSpineJava
   - Editor.D:I 版本号、fonts/、/tzax 资源、Java8 版 launcher.Launcher 替身
2. 3.8.99 全量解密 → 可读源码
   - 字符串 17251/17461(伪造同名调用帧对齐 key)
   - 混淆动态派发还原 53871 处(调引导方法取 MemberName)
3. 自建视图
   - agent 在内存里给 us 枚举加 spineView 常量(不改磁盘,避开完整性自检)
   - 面板 Actor 由外部反射填进 us.spineView.D
   - 复用已有图标做别名(不新建图片资源)
   最终 "Spine View" 出现在 Views 菜单,可与 Tree 并排停靠、折叠展开

另外:
- ViewPatcher/ViewAgent:视图枚举与面板挂载的字节码插桩
- DecAll/ObMap/rewrite_source:字符串解密、派发还原、可读源码生成
- 阶段四-视图面板挂载.md:完整记录做法与踩过的坑

不纳入版本管理:rea/(独立仓库)、tools 下的 JDK/Ghidra 工具链、
Spine.app 与 spine-lab 副本、从载荷派生的批量产物。
This commit is contained in:
tianmo committed 2026-10-16 13:34:18 +08:00
commit 2e7ab7c33c
113 files changed
+25327

No files matched your search

+1
View File
@@ -0,0 +1 @@
{"A": {"name": "A", "super": "java.lang.Enum", "interfaces": [], "flags": 16433, "fields": [{"name": "D", "type": "A", "flags": 16409}, {"name": "B", "type": "A", "flags": 16409}, {"name": "L", "type": "A", "flags": 16394}, {"name": "I", "type": "A", "flags": 16394}, {"name": "S", "type": "A", "flags": 16394}, {"name": "C", "type": "A", "flags": 16394}, {"name": "Z", "type": "A", "flags": 16394}, {"name": "D", "type": "int", "flags": 17}, {"name": "D", "type": "A[]", "flags": 4122}], "methods": [{"name": "values", "params": [], "returns": "A[]", "flags": 9}, {"name": "valueOf", "params": ["java.lang.String"], "returns": "A", "flags": 9}, {"name": "<init>", "params": ["java.lang.String", "int", "int"], "returns": "void", "flags": 2}, {"name": "<clinit>", "params": [], "returns": "void", "flags": 8}], "path": "/Volumes/Spine398/A.class"}, "AA": {"name": "AA", "super": "java.lang.Enum", "interfaces": [], "flags": 16433, "fields": [{"name": "D", "type": "AA", "flags": 16409}, {"name": "B", "type": "AA", "flags": 16409}, {"name": "L", "type": "AA", "flags": 16409}, {"name": "I", "type": "AA", "flags": 16409}, {"name": "S", "type": "AA", "flags": 16409}, {"name": "D", "type": "AA[]", "flags": 4122}], "methods": [{"name": "values", "params": [], "returns": "AA[]", "flags": 9}, {"name": "valueOf", "params": ["java.lang.String"], "returns": "AA", "flags": 9}, {"name": "<init>", "params": ["java.lang.String", "int"], "returns": "void", "flags": 2}, {"name": "<clinit>", "params": [], "returns": "void", "flags": 8}], "path": "/Volumes/Spine398/AA.class"}, "AB": {"name": "AB", "super": "et", "interfaces": [], "flags": 1057, "fields": [{"name": "D", "type": "Ah", "flags": 17}, {"name": "D", "type": "JS", "flags": 1}, {"name": "B", "type": "boolean", "flags": 0}], "methods": [{"name": "<init>", "params": ["Ah", "JS"], "returns": "void", "flags": 1}, {"name": "L", "params": ["java.lang.String"], "returns": "void", "flags": 20}, {"name": "D", "params": ["AB"], "returns": "void", "flags": 1}, {"name": "B", "params": ["AB"], "returns": "void", "flags": 1}, {"name": "D", "params": [], "returns": "java.lang.Exception", "flags": 1025}, {"name": "D", "params": ["com.esotericsoftware.spine.editor.export.ExportSettings"], "returns": "void", "flags": 1025}, {"name": "D", "params": [], "returns": "com.esotericsoftware.spine.editor.export.ExportSettings", "flags": 1025}, {"name": "D", "params": ["java.lang.String"], "returns": "boolean", "flags": 17}, {"name": "D", "params": ["java.lang.Class", "java.lang.String"], "returns": "java.io.InputStream", "flags": 8}, {"name": "Nb", "params": ["java.lang.Object", "java.lang.Object", "java.lang.Object", "java.lang.Object"], "returns": "java.lang.Object", "flags": 10}], "path": "/Volumes/Spine398/AB.class"}, "AC": {"name": "AC", "super": "vv", "interfaces": [], "flags": 48, "fields": [{"name": "D", "type": "AB", "flags": 4098}], "methods": [{"name": "<init>", "params": ["AB", "java.lang.String"], "returns": "void", "flags": 0}, {"name": "L", "params": ["java.lang.Object"], "returns": "void", "flags": 17}, {"name": "xp", "params": ["java.lang.Object", "java.lang.Object", "java.lang.Object", "java.lang.Object"], "returns": "java.lang.Object", "flags": 10}], "path": "/Volumes/Spine398/AC.class"}, "AD": {"name": "AD", "super": "et", "interfaces": ["java.lang.Runnable"], "flags": 49, "fields": [{"name": "D", "type": "Ah", "flags": 16}, {"name": "D", "type": "s", "flags": 1}, {"name": "D", "type": "JX", "flags": 1}, {"name": "D", "type": "dl", "flags": 1}, {"name": "D", "type": "df", "flags": 16}, {"name": "B", "type": "df", "flags": 2}, {"name": "D", "type": "float[]", "flags": 16}, {"name": "B", "type": "int", "flags": 0}, {"name": "Code", "type": "float", "flags": 0}, {"name": "SourceFile", "type": "float", "flags": 0}, {"name": "StackMapTable", "type": "float", "flags": 0}, {"name": "init", "type": "float", "flags": 0}, {"name": "LineNumberTable", "type": "float", "flags": 0}, {"name": "String", "type": "float", "flags": 0}, {"name": "Class", "type": "float", "flags": 0}, {"name": "Ljava", "type": "float", "flags": 0}, {"name": "java", "type": "float", "flags": 0}, {"name": "lang", "type": "float", "flags": 0}, {"name": "Object", "type": "float", "flags": 0}, {"name": "invoke", "type": "float", "flags": 0}, {"name": "MethodHandle", "type": "float", "flags": 0}, {"name": "Lcom", "type": "float", "flags": 0}, {"name": "CallSite", "type": "float", "flags": 0}, {"name": "ConstantCallSite", "type": "float", "flags": 0}, {"name": "Exceptions", "type": "float", "flags": 0}, {"name": "util", "type": "float", "flags": 0}, {"name": "B", "type": "boolean", "flags": 0}, {"name": "L", "type": "boolean", "flags": 0}, {"name": "D", "type": "de", "flags": 2}, {"name": "D", "type": "long", "flags": 2}, {"name": "D", "type": "java.util.concurrent.ThreadPoolExecutor", "flags": 16}, {"name": "D", "type": "z", "flags": 0}, {"name": "I", "type": "boolean", "flags": 0}, {"name": "S", "type": "boolean", "flags": 0}, {Line truncated