From 1333e3d89cb3cc02581c554fa2dd64ea1dfa7228 Mon Sep 17 00:00:00 2001 From: tianmo Date: Fri, 16 Oct 2026 16:00:46 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E5=86=85=E5=AE=B9=E5=8C=BA?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=B8=BA=E4=B8=80=E4=B8=AA=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E5=8C=BA=EF=BC=9A=E5=88=97=E8=A1=A8/Inspector=20=E5=9C=A8?= =?UTF-8?q?=E4=B8=8A=E3=80=81=E6=97=A5=E5=BF=97=E5=9D=97=E5=9C=A8=E4=B8=8B?= =?UTF-8?q?=EF=BC=88=E4=B8=8D=E5=86=8D=E7=94=A8=E4=B8=A4=E4=B8=AA=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=A0=BC=EF=BC=8C=E9=A1=BA=E5=BA=8F=E4=B8=8D=E4=BC=9A?= =?UTF-8?q?=E5=86=8D=E5=8F=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viewpanel/src/com/spineview/ObjectPanel.java | 75 +++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/viewpanel/src/com/spineview/ObjectPanel.java b/viewpanel/src/com/spineview/ObjectPanel.java index 7fdb569..a509875 100644 --- a/viewpanel/src/com/spineview/ObjectPanel.java +++ b/viewpanel/src/com/spineview/ObjectPanel.java @@ -41,6 +41,8 @@ public final class ObjectPanel { String statusText; Object nameField; final java.util.Deque log = new java.util.ArrayDeque(); + boolean rendering; + Runnable logPanelRefresh; List objects = new ArrayList(); Object target; } @@ -106,21 +108,16 @@ public final class ObjectPanel { Object cell = call(root, Obf.TABLE_ADD, new Class[] {actorClass}, cellClass, state.nameField); layoutCell(cell, Obf.CELL_LEFT); call(root, Obf.TABLE_ROW, new Class[0], cellClass); - // 中段:列表区 —— 唯一 expand+fill 的单元格,吃掉剩余的高度 + // 唯一 expand+fill 的单元格:内容区(上面是列表/Inspector,最下面是日志块,同一个滚动区) cell = call(root, Obf.TABLE_ADD, new Class[] {actorClass}, cellClass, scroll); layoutCell(cell, Obf.CELL_TOP, Obf.CELL_EXPAND, Obf.CELL_FILL); - // 下段:实时提示(多行、只靠左,不加 fill,保持自然高度贴在底部) - call(root, Obf.TABLE_ROW, new Class[0], cellClass); - cell = call(root, Obf.TABLE_ADD, new Class[] {actorClass}, cellClass, - logScroll == null ? state.status : logScroll); - layoutCell(cell, Obf.CELL_LEFT, Obf.CELL_FILL_X); - try { - // 固定高度 90px:下段永远占一块,消息多了在它自己里滚 - call(cell, "L", new Class[] {float.class}, cellClass, Float.valueOf(90f)); - } catch (Throwable error) { - System.err.println("[panel] 提示区高度设置失败: " + error); - } + state.logPanelRefresh = new Runnable() { + @Override + public void run() { + refreshList(state); + } + }; wire(loader, refresh, new Runnable() { @Override public void run() { @@ -191,6 +188,28 @@ public final class ObjectPanel { return root; } + /** 在内容表格末尾追加"日志块"(分隔行 + 最近几条消息)。 */ + private static void appendLogRows(State state) { + try { + Class cellClass = Class.forName(Obf.CELL, true, state.loader); + Class actorClass = Class.forName(Obf.ACTOR, true, state.loader); + Object cell = call(state.listTable, Obf.TABLE_ADD, new Class[] {actorClass}, + cellClass, label(state.loader, state.skin, "---------- log ----------")); + layoutCell(cell, Obf.CELL_LEFT); + call(state.listTable, Obf.TABLE_ROW, new Class[0], cellClass); + synchronized (state.log) { + for (String line : state.log) { + cell = call(state.listTable, Obf.TABLE_ADD, new Class[] {actorClass}, + cellClass, label(state.loader, state.skin, line)); + layoutCell(cell, Obf.CELL_LEFT); + call(state.listTable, Obf.TABLE_ROW, new Class[0], cellClass); + } + } + } catch (Throwable error) { + System.err.println("[panel] 日志块追加失败: " + error); + } + } + /** 状态文字:作为列表区的第一行显示(这样不再单独占根表格的一行,布局更稳)。 */ private static void statusRow(final State state, final String text) { try { @@ -212,6 +231,7 @@ public final class ObjectPanel { @Override public void run() { List objects; + state.rendering = true; try { objects = SceneObjects.listAllNodes(state.loader); } catch (Throwable error) { @@ -222,9 +242,6 @@ public final class ObjectPanel { try { // Table.clearChildren()(载荷名 `SourceFile()V`):把列表里的行全清掉重建。 call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class[0], void.class); - setStatus(state, objects.size() + " scene objects" - + (state.target == null ? "" : "; target = " + SceneObjects.kind(state.target) - + " " + SceneObjects.nameOf(state.target))); Class cellClass = Class.forName(Obf.CELL, true, state.loader); Class actorClass = Class.forName(Obf.ACTOR, true, state.loader); for (int i = 0; i < objects.size() && i < 300; i++) { @@ -246,6 +263,11 @@ public final class ObjectPanel { setStatus(state, "List build failed: " + error); return; } + setStatus(state, objects.size() + " scene objects" + + (state.target == null ? "" : "; target = " + SceneObjects.kind(state.target) + + " " + SceneObjects.nameOf(state.target))); + state.rendering = false; + appendLogRows(state); invalidateList(state); } }); @@ -389,6 +411,8 @@ public final class ObjectPanel { layoutCell(cell, Obf.CELL_LEFT); call(state.listTable, Obf.TABLE_ROW, new Class[0], cellClass); } + state.rendering = false; + appendLogRows(state); invalidateList(state); } catch (Throwable error) { System.err.println("[panel] inspector 填充失败: " + error); @@ -408,29 +432,12 @@ public final class ObjectPanel { private static void setStatus(final State state, final String text) { state.statusText = text; System.err.println("[panel] " + text); - if (state.status == null) return; synchronized (state.log) { state.log.addLast(text); while (state.log.size() > LOG_LINES) state.log.removeFirst(); } - final StringBuilder joined = new StringBuilder(); - synchronized (state.log) { - for (String line : state.log) { - if (joined.length() > 0) joined.append('\n'); - joined.append(line); - } - } - SceneActions.onEditorThread(state.loader, new Runnable() { - @Override - public void run() { - try { - call(state.status, Obf.LABEL_SET_TEXT, new Class[] {CharSequence.class}, - void.class, joined.toString()); - } catch (Throwable error) { - System.err.println("[panel] 提示区更新失败: " + error); - } - } - }); + // 没在渲染中就立刻把日志块刷出来(渲染中则由那次渲染带上,避免递归重排) + if (!state.rendering && state.logPanelRefresh != null) state.logPanelRefresh.run(); } /** TextField 里的文字(名字被混淆了,按"无参 + 返回 String"取)。 */