Commit 0ecf4b14 authored by Ivan Dages's avatar Ivan Dages
Browse files

component subdivision

parent 894c287d
......@@ -22,5 +22,10 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
package fr.ill.ics.n3d.gui;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.LinkedList;
import java.util.Optional;
import java.util.logging.Logger;
import org.apache.commons.io.FilenameUtils;
import fr.ill.ics.n3d.Nomad3DEditor;
import fr.ill.ics.n3d.io.Nomad3DExporter;
import fr.ill.ics.n3d.io.Nomad3DImporter;
......@@ -19,6 +22,7 @@ import fr.ill.ics.n3d.model.Axis.Type;
import fr.ill.ics.n3d.model.Component;
import fr.ill.ics.n3d.model.ConfigParams;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
......@@ -59,8 +63,10 @@ import javafx.scene.input.KeyCombination;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.text.TextAlignment;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.FileChooser.ExtensionFilter;
/**
* Menu bar of the Nomad3DEditor.getInstance().
......@@ -109,6 +115,17 @@ public class EditorMenuBar extends MenuBar {
private int activeLod;
private class SubdividedChild {
SimpleStringProperty name = new SimpleStringProperty();
SimpleStringProperty path = new SimpleStringProperty();
@Override
public String toString() {
return "SubdividedChild [name=" + name.get() + ", path=" + path.get() + "]";
}
}
LinkedList<SubdividedChild> subdividedChilds;
/**
* Constructor.
* @param Nomad3DEditor.getInstance() Editor owning the menu bar
......@@ -120,6 +137,7 @@ public class EditorMenuBar extends MenuBar {
this.focusSelection = false;
this.activeConfiguration = null;
this.activeLod = 0;
this.subdividedChilds = new LinkedList<>();
this.file = new Menu("File");
MenuItem openItem = new MenuItem("Open");
......@@ -976,11 +994,208 @@ public class EditorMenuBar extends MenuBar {
});
MenuItem subdivideComponentItem = new MenuItem("Subdivide component");
subdivideComponentItem.setOnAction(event -> {
// TODO subdivide ui
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle(subdivideComponentItem.getText());
alert.setContentText(subdivideComponentItem.getText() + " TODO");
alert.showAndWait();
if (!modelLoaded()) {
return;
}
Component selectedComponent = selectComponent(subdivideComponentItem.getText());
if (selectedComponent == null) {
return;
}
Alert confirmAlert = new Alert(AlertType.CONFIRMATION);
confirmAlert.setTitle(subdivideComponentItem.getText());
confirmAlert.setContentText("Subdividing a component will remove its geometry.");
Optional<ButtonType> res = confirmAlert.showAndWait();
if (res.get() != ButtonType.OK) {
return;
}
this.subdividedChilds.clear();
GridPane scenePane = new GridPane();
scenePane.setAlignment(Pos.TOP_CENTER);
Scene subdivScene = new Scene(scenePane);
Stage subdivStage = new Stage(StageStyle.UTILITY);
subdivStage.setTitle(modifyMaterialItem.getText());
subdivStage.setScene(subdivScene);
subdivStage.initOwner(Nomad3DEditor.getInstance().getStage());
final double lineHeight = 30;
GridPane childPane = new GridPane();
childPane.setVgap(5);
childPane.setHgap(10);
childPane.setAlignment(Pos.CENTER);
scenePane.addRow(0, childPane);
childPane.setPrefHeight(2*lineHeight);
GridPane.setMargin(childPane, new Insets(10));
Label childLabel = new Label("Children : ");
childLabel.setPrefWidth(500);
Label nameLabel = new Label("Name");
nameLabel.setPrefWidth((childLabel.getPrefWidth() - childPane.getHgap())/2);
nameLabel.setAlignment(Pos.CENTER);
nameLabel.setTextAlignment(TextAlignment.CENTER);
Label meshLabel = new Label("STL file");
meshLabel.setPrefWidth((childLabel.getPrefWidth() - childPane.getHgap())/2);
meshLabel.setAlignment(Pos.CENTER);
meshLabel.setTextAlignment(TextAlignment.CENTER);
Button addButton = new Button("Add");
addButton.setPrefSize(40, lineHeight);
addButton.setAlignment(Pos.CENTER_RIGHT);
addButton.setTextAlignment(TextAlignment.CENTER);
addButton.setOnAction(addEvent -> {
SubdividedChild newChild = new SubdividedChild();
subdividedChilds.push(newChild);
int colCount = 20;
TextField nameField = new TextField();
nameField.setPrefColumnCount(colCount);
nameField.setPrefHeight(lineHeight);
newChild.name.bind(nameField.textProperty());
TextField meshField = new TextField();
meshField.setPrefColumnCount(colCount);
meshField.setPrefHeight(lineHeight);
newChild.path.bind(meshField.textProperty());
Button browseButton = new Button("Browse files");
browseButton.setPrefSize(80, lineHeight);
browseButton.setOnAction(browseEvent -> {
FileChooser chooser = new FileChooser();
chooser.setTitle("Open model");
if (!meshField.getText().isEmpty()) {
File meshFile = new File(meshField.getText());
if (meshFile.exists() && meshFile.getParentFile() != null && meshFile.getParentFile().exists()) {
chooser.setInitialDirectory(meshFile.getParentFile());
}
}
chooser.getExtensionFilters().addAll(new ExtensionFilter("STL files", "*.STL"));
File selectedFile = chooser.showOpenDialog(null);
if (selectedFile != null) {
meshField.setText(selectedFile.getAbsolutePath());
if (nameField.getText().isEmpty()) {
nameField.setText(FilenameUtils.removeExtension(selectedFile.getName()));
}
}
});
childPane.addRow(subdividedChilds.size()+1, nameField, meshField, browseButton);
childPane.setPrefHeight(childPane.getPrefHeight() + lineHeight);
subdivStage.setHeight(subdivStage.getHeight() + lineHeight);
});
childPane.addColumn(0, childLabel);
childPane.addColumn(2, addButton);
GridPane.setColumnSpan(childLabel, 2);
GridPane.setMargin(addButton, new Insets(0, 0, 0, 40));
childPane.addRow(1, nameLabel, meshLabel);
childPane.setPrefWidth(childLabel.getPrefWidth() + 2*addButton.getPrefWidth() + 2*childPane.getHgap());
int initLines = 1;
for (int i = 0 ; i < initLines ; i++) {
addButton.getOnAction().handle(null);
}
GridPane buttonsPane = new GridPane();
buttonsPane.setVgap(5);
buttonsPane.setHgap(10);
buttonsPane.setAlignment(Pos.CENTER);
scenePane.addRow(1, buttonsPane);
GridPane.setMargin(buttonsPane, new Insets(10));
Button okButton = new Button("OK");
okButton.setDefaultButton(true);
okButton.setOnAction(okEvent -> {
try {
// TODO remove traces
System.out.println(subdividedChilds);
Path tmpDirPath = Files.createTempDirectory("nomad-3d-editor-subdivision-");
File tmpDir = tmpDirPath.toFile();
tmpDir.deleteOnExit();
Logger.getLogger("nomad-3d").info("Creating temporary directory " + tmpDirPath + " for STL files");
for (SubdividedChild child : subdividedChilds) {
try {
File inFile = new File(child.path.get());
File tmpFile = new File(tmpDir, inFile.getName());
Files.copy(inFile.toPath(), tmpFile.toPath());
tmpFile.deleteOnExit();
Logger.getLogger("nomad-3d").info("Copy : " + inFile + " --> " + tmpFile);
} catch (Exception e) {
// Empty fields are ignored
if (!child.name.get().isEmpty() && !child.path.get().isEmpty()) {
Logger.getLogger("nomad-3d").severe(e.getMessage());
e.printStackTrace();
}
}
}
// Convert geometries
File modelDir = new File(Nomad3DEditor.getInstance().getModel().getDirectoryPath());
String blenderExe = "blender";
if (System.getProperty("os.name").toUpperCase().startsWith("WIN")) {
blenderExe = "C:\\Program Files\\Blender Foundation\\Blender\\blender.exe";
}
// TODO get this from somewhere
double decimateRatio = 0.5;
String converterPath = ".." + File.separator + "nomad-3d-converter";
// Call the blender script
ProcessBuilder builder = new ProcessBuilder(blenderExe, "--background", "--python",
converterPath + File.separator + "scripts" + File.separator + "simplify.py",
tmpDir.toString(), modelDir.toString(), Double.toString(decimateRatio));
builder.inheritIO();
// builder.redirectOutput(ProcessBuilder.Redirect.appendTo(BLENDER_LOG_FILE));
// builder.redirectError(ProcessBuilder.Redirect.appendTo(BLENDER_LOG_FILE));
Logger.getLogger("nomad-3d").info("Executing command : \n" + builder.command());
Process blenderProcess = builder.start();
int exitValue = blenderProcess.waitFor();
Logger.getLogger("nomad-3d").info("Blender exit value : " + exitValue);
// Add new components to the model
Logger.getLogger("nomad-3d").info("Adding new components to the model...");
for (SubdividedChild subChild : subdividedChilds) {
Component child = new Component();
child.setName(subChild.name.get());
child.setFileName(FilenameUtils.removeExtension(new File(subChild.path.get()).getName()));
boolean fixed = false;
for (ConfigParams parentConfig : selectedComponent.getConfigurations()) {
ConfigParams config = new ConfigParams(child);
config.setConfiguration(parentConfig.getConfiguration());
config.setTranslation(parentConfig.getTranslation().clone());
config.setRotation(parentConfig.getRotation().clone());
config.setScale(parentConfig.getScale().clone());
config.setVisible(parentConfig.isVisible());
config.setFixed(parentConfig.isFixed());
fixed |= config.isFixed();
child.addConfiguration(config);
}
child.setMaterial(selectedComponent.getMaterial());
child.setAxis(((fixed) ? Axis.FIXED_AXIS : Axis.FREE_AXIS).clone());
selectedComponent.addChild(child);
}
Logger.getLogger("nomad-3d").info("New components added.");
updateScene();
} catch (Exception e) {
e.printStackTrace();
} finally {
subdividedChilds.clear();
subdivStage.close();
}
});
Button cancelButton = new Button("Cancel");
cancelButton.setCancelButton(true);
cancelButton.setOnAction(cancelEvent -> {
subdividedChilds.clear();
subdivStage.close();
});
buttonsPane.addRow(0, okButton, cancelButton);
subdivStage.show();
});
MenuItem removeComponentsItem = new MenuItem("Remove components");
removeComponentsItem.setOnAction(event -> {
......@@ -1419,7 +1634,7 @@ public class EditorMenuBar extends MenuBar {
if(selectRoots.size() > 1) {
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle(title);
alert.setContentText("Several components are selected, multiple axes cannot be calibrated at once.");
alert.setContentText("Several components are selected.");
alert.showAndWait();
return null;
} else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment