阶段四收尾:面板两行布局(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:类/方法/字段映射、推导办法、已踩的坑、验证状态
This commit is contained in:
tianmo committed 2026-10-16 14:06:42 +08:00
1 parent 2e7ab7c33c
commit 8f7b72271f
8 files changed
+677 -52

No files matched your search

+123
View File
@@ -0,0 +1,123 @@
package com.spineview;
/**
* Spine 3.8.99 载荷里**被混淆成员的对照表**(推导过程见仓库根目录 `混淆名对照表.md`)。
*
* 推导办法(可复现,不是猜的):
* 1) `tools/obfmap/MapMethods.java`:把载荷类与上游 libGDX 同签名方法做
* "忽略名字的字节码指纹"比对(操作码序列 + 常量 + 成员的描述符);
* 2) 拿上游 libGDX 1.11.0 的源码逐条核对方法体语义。
*
* ⚠️ 这套载荷用了"**同名不同描述符**"的混淆手法:类里同时存在
* `D(Ldl;)LdR;`、`D()LdR;`、`D(F)LdR;`… 全部叫 `D`。所以任何一处都必须
* **名字 + 描述符一起判断**,只看名字一定会读错。
*/
public final class Obf {
// ======================= 类 =======================
/** com.badlogic.gdx.scenes.scene2d.Actor */
public static final String ACTOR = "dl";
/** com.badlogic.gdx.scenes.scene2d.Group(do extends dl) */
public static final String GROUP = "do";
/** com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup(eX extends do) */
public static final String WIDGET_GROUP = "eX";
/** com.badlogic.gdx.scenes.scene2d.ui.Table(et extends eX) */
public static final String TABLE = "et";
/** com.badlogic.gdx.scenes.scene2d.ui.Cell(implements Poolable) */
public static final String CELL = "dR";
/** com.badlogic.gdx.scenes.scene2d.Stage 的实现(uk extends dt) */
public static final String STAGE = "dt";
/** com.badlogic.gdx.scenes.scene2d.ui.Value */
public static final String VALUE = "eN";
/** com.badlogic.gdx.utils.Array */
public static final String ARRAY = "fI";
// ======================= Button =======================
// 类名保留(TextButton 继承它),但方法名被混淆了。
/** com.badlogic.gdx.scenes.scene2d.ui.Button */
public static final String BUTTON = "com.badlogic.gdx.scenes.scene2d.ui.Button";
/** `isChecked() -> boolean`(体是 `return isChecked;`,读第 1 个 boolean 字段) */
public static final String BUTTON_IS_CHECKED = "String";
/** `setChecked(boolean)` */
public static final String BUTTON_SET_CHECKED = "I";
/** `setChecked(boolean, boolean)`(第二个参数是否派发事件) */
public static final String BUTTON_SET_CHECKED_FIRE = "B";
/** `setDisabled(boolean)` */
public static final String BUTTON_SET_DISABLED = "a_";
// ======================= Label =======================
/** com.badlogic.gdx.scenes.scene2d.ui.Label */
public static final String LABEL = "com.badlogic.gdx.scenes.scene2d.ui.Label";
/**
* `setText(CharSequence) -> void`。
* ⚠️ Label 上还有一个 `D(CharSequence) -> boolean`,那是 `textEquals(CharSequence)`
* —— 只按"一个 CharSequence 参数"去找方法会挑中它,现象是**日志说读取成功、面板文字却不变**。
*/
public static final String LABEL_SET_TEXT = "D";
/** `getText() -> StringBuilder` */
public static final String LABEL_GET_TEXT = "D";
// ======================= Table =======================
/** `add(Actor) -> Cell` */
public static final String TABLE_ADD = "D";
/** `add(Actor...) -> Table`(varargs 版,谨慎别选错) */
public static final String TABLE_ADD_VARARGS = "D";
/** `row() -> Cell` —— 换行的关键,不调用的话所有控件都挤在第一行 */
public static final String TABLE_ROW = "I";
/** `setFillParent(boolean)`(WidgetGroup 的,让面板铺满停靠框) */
public static final String TABLE_SET_FILL_PARENT = "Z";
/** `setClip(boolean)` */
public static final String TABLE_SET_CLIP = "C";
/** `setDebug(boolean)` —— 会把单元格描出彩色边框,别误当成 setFillParent */
public static final String TABLE_SET_DEBUG = "B";
/** `top() -> Table`(表格内容整体对齐) */
public static final String TABLE_TOP = "I";
/** `left() -> Table` */
public static final String TABLE_LEFT = "S";
/** `center() / bottom() / right() -> Table` */
public static final String TABLE_CENTER = "L";
public static final String TABLE_BOTTOM = "C";
public static final String TABLE_RIGHT = "Z";
/** `align(int) -> Table` */
public static final String TABLE_ALIGN = "D";
/** `pad(float) / pad(float×4) -> Table` */
public static final String TABLE_PAD = "D";
/** `padTop/padLeft/padBottom/padRight(float) -> Table` */
public static final String TABLE_PAD_TOP = "B";
public static final String TABLE_PAD_LEFT = "L";
public static final String TABLE_PAD_BOTTOM = "I";
public static final String TABLE_PAD_RIGHT = "S";
// ======================= Cell =======================
/** `fill() -> Cell`(fillX = fillY = 1,撑满单元格) */
public static final String CELL_FILL = "D";
/** `fill(boolean)` */
public static final String CELL_FILL_BOOL = "D";
/** `expand() -> Cell`(expandX = expandY = 1,占掉剩余空间) */
public static final String CELL_EXPAND = "StackMapTable";
/** `expandX() / expandY() -> Cell` */
public static final String CELL_EXPAND_X = "init";
public static final String CELL_EXPAND_Y = "LineNumberTable";
/** `fillX() / fillY() -> Cell` */
public static final String CELL_FILL_X = "B";
public static final String CELL_FILL_Y = "L";
/** `grow() / growX() / growY() -> Cell` */
public static final String CELL_GROW = "F";
public static final String CELL_GROW_X = "Code";
public static final String CELL_GROW_Y = "SourceFile";
/**
* 对齐:`top() / left() / bottom() / right() / center()`。
* 载体是 `align |= X & ~Y` 的形式,位掩码取自 libGDX 的 Align:
* center=1、top=2、bottom=4、left=8、right=16。
*/
public static final String CELL_TOP = "S";
public static final String CELL_LEFT = "C";
public static final String CELL_BOTTOM = "Z";
public static final String CELL_RIGHT = "V";
public static final String CELL_CENTER = "I";
/** `align(int) -> Cell` */
public static final String CELL_ALIGN = "D";
private Obf() {
}
}