From 05e2d1b0742bd5e0ac5547362802ef1079e3427c Mon Sep 17 00:00:00 2001 From: tianmo Date: Fri, 16 Oct 2026 16:50:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AD=E6=AE=B5=E5=9B=BA=E5=AE=9A=E9=AB=98?= =?UTF-8?q?=E5=BA=A6=EF=BC=9ACell.I(float)=3Dheight=EF=BC=88=E5=AE=9E?= =?UTF-8?q?=E6=B5=8B=E7=A1=AE=E8=AE=A4=EF=BC=9A=E8=AE=BE=20900=20=E2=86=92?= =?UTF-8?q?=20=E6=A0=B9=E8=A1=A8=E6=A0=BC=20580->1080=EF=BC=9B=E8=AE=BE?= =?UTF-8?q?=E5=90=8E=E5=88=97=E8=A1=A8=E5=8C=BA=E5=87=BA=E7=8E=B0=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E6=9D=A1=E5=8F=AF=E6=BB=9A=EF=BC=89=E3=80=82=E5=80=BC?= =?UTF-8?q?=E5=85=88=E5=8F=96=20700=EF=BC=8C=E5=B9=B6=E6=8A=8A=E8=AF=A5?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E5=86=99=E8=BF=9B=20anchors.tsv/names.tsv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/deobf/anchors.tsv | 5 ++ tools/deobf/names.tsv | 2 +- viewpanel/src/com/spineview/ObjectPanel.java | 83 ++++++-------------- 3 files changed, 28 insertions(+), 62 deletions(-) diff --git a/tools/deobf/anchors.tsv b/tools/deobf/anchors.tsv index 8d3e1a5..c3e4ec3 100644 --- a/tools/deobf/anchors.tsv +++ b/tools/deobf/anchors.tsv @@ -93,3 +93,8 @@ dR V (F)LdR; prefHeight # 现象佐证:ScrollPane 默认 childrenOnly 时自己不是命中目标,收不到 enter → 滚轮事件不会送到它, # 但程序化 scrollY() 是生效的(实测 before=0 after=200)。 dl L (Ldv;)V setTouchable +# ---- Cell.height(2026-10-16 实测确认)---- +# 依据:对 Cell 的候选 (float) 方法依次调用 900,等一帧后量"根表格高度": +# Cell.I(900) -> root 高度 580 -> 1080(其它候选 L/B/Z/V/C/S/F 都没这个效果) +# => Cell.I(float) 就是 height(float);现象佐证:设了它之后列表区出现滚动条、可滚。 +dR I (F)LdR; height diff --git a/tools/deobf/names.tsv b/tools/deobf/names.tsv index 0510822..c693fc7 100644 --- a/tools/deobf/names.tsv +++ b/tools/deobf/names.tsv @@ -1,4 +1,4 @@ -# 合并后的名字映射表:**只用确定(=)的指纹命中 + 手动/实测锚点** +# 合并后的名字映射表:确定(=)指纹 + 手动/实测锚点 # owner name desc newName GO C F width GO I F scaleY diff --git a/viewpanel/src/com/spineview/ObjectPanel.java b/viewpanel/src/com/spineview/ObjectPanel.java index 66620eb..807c96b 100644 --- a/viewpanel/src/com/spineview/ObjectPanel.java +++ b/viewpanel/src/com/spineview/ObjectPanel.java @@ -148,6 +148,13 @@ public final class ObjectPanel { layoutCell(logCell, Obf.CELL_LEFT); cell = call(root, Obf.TABLE_ADD, new Class[] {actorClass}, cellClass, content); layoutCell(cell, Obf.CELL_EXPAND, Obf.CELL_FILL); + // 中段高度固定:Cell.height(float) 在载荷里叫 `I`(描述符 (F)LdR;) + // 实测确认:设 900 后根表格高度 580 -> 1080,说明它就是 height()。 + try { + call(cell, "I", new Class[] {float.class}, cellClass, Float.valueOf(700f)); + } catch (Throwable error) { + System.err.println("[panel] 设置中段高度失败: " + error); + } wire(loader, setValue, new Runnable() { @Override @@ -191,67 +198,6 @@ public final class ObjectPanel { }); startSelectionWatcher(state); - // 一次性诊断:等布局稳定后把 ScrollPane / 日志 Label 的几何打出来(只读,不改行为) - Thread measure = new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(2500); - } catch (InterruptedException ignored) { - return; - } - StringBuilder a = new StringBuilder("[panel] 列表 ScrollPane 几何: "); - for (Method m : state.listScroll.getClass().getMethods()) { - if (m.getParameterTypes().length != 0 || m.getReturnType() != float.class) continue; - try { - m.setAccessible(true); - a.append(m.getName()).append('=').append(m.invoke(state.listScroll)).append(' '); - } catch (Throwable ignored) { - // 跳过 - } - } - StringBuilder b = new StringBuilder("[panel] 日志 Label 几何: "); - for (Method m : state.status.getClass().getMethods()) { - if (m.getParameterTypes().length != 0 || m.getReturnType() != float.class) continue; - try { - m.setAccessible(true); - b.append(m.getName()).append('=').append(m.invoke(state.status)).append(' '); - } catch (Throwable ignored) { - // 跳过 - } - } - // 同一方法名在 root/content/pane 上各读一遍:真正的 getWidth/getHeight 会给出"面板那么大"的数 - for (Method m : state.listScroll.getClass().getMethods()) { - if (m.getParameterTypes().length != 0 || m.getReturnType() != float.class) continue; - String name = m.getName(); - StringBuilder row = new StringBuilder("[panel] " + name + ": "); - Object[] targets = {state.root, state.content, state.listScroll, state.status}; - String[] tags = {"root", "content", "pane", "log"}; - for (int i = 0; i < targets.length; i++) { - if (targets[i] == null) continue; - try { - Method same = null; - for (Method candidate : targets[i].getClass().getMethods()) { - if (candidate.getName().equals(name) - && candidate.getParameterTypes().length == 0 - && candidate.getReturnType() == float.class) { - same = candidate; - break; - } - } - if (same == null) continue; - same.setAccessible(true); - row.append(tags[i]).append('=').append(same.invoke(targets[i])).append(' '); - } catch (Throwable ignored) { - // 跳过 - } - } - System.err.println(row.toString()); - } - } - }, "spineview-measure"); - measure.setDaemon(true); - measure.start(); System.err.println("[panel] 增删改查面板已建好"); refreshList(state); return root; @@ -817,6 +763,21 @@ public final class ObjectPanel { } } + /** 读某个对象的某个无参 float 方法(诊断用)。 */ + static float floatOf(Object target, String name) { + try { + for (Method m : target.getClass().getMethods()) { + if (!m.getName().equals(name)) continue; + if (m.getParameterTypes().length != 0 || m.getReturnType() != float.class) continue; + m.setAccessible(true); + return ((Float) m.invoke(target)).floatValue(); + } + } catch (Throwable ignored) { + // 读不到 + } + return -1f; + } + private static float readFloat(Object target, String name) { try { for (Method method : target.getClass().getMethods()) {