79 Commits
Author SHA1 Message Date
tianmo 6580611012 动画面板:新增两个动画测试按钮 + 把动画模型 API 全部落进对照表
## 功能(面板源码,重启后仍在)
- 新增 AnimationTools:
  - Animate Random Props:随机骨骼/插槽/附件 → ani_api_test
    旋转 0°→90°、位移 (0,0)→(120,-60)、缩放 (1,1)→(1.6,0.6)、斜切 (0,0)→(25,15)
    插槽颜色 (1,1,1,1)→(1,0.2,0.2,0.25)、附件 显示→隐藏;全部只在 0f/30f
  - Curve Test 6 Modes:curve_test,6 根骨骼各一条旋转轴(0°→45°,0f/30f),
    分别 linear / curve 平滑(0.25,0,0.75,1) / stepped / ease-in(0.42,0,1,1) /
    ease-out(0,0,0.58,1) / 对称自动(0.25,0.25,0.75,0.75)
- ObjectPanel.build 里挂载这两个按钮,复用面板自己的 wire() 点击轮询

## 对照表(tools/deobf/anchors.tsv + 混淆名对照表.md 第十一节)
- GP.I=animations、GP.D:LFT;.D:F=fps、Gl=动画(name/skeleton/timelineGroups/register)
- Gl.D/B/L/I(Gp)=旋转/位移/缩放/斜切;Gl.D/B(Gp,GU)=插槽颜色/附件;Gl.D()=绘制顺序
- FH=组;FI=时间轴(runtimeTimelineClass、keys、findKey、insertKey、invalidateRuntime)
- FN=关键帧(time、curve、c2x/c2y/c3x/c3y、setAngle/setX/setY、Color、Gn)
- FV=曲线枚举(linear/curve/stepped;'自动'=curve+控制值)
- 踩坑记录:
  * 关键帧数值写在 FN.D()/B()/L() 的 float 字段,**不是** FN.D():ga(ga 是 deform 的),
    否则会出现'有帧但运行时不变'
  * 编辑器时间轴刻度就是**帧**,关键帧时间写 0/30,不要按 1 秒=30 帧换算
  * FI.D(float,int) 建帧要求时间轴已有关键帧(先有鸡问题)
  * fI.removeRange 两个 (int,int) 重载都不缩容 → 清空动画直接换新 fI
names.tsv 合并成 380 条,payload-named.zip 重产(7271 处成员引用)。

验证:全部在运行中的编辑器里逐条读回(时间轴/关键帧/曲线枚举/控制值),
重启后 pid 94663 单实例,日志确认 '[animtool] 两个动画按钮已加入'。
2026-10-17 12:57:17 +08:00
tianmo 8df990a058 把 New 15 Bone+Slot+Att 按钮移植进面板源码(重启后仍在)
- 新类 com.spineview.NewFifteen:按钮 → 编辑器自带名称面板(xl + ASM 子类拿名字) → 按名字匹配附件
  → 当前选中骨骼下建 15 根骨骼,每根 1 插槽 1 附件(该名字的副本)
  骨骼 x/y 0~500 随机、rotation/scale/shear=0/1/0;插槽 alpha 0.5~1、blend normal/additive 随机;
  附件 x/y/rotation=0、scaleX/scaleY=1(并替换掉 ADD_SLOT 带过来的模板附件)
  弹窗按 pref 尺寸(>=360x170)撑开、同一次渲染回调里居中
