Skip to content

Commit 8a549f6

Browse files
committed
Закончина реализация простого редактора моделей
1 parent 1a2a97f commit 8a549f6

File tree

7 files changed

+167
-10
lines changed

7 files changed

+167
-10
lines changed

resources/ui/css/custom_classes.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@
4949
-fx-background-color: transparent;
5050
-fx-background-insets: 0;
5151
-fx-border-color: transparent;
52-
-fx-padding: -5;
52+
-fx-padding: 0;
5353
-fx-effect: null;
5454
}
5555

5656
.transparent-tree-view:focused {
5757
-fx-background-color: transparent;
5858
-fx-background-insets: 0;
5959
-fx-border-color: transparent;
60-
-fx-padding: -5;
60+
-fx-padding: 0;
6161
-fx-effect: null;
6262
}
6363

resources/ui/css/custom_ids.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@
295295
-fx-min-height: 25;
296296
-fx-pref-height: -fx-min-height;
297297
-fx-max-height: -fx-min-height;
298-
-fx-background: transparent;
299298
}
300299

301300
#ModelNodeTreeCellDragged {

src/com/ss/editor/state/editor/impl/model/ModelEditorState.java

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@
55
import com.jme3.bounding.BoundingBox;
66
import com.jme3.bounding.BoundingSphere;
77
import com.jme3.bounding.BoundingVolume;
8+
import com.jme3.collision.CollisionResult;
9+
import com.jme3.collision.CollisionResults;
810
import com.jme3.effect.ParticleEmitter;
911
import com.jme3.environment.generation.JobProgressAdapter;
1012
import com.jme3.input.ChaseCamera;
13+
import com.jme3.input.InputManager;
14+
import com.jme3.input.MouseInput;
15+
import com.jme3.input.controls.ActionListener;
16+
import com.jme3.input.controls.MouseButtonTrigger;
1117
import com.jme3.light.DirectionalLight;
1218
import com.jme3.light.LightProbe;
1319
import com.jme3.material.Material;
1420
import com.jme3.math.ColorRGBA;
21+
import com.jme3.math.Ray;
22+
import com.jme3.math.Vector2f;
23+
import com.jme3.math.Vector3f;
24+
import com.jme3.renderer.Camera;
1525
import com.jme3.scene.Geometry;
1626
import com.jme3.scene.Mesh;
1727
import com.jme3.scene.Node;
@@ -20,6 +30,7 @@
2030
import com.jme3.scene.debug.WireBox;
2131
import com.jme3.scene.debug.WireSphere;
2232
import com.ss.editor.state.editor.impl.AbstractEditorState;
33+
import com.ss.editor.ui.component.editor.impl.model.ModelFileEditor;
2334

2435
import rlib.geom.util.AngleUtils;
2536

@@ -46,6 +57,16 @@ public void done(final LightProbe result) {
4657
}
4758
};
4859

