Main.java 34 KB

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