- ObjectPanel.build 里挂一行按钮(复用 ObjectPanel.wire 的点击轮询)
- build.sh 的 javac 加 -cp ../tools/asm/asm.jar(NewFifteen 现场生成 xl 子类需要 ASM)
依据:tools/deobf/anchors.tsv + 混淆名对照表.md(全部字节码/实测确认)
2026-10-17 10:25:22 +08:00
tianmo 64361e389e 保留本次功能的最终实现源码(热更 agent 第 10 版)
内容:不重启、纯编辑器自身 API 加一个按钮 → 弹名称输入面板(编辑器自带 xl 对话框,ASM 现场生成子类拿名字)
→ 按名字匹配附件 → 在当前选中骨骼下建 15 根骨骼,每根 1 插槽 1 附件(输入的附件名):
- 骨骼 x/y 0~500 随机、rotation/scale/shear = 0/1/1/0/0
- 插槽 alpha 0.5~1 随机、blend normal/additive 随机
- 附件在插槽上 x/y/rotation=0、scaleX/scaleY=1(并换掉 ADD_SLOT 带来的模板附件)
- 弹窗按 pref 尺寸(399x170)撑开、同一次渲染回调里居中(不再先闪左下角)
同期其余临时件(build*/、*.jar、实验探针源码)已移出到 /tmp/spineview-tools-live-backup-1016-1933(可恢复)
2026-10-16 19:33:51 +08:00
tianmo 0a2da7f11b spine修改 2026-10-16 19:32:49 +08:00
tianmo f40979f965 对照表:补 WidgetGroup 尺寸读取(min/pref/maxW/H) + 对话框显示不全/闪左下角的两个修正
- 弹窗建出来默认 150x150,正文和按钮被裁 → 显式设 width/height=max(pref,min,下限) 再 invalidate
- '先左下角再跳中间' = addActor 后过一帧才居中;改成尺寸+居中在同一次渲染回调里做完
names.tsv 338 条,payload-named.zip 已重产(5617 处引用)
2026-10-16 19:31:04 +08:00
tianmo 42b40f6f65 对照表:补上'操作类'API(加插槽/加附件/加骨骼/不重名/撤销/名称输入面板/Actor 几何),全部来自热更实测
这次任务(不重启,纯编辑器自身 API:按钮→名称面板→按名字匹配附件→当前选中骨骼下建 15 根骨骼,每根 1 插槽 1 附件)
用到的 API 全部落表,含踩坑:
- ADD_SLOT 会把模板插槽连它自带的附件一起复制('插槽上的附件变换没改'就是这个)
- xl.D(dt) 不会把对话框挂进 Stage,必须再 dt.D(dl)V(Stage.addActor)
- dl.b_()Z=remove 与 eX.b_()V=invalidate 同名不同描述符,按名字取会删不掉
- et(Table) 也声明 int L()/I(),按名字取 Actor 几何必须按返回类型 float 过滤
- iz 枚举顺序 normal/additive/multiply/screen 取自 clinit
- un.Z()=撤销(实测栈 23->22、对象数回退)
names.tsv 合并成 332 条,payload-named.zip 已重新产出(5605 处引用)
2026-10-16 19:26:25 +08:00
tianmo b8e84c7aa5 停用 grabScrollFocus:它把列表的 ScrollPane 当 Stage.addActor 的参数传进去,导致列表被搬出面板画到窗口左下角
现象:点过面板按钮后,列表(Inspector 114 行)画在窗口左下角一小块里,面板中段只剩红/绿描边。
原因(探针实测 pid 59699):
  - 面板根表格只剩 2 个子控件(按钮块 + 日志 Label),ScrollPane 不见了;
  - ScrollPane 的父级变成 do[0,0,0x0](Stage 根),绝对坐标 (57,824);
  - grabScrollFocus 在 Stage 上找「1 个 Actor 参数 + void」当 setScrollFocus,
    只排除 dl/do/eX;但编辑器的 Stage 类 dt **自己声明** D(Ldl;)V(字节码 = root.addActor),
    于是唯一候选就是 addActor,被 invoke 后 Group.addActor 先把 ScrollPane 摘下来再挂到 Stage 根。