60+
/**
61+
* Слушатель кликов мышкой по области редактора.
62+
*/
63+
private final ActionListener actionListener = (name, isPressed, tpf) -> processClick(isPressed);
64+
65+
/**
66+
* Редактор в который встроен этот стейт.
67+
*/
68+
private final ModelFileEditor editor;
69+
4970
/**
5071
* Узел для размещения модели.
5172
*/
@@ -111,7 +132,8 @@ public void done(final LightProbe result) {
111132
*/
112133
private int frame;
113134

114-
public ModelEditorState() {
135+
public ModelEditorState(final ModelFileEditor editor) {
136+
this.editor = editor;
115137
this.modelNode = new Node("ModelNode");
116138
this.modelNode.setUserData(ModelEditorState.class.getName(), true);
117139
this.toolNode = new Node("ToolNode");
@@ -130,6 +152,62 @@ public ModelEditorState() {
130152
setShowGrid(true);
131153
}
132154

155+
/**
156+
* @return слушатель кликов мышкой по области редактора.
157+
*/
158+
private ActionListener getActionListener() {
159+
return actionListener;
160+
}
161+
162+
/**
163+
* Обработка клика мышкой по области редактора.
164+
*/
165+
private void processClick(final boolean isPressed) {
166+
167+
if(!isPressed) {
168+
return;
169+
}
170+
171+
final Camera camera = EDITOR.getCamera();
172+
173+
final InputManager inputManager = EDITOR.getInputManager();
174+
final Vector2f cursor = inputManager.getCursorPosition();
175+
final Vector3f click3d = camera.getWorldCoordinates(cursor, 0f);
176+
final Vector3f dir = camera.getWorldCoordinates(cursor, 1f).subtractLocal(click3d).normalizeLocal();
177+
178+
final Ray ray = new Ray();
179+
ray.setOrigin(click3d);
180+
ray.setDirection(dir);
181+
182+
final CollisionResults results = new CollisionResults();
183+
184+
final Node modelNode = getModelNode();
185+
modelNode.collideWith(ray, results);
186+
187+
final ModelFileEditor editor = getEditor();
188+
189+
if(results.size() < 1) {
190+
EXECUTOR_MANAGER.addFXTask(() -> editor.notifySelected(null));
191+
return;
192+
}
193+
194+
final CollisionResult collision = results.getClosestCollision();
195+
196+
if(collision == null) {
197+
EXECUTOR_MANAGER.addFXTask(() -> editor.notifySelected(null));
198+
return;
199+
}
200+
201+
EXECUTOR_MANAGER.addFXTask(() -> editor.notifySelected(collision.getGeometry()));
202+
}
203+
204+
/**
205+
* @return редактор в который встроен этот стейт.
206+
*/
207+
private ModelFileEditor getEditor() {
208+
return editor;
209+
}
210+
133211
/**
134212
* Создание вспомогательных элементов.
135213
*/
@@ -264,6 +342,16 @@ public void initialize(final AppStateManager stateManager, final Application app
264342
super.initialize(stateManager, application);
265343

266344
frame = 0;
345+
346+
final String mappingName = getClass().getName() + "_click";
347+
348+
final InputManager inputManager = EDITOR.getInputManager();
349+
350+
if(!inputManager.hasMapping(mappingName)) {
351+
inputManager.addMapping(mappingName, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
352+
}
353+
354+
inputManager.addListener(getActionListener(), mappingName);
267355
}
268356

269357
@Override
@@ -273,6 +361,9 @@ public void cleanup() {
273361
final Node stateNode = getStateNode();
274362
stateNode.detachChild(getModelNode());
275363
stateNode.detachChild(getToolNode());
364+
365+
final InputManager inputManager = EDITOR.getInputManager();
366+
inputManager.removeListener(getActionListener());
276367
}
277368

278369
@Override

src/com/ss/editor/ui/component/editor/impl/model/ModelFileEditor.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public class ModelFileEditor extends AbstractFileEditor<StackPane> {
128128
private boolean ignoreListeners;
129129

130130
public ModelFileEditor() {
131-
this.editorState = new ModelEditorState();
131+
this.editorState = new ModelEditorState(this);
132132
addEditorState(editorState);
133133
}
134134

@@ -170,7 +170,7 @@ public void openFile(final Path file) {
170170
super.openFile(file);
171171

172172
final Path assetFile = EditorUtil.getAssetFile(file);
173-
final ModelKey modelKey = new ModelKey(assetFile.toString());
173+
final ModelKey modelKey = new ModelKey(EditorUtil.toClasspath(assetFile));
174174

175175
final AssetManager assetManager = EDITOR.getAssetManager();
176176
assetManager.clearCache();
@@ -212,7 +212,7 @@ private void setIgnoreListeners(final boolean ignoreListeners) {
212212
/**
213213
* @param currentModel текущая модель.
214214
*/
215-
private void setCurrentModel(Spatial currentModel) {
215+
private void setCurrentModel(final Spatial currentModel) {
216216
this.currentModel = currentModel;
217217
}
218218

@@ -238,6 +238,7 @@ public void doSave() {
238238
}
239239

240240
setDirty(false);
241+
notifyFileChanged();
241242
}
242243

243244
@Override
@@ -271,7 +272,22 @@ protected void createContent(final StackPane root) {
271272
/**
272273
* Обработка выделения узла в дереве.
273274
*/
274-
private void processSelect(final Object object) {
275+
public void notifySelected(final Object object) {
276+
277+
Spatial spatial = null;
278+
279+
if(object instanceof Spatial) {
280+
spatial = (Spatial) object;
281+
}
282+
283+
final ModelNodeTree modelNodeTree = getModelNodeTree();
284+
modelNodeTree.select(object);
285+
}
286+
287+
/**
288+
* Обработка выделения узла в дереве.
289+
*/
290+
public void processSelect(final Object object) {
275291

276292
Spatial spatial = null;
277293

src/com/ss/editor/ui/control/model/property/ModelPropertyEditor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ public void buildFor(final Object object) {
6969
final ObservableList<Node> children = container.getChildren();
7070
children.clear();
7171

72-
PropertyBuilder.buildFor(object, container, getChangeHandler());
72+
if(object != null) {
73+
PropertyBuilder.buildFor(object, container, getChangeHandler());
74+
}
7375

7476
setCurrentObject(object);
7577
}

src/com/ss/editor/ui/control/model/tree/ModelNodeTree.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ private void createContent() {
6767

6868
treeView = new TreeView<>();
6969
treeView.setCellFactory(param -> new ModelNodeTreeCell(this));
70+
treeView.setShowRoot(true);
7071
treeView.setEditable(true);
72+
treeView.setFocusTraversable(true);
7173

7274
final MultipleSelectionModel<TreeItem<ModelNode<?>>> selectionModel = treeView.getSelectionModel();
7375
selectionModel.selectedItemProperty().addListener((observable, oldValue, newValue) -> processSelect(newValue));
@@ -93,6 +95,13 @@ private Consumer<Object> getSelectionHandler() {
9395
*/
9496
private void processSelect(final TreeItem<ModelNode<?>> treeItem) {
9597

98+
final Consumer<Object> selectionHandler = getSelectionHandler();
99+
100+
if(treeItem == null) {
101+
selectionHandler.accept(null);
102+
return;
103+
}
104+
96105
final ModelNode<?> value = treeItem.getValue();
97106
final Object element = value == null? null : value.getElement();
98107

@@ -108,7 +117,6 @@ private void processSelect(final TreeItem<ModelNode<?>> treeItem) {
108117
toSelect = parentElement.getElement();
109118
}
110119

111-
final Consumer<Object> selectionHandler = getSelectionHandler();
112120
selectionHandler.accept(toSelect);
113121
}
114122

@@ -272,4 +280,29 @@ public void startEdit(final ModelNode<?> modelNode) {
272280

273281
treeView.edit(treeItem);
274282
}
283+
284+
/**
285+
* Выделение указанного объекта в дереве.
286+
*/
287+
public void select(final Object object) {
288+
289+
final TreeView<ModelNode<?>> treeView = getTreeView();
290+
final MultipleSelectionModel<TreeItem<ModelNode<?>>> selectionModel = treeView.getSelectionModel();
291+
292+
final ModelNode<Object> modelNode = ModelNodeFactory.createFor(object);
293+
294+
if(modelNode == null) {
295+
selectionModel.select(null);
296+
return;
297+
}
298+
299+
final TreeItem<ModelNode<?>> treeItem = findItemForValue(treeView, modelNode);
300+
301+
if(treeItem == null) {
302+
selectionModel.select(null);
303+
return;
304+
}
305+
306+
selectionModel.select(treeItem);
307+
}
275308
}

src/com/ss/editor/ui/control/model/tree/node/ModelNode.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,20 @@ public String toString() {
134134
", element=" + element +
135135
'}';
136136
}
137+
138+
@Override
139+
public boolean equals(Object o) {
140+
141+
if (this == o) return true;
142+
if (o == null || getClass() != o.getClass()) return false;
143+
144+
ModelNode<?> modelNode = (ModelNode<?>) o;
145+
146+
return !(element != null ? !element.equals(modelNode.element) : modelNode.element != null);
147+
}
148+
149+
@Override
150+
public int hashCode() {
151+
return element != null ? element.hashCode() : 0;
152+
}
137153
}

0 commit comments

Comments
 (0)