Main.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. package ui;
  2. import com.interactivemesh.jfx.importer.stl.StlMeshImporter;
  3. import controller.Controller;
  4. import controller.Export;
  5. import controller.SettingsController;
  6. import javafx.animation.KeyFrame;
  7. import javafx.animation.Timeline;
  8. import javafx.application.Application;
  9. import javafx.application.Platform;
  10. import javafx.collections.FXCollections;
  11. import javafx.collections.ObservableList;
  12. import javafx.concurrent.Task;
  13. import javafx.event.EventHandler;
  14. import javafx.fxml.FXMLLoader;
  15. import javafx.geometry.Pos;
  16. import javafx.scene.*;
  17. import javafx.scene.control.*;
  18. import javafx.scene.image.Image;
  19. import javafx.scene.image.ImageView;
  20. import javafx.scene.input.MouseEvent;
  21. import javafx.scene.layout.*;
  22. import javafx.scene.paint.Color;
  23. import javafx.scene.paint.PhongMaterial;
  24. import javafx.scene.shape.Mesh;
  25. import javafx.scene.shape.MeshView;
  26. import javafx.scene.transform.Rotate;
  27. import javafx.stage.DirectoryChooser;
  28. import javafx.stage.Stage;
  29. import javafx.stage.StageStyle;
  30. import javafx.util.Duration;
  31. import model.Settings;
  32. import java.io.BufferedReader;
  33. import java.io.File;
  34. import java.io.IOException;
  35. import java.io.InputStreamReader;
  36. import java.util.Collections;
  37. public class Main extends Application {
  38. private static Main window;
  39. //Save the last x/y value of the mouse, used for rotating the object in the javaFX panel
  40. private int lastX = 0;
  41. private int lastY = 0;
  42. //Which view is currently used for the javaFX panel
  43. private static final int VIEW_ALL = 0;
  44. private static final int VIEW_CONDUCTIVE = 1;
  45. private static final int VIEW_NON_CONDUCTIVE = 2;
  46. private static final int VIEW_CROSS_SECTION = 3;
  47. //If creating the STLs is finished. If yes, change the javaFX view
  48. private static boolean finished = false;
  49. //If the openSCAD installation got detected. If not, show a message.
  50. private static boolean detected = true;
  51. private CheckBox accelerationCheckBox;
  52. private Label accelerationLabel;
  53. private CheckBox weightCheckBox;
  54. private Label weightLabel;
  55. private CheckBox tempCheckBox;
  56. private Label tempLabel;
  57. private CheckBox rotationCheckBox;
  58. private Label rotationLabel;
  59. private CheckBox pressureCheckBox;
  60. private Label pressureLabel;
  61. private Button createObjectButton;
  62. private ComboBox<String> comboBox;
  63. private Pane fxPanel;
  64. private Group rootGroup;
  65. private StackPane glassPane;
  66. private Parent root;
  67. private Spinner<String> accelerationSpinner;
  68. private Spinner<String> loadSpinner;
  69. @Override
  70. public void start(Stage primaryStage) throws Exception{
  71. root = FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
  72. primaryStage.setTitle("Off-Line Interactor Printing");
  73. primaryStage.setOnCloseRequest(e -> {
  74. try {
  75. Platform.exit();
  76. }
  77. catch (Exception e1) {
  78. e1.printStackTrace();
  79. }
  80. });
  81. UIController.setPath(getClass().getResource("/pictures/acceleration.png").toString().replace("acceleration.png", ""));
  82. Node nodeAccel = root.lookup("#accelerationPane");
  83. TitledPane pane = (TitledPane) nodeAccel;
  84. BorderPane borderPane = new BorderPane();
  85. accelerationCheckBox = new CheckBox();
  86. borderPane.setLeft(accelerationCheckBox);
  87. BorderPane.setAlignment(accelerationCheckBox, Pos.CENTER_LEFT);
  88. accelerationLabel = new Label(" Acceleration");
  89. accelerationLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
  90. @Override
  91. public void handle(MouseEvent event) {
  92. accelerationCheckBox.setSelected(!accelerationCheckBox.isSelected());
  93. accelerationClicked();
  94. }
  95. });
  96. Image imgAccelSymbol = new Image(getClass().getResource("/pictures/acceleration.png").toString());
  97. ImageView imViewAccelSymbol = new ImageView(imgAccelSymbol);
  98. imViewAccelSymbol.setFitWidth(30);
  99. imViewAccelSymbol.setFitHeight(30);
  100. accelerationLabel.setGraphic(imViewAccelSymbol);
  101. borderPane.setCenter(accelerationLabel);
  102. pane.setGraphic(borderPane);
  103. accelerationCheckBox.setOnAction(event -> {
  104. accelerationClicked();
  105. event.consume();
  106. });
  107. Node nodeWeight = root.lookup("#weightPane");
  108. TitledPane paneWeight = (TitledPane) nodeWeight;
  109. BorderPane borderPaneWeight = new BorderPane();
  110. weightCheckBox = new CheckBox();
  111. borderPaneWeight.setLeft(weightCheckBox);
  112. BorderPane.setAlignment(weightCheckBox, Pos.CENTER_LEFT);
  113. weightLabel = new Label(" Load");
  114. weightLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
  115. @Override
  116. public void handle(MouseEvent event) {
  117. weightCheckBox.setSelected(!weightCheckBox.isSelected());
  118. weightClicked();
  119. }
  120. });
  121. Image imgWeightSymbol = new Image(getClass().getResource("/pictures/weight.png").toString());
  122. ImageView imViewWeightSymbol = new ImageView(imgWeightSymbol);
  123. imViewWeightSymbol.setFitWidth(30);
  124. imViewWeightSymbol.setFitHeight(30);
  125. weightLabel.setGraphic(imViewWeightSymbol);
  126. borderPaneWeight.setCenter(weightLabel);
  127. paneWeight.setGraphic(borderPaneWeight);
  128. weightCheckBox.setOnAction(event -> {
  129. weightClicked();
  130. event.consume();
  131. });
  132. Node nodeTemp = root.lookup("#temperaturePane");
  133. TitledPane paneTemp = (TitledPane) nodeTemp;
  134. BorderPane borderPaneTemp = new BorderPane();
  135. tempCheckBox = new CheckBox();
  136. borderPaneTemp.setLeft(tempCheckBox);
  137. BorderPane.setAlignment(tempCheckBox, Pos.CENTER_LEFT);
  138. tempLabel = new Label(" Temperature");
  139. tempLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
  140. @Override
  141. public void handle(MouseEvent event) {
  142. tempCheckBox.setSelected(!tempCheckBox.isSelected());
  143. temperatureClicked();
  144. }
  145. });
  146. Image imgTempSymbol = new Image(getClass().getResource("/pictures/temperature.png").toString());
  147. ImageView imViewTempSymbol = new ImageView(imgTempSymbol);
  148. imViewTempSymbol.setFitWidth(14);
  149. imViewTempSymbol.setFitHeight(30);
  150. tempLabel.setGraphic(imViewTempSymbol);
  151. borderPaneTemp.setCenter(tempLabel);
  152. paneTemp.setGraphic(borderPaneTemp);
  153. tempCheckBox.setOnAction(event -> {
  154. temperatureClicked();
  155. event.consume();
  156. });
  157. Node nodeRotation = root.lookup("#rotationPane");
  158. TitledPane paneRotation = (TitledPane) nodeRotation;
  159. BorderPane borderPaneRotation = new BorderPane();
  160. rotationCheckBox = new CheckBox();
  161. borderPaneRotation.setLeft(rotationCheckBox);
  162. BorderPane.setAlignment(rotationCheckBox, Pos.CENTER_LEFT);
  163. rotationLabel = new Label(" Rotation");
  164. rotationLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
  165. @Override
  166. public void handle(MouseEvent event) {
  167. rotationCheckBox.setSelected(!rotationCheckBox.isSelected());
  168. rotationClicked();
  169. }
  170. });
  171. Image imgRotationSymbol = new Image(getClass().getResource("/pictures/rotation.png").toString());
  172. ImageView imViewRotationSymbol = new ImageView(imgRotationSymbol);
  173. imViewRotationSymbol.setFitWidth(30);
  174. imViewRotationSymbol.setFitHeight(30);
  175. rotationLabel.setGraphic(imViewRotationSymbol);
  176. borderPaneRotation.setCenter(rotationLabel);
  177. paneRotation.setGraphic(borderPaneRotation);
  178. rotationCheckBox.setOnAction(event -> {
  179. rotationClicked();
  180. event.consume();
  181. });
  182. Node nodePressure = root.lookup("#pressurePane");
  183. TitledPane panePressure = (TitledPane) nodePressure;
  184. BorderPane borderPanePressure = new BorderPane();
  185. pressureCheckBox = new CheckBox();
  186. borderPanePressure.setLeft(pressureCheckBox);
  187. BorderPane.setAlignment(pressureCheckBox, Pos.CENTER_LEFT);
  188. pressureLabel = new Label(" Pressure");
  189. pressureLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
  190. @Override
  191. public void handle(MouseEvent event) {
  192. pressureCheckBox.setSelected(!pressureCheckBox.isSelected());
  193. pressureClicked();
  194. }
  195. });
  196. Image imgPressureSymbol = new Image(getClass().getResource("/pictures/pressure.png").toString());
  197. ImageView imViewPressureSymbol = new ImageView(imgPressureSymbol);
  198. imViewPressureSymbol.setFitWidth(30);
  199. imViewPressureSymbol.setFitHeight(30);
  200. pressureLabel.setGraphic(imViewPressureSymbol);
  201. borderPanePressure.setCenter(pressureLabel);
  202. panePressure.setGraphic(borderPanePressure);
  203. pressureCheckBox.setOnAction(event -> {
  204. pressureClicked();
  205. event.consume();
  206. });
  207. primaryStage.setScene(new Scene(root, 1280, 720));
  208. primaryStage.show();
  209. accelerationLabel.setMinWidth(((TitledPane) nodeAccel).getWidth() * 0.83);
  210. weightLabel.setMinWidth(((TitledPane) nodeAccel).getWidth() * 0.83);
  211. tempLabel.setMinWidth(((TitledPane) nodeAccel).getWidth() * 0.83);
  212. rotationLabel.setMinWidth(((TitledPane) nodeAccel).getWidth() * 0.83);
  213. pressureLabel.setMinWidth(((TitledPane) nodeAccel).getWidth() * 0.83);
  214. ObservableList<String> accelerationEntries = FXCollections.observableArrayList("5.0 m/s²", "12.0 m/s²");
  215. accelerationSpinner = new Spinner<>();
  216. SpinnerValueFactory<String> accelerationValueFactory = new SpinnerValueFactory<String>() {
  217. @Override
  218. public void decrement(int steps) {
  219. String current = this.getValue();
  220. int index = accelerationEntries.indexOf(current);
  221. this.setValue(accelerationEntries.get((accelerationEntries.size() + index - steps)%accelerationEntries.size()));
  222. double value = Double.parseDouble(this.getValue().replace(" m/s²", ""));
  223. Controller.getC().setAcceleration(value);
  224. }
  225. @Override
  226. public void increment(int steps) {
  227. String current = this.getValue();
  228. int index = accelerationEntries.indexOf(current);
  229. this.setValue(accelerationEntries.get((index + steps)%accelerationEntries.size()));
  230. double value = Double.parseDouble(this.getValue().replace(" m/s²", ""));
  231. Controller.getC().setAcceleration(value);
  232. }
  233. };
  234. accelerationValueFactory.setValue("5.0 m/s²");
  235. accelerationSpinner.setValueFactory(accelerationValueFactory);
  236. accelerationSpinner.setDisable(true);
  237. accelerationSpinner.setMaxWidth(120);
  238. HBox accelHBox = ((HBox)root.lookup("#accelerationContent"));
  239. accelHBox.getChildren().add(accelerationSpinner);
  240. ObservableList<Node> workingCollection = FXCollections.observableArrayList(accelHBox.getChildren());
  241. Collections.swap(workingCollection, 1, 3);
  242. Collections.swap(workingCollection, 2, 3);
  243. accelHBox.getChildren().setAll(workingCollection);
  244. ObservableList<String> loadEntries = FXCollections.observableArrayList("5.4 Kg", "10.8 Kg", "16.2 Kg");
  245. loadSpinner = new Spinner<>();
  246. SpinnerValueFactory<String> loadValueFactory = new SpinnerValueFactory<String>() {
  247. @Override
  248. public void decrement(int steps) {
  249. String current = this.getValue();
  250. int index = loadEntries.indexOf(current);
  251. this.setValue(loadEntries.get((loadEntries.size() + index - steps)%loadEntries.size()));
  252. double value = Double.parseDouble(this.getValue().replace(" Kg", ""));
  253. Controller.getC().setWeight((int)(value*10));
  254. }
  255. @Override
  256. public void increment(int steps) {
  257. String current = this.getValue();
  258. int index = loadEntries.indexOf(current);
  259. this.setValue(loadEntries.get((index + steps)%loadEntries.size()));
  260. double value = Double.parseDouble(this.getValue().replace(" Kg", ""));
  261. Controller.getC().setWeight((int)(value*10));
  262. }
  263. };
  264. loadValueFactory.setValue("5.4 Kg");
  265. loadSpinner.setValueFactory(loadValueFactory);
  266. loadSpinner.setDisable(true);
  267. loadSpinner.setMaxWidth(120);
  268. HBox loadHBox = ((HBox)root.lookup("#weightContent"));
  269. loadHBox.getChildren().add(loadSpinner);
  270. ObservableList<Node> loadWorkingCollection = FXCollections.observableArrayList(loadHBox.getChildren());
  271. Collections.swap(loadWorkingCollection, 1, 3);
  272. Collections.swap(loadWorkingCollection, 2, 3);
  273. loadHBox.getChildren().setAll(loadWorkingCollection);
  274. /* ((ScrollBar) root.lookup("#accelerationScrollBar")).valueProperty().addListener((observable, oldValue, newValue) -> {
  275. double d = newValue.intValue();
  276. Controller.getC().setAcceleration(d);
  277. ((Label) root.lookup("#accelerationLabel")).setText("Acceleration limit: " + d + " m/s²");
  278. });
  279. ((ScrollBar) root.lookup("#weightScrollBar")).valueProperty().addListener((observable, oldValue, newValue) -> {
  280. int w = newValue.intValue();
  281. Controller.getC().setWeight(w);
  282. ((Label) root.lookup("#weightLabel")).setText("Load limit: " + (w/10.0) + " Kg");
  283. });*/
  284. ToggleGroup groupTemp = new ToggleGroup();
  285. ((RadioButton) root.lookup("#temperatureRadio1")).setToggleGroup(groupTemp);
  286. ((RadioButton) root.lookup("#temperatureRadio2")).setToggleGroup(groupTemp);
  287. ((RadioButton) root.lookup("#temperatureRadio1")).selectedProperty().addListener((observable, oldValue, newValue) -> {
  288. if (newValue)
  289. Controller.getC().setTemperature(Settings.Temp.OVER0);
  290. });
  291. ((RadioButton) root.lookup("#temperatureRadio2")).selectedProperty().addListener((observable, oldValue, newValue) -> {
  292. if (newValue)
  293. Controller.getC().setTemperature(Settings.Temp.UNDER0);
  294. });
  295. ToggleGroup groupTilt = new ToggleGroup();
  296. ((RadioButton) root.lookup("#rotationRadio1")).setToggleGroup(groupTilt);
  297. ((RadioButton) root.lookup("#rotationRadio2")).setToggleGroup(groupTilt);
  298. ((RadioButton) root.lookup("#rotationRadio1")).selectedProperty().addListener((observable, oldValue, newValue) -> {
  299. if (newValue)
  300. Controller.getC().setTilt(Settings.Tilt.TILT);
  301. });
  302. ((RadioButton) root.lookup("#rotationRadio2")).selectedProperty().addListener((observable, oldValue, newValue) -> {
  303. if (newValue)
  304. Controller.getC().setTilt(Settings.Tilt.FLIP);
  305. });
  306. fxPanel = (Pane) root.lookup("#fxPanel");
  307. SubScene subScene = createScene();
  308. fxPanel.getChildren().add(subScene);
  309. subScene.heightProperty().bind(fxPanel.heightProperty());
  310. subScene.widthProperty().bind(fxPanel.widthProperty());
  311. fxPanel.setOnMousePressed(event -> {
  312. lastX = (int) event.getX();
  313. lastY = (int) event.getY();
  314. });
  315. fxPanel.setOnMouseDragged(event -> {
  316. //Rotation
  317. Group root1 = rootGroup;//(SubScene) fxPanel.getChildren().get(1);
  318. Rotate rY = (Rotate) root1.getTransforms().get(0);
  319. rY.setAngle(rY.getAngle()+ event.getY() - lastY);
  320. lastY = (int) event.getY();
  321. Rotate rX = (Rotate) root1.getTransforms().get(1);
  322. rX.setAngle(rX.getAngle()+ event.getX() - lastX);
  323. lastX = (int) event.getX();
  324. });
  325. fxPanel.setOnScroll(event -> {
  326. //Zooming
  327. Group root12 = rootGroup;//(SubScene) fxPanel.getChildren().get(1);
  328. int direction;
  329. if (root12.getScaleX() > 0) {
  330. if (event.getDeltaY() > 0)
  331. direction = 1;
  332. else
  333. direction = -1;
  334. }
  335. else {
  336. if (event.getDeltaY() > 0)
  337. direction = 1;
  338. else
  339. direction = 0;
  340. }
  341. root12.setScaleX(root12.getScaleX() + direction);
  342. root12.setScaleY(root12.getScaleY() + direction);
  343. root12.setScaleZ(root12.getScaleZ() + direction);
  344. });
  345. comboBox = (ComboBox<String>) root.lookup("#comboBox");
  346. ObservableList<String> options = FXCollections.observableArrayList(
  347. "Show All Parts",
  348. "Show Conductive Only",
  349. "Show Non-Conductive Only",
  350. "Show Cross-Section"
  351. );
  352. comboBox.getItems().addAll(options);
  353. comboBox.setValue(options.get(3));
  354. comboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> Platform.runLater(() -> {
  355. clearView((SubScene)fxPanel.getChildren().get(0));
  356. int index = -1;
  357. switch (newValue) {
  358. case "Show All Parts": index = 0; break;
  359. case "Show Conductive Only": index = 1; break;
  360. case "Show Non-Conductive Only": index = 2; break;
  361. case "Show Cross-Section": index = 3; break;
  362. }
  363. changeObject((SubScene)fxPanel.getChildren().get(0), index);
  364. }));
  365. createObjectButton = (Button) root.lookup("#createObjectButton");
  366. Image imageCreate = new Image(getClass().getResource("/pictures/cog.png").toString());
  367. ImageView imageViewCreate = new ImageView(imageCreate);
  368. imageViewCreate.setFitWidth(30);
  369. imageViewCreate.setFitHeight(30);
  370. createObjectButton.setGraphic(imageViewCreate);
  371. createObjectButton.setContentDisplay(ContentDisplay.LEFT);
  372. createObjectButton.setOnAction(event -> {
  373. Task task = new Task() {
  374. @Override
  375. protected Void call() throws Exception {
  376. Export.createSTL();
  377. return null;
  378. }
  379. };
  380. task.setOnSucceeded( e -> {
  381. glassPane.setVisible(false);
  382. });
  383. task.setOnRunning(e -> {
  384. glassPane.setVisible(true);
  385. clearView((SubScene) fxPanel.getChildren().get(0));
  386. this.root.lookup("#saveObjectButton").setDisable(true);
  387. });
  388. new Thread(task).start();
  389. //Same as above
  390. comboBox.setDisable(false);
  391. Task task2 = new Task() {
  392. @Override
  393. protected Void call() throws Exception {
  394. while (!finished) {
  395. try {
  396. Thread.sleep(100);
  397. } catch (InterruptedException e) {
  398. e.printStackTrace();
  399. }
  400. }
  401. finished = false;
  402. int index = -1;
  403. switch (comboBox.getValue()) {
  404. case "Show All Parts": index = 0; break;
  405. case "Show Conductive Only": index = 1; break;
  406. case "Show Non-Conductive Only": index = 2; break;
  407. case "Show Cross-Section": index = 3; break;
  408. }
  409. int finalIndex = index;
  410. Platform.runLater(() -> changeObject((SubScene) fxPanel.getChildren().get(0), finalIndex));
  411. return null;
  412. }
  413. };
  414. new Thread(task2).start();
  415. });
  416. Button saveObjectButton = ((Button) root.lookup("#saveObjectButton"));
  417. Image imageSave = new Image(getClass().getResource("/pictures/save.png").toString());
  418. ImageView imageViewSave = new ImageView(imageSave);
  419. imageViewSave.setFitWidth(30);
  420. imageViewSave.setFitHeight(30);
  421. saveObjectButton.setGraphic(imageViewSave);
  422. saveObjectButton.setContentDisplay(ContentDisplay.LEFT);
  423. saveObjectButton.setOnAction(event -> {
  424. DirectoryChooser chooser = new DirectoryChooser();
  425. Platform.runLater(() -> {
  426. File file = chooser.showDialog(primaryStage);
  427. if (file != null) {
  428. Export.saveFilesTo(file);
  429. }
  430. });
  431. /* JFileChooser chooser = new JFileChooser();
  432. chooser.setCurrentDirectory(new File("."));
  433. chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  434. chooser.setAcceptAllFileFilterUsed(false);
  435. chooser.showOpenDialog(null);
  436. if (chooser.getSelectedFile() != null) {
  437. Export.saveFilesTo(chooser.getSelectedFile());
  438. }*/
  439. });
  440. Image image = new Image(getClass().getResource("/pictures/information-icon-6086.png").toString());
  441. ImageView imViewAccel = new ImageView(image);
  442. imViewAccel.setFitWidth(15);
  443. imViewAccel.setFitHeight(15);
  444. ((Button) root.lookup("#accelerationInfo")).setGraphic(imViewAccel);
  445. ImageView imViewWeight = new ImageView(image);
  446. imViewWeight.setFitWidth(15);
  447. imViewWeight.setFitHeight(15);
  448. ((Button) root.lookup("#weightInfo")).setGraphic(imViewWeight);
  449. ImageView imViewFreeze = new ImageView(image);
  450. imViewFreeze.setFitWidth(15);
  451. imViewFreeze.setFitHeight(15);
  452. ((Button) root.lookup("#freezeInfo")).setGraphic(imViewFreeze);
  453. ImageView imViewMelt = new ImageView(image);
  454. imViewMelt.setFitWidth(15);
  455. imViewMelt.setFitHeight(15);
  456. ((Button) root.lookup("#meltInfo")).setGraphic(imViewMelt);
  457. ImageView imViewTilt = new ImageView(image);
  458. imViewTilt.setFitWidth(15);
  459. imViewTilt.setFitHeight(15);
  460. ((Button) root.lookup("#tiltInfo")).setGraphic(imViewTilt);
  461. ImageView imViewFlip = new ImageView(image);
  462. imViewFlip.setFitWidth(15);
  463. imViewFlip.setFitHeight(15);
  464. ((Button) root.lookup("#flipInfo")).setGraphic(imViewFlip);
  465. ImageView imViewSqueeze = new ImageView(image);
  466. imViewSqueeze.setFitWidth(15);
  467. imViewSqueeze.setFitHeight(15);
  468. ((Button) root.lookup("#squeezeInfo")).setGraphic(imViewSqueeze);
  469. Image imageSettings = new Image(getClass().getResource("/pictures/cog.png").toString());
  470. ImageView imageViewSettings = new ImageView(imageSettings);
  471. imageViewSettings.setFitWidth(20);
  472. imageViewSettings.setFitHeight(20);
  473. ((Button)root.lookup("#settingsButton")).setGraphic(imageViewSettings);
  474. glassPane = new StackPane();
  475. glassPane.setStyle("-fx-background-color: rgba(0, 0, 0, 0.2);");
  476. glassPane.setVisible(false);
  477. Label loadingLabel = new Label("Creating Object...");
  478. Image loadingImage = new Image(getClass().getResource("/pictures/loadingCircle.gif").toString());
  479. ImageView imView = new ImageView(loadingImage);
  480. imView.setFitHeight(16);
  481. imView.setFitWidth(128);
  482. // loadingLabel.setGraphic(new ImageView(image));
  483. VBox vb = new VBox();
  484. //ProgressBar pbar = new ProgressBar();
  485. //pbar.setProgress(0.5);
  486. vb.setAlignment(Pos.CENTER);
  487. //vb.getChildren().add(pbar);
  488. vb.getChildren().add(imView);
  489. vb.getChildren().add(loadingLabel);
  490. glassPane.getChildren().add(vb);
  491. StackPane.setAlignment(vb, Pos.CENTER);
  492. ((GridPane)root).add(glassPane, 1, 0);
  493. //If openSCAD could not be found, show a warning. The text depends on the OS.
  494. if (!detected) {
  495. if (System.getProperty("os.name").toLowerCase().contains("windows")) {
  496. Alert alert = new Alert(Alert.AlertType.INFORMATION);
  497. alert.initStyle(StageStyle.UTILITY);
  498. alert.setTitle("Information");
  499. alert.setHeaderText("Warning");
  500. alert.setContentText("Couldn't find openscad.exe.\nMake sure that OpenSCAD is installed and select its folder under Menu -> Settings.");
  501. alert.showAndWait();
  502. }
  503. else if (System.getProperty("os.name").toLowerCase().contains("linux")) {
  504. Alert alert = new Alert(Alert.AlertType.INFORMATION);
  505. alert.initStyle(StageStyle.UTILITY);
  506. alert.setTitle("Information");
  507. alert.setHeaderText("Warning");
  508. alert.setContentText("Couldn't find openscad.\nMake sure that OpenSCAD is installed and is visible gloabaly.");
  509. alert.showAndWait();
  510. }
  511. else if (System.getProperty("os.name").toLowerCase().contains("mac")) {
  512. Alert alert = new Alert(Alert.AlertType.INFORMATION);
  513. alert.initStyle(StageStyle.UTILITY);
  514. alert.setTitle("Information");
  515. alert.setHeaderText("Warning");
  516. alert.setContentText("Couldn't find openscad.app.\nMake sure that OpenSCAD is installed and select its folder under Menu -> Settings.");
  517. alert.showAndWait();
  518. }
  519. }
  520. }
  521. public static void main(String[] args) {
  522. //Load the settings.ini
  523. try {
  524. File file = new File(new java.io.File( "." ).getCanonicalPath() + File.separator + "settings.ini");
  525. if (file.exists())
  526. SettingsController.loadSettings();
  527. else {
  528. //If there isn't a settings.ini file, create a new one and search if OpenSCAD is installed.
  529. //Windows: exe typically under the given path.
  530. if (System.getProperty("os.name").toLowerCase().contains("windows")) {
  531. File openscadexe = new File("C:\\Program Files\\OpenSCAD\\openscad.exe");
  532. if (openscadexe.exists())
  533. Controller.getC().setOpenSCADPath(openscadexe.toPath().getParent());
  534. else {
  535. notDetected();
  536. }
  537. }
  538. //Linux: OpenSCAD is visible globally, so check via command line
  539. else if (System.getProperty("os.name").toLowerCase().contains("linux")) {
  540. try {
  541. Process p = Runtime.getRuntime().exec("which openscad");
  542. p.waitFor();
  543. BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
  544. String s = in.readLine();
  545. if (s != null) {
  546. Controller.getC().setOpenSCADPath(new File(s).toPath());
  547. }
  548. else {
  549. notDetected();
  550. }
  551. } catch (IOException | InterruptedException e1) {
  552. e1.printStackTrace();
  553. }
  554. }
  555. //MacOS: OpenSCAD is installed as an app, so look for in in the application folder
  556. else if (System.getProperty("os.name").toLowerCase().contains("mac")) {
  557. File openscadapp = new File("/Applications/OpenSCAD.app");
  558. if (openscadapp.exists())
  559. Controller.getC().setOpenSCADPath(new File(openscadapp.toPath().toString() + "/Contents/MacOS/").toPath());
  560. else
  561. notDetected();
  562. }
  563. SettingsController.saveSettings();
  564. }
  565. } catch (IOException e) {
  566. e.printStackTrace();
  567. }
  568. launch(args);
  569. }
  570. private void accelerationClicked() {
  571. boolean disable = accelerationCheckBox.isSelected();
  572. createObjectButton.setDisable(!disable);
  573. disableWeight();
  574. disableTemperature();
  575. disableRotation();
  576. disablePressure();
  577. root.lookup("#accelerationLabel").setDisable(!disable);
  578. accelerationSpinner.setDisable(!disable);
  579. Controller.getC().acceleration(disable);
  580. }
  581. private void disableAcceleration() {
  582. accelerationCheckBox.setSelected(false);
  583. Controller.getC().acceleration(false);
  584. root.lookup("#accelerationLabel").setDisable(true);
  585. accelerationSpinner.setDisable(true);
  586. }
  587. private void weightClicked() {
  588. boolean disable = weightCheckBox.isSelected();
  589. createObjectButton.setDisable(!disable);
  590. disableAcceleration();
  591. disableTemperature();
  592. disableRotation();
  593. disablePressure();
  594. root.lookup("#weightLabel").setDisable(!disable);
  595. loadSpinner.setDisable(!disable);
  596. Controller.getC().weight(disable);
  597. }
  598. private void disableWeight() {
  599. weightCheckBox.setSelected(false);
  600. Controller.getC().weight(false);
  601. root.lookup("#weightLabel").setDisable(true);
  602. loadSpinner.setDisable(true);
  603. }
  604. private void temperatureClicked() {
  605. boolean disable = tempCheckBox.isSelected();
  606. createObjectButton.setDisable(!disable);
  607. disableWeight();
  608. disableAcceleration();
  609. disableRotation();
  610. disablePressure();
  611. root.lookup("#temperatureRadio1").setDisable(!disable);
  612. root.lookup("#temperatureRadio2").setDisable(!disable);
  613. Controller.getC().temperature(disable);
  614. }
  615. private void disableTemperature() {
  616. tempCheckBox.setSelected(false);
  617. Controller.getC().temperature(false);
  618. root.lookup("#temperatureRadio1").setDisable(true);
  619. root.lookup("#temperatureRadio2").setDisable(true);
  620. }
  621. private void rotationClicked() {
  622. boolean disable = rotationCheckBox.isSelected();
  623. createObjectButton.setDisable(!disable);
  624. disableWeight();
  625. disableTemperature();
  626. disableAcceleration();
  627. disablePressure();
  628. root.lookup("#rotationRadio1").setDisable(!disable);
  629. root.lookup("#rotationRadio2").setDisable(!disable);
  630. Controller.getC().tilt(disable);
  631. }
  632. private void disableRotation() {
  633. rotationCheckBox.setSelected(false);
  634. Controller.getC().tilt(false);
  635. root.lookup("#rotationRadio1").setDisable(true);
  636. root.lookup("#rotationRadio2").setDisable(true);
  637. }
  638. private void pressureClicked() {
  639. boolean disable = pressureCheckBox.isSelected();
  640. createObjectButton.setDisable(!disable);
  641. disableWeight();
  642. disableTemperature();
  643. disableRotation();
  644. disableAcceleration();
  645. //root.lookup("#pressureContent").setDisable(!disable);
  646. Controller.getC().squeeze(disable);
  647. }
  648. private void disablePressure() {
  649. pressureCheckBox.setSelected(false);
  650. Controller.getC().squeeze(false);
  651. }
  652. /**
  653. * Initialize the JavaFX panel
  654. * @return initialized panel
  655. */
  656. private SubScene createScene() {
  657. rootGroup = new Group();
  658. SubScene scene = new SubScene(rootGroup, 1000, 1000, true, null);
  659. scene.setFill(new Color(0.9, 0.9, 0.9, 1.0));
  660. Timeline timer = new Timeline(new KeyFrame(Duration.seconds(0.001667), event -> {
  661. rootGroup.setTranslateX(fxPanel.getWidth()/2);
  662. rootGroup.setTranslateY(fxPanel.getHeight()/2);
  663. }));
  664. timer.setCycleCount(Timeline.INDEFINITE);
  665. timer.play();
  666. rootGroup.setScaleX(Math.min(fxPanel.getWidth()/80, fxPanel.getHeight()/80));
  667. rootGroup.setScaleY(Math.min(fxPanel.getWidth()/80, fxPanel.getHeight()/80));
  668. rootGroup.setScaleZ(Math.min(fxPanel.getWidth()/80, fxPanel.getHeight()/80));
  669. //rootGroup.setTranslateX(400);
  670. //rootGroup.setTranslateY(400);
  671. rootGroup.setTranslateZ(0);
  672. Rotate r = new Rotate();
  673. r.setAngle(-60);
  674. r.setAxis(Rotate.Y_AXIS);
  675. rootGroup.getTransforms().add(r);
  676. Rotate r2 = new Rotate();
  677. r.setAxis(Rotate.X_AXIS);
  678. r2.setAngle(-20);
  679. rootGroup.getTransforms().add(r2);
  680. rootGroup.getChildren().add(new AmbientLight(Color.WHITE));
  681. return scene;
  682. }
  683. /**
  684. * Reload the object (changes if another object got created) or just change the view mode
  685. * @param scene area to show the 3d scene
  686. * @param viewMode view mode, dependend on dropdown menu
  687. */
  688. private void changeObject(SubScene scene, int viewMode) {
  689. Label previewlabel = ((Label) this.root.lookup("#previewLabel"));
  690. Label propertiesLabel = ((Label) this.root.lookup("#propertiesLabel"));
  691. if (Settings.getSettings().isAcceleration()) {
  692. previewlabel.setText("Preview for Acceleration");
  693. propertiesLabel.setText("Acceleration Limit: " + Settings.getSettings().getAcceleration() + " m/s²\n" +
  694. "Fill Hole " + (Controller.getC().getFill()?"enabled":"disabled")+ "\n" +
  695. "Touchscreen Dot Size " + Controller.getC().getSizeScreen() + " mm\n" +
  696. "Finger Dot Size " + Controller.getC().getSizeFinger() + " mm");
  697. } else if (Settings.getSettings().isWeight()) {
  698. previewlabel.setText("Preview for Load");
  699. propertiesLabel.setText("Weight Limit: " + Settings.getSettings().getWeight()/10.0 + " Kg\n" +
  700. "Fill Hole " + (Controller.getC().getFill()?"enabled":"disabled")+ "\n" +
  701. "Touchscreen Dot Size " + Controller.getC().getSizeScreen() + " mm\n" +
  702. "Finger Dot Size " + Controller.getC().getSizeFinger() + " mm");
  703. } else if (Settings.getSettings().isTemperature()) {
  704. previewlabel.setText("Preview for Temperature");
  705. propertiesLabel.setText((Settings.getSettings().getTemperature()== Settings.Temp.OVER0?"Rising":"Falling") + " Temperature\n" +
  706. "Fill Hole " + (Controller.getC().getFill()?"enabled":"disabled") + "\n" +
  707. "Touchscreen Dot Size " + Controller.getC().getSizeScreen() + " mm\n" +
  708. "Finger Dot Size " + Controller.getC().getSizeFinger() + " mm");
  709. } else if (Settings.getSettings().isTilt()) {
  710. previewlabel.setText("Preview for Rotation");
  711. propertiesLabel.setText("Rotation by " + (Settings.getSettings().getTilting()== Settings.Tilt.TILT?"90°":"180°") + "\n" +
  712. "Fill Hole " + (Controller.getC().getFill()?"enabled":"disabled")+ "\n" +
  713. "Touchscreen Dot Size " + Controller.getC().getSizeScreen() + " mm\n" +
  714. "Finger Dot Size " + Controller.getC().getSizeFinger() + " mm");
  715. } else if (Settings.getSettings().isSqueeze()) {
  716. previewlabel.setText("Preview for Pressure");
  717. propertiesLabel.setText("Fill Hole " + (Controller.getC().getFill()?"enabled":"disabled")+ "\n" +
  718. "Touchscreen Dot Size " + Controller.getC().getSizeScreen() + " mm\n" +
  719. "Finger Dot Size " + Controller.getC().getSizeFinger() + " mm");
  720. } else {
  721. previewlabel.setText("Preview");
  722. propertiesLabel.setText("");
  723. }
  724. Group root = (Group) scene.getRoot();
  725. StlMeshImporter stlimport = new StlMeshImporter();
  726. String fileName;
  727. switch (viewMode) {
  728. case VIEW_ALL: fileName = "output.stl"; break;
  729. case VIEW_CONDUCTIVE: fileName = "output_conductive.stl"; break;
  730. case VIEW_NON_CONDUCTIVE: fileName = "output.stl"; break;
  731. case VIEW_CROSS_SECTION: fileName = "output_crosssection.stl"; break;
  732. default: fileName = "output.stl";
  733. }
  734. stlimport.read(new File(fileName));
  735. Mesh mesh = stlimport.getImport();
  736. MeshView meshView = new MeshView(mesh);
  737. PhongMaterial mat = new PhongMaterial();
  738. mat.setSpecularColor(Color.WHITE);
  739. if (viewMode == VIEW_CONDUCTIVE)
  740. mat.setDiffuseColor(Color.RED);
  741. else
  742. mat.setDiffuseColor(Color.LIGHTGRAY);
  743. meshView.setMaterial(mat);
  744. root.getChildren().add(meshView);
  745. if (viewMode == VIEW_ALL || viewMode == VIEW_CROSS_SECTION) {
  746. String fileName2;
  747. if (viewMode == VIEW_ALL)
  748. fileName2 = "output_conductive.stl";
  749. else
  750. fileName2 = "output_crosssection_conductive.stl";
  751. stlimport.read(new File(fileName2));
  752. Mesh mesh2 = stlimport.getImport();
  753. MeshView meshView2 = new MeshView(mesh2);
  754. PhongMaterial mat2 = new PhongMaterial();
  755. mat2.setSpecularColor(Color.WHITE);
  756. mat2.setDiffuseColor(Color.RED);
  757. meshView2.setMaterial(mat2);
  758. root.getChildren().add(meshView2);
  759. }
  760. this.root.lookup("#saveObjectButton").setDisable(false);
  761. }
  762. private void clearView(SubScene scene) {
  763. Group root = (Group) scene.getRoot();
  764. while (root.getChildren().size() > 0)
  765. root.getChildren().remove(0);
  766. }
  767. /**
  768. * Tell this frame that the creation of the STLs is finished
  769. */
  770. public static void finished() {
  771. finished = true;
  772. }
  773. /**
  774. * Tell this frame that openSCAD could not be found
  775. */
  776. private static void notDetected() {
  777. detected = false;
  778. }
  779. }