修复(用户选方案 B):不再调用 grabScrollFocus(滚动焦点本来就靠鼠标点列表拿到)。
复验(新进程 pid 60682,同一探针):root 子控件 = 3,ScrollPane 父级 = root,
绝对坐标 (2115,830) 回到停靠框内。
2026-10-16 18:47:34 +08:00
tianmo 7f06c6744a 新增阶段五文档:面板接真实数据(增删改查/属性读写/Inspector 真名翻译/滚动焦点/统计)+ 14 条踩坑点 + 未完成清单 2026-10-16 18:46:16 +08:00
tianmo bb817b85e5 映射表:用编辑器自带的 JSON 导出器(sB)反查字段含义(权威对照)
依据:导出 JSON 时每个 key 后面紧跟被读的字段,所以 key 名就是字段语义。
- 可读载荷 spine398.jar(DecAll 产出)javap -c sB 能直接看到 key 紧跟 getfield;
- 未解密载荷用 strings.tsv(class sB, method D) 的密文顺序核对,281 条顺序逐条一致(三段解密器各自成组)。
新增:Gp(骨骼) length/transform/skin;GU(插槽) color/dark/attachment/blend(注意是 B 不是 D);
各附件 GO/GE/Gx/Gr/Gs 与附件基类 Gn;约束 Gw/GX/GD。
修正:删掉被导出器证伪的 Gp.Class=length 与'静姿态 setup 组'推断(C:F 就是 length)。
同步:names.tsv 合并成 297 条,payload-named.zip 重新产出。
2026-10-16 18:30:03 +08:00
tianmo 7f519edc67 热更(不重启)整理新建附件:用编辑器自身 API 重置图片附件变换 + 删除占位(skin)附件
- 确认 GO 的字段/入口:x=D(float)、y=B(float)、rotation=S、scaleX=L、scaleY=I、width=C、height=Z;
  GO.D(FFFFF)V 就是编辑器自己的 setTransform(x,y,rotation,scaleX,scaleY)。
  依据:载荷 JSON 写入器 sb_0.java:669-675 + javap -c GO(两条独立证据),
  width/height 与 mega_dg4.png 真实像素 157x154 对上。
- 确认删除入口:Gn.L()V => skeleton.removeAttachment(this,true,true);GP.L=附件表、GP.Z=插槽表;
  占位附件是载荷类 Hi(hi_2.java 的 I() 返回 "placeholder")。
- 实机(JDK8 attach,进程 56177 全程没重启):20 个新建插槽的图片附件 x/y/rotation 归 0、scale 归 1;
  20 个 Hi 占位附件删除;骨架附件表 43 -> 23;逐个核对删除占位没连带删掉图片附件。
