changeset 4030:861cc97175cb

3DViewer: Implemented "Show hierarchy" feature.
author Alexander Kouznetsov
date Fri, 21 Jun 2013 13:44:34 -0700
parents 7ba42dc66b10
children f78fc2ff7c9a
files apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/ContentModel.java apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/MainController.java apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SessionManager.java apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SettingsController.java apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/settings.fxml
diffstat 5 files changed, 100 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/ContentModel.java	Fri Jun 21 10:15:34 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/ContentModel.java	Fri Jun 21 13:44:34 2013 -0700
@@ -56,6 +56,7 @@
 import javafx.scene.transform.Translate;
 import com.javafx.experiments.shape3d.PolygonMeshView;
 import com.javafx.experiments.shape3d.SubDivision;
+import javafx.beans.property.ObjectProperty;
 
 /**
  * 3D Content Model for Viewer App. Contains the 3D scene and everything related to it: light, cameras etc.
@@ -70,7 +71,7 @@
     private final Rotate cameraLookZRotate = new Rotate(0,0,0,0,Rotate.Z_AXIS);
     private final Translate cameraPosition = new Translate(0,0,-7);
     private double dragStartX, dragStartY, dragStartRotateX, dragStartRotateY;
-    private Node content;
+    private ObjectProperty<Node> content = new SimpleObjectProperty<>();
     private AutoScalingGroup autoScalingGroup = new AutoScalingGroup(2);
     private Box xAxis,yAxis,zAxis;
     private AmbientLight ambientLight = new AmbientLight(Color.DARKGREY);
@@ -293,19 +294,24 @@
         return autoScalingGroup;
     }
 
-    public Node get3dContent() {
-        return this.content;
-    }
+    public ObjectProperty<Node> contentProperty() { return content; }
+    public Node getContent() { return content.get(); }
+    public void setContent(Node content) { this.content.set(content); }
 
-    public void set3dContent(Node content) {
-        autoScalingGroup.getChildren().remove(this.content);
-        this.content = content;
-        autoScalingGroup.getChildren().add(this.content);
-        setWireFrame(content,wireframe);
-        // TODO mesh is updated each time these are called even if no rendering needs to happen
-        setSubdivisionLevel(content, subdivisionLevel);
-        setBoundaryMode(content, boundaryMode);
-        setMapBorderMode(content, mapBorderMode);
+    {
+        contentProperty().addListener(new ChangeListener<Node>() {
+
+            @Override
+            public void changed(ObservableValue<? extends Node> ov, Node oldContent, Node newContent) {
+                autoScalingGroup.getChildren().remove(oldContent);
+                autoScalingGroup.getChildren().add(newContent);
+                setWireFrame(newContent,wireframe);
+                // TODO mesh is updated each time these are called even if no rendering needs to happen
+                setSubdivisionLevel(newContent, subdivisionLevel);
+                setBoundaryMode(newContent, boundaryMode);
+                setMapBorderMode(newContent, mapBorderMode);
+            }
+        });
     }
 
     public SubScene getSubScene() {
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/MainController.java	Fri Jun 21 10:15:34 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/MainController.java	Fri Jun 21 13:44:34 2013 -0700
@@ -227,7 +227,7 @@
             if (optimizeCheckBox.isSelected()) {
                 new Optimizer(timeline, root, true).optimize();
             }
-            contentModel.set3dContent(root);
+            contentModel.setContent(root);
             contentModel.setTimeline(timeline);
 
             if (timeline != null) {
@@ -245,7 +245,7 @@
         meshCount = 0;
         triangleCount = 0;
         updateCount(contentModel.getRoot3D());
-        Node content = contentModel.get3dContent();
+        Node content = contentModel.getContent();
         final Bounds bounds = content == null ? new BoundingBox(0, 0, 0, 0) : content.getBoundsInLocal();
         status.setText(
                 String.format("Nodes [%d] :: Meshes [%d] :: Triangles [%d] :: " +
@@ -317,12 +317,12 @@
 
                 JavaSourceExporter javaSourceExporter = new JavaSourceExporter(
                         baseUrl,
-                        contentModel.get3dContent(),
+                        contentModel.getContent(),
                         contentModel.getTimeline(),
                         newFile);
                 javaSourceExporter.export();
             } else if ("fxml".equals(extension)) {
-                new FXMLExporter(newFile.getAbsolutePath()).export(contentModel.get3dContent());
+                new FXMLExporter(newFile.getAbsolutePath()).export(contentModel.getContent());
             } else {
                 System.err.println("Can not export a file of type [."+extension+"]");
             }
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SessionManager.java	Fri Jun 21 10:15:34 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SessionManager.java	Fri Jun 21 13:44:34 2013 -0700
@@ -139,7 +139,7 @@
     public void bind(final ToggleGroup toggleGroup, final String propertyName) {
         String selectedToggle = props.getProperty(propertyName);
         for (Toggle t : toggleGroup.getToggles()) {
-            if (t.getUserData().equals(selectedToggle)) {
+            if (t.getUserData() != null && t.getUserData().equals(selectedToggle)) {
                 if (toggleGroup.getSelectedToggle() != t) {
                     toggleGroup.selectToggle(t);
                 }
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SettingsController.java	Fri Jun 21 10:15:34 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SettingsController.java	Fri Jun 21 13:44:34 2013 -0700
@@ -47,6 +47,14 @@
 import javafx.scene.control.ToggleGroup;
 import javafx.scene.paint.Color;
 import com.javafx.experiments.shape3d.SubDivision;
+import javafx.beans.binding.ObjectBinding;
+import javafx.scene.Node;
+import javafx.scene.Parent;
+import javafx.scene.control.TreeItem;
+import javafx.scene.control.TreeTableColumn;
+import javafx.scene.control.TreeTableView;
+import javafx.scene.control.cell.CheckBoxTreeTableCell;
+import javafx.util.Callback;
 
 /**
  * Controller class for settings panel
@@ -82,6 +90,10 @@
     public ToggleGroup subdivisionLevelGroup;
     public ToggleGroup subdivisionBoundaryGroup;
     public ToggleGroup subdivisionSmoothGroup;
+    public TreeTableView<Node> hierarachyTreeTable;
+    public TreeTableColumn<Node, String> nodeColumn;
+    public TreeTableColumn<Node, String> idColumn;
+    public TreeTableColumn<Node, Boolean> visibilityColumn;
     
     @Override public void initialize(URL location, ResourceBundle resources) {
         // keep one pane open always
@@ -199,6 +211,45 @@
         fovSlider.setValue(contentModel.getCamera().getFieldOfView());
         contentModel.getCamera().fieldOfViewProperty().bind(fovSlider.valueProperty());
 
+        hierarachyTreeTable.rootProperty().bind(new ObjectBinding<TreeItem<Node>>() {
+
+            {
+                bind(contentModel.contentProperty());
+            }
+
+            @Override
+            protected TreeItem<Node> computeValue() {
+                Node content3D = contentModel.getContent();
+                if (content3D != null) {
+                    return new TreeItemImpl(content3D);
+                } else {
+                    return null;
+                }
+            }
+        });
+        nodeColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<Node, String>, ObservableValue<String>>() {
+
+            @Override
+            public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<Node, String> p) {
+                return p.getValue().valueProperty().asString();
+            }
+        });
+        idColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<Node, String>, ObservableValue<String>>() {
+
+            @Override
+            public ObservableValue<String> call(TreeTableColumn.CellDataFeatures<Node, String> p) {
+                return p.getValue().getValue().idProperty();
+            }
+        });
+        visibilityColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<Node, Boolean>, ObservableValue<Boolean>>() {
+
+            @Override
+            public ObservableValue<Boolean> call(TreeTableColumn.CellDataFeatures<Node, Boolean> p) {
+                return p.getValue().getValue().visibleProperty();
+            }
+        });
+        visibilityColumn.setCellFactory(CheckBoxTreeTableCell.forTreeTableColumn(visibilityColumn));
+
         SessionManager sessionManager = SessionManager.getSessionManager();
 
         sessionManager.bind(showAxisCheckBox.selectedProperty(), "showAxis");
@@ -231,6 +282,15 @@
         sessionManager.bind(settings, "settingsPane");
     }
 
+    private class TreeItemImpl extends TreeItem<Node> {
 
-
+        public TreeItemImpl(Node node) {
+            super(node);
+            if (node instanceof Parent) {
+                for (Node n : ((Parent) node).getChildrenUnmodifiable()) {
+                    getChildren().add(new TreeItemImpl(n));
+                }
+            }
+        }
+    }
 }
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/settings.fxml	Fri Jun 21 10:15:34 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/settings.fxml	Fri Jun 21 13:44:34 2013 -0700
@@ -46,7 +46,20 @@
 
 <Accordion fx:id="settings" minWidth="0.0" prefHeight="798.0" prefWidth="279.0" xmlns:fx="http://javafx.com/fxml" fx:controller="com.javafx.experiments.jfx3dviewer.SettingsController">
   <expandedPane>
-    <TitledPane fx:id="x4" animated="false" expanded="true" text="Options">
+    <TitledPane fx:id="x5" animated="false" expanded="true" text="Hierarchy">
+      <content>
+        <TreeTableView fx:id="hierarachyTreeTable" editable="true" prefHeight="200.0" prefWidth="200.0">
+          <columns>
+            <TreeTableColumn fx:id="nodeColumn" editable="false" prefWidth="75.0" sortable="false" text="Node" />
+            <TreeTableColumn fx:id="idColumn" prefWidth="75.0" text="Id" />
+            <TreeTableColumn fx:id="visibilityColumn" editable="true" maxWidth="5000.0" minWidth="10.0" prefWidth="26.0" sortable="false" text="Visibility" />
+          </columns>
+        </TreeTableView>
+      </content>
+    </TitledPane>
+  </expandedPane>
+  <panes>
+    <TitledPane fx:id="x4" animated="false" expanded="false" text="Options">
       <content>
         <GridPane hgap="5.0" styleClass="settings" vgap="5.0">
           <children>
@@ -152,9 +165,6 @@
         </GridPane>
       </content>
     </TitledPane>
-  </expandedPane>
-  <panes>
-    <fx:reference source="x4" />
     <TitledPane fx:id="x2" animated="false" text="Lights">
       <content>
         <ScrollPane fitToWidth="true" prefHeight="200.0" prefWidth="200.0">
@@ -252,5 +262,6 @@
         </GridPane>
       </content>
     </TitledPane>
+    <fx:reference source="x5" />
   </panes>
 </Accordion>