diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf4d82e8a..c59fb05d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -73,7 +73,15 @@ jobs: tag_name: ${{ github.ref }} env: GITHUB_TOKEN: ${{ github.token }} - + - name: upload JVM Configuration + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: jvm.json + asset_name: jvm.json + asset_content_type: application/json - name: upload BowlerStudio artifact uses: actions/upload-release-asset@v1 env: diff --git a/.gitignore b/.gitignore index 9249e1eb2..a7fab7f96 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ /Oracle_VM_VirtualBox_Extension_Pack-5.2.20.vbox-extpack /chdk-ptp-java.log /deps.txt +/MUJOCO_LOG.TXT +/physicsTest/ diff --git a/build.gradle b/build.gradle index 92e047b9f..9ae1566e6 100644 --- a/build.gradle +++ b/build.gradle @@ -233,11 +233,9 @@ dependencies { compile group: 'java3d', name: 'vecmath', version: '1.3.1' compile 'org.slf4j:slf4j-simple:1.6.1' - //compile "com.neuronrobotics:JavaCad:0.14.0" compile "com.neuronrobotics:CHDK-PTP-Java:0.5.3-SNAPSHOT" //compile "com.neuronrobotics:java-bowler:3.25.4" //compile fileTree (dir: '../java-bowler/build/libs/', includes: ['nrsdk-3.23.3-jar-with-dependencies.jar']) - //compile fileTree (dir: '../JCSG/build/libs/', includes: ['JavaCad-0.8.2.jar']) compile "com.neuronrobotics:WalnutiQ:2.3.3" @@ -342,7 +340,8 @@ dependencies { //compile fileTree (dir: 'libraries/bowler-script-kernel/libs/', includes: ['*.jar']) compile project(':libraries:bowler-script-kernel:java-bowler') compile project(':libraries:bowler-script-kernel') - compile project(':libraries:bowler-script-kernel:JCSG') + //compile project(':libraries:bowler-script-kernel:JCSG') + compile project(':libraries:dockfx') compile project(':libraries:bowler-script-kernel:GithubPasswordManager:GithubPasswordManager') //compile project(':kinematics-chef') @@ -356,6 +355,10 @@ dependencies { //https://github.com/HanSolo/Medusa compile group: 'eu.hansolo', name: 'Medusa', version: '7.1' + //MuJoCo + implementation group: 'org.bytedeco', name: 'javacpp', version: '1.5.7' + implementation group: 'com.neuronrobotics', name: 'mujoco-java', version:'3.1.3-pre.11' + } diff --git a/jvm.json b/jvm.json new file mode 100644 index 000000000..706675686 --- /dev/null +++ b/jvm.json @@ -0,0 +1,38 @@ +{ +"Linux-x64":{ + "url":"https://cdn.azul.com/zulu/bin/" + , + "type":"tar.gz", + "name":"zulu8.78.0.19-ca-fx-jdk8.0.412-linux_x64", + "jvmargs":["-Dprism.forceGPU=true"] + }, +"Linux-aarch64":{ + "url":"https://cdn.azul.com/zulu/bin/" + , + "type":"tar.gz", + "name":"zulu8.78.0.19-ca-fx-jdk8.0.412-linux_aarch64", + "jvmargs":["-Dprism.forceGPU=true"] + + }, +"Windows-x64":{ + "url":"https://cdn.azul.com/zulu/bin/" + , + "type":"zip", + "name":"zulu8.78.0.19-ca-fx-jdk8.0.412-win_x64" + }, +"Mac-x64":{ + "url":"https://cdn.azul.com/zulu/bin/" + , + "type":"zip", + "name":"zulu8.78.0.19-ca-fx-jdk8.0.412-macosx_x64", + "jvmargs":["-Dprism.forceGPU=true"] + }, +"Mac-aarch64":{ + "url":"https://cdn.azul.com/zulu/bin/" + , + "type":"zip", + "name":"zulu8.78.0.19-ca-fx-jdk8.0.412-macosx_aarch64", + "jvmargs":["-Dprism.forceGPU=true"] + } + +} \ No newline at end of file diff --git a/libraries/bowler-script-kernel b/libraries/bowler-script-kernel index 95d8ebcb6..aff4d787a 160000 --- a/libraries/bowler-script-kernel +++ b/libraries/bowler-script-kernel @@ -1 +1 @@ -Subproject commit 95d8ebcb6bc7f22a50aa270e74c1d1d592ea1dce +Subproject commit aff4d787af76c25e6bd5e49efd5d7c6ecd3c0396 diff --git a/settings.gradle b/settings.gradle index c8f4f520e..d7e2d93cf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,5 @@ include ':libraries:bowler-script-kernel' include ':libraries:bowler-script-kernel:java-bowler' -include ':libraries:bowler-script-kernel:JCSG' include ':libraries:dockfx' include ':libraries:bowler-script-kernel:GithubPasswordManager:GithubPasswordManager' rootProject.name = 'BowlerStudio' diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/AddFileToGistController.java b/src/main/java/com/neuronrobotics/bowlerstudio/AddFileToGistController.java index e3cb9df4a..d899b027b 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/AddFileToGistController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/AddFileToGistController.java @@ -1,6 +1,7 @@ package com.neuronrobotics.bowlerstudio; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.scripting.ArduinoLoader; import com.neuronrobotics.bowlerstudio.scripting.IScriptingLanguage; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; @@ -94,6 +95,12 @@ public void start(Stage primaryStage) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); extention.getItems().clear(); if (getGitRepo() != null) { newProject.getChildren().clear(); @@ -114,6 +121,10 @@ public void start(Stage primaryStage) throws Exception { icon = AssetFactory.loadAsset(asset); langaugeIcon.setImage(icon); + FontSizeManager.addListener(fontNum->{ + langaugeIcon.setScaleX(FontSizeManager.getImageScale()); + langaugeIcon.setScaleY(FontSizeManager.getImageScale()); + }); } catch (Exception e2) { // TODO Auto-generated catch block e2.printStackTrace(); @@ -147,6 +158,7 @@ private void setSelected(String selectedItem) throws Exception { Image loadAsset = AssetFactory.loadAsset(file); try { langaugeIcon.setImage(loadAsset); + }catch(Throwable t) { t.printStackTrace(); } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudio.java b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudio.java index 67e65618c..3c119dd0d 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudio.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudio.java @@ -1,5 +1,7 @@ package com.neuronrobotics.bowlerstudio; +import javafx.scene.control.Button; + //import com.neuronrobotics.kinematicschef.InverseKinematicsEngine; import com.neuronrobotics.bowlerkernel.BowlerKernelBuildInfo; import com.neuronrobotics.bowlerkernel.Bezier3d.IInteractiveUIElementProvider; @@ -7,6 +9,7 @@ import com.neuronrobotics.bowlerstudio.assets.AssetFactory; import com.neuronrobotics.bowlerstudio.assets.BowlerStudioResourceFactory; import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.assets.StudioBuildInfo; import com.neuronrobotics.bowlerstudio.creature.MobileBaseCadManager; import com.neuronrobotics.bowlerstudio.creature.MobileBaseLoader; @@ -18,6 +21,7 @@ import com.neuronrobotics.bowlerstudio.scripting.ScriptingFileWidget; import com.neuronrobotics.bowlerstudio.scripting.StlLoader; import com.neuronrobotics.bowlerstudio.util.FileChangeWatcher; +import com.neuronrobotics.bowlerstudio.vitamins.Vitamins; import com.neuronrobotics.imageprovider.NativeResource; //import com.neuronrobotics.imageprovider.OpenCVJNILoader; import com.neuronrobotics.javacad.JavaCadBuildInfo; @@ -38,6 +42,8 @@ import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; +import javafx.geometry.Rectangle2D; +import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; @@ -46,8 +52,17 @@ import javafx.stage.Stage; import org.dockfx.DockPane; -import javax.swing.*; -import java.awt.*; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRefNameException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.RefAlreadyExistsException; +import org.eclipse.jgit.api.errors.RefNotFoundException; +import org.eclipse.jgit.api.errors.TransportException; + +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.GraphicsEnvironment; +import java.awt.SplashScreen; import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -58,8 +73,13 @@ import java.net.URLConnection; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + @SuppressWarnings("restriction") public class BowlerStudio extends Application { final static SplashScreen splash = null;// = SplashScreen.getSplashScreen(); @@ -232,13 +252,25 @@ public static void select(MobileBase base, DHParameterKinematics limb) { * (Exception ex) { System.err.println("Limb not loaded yet"); } */ } - - public static void select(Affine globalPositionListener) { + /** + * Select a provided affine that is in a given global pose + * @param startingLocation the starting pose + * @param rootListener what affine to attach to + */ + public static void select(TransformNR startingLocation,Affine rootListener) { if (CreatureLab3dController.getEngine().isAutoHightlight()) { - CreatureLab3dController.getEngine().setSelected(globalPositionListener); + CreatureLab3dController.getEngine().setSelected(startingLocation,rootListener); + } + } + /** + * Select a provided affine that is in a given global pose + * @param rootListener what affine to attach to + */ + public static void select(Affine rootListener) { + if (CreatureLab3dController.getEngine().isAutoHightlight()) { + CreatureLab3dController.getEngine().setSelected(new TransformNR(),rootListener); } } - public static void select(MobileBase base, LinkConfiguration limb) { if (CreatureLab3dController.getEngine().isAutoHightlight()) { MobileBaseCadManager.get(base).selectCsgByLink(base, limb); @@ -263,13 +295,7 @@ public static void select(File script, int lineNumber) { } } - public static TransformNR getCamerFrame() { - return CreatureLab3dController.getEngine().getFlyingCamera().getCamerFrame(); - } - public static double getCamerDepth() { - return CreatureLab3dController.getEngine().getFlyingCamera().getZoomDepth(); - } /** * @param args the command line arguments @@ -278,6 +304,12 @@ public static double getCamerDepth() { @SuppressWarnings({ "unchecked", "restriction" }) public static void main(String[] args) throws Exception { + if (args.length != 0) { + //System.err.println("Arguments detected, starting Kernel mode."); + //SplashManager.closeSplash(); + BowlerKernel.main(args); + return; + } System.setOut(System.err);// send all prints to err until replaced with the terminal net.java.games.input.ControllerEnvironment.getDefaultEnvironment(); @@ -340,196 +372,231 @@ public double getCamerDepth() { return BowlerStudio.getCamerDepth(); } }); - if (args.length != 0) { - System.err.println("Arguments detected, starting Kernel mode."); - SplashManager.closeSplash(); - BowlerKernel.main(args); - } else { - renderSplashFrame(5, "Loging In..."); - // ScriptingEngine.logout(); - // switching to Web Flow auth - List listOfScopes = Arrays.asList("repo", "gist", "user", "admin:org", "admin:org_hook", - "workflow"); - if (OSUtil.isOSX()) - GitHubWebFlow.setOpen(new IURLOpen() { - public void open(URI toOpe) { - try { - BowlerStudio.openExternalWebpage(toOpe.toURL()); - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - }); - PasswordManager.setListOfScopes(listOfScopes); - GitHubWebFlow.setMyAPI(() -> { - String line = System.getProperty("API-ID"); - if (line != null) - return line; - return "1edf79fae494c232d4d2"; - }); - NameGetter mykey = new NameGetter(); - GitHubWebFlow.setName(mykey); - String myAssets = AssetFactory.getGitSource(); - if (PasswordManager.hasNetwork()) { - System.err.println("Attempt to log in with disk credentials"); - ScriptingEngine.waitForLogin(); - if (ScriptingEngine.isLoginSuccess()) { - if (BowlerStudio.hasNetwork()) { - ScriptingEngine.setAutoupdate(true); - - } - renderSplashFrame(15, "Load Configs"); + renderSplashFrame(5, "Loging In..."); + // ScriptingEngine.logout(); + // switching to Web Flow auth + List listOfScopes = Arrays.asList("repo", "gist", "user", "admin:org", "admin:org_hook", "workflow"); + if (OSUtil.isOSX()) + GitHubWebFlow.setOpen(new IURLOpen() { + public void open(URI toOpe) { try { - firstVer = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "firstVersion", - StudioBuildInfo.getVersion()); - } catch (Throwable t) { - System.err.println("Resetting the configs repo..."); - // clear the configs repo - ScriptingEngine.deleteRepo(ConfigurationDatabase.getGitSource()); - firstVer = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "firstVersion", - StudioBuildInfo.getVersion()); + BowlerStudio.openExternalWebpage(toOpe.toURL()); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } - ConfigurationDatabase.setObject("BowlerStudioConfigs", "currentVersion", + } + }); + PasswordManager.setListOfScopes(listOfScopes); + GitHubWebFlow.setMyAPI(() -> { + String line = System.getProperty("API-ID"); + if (line != null) + return line; + return "1edf79fae494c232d4d2"; + }); + NameGetter mykey = new NameGetter(); + GitHubWebFlow.setName(mykey); + String myAssets = AssetFactory.getGitSource(); + if (PasswordManager.hasNetwork()) { + System.err.println("Attempt to log in with disk credentials"); + ScriptingEngine.waitForLogin(); + if (ScriptingEngine.isLoginSuccess()) { + +// if (BowlerStudio.hasNetwork()) { +// ScriptingEngine.setAutoupdate(true); +// +// } + renderSplashFrame(15, "Load Configs"); + try { + firstVer = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "firstVersion", StudioBuildInfo.getVersion()); - renderSplashFrame(16, "Done Load Configs"); - myAssets = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "skinRepo", - "https://github.com/madhephaestus/BowlerStudioImageAssets.git"); - renderSplashFrame(20, "DL'ing Image Assets"); - System.err.println("Asset Repo " + myAssets); - - System.err.println("Asset intended ver " + StudioBuildInfo.getVersion()); + } catch (Throwable t) { + System.err.println("Resetting the configs repo..."); + // clear the configs repo + firstVer = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "firstVersion", + StudioBuildInfo.getVersion()); + } + ConfigurationDatabase.setObject("BowlerStudioConfigs", "currentVersion", StudioBuildInfo.getVersion()); + renderSplashFrame(16, "Done Load Configs"); +// myAssets = (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "assetRepo", +// myAssets); + renderSplashFrame(20, "DL'ing Image Assets"); + System.err.println("Asset Repo " + myAssets); + + System.err.println("Asset intended ver " + StudioBuildInfo.getVersion()); + ScriptingEngine.cloneRepo(myAssets, null); + try { + ScriptingEngine.pull(myAssets, "main"); + System.err.println("Studio version is the same"); + } catch (Exception e) { + e.printStackTrace(); + ScriptingEngine.deleteRepo(myAssets); ScriptingEngine.cloneRepo(myAssets, null); - try { - ScriptingEngine.pull(myAssets, "main"); - System.err.println("Studio version is the same"); - } catch (Exception e) { - e.printStackTrace(); - ScriptingEngine.deleteRepo(myAssets); - ScriptingEngine.cloneRepo(myAssets, null); - } + } - if (ScriptingEngine.checkOwner(myAssets)) { - if (!ScriptingEngine.tagExists(myAssets, StudioBuildInfo.getVersion())) { - System.out.println("Tagging Assets at " + StudioBuildInfo.getVersion()); - ScriptingEngine.tagRepo(myAssets, StudioBuildInfo.getVersion()); - } + if (ScriptingEngine.checkOwner(myAssets)) { + if (!ScriptingEngine.tagExists(myAssets, StudioBuildInfo.getVersion())) { + System.out.println("Tagging Assets at " + StudioBuildInfo.getVersion()); + ScriptingEngine.tagRepo(myAssets, StudioBuildInfo.getVersion()); } + } - if (BowlerStudio.hasNetwork()) { - renderSplashFrame(25, "Populating Menu"); - } - } else { - renderSplashFrame(20, "DL'ing Image Assets"); - ScriptingEngine.cloneRepo(myAssets, null); - ScriptingEngine.pull(myAssets, "main"); + if (BowlerStudio.hasNetwork()) { + renderSplashFrame(25, "Populating Menu"); } + } else { + renderSplashFrame(20, "DL'ing Image Assets"); + ScriptingEngine.cloneRepo(myAssets, null); + ScriptingEngine.pull(myAssets, "main"); } + } + layoutFile = AssetFactory.loadFile("layout/default.css"); + if (layoutFile == null || !layoutFile.exists()) { + ScriptingEngine.deleteRepo(myAssets); + ScriptingEngine.cloneRepo(myAssets, null); layoutFile = AssetFactory.loadFile("layout/default.css"); - if (layoutFile == null || !layoutFile.exists()) { - ScriptingEngine.deleteRepo(myAssets); + } + // SplashManager.setIcon(AssetFactory.loadAsset("BowlerStudioTrayIcon.png")); + renderSplashFrame(50, "DL'ing Tutorials..."); + // load tutorials repo - throw new RuntimeException("Style sheet does not exist"); - } - // SplashManager.setIcon(AssetFactory.loadAsset("BowlerStudioTrayIcon.png")); - renderSplashFrame(50, "DL'ing Tutorials..."); - // load tutorials repo - - Tutorial.getHomeUrl(); // Dowload and launch the Tutorial server - // force the current version in to the version number - ConfigurationDatabase.setObject("BowlerStudioConfigs", "skinBranch", StudioBuildInfo.getVersion()); - renderSplashFrame(53, "Loading Images"); - AssetFactory.setGitSource( - (String) ConfigurationDatabase.getObject("BowlerStudioConfigs", "skinRepo", myAssets), - ScriptingEngine.getBranch(myAssets)); - renderSplashFrame(54, "Load Assets"); - // Download and Load all of the assets - - renderSplashFrame(60, "Vitamins..."); - // load the vitimins repo so the demo is always snappy - ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/BowlerStudioVitamins.git", null); - - renderSplashFrame(80, "Example Robots"); - ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", null); - ScriptingEngine.pull("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git"); - renderSplashFrame(81, "CSG database"); - CSGDatabase.setDbFile(new File(ScriptingEngine.getWorkspace().getAbsoluteFile() + "/csgDatabase.json")); - - // System.err.println("Loading assets "); - - // System.err.println("Loading Main.fxml"); - renderSplashFrame(81, "Find arduino"); - String arduino = "arduino"; - if (NativeResource.isLinux()) { - - // Slic3r.setExecutableLocation("/usr/bin/slic3r"); - - } else if (NativeResource.isWindows()) { - arduino = "C:\\Program Files (x86)\\Arduino\\arduino.exe"; - if (!new File(arduino).exists()) { - arduino = "C:\\Program Files\\Arduino\\arduino.exe"; - } + Tutorial.getHomeUrl(); // Dowload and launch the Tutorial server + // force the current version in to the version number + // Download and Load all of the assets + + renderSplashFrame(60, "Vitamins..."); + // load the vitimins repo so the demo is always snappy + ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/BowlerStudioVitamins.git", null); + + renderSplashFrame(80, "Example Robots"); + ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", null); + ScriptingEngine.pull("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git"); + renderSplashFrame(81, "CSG database"); + CSGDatabase.setDbFile(new File(ScriptingEngine.getWorkspace().getAbsoluteFile() + "/csgDatabase.json")); + + // System.err.println("Loading assets "); + + // System.err.println("Loading Main.fxml"); + renderSplashFrame(81, "Find arduino"); + String arduino = "arduino"; + if (NativeResource.isLinux()) { + + // Slic3r.setExecutableLocation("/usr/bin/slic3r"); - } else if (NativeResource.isOSX()) { - arduino = "/Applications/Arduino.app/Contents/MacOS/Arduino"; + } else if (NativeResource.isWindows()) { + arduino = "C:\\Program Files (x86)\\Arduino\\arduino.exe"; + if (!new File(arduino).exists()) { + arduino = "C:\\Program Files\\Arduino\\arduino.exe"; } - try { - if (!new File(arduino).exists() && !NativeResource.isLinux()) { - boolean alreadyNotified = Boolean.getBoolean(ConfigurationDatabase - .getObject("BowlerStudioConfigs", "notifiedArduinoDep", false).toString()); - if (!alreadyNotified) { - ConfigurationDatabase.setObject("BowlerStudioConfigs", "notifiedArduinoDep", true); - String adr = arduino; - } + } else if (NativeResource.isOSX()) { + arduino = "/Applications/Arduino.app/Contents/MacOS/Arduino"; + } + try { + if (!new File(arduino).exists() && !NativeResource.isLinux()) { + boolean alreadyNotified = Boolean.getBoolean( + ConfigurationDatabase.getObject("BowlerStudioConfigs", "notifiedArduinoDep", false).toString()); + if (!alreadyNotified) { + ConfigurationDatabase.setObject("BowlerStudioConfigs", "notifiedArduinoDep", true); + String adr = arduino; } - System.err.println("Arduino exec found at: " + arduino); - ArduinoLoader.setARDUINOExec(arduino); - } catch (Exception e) { - reporter.uncaughtException(Thread.currentThread(), e); } - renderSplashFrame(82, "Set up UI"); - try { - UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - // This is a workaround for #8 and is only relavent on osx - // it causes the SwingNodes not to load if not called way ahead - // of time - javafx.scene.text.Font.getFamilies(); - } catch (Exception e) { - reporter.uncaughtException(Thread.currentThread(), e); + System.err.println("Arduino exec found at: " + arduino); + ArduinoLoader.setARDUINOExec(arduino); + } catch (Exception e) { + reporter.uncaughtException(Thread.currentThread(), e); - } - renderSplashFrame(90, "Loading STL Loader"); - // Add the engine handeler for STLs - ScriptingEngine.addScriptingLanguage(new StlLoader()); - // add a new link provider to the link factory - FirmataLink.addLinkFactory(); - // Log.enableInfoPrint(); - renderSplashFrame(91, "DL'ing Devices..."); - // ThreadUtil.wait(100); + } + renderSplashFrame(82, "Set up UI"); + try { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + // This is a workaround for #8 and is only relavent on osx + // it causes the SwingNodes not to load if not called way ahead + // of time + javafx.scene.text.Font.getFamilies(); + } catch (Exception e) { + reporter.uncaughtException(Thread.currentThread(), e); - try { - ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/HotfixBowlerStudio.git", null); - ScriptingEngine.cloneRepo("https://github.com/CommonWealthRobotics/DeviceProviders.git", null); - ScriptingEngine.pull("https://github.com/CommonWealthRobotics/HotfixBowlerStudio.git"); - ScriptingEngine.gitScriptRun("https://github.com/CommonWealthRobotics/HotfixBowlerStudio.git", - "hotfix.groovy", null); - ScriptingEngine.gitScriptRun("https://github.com/CommonWealthRobotics/DeviceProviders.git", - "loadAll.groovy", null); - } catch (Exception e) { - e.printStackTrace(); - reporter.uncaughtException(Thread.currentThread(), e); + } + renderSplashFrame(90, "Loading STL Loader"); + // Add the engine handeler for STLs + ScriptingEngine.addScriptingLanguage(new StlLoader()); + // add a new link provider to the link factory + FirmataLink.addLinkFactory(); + // Log.enableInfoPrint(); + renderSplashFrame(91, "DL'ing Devices..."); + // ThreadUtil.wait(100); + try { + ensureUpdated("https://github.com/CommonWealthRobotics/DHParametersCadDisplay.git", + "https://github.com/CommonWealthRobotics/HotfixBowlerStudio.git", + "https://github.com/CommonWealthRobotics/DeviceProviders.git", + "https://github.com/OperationSmallKat/Katapult.git"); + ScriptingEngine.gitScriptRun("https://github.com/CommonWealthRobotics/HotfixBowlerStudio.git", + "hotfix.groovy", null); + ScriptingEngine.gitScriptRun("https://github.com/CommonWealthRobotics/DeviceProviders.git", + "loadAll.groovy", null); + renderSplashFrame(92, "Vitamin Scripts..."); + HashSet urls = new HashSet<>(); + for (String type : Vitamins.listVitaminTypes()) { + String url = Vitamins.getScriptGitURL(type); + urls.add(url); } - renderSplashFrame(92, "Launching UI"); - launch(); + new Thread(() -> { + boolean wasState = ScriptingEngine.isPrintProgress(); + ScriptingEngine.setPrintProgress(false); + for (Iterator iterator = urls.iterator(); iterator.hasNext();) { + String url = iterator.next(); + + ensureUpdated(url); + + } + ScriptingEngine.setPrintProgress(wasState); + }).start(); + } catch (Exception e) { + e.printStackTrace(); + reporter.uncaughtException(Thread.currentThread(), e); } + renderSplashFrame(92, "Launching UI"); + launch(); + } + + private static void ensureUpdated(String ... urls) { + for(String s:urls) { + + ScriptingEngine.cloneRepo(s, null); + try { + ScriptingEngine.pull(s); + } catch (RefAlreadyExistsException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (RefNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidRefNameException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvalidRemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (TransportException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (GitAPIException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } // private static void removeAssets(String myAssets) // throws InvalidRemoteException, TransportException, GitAPIException, IOException, Exception { @@ -695,13 +762,37 @@ public void start(Stage primaryStage) { } renderSplashFrame(96, "UI Launch..."); - Scene scene = new Scene(mainControllerPanel.getRoot(), 1174, 768, true); + Parent root = mainControllerPanel.getRoot(); + FontSizeManager.addListener(fontNum->{ + BowlerStudioController.getBowlerStudio().setFontSize(fontNum); + double tmp = FontSizeManager.getImageScale()*9; - String nwfile = layoutFile.toURI().toString().replace("file:/", "file:///"); - - scene.getStylesheets().clear(); - scene.getStylesheets().add(nwfile); - System.err.println("Loading CSS from " + nwfile); + root.setStyle("-fx-font-size: "+((int)tmp)+"pt"); + }); + double sw = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() + .getDisplayMode().getWidth(); + double sh = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice() + .getDisplayMode().getHeight(); + Rectangle2D primaryScreenBounds = javafx.stage.Screen.getPrimary().getVisualBounds(); + double scalew = primaryScreenBounds.getWidth(); + double screenZoom = sw/scalew; + + if (FontSizeManager.getDefaultSize() == FontSizeManager.systemDefaultFontSize) { + double newSize= sw/2256.0*(2*FontSizeManager.systemDefaultFontSize)/screenZoom; + if(newSize { primaryStage.setScene(scene); @@ -728,7 +819,7 @@ public void start(Stage primaryStage) { }); BowlerStudio.runLater(() -> { - primaryStage.setTitle("Bowler Studio: v " + StudioBuildInfo.getVersion()); + setTitle(null); try { primaryStage.getIcons().add(AssetFactory.loadAsset("BowlerStudioTrayIcon.png")); @@ -781,6 +872,39 @@ public void onDeviceRemoved(BowlerAbstractDevice arg0) { } + public static void setTitle(String title) { + if(title==null) + title="Bowler Studio: v " + StudioBuildInfo.getVersion(); + if(primaryStage2!=null) + primaryStage2.setTitle(title); + } + + public static void setBowlerStudioCSS(Scene scene) { + String nwfile = layoutFile.toURI().toString().replace("file:/", "file:///"); + + scene.getStylesheets().clear(); + scene.getStylesheets().add(nwfile); + + System.err.println("Loading CSS from " + nwfile); + } + + public static void setToRunButton(Button b) { + b.setText("Run"); + b.setGraphic(AssetFactory.loadIcon("Run.png")); + b.getStyleClass().clear(); + b.getStyleClass().add("button-run"); + b.getStyleClass().add("button"); + b.setMinWidth(80); + } + public static void setToStopButton(Button b) { + b.setText("Stop"); + b.setGraphic(AssetFactory.loadIcon("Stop.png")); + b.getStyleClass().clear(); + b.getStyleClass().add("button"); + b.getStyleClass().add("button-stop"); + b.setMinWidth(80); + } + @SuppressWarnings("restriction") public static void closeBowlerStudio() { BowlerStudio.runLater(() -> { @@ -856,5 +980,35 @@ public static void invokeLater(Runnable object) { } }); } + + public static void moveCamera(TransformNR tf) { + runLater(()->{ + CreatureLab3dController.getEngine().moveCamera(tf); + }); + } + public static void setCamera(TransformNR tf) { + TransformNR current = getCamerFrame(); + TransformNR tfupde=current.inverse().times(tf); + runLater(()->{ + CreatureLab3dController.getEngine().moveCamera(tfupde); + }); + } + public static TransformNR getCamerFrame() { + return CreatureLab3dController.getEngine().getFlyingCamera().getCamerFrame(); + } + public static double getCamerDepth() { + return CreatureLab3dController.getEngine().getFlyingCamera().getZoomDepth(); + } + public static void zoomCamera(double increment) { + runLater(()->{ + CreatureLab3dController.getEngine().zoomIncrement(increment); + }); + } + public static TransformNR getTargetFrame() { + return CreatureLab3dController.getEngine().getTargetNR(); + } + public static void loadMobilBaseIntoUI(MobileBase base) { + BowlerStudioController.getBowlerStudio().onScriptFinished(base, base, null); + } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioController.java b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioController.java index 20b84b2f8..7c1875164 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioController.java @@ -123,7 +123,6 @@ public void setFontSize(int size) { for (String key : widgets.keySet()) { widgets.get(key).setFontSize(size); } - ConfigurationDatabase.setObject("BowlerStudioConfigs", "fontsize", size); } // Custom function for creation of New Tabs. @@ -417,6 +416,9 @@ public static void addUserNode(Node toadd) { public static void setSelectedCsg(CSG obj) { CreatureLab3dController.getEngine().setSelectedCsg(obj); } + public static void highlightCsg(CSG obj) { + CreatureLab3dController.getEngine().setSelectedCsg(obj,true); + } public static void setSelectedCsg(Vector3d v) { Affine manipulator2 = new Affine(); TransformNR poseToMove = new TransformNR(v.x, v.y, v.z, new RotationNR()); @@ -426,6 +428,15 @@ public static void setSelectedCsg(TransformNR poseToMove) { Affine manipulator2 = new Affine(); CreatureLab3dController.getEngine().focusToAffine(poseToMove, manipulator2); } + public static void setSelectedAffine(TransformNR poseToMove, Affine manipulator2) { + CreatureLab3dController.getEngine().focusToAffine(poseToMove, manipulator2); + } + public static void targetAndFollow(TransformNR poseToMove, Affine manipulator2) { + CreatureLab3dController.getEngine().targetAndFollow(poseToMove, manipulator2); + } + public static void setSelectedAffine(Affine af) { + CreatureLab3dController.getEngine().focusToAffine(af); + } public static void addCsg(CSG toadd, File source) { BowlerStudio.runLater(() -> { if (toadd != null) @@ -661,6 +672,8 @@ public static IMobileBaseUI getMobileBaseUI() { return mbui; } + + } \ No newline at end of file diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenu.java b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenu.java index 54e95ff43..edddec8f2 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenu.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenu.java @@ -8,6 +8,7 @@ import com.google.common.collect.Lists; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.creature.MobileBaseLoader; import com.neuronrobotics.bowlerstudio.scripting.IGithubLoginListener; import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; @@ -15,6 +16,7 @@ import com.neuronrobotics.bowlerstudio.scripting.ScriptingFileWidget; import com.neuronrobotics.bowlerstudio.tabs.LocalFileScriptTab; import com.neuronrobotics.bowlerstudio.vitamins.Vitamins; +import com.neuronrobotics.nrconsole.util.CommitWidget; //import com.neuronrobotics.imageprovider.CHDKImageProvider; import com.neuronrobotics.nrconsole.util.FileSelectionFactory; import com.neuronrobotics.nrconsole.util.PromptForGit; @@ -38,6 +40,7 @@ import org.eclipse.jgit.api.errors.CheckoutConflictException; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; @@ -213,7 +216,7 @@ public void setToLoggedOut() { myGists.getItems().clear(); logoutGithub.disableProperty().set(true); logoutGithub.setText("Anonymous"); - ConfigurationDatabase.loginEvent(null); + //ConfigurationDatabase.loginEvent(null); this.username=null; }); while(this.username!=null) @@ -236,7 +239,7 @@ private void setToLoggedIn(final String n) { logoutGithub.setText("Log out " + username); new Thread() { public void run() { - ConfigurationDatabase.loginEvent(username); + //ConfigurationDatabase.loginEvent(username); ConfigurationDatabase.getParamMap("workspace"); BowlerStudioMenuWorkspace.loginEvent(); if (!PasswordManager.hasNetwork()) @@ -409,6 +412,7 @@ private void LoadGistMenu(GitHub github) { for (GHGist gist : gists) { String url = gist.getGitPushUrl(); + String desc = gist.getDescription(); if (desc == null || desc.length() == 0 || desc.contentEquals("Adding new file from BowlerStudio")) { desc = gist.getFiles().keySet().toArray()[0].toString(); @@ -447,7 +451,8 @@ public static String gitURLtoMessage(String url) { } public static void setUpRepoMenue(Menu repoMenue, String url, boolean useAddToWorkspaceItem, boolean threaded) { - setUpRepoMenue(repoMenue, url, useAddToWorkspaceItem, threaded, gitURLtoMessage(url)); + if(url.endsWith(".git")) + setUpRepoMenue(repoMenue, url, useAddToWorkspaceItem, threaded, gitURLtoMessage(url)); } private static void resetRepoMenue(Menu repoMenue, GHRepository repo) { @@ -507,17 +512,21 @@ public void run() { updateRepo.setOnAction(event -> { new Thread() { + @SuppressWarnings("restriction") public void run() { try { ScriptingEngine.pull(url, ScriptingEngine.getBranch(url)); - } catch (Exception e) { - ScriptingEngine.deleteRepo(url); - try { - ScriptingEngine.checkout(url, ScriptingEngine.getBranch(url)); - } catch (Exception ex) { - exp.uncaughtException(Thread.currentThread(), ex); - } - + } catch(WrongRepositoryStateException ex) { + // ignore unsaved files + BowlerStudio.runLater(() -> { + @SuppressWarnings("restriction") + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("You have Un-Saved work, commit first"); + alert.setHeaderText("You have Un-Saved work, commit first"); + alert.setContentText("You have Un-Saved work, commit first"); + }); + }catch (Exception e) { + BowlerStudioMenu.checkandDelete(url); } myEvent.run(); // selfRef.onRefresh(null); @@ -562,23 +571,7 @@ public void run() { MenuItem delete = new MenuItem("Delete Local Copy..."); delete.setOnAction(event->{ - Alert alert = new Alert(AlertType.CONFIRMATION); - alert.setTitle("Are you sure you have published all your work?"); - alert.setHeaderText("This will wipe out the local cache for "+url); - alert.setContentText("All files that are not published will be deleted"); - - Optional result = alert.showAndWait(); - if (result.get() == ButtonType.OK) { - new Thread(() -> { - ScriptingEngine.deleteRepo(url); - BowlerStudioMenuWorkspace.remove(url); - BowlerStudio.runLater(()->{ - BowlerStudioMenuWorkspace.sort(); - }); - }).start(); - } else { - System.out.println("Nothing was deleted"); - } + checkandDelete(url); }); @@ -598,13 +591,33 @@ public void run() { } + + }; if (threaded) t.start(); else t.run(); } - + public static void checkandDelete(String url) { + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Are you sure you have published all your work?"); + alert.setHeaderText("This will wipe out the local cache for "+url); + alert.setContentText("All files that are not published will be deleted"); + + Optional result = alert.showAndWait(); + if (result.get() == ButtonType.OK) { + new Thread(() -> { + ScriptingEngine.deleteRepo(url); + BowlerStudioMenuWorkspace.remove(url); + BowlerStudio.runLater(()->{ + BowlerStudioMenuWorkspace.sort(); + }); + }).start(); + } else { + System.out.println("Nothing was deleted"); + } + } private static MenuResettingEventHandler createLoadCommitsEvent(String url, Menu orgCommits) { return new MenuResettingEventHandler() { public boolean gistFlag = false; @@ -1427,7 +1440,6 @@ assert getMeneBarBowlerStudio() != null new Thread() { public void run() { try { - ScriptingEngine.setAutoupdate(true); File f = ScriptingEngine.fileFromGit( "https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", // git // repo, @@ -1498,10 +1510,10 @@ public void onLogin(String arg0) { } // WindowMenu - int[] fonts = new int[] { 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40 }; + int[] fonts =FontSizeManager.getFontOptions(); Menu fontSelect = new Menu("Font Size"); ToggleGroup toggleGroup = new ToggleGroup(); - int defSize = ((Number) ConfigurationDatabase.getObject("BowlerStudioConfigs", "fontsize", 12)).intValue(); + int defSize =FontSizeManager.getDefaultSize(); for (int i = 0; i < fonts.length; i++) { int myFoneNum = fonts[i]; RadioMenuItem ftmp = new RadioMenuItem(myFoneNum + " pt"); @@ -1510,14 +1522,22 @@ public void onLogin(String arg0) { ftmp.setSelected(true); } else ftmp.setSelected(false); - ftmp.setOnAction((event) -> { + EventHandler eventHandler = (event) -> { if (ftmp.isSelected()) { - BowlerStudioController.getBowlerStudio().setFontSize(myFoneNum); + FontSizeManager.setFontSize(myFoneNum); } - }); + }; + ftmp.setOnAction(eventHandler); ftmp.setToggleGroup(toggleGroup); fontSelect.getItems().add(ftmp); - + FontSizeManager.addListener(nf->{ + ftmp.setOnAction(null); + if(myFoneNum==nf) { + ftmp.setSelected(true); + }else + ftmp.setSelected(false); + ftmp.setOnAction(eventHandler); + }); } WindowMenu.getItems().add(fontSelect); CheckMenuItem autohighlight = new CheckMenuItem("Auto Highlight 3d Items"); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenuWorkspace.java b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenuWorkspace.java index 6ef969249..841808511 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenuWorkspace.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioMenuWorkspace.java @@ -8,6 +8,7 @@ import java.util.Set; import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.WrongRepositoryStateException; import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; @@ -15,7 +16,9 @@ import com.neuronrobotics.sdk.util.ThreadUtil; import javafx.application.Platform; +import javafx.scene.control.Alert; import javafx.scene.control.Menu; +import javafx.scene.control.Alert.AlertType; @SuppressWarnings("restriction") public class BowlerStudioMenuWorkspace { @@ -42,25 +45,26 @@ public static void loginEvent() { try { String o = (String) getWorkspaceData().keySet().toArray()[i]; if (o.endsWith(".git")) { + boolean wasState = ScriptingEngine.isPrintProgress(); + ScriptingEngine.setPrintProgress(false); System.err.println("Pulling workspace " + o); try { if (!ScriptingEngine.isUrlAlreadyOpen(o)) ScriptingEngine.pull(o); - } catch (Throwable e) { - try { - ScriptingEngine.pull(o); - } catch (InvalidRemoteException ex) { - System.err.println("Deleting repo from workspace " + ex.getMessage()); - getWorkspaceData().remove(o); - ScriptingEngine.deleteRepo(o); - } catch (Throwable ex) { - e.printStackTrace(); - getWorkspaceData().remove(o); - // ScriptingEngine.deleteRepo(o); - // i--; - } + } catch(WrongRepositoryStateException ex) { + // ignore, unsaved work + }catch (Exception e) { + BowlerStudioMenu.checkandDelete(o); + }catch (Throwable ex) { + ex.printStackTrace(); + getWorkspaceData().remove(o); + // ScriptingEngine.deleteRepo(o); + // i--; } - }else { + ScriptingEngine.setPrintProgress(wasState); + + + } else { getWorkspaceData().remove(o); } } catch (Exception e) { @@ -92,7 +96,7 @@ public static void add(String url, String menueMessage) { data.add(menueMessage); data.add(new Long(System.currentTimeMillis()).toString()); getWorkspaceData().put(url, data); - System.out.println("Workspace add: " + url); + //System.out.println("Workspace add: " + url); } } // data = (ArrayList) workspaceData.get(url); @@ -171,7 +175,7 @@ public static void sort() { new Thread(() -> { for (String url : menu) { - System.out.println("Workspace : " + url); + //System.out.println("Workspace : " + url); ArrayList arrayList = (ArrayList) getWorkspaceData().get(url); if (arrayList != null) BowlerStudioMenu.setUpRepoMenue(workspaceMenu, url, false, false, arrayList.get(0)); @@ -188,7 +192,7 @@ public static void sort() { ex.printStackTrace(); } if (rankChanged) { - System.out.println("Sorting workspace..."); + //System.out.println("Sorting workspace..."); new Thread(() -> { ConfigurationDatabase.save(); }).start(); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioModularFrame.java b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioModularFrame.java index 5ccc4aa0a..b80cf7c2c 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioModularFrame.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/BowlerStudioModularFrame.java @@ -106,7 +106,7 @@ void initialize() throws Exception { BowlerStudio.runLater(()->{ try { - webtab = new WebTab("Tutorial", homeURL, true); + webtab = new WebTab("Documentation", homeURL, true); setTutorialDockNode(new DockNode(webtab.getContent(), webtab.getText(), webtab.getGraphic())); getTutorialDockNode().setPrefSize(1024, 730); } catch (IOException | InterruptedException e) { diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/ChangeAssetRepoController.java b/src/main/java/com/neuronrobotics/bowlerstudio/ChangeAssetRepoController.java index b6a025237..26e3b2100 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/ChangeAssetRepoController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/ChangeAssetRepoController.java @@ -2,6 +2,8 @@ import com.neuronrobotics.bowlerstudio.assets.AssetFactory; import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; + import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; @@ -36,7 +38,12 @@ public void start(Stage primaryStage) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); - + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); BowlerStudio.runLater(() -> { primaryStage.setTitle("Change Asset Repository"); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/MakeReleaseController.java b/src/main/java/com/neuronrobotics/bowlerstudio/MakeReleaseController.java index feea4214d..4f7df7c3e 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/MakeReleaseController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/MakeReleaseController.java @@ -17,6 +17,7 @@ import javafx.scene.control.TextField; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.sdk.util.ThreadUtil; @@ -234,6 +235,12 @@ public void start(Stage st) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); tags = ScriptingEngine.getAllTags(gitRepo); for (String s : tags) { listOfTags.getItems().add(s); @@ -243,7 +250,7 @@ public void start(Stage st) throws Exception { String[] top = topValue.split("\\."); String majorStart = top[0]; String minorStart = top[1]; - String bugStart = "" + (Integer.parseInt(top[2]) + 1); + String bugStart = "" + (Integer.parseInt(top[2].split("-")[0]) + 1); major.setText(majorStart); minor.setText(minorStart); bugfix.setText(bugStart); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/NewVitaminWizardController.java b/src/main/java/com/neuronrobotics/bowlerstudio/NewVitaminWizardController.java index f7db086a9..619f58c5e 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/NewVitaminWizardController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/NewVitaminWizardController.java @@ -18,6 +18,7 @@ import org.kohsuke.github.GitHub; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.bowlerstudio.vitamins.Vitamins; @@ -580,6 +581,12 @@ public void start(Stage primaryStage) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); BowlerStudio.runLater(() -> { primaryStage.setTitle("Edit Vitamins Wizard"); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/Terminal.java b/src/main/java/com/neuronrobotics/bowlerstudio/Terminal.java index 6ba79b2eb..773d6da17 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/Terminal.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/Terminal.java @@ -5,6 +5,7 @@ **/ import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; //import com.neuronrobotics.imageprovider.OpenCVImageProvider; import com.neuronrobotics.sdk.common.Log; @@ -141,6 +142,10 @@ public void run() { try { icon = AssetFactory.loadAsset("Script-Tab-" + langauges.getSelectionModel().getSelectedItem() + ".png"); langaugeIcon.setImage(icon); + FontSizeManager.addListener(fontNum->{ + langaugeIcon.setScaleX(FontSizeManager.getImageScale()); + langaugeIcon.setScaleY(FontSizeManager.getImageScale()); + }); } catch (Exception e2) { // TODO Auto-generated catch block e2.printStackTrace(); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/assets/BowlerStudioResourceFactory.java b/src/main/java/com/neuronrobotics/bowlerstudio/assets/BowlerStudioResourceFactory.java index ab05a6ab8..f149a57e8 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/assets/BowlerStudioResourceFactory.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/assets/BowlerStudioResourceFactory.java @@ -70,6 +70,13 @@ public static void load() throws Exception { try { githubLogin.load(); + javafx.scene.Parent root = githubLogin.getRoot(); + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); } catch (IOException e) { Logger.getLogger(BowlerStudio.class.getName()).log(Level.SEVERE, null, e); } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLab.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLab.java index 3cdbd1016..ebd05144e 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLab.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLab.java @@ -3,33 +3,26 @@ import com.neuronrobotics.bowlerstudio.BowlerStudio; import com.neuronrobotics.bowlerstudio.BowlerStudioController; import com.neuronrobotics.bowlerstudio.BowlerStudioModularFrame; -import com.neuronrobotics.bowlerstudio.IssueReportingExceptionHandler; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.bowlerstudio.tabs.AbstractBowlerStudioTab; -import com.neuronrobotics.bowlerstudio.util.FileWatchDeviceWrapper; import com.neuronrobotics.sdk.addons.gamepad.BowlerJInputDevice; import com.neuronrobotics.sdk.addons.kinematics.DHLink; import com.neuronrobotics.sdk.addons.kinematics.DHParameterKinematics; -import com.neuronrobotics.sdk.addons.kinematics.DhInverseSolver; import com.neuronrobotics.sdk.addons.kinematics.IDriveEngine; import com.neuronrobotics.sdk.addons.kinematics.MobileBase; import com.neuronrobotics.sdk.common.BowlerAbstractDevice; -import com.neuronrobotics.sdk.common.IDeviceConnectionEventListener; import com.neuronrobotics.sdk.util.ThreadUtil; -import javafx.application.Platform; -import javafx.beans.InvalidationListener; -import javafx.beans.property.Property; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.fxml.FXMLLoader; +import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Group; import javafx.scene.Parent; import javafx.scene.control.*; import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.VBox; -import javafx.scene.layout.HBox; +import javafx.scene.layout.GridPane; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; @@ -41,6 +34,7 @@ public class CreatureLab extends AbstractBowlerStudioTab implements IOnEngineeringUnitsChange { private BowlerAbstractDevice pm; + private boolean enabled=true; private IDriveEngine defaultDriveEngine; // private DhInverseSolver defaultDHSolver; @@ -48,15 +42,16 @@ public class CreatureLab extends AbstractBowlerStudioTab implements IOnEngineeri private ProgressIndicator pi; private MobileBaseCadManager baseManager; - private CheckBox autoRegen = new CheckBox("Auto-Generate CAD"); - private Button regen=new Button("Generate Cad Now"); + private CheckBox autoRegen = new CheckBox("Auto"); + private Button regen=new Button("Generate Vitamins Now"); Parent root; private BowlerJInputDevice gameController = null; CreatureLabControlsTab tab = new CreatureLabControlsTab(); - + boolean stateOfAutoWhenForced = true; private long timeSinceLastUpdate = 0; - private HBox radioOptions;; + private GridPane radioOptions; + private long timeOfLastDisable=0; @Override public void onTabClosing() { @@ -76,24 +71,26 @@ public void initializeUI(BowlerAbstractDevice pm) { this.pm = pm; autoRegen.setSelected(true); - disable(); autoRegen.setOnAction(event -> { - regenFromUiEvent(); + stateOfAutoWhenForced = autoRegen.isSelected(); + baseManager.setAutoRegen(autoRegen.isSelected()); + //BowlerStudio.runLater(() -> { + regenFromUiEvent(); + //}); }); regen.setOnAction(event -> { + stateOfAutoWhenForced = autoRegen.isSelected(); autoRegen.setSelected(true); - regenFromUiEvent(); + baseManager.setAutoRegen(true); + //BowlerStudio.runLater(()->{ + regenFromUiEvent(); + //}); }); regen.setGraphic(AssetFactory.loadIcon("Generate-Cad.png")); // TODO Auto-generated method stub setText(pm.getScriptingName()); - try { - ScriptingEngine.setAutoupdate(true); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } + MobileBase device = (MobileBase) pm; // Button save = new Button("Save Configuration"); @@ -131,27 +128,19 @@ public void initializeUI(BowlerAbstractDevice pm) { } private void regenFromUiEvent() { + if (System.currentTimeMillis() - timeSinceLastUpdate < 500) { + return; + } + System.out.println("Regenerating robot "+System.currentTimeMillis()); + timeSinceLastUpdate = System.currentTimeMillis(); BowlerStudio.runLater(() -> { - if (System.currentTimeMillis() - timeSinceLastUpdate < 500) { - return; - } - timeSinceLastUpdate = System.currentTimeMillis(); - if (autoRegen.isSelected()) { - disable(); - } - baseManager.setAutoRegen(autoRegen.isSelected()); if (autoRegen.isSelected()) { generateCad(); } }); } - private void disable() { - autoRegen.setDisable(true); - if (radioOptions != null) - radioOptions.setDisable(true); - regen.setDisable(true); - } + private void finishLoading(MobileBase device) { @@ -183,15 +172,17 @@ private void finishLoading(MobileBase device) { // @JansenSmith - placed contents in llambda runnable - 20220915 BowlerStudio.runLater(() -> { TreeView tree = new TreeView<>(rootItemFinal); + treebox1.getChildren().clear(); treebox1.getChildren().add(tree); + AnchorPane.setTopAnchor(tree, 0.0); AnchorPane.setLeftAnchor(tree, 0.0); AnchorPane.setRightAnchor(tree, 0.0); AnchorPane.setBottomAnchor(tree, 0.0); HashMap, Runnable> callbackMapForTreeitems = new HashMap<>(); - HashMap, Group> widgetMapForTreeitems = new HashMap<>(); + HashMap, Parent> widgetMapForTreeitems = new HashMap<>(); File source; boolean creatureIsOwnedByUser = false; try { @@ -206,49 +197,25 @@ private void finishLoading(MobileBase device) { MobileBaseCadManager.get(device, BowlerStudioController.getMobileBaseUI()); MobleBaseMenueFactory.load(device, tree, mainBaseFinal, callbackMapForTreeitems, widgetMapForTreeitems, this, true, creatureIsOwnedByUser); - tree.setPrefWidth(325); + //tree.setPrefWidth(325); + treebox1.widthProperty().addListener((obs, oldVal, newVal) -> { + //System.out.println("Creature lab width "+newVal); + tree.setPrefWidth((double)newVal); + }); tree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); JogMobileBase walkWidget = new JogMobileBase(device); - tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { - - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) { - @SuppressWarnings("unchecked") - TreeItem treeItem = (TreeItem) newValue; - new Thread() { - public void run() { - - if (callbackMapForTreeitems.get(treeItem) != null) { - callbackMapForTreeitems.get(treeItem).run(); - } - AnchorPane box = hasWalking(device) ? tab.getControlsBox() : tab.getWalkingBox(); - if (widgetMapForTreeitems.get(treeItem) != null) { - - BowlerStudio.runLater(() -> { - box.getChildren().clear(); - Group g = widgetMapForTreeitems.get(treeItem); - box.getChildren().add(g); - AnchorPane.setTopAnchor(g, 0.0); - AnchorPane.setLeftAnchor(g, 0.0); - AnchorPane.setRightAnchor(g, 0.0); - AnchorPane.setBottomAnchor(g, 0.0); - }); - } else { - BowlerStudio.runLater(() -> { - box.getChildren().clear(); - }); - } - } - - }.start(); + tree.getSelectionModel().selectedItemProperty().addListener((ChangeListener) (observable, oldValue, newValue) -> { + tree.autosize(); + @SuppressWarnings("unchecked") + TreeItem treeItem = (TreeItem) newValue; + mainWidget(device, callbackMapForTreeitems, widgetMapForTreeitems, walkWidget, treeItem); - } }); if (hasWalking(device)) { tab.setOverlayTopRight(walkWidget); } }); - VBox progress = new VBox(10); + //VBox progress = new VBox(10); final ToggleGroup group = new ToggleGroup(); @@ -256,61 +223,105 @@ public void run() { rb1.setToggleGroup(group); rb1.setSelected(true); rb1.setOnAction(event -> { + //disable(); + //autoRegen.setText("Auto-Generate CAD"); + regen.setText("Generate CAD Now"); + BowlerStudio.runLater(() ->setCadMode(false)); }); + regen.setMinWidth(120); RadioButton rb2 = new RadioButton(); rb2.setToggleGroup(group); rb2.fire(); rb2.setOnAction(event -> { + //disable(); + + //autoRegen.setText("Auto-Generate Vitamins"); + regen.setText("Generate Vitamins Now"); BowlerStudio.runLater(() ->setCadMode(true)); }); - radioOptions = new HBox(10); - radioOptions.getChildren().addAll(new Label("Cad"), rb1, rb2, new Label("Config")); + radioOptions = new GridPane(); + radioOptions.setPadding(new Insets(10, 10, 10, 10)); + radioOptions.setVgap(5); + radioOptions.setHgap(5); + + // Setting the Grid alignment + radioOptions.setAlignment(Pos.CENTER); + radioOptions.add(new Label("Select Display Mode:"), 0, 0); + radioOptions.add(new Label("Cad Generation"), 0, 1); + radioOptions.add(rb1, 1, 1); + + radioOptions.add(new Label("Vitamins View"), 0, 2); + radioOptions.add(rb2, 1, 2); pi = new ProgressIndicator(0); baseManager = MobileBaseCadManager.get(device, BowlerStudioController.getMobileBaseUI()); pi.progressProperty().bindBidirectional(baseManager.getProcesIndictor()); - HBox progressIndicatorPanel = new HBox(10); - progress.getChildren().addAll( regen,autoRegen, radioOptions); - progressIndicatorPanel.getChildren().addAll( progress,pi); + radioOptions.add(pi, 1, 0); + radioOptions.add(autoRegen, 1, 3); + radioOptions.add(regen,0,3); + - progressIndicatorPanel.setStyle("-fx-background-color: #FFFFFF;"); - progressIndicatorPanel.setOpacity(.7); - progressIndicatorPanel.setMinHeight(100); - progressIndicatorPanel.setPrefSize(325, 150); - tab.setOverlayTop(progressIndicatorPanel); + tab.setOverlayTop(radioOptions); BowlerStudioModularFrame.getBowlerStudioModularFrame().showCreatureLab(); setCadMode(true);// start the UI in config mode - generateCad(); - pi.progressProperty().addListener(new ChangeListener() { + } + + private void mainWidget(MobileBase device, HashMap, Runnable> callbackMapForTreeitems, + HashMap, Parent> widgetMapForTreeitems, JogMobileBase walkWidget, + TreeItem treeItem) { + new Thread() { + public void run() { + + if (callbackMapForTreeitems.get(treeItem) != null) { + callbackMapForTreeitems.get(treeItem).run(); + } + AnchorPane box = hasWalking(device) ? tab.getControlsBox() : tab.getWalkingBox(); + if (widgetMapForTreeitems.get(treeItem) != null) { - @Override - public void changed(ObservableValue observable, Number oldValue, Number newValue) { - System.out.println("Progress listener " + newValue); - if (newValue.doubleValue() > 0.99) { BowlerStudio.runLater(() -> { - enable(); + box.getChildren().clear(); + Parent g = widgetMapForTreeitems.get(treeItem); + box.getChildren().add(g); + AnchorPane.setTopAnchor(g, 0.0); + AnchorPane.setLeftAnchor(g, 0.0); + AnchorPane.setRightAnchor(g, 0.0); + AnchorPane.setBottomAnchor(g, 0.0); }); - }else { + } else { BowlerStudio.runLater(() -> { - disable(); + box.getChildren().clear(); + if (hasWalking(device)) { + tab.setOverlayTopRight(walkWidget); + } }); } } - + }.start(); + } + private void disable() { + enabled=false; + BowlerStudio.runLater(() -> { + autoRegen.setDisable(true); + if (radioOptions != null) + radioOptions.setDisable(true); + regen.setDisable(true); }); } private void enable() { - autoRegen.setDisable(false); - if (radioOptions != null) - radioOptions.setDisable(false); - regen.setDisable(false); + enabled=true; + BowlerStudio.runLater(() -> { + autoRegen.setDisable(false); + if (radioOptions != null) + radioOptions.setDisable(false); + regen.setDisable(false); + }); } private boolean hasWalking(MobileBase device) { return device.getLegs().size() > 0 || device.getSteerable().size() > 0 || device.getDrivable().size() > 0; @@ -325,8 +336,14 @@ private void setCadMode(boolean mode) { } public void generateCad() { - // new Exception().printStackTrace(); - baseManager.generateCad(); + //new RuntimeException().printStackTrace(); + if(!enabled) + return; + disable(); + baseManager.generateCadWithEnd(()->{ + enable(); + autoRegen.setSelected(stateOfAutoWhenForced ); + }); } @Override diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLabControlsTab.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLabControlsTab.java index 750eab81b..e5ff55b09 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLabControlsTab.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreatureLabControlsTab.java @@ -4,6 +4,7 @@ import javafx.fxml.FXML; import javafx.scene.control.TreeView; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; @@ -25,17 +26,17 @@ public AnchorPane getWalkingBox() { return walkingBox; } - public void setWalkingBox(AnchorPane walkingBox) { - this.walkingBox = walkingBox; - } +// public void setWalkingBox(AnchorPane walkingBox) { +// this.walkingBox = walkingBox; +// } public AnchorPane getControlsBox() { - return controlsBox; + return walkingBox; } - public void setControlsBox(AnchorPane controlsBox) { - this.controlsBox = controlsBox; - } +// public void setControlsBox(AnchorPane controlsBox) { +// this.controlsBox = controlsBox; +// } // public AnchorPane getProgressBar() { // return progressBar; @@ -54,15 +55,15 @@ public void setTreeBox(AnchorPane treeBox) { } - public void setOverlayTop(HBox progress) { + public void setOverlayTop(GridPane radioOptions) { // TODO Auto-generated method stub BowlerStudio.runLater(()->{ progressBar.getChildren().clear(); - progressBar.getChildren().add(progress); - AnchorPane.setTopAnchor(progress, 0.0); - AnchorPane.setLeftAnchor(progress, 0.0); - AnchorPane.setRightAnchor(progress, 0.0); - AnchorPane.setBottomAnchor(progress, 0.0); + progressBar.getChildren().add(radioOptions); + AnchorPane.setTopAnchor(radioOptions, 0.0); + AnchorPane.setLeftAnchor(radioOptions, 0.0); + AnchorPane.setRightAnchor(radioOptions, 0.0); + AnchorPane.setBottomAnchor(radioOptions, 0.0); }); } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreaturePhysicsWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreaturePhysicsWidget.java deleted file mode 100644 index 774a4f14a..000000000 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/CreaturePhysicsWidget.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.neuronrobotics.bowlerstudio.creature; - -import com.neuronrobotics.bowlerstudio.BowlerStudio; -import com.neuronrobotics.bowlerstudio.BowlerStudioController; -import com.neuronrobotics.bowlerstudio.CreatureLab3dController; -import com.neuronrobotics.bowlerstudio.assets.AssetFactory; -import com.neuronrobotics.bowlerstudio.physics.MobileBasePhysicsManager; -import com.neuronrobotics.bowlerstudio.physics.PhysicsEngine; -import com.neuronrobotics.bowlerstudio.threed.BowlerStudio3dEngine; -import com.neuronrobotics.sdk.addons.kinematics.LinkConfiguration; -import com.neuronrobotics.sdk.addons.kinematics.MobileBase; -import com.neuronrobotics.sdk.addons.kinematics.imu.IMUUpdate; -import com.neuronrobotics.sdk.addons.kinematics.imu.IMUUpdateListener; -import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR; -import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; -import com.neuronrobotics.sdk.common.BowlerAbstractDevice; -import com.neuronrobotics.sdk.common.IDeviceConnectionEventListener; -import com.neuronrobotics.sdk.util.ThreadUtil; -import eu.mihosoft.vrl.v3d.CSG; -import javafx.application.Platform; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import javafx.scene.layout.GridPane; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Set; - -public class CreaturePhysicsWidget extends GridPane implements IMUUpdateListener { - Button runstop = new Button("Run", AssetFactory.loadIcon("Run.png")); - Button pauseresume = new Button("Pause", AssetFactory.loadIcon("Pause.png")); - Button step = new Button("Step", AssetFactory.loadIcon("Step.png")); - TextField msLoopTime =new TextField("20") ; - int msLoopTimeInt =0; - private boolean run=false; - private boolean takestep=false; - private boolean pause=false; - Thread physicsThread =null; - private Set oldParts=null; - private MobileBase base; - - @SuppressWarnings("restriction") - public CreaturePhysicsWidget(MobileBase base){ - - this.base = base; - base.addConnectionEventListener(new IDeviceConnectionEventListener() { - - @Override - public void onDisconnect(BowlerAbstractDevice arg0) { - BowlerStudio.runLater(()->{ - stop(); - }); - } - - @Override - public void onConnect(BowlerAbstractDevice arg0) {} - }); - add(runstop,0,0); - add(pauseresume,1,0); - add(step,2,0); - add(new Label("MS loop"),3,0); - add(msLoopTime,4,0); - pauseresume.setDisable(true); - step.setDisable(true); - pauseresume.setOnAction(event->{ - if(!isPause()){ - pauseresume.setGraphic(AssetFactory.loadIcon("Resume.png")); - pauseresume.setText("Resume"); - step.setDisable(false); - }else{ - pauseresume.setGraphic(AssetFactory.loadIcon("Pause.png")); - pauseresume.setText("Pause"); - step.setDisable(true); - } - setPause(!isPause()); - }); - step.setOnAction(event->{ - setTakestep(true); - }); - runstop.setOnAction(event->{ - if(isRun()){ - stop(); -// new Thread(){ -// public void run(){ -// ThreadUtil.wait(50); -// System.gc();// clean up any objects created by the physics engine -// } -// }.start(); - }else{ - //System.gc();// clean up any objects created by the physics engine - runstop.setGraphic(AssetFactory.loadIcon("Stop.png")); - runstop.setText("Stop"); - msLoopTime.setDisable(true); - pauseresume.setDisable(false); - base.getImu().addvirtualListeners(this); - new Thread(){ - - - public void run(){ - while(MobileBaseCadManager.get( base).getProcesIndictor().get()<1){ - ThreadUtil.wait(10); - } - HashMap> simplecad = MobileBaseCadManager.getSimplecad(base) ; - ArrayList baseCad=MobileBaseCadManager.getBaseCad(base); - base.DriveArc(new TransformNR(.01,0,0,new RotationNR()), 0); - PhysicsEngine.get().clear(); - MobileBasePhysicsManager m =new MobileBasePhysicsManager(base, baseCad, simplecad); - //BowlerStudio3dEngine threeD = BowlerStudioController.getBowlerStudio().getJfx3dmanager(); - oldParts = CreatureLab3dController.getEngine().getCsgMap().keySet(); - BowlerStudioController.setCsg(PhysicsEngine.get().getCsgFromEngine()); - int loopTiming = (int) Double.parseDouble(msLoopTime.getText()); - - physicsThread = new Thread(){ - public void run(){ - try{ - while(!Thread.interrupted() && isRun()){ - while(!Thread.interrupted() && isPause() && isTakestep()==false){ - ThreadUtil.wait(loopTiming); - } - setTakestep(false); - long start = System.currentTimeMillis(); - PhysicsEngine.get().stepMs(loopTiming); - long took = (System.currentTimeMillis() - start); - if (took < loopTiming) - ThreadUtil.wait((int) (loopTiming - took)/4); - else{ - if(took>loopTiming*2) - System.out.println("ERROR Real time broken by: "+took+"ms"); - } - } - PhysicsEngine.get().clear(); - m.clear(); - }catch(Exception e){ - e.printStackTrace(); - } - } - }; - physicsThread.start(); - } - }.start(); - - } - setRun(!isRun()); - }); - - } - private void stop() { - runstop.setGraphic(AssetFactory.loadIcon("Run.png")); - runstop.setText("Run"); - if(physicsThread!=null) - physicsThread.interrupt(); - - msLoopTime.setDisable(false); - pauseresume.setDisable(true); - if(oldParts!=null){ - ArrayListoldp=new ArrayList<>(); - for(CSG c:oldParts){ - oldp.add(c); - } - BowlerStudioController.setCsg(oldp); - oldParts=null; - } - base.getImu().removevirtualListeners(this); - } - public boolean isTakestep() { - return takestep; - } - public void setTakestep(boolean takestep) { - this.takestep = takestep; - } - public boolean isPause() { - return pause; - } - public void setPause(boolean pause) { - this.pause = pause; - } - public boolean isRun() { - return run; - } - public void setRun(boolean run) { - this.run = run; - } - @Override - public void onIMUUpdate(IMUUpdate arg0) { -// System.err.println("X = "+arg0.getxAcceleration()+ -// " Y = "+arg0.getyAcceleration()+ -// " Z = "+arg0.getzAcceleration()+ -// " rX = "+arg0.getRotxAcceleration()+ -// " rY = "+arg0.getRotyAcceleration()+ -// " rZ = "+arg0.getRotzAcceleration() -// -// ); - } -} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/EngineeringUnitsSliderWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/EngineeringUnitsSliderWidget.java index 9c5ca4e60..840fc97ef 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/EngineeringUnitsSliderWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/EngineeringUnitsSliderWidget.java @@ -11,9 +11,12 @@ import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; +import javafx.scene.control.Label; +@SuppressWarnings("restriction") public class EngineeringUnitsSliderWidget extends GridPane implements ChangeListener { private TextField spv; + private Label increment; private Slider setpoint; private IOnEngineeringUnitsChange listener; private boolean intCast = false; @@ -22,6 +25,10 @@ public class EngineeringUnitsSliderWidget extends GridPane implements ChangeList private Button jogminus = new Button("-"); private double instantValueStore = 0; private boolean editing = false; + private double jogIncrement = 1.0; + private String units; + private double min; + private double max; public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double min, double max, double current, double width, String units, boolean intCast) { @@ -31,8 +38,8 @@ public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double m public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double current, double width, String units) { - this(listener, current / 2, current * 2, current, width, units); - + this(listener, -Float.MAX_VALUE, Float.MAX_VALUE, current, width, units); + } private void onSliderMovingInternal(EngineeringUnitsSliderWidget source, double newAngleDegrees) { @@ -43,14 +50,19 @@ private void onSliderMovingInternal(EngineeringUnitsSliderWidget source, double private void onSliderDoneMovingInternal(EngineeringUnitsSliderWidget source, double newAngleDegrees) { editing = false; + instantValueStore=(newAngleDegrees); //System.out.println("Slider done"); getListener().onSliderDoneMoving(this, newAngleDegrees); } - public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double min, double max, double current, + public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double minIn, double maxIn, double current, double width, String units) { + this.min = minIn; + this.max = maxIn; + this.units = units; this.setListener(listener); setpoint = new Slider(); + increment = new Label(jogIncrement+""); instantValueStore = current; if (min > max) { double minStart = min; @@ -82,10 +94,10 @@ public EngineeringUnitsSliderWidget(IOnEngineeringUnitsChange listener, double m public void changed(ObservableValue arg0, Boolean oldPropertyValue, Boolean newPropertyValue) { if (newPropertyValue) { - System.out.println("Textfield on focus"); + //System.out.println("Textfield on focus"); editing = true; } else { - System.out.println("Textfield out focus"); + //System.out.println("Textfield out focus"); editing = false; } } @@ -117,15 +129,17 @@ public void changed(ObservableValue arg0, Boolean oldProperty String unitsString = "(" + units + ")"; getColumnConstraints().add(new ColumnConstraints(30)); // column 2 is 100 wide + getColumnConstraints().add(new ColumnConstraints(40)); // column 2 is 100 wide getColumnConstraints().add(new ColumnConstraints(30)); // column 2 is 100 wide getColumnConstraints().add(new ColumnConstraints(100)); // column 2 is 100 wide getColumnConstraints().add(new ColumnConstraints(unitsString.length() * 7)); // column 2 is 100 wide - add(setpoint, 2, 1); - add(jogplus, 1, 0); + add(setpoint, 3, 1); + add(jogplus, 2, 0); + add(increment, 1, 0); add(jogminus, 0, 0); - add(spv, 2, 0); - add(new Text(unitsString), 3, 0); + add(spv, 3, 0); + add(new Text(unitsString), 4, 0); jogplus.setOnAction(event -> { jogPlusOne(); @@ -146,17 +160,19 @@ private void localSetValue(double val) { } public void jogMinusOne() { - double value = getValue() - 1; - if (value < setpoint.getMin()) - return; - setValue(value); - onSliderMovingInternal(this, value); - onSliderDoneMovingInternal(this, value); + jog(-getJogIncrement()); } public void jogPlusOne() { - double value = getValue() + 1; - if (value > setpoint.getMax()) + jog(getJogIncrement()); + } + public void jog(double amount) { + double value = getValue() + amount; + double max2 = setpoint.getMax(); + if (value > max2) + return; + double min2 = setpoint.getMin(); + if (value < min2) return; setValue(value); onSliderMovingInternal(this, value); @@ -269,4 +285,22 @@ public void showSlider(boolean b) { public boolean isEditing() { return editing; } + + /** + * @return the jogIncrement + */ + public double getJogIncrement() { + return jogIncrement; + } + + /** + * @param jogIncrement the jogIncrement to set + */ + public void setJogIncrement(double j) { + //System.out.println("Increment set to "+j+" "+units); + jogIncrement=Math.abs(j); + BowlerStudio.runLater(()->{ + increment.setText(""+jogIncrement); + }); + } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/GameControlThreadManager.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/GameControlThreadManager.java new file mode 100644 index 000000000..1f10b8840 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/GameControlThreadManager.java @@ -0,0 +1,139 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.TransportException; + +import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; +import com.neuronrobotics.sdk.common.Log; +import com.neuronrobotics.sdk.util.ThreadUtil; + +public class GameControlThreadManager { + private static Thread scriptRunner=null; + private static IAmControlled currentController=null; + private static boolean running = false; + public static void stop() { + if(!isRunning()) + return; + //new RuntimeException().printStackTrace(); + + reset(); + Thread tmp = scriptRunner; + if (tmp != null) + while (tmp.isAlive()) { + + System.out.println("Interrupting "+currentController.getName()); + ThreadUtil.wait(10); + try { + tmp.interrupt(); + tmp.join(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + } + } + + scriptRunner = null; + } + /** + * @return the currentController + */ + public static IAmControlled getCurrentController() { + return currentController; + } + /** + * @param currentController the currentController to set + */ + public static void setCurrentController(IAmControlled c) { + boolean was=isRunning(); + boolean b =false; + if(currentController!=null) { + b = c!=currentController; + if(b) + stop(); + } + currentController = c; + if(was && b) { + start(); + } + } + public static void startStopAction() { + //new RuntimeException().printStackTrace(); + currentController.getRunStopButton().setDisable(true); + if (isRunning()) + stop(); + else + try { + start(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + currentController.getRunStopButton().setDisable(false); + } + public static void start() { + File currentFile = currentController.getScriptFile(); + + + setRunning(true); + BowlerStudio.runLater(() -> { + BowlerStudio.setToStopButton(currentController.getRunStopButton()); + }); + //new RuntimeException().printStackTrace(); + scriptRunner = new Thread() { + + public void run() { + try { + + ScriptingEngine.inlineFileScriptRun(currentFile, currentController.getArguments()); + reset(); + + } catch (Throwable ex) { + BowlerStudio.printStackTrace(ex); + reset(); + } + + } + }; + + try { + + scriptRunner.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public static void reset() { + setRunning(false); + BowlerStudio.runLater(() -> { + currentController.getRunStopButton().setText(currentController.getButtonRunText()); + // game.setGraphic(AssetFactory.loadIcon("Run.png")); + for(String classes : currentController.getRunStopButton().getStyleClass()) { + //System.out.println("Clearing "+classes); + } + BowlerStudio.setToRunButton(currentController.getRunStopButton()); + currentController.getRunStopButton().setGraphic(currentController.getRunAsset()); + }); + + } + /** + * @return the running + */ + public static boolean isRunning() { + return running; + } + /** + * @param running the running to set + */ + private static void setRunning(boolean running) { + GameControlThreadManager.running = running; + } +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/IAmControlled.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/IAmControlled.java new file mode 100644 index 000000000..02300d735 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/IAmControlled.java @@ -0,0 +1,13 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import java.io.File; +import java.util.ArrayList; + +public interface IAmControlled { + File getScriptFile(); + ArrayList getArguments(); + javafx.scene.image.ImageView getRunAsset(); + javafx.scene.control.Button getRunStopButton(); + String getButtonRunText(); + String getName(); +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/ITransformProvider.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/ITransformProvider.java new file mode 100644 index 000000000..46d2c6408 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/ITransformProvider.java @@ -0,0 +1,8 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import com.neuronrobotics.sdk.addons.kinematics.VitaminLocation; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; + +public interface ITransformProvider { + TransformNR get(VitaminLocation selectedVitamin); +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogMobileBase.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogMobileBase.java index 993e9492f..2328c2651 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogMobileBase.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogMobileBase.java @@ -52,7 +52,7 @@ import javax.management.RuntimeErrorException; public class JogMobileBase extends GridPane implements IGameControlEvent,IJogProvider { - double defauletSpeed = 0.1; + double defauletSpeed = 0.3; private MobileBase mobilebase = null; Button px = new Button("", AssetFactory.loadIcon("Plus-X.png")); Button nx = new Button("", AssetFactory.loadIcon("Minus-X.png")); @@ -280,9 +280,8 @@ private void reset() { running = false; BowlerStudio.runLater(() -> { game.setText("Run Game Controller"); - //game.setGraphic(AssetFactory.loadIcon("Run.png")); - game.setBackground(new Background(new BackgroundFill(Color.LIGHTGREEN, CornerRadii.EMPTY, Insets.EMPTY))); - + BowlerStudio.setToRunButton(game); + game.setGraphic(AssetFactory.loadIcon("Add-Game-Controller.png")); }); } @@ -314,7 +313,7 @@ private void start() { BowlerStudio.runLater(()->{ game.setText("Stop Game Controller"); //game.setGraphic(AssetFactory.loadIcon("Stop.png")); - game.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY))); + BowlerStudio.setToStopButton(game); }); scriptRunner = new Thread() { @@ -424,18 +423,27 @@ private void handle(final Button button) { public void home() { getMobilebase().setGlobalToFiducialTransform(new TransformNR()); - for (DHParameterKinematics c : getMobilebase().getAllDHChains()) { + homeBase( getMobilebase()); + + } + + private void homeBase(MobileBase mb) { + for (DHParameterKinematics c : mb.getAllDHChains()) { homeLimb(c); } } - private void homeLimb(AbstractKinematicsNR c) { + private void homeLimb(DHParameterKinematics c) { double[] joints = c.getCurrentJointSpaceVector(); for (int i = 0; i < c.getNumberOfLinks(); i++) { joints[i] = 0; + if(c.getFollowerMobileBase(i)!=null) { + homeBase(c.getFollowerMobileBase(i)); + } } try { - c.setDesiredJointSpaceVector(joints, 0); + double time =c.getBestTime(joints); + c.setDesiredJointSpaceVector(joints, time); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogThread.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogThread.java index 244a398ac..316a7c616 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogThread.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogThread.java @@ -104,7 +104,7 @@ public void run() { kin.setDesiredTaskSpaceTransform(toSet, bestTime); //System.out.println("Joging to "+toSet); } catch (Exception e) { - e.printStackTrace(); + System.err.println("Exception in Jog Thread "+e.getMessage()); // BowlerStudioController.highlightException(null, e); } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogWidget.java index 78afea6fd..b5a57048c 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/JogWidget.java @@ -264,23 +264,27 @@ public void home() { }).start(); } - private void homeLimb(AbstractKinematicsNR c) { + private void homeBase(MobileBase mb) { + for (DHParameterKinematics c : mb.getAllDHChains()) { + homeLimb(c); + } + } - TransformNR t = c.calcHome(); + private void homeLimb(DHParameterKinematics c) { + double[] joints = c.getCurrentJointSpaceVector(); + for (int i = 0; i < c.getNumberOfLinks(); i++) { + joints[i] = 0; + if(c.getFollowerMobileBase(i)!=null) { + homeBase(c.getFollowerMobileBase(i)); + } + } try { - c.setDesiredTaskSpaceTransform(t, 0); + c.setDesiredJointSpaceVector(joints, c.getBestTime(joints)); } catch (Exception e) { - double[] joints = c.getCurrentJointSpaceVector(); - for (int i = 0; i < c.getNumberOfLinks(); i++) { - joints[i] = 0; - } - try { - c.setDesiredJointSpaceVector(joints, 0); - } catch (Exception ex) { - // TODO Auto-generated catch block - ex.printStackTrace(); - } + // TODO Auto-generated catch block + e.printStackTrace(); } + } @Override diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/LinkConfigurationWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/LinkConfigurationWidget.java index 5214c126b..220fbaaa1 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/LinkConfigurationWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/LinkConfigurationWidget.java @@ -20,6 +20,7 @@ import javafx.scene.layout.GridPane; import javafx.scene.text.Text; import java.time.Duration; +import javafx.scene.control.CheckBox; @SuppressWarnings("restriction") public class LinkConfigurationWidget extends GridPane implements ITrimControl { @@ -225,7 +226,8 @@ public void run() { add(new Text("Scale To Degrees "), 0, 0); add(scale, 1, 0); add(new Text("(unitless)"), 2, 0); - + + double min = activLink.getDeviceMinimumValue(); lowerBound = new EngineeringUnitsSliderWidget(new IOnEngineeringUnitsChange() { @@ -389,6 +391,13 @@ public void handle(ActionEvent event) { add(new Text("Shaft Size"), 0, 15); add(shaftSize, 1, 15); // add(newShaft, 1, 16); + CheckBox isPassive =new CheckBox(); + isPassive.setSelected(conf.isPassive()); + isPassive.setOnAction(action->{ + conf.setPassive(isPassive.isSelected()); + }); + add(new Text("Link Is Passive"), 0, 16); + add(isPassive, 1, 16); } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/MobleBaseMenueFactory.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/MobleBaseMenueFactory.java index 5d83252c7..56add7b2f 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/MobleBaseMenueFactory.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/MobleBaseMenueFactory.java @@ -7,6 +7,7 @@ import com.neuronrobotics.bowlerstudio.ConnectionManager; import com.neuronrobotics.bowlerstudio.IssueReportingExceptionHandler; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.physics.TransformFactory; import com.neuronrobotics.bowlerstudio.printbed.PrintBedManager; import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; @@ -20,13 +21,17 @@ import com.neuronrobotics.sdk.common.DeviceManager; import com.neuronrobotics.sdk.util.ThreadUtil; import javafx.application.Platform; +import javafx.fxml.FXMLLoader; import javafx.scene.Group; +import javafx.scene.Parent; import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; import javafx.scene.layout.VBox; import javafx.scene.transform.Affine; import javafx.stage.DirectoryChooser; import javafx.stage.Modality; + +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; @@ -40,11 +45,14 @@ import java.io.File; import java.io.IOException; +import java.io.OutputStream; import java.net.URL; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.Set; public class MobleBaseMenueFactory { @@ -56,11 +64,42 @@ private MobleBaseMenueFactory() { public static String[] copyGitFile(String sourceGit, String targetGit, String filename) { return ScriptingEngine.copyGitFile(sourceGit, targetGit, filename); } + + public static void addVitamins(IVitaminHolder vitamins, TreeItem rootItem, + HashMap, Runnable> callbackMapForTreeitems, + HashMap, Parent> widgetMapForTreeitems,ITransformProvider tfp) { + TreeItem vitaminsMenu = new TreeItem("Vitamins Add/Remove", + AssetFactory.loadIcon("Vitamins.png")); + HashMap widget = new HashMap<>(); + callbackMapForTreeitems.put(vitaminsMenu, () -> { + if (widgetMapForTreeitems.get(vitaminsMenu) == null) { + FXMLLoader loader; + try { + loader = AssetFactory.loadLayout("layout/AddRemoveVitamins.fxml",true); + //loader.setClassLoader(VitatminWidget.class.getClassLoader()); + Parent w = loader.load(); + VitatminWidget tw = loader.getController(); + tw.setVitaminProvider(vitamins,tfp); + + //Group value = new Group(w); + widgetMapForTreeitems.put(vitaminsMenu, w); + widget.put(w, tw); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + VitatminWidget tw = widget.get(widgetMapForTreeitems.get(vitaminsMenu)); + if(tw!=null) + tw.fireVitaminSelectedUpdate(); + }); + rootItem.getChildren().add(vitaminsMenu); + } @SuppressWarnings("unchecked") public static void load(MobileBase device, TreeView view, TreeItem rootItem, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, boolean root, + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean root, boolean creatureIsOwnedByUser) { // boolean creatureIsOwnedByUser = false; @@ -83,10 +122,24 @@ public static void load(MobileBase device, TreeView view, TreeItem { if (widgetMapForTreeitems.get(physics) == null) { - widgetMapForTreeitems.put(physics, new Group(new CreaturePhysicsWidget(device))); + widgetMapForTreeitems.put(physics, new Group(new PhysicsWidget(device))); } }); + TreeItem save; + save = new TreeItem("Save to XML", AssetFactory.loadIcon("Save.png")); + + if (!(device.getGitSelfSource()[0] == null || device.getGitSelfSource()[1] == null)) { + try { + + callbackMapForTreeitems.put(save, () -> { + saveToXML(device); + }); + } catch (Exception e) { + Log.error(device.getGitSelfSource()[0] + " " + device.getGitSelfSource()[1] + " failed to load"); + e.printStackTrace(); + } + } TreeItem publish; publish = new TreeItem("Publish", AssetFactory.loadIcon("Publish.png")); @@ -104,10 +157,11 @@ public static void load(MobileBase device, TreeView view, TreeItem view, TreeItem { BowlerStudio.runLater(() -> { String oldname = device.getScriptingName(); @@ -158,13 +213,17 @@ public static void load(MobileBase device, TreeView view, TreeItem { // TODO Auto-generated method stub - System.out.println("Adding Fixed Wheel"); - try { - String xmlContent = ScriptingEngine.codeFromGit("https://gist.github.com/b5b9450f869dd0d2ea30.git", - "defaultFixed.xml")[0]; - DHParameterKinematics newArm = new DHParameterKinematics(null, - IOUtils.toInputStream(xmlContent, "UTF-8")); - System.out.println("Arm has " + newArm.getNumberOfLinks() + " links"); - addAppendage(device, view, device.getDrivable(), newArm, drive, rootItem, callbackMapForTreeitems, - widgetMapForTreeitems, creatureLab, creatureIsOwnedByUserTmp); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + System.out.println("Adding Wheel"); + + + HashMap> options; + try { + options = (HashMap>) ScriptingEngine + .gitScriptRun("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", + "wheelOptions.json"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + Set optionsKeys = options.keySet(); + BowlerStudio.runLater(() -> { + ChoiceDialog d = new ChoiceDialog(optionsKeys.toArray()[0].toString(), optionsKeys); + + Optional result = d.showAndWait(); + if (result.isPresent()) + new Thread(() -> { + String back = result.get(); + HashMap values = options.get(back); + if (back.toLowerCase().contains("fixed")) { + try { + + String xmlContent = ScriptingEngine.codeFromGit( + values.get("scriptGit").toString(), + values.get("scriptFile").toString())[0]; + DHParameterKinematics newArm = new DHParameterKinematics(null, + IOUtils.toInputStream(xmlContent, "UTF-8")); + newArm.setGitCadEngine(device.getGitCadEngine()); + + System.out.println("Wheel has " + newArm.getNumberOfLinks() + " links"); + addAppendage(device, view, device.getDrivable(), newArm, drive, rootItem, + callbackMapForTreeitems, widgetMapForTreeitems, creatureLab, + creatureIsOwnedByUserTmp); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + }else { + try { + MobileBase base = (MobileBase)ScriptingEngine.gitScriptRun(values.get("scriptGit").toString(), values.get("scriptFile").toString()); + DHParameterKinematics newArm = base.getDrivable().get(0); + newArm.setGitCadEngine(device.getGitCadEngine()); + addAppendage(device, view, device.getDrivable(), newArm, drive, rootItem, + callbackMapForTreeitems, widgetMapForTreeitems, creatureLab, + creatureIsOwnedByUserTmp); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + } + }).start(); + }); + }); TreeItem addsteerable = new TreeItem<>("Add Steerable Wheel", AssetFactory.loadIcon("Add-Steerable-Wheel.png")); @@ -361,13 +465,16 @@ public void run() { // TODO Auto-generated method stub System.out.println("Adding Steerable Wheel"); try { - String xmlContent = ScriptingEngine.codeFromGit("https://gist.github.com/b5b9450f869dd0d2ea30.git", + String xmlContent = ScriptingEngine.codeFromGit("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", "defaultSteerable.xml")[0]; DHParameterKinematics newArm = new DHParameterKinematics(null, IOUtils.toInputStream(xmlContent, "UTF-8")); - System.out.println("Arm has " + newArm.getNumberOfLinks() + " links"); + newArm.setGitCadEngine(device.getGitCadEngine()); + + System.out.println("Steerable has " + newArm.getNumberOfLinks() + " links"); addAppendage(device, view, device.getSteerable(), newArm, steer, rootItem, callbackMapForTreeitems, widgetMapForTreeitems, creatureLab, creatureIsOwnedByUserTmp); + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -416,13 +523,15 @@ public void onTransformFinished(TransformNR newTrans) { // TODO Auto-generated method stub System.out.println("Adding Arm"); try { - String xmlContent = ScriptingEngine.codeFromGit("https://gist.github.com/b5b9450f869dd0d2ea30.git", + String xmlContent = ScriptingEngine.codeFromGit("https://github.com/CommonWealthRobotics/BowlerStudioExampleRobots.git", "defaultarm.xml")[0]; DHParameterKinematics newArm = new DHParameterKinematics(null, IOUtils.toInputStream(xmlContent, "UTF-8")); + newArm.setGitCadEngine(device.getGitCadEngine()); System.out.println("Arm has " + newArm.getNumberOfLinks() + " links"); addAppendage(device, view, device.getAppendages(), newArm, arms, rootItem, callbackMapForTreeitems, widgetMapForTreeitems, creatureLab, creatureIsOwnedByUserTmp); + } catch (Exception e) { new IssueReportingExceptionHandler().except(e); @@ -460,8 +569,11 @@ public void onTransformChaging(TransformNR newTrans) { }); rootItem.getChildren().addAll(bodymass, imuCenter,PlaceLimb); + addVitamins( device, rootItem, callbackMapForTreeitems, widgetMapForTreeitems, selected->{ + return device.forwardOffset(new TransformNR()); + }); if (root) - rootItem.getChildren().addAll(physics, printable,arrangeBed, kinematics); + rootItem.getChildren().addAll( printable,arrangeBed, kinematics); rootItem.getChildren().addAll(addArm, addleg, addFixed, addsteerable); if (creatureIsOwnedByUser) { if (root) @@ -472,6 +584,42 @@ public void onTransformChaging(TransformNR newTrans) { new IssueReportingExceptionHandler().except(e); } } + + private static void reload(MobileBase device) { + saveToXML(device); + String[]source=device.getGitSelfSource(); + device.disconnect(); + try { + MobileBase reloaded=MobileBaseLoader.fromGit(source[0], source[1]); + BowlerStudio.loadMobilBaseIntoUI(reloaded); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + public static void saveToXML(MobileBase device) { + OutputStream out = null; + try { + File source = ScriptingEngine.fileFromGit(device.getGitSelfSource()[0], device.getGitSelfSource()[1]); + + out = FileUtils.openOutputStream(source, false); + IOUtils.write(device.getXml(), out, Charset.defaultCharset()); + out.close(); // don't swallow close Exception if copy completes + // normally + } catch(Throwable t){ + t.printStackTrace(); + }finally { + try { + out.close(); + } catch (Exception e) { + + } + } + } + + private static Thread makeACopyOfACreature(MobileBase device, String oldname, String newName) { return new Thread() { @@ -560,6 +708,24 @@ public void run() { private static void getNextChannel(MobileBase base, LinkConfiguration confOfChannel) { HashMap> deviceMap = new HashMap<>(); + searchForAllLinks(base, deviceMap); + for (Map.Entry> entry : deviceMap.entrySet()) { + HashMap chans = entry.getValue(); + for (int i = 0; i < 48; i++) { + + if (chans.get(i) == null) { + System.err.println("Channel free: " + i + " on device " + entry.getKey()); + confOfChannel.setDeviceScriptingName(entry.getKey()); + confOfChannel.setHardwareIndex(i); + return; + } + } + } + + throw new RuntimeException("No channels are availible on given devices"); + } + + private static void searchForAllLinks(MobileBase base, HashMap> deviceMap) { for (DHParameterKinematics dh : base.getAllDHChains()) { for (LinkConfiguration conf : dh.getLinkConfigurations()) { HashMap channelMap; @@ -576,28 +742,17 @@ private static void getNextChannel(MobileBase base, LinkConfiguration confOfChan slavechannelMap = deviceMap.get(sl.getDeviceScriptingName()); slavechannelMap.put(sl.getHardwareIndex(), true); } - } - } - for (Map.Entry> entry : deviceMap.entrySet()) { - HashMap chans = entry.getValue(); - for (int i = 0; i < 24; i++) { - - if (chans.get(i) == null) { - System.err.println("Channel free: " + i + " on device " + entry.getKey()); - confOfChannel.setDeviceScriptingName(entry.getKey()); - confOfChannel.setHardwareIndex(i); - return; + if(dh.getFollowerMobileBase(conf)!=null) { + searchForAllLinks(dh.getFollowerMobileBase(conf),deviceMap); } } } - - throw new RuntimeException("No channels are availible on given devices"); } private static void addAppendage(MobileBase base, TreeView view, ArrayList deviceList, DHParameterKinematics newDevice, TreeItem rootItem, TreeItem topLevel, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean creatureIsOwnedByUser) { BowlerStudio.runLater(() -> { @@ -613,7 +768,7 @@ private static void addAppendage(MobileBase base, TreeView view, new Thread() { public void run() { System.out.println("Your new limb: " + result.get()); - newDevice.setScriptingName(result.get()); + setDeviceName(newDevice, result.get()); ConnectionManager.addConnection(newDevice, newDevice.getScriptingName()); deviceList.add(newDevice); for (LinkConfiguration conf : newDevice.getLinkConfigurations()) { @@ -629,15 +784,22 @@ public void run() { } - rootItem.setExpanded(true); - try { - loadSingleLimb(base, view, newDevice, rootItem, callbackMapForTreeitems, - widgetMapForTreeitems, creatureLab, creatureIsOwnedByUser); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + reload(base); + } + + private void setDeviceName(DHParameterKinematics newDevice, String name) { + newDevice.setScriptingName(name); + for(int i=0;i loadLimbs(MobileBase base, TreeView view, ArrayList drivable, String label, TreeItem rootItem, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean creatureIsOwnedByUser) throws Exception { TreeItem apps = new TreeItem<>(label, @@ -668,7 +830,7 @@ private static TreeItem loadLimbs(MobileBase base, TreeView view private static LinkConfigurationWidget setHardwareConfig(MobileBase myBase, LinkConfiguration MyConf, LinkFactory myLinkFactory, TreeItem rootItem1, HashMap, Runnable> callbackMapForTreeitems1, - HashMap, Group> widgetMapForTreeitems1) throws Exception { + HashMap, Parent> widgetMapForTreeitems1) throws Exception { TreeItem hwConf = new TreeItem<>("Hardware Config " + MyConf.getName(), AssetFactory.loadIcon("Hardware-Config.png")); @@ -690,7 +852,7 @@ private static LinkConfigurationWidget setHardwareConfig(MobileBase myBase, Link private static void loadSingleLink(int linkIndex, MobileBase base, TreeView view, LinkConfiguration conf, DHParameterKinematics dh, TreeItem rootItem, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, boolean isOwner) + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean isOwner) throws Exception { TreeItem link = new TreeItem<>(conf.getName(), AssetFactory.loadIcon("Move-Single-Motor.png")); DHLink dhLink; @@ -942,6 +1104,24 @@ public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAn link.getChildren().addAll(design); + addVitamins( dh.getLinkConfiguration(linkIndex), link, callbackMapForTreeitems, widgetMapForTreeitems,selected->{ + Affine linkObjectManipulator = (Affine) dh.getLinkObjectManipulator(linkIndex); + TransformNR pose = TransformFactory.affineToNr(linkObjectManipulator); + if(selected.getFrame()==VitaminFrame.LinkOrigin) { + TransformNR step = dh.getDHStep(linkIndex).inverse(); + pose=pose.times(step); + } + if(selected.getFrame()==VitaminFrame.previousLinkTip) { + Affine ll; + if(linkIndex==0) { + ll=(Affine) dh.getRootListener(); + }else + ll = (Affine) dh.getLinkObjectManipulator(linkIndex-1); + pose = TransformFactory.affineToNr(ll); + } + return pose; + }); + link.getChildren().addAll(slaves, remove); @@ -951,7 +1131,7 @@ public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAn private static TreeItem setUpNewMobileBaseEditor(TreeView view, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, boolean isOwner, + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean isOwner, DHLink dhLink) { TreeItem mobile = new TreeItem<>( dhLink.getSlaveMobileBase().getScriptingName(), AssetFactory.loadIcon("creature.png")); @@ -962,7 +1142,7 @@ private static TreeItem setUpNewMobileBaseEditor(TreeView view, @SuppressWarnings("unchecked") private static void loadSingleLimb(MobileBase base, TreeView view, DHParameterKinematics dh, TreeItem rootItem, HashMap, Runnable> callbackMapForTreeitems, - HashMap, Group> widgetMapForTreeitems, CreatureLab creatureLab, + HashMap, Parent> widgetMapForTreeitems, CreatureLab creatureLab, boolean creatureIsOwnedByUser) throws Exception { TreeItem dhItem = new TreeItem<>(dh.getScriptingName(), AssetFactory.loadIcon("Move-Limb.png")); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/PhysicsWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/PhysicsWidget.java new file mode 100644 index 000000000..ed12147c1 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/PhysicsWidget.java @@ -0,0 +1,404 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.BowlerStudioController; +import com.neuronrobotics.bowlerstudio.CreatureLab3dController; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.ConfigurationDatabase; +import com.neuronrobotics.bowlerstudio.physics.MuJoCoPhysicsManager; +import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; +import com.neuronrobotics.sdk.addons.kinematics.LinkConfiguration; +import com.neuronrobotics.sdk.addons.kinematics.MobileBase; +import com.neuronrobotics.sdk.addons.kinematics.imu.IMUUpdate; +import com.neuronrobotics.sdk.addons.kinematics.imu.IMUUpdateListener; +import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; +import com.neuronrobotics.sdk.common.BowlerAbstractDevice; +import com.neuronrobotics.sdk.common.IDeviceConnectionEventListener; +import com.neuronrobotics.sdk.util.ThreadUtil; + +import eu.mihosoft.vrl.v3d.CSG; +import javafx.application.Platform; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.xml.bind.JAXBException; + +import org.mujoco.xml.attributetypes.IntegratorType; + +@SuppressWarnings("restriction") +public class PhysicsWidget extends GridPane implements IMUUpdateListener { + Button runstop = new Button("Run", AssetFactory.loadIcon("Run.png")); + Button pauseresume = new Button("Pause", AssetFactory.loadIcon("Pause.png")); + Button step = new Button("Step", AssetFactory.loadIcon("Step.png")); + TextField msLoopTime =new TextField("1") ; + int msLoopTimeInt =0; + private boolean run=false; + private boolean takestep=false; + private boolean pause=false; + Thread physicsThread =null; + private Set oldParts=null; + private MobileBase base; + private MuJoCoPhysicsManager mujoco; + private ComboBox filesStatic; + private ComboBox filesMoving; + private TextField gitStatic; + private TextField gitMoving; + private ArrayList staticObjects=null; + + private ArrayList movingObjects=null; + + @SuppressWarnings("restriction") + public PhysicsWidget(MobileBase base){ + + this.base = base; + base.addConnectionEventListener(new IDeviceConnectionEventListener() { + + @Override + public void onDisconnect(BowlerAbstractDevice arg0) { + BowlerStudio.runLater(()->{ + stopPhysics(); + }); + } + + @Override + public void onConnect(BowlerAbstractDevice arg0) {} + }); + GridPane controls=new GridPane(); + BowlerStudio.setToRunButton(runstop); + controls.add(runstop,0,0); + controls.add(pauseresume,1,0); + controls.add(step,2,0); + controls.add(new Label("MS loop"),3,0); + controls.add(msLoopTime,4,0); + add(controls,0,0); + add(new Label("Static Objects:"),0,1); + gitStatic = new TextField(); + filesStatic = new ComboBox<>(); + add(gitStatic,0,2); + add(filesStatic,1,2); + + + add(new Label("Moving Objects:"),0,4); + gitMoving = new TextField(); + filesMoving = new ComboBox<>(); + add(gitMoving,0,5); + add(filesMoving,1,5); + + + filesMoving.setDisable(true); + filesStatic.setDisable(true); + filesMoving.setOnAction(event->{ + updateObjects(); + }); + filesStatic.setOnAction(event->{ + updateObjects(); + }); + String string = ConfigurationDatabase.getObject("PhysicsWidget", "gitMoving", "").toString(); + gitMoving.setText( string); + String string2 = ConfigurationDatabase.getObject("PhysicsWidget", "gitStatic", "").toString(); + gitStatic.setText( string2); + validateInput(); + gitMoving.textProperty().addListener((observable, oldValue, newValue) -> { + validateInput(); + }); + gitStatic.textProperty().addListener((observable, oldValue, newValue) -> { + validateInput(); + }); + + pauseresume.setDisable(true); + step.setDisable(true); + pauseresume.setOnAction(event->{ + if(!isPause()){ + pauseresume.setGraphic(AssetFactory.loadIcon("Resume.png")); + pauseresume.setText("Resume"); + step.setDisable(false); + }else{ + pauseresume.setGraphic(AssetFactory.loadIcon("Pause.png")); + pauseresume.setText("Pause"); + step.setDisable(true); + } + setPause(!isPause()); + }); + step.setOnAction(event->{ + setTakestep(true); + }); + runstop.setOnAction(event->{ + if(isRun()){ + stopPhysics(); +// new Thread(){ +// public void run(){ +// ThreadUtil.wait(50); +// System.gc();// clean up any objects created by the physics engine +// } +// }.start(); + }else{ + //System.gc();// clean up any objects created by the physics engine +// runstop.setGraphic(AssetFactory.loadIcon("Stop.png")); +// runstop.setText("Stop"); + BowlerStudio.setToStopButton(runstop); + msLoopTime.setDisable(true); + pauseresume.setDisable(false); + base.getImu().addvirtualListeners(this); + new Thread(){ + + + public void run(){ + while(MobileBaseCadManager.get( base).getProcesIndictor().get()<1){ + ThreadUtil.wait(100); + } + base.DriveArc(new TransformNR(.01,0,0,new RotationNR()), 0); + ArrayList bases=new ArrayList<>(); + bases.add(base); + File cache = new File(ScriptingEngine.getWorkspace().getAbsolutePath()+"/physics-"+base.getScriptingName()); + try { + mujoco = new MuJoCoPhysicsManager(base.getScriptingName(),bases,movingObjects,staticObjects,cache); + + } catch (IOException | JAXBException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + //MobileBasePhysicsManager m =new MobileBasePhysicsManager(base, baseCad, simplecad); + //BowlerStudio3dEngine threeD = BowlerStudioController.getBowlerStudio().getJfx3dmanager(); + oldParts = CreatureLab3dController.getEngine().getCsgMap().keySet(); + double loopTiming = (int) Double.parseDouble(msLoopTime.getText()); + mujoco.setTimestep(loopTiming/1000.0); + mujoco.setIntegratorType(IntegratorType.IMPLICIT); + mujoco.setCondim(4); + try { + mujoco.generateNewModel(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(System.out); + close(); + return; + } // generate model before start counting time + physicsThread = new Thread(){ + public void run(){ + blockingUpdateObjects(); + BowlerStudioController.clearCSG(); + BowlerStudioController.clearUserNodes(); + BowlerStudioController.addObject(mujoco.getAllCSG(),null ); + ConfigurationDatabase.save(); + try{ + long timeSinceLastPrint=0; + while(isRun()){ + while(isPause() && isTakestep()==false){ + ThreadUtil.wait(0,100); + } + setTakestep(false); + long now; + if((now=mujoco.stepAndWait())>(3*mujoco.getTimestepMilliSeconds())) { + if(System.currentTimeMillis()-timeSinceLastPrint>500) { + timeSinceLastPrint=System.currentTimeMillis(); + System.out.println("MuJoCo Real time broken, expected "+mujoco.getTimestepMilliSeconds()+" took: "+now); + } + } + } + }catch(Exception e){ + e.printStackTrace(); + } + close(); + } + }; + physicsThread.start(); + } + + private void close() { + if(mujoco!=null) + mujoco.close(); + mujoco=null; + BowlerStudio.runLater(()->{ + stopPhysics(); + }); + } + }.start(); + + } + setRun(!isRun()); + }); + + } + private void validateInput() { + new Thread(()->{ + validateInput(gitMoving,filesMoving,"gitMoving","movingObjects"); + validateInput(gitStatic,filesStatic,"gitStatic","staticObjects"); + }).start(); + } + private void validateInput(TextField text,ComboBox box,String key,String key2) { + BowlerStudio.runLater(()->box.getItems().clear()); + BowlerStudio.runLater(()->box.setDisable(true)); + String text2 = text.getText(); + ConfigurationDatabase.setObject("PhysicsWidget",key ,text2); + if(!text2.endsWith(".git")) + return; + if(text2.length()<=5) + return; + try { + new java.net.URL(text2); + }catch(Exception ex) { + if(!text2.startsWith("git@")) { + ex.printStackTrace(); + return; + } + } + BowlerStudio.runLater(()->box.setDisable(false)); + + try { + ArrayList files = ScriptingEngine.filesInGit(text2); + + for(String name:files) { + BowlerStudio.runLater(()->box.getItems().add(name)); + } + String file=ConfigurationDatabase.getObject("PhysicsWidget",key2 ,"").toString(); + if(file.length()>0) { + boolean hasFile=false; + for(String s:files) + if(s.contentEquals(file)) hasFile=true; + if(!hasFile) + return; + Thread.sleep(16*files.size()); + BowlerStudio.runLater(()->box.getSelectionModel().select(file)); + updateObjects(); + } + } catch (Exception e) { + BowlerStudio.runLater(()->box.setDisable(true)); + e.printStackTrace(); + } + + } + private void updateObjects() { + new Thread(()->{ + blockingUpdateObjects(); + + }).start(); + + + } + private void blockingUpdateObjects() { + if(movingObjects!=null) { + for(CSG c:movingObjects) { + BowlerStudioController.removeObject(c); + } + } + if(staticObjects!=null) { + for(CSG c:staticObjects) { + BowlerStudioController.removeObject(c); + } + } + try { + movingObjects=null; + String selectedItem = filesMoving.getSelectionModel().getSelectedItem(); + movingObjects=loadObjects(gitMoving.getText(),selectedItem); + ConfigurationDatabase.setObject("PhysicsWidget","movingObjects" ,selectedItem); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + try { + staticObjects=null; + String selectedItem = filesStatic.getSelectionModel().getSelectedItem(); + staticObjects=loadObjects(gitStatic.getText(), selectedItem); + ConfigurationDatabase.setObject("PhysicsWidget","staticObjects" ,selectedItem); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if(movingObjects!=null) { + for(CSG c:movingObjects) { + BowlerStudioController.addObject(c,null); + } + } + if(staticObjects!=null) { + for(CSG c:staticObjects) { + BowlerStudioController.addObject(c,null); + } + } + } + private ArrayList loadObjects(String url,String selectedItem) throws Exception { + ArrayList ret= new ArrayList(); + if(url==null||selectedItem==null) + return ret; + ScriptingEngine.cloneRepo(url, null); + ScriptingEngine.pull(url); + Object o=ScriptingEngine.gitScriptRun(url, selectedItem); + load(o,ret); + return ret; + } + private void load(Object o,ArrayList storage) { + if(CSG.class.isInstance(o)) + storage.add((CSG)o); + if(ArrayList.class.isInstance(o)) { + ArrayList l=(ArrayList)o; + for(int i=0;ioldp=new ArrayList<>(); + for(CSG c:oldParts){ + oldp.add(c); + } + BowlerStudioController.setCsg(oldp); + oldParts=null; + } + base.getImu().removevirtualListeners(this); + } + public boolean isTakestep() { + return takestep; + } + public void setTakestep(boolean takestep) { + this.takestep = takestep; + } + public boolean isPause() { + return pause; + } + public void setPause(boolean pause) { + this.pause = pause; + } + public boolean isRun() { + return run; + } + public void setRun(boolean run) { + this.run = run; + } + @Override + public void onIMUUpdate(IMUUpdate arg0) { +// System.err.println("X = "+arg0.getxAcceleration()+ +// " Y = "+arg0.getyAcceleration()+ +// " Z = "+arg0.getzAcceleration()+ +// " rX = "+arg0.getRotxAcceleration()+ +// " rY = "+arg0.getRotyAcceleration()+ +// " rZ = "+arg0.getRotzAcceleration() +// +// ); + } +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidget.java index 351071b2f..ff4610194 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidget.java @@ -1,218 +1,374 @@ package com.neuronrobotics.bowlerstudio.creature; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.TransportException; + import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR; import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; +import com.neuronrobotics.sdk.common.Log; +import com.neuronrobotics.sdk.util.ThreadUtil; + +import eu.mihosoft.vrl.v3d.JavaFXInitializer; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; -import javafx.scene.text.Text; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.control.Tooltip; +import javafx.scene.image.ImageView; +import javafx.stage.Stage; +import javafx.scene.control.Label; -public class TransformWidget extends GridPane implements IOnEngineeringUnitsChange, EventHandler { - - private IOnTransformChange onChange; - //EngineeringUnitsSliderWidget rw; - private EngineeringUnitsSliderWidget tilt; - private EngineeringUnitsSliderWidget elevation; - private EngineeringUnitsSliderWidget azimeth; - private EngineeringUnitsSliderWidget tx; - private EngineeringUnitsSliderWidget ty; - private EngineeringUnitsSliderWidget tz; -// private TextField tx; -// private TextField ty; -// private TextField tz; - private TransformNR initialState; - private RotationNR storeRotation; - public TransformWidget(String title, TransformNR is, IOnTransformChange onChange){ - initialState=is.copy(); - this.onChange = onChange; +public class TransformWidget extends GridPane implements IOnEngineeringUnitsChange, EventHandler, IAmControlled { + + public IOnTransformChange onChange; + // EngineeringUnitsSliderWidget rw; + public EngineeringUnitsSliderWidget tilt; + public EngineeringUnitsSliderWidget elevation; + public EngineeringUnitsSliderWidget azimuth; + public EngineeringUnitsSliderWidget tx; + public EngineeringUnitsSliderWidget ty; + public EngineeringUnitsSliderWidget tz; +// public TextField tx; +// public TextField ty; +// public TextField tz; + public TransformNR initialState; + public RotationNR storeRotation; + public double linearIncrement = 1; + public double rotationIncrement = 5; + public Button game = new Button("Jog With Game Controller", AssetFactory.loadIcon("Add-Game-Controller.png")); + public Thread scriptRunner = null; + private String title; + private TransformWidget self; + private Label mode= new Label(""); + + public TransformWidget(String title, TransformNR is, IOnTransformChange onChange) { + TransformWidget c = this; + c.title = title; + self=c; + initialState = is.copy(); + c.onChange=(onChange); // tx = new TextField(CreatureLab.getFormatted(initialState.getX())); // ty = new TextField(CreatureLab.getFormatted(initialState.getY())); // tz = new TextField(CreatureLab.getFormatted(initialState.getZ())); // tx.setOnAction(this); // ty.setOnAction(this); // tz.setOnAction(this); - tx = new EngineeringUnitsSliderWidget(this, initialState.getX(), 100,"mm"); - ty = new EngineeringUnitsSliderWidget(this, initialState.getY(), 100,"mm"); - tz = new EngineeringUnitsSliderWidget(this, initialState.getZ(), 100,"mm"); - + tx = new EngineeringUnitsSliderWidget(c, initialState.getX(), 100, "mm"); + ty = new EngineeringUnitsSliderWidget(c, initialState.getY(), 100, "mm"); + tz = new EngineeringUnitsSliderWidget(c, initialState.getZ(), 100, "mm"); + storeRotation = initialState.getRotation(); - double t=0; - try{ - t=Math.toDegrees(storeRotation.getRotationTilt()); - }catch(Exception ex){ + double t = 0; + try { + t = Math.toDegrees(storeRotation.getRotationTilt()); + } catch (Exception ex) { ex.printStackTrace(); } - double e=0; - try{ - e=Math.toDegrees(storeRotation.getRotationElevation()); - }catch(Exception ex){ + double e = 0; + try { + e = Math.toDegrees(storeRotation.getRotationElevation()); + } catch (Exception ex) { ex.printStackTrace(); } - double a=0; - try{ - a=Math.toDegrees(storeRotation.getRotationAzimuth()); - }catch(Exception ex){ + double a = 0; + try { + a = Math.toDegrees(storeRotation.getRotationAzimuth()); + } catch (Exception ex) { ex.printStackTrace(); } tilt = new EngineeringUnitsSliderWidget(new IOnEngineeringUnitsChange() { - + @Override public void onSliderMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { initialState.setTiltDegrees(newAngleDegrees); onChange.onTransformChaging(getCurrent()); } - + @Override public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { - initialState.setTiltDegrees(newAngleDegrees); + initialState.setTiltDegrees(newAngleDegrees); onChange.onTransformFinished(getCurrent()); } - }, -179.99, 179.99, t, 100,"degrees"); + }, -179.99, 179.99, t, 100, "degrees"); elevation = new EngineeringUnitsSliderWidget(new IOnEngineeringUnitsChange() { - + @Override public void onSliderMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { initialState.setElevationDegrees(newAngleDegrees); onChange.onTransformChaging(getCurrent()); } - + @Override public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { initialState.setElevationDegrees(newAngleDegrees); onChange.onTransformFinished(getCurrent()); } - }, -89.99, 89.99, e, 100,"degrees"); - azimeth = new EngineeringUnitsSliderWidget(new IOnEngineeringUnitsChange() { - + }, -89.99, 89.99, e, 100, "degrees"); + azimuth = new EngineeringUnitsSliderWidget(new IOnEngineeringUnitsChange() { + @Override public void onSliderMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { initialState.setAzimuthDegrees(newAngleDegrees); onChange.onTransformChaging(getCurrent()); } - + @Override public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { initialState.setAzimuthDegrees(newAngleDegrees); onChange.onTransformFinished(getCurrent()); } - }, -179.99, 179.99, a, 100,"degrees"); + }, -179.99, 179.99, a, 100, "degrees"); tilt.setAllowResize(false); elevation.setAllowResize(false); - azimeth.setAllowResize(false); + azimuth.setAllowResize(false); getColumnConstraints().add(new ColumnConstraints(60)); // translate text - getColumnConstraints().add(new ColumnConstraints(200)); // translate values - getColumnConstraints().add(new ColumnConstraints(60)); // units - getColumnConstraints().add(new ColumnConstraints(60)); // rotate text - setHgap(20);// gab between elements - - tx.showSlider(false); - ty.showSlider(false); - tz.showSlider(false); - - add( new Text(title), - 1, 0); - - // These all seem out of order here, but it is because the - // screen is rotating the orenation of this interface from BowlerStudio3dEngine.getOffsetforvisualization() - //X line - add( new Text("X"), - 0, 1); - add( tx, - 1, 1); - - add( new Text("Tilt"), - 0, 4); - add( tilt, - 1, 4); - //Y line - add( new Text("Y"), - 0, 2); - add( ty, - 1, 2); - - add( new Text("Elevation"), - 0, 5); - add( elevation, - 1, 5); - //Z line - add( new Text("Z"), - 0, 3); - add( tz, - 1, 3); - - add( new Text("Azimuth"), - 0, 6); - add( azimeth, - 1, 6); - updatePose(is); + getColumnConstraints().add(new ColumnConstraints(200)); // translate values + getColumnConstraints().add(new ColumnConstraints(60)); // units + getColumnConstraints().add(new ColumnConstraints(60)); // rotate text + setHgap(20);// gab between elements + + tx.showSlider(false); + ty.showSlider(false); + tz.showSlider(false); + setIncrements(); + GameControlThreadManager.setCurrentController(c); + GameControlThreadManager.reset(); + game.setOnAction(event -> { + new Thread() { + public void run() { + GameControlThreadManager.setCurrentController(c); + GameControlThreadManager.startStopAction(); + } + }.start(); + + }); + game.setTooltip(new Tooltip("Connect game controllers and use them jog the item around. Use the joysticks to move. \nPress X to Translate. \nPress Y to rotate. \nPress A to exit")); + + add(new Label(title), 1, 0); + add(mode, 1, 1); + add(game, 0, 0); + + // These all seem out of order here, but it is because the + // screen is rotating the orenation of this interface from + // BowlerStudio3dEngine.getOffsetforvisualization() + // X line + + int startIndex = 3; + TextField lin = new TextField(linearIncrement + ""); + TextField rot = new TextField(rotationIncrement + ""); + lin.setOnAction(ac -> { + linearIncrement = Double.parseDouble(lin.getText()); + setIncrements(); + }); + rot.setOnAction(ac -> { + rotationIncrement = Double.parseDouble(rot.getText()); + setIncrements(); + }); + + add(new Label("Linear "), 0, startIndex-1); + add(new Label("Rotation "), 0, startIndex); + + add(lin, 1, startIndex-1); + add(rot, 1, startIndex); + add(new Label("(mm)"), 2, startIndex-1); + add(new Label("(degrees)"), 2, startIndex); + + add(new Label("X"), 0, 1 + startIndex); + add(tx, 1, 1 + startIndex); + + // Y line + add(new Label("Y"), 0, 2 + startIndex); + add(ty, 1, 2 + startIndex); + + // Z line + add(new Label("Z"), 0, 3 + startIndex); + add(tz, 1, 3 + startIndex); + add(new Label("Tilt"), 0, 4 + startIndex); + add(tilt, 1, 4 + startIndex); + + add(new Label("Elevation"), 0, 5 + startIndex); + add(elevation, 1, 5 + startIndex); + + add(new Label("Azimuth"), 0, 6 + startIndex); + add(azimuth, 1, 6 + startIndex); + // game + + + updatePose(is); } - private TransformNR getCurrent(){ - TransformNR tmp = new TransformNR( - tx.getValue(), - ty.getValue(), - tz.getValue(), - initialState.getRotation()); + public String toString() { + return title+" "+initialState.toSimpleString(); + } + + + public void setMode(String m) { + BowlerStudio.runLater(()->{ + mode.setText(m+" Mode"); + }); + } + + + + + + public void setIncrements() { + tx.setJogIncrement(linearIncrement); + ty.setJogIncrement(linearIncrement); + tz.setJogIncrement(linearIncrement); + tilt.setJogIncrement(rotationIncrement); + elevation.setJogIncrement(rotationIncrement); + azimuth.setJogIncrement(rotationIncrement); + } + + public TransformNR getCurrent() { + TransformNR tmp = new TransformNR(tx.getValue(), ty.getValue(), tz.getValue(), initialState.getRotation()); - return tmp; } @Override public void onSliderMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { - onChange.onTransformChaging(getCurrent()); + getOnChange().onTransformChaging(getCurrent()); } @Override - public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, - double newAngleDegrees) { + public void onSliderDoneMoving(EngineeringUnitsSliderWidget source, double newAngleDegrees) { handle(null); } @Override public void handle(ActionEvent event) { - onChange.onTransformChaging(getCurrent()); - onChange.onTransformFinished(getCurrent()); + getOnChange().onTransformChaging(getCurrent()); + getOnChange().onTransformFinished(getCurrent()); } public void updatePose(TransformNR p) { initialState = p.copy(); - - + tx.setValue(initialState.getX()); ty.setValue(initialState.getY()); tz.setValue(initialState.getZ()); - + RotationNR rot = initialState.getRotation(); - double t=0; - try{ - t=Math.toDegrees(rot.getRotationTilt()); - }catch(Exception ex){ + double t = 0; + try { + t = Math.toDegrees(rot.getRotationTilt()); + } catch (Exception ex) { ex.printStackTrace(); } - double e=0; - try{ - e=Math.toDegrees(rot.getRotationElevation()); - }catch(Exception ex){ + double e = 0; + try { + e = Math.toDegrees(rot.getRotationElevation()); + } catch (Exception ex) { ex.printStackTrace(); } - double a=0; - try{ - a=Math.toDegrees(rot.getRotationAzimuth()); - }catch(Exception ex){ + double a = 0; + try { + a = Math.toDegrees(rot.getRotationAzimuth()); + } catch (Exception ex) { ex.printStackTrace(); } - double tiltVar=t; - double eVar=e; - double aVar=a; + double tiltVar = t; + double eVar = e; + double aVar = a; tilt.setValue(tiltVar); - elevation .setValue(eVar); - azimeth .setValue(aVar); - // Set the rotation after setting the UI so the read will load the rotation in its pure form + elevation.setValue(eVar); + azimuth.setValue(aVar); + // Set the rotation after setting the UI so the read will load the rotation in + // its pure form + + } + + public static void main(String[] args) { + JavaFXInitializer.go(); + BowlerStudio.runLater(() -> { + Stage s = new Stage(); + // new Thread(() -> { + TransformWidgetTest controller = new TransformWidgetTest(); + + try { + controller.start(s); + } catch (Exception e) { + e.printStackTrace(); + } + // }).start(); + }); + } + + /** + * @return the onChange + */ + public IOnTransformChange getOnChange() { + return onChange; + } + /** + * @param onChange the onChange to set + */ + public void setOnChange(IOnTransformChange onChange, TransformNR initial) { + this.onChange = onChange; + initialState = initial; + updatePose(initial); + } + + @Override + public File getScriptFile() { + // TODO Auto-generated method stub + try { + return ScriptingEngine.fileFromGit("https://github.com/OperationSmallKat/Katapult.git", + "jogWidget.groovy"); + } catch (InvalidRemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (TransportException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (GitAPIException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + @Override + public ArrayList getArguments() { + ArrayList args = new ArrayList<>(); + args.add(self); + return args; + } + + @Override + public ImageView getRunAsset() { + return AssetFactory.loadIcon("Add-Game-Controller.png"); + } + + @Override + public Button getRunStopButton() { + return game; + } + + @Override + public String getButtonRunText() { + return "Run Game Controller"; + } + + public String getName() { + return title; } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidgetTest.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidgetTest.java new file mode 100644 index 000000000..83480a034 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/TransformWidgetTest.java @@ -0,0 +1,49 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import java.io.File; + +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; + +import javafx.application.Application; +import javafx.stage.Stage; +import javafx.scene.Scene; + +public class TransformWidgetTest extends Application { + private TransformWidget w; + + public TransformWidgetTest() { + this.w = new TransformWidget("Test Widget", new TransformNR(1,2,3), new IOnTransformChange() { + + @Override + public void onTransformFinished(TransformNR newTrans) { + System.out.println("Finished "+newTrans.toSimpleString() ); + } + + @Override + public void onTransformChaging(TransformNR newTrans) { + System.out.println("Changing "+newTrans.toSimpleString() ); + } + }); + + } + + @Override + public void start(Stage primaryStage) throws Exception { + File layoutFile = AssetFactory.loadFile("layout/default.css"); + String nwfile = layoutFile.toURI().toString().replace("file:/", "file:///"); + Scene scene = new Scene(w); + + scene.getStylesheets().clear(); + scene.getStylesheets().add(nwfile); + System.err.println("Loading CSS from " + nwfile); + + primaryStage.setScene(scene); + primaryStage.setWidth(370); + primaryStage.setHeight(490); + primaryStage.setTitle("Test Application"); + primaryStage.show(); + } + + +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitaminWidgetTest.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitaminWidgetTest.java new file mode 100644 index 000000000..d1106c6d6 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitaminWidgetTest.java @@ -0,0 +1,97 @@ +package com.neuronrobotics.bowlerstudio.creature; + +import java.io.File; + +import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.BowlerStudioController; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; +import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; +import com.neuronrobotics.sdk.addons.kinematics.MobileBase; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; + +import eu.mihosoft.vrl.v3d.JavaFXInitializer; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.stage.Stage; +import javafx.scene.Parent; +import javafx.fxml.FXMLLoader; + +public class VitaminWidgetTest extends Application { + private VitatminWidget tw; + + @Override + public void start(Stage primaryStage) throws Exception { + FXMLLoader loader = AssetFactory.loadLayout("layout/AddRemoveVitamins.fxml"); + loader.setClassLoader(VitatminWidget.class.getClassLoader()); + Parent w = loader.load(); + + tw = loader.getController(); + + File layoutFile = AssetFactory.loadFile("layout/default.css"); + String nwfile = layoutFile.toURI().toString().replace("file:/", "file:///"); + Scene scene = new Scene(w); + + scene.getStylesheets().clear(); + scene.getStylesheets().add(nwfile); + System.err.println("Loading CSS from " + nwfile); + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + System.out.println("Setting font size to "+fontNum); + w.setStyle("-fx-font-size: "+tmp+"pt"); + }); + primaryStage.setOnCloseRequest(arg0 -> { + System.exit(0); + }); + primaryStage.setScene(scene); + primaryStage.setWidth(600); + primaryStage.setHeight(777); + primaryStage.setTitle("Test Application"); + primaryStage.show(); + } + + public static void main(String[] args) { + JavaFXInitializer.go(); + BowlerStudio.runLater(() -> { + Stage s = new Stage(); + // + VitaminWidgetTest controller = new VitaminWidgetTest(); + try { + controller.start(s); + } catch (Exception e) { + e.printStackTrace(); + } + VitatminWidget tw = controller.getTw(); + new Thread(() -> { + try { + MobileBase mb = (MobileBase) ScriptingEngine + .gitScriptRun("https://github.com/NeuronRobotics/NASACurisoity.git", "NASA_Curiosity.xml"); + tw.setVitaminProvider(mb.getAllDHChains().get(0).getLinkConfiguration(0),selected->{ + return mb.forwardOffset(new TransformNR()); + }); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }).start(); + }); + } + + /** + * @return the tw + */ + public VitatminWidget getTw() { + return tw; + } + + /** + * @param tw the tw to set + */ + public void setTw(VitatminWidget tw) { + if (tw == null) + throw new RuntimeException(); + this.tw = tw; + } +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitatminWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitatminWidget.java new file mode 100644 index 000000000..0b98a43d3 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/creature/VitatminWidget.java @@ -0,0 +1,215 @@ +/** + * Sample Skeleton for 'AddRemoveVitamins.fxml' Controller Class + */ + +package com.neuronrobotics.bowlerstudio.creature; + +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.ResourceBundle; +import java.util.stream.Collectors; + +import com.neuronrobotics.bowlerstudio.BowlerStudioController; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.vitamins.Vitamins; +import com.neuronrobotics.sdk.addons.kinematics.IVitaminHolder; +import com.neuronrobotics.sdk.addons.kinematics.VitaminFrame; +import com.neuronrobotics.sdk.addons.kinematics.VitaminLocation; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; + +import eu.mihosoft.vrl.v3d.CSG; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.layout.*; +import javafx.scene.transform.Affine; + +public class VitatminWidget implements IOnTransformChange { + + private String selectedType = null; + private String sizeSelected = null; + private TransformWidget tf; + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // fx:id="add" + private Button add; // Value injected by FXMLLoader + + @FXML // fx:id="name" + private TextField name; // Value injected by FXMLLoader + + @FXML // fx:id="type" + private ComboBox type; // Value injected by FXMLLoader + + @FXML // fx:id="size" + private ComboBox size; // Value injected by FXMLLoader + @FXML // fx:id="listOfItems" + private ListView listOfItems; // Value injected by FXMLLoader + @FXML + private ComboBox frameType; + @FXML // fx:id="transformPanel" + private AnchorPane transformPanel; // Value injected by FXMLLoader + + private IVitaminHolder holder; + private HashMap locationMap = new HashMap<>(); + private VitaminLocation selectedVitamin; + private ITransformProvider currentTipProvider; + + @FXML + void onAdd(ActionEvent event) { + VitaminLocation newVit = new VitaminLocation(name.getText(), selectedType, sizeSelected, tf.getCurrent()); + VitaminFrame value = frameType.getValue(); + if(value==null) + value=VitaminFrame.DefaultFrame; + newVit.setFrame(value); + holder.addVitamin(newVit); + add(newVit); + validateInput(); + } + + private void add(VitaminLocation newVit) { + GridPane box = new GridPane(); + box.getColumnConstraints().add(new ColumnConstraints(30)); // translate text + box.getColumnConstraints().add(new ColumnConstraints(200)); // translate values + box.getColumnConstraints().add(new ColumnConstraints(200)); // units + box.getColumnConstraints().add(new ColumnConstraints(200)); // rotate text + box.setHgap(20);// gab between elements + box.setVgap(10);// gab between elements + locationMap.put(box, newVit); + Button remove = new Button(); + remove.setGraphic(AssetFactory.loadIcon("Clear-Screen.png")); + remove.setOnAction(action -> { + listOfItems.getSelectionModel().clearSelection(); + listOfItems.getItems().remove(box); + transformPanel.setDisable(true); + frameType.setDisable(true); + holder.removeVitamin(newVit); + validateInput(); + locationMap.remove(box); + }); + box.add(remove, 0, 0); + box.add(new Label(newVit.getName()), 1, 0); + box.add(new Label(newVit.getType()), 2, 0); + box.add(new Label(newVit.getSize()), 3, 0); + + listOfItems.getItems().add(box); + } + + void validateInput() { + add.setDisable(true); + String nameTmp = name.getText(); + //System.out.println("Validating " + nameTmp); + + if (nameTmp.length() == 0) + return; + if (selectedType == null) + return; + if (sizeSelected == null) + return; + for (VitaminLocation l : holder.getVitamins()) { + String name2 = l.getName(); + if (name2.contentEquals(nameTmp)) + return; + //System.out.println(nameTmp + " is not " + name2); + } + add.setDisable(false); + } + + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + assert add != null : "fx:id=\"add\" was not injected: check your FXML file 'AddRemoveVitamins.fxml'."; + assert name != null : "fx:id=\"name\" was not injected: check your FXML file 'AddRemoveVitamins.fxml'."; + assert type != null : "fx:id=\"type\" was not injected: check your FXML file 'AddRemoveVitamins.fxml'."; + assert size != null : "fx:id=\"size\" was not injected: check your FXML file 'AddRemoveVitamins.fxml'."; + List types = Vitamins.listVitaminTypes().stream().sorted().collect(Collectors.toList()); + for (String s : types) { + type.getItems().add(s); + } + type.setOnAction(action -> { + add.setDisable(true); + size.getItems().clear(); + selectedType = type.getSelectionModel().getSelectedItem(); + sizeSelected = null; + List sizes = Vitamins.listVitaminSizes(selectedType).stream().sorted().collect(Collectors.toList()); + for (String s : sizes) { + size.getItems().add(s); + } + }); + size.setOnAction(action -> { + add.setDisable(true); + sizeSelected = size.getSelectionModel().getSelectedItem(); + validateInput(); + }); + name.textProperty().addListener((observable, oldValue, newValue) -> { + validateInput(); + }); + listOfItems.getSelectionModel().selectedItemProperty().addListener((ob, old, fresh) -> { + selectedVitamin = locationMap.get(fresh); + if (selectedVitamin != null) { + fireVitaminSelectedUpdate(); + } + }); + tf = new TransformWidget("Vitamin Location", new TransformNR(), this); + transformPanel.getChildren().add(tf); + transformPanel.setDisable(true); + frameType.setDisable(true); + frameType.setOnAction(event->{ + if(frameType.getValue()!=selectedVitamin.getFrame()) + selectedVitamin.setFrame(frameType.getValue()); + }); + for(VitaminFrame vf:VitaminFrame.values()) { + frameType.getItems().add(vf); + } + } + + public void fireVitaminSelectedUpdate() { + if(selectedVitamin==null) + return; + System.out.println("Selected " + selectedVitamin.getName()); + name.setText(selectedVitamin.getName()); + type.getSelectionModel().select(selectedVitamin.getType()); + size.getSelectionModel().select(selectedVitamin.getSize()); + + tf.updatePose(selectedVitamin.getLocation()); + transformPanel.setDisable(false); + frameType.setDisable(false); + frameType.getSelectionModel().select(selectedVitamin.getFrame()); + MobileBaseCadManager manager = MobileBaseCadManager.get(holder); + try { + Affine af = manager.getVitaminAffine(selectedVitamin); + TransformNR poseToMove = currentTipProvider.get(selectedVitamin).copy(); + //poseToMove.setRotation(new RotationNR()); + CSG current = manager.getVitaminDisplay(selectedVitamin, af, poseToMove); + BowlerStudioController.highlightCsg(current); + BowlerStudioController.targetAndFollow(poseToMove,af); + } catch (Exception e) { + //e.printStackTrace(); + } + GameControlThreadManager.setCurrentController(tf); + + } + + public void setVitaminProvider(IVitaminHolder h,ITransformProvider currentTipProvider) { + this.holder = h; + this.currentTipProvider = currentTipProvider; + for (VitaminLocation l : h.getVitamins()) { + add(l); + } + } + + @Override + public void onTransformChaging(TransformNR newTrans) { + // TODO Auto-generated method stub + selectedVitamin.setLocation(newTrans); + } + + @Override + public void onTransformFinished(TransformNR newTrans) { + selectedVitamin.setLocation(newTrans); + } +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ExternalEditorController.java b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ExternalEditorController.java index 46df4a610..12b773116 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ExternalEditorController.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ExternalEditorController.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import javafx.scene.Node; import javafx.scene.control.Button; @@ -33,6 +34,10 @@ public ExternalEditorController(File f, CheckBox autoRun){ hasEditor=true; myEditor=e; image.setImage(e.getImage()); + FontSizeManager.addListener(fontNum->{ + image.setScaleX(FontSizeManager.getImageScale()); + image.setScaleY(FontSizeManager.getImageScale()); + }); System.err.println("ExternalEditorController: FOUND "+f.getName()+" is supported by "+e.getClass()); break; }else { @@ -45,16 +50,25 @@ public ExternalEditorController(File f, CheckBox autoRun){ advanced.setGraphic(image); advanced.setTooltip(new Tooltip("Click here to launch "+myEditor.nameOfEditor()+" the advanced editor for this file")); advanced.setText(myEditor.nameOfEditor()); - + advanced.setMinWidth(100); + advanced.setTextOverrun(javafx.scene.control.OverrunStyle.CLIP); advanced.setOnAction(event -> { advanced.setDisable(true); myEditor.launch(currentFile,advanced); //autoRun.setSelected(true); }); +// FontSizeManager.addListener(fontNum->{ +// advanced.setScaleX(FontSizeManager.getImageScale()); +// advanced.setScaleY(FontSizeManager.getImageScale()); +// }); }else { try { Image loadAsset = AssetFactory.loadAsset("Script-Tab-"+ScriptingEngine.getShellType(currentFile.getName())+".png"); image.setImage(loadAsset); + FontSizeManager.addListener(fontNum->{ + image.setScaleX(FontSizeManager.getImageScale()); + image.setScaleY(FontSizeManager.getImageScale()); + }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingFileWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingFileWidget.java index 58f463e5d..b1fe09f47 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingFileWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingFileWidget.java @@ -45,6 +45,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Scanner; +import javafx.scene.control.Tooltip; @SuppressWarnings("unused") public class ScriptingFileWidget extends BorderPane implements IFileChangeListener { @@ -59,7 +60,7 @@ public class ScriptingFileWidget extends BorderPane implements IFileChangeListen private ArrayList listeners = new ArrayList<>(); private Button runfx = new Button("Run"); - private Button arrange = new Button("Arrange"); + private Button arrange = new Button("Bed"); private Button publish = new Button("Save"); @@ -128,6 +129,10 @@ private void load(ScriptingWidgetType type, File currentFile) { }); publish.setTooltip(new Tooltip("Save this code to Git")); autoRun.setTooltip(new Tooltip("Check to auto-run files on file change")); + + arrange.setMinWidth(80); + publish.setMinWidth(80); + // Set up the run controls and the code area // The BorderPane has the same areas laid out as the @@ -168,14 +173,18 @@ private void load(ScriptingWidgetType type, File currentFile) { // little bit }); }); - System.err.println("\n\n\nScriptingFileWidget loading the editor loader:\n\n\n"); + + //System.err.println("\n\n\nScriptingFileWidget loading the editor loader:\n\n\n"); try { externalEditorController = new ExternalEditorController(currentFile, autoRun); }catch(Throwable t) { t.printStackTrace(); } - Button openFile = new Button("Open..."); + Button openFile = new Button("Open"); + openFile.setGraphic(AssetFactory.loadIcon("Folder.png")); + openFile.setMinWidth(85); + openFile.setTooltip(new Tooltip("Click here to open the file in the OS browser")); openFile.setOnAction(event -> { new Thread(() -> { Desktop desktop = Desktop.getDesktop(); @@ -188,7 +197,8 @@ private void load(ScriptingWidgetType type, File currentFile) { }).start(); }); - printbed = new Button("Export"); + printbed = new Button("STL"); + printbed.setMinWidth(80); printbed.setGraphic(AssetFactory.loadIcon("Edit-CAD-Engine.png")); BowlerStudio.runLater(() -> { printbed.setDisable(true); @@ -207,7 +217,6 @@ private void load(ScriptingWidgetType type, File currentFile) { tooltip.setText("\nMake a print bed and export all of the parts on the screen\n" + "to manufacturing. STL and SVG\n"); printbed.setTooltip(tooltip); - openFile.setTooltip(new Tooltip("Click here to open the file in the OS browser")); controlPane.getChildren().add(runfx); if (isOwnedByLoggedInUser) { controlPane.getChildren().add(arrange); @@ -218,10 +227,14 @@ private void load(ScriptingWidgetType type, File currentFile) { controlPane.getChildren().add(autoRun); controlPane.getChildren().add(publish); controlPane.getChildren().add(openFile); - controlPane.getChildren().add(new Label("file:")); + Label e = new Label("file:"); + e.setMinWidth(30); + controlPane.getChildren().add(e); controlPane.getChildren().add(fileNameBox); fileNameBox.setMaxWidth(Double.MAX_VALUE); - controlPane.getChildren().add(new Label("git:")); + Label e2 = new Label("git:"); + e2.setMinWidth(30); + controlPane.getChildren().add(e2); controlPane.getChildren().add(fileListBox); fileListBox.setMaxWidth(Double.MAX_VALUE); controlPane.setMaxWidth(Double.MAX_VALUE); @@ -318,10 +331,7 @@ public void saveTheFile(File currentFile) { private void reset() { running = false; BowlerStudio.runLater(() -> { - runfx.setText("Run"); - runfx.setGraphic(AssetFactory.loadIcon("Run.png")); - runfx.setBackground(new Background(new BackgroundFill(Color.LIGHTGREEN, CornerRadii.EMPTY, Insets.EMPTY))); - + BowlerStudio.setToRunButton(runfx); }); } @@ -385,21 +395,15 @@ private void start() { } } catch (Exception e) { // ignore CSG database - e.printStackTrace(); + //e.printStackTrace(); } BowlerStudio.clearConsole(); BowlerStudioController.clearHighlight(); - try { - ScriptingEngine.setAutoupdate(false); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } + running = true; BowlerStudio.runLater(() -> { - runfx.setText("Stop"); - runfx.setGraphic(AssetFactory.loadIcon("Stop.png")); - runfx.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY))); + BowlerStudio.setToStopButton(runfx); + }); scriptRunner = new Thread() { @@ -440,7 +444,7 @@ public void run() { } } if(enableArraange) { - Platform.runLater(()->{arrange.setDisable(false);}); + BowlerStudio.runLater(()->{arrange.setDisable(false);}); if (git != null && isArrange) { manager = new PrintBedManager(git, cache); obj=manager.get(); @@ -537,9 +541,11 @@ private void setUpFile(File f) { BowlerStudio.runLater(() -> { // fileListBox.setMinWidth(remote.getBytes().length*10); fileListBox.setText(remote); + fileListBox.setTooltip(new Tooltip(remote)); // fileListBox.res fileNameBox.setText(findLocalPath); + fileNameBox.setTooltip(new Tooltip(findLocalPath)); // These values are display only, so if hte user tries to change them, they // reset // the use of text field for static dats is so the user cna copy the vlaues and diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingWebWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingWebWidget.java index 55b3ea652..a304a109a 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingWebWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/scripting/ScriptingWebWidget.java @@ -4,6 +4,7 @@ import com.neuronrobotics.bowlerstudio.BowlerStudioController; import com.neuronrobotics.bowlerstudio.ConnectionManager; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; //import com.neuronrobotics.imageprovider.OpenCVImageProvider; import com.neuronrobotics.sdk.common.Log; import com.neuronrobotics.sdk.util.ThreadUtil; @@ -149,10 +150,7 @@ private void doFork() { private void reset() { running = false; BowlerStudio.runLater(() -> { - runfx.setText("Run"); - runfx.setGraphic(AssetFactory.loadIcon("Run.png")); - runfx.setBackground(new Background(new BackgroundFill(Color.LIGHTGREEN, CornerRadii.EMPTY, Insets.EMPTY))); - + BowlerStudio.setToRunButton(runfx); }); } @@ -218,6 +216,10 @@ private void loadGitLocal(String id, String file) { try { image.setImage(AssetFactory .loadAsset("Script-Tab-" + ScriptingEngine.getShellType(currentFile.getName()) + ".png")); + FontSizeManager.addListener(fontNum->{ + image.setScaleX(FontSizeManager.getImageScale()); + image.setScaleY(FontSizeManager.getImageScale()); + }); } catch (Exception e2) { // TODO Auto-generated catch block e2.printStackTrace(); @@ -303,18 +305,10 @@ public void loadCodeFromGist(String a, WebEngine e) throws Exception { private void start() { BowlerStudio.clearConsole(); - try { - ScriptingEngine.setAutoupdate(true); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } + running = true; BowlerStudio.runLater(() -> { - runfx.setText("Stop"); - runfx.setGraphic(AssetFactory.loadIcon("Stop.png")); - runfx.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY))); - + BowlerStudio.setToStopButton(runfx); }); scriptRunner = new Thread() { diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/CalibrateGameControl.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/CalibrateGameControl.java index a4a133ee7..a24245cef 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/CalibrateGameControl.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/CalibrateGameControl.java @@ -10,6 +10,7 @@ import org.firmata4j.ui.JPinboard; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.sdk.addons.gamepad.BowlerJInputDevice; import com.neuronrobotics.sdk.addons.gamepad.JogTrainerWidget; import com.neuronrobotics.sdk.addons.kinematics.FirmataBowler; @@ -52,7 +53,12 @@ public void initializeUI(BowlerAbstractDevice pm) { // This is needed when loading on MAC loader.setClassLoader(JogTrainerWidget.class.getClassLoader()); root = loader.load(); - + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); setContent(root); } catch (Exception e) { // TODO Auto-generated catch block diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/LocalFileScriptTab.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/LocalFileScriptTab.java index 60d010a1b..1382b758e 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/LocalFileScriptTab.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/LocalFileScriptTab.java @@ -435,14 +435,14 @@ private void setContent(String current) { timeSinceLastUpdate=now; System.out.println("External change of " + file.getName() + " on " + dateFormat.format(new Date())); - if (current.length() > MaxTextSize) { - textArea.setText( - "File too big for this text editor: " + current.length() + " larger than " + MaxTextSize); - textArea.setEnabled(false); - } else { +// if (current.length() > MaxTextSize) { +// textArea.setText( +// "File too big for this text editor: " + current.length() + " larger than " + MaxTextSize); +// textArea.setEnabled(false); +// } else { if (!textArea.getText().contentEquals(content)) textArea.setText(current); - } + //} } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTab.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTab.java index 661884cec..fa33f842b 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTab.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTab.java @@ -4,6 +4,7 @@ import com.neuronrobotics.bowlerstudio.BowlerStudioController; import com.neuronrobotics.bowlerstudio.Tutorial; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; import com.neuronrobotics.bowlerstudio.scripting.ScriptingWebWidget; @@ -184,7 +185,14 @@ public void changed(ObservableValue observable, vBox = new VBox(5); vBox.getChildren().setAll(hBox, webView); VBox.setVgrow(webView, Priority.ALWAYS); - + FontSizeManager.addListener(fontNum -> { + double scale = ((double) fontNum - 10) / 12.0; + if (scale < 1) + scale = 1; + System.out.println("Web scale "+scale); + double s=scale; + BowlerStudio.runLater(() ->webView.setZoom(s)); + }); myTab.setContent(vBox); //Action definition for the Button Go. EventHandler goAction = event -> { diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabController.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabController.java new file mode 100644 index 000000000..e0ae4316d --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabController.java @@ -0,0 +1,173 @@ +/** + * Sample Skeleton for 'WebTabLayout.fxml' Controller Class + */ + +package com.neuronrobotics.bowlerstudio.tabs; + +import java.net.URL; +import java.time.Duration; +import java.util.ResourceBundle; + +import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.BowlerStudioController; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; +import com.neuronrobotics.bowlerstudio.scripting.PasswordManager; +import com.neuronrobotics.sdk.common.Log; + +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebView; + +public class WebTabController { + private boolean initialized = false; + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // fx:id="pane" + private TabPane pane; // Value injected by FXMLLoader + + @FXML // fx:id="tab" + private Tab tab; // Value injected by FXMLLoader + + @FXML // fx:id="back" + private Button back; // Value injected by FXMLLoader + + @FXML // fx:id="forward" + private Button forward; // Value injected by FXMLLoader + + @FXML // fx:id="home" + private Button home; // Value injected by FXMLLoader + + @FXML // fx:id="refresh" + private Button refresh; // Value injected by FXMLLoader + + @FXML // fx:id="urlField" + private TextField urlField; // Value injected by FXMLLoader + + @FXML // fx:id="run" + private Button run; // Value injected by FXMLLoader + + @FXML // fx:id="iconHolder" + private VBox iconHolder; // Value injected by FXMLLoader + + @FXML // fx:id="copy" + private Button copy; // Value injected by FXMLLoader + + @FXML // fx:id="fileCHoice" + private ComboBox fileCHoice; // Value injected by FXMLLoader + + @FXML // fx:id="scrollpane" + private ScrollPane scrollpane; // Value injected by FXMLLoader + + @FXML // fx:id="webview" + private WebView webview; // Value injected by FXMLLoader + + private WebEngine webEngine; + + private String Current_URL; + + @FXML + void onCopy(ActionEvent event) { + + } + + @FXML + void onFileSelect(ActionEvent event) { + + } + + @FXML + void onRunStop(ActionEvent event) { + + } + + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + assert pane != null : "fx:id=\"pane\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert back != null : "fx:id=\"back\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert forward != null : "fx:id=\"forward\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert home != null : "fx:id=\"home\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert refresh != null : "fx:id=\"refresh\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert urlField != null : "fx:id=\"urlField\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert run != null : "fx:id=\"run\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert iconHolder != null : "fx:id=\"iconHolder\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert copy != null : "fx:id=\"copy\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert fileCHoice != null : "fx:id=\"fileCHoice\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + //assert scrollpane != null : "fx:id=\"scrollpane\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + assert webview != null : "fx:id=\"webview\" was not injected: check your FXML file 'WebTabLayout.fxml'."; + webEngine = webview.getEngine(); + FontSizeManager.addListener(fontNum -> { + double scale = ((double) fontNum - 10) / 12.0; + if (scale < 1) + scale = 1; + System.out.println("Web scale "+scale); +// webview.setScaleX(scale); +// webview.setScaleY(scale); + double s=scale; + BowlerStudio.runLater(() ->webview.setZoom(s)); + }); + scrollpane.setFitToHeight(true); + scrollpane.setFitToWidth(true); + + refresh.setGraphic(AssetFactory.loadIcon("Go-Refresh.png")); + home.setGraphic(AssetFactory.loadIcon("Home.png")); + back.setGraphic(AssetFactory.loadIcon("Back-Button.png")); + forward.setGraphic(AssetFactory.loadIcon("Forward-Button.png")); + BowlerStudio.setToRunButton(run); + webEngine.locationProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable1,String oldValue, String newValue) { + + //System.out.println("Location Changed: "+newValue); + BowlerStudio.runLater(() -> { + urlField.setText(newValue); + }); + } + }); + + setInitialized(true); + BowlerStudio.runLater( + Duration.ofMillis(200) ,()->{ + loadUrl("https://commonwealthrobotics.com/BowlerStudio/Welcome-To-BowlerStudio/"); + }); + } + + public void loadUrl(String url) { + BowlerStudio.runLater(() -> { + Current_URL = url.startsWith("http://") ||url.startsWith("https://") + || url.startsWith("file:") ? url : "http://" + url; + webEngine.load(Current_URL); + System.out.println("Go TO URL " + url); + }); + + } + /** + * @return the initialized + */ + public boolean isInitialized() { + return initialized; + } + + /** + * @param initialized the initialized to set + */ + private void setInitialized(boolean initialized) { + this.initialized = initialized; + } + +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabFactory.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabFactory.java new file mode 100644 index 000000000..3989994cf --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabFactory.java @@ -0,0 +1,24 @@ +package com.neuronrobotics.bowlerstudio.tabs; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.collections.ObservableList; +import javafx.concurrent.Worker.State; +import javafx.event.ActionEvent; +import javafx.event.Event; +import javafx.event.EventHandler; +import javafx.scene.control.Button; +import javafx.scene.control.Tab; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebHistory; +import javafx.scene.web.WebView; +import javafx.scene.layout.AnchorPane; +public class WebTabFactory { + + public static Tab WebTab(String title, String Url,boolean isTutorialTab) { + return null; + } +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabTest.java b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabTest.java new file mode 100644 index 000000000..b92b93745 --- /dev/null +++ b/src/main/java/com/neuronrobotics/bowlerstudio/tabs/WebTabTest.java @@ -0,0 +1,90 @@ +package com.neuronrobotics.bowlerstudio.tabs; + +import java.io.File; +import java.time.Duration; + +import com.neuronrobotics.bowlerstudio.BowlerStudio; +import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; +import com.neuronrobotics.bowlerstudio.creature.VitaminWidgetTest; +import com.neuronrobotics.bowlerstudio.creature.VitatminWidget; +import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine; +import com.neuronrobotics.sdk.addons.kinematics.MobileBase; +import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR; + +import eu.mihosoft.vrl.v3d.JavaFXInitializer; +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Tab; +import javafx.stage.Stage; + +public class WebTabTest extends Application { + private WebTabController tw; + + @Override + public void start(Stage primaryStage) throws Exception { + FXMLLoader loader = AssetFactory.loadLayout("layout/WebTabLayout.fxml"); + loader.setClassLoader(WebTabController.class.getClassLoader()); + Parent w = loader.load(); + + tw = loader.getController(); + + File layoutFile = AssetFactory.loadFile("layout/default.css"); + String nwfile = layoutFile.toURI().toString().replace("file:/", "file:///"); + Scene scene = new Scene(w); + + scene.getStylesheets().clear(); + scene.getStylesheets().add(nwfile); + System.err.println("Loading CSS from " + nwfile); + + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + System.out.println("Setting font size to "+fontNum); + w.setStyle("-fx-font-size: "+tmp+"pt"); + }); + primaryStage.setOnCloseRequest(arg0 -> { + System.exit(0); + }); + + + primaryStage.setScene(scene); + primaryStage.setWidth(600); + primaryStage.setHeight(777); + primaryStage.setTitle("Web Tab Test Application"); + primaryStage.show(); + + } + + public static void main(String[] args) { + JavaFXInitializer.go(); + + BowlerStudio.runLater(() -> { + Stage s = new Stage(); + // + WebTabTest controller = new WebTabTest(); + try { + controller.start(s); + + } catch (Exception e) { + e.printStackTrace(); + } + WebTabController tw = controller.getTw(); + new Thread(() -> { + FontSizeManager.setFontSize(48); + }).start(); + }); + } + + /** + * @return the tw + */ + public WebTabController getTw() { + return tw; + } + + +} diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/threed/Axis.java b/src/main/java/com/neuronrobotics/bowlerstudio/threed/Axis.java index 5f73d0742..a8cdcf551 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/threed/Axis.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/threed/Axis.java @@ -136,13 +136,17 @@ public void show() { } private void showAll() { - for (Node n : Arrays.asList(xAxis.getMesh(), yAxis.getMesh(), zAxis.getMesh(), xText.getMesh(), yText.getMesh(), zText.getMesh())) { - try { - n.setPickOnBounds(false); - n.setMouseTransparent(true); - getChildren().add(n); - } catch (Exception e) { + try { + for (Node n : Arrays.asList(xAxis.getMesh(), yAxis.getMesh(), zAxis.getMesh(), xText.getMesh(), yText.getMesh(), zText.getMesh())) { + try { + n.setPickOnBounds(false); + n.setMouseTransparent(true); + getChildren().add(n); + } catch (Exception e) { + } } + }catch(Exception ex) { + // no exception on exit } } diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/threed/BowlerStudio3dEngine.java b/src/main/java/com/neuronrobotics/bowlerstudio/threed/BowlerStudio3dEngine.java index 3988cff68..eaa84f131 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/threed/BowlerStudio3dEngine.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/threed/BowlerStudio3dEngine.java @@ -53,6 +53,7 @@ import com.neuronrobotics.sdk.common.Log; import eu.mihosoft.vrl.v3d.CSG; import eu.mihosoft.vrl.v3d.Cylinder; +import eu.mihosoft.vrl.v3d.JavaFXInitializer; import eu.mihosoft.vrl.v3d.parametrics.CSGDatabase; import eu.mihosoft.vrl.v3d.parametrics.IParameterChanged; import eu.mihosoft.vrl.v3d.parametrics.LengthParameter; @@ -217,7 +218,11 @@ public class BowlerStudio3dEngine extends JFXPanel { private HBox controlsChecks; private Thread autospingThread=null; private CheckMenuItem showRuler; + private TransformNR targetNR; + private TransformNR poseToMove=new TransformNR(); + static { + //JavaFXInitializer.go(); BowlerStudio.runLater(() -> { Thread.currentThread().setUncaughtExceptionHandler(new IssueReportingExceptionHandler()); @@ -230,7 +235,7 @@ public class BowlerStudio3dEngine extends JFXPanel { public BowlerStudio3dEngine() { System.err.println("Setting Scene "); - setSubScene(new SubScene(getRoot(), 1024, 1024, true, SceneAntialiasing.BALANCED)); + setSubScene(new SubScene(getRoot(), 1024, 1024, true, SceneAntialiasing.DISABLED)); // Set up the Ui THread explosion handler @@ -560,12 +565,13 @@ public MeshView addObject(CSG currentCsg, File source) { } MeshView current = getCsgMap().get(currentCsg); - + current.setCullFace(javafx.scene.shape.CullFace.NONE); // TriangleMesh mesh =(TriangleMesh) current.getMesh(); // mesh.vertexFormatProperty() ContextMenu cm = new ContextMenu(); Menu infomenu = new Menu("Info..."); infomenu.getItems().add(new MenuItem("Name= " + currentCsg.getName())); + infomenu.getItems().add(new MenuItem("Mass = " + (currentCsg.getMassKG(0.001)*1000)+" grams ")); infomenu.getItems().add(new MenuItem("Total X= " + currentCsg.getTotalX())); infomenu.getItems().add(new MenuItem("Total Y= " + currentCsg.getTotalY())); infomenu.getItems().add(new MenuItem("Total Z= " + currentCsg.getTotalZ())); @@ -909,7 +915,7 @@ private void buildCamera() { hand = new Group(cylinder.getMesh()); camera.setNearClip(.1); - camera.setFarClip(100.0); + //camera.setFarClip(1000.0);//this is set in VirtualCameraMobileBase getSubScene().setCamera(camera); camera.setRotationAxis(Rotate.Z_AXIS); @@ -1111,7 +1117,7 @@ public void run() { // reset only if an object is not being selected if (lastClickedDifference < offset) { cancelSelection(); - // System.err.println("Cancel event detected"); + System.err.println("Cancel event detected"); } } else { // System.err.println("too soon after a select @@ -1184,23 +1190,27 @@ public void handle(MouseEvent me) { scene.addEventHandler(ScrollEvent.ANY, t -> { if (ScrollEvent.SCROLL == t.getEventType()) { - double zoomFactor = -(t.getDeltaY()) * getVirtualcam().getZoomDepth() / 500; - // - // double z = camera.getTranslateY(); - // double newZ = z + zoomFactor; - // camera.setTranslateY(newZ); - // System.out.println("Z = "+zoomFactor); - - getVirtualcam().setZoomDepth(getVirtualcam().getZoomDepth() + zoomFactor); + double deltaY = t.getDeltaY(); + zoomIncrement(deltaY); } t.consume(); }); } - private void moveCamera(TransformNR newPose) { - getFlyingCamera().DriveArc(newPose); + public void zoomIncrement(double deltaY) { + double zoomFactor = -deltaY * getVirtualcam().getZoomDepth() / 500; + // + // double z = camera.getTranslateY(); + // double newZ = z + zoomFactor; + // camera.setTranslateY(newZ); + // System.out.println("Z = "+zoomFactor); + + getVirtualcam().setZoomDepth(getVirtualcam().getZoomDepth() + zoomFactor); + } + public void moveCamera(TransformNR newPose) { + getFlyingCamera().DriveArc(newPose); } private void selectObjectsSourceFile(CSG source) { @@ -1289,6 +1299,7 @@ public SubScene getSubScene() { public void setSubScene(SubScene scene) { System.out.println("Setting UI scene"); this.scene = scene; + } /** @@ -1339,26 +1350,26 @@ public void cancelSelection() { this.selectedCsg = null; // new Exception().printStackTrace(); - TransformNR startSelectNr = perviousTarget.copy(); - TransformNR targetNR = new TransformNR(); - Affine interpolator = new Affine(); - - BowlerStudio.runLater(() -> { - TransformFactory.nrToAffine(startSelectNr, interpolator); - - removeAllFocusTransforms(); - - focusGroup.getTransforms().add(interpolator); - - focusInterpolate(startSelectNr, targetNR, 0, 15, interpolator); - - }); + focusToAffine(new TransformNR(), new Affine()); resetMouseTime(); } - - public void setSelected(Affine rootListener) { - focusToAffine(new TransformNR(), rootListener); +/** + * Select a provided affine that is in a given global pose + * @param startingLocation the starting pose + * @param rootListener what affine to attach to + */ + public void setSelected(TransformNR startingLocation,Affine rootListener) { + focusToAffine(startingLocation, rootListener); } + + /** + * Select a provided affine that is in a given global pose + * @param startingLocation the starting pose + * @param rootListener what affine to attach to + */ + public void setSelected(Affine rootListener) { + focusToAffine(new TransformNR(), rootListener); + } public void setSelectedCsg(List selectedCsg) { // System.err.println("Selecting group"); @@ -1380,9 +1391,15 @@ public void setSelectedCsg(List selectedCsg) { } // if a selection is called before the limb is loaded resetMouseTime(); } - public void setSelectedCsg(CSG scg) { - if (scg == this.selectedCsg || focusing || scg == null) + setSelectedCsg(scg,false); + } + public void setSelectedCsg(CSG scg, boolean justHighlight) { + if (scg == this.selectedCsg ) + return; + if ( focusing ) + return; + if (scg == null) return; this.selectedCsg = scg; @@ -1396,46 +1413,37 @@ public void setSelectedCsg(CSG scg) { }); } lastSelectedTime = System.currentTimeMillis(); - // System.err.println("Selecting a CSG"); - // System.err.println("Selecting one"); - -// FxTimer.runLater(java.time.Duration.ofMillis(1), -// -// new Runnable() { -// @Override -// public void run() { BowlerStudio.runLater(() -> { try { getCsgMap().get(selectedCsg).setMaterial(new PhongMaterial(Color.GOLD)); } catch (Exception e) { } }); -// } - // }); - // System.out.println("Selecting "+selectedCsg); - double xcenter = selectedCsg.getMaxX() / 2 + selectedCsg.getMinX() / 2; - double ycenter = selectedCsg.getMaxY() / 2 + selectedCsg.getMinY() / 2; - double zcenter = selectedCsg.getMaxZ() / 2 + selectedCsg.getMinZ() / 2; - - TransformNR poseToMove = new TransformNR(); - CSG finalCSG = selectedCsg; - if (selectedCsg.getMaxX() < 1 || selectedCsg.getMinX() > -1) { - finalCSG = finalCSG.movex(-xcenter); - poseToMove.translateX(xcenter); - } - if (selectedCsg.getMaxY() < 1 || selectedCsg.getMinY() > -1) { - finalCSG = finalCSG.movey(-ycenter); - poseToMove.translateY(ycenter); - } - if (selectedCsg.getMaxZ() < 1 || selectedCsg.getMinZ() > -1) { - finalCSG = finalCSG.movez(-zcenter); - poseToMove.translateZ(zcenter); + if(!justHighlight) { + double xcenter = selectedCsg.getMaxX() / 2 + selectedCsg.getMinX() / 2; + double ycenter = selectedCsg.getMaxY() / 2 + selectedCsg.getMinY() / 2; + double zcenter = selectedCsg.getMaxZ() / 2 + selectedCsg.getMinZ() / 2; + + TransformNR poseToMove = new TransformNR(); + CSG finalCSG = selectedCsg; + if (selectedCsg.getMaxX() < 1 || selectedCsg.getMinX() > -1) { + finalCSG = finalCSG.movex(-xcenter); + poseToMove.translateX(xcenter); + } + if (selectedCsg.getMaxY() < 1 || selectedCsg.getMinY() > -1) { + finalCSG = finalCSG.movey(-ycenter); + poseToMove.translateY(ycenter); + } + if (selectedCsg.getMaxZ() < 1 || selectedCsg.getMinZ() > -1) { + finalCSG = finalCSG.movez(-zcenter); + poseToMove.translateZ(zcenter); + } + + Affine manipulator2 = selectedCsg.getManipulator(); + + focusToAffine(poseToMove, manipulator2); } - - Affine manipulator2 = selectedCsg.getManipulator(); - - focusToAffine(poseToMove, manipulator2); resetMouseTime(); } @@ -1466,6 +1474,7 @@ public void focusToAffine(TransformNR poseToMove, Affine manipulator2) { } else { targetNR = TransformFactory.affineToNr(centering); } + this.poseToMove = targetNR; Affine interpolator = new Affine(); Affine correction = TransformFactory.nrToAffine(reverseRotation); interpolator.setTx(startSelectNr.getX() - targetNR.getX()); @@ -1487,63 +1496,119 @@ public void focusToAffine(TransformNR poseToMove, Affine manipulator2) { // }); } catch (Exception ex) { + ex.printStackTrace(); } - focusInterpolate(startSelectNr, targetNR, 0, 30, interpolator); + focusInterpolate(startSelectNr, targetNR, 30, interpolator); }); } + public void targetAndFollow(TransformNR poseToMove, Affine manipulator2) { + this.poseToMove = poseToMove; + if (focusing) + return; + if (manipulator2 == null) { + new RuntimeException("Can not focus on null affine").printStackTrace(); + return; + } + focusing = true; + BowlerStudio.runLater(() -> { + Affine referenceFrame = TransformFactory.nrToAffine(poseToMove); + // this section keeps the camera orented the same way to avoid whipping + // around + + TransformNR rotationOnlyCOmponentOfManipulator2 = poseToMove.copy(); + rotationOnlyCOmponentOfManipulator2.setX(0); + rotationOnlyCOmponentOfManipulator2.setY(0); + rotationOnlyCOmponentOfManipulator2.setZ(0); + TransformNR reverseRotation2 = rotationOnlyCOmponentOfManipulator2.inverse(); + Affine correction2 = TransformFactory.nrToAffine(reverseRotation2); + + TransformNR rotationOnlyCOmponentOfManipulator = TransformFactory.affineToNr(manipulator2); + rotationOnlyCOmponentOfManipulator.setX(0); + rotationOnlyCOmponentOfManipulator.setY(0); + rotationOnlyCOmponentOfManipulator.setZ(0); + TransformNR reverseRotation = rotationOnlyCOmponentOfManipulator.inverse(); + Affine correction = TransformFactory.nrToAffine(reverseRotation); + TransformNR startSelectNr = perviousTarget.copy(); + // = + // TransformFactory.affineToNr(selectedCsg.getManipulat/or()); + + targetNR = poseToMove.times(TransformFactory.affineToNr(manipulator2)); + + Affine interpolator = new Affine(); + interpolator.setTx(startSelectNr.getX() - targetNR.getX()); + interpolator.setTy(startSelectNr.getY() - targetNR.getY()); + interpolator.setTz(startSelectNr.getZ() - targetNR.getZ()); + removeAllFocusTransforms(); + focusGroup.getTransforms().add(interpolator); + focusGroup.getTransforms().add(referenceFrame); + try { + focusGroup.getTransforms().add(manipulator2); + focusGroup.getTransforms().add(correction); + focusGroup.getTransforms().add(correction2); + } catch (Exception ex) { + ex.printStackTrace(); + } + focusInterpolate(startSelectNr, targetNR, 30, interpolator); + }); + } private void resetMouseTime() { // System.err.println("Resetting mouse"); this.lastMosueMovementTime = System.currentTimeMillis(); } - private void focusInterpolate(TransformNR start, TransformNR target, int depth, int targetDepth, + private void focusInterpolate(TransformNR start, TransformNR target, int targetDepth, Affine interpolator) { - double depthScale = 1 - (double) depth / (double) targetDepth; - double sinunsoidalScale = Math.sin(depthScale * (Math.PI / 2)); + + new Thread(() -> { + int depth=0; + while (focusing) { + try { + Thread.sleep(16); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + focusing = false; + } + double depthScale = 1 - (double) depth / (double) targetDepth; + double sinunsoidalScale = Math.sin(depthScale * (Math.PI / 2)); - // double xIncrement =target.getX()- ((start.getX() - target.getX()) * - // depthScale) + start.getX(); - double difference = start.getX() - target.getX(); - double scaledDifference = (difference * sinunsoidalScale); + // double xIncrement =target.getX()- ((start.getX() - target.getX()) * + // depthScale) + start.getX(); + double difference = start.getX() - target.getX(); + double scaledDifference = (difference * sinunsoidalScale); - double xIncrement = scaledDifference; - double yIncrement = ((start.getY() - target.getY()) * sinunsoidalScale); - double zIncrement = ((start.getZ() - target.getZ()) * sinunsoidalScale); + double xIncrement = scaledDifference; + double yIncrement = ((start.getY() - target.getY()) * sinunsoidalScale); + double zIncrement = ((start.getZ() - target.getZ()) * sinunsoidalScale); - BowlerStudio.runLater(() -> { - interpolator.setTx(xIncrement); - interpolator.setTy(yIncrement); - interpolator.setTz(zIncrement); - }); - // System.err.println("Interpolation step " + depth + " x " + xIncrement - // + " y " + yIncrement + " z " + zIncrement); - if (depth < targetDepth) { - BowlerStudio.runLater(Duration.ofMillis(16), new Runnable() { - @Override - public void run() { - focusInterpolate(start, target, depth + 1, targetDepth, interpolator); + BowlerStudio.runLater(() -> { + interpolator.setTx(xIncrement); + interpolator.setTy(yIncrement); + interpolator.setTz(zIncrement); + }); + // System.err.println("Interpolation step " + depth + " x " + xIncrement + // + " y " + yIncrement + " z " + zIncrement); + if (depth >= targetDepth) { + // System.err.println("Camera intrpolation done"); + BowlerStudio.runLater(() -> { + focusGroup.getTransforms().remove(interpolator); + }); + perviousTarget = target.copy(); + perviousTarget.setRotation(new RotationNR()); + focusing = false; } - }); - } else { - // System.err.println("Camera intrpolation done"); - BowlerStudio.runLater(() -> { - focusGroup.getTransforms().remove(interpolator); - }); - perviousTarget = target.copy(); - perviousTarget.setRotation(new RotationNR()); - focusing = false; - } + + depth++; + } + }).start(); + } private void removeAllFocusTransforms() { - ObservableList allTrans = focusGroup.getTransforms(); - List toRemove = Arrays.asList(allTrans.toArray()); - for (Object t : toRemove) { - allTrans.remove(t); - } + focusGroup.getTransforms().clear(); } public HashMap getCsgMap() { @@ -1606,4 +1671,13 @@ public void setDefaultStlDir(File defaultStlDir) { this.defaultStlDir = defaultStlDir; } + public void focusToAffine(Affine af) { + focusToAffine(new TransformNR(),af); + } + + public TransformNR getTargetNR() { + // TODO Auto-generated method stub + return poseToMove; + } + } \ No newline at end of file diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/threed/VirtualCameraMobileBase.java b/src/main/java/com/neuronrobotics/bowlerstudio/threed/VirtualCameraMobileBase.java index 5360b8b29..081094607 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/threed/VirtualCameraMobileBase.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/threed/VirtualCameraMobileBase.java @@ -120,8 +120,8 @@ public void setZoomDepth(double zoomDepth) { if (zoomDepth < -9000) zoomDepth = -9000; this.zoomDepth = zoomDepth; - if(zoomDepth>5000) - camera.setFarClip(zoomDepth*2); + if(zoomDepth<-5000) + camera.setFarClip(-zoomDepth*2); else camera.setFarClip(10000); zoomAffine.setTz(getZoomDepth()); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/utils/BowlerConnectionMenu.java b/src/main/java/com/neuronrobotics/bowlerstudio/utils/BowlerConnectionMenu.java index 31659f517..2735753ac 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/utils/BowlerConnectionMenu.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/utils/BowlerConnectionMenu.java @@ -3,6 +3,7 @@ import com.neuronrobotics.bowlerstudio.BowlerStudio; import com.neuronrobotics.bowlerstudio.BowlerStudioController; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; import com.neuronrobotics.sdk.common.BowlerDatagram; import com.neuronrobotics.sdk.common.DeviceManager; import com.neuronrobotics.sdk.common.Log; @@ -231,7 +232,12 @@ public void start(Stage primaryStage) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); - + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); BowlerStudio.runLater(() -> { primaryStage.setTitle("Bowler Device Connection"); diff --git a/src/main/java/com/neuronrobotics/bowlerstudio/utils/FindTextWidget.java b/src/main/java/com/neuronrobotics/bowlerstudio/utils/FindTextWidget.java index 1efecfedf..d30387d7b 100644 --- a/src/main/java/com/neuronrobotics/bowlerstudio/utils/FindTextWidget.java +++ b/src/main/java/com/neuronrobotics/bowlerstudio/utils/FindTextWidget.java @@ -5,6 +5,8 @@ import com.neuronrobotics.bowlerstudio.BowlerStudio; import com.neuronrobotics.bowlerstudio.assets.AssetFactory; +import com.neuronrobotics.bowlerstudio.assets.FontSizeManager; + import javafx.application.Application; import javafx.application.Platform; import javafx.event.ActionEvent; @@ -213,7 +215,12 @@ public void start(Stage primaryStage) throws Exception { // This is needed when loading on MAC loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); - + FontSizeManager.addListener(fontNum->{ + int tmp = fontNum-10; + if(tmp<12) + tmp=12; + root.setStyle("-fx-font-size: "+tmp+"pt"); + }); BowlerStudio.runLater(() -> { primaryStage.setTitle("Find/Replace"); Scene scene = new Scene(root);