Main.java 33 KB

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