- 顺带把 tools/live(attach 热更工具源码)入库,jar/build 加进 .gitignore。
2026-10-16 18:26:40 +08:00
tianmo 0886ba647c 补回误删的 listQuietly(上一次改动把编译搞坏了,编辑器起不来);+10 Red Bones 暂用已验证可行的一根一次路径 2026-10-16 18:07:36 +08:00
tianmo 4000a06d61 +10 Red Bones 修两处:①每建一根等一帧(编辑器下一帧才真建,同帧连调只生效一次)②颜色按映射表写 Gp 的 color 字段(混淆名 B),不再取'第一个 Color 字段' 2026-10-16 17:57:06 +08:00
tianmo b09a7e0659 统一'当前操作对象':优先取编辑器里的选择(用户在层级面板选),New/Delete/Rename/+10 全部改用 currentTarget() 2026-10-16 17:55:50 +08:00
tianmo dd520655f0 +10 Red Bones 的父级改为读'编辑器当前选择'(用户是在层级面板里选的,不走我们列表行) 2026-10-16 17:55:10 +08:00
tianmo e57d31dfe6 撤掉列表表格外层的包装容器(它让编辑器布局抛 RuntimeException: Actor: ScrollPane,面板因此失去响应) 2026-10-16 17:53:55 +08:00
tianmo f696c15671 新增按钮 +10 Red Bones:在当前选中骨骼下用编辑器自己的 New Bone 建 10 根,位置随机(±200),颜色写 red(Gp 的 x/y 走 names.tsv 反查、color 按类型找字段) 2026-10-16 17:52:04 +08:00
tianmo 2e325bc1b9 去掉根表格 setFillParent(它把根表格拉成父容器大小,反而压扁三段);实测 root 仍被父容器限制在 ~1250 2026-10-16 17:39:50 +08:00
tianmo a0c1b13a47 列表表格外包一层容器(容器 setFillParent + 表格 expand/fill),让表格铺满 ScrollPane 视口(绿框=红框) 2026-10-16 17:37:47 +08:00
tianmo 3b5e80f991 中段套回 ScrollPane(填满该格高度=红框、内容超出时裁剪+可滚) 2026-10-16 17:36:14 +08:00
tianmo b737cc2b87 修 spine-lab/启动实验室Spine.command:它注入的 native-hook/hook.dylib 早已不存在(那套方案已废弃),改为调用 viewpanel/run.sh 2026-10-16 17:31:33 +08:00
tianmo 104eaba8c0 中段直接放列表表格(去掉 ScrollPane):expand/fill 撑满红框(代价:失去滚动) 2026-10-16 17:25:08 +08:00
tianmo d6a766d5b4 列表表格垫空白(80行)让 pref ≥ ScrollPane 视口:列表区域铺满红框,内容多时照常滚动 2026-10-16 17:24:23 +08:00
tianmo 949d741cde 列表表格 setFillParent(true):撑满 ScrollPane 视口(原来按内容固定高度只画一小块) 2026-10-16 17:23:38 +08:00
tianmo 9b85090e93 拉伸后保持内容靠左上:按钮块 top()+left(),日志格加 top() 2026-10-16 17:22:11 +08:00
tianmo 22c483738c 三段控件纵向拉伸填满各自单元格:按钮块与日志块加 fillY(Cell.L),中段原本已有 fillY 2026-10-16 17:21:28 +08:00
tianmo ee82bedabe 三段都加 expand(用户点名):吃掉停靠框剩余空间,消掉底部空带;600:1400:400 的比例仍作为各段 pref 2026-10-16 17:19:31 +08:00
tianmo dc4db3e8fa 三段按 600:1400:400 等比缩放到 Stage 高度(略大于停靠框):内容盖过底部,消掉底部空带 2026-10-16 17:17:37 +08:00
tianmo efeee1fe5a 加一行布局实测日志(root/按钮表/日志Label 高度),用于定位'底部空一条'的原因 2026-10-16 17:15:01 +08:00
tianmo 120d88bf0b 改回固定高度:上 600 / 中 1400 / 日志 400(不做等比缩放) 2026-10-16 17:13:32 +08:00
tianmo 4505c50af1 三段按 600:1400:400 的比例缩放到面板高度(原来三个数合计 2400 超过面板,被 libGDX 压扁导致比例看着不对) 2026-10-16 17:12:36 +08:00
tianmo 2a02984b79 三段固定高度按用户指定:上 600 / 中 1400 / 日志 400 2026-10-16 17:11:46 +08:00
tianmo 6744f122b4 三段高度按用户指定:中段 1400、日志段 400、上段取剩余;三段单元格都用 fillX 占满面板宽度 2026-10-16 17:10:22 +08:00
tianmo 8e9f70fdbd 下段(日志)固定 800 高;中段 = 面板高 − 上段20% − 800(仍铺满,不出空带) 2026-10-16 17:08:51 +08:00
tianmo 05c5d45cca 修 run.sh(漏 import os,导致编辑器根本起不来)+ 三段高度 20/60/20 自动按 Stage 高度算(实测 Stage.B()F=getHeight:4K 窗口 2044) 2026-10-16 17:07:41 +08:00
tianmo 84a8f30811 三段高度按 20/60/20 计算,面板高度可配置:-Dpanel.h=<像素>(默认 984,run.sh 支持 PANEL_H 环境变量)——4K 屏窗口更大时用得上 2026-10-16 17:01:37 +08:00
tianmo 77d6a91422 中段高度自适应父容器:middle = 父容器高(fillParent 前读到的 dock) − 按钮段 − 日志段(不用 expand);3 次迭代收敛 2026-10-16 16:59:27 +08:00
tianmo 8a1279bf5c 按用户要求去掉 expand:中段(列表)只用固定高度 700 做成最长的一段(fillY=L 拉伸),日志段自然高度贴底 2026-10-16 16:57:10 +08:00
tianmo 5c5ae8e7aa 中段(列表)改回最长的一段:expand+fill 吃掉剩余空间、保留高度下限;日志段只占自然高度贴底 2026-10-16 16:56:10 +08:00
tianmo 42def5b395 消除第 4 条空带:中段固定 450 且不再 expand,剩余高度全部给日志段(文字贴段顶)——此时面板就是干净的 上/中/下 三段 2026-10-16 16:55:14 +08:00
tianmo 1f402ea8e4 日志段固定高度 200(Cell.I=height 实测确认),中段 450:根表格三段都能看出来(上按钮/中列表/下日志) 2026-10-16 16:54:34 +08:00
tianmo 5a59b0f739 按用户要求画出上/中/下三段边界:根表格 setDebug(true)(载荷名 et.B(Z)V,对照表已确认)—— 红线=根表格三个单元格(按钮/中段/日志)的边界,绿线=按钮块内部单元格 2026-10-16 16:51:13 +08:00
tianmo 05e2d1b074 中段固定高度:Cell.I(float)=height(实测确认:设 900 → 根表格 580->1080;设后列表区出现滚动条可滚)。值先取 700,并把该映射写进 anchors.tsv/names.tsv 2026-10-16 16:50:16 +08:00
tianmo a5307021f3 回滚到可编译版本并修映射表路径:从 classes 往上找含 tools/deobf/names.tsv 的仓库根(Inspector 显示真名) 2026-10-16 16:46:14 +08:00
tianmo 84eb409b76 修映射表路径:classes 上跳三级才是仓库根(<root>/viewpanel/build/classes) 2026-10-16 16:44:46 +08:00
tianmo f0b78dbfd6 Inspector 显示用映射表翻译真名:字段/方法显示为 realName(混淆名),表来自 tools/deobf/names.tsv(运行时载荷不能改名,indy 靠加密串里的原名反射查找) 2026-10-16 16:44:12 +08:00
tianmo 0cdc0894a4 Revert "面板支持热更:视图里挂稳定容器(编辑器类加载器建的 Table),面板内容放在容器里;后台线程轮询 build/classes/com/spineview/ObjectPanel.class 的 mtime,一变就用新的子类加载器重建内容换进容器 —— 改完代码只需 build.sh,编辑器不用重启、场景与选择状态保留"
This reverts commit be0ed2352b.
2026-10-16 16:37:58 +08:00
tianmo be0ed2352b 面板支持热更:视图里挂稳定容器(编辑器类加载器建的 Table),面板内容放在容器里;后台线程轮询 build/classes/com/spineview/ObjectPanel.class 的 mtime,一变就用新的子类加载器重建内容换进容器 —— 改完代码只需 build.sh,编辑器不用重启、场景与选择状态保留 2026-10-16 16:35:23 +08:00
tianmo f8d2cda17c grabScrollFocus 改用 getMethods():Stage 的焦点 API 声明在接口里(lpt6 implements LPt9),getDeclaredMethods 扫不到(实测 setter1/getter0);排除 Actor/Group/WidgetGroup 上声明的同名形状方法以免误调 addActor 2026-10-16 16:31:48 +08:00
tianmo 55c0794ed4 面板恢复成上/中/下三段:上=按钮块(两列紧邻+名字输入框)、中=列表(expand+fill)、下=日志(独立 Label,自然高度贴底);去掉列表里内嵌的日志行与之前未验证的尺寸调用 2026-10-16 16:26:15 +08:00
tianmo 4b05804479 修鼠标滚轮(第3版):面板按钮动作后把编辑器的滚动焦点抢到列表上
- 诊断证据:给列表 ScrollPane 挂 EventListener 代理后,滚轮事件收到 0 条 → 滚轮被视口的 scroll focus 拿走;
- grabScrollFocus():只在 **Stage 自己声明**的方法里找(addActor 声明在 Group,不会误调);
  setter=『1 个参数是 Actor、返回 void』,getter=『无参返回 Actor』;调 setter 后看哪个 getter 变成面板,
  找到就写日志『滚动焦点已抢到面板:setter=.. getter=..』,找不到写『没找到 setScrollFocus』。
