feat(render): 实现模型图层管理与选中高亮功能
- 添加 ModelLayerPanel 图层管理面板,支持图层增删、重排、重命名- 实现 Mesh2D 选中状态管理与可视化高亮边框绘制 - 添加模型点击与悬停事件监听接口 ModelClickListener - 引入完整着色器接口 CompleteShader 及默认片段着色器实现 - 改进 BufferUploader 支持颜色 uniform 传递- 完善 Mesh2D 复制逻辑与边界框计算方法 - 重构部分工具类包路径并增强矩阵工具功能 - 移除 LightSourceData 中冗余的构造逻辑 重要更新 - 更新了一个可视化界面可以控制图层顺序(ModelLayerPanel),并且给ModelRenderPanel增加了很多新功能,比如设置模型图层位置、大小 - 重写了逻辑着色器(Shader)、BufferUploader逻辑,让着色器能够规范的注册和使用
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package com.chuangzhou.vivid2D.test;
|
||||
|
||||
import com.chuangzhou.vivid2D.render.awt.ModelClickListener;
|
||||
import com.chuangzhou.vivid2D.render.awt.ModelLayerPanel;
|
||||
import com.chuangzhou.vivid2D.render.awt.ModelRenderPanel;
|
||||
import com.chuangzhou.vivid2D.render.model.Model2D;
|
||||
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
||||
import com.chuangzhou.vivid2D.render.model.util.Mesh2D;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* 简单的测试示例:创建一个 Model2D,添加几层(部件),
|
||||
* 然后在 JFrame 中展示 ModelLayerPanel(左侧)、ModelRenderPanel(中间渲染区)
|
||||
* 和模型树(右侧)以便观察变化。
|
||||
*/
|
||||
public class ModelLayerPanelTest {
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
// 创建示例模型并添加图层
|
||||
Model2D model = new Model2D("示例模型");
|
||||
|
||||
// 调整一些初始属性(可选)
|
||||
ModelPart person = model.getPart("人物");
|
||||
if (person != null) {
|
||||
try {
|
||||
person.setOpacity(0.85f);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
// 创建 UI
|
||||
JFrame frame = new JFrame("ModelLayerPanel 测试(含渲染面板)");
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
frame.setLayout(new BorderLayout());
|
||||
|
||||
// 左侧:图层面板(传入 renderPanel 后可在面板中绑定贴图到 GL 上下文)
|
||||
// 先创建一个占位 renderPanel,再把它传给 layerPanel(ModelRenderPanel 构造需要尺寸)
|
||||
ModelRenderPanel renderPanel = new ModelRenderPanel(model, 640, 480);
|
||||
//renderPanel.addModelClickListener(new ModelClickListener() {
|
||||
// @Override
|
||||
// public void onModelClicked(Mesh2D mesh, float modelX, float modelY, int screenX, int screenY) {
|
||||
// if (mesh == null) return;
|
||||
// System.out.println("点击了模型:" + mesh.getName() + ",模型坐标:" + modelX + ", " + modelY + ",屏幕坐标:" + screenX + ", " + screenY);
|
||||
// }
|
||||
//});
|
||||
ModelLayerPanel layerPanel = new ModelLayerPanel(model, renderPanel);
|
||||
layerPanel.setPreferredSize(new Dimension(260, 600));
|
||||
frame.add(layerPanel, BorderLayout.WEST);
|
||||
|
||||
// 中间:渲染面板
|
||||
renderPanel.setPreferredSize(new Dimension(640, 480));
|
||||
frame.add(renderPanel, BorderLayout.CENTER);
|
||||
|
||||
// 右侧:显示模型树(用于观察当前模型部件结构)
|
||||
JTree tree = new JTree(model.toTreeNode());
|
||||
JScrollPane treeScroll = new JScrollPane(tree);
|
||||
treeScroll.setPreferredSize(new Dimension(240, 600));
|
||||
frame.add(treeScroll, BorderLayout.EAST);
|
||||
|
||||
// 底部:演示按钮(刷新树以反映面板中对模型的更改)
|
||||
JPanel bottom = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
JButton refreshBtn = new JButton("刷新模型树");
|
||||
refreshBtn.addActionListener(e -> {
|
||||
tree.setModel(new javax.swing.tree.DefaultTreeModel(model.toTreeNode()));
|
||||
for (int i = 0; i < tree.getRowCount(); i++) tree.expandRow(i);
|
||||
// 同步通知渲染面板(如果需要)去刷新模型
|
||||
try {
|
||||
renderPanel.setModel(model);
|
||||
} catch (Exception ignored) {}
|
||||
});
|
||||
bottom.add(refreshBtn);
|
||||
|
||||
JButton printOrderBtn = new JButton("打印部件顺序(控制台)");
|
||||
printOrderBtn.addActionListener(e -> {
|
||||
System.out.println("当前模型部件顺序:");
|
||||
for (ModelPart p : model.getParts()) {
|
||||
System.out.println(" - " + p.getName() + " (可见=" + p.isVisible() + ", 不透明度=" + p.getOpacity() + ")");
|
||||
}
|
||||
});
|
||||
bottom.add(printOrderBtn);
|
||||
|
||||
frame.add(bottom, BorderLayout.SOUTH);
|
||||
|
||||
// 监听窗口关闭,确保释放 GL 资源
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent e) {
|
||||
// 先释放渲染面板相关 GL 资源与线程
|
||||
try {
|
||||
renderPanel.dispose();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(java.awt.event.WindowEvent e) {
|
||||
// 进程退出(确保彻底关闭)
|
||||
try {
|
||||
renderPanel.dispose();
|
||||
} catch (Throwable ignored) {}
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
frame.setSize(1200, 700);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user