- 触发时机:每次点击面板按钮/字段行之后(路由器里统一调用)。
2026-10-16 16:22:19 +08:00
tianmo 995ec585f4 修正映射表:把 MapMethods 的候选猜测(~n/m)从确定表里剔除
- anchors-libgdx.tsv 只保留唯一命中的 (126 条);候选消歧的 (138 条)移到
  anchors-libgdx-unconfirmed.tsv 并标『不可信、要用先实测』;
- names.tsv 重新合并 = 确定(=) + 手动/实测锚点(不再混入猜测)。
2026-10-16 16:20:00 +08:00
tianmo 13bce4509d 让鼠标滚轮能滚列表:把列表 ScrollPane 的 touchable 从默认 childrenOnly 改成 enabled(无参返回枚举的方法=getTouchable,枚举 dv 第0常量=enabled)
- 诊断证据:程序化 scrollY(200) 生效(before=0 after=200),说明可滚范围没问题,
  是滚轮事件没送到面板 —— 因为 childrenOnly 时 ScrollPane 自己不是命中目标,收不到 enter、
  也就不会 setScrollFocus。
- 顺带把这条 Actor/Touchable 映射写进 anchors.tsv + names.tsv。
2026-10-16 16:18:28 +08:00
tianmo d59287937d 列表滚动(第二版):给列表单元格固定高度 360(Cell.height 载荷名 I,(F)LdR; 指纹确认)+ setForceScroll(false,true)(ScrollPane.I(ZZ)V 指纹确认);并把 setForceScroll/setOverscroll/Cell 尺寸方法写进 anchors.tsv+names.tsv 2026-10-16 16:15:35 +08:00
tianmo f558a4e4aa 把确认的映射写进表 + 技能补一条立即生效的规矩
- anchors.tsv 增补 ScrollPane(含踩坑确认的 B(ZZ)V=setScrollingDisabled,不是 setForceScroll),
  names.tsv 同步为 220 条;
- 混淆名对照表.md 新增第七节(ScrollPane 方法映射 + 教训);
- .codex/skills/scope-discipline 增补『结论必须落进映射表(立即生效)』:新确认的映射/字段语义
  当场写进 anchors.tsv 并同步 names.tsv / src-named,不许只留在对话里。
2026-10-16 16:13:54 +08:00
tianmo 8d396ecb5b 修列表滚动:ScrollPane 的 (boolean,boolean) 方法是 setScrollingDisabled 不是 setForceScroll;上一版传 (false,true) 把纵向滚动关掉了,现改为 (false,false) 恢复双向滚动 2026-10-16 16:13:09 +08:00
tianmo 320f537a60 只修列表:beginRender 改回复用同一个 Table(换新 ScrollPane 会抛 InvocationTargetException 导致列表渲染失败);invalidate 后再调 ScrollPane(boolean,boolean)=setForceScroll 让它按新内容高度重算可滚动范围 2026-10-16 16:11:54 +08:00
tianmo b8fe2f98d1 新增项目级 skill:.codex/skills/scope-discipline(只做用户明确要求的事;改完自动重启并确认进程活着) 2026-10-16 16:10:49 +08:00
tianmo ee1f2a2ced 只修列表滚动:每次渲染换一套新的 Table+ScrollPane 塞回同一单元格(复用时 ScrollPane 不重新测量 widget 高度,maxY=0 导致滚轮失效) 2026-10-16 16:10:20 +08:00
tianmo 94c467a40d Revert "列表区改分页:每页 12 行 + Prev/Next(复用同一个 ScrollPane 时高度不重算,滚轮失效;分页绕开滚动)"
This reverts commit 32e707d23a.
2026-10-16 16:09:11 +08:00
tianmo 32e707d23a 列表区改分页:每页 12 行 + Prev/Next(复用同一个 ScrollPane 时高度不重算,滚轮失效;分页绕开滚动) 2026-10-16 16:09:08 +08:00
tianmo 5e7aed4a51 Inspector 变成可测数据的入口:字段行可点(读出当前值到输入框) + Set Value 按钮直接改模型字段(带撤销+重建树节点) + 跟随编辑器选择自动重新 Inspect 2026-10-16 16:08:05 +08:00
tianmo 0ec33d90ae 修 Inspect 被日志覆盖:setStatus 改为只追加一行日志(不再触发整表重排),日志块用 logBlockStarted 标记 2026-10-16 16:06:48 +08:00
tianmo 8fefcb76c4 run.sh 改用 python subprocess.Popen(start_new_session=True) 启动:nohup 方式会让编辑器挂在启动它的会话下,会话结束就被收掉 2026-10-16 16:04:26 +08:00
tianmo 1333e3d89c 面板内容区合并为一个滚动区:列表/Inspector 在上、日志块在下(不再用两个单元格,顺序不会再反) 2026-10-16 16:00:46 +08:00
tianmo 9e318f3361 下段提示区:包进 ScrollPane + 固定 90px 高度,保证任意停靠高度下三段都各占一块 2026-10-16 15:58:32 +08:00
tianmo 1cfd5e13cd 面板改为上/中/下三段:上=按钮(自适应)、中=列表(expand+fill 吃掉剩余)、下=实时提示(保留最近6条,多行) 2026-10-16 15:57:36 +08:00
tianmo 7f5ee1f00e 面板布局再修:按钮直接进根表格(两列多行),列表区是唯一 expand+fill 的行;列表内容 Table 设 top()+left(),否则 ScrollPane 里控件比视口小时会居中显示,看着像'列表跑到下面' 2026-10-16 15:51:46 +08:00
tianmo f4cf713ded 修面板布局:根表格与按钮子表 top(),按钮行/状态行不再 fill(否则控件被拉伸挤到停靠框下方) 2026-10-16 15:49:29 +08:00
tianmo 1f8a3b4dae 加可双击的 viewpanel/重启编辑器.command(Finder 双击即重启编辑器) 2026-10-16 15:47:58 +08:00
tianmo e5461cbf12 加 viewpanel/run.sh:一条命令手动重启编辑器(先杀旧实例、按需 rebuild、日志写 /tmp/spineview.log) 2026-10-16 15:46:40 +08:00
tianmo 15468829ae 按 setup pose 实测补锚点:Gp.length/worldScale、GU.name/bone/attachment/color、GO 附件的 rotation/scale/width/height
用户用四张 setup pose 截图给出对照:Gp(root/bone)、GU(插槽)、GO(region 附件)。
- Gp:面板 Length 与 float Class 一致 → length;Ljava/java 与 Code/SourceFile 相等 → 世界缩放。
- GU:String D=名字、Gp D=所属骨骼、Gn D=附件、Color D=颜色。
- GO:六个 float 对上 Region 附件的 旋转/缩放XY/宽高。
names.tsv 合并后 222 行,Renamer 重新产出 payload-named.zip。
2026-10-16 15:44:31 +08:00
tianmo e197a6883a Spine View 启动自动打开(等价 Views 菜单勾选),不用每次手点
- ViewInstaller.showView():面板 Actor 填好后调 Fx.D(us.spineView) —— 菜单 'Tree View' 的动作体就是
  Fx.D(us.Tree)(og.java:23),是编辑器自己的'显示/停靠视图'入口。
- 为什么之前每次都要手点:视图可见状态写在 views.json,只有正常退出才落盘;而我们一直用 SIGTERM
  杀编辑器进程,状态没写回去。启动时主动开一次就绕过了这个。
- 列表区仍按设计需要点一次 Refresh(面板是编辑器 UI 搭好之前就建的,那时场景树还是空的)。
2026-10-16 15:36:42 +08:00
tianmo 9a6913e610 骨骼字段语义命名(实测证据)+ 逐类反编译避免大小写撞名
- anchors.tsv:按用户实测把这批字段钉死 ——
  Z/V=x/y、F=rotation、Code/SourceFile=scaleX/scaleY、StackMapTable/LineNumberTable=shearX/shearY
  (证据:编辑器里 Rotate=341.456 / Translate(-168,-116) / Scale(0.8799,0.572) / Shear(-52.221,-28.63)
   与 Inspector 显示值一一对应);D/B/L/I/S/C = 静止姿态组(推断);D:LGP;=skeleton、D:LGp;=parent、B:Color=color。
- names.tsv 合并后 208 条,Renamer 改名 2867 处成员引用。
- src-named 改为**每个类单独反编译、用载荷类名当文件名**:CFR 直接输出会把 GP.java/Gp.java
  这类只差大小写的类写到同一个文件(macOS 文件系统不区分大小写),必须逐类产出。
- 注:CFR 对同名成员的自动改名(var_xxx 风格)不要开(--renamedupmembers),否则会盖掉我们的语义名。
2026-10-16 15:35:33 +08:00
tianmo d9ea449b64 面板增删改查 + 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 新增第六节(工具链 + 已验证 + 已知限制)。
2026-10-16 15:25:02 +08:00
tianmo 7fbb042aa6 编辑器交互/数据 API 调研完成:解出 KP=SelectBox、选中链路、增删改真实落点与撤销栈
- 新工具 tools/decrypt/DumpSites.java:逐 indy 站点解出『类.方法 + 描述符』(带描述符,
  解决 rewrite_source.py 丢描述符导致的重载混淆);ResolveSites.java 走运行时 CallSite 交叉验证。
- 结论改正:KP = libGDX SelectBox,KP.B(String)V = setSelected;XW/acW/acK/Yr 是
  『属性面板控件』而不是场景数据;场景对象是树节点上的 GP/Gp/GU/GO。
- 补齐:当前选择怎么设(VZ.D(Object))、谁刷新界面(VZ.D(GP,ZZ) / rW.B / fC.C)、
  撤销栈(载荷类 un 的 D()/B() 成对包一层)、删除边界(root 的删除按钮本来就是 disabled)、
  查/选/改名/删除/导出的真实实现与出处。
- 新增运行时探针 -Dspine.probe=objects(SceneObjects.java),实测打印整棵场景对象树。
- 文档:编辑器交互与数据API.md 重写;混淆名对照表.md 增补类/方法对照与大小写同名类坑。
2026-10-16 14:38:25 +08:00
tianmo 2b23ce59db 新增《编辑器交互与数据API》调研文档
- 交互层:工具注册(Create Tool 等)与视口交互入口
- 层级树:VZ(视图) / uo_2(节点) / xw_2(骨架) / gp_2(骨) / acK(插槽) 包装模型
- 当前选择:og_1.D.D 的读取点与菜单动作的依赖关系
- 数据层:所有 New X 都落到 KP.B(父级, 类型名),以及 KP 真实类名待解
- 改删查命令清单、撤销注意点、skeleton/root 删除边界、下一步 5 条
2026-10-16 14:22:48 +08:00
tianmo a0080428f9 场景对象增删改查调研:命令系统入口 + 新建对象的真实落点
- Commands.java:Editor -> pE(命令系统) -> void D(String) 按名字执行命令
- Launcher:新增 -Dspine.runCommand="<命令名>" 便于验证
- SceneReader:Tree/选中项探针(actor 树按 SnapshotArray 结构遍历)
- 混淆名对照表.md:补命令系统一节、可执行命令名单、skeleton/root 删除边界、
  以及 New X 最终落到静态 KP.B(target, 类型名) 的结论与待办
2026-10-16 14:20:45 +08:00
tianmo 8f7b72271f 阶段四收尾:面板两行布局(row/expand/fill)+ 英文输出 + 混淆名对照表
- ViewInstaller:用 Table.row()/Cell.expand()+fill()/setFillParent 排出"
  按钮一行、可滚动文字区一行"的面板;修掉把 setDebug 当成 setFillParent 的误用
- Scene2dPanel:按钮 isChecked/setChecked 与 Label.setText 改用对照表定名,
  修掉"点一次反复触发"与"文字不刷新"两个 bug
- SceneReader:面板输出改英文(编辑器缺中文字形,中文会渲染成方块)
- 新增 tools/obfmap/MapMethods.java:载荷 vs 上游 libGDX 的字节码指纹比对工具
- 新增 混淆名对照表.md:类/方法/字段映射、推导办法、已踩的坑、验证状态
2026-10-16 14:06:42 +08:00
tianmo 2e7ab7c33c 阶段四: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 副本、从载荷派生的批量产物。
2026-10-16 13:34:18 +08:00