From 1e96334981178146c84881265d15e66f26e8bd3e Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Sun, 21 Oct 2018 17:27:28 -0600 Subject: [PATCH 01/28] Branch for UI Development A few changes to get it running in VR --- build.sbt | 2 ++ project/build.properties | 1 + project/build.sbt | 2 +- project/ghpages.sbt | 2 +- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 5 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 project/build.properties diff --git a/build.sbt b/build.sbt index 709192c..9a65cd7 100644 --- a/build.sbt +++ b/build.sbt @@ -21,6 +21,7 @@ skip in packageJSDependencies := false libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.5" libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test" +/* // sbt ghpagesPushSite enablePlugins(GhpagesPlugin) enablePlugins(SiteScaladocPlugin) @@ -46,3 +47,4 @@ mappings in makeSite ++= Seq( file(s"${Paths.www}/js/lib/webvr-polyfill.min.js") -> "js/lib/webvr-polyfill.min.js", file("target/scala-2.12/vrdatavisualization-opt.js") -> "js/vrdatavisualization-opt.js" ) +*/ diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..0531343 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.1.2 diff --git a/project/build.sbt b/project/build.sbt index 909198e..45c500c 100644 --- a/project/build.sbt +++ b/project/build.sbt @@ -1,3 +1,3 @@ addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.22") -addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.2") +/*addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.3.2")*/ diff --git a/project/ghpages.sbt b/project/ghpages.sbt index 06eabbc..e335f67 100644 --- a/project/ghpages.sbt +++ b/project/ghpages.sbt @@ -1 +1 @@ -addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2") \ No newline at end of file +/*addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.2")*/ \ No newline at end of file diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index b798c32..3d4ad54 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -26,7 +26,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.setSize(window.innerWidth, window.innerHeight) renderer.devicePixelRatio = window.devicePixelRatio - //renderer.vr.enabled = true + renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 79f548c391addbb29548e8e2e6e9f10a6278d850 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 25 Oct 2018 14:56:55 -0600 Subject: [PATCH 02/28] Added TEst Button to GUI --- src/main/scala/vrdv/obj3D/DatGui.scala | 8 ++++++++ src/main/scala/vrdv/view/ViewManager.scala | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index 6085908..22cae58 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -2,6 +2,7 @@ package vrdv.obj3D import facade.Dat import facade.Dat.{GuiButton, GuiSlider} +import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter import vrdv.obj3D.plots._ @@ -115,6 +116,13 @@ object DatGui { Button(3, embeddingFolder).setLabels("Embed!", "Embed xVar") gui.object3D.addFolder(embeddingFolder) + val testFolder = Dat.GUIVR.create("Testing") + testFolder.addButton(() => { + Log.show("Test button clicked!") + }) + Button(0, testFolder).setLabels("TestButton!", "Test button.") + gui.object3D.addFolder(testFolder) + gui } diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 3d4ad54..3f7ba15 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -26,6 +26,8 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.setSize(window.innerWidth, window.innerHeight) renderer.devicePixelRatio = window.devicePixelRatio + + //Comment out the next line to use keyboard controls in browser - VR will not work renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From d74c1b41026f87e34044598392fd9b2eea18e0a0 Mon Sep 17 00:00:00 2001 From: "Dorian Thiessen (dbt908)" Date: Fri, 26 Oct 2018 16:36:02 -0600 Subject: [PATCH 03/28] Add sample checkbox and drop-down --- src/main/scala/facade/Dat.scala | 1 + src/main/scala/vrdv/model/Plotter.scala | 2 ++ src/main/scala/vrdv/obj3D/DatGui.scala | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index be43d1a..4efb75d 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -26,6 +26,7 @@ object Dat { trait GUI extends Object3D { def add(something: js.Object): Unit = js.native def add(something: js.Object, id: String): Unit = js.native + def add(something: js.Object, id: String, options: js.Array[String]): Unit = js.native // For drop-downs def add(something: js.Object, id: String, min: Double, max: Double): GuiSlider = js.native def addFolder(folder: GUI): GUI = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index 65e3979..c4d2886 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -13,6 +13,8 @@ import vrdv.obj3D.{CustomColors, DatGui, Region} */ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { + scene.add(DatGui.sample.object3D) + private var DATA: Array[Array[Data]] = Array() private var REGIONS: Array[Region] = Array() private var PLOT: Array[Plot] = Array() diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index 22cae58..187c8a6 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -24,6 +24,11 @@ class DatGui { // 0: HPD Folder, 1: SPS Folder var folders: Array[Dat.GUI] = Array() + var samples: js.Object = js.Dynamic.literal( + "someBoolean" → false, + "someValue" → "a" + ) + def addFolder(folder: Dat.GUI): Unit = { object3D.addFolder(folder) folders = folders :+ folder @@ -80,6 +85,19 @@ class DatGui { object DatGui { + def sample: DatGui = { + val gui = new DatGui() + // # Checkbox sample + gui.object3D.add(gui.samples, "someBoolean") + + // # Drop-down sample + // NOTE: Position of selected value is lower than it should be. + val dropDownOptions = js.Array("a", "b", "c") + gui.object3D.add(gui.samples, "someValue", dropDownOptions) + + gui + } + def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { val gui = new DatGui() createHighlightedPointDataFolder(gui, plot) From a1d4134d020d467743974d8be64b32b0209f75bd Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 1 Nov 2018 13:36:18 -0600 Subject: [PATCH 04/28] Creating second menu. Can't get title to change. --- src/main/scala/vrdv/model/Plotter.scala | 3 +- src/main/scala/vrdv/obj3D/DatGui.scala | 36 +++++++++++++++++++++- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index c4d2886..bffdb64 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -13,7 +13,8 @@ import vrdv.obj3D.{CustomColors, DatGui, Region} */ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { - scene.add(DatGui.sample.object3D) + //Instantiating the Initial Menu + scene.add(DatGui.initialMenu.object3D) private var DATA: Array[Array[Data]] = Array() private var REGIONS: Array[Region] = Array() diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index 187c8a6..6f5e3ef 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -85,6 +85,29 @@ class DatGui { object DatGui { + def initialMenu: DatGui = { + val gui = new DatGui() + + gui.object3D.position.set(0, 2, -3) + + gui.object3D.addButton(() => { + Log.show("Graph 1 button clicked!") + }) + Button(0, gui.object3D).setLabels("Create", "Graph 1") + + gui.object3D.addButton((() => { + Log.show("Graph 2 button clicked!") + })) + Button(1, gui.object3D).setLabels("Create", "Graph 2") + + gui.object3D.addButton(() => { + Log.show("Graph 3 button clicked!") + }) + Button(2, gui.object3D).setLabels("Create", "Graph 3") + + gui + } + def sample: DatGui = { val gui = new DatGui() // # Checkbox sample @@ -98,7 +121,7 @@ object DatGui { gui } - def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { + def plotDetailsMenu(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { val gui = new DatGui() createHighlightedPointDataFolder(gui, plot) createSelectedPointsDataFolder(gui, plot, mc) @@ -144,6 +167,17 @@ object DatGui { gui } + def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { + plotDetailsMenu(plot, axes, mc) + } + + def apply(title: String): Dat.GUI = { + val gui = Dat.GUIVR.create(title) + gui.position.set(-0.8, 1.4, -2) + //gui.rotateY(3.14/4 * 1.1) + gui + } + def apply(): Dat.GUI = { val gui = Dat.GUIVR.create("Plot Details") gui.position.set(-0.8, 1.4, -2) diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 3f7ba15..61dcdea 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - renderer.vr.enabled = true + //renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 2fbce5909029e1a4484ceac6b9a44eaa22153895 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 1 Nov 2018 15:56:14 -0600 Subject: [PATCH 05/28] Working on Initial Menu --- src/main/scala/vrdv/model/Plotter.scala | 4 +- src/main/scala/vrdv/obj3D/DatGuiW.scala | 61 +++++++++++++++++++++ src/main/scala/vrdv/obj3D/InitialMenu.scala | 15 +++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 src/main/scala/vrdv/obj3D/DatGuiW.scala create mode 100644 src/main/scala/vrdv/obj3D/InitialMenu.scala diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index bffdb64..dae7018 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -6,7 +6,7 @@ import util.Log import vrdv.input.{Action, InputDetails, Interactions} import vrdv.obj3D.displays.{CSC_DefaultConfig, ColumnSelectionConsole} import vrdv.obj3D.plots._ -import vrdv.obj3D.{CustomColors, DatGui, Region} +import vrdv.obj3D.{CustomColors, DatGui, DatGuiW, InitialMenu, Region} /** * Created by Dorian Thiessen on 2018-07-29. @@ -14,7 +14,7 @@ import vrdv.obj3D.{CustomColors, DatGui, Region} class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { //Instantiating the Initial Menu - scene.add(DatGui.initialMenu.object3D) + scene.add(new InitialMenu().object3D) private var DATA: Array[Array[Data]] = Array() private var REGIONS: Array[Region] = Array() diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala new file mode 100644 index 0000000..e54216b --- /dev/null +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -0,0 +1,61 @@ +package vrdv.obj3D + +import facade.Dat +import facade.Dat.{GuiButton, GuiSlider} +import util.Log +import vrdv.input.InputDetails +import vrdv.model.Plotter +import vrdv.obj3D.DatGuiW.WButton +import vrdv.obj3D.plots._ + +import scala.scalajs.js + +/** + * Created by Dorian Thiessen on 2018-05-10. + * Modified by Wade MCDonald 2018-11-01 + */ +class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { + val object3D: Dat.GUI = DatGuiW(title, xInit, yInit, zInit) + + var folders: Array[Dat.GUI] = Array() + + def addFolder(folder: Dat.GUI): Unit = { + object3D.addFolder(folder) + folders = folders :+ folder + } + + def addButton(function: () => Unit, name: String, description: String): Unit = { + val idx = object3D.children(0).children.length + object3D.addButton(function) + WButton(idx, object3D).setLabels(name, description) + } +} + +object DatGuiW { + + def apply(title: String, xInit: Double, yInit: Double, zInit: Double): Dat.GUI = { + val gui = Dat.GUIVR.create(title) + gui.position.set(xInit, yInit, zInit) + //gui.rotateY(3.14/4 * 1.1) + gui + } + + object WButton { + case class WButton(instance: GuiButton) { + + def setLabel_Description(str: String): Unit = instance.name(str) + + def setLabel_Button(str: String): Unit = instance + .children(0).children(1).children(0).children(0) + .asInstanceOf[js.Dynamic].updateLabel(str) + + def setLabels(onButton: String, onDesc: String): Unit = { + setLabel_Button(onButton) + setLabel_Description(onDesc) + } + } + + // Assumes button is not nested in a sub-folder + def apply(i: Int, folder: Dat.GUI): WButton = WButton(folder.children(0).children(i).asInstanceOf[GuiButton]) + } +} diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala new file mode 100644 index 0000000..905bac3 --- /dev/null +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -0,0 +1,15 @@ +package vrdv.obj3D + +import util.Log + + +/** + * Created by Wade McDonald 2018-11-01 + */ +class InitialMenu() + extends DatGuiW("Welcome", 0, 2, -3) { + + addButton((() => { Log.show("Graph 1 button clicked!") }), "Create", "Graph 1") + addButton((() => { Log.show("Graph 2 button clicked!") }), "Create", "Graph 2") + addButton((() => { Log.show("Graph 3 button clicked!") }), "Create", "Graph 3") +} \ No newline at end of file From 7c927f57b5d999dffd33487ca7ca23fd9473ca6e Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 2 Nov 2018 14:12:26 -0600 Subject: [PATCH 06/28] Initial Menu Spawns Graphs, Added some test listeners for Oculus Controller --- .../vrdv/input/oculus/OculusController.scala | 10 ++- .../scala/vrdv/input/oculus/package.scala | 3 + src/main/scala/vrdv/model/Plotter.scala | 56 ++++++++++++++++- src/main/scala/vrdv/obj3D/DatGui.scala | 62 +------------------ src/main/scala/vrdv/obj3D/DatGuiW.scala | 4 ++ src/main/scala/vrdv/obj3D/InitialMenu.scala | 11 ++-- src/main/scala/vrdv/package.scala | 3 +- 7 files changed, 77 insertions(+), 72 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index f9f79cf..7c24a69 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -202,15 +202,19 @@ abstract class OculusController(vrc: VRController) extends input.Device { Log("Grip Press Ended") }) + */ + setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { - Log("Thumbrest Touch Began") + Log("Thumbrest Touch Began - event: " + event.`type`) }) setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { - Log("Thumbrest Touch Ended") + Log("Thumbrest Touch Ended - event: " + event.`type`) }) - */ + setEventListener(Input.Home_PressEnded, (event: Event) => { + Log("Home Button Pressed - event: " + event.`type`)//; Log(event) + }) } // end of initCommonEventListeners diff --git a/src/main/scala/vrdv/input/oculus/package.scala b/src/main/scala/vrdv/input/oculus/package.scala index 3a15545..17cbd17 100644 --- a/src/main/scala/vrdv/input/oculus/package.scala +++ b/src/main/scala/vrdv/input/oculus/package.scala @@ -24,6 +24,9 @@ package object oculus { val Axes_Changed: String = "thumbstick axes changed" val Disconnected: String = "vr controller disconnected" + val Home_PressBegan: String = "home press began" + val Home_PressEnded: String = "home press ended" + object Left { // Event ID's specific to the Left controller val X_PressBegan: String = "X press began" diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index dae7018..e48cc7c 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -10,12 +10,10 @@ import vrdv.obj3D.{CustomColors, DatGui, DatGuiW, InitialMenu, Region} /** * Created by Dorian Thiessen on 2018-07-29. + * Modified by Wade McDonald on 2018-10-02. */ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { - //Instantiating the Initial Menu - scene.add(new InitialMenu().object3D) - private var DATA: Array[Array[Data]] = Array() private var REGIONS: Array[Region] = Array() private var PLOT: Array[Plot] = Array() @@ -39,6 +37,58 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { // ------ Plot stuff + /*---- New 2018-11-02 ----*/ + + private val initialMenu = new InitialMenu(this) + + def setupData(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { + if (data.isEmpty) return + DATA = DATA :+ data + + if(data.length >= 3) { + //Instantiating the Initial Menu + scene.add(initialMenu.object3D) + + } else { + val i = data.length - 1 + val shadowManifold: ShadowManifold = ShadowManifold(data(i), Res.getLastLoadedTextureID, pointColor) + addPlot3DToRegion(shadowManifold) + plot2D(false) + } + } + + def newPlot3DWithData: Unit = { + val data = DATA(0) + val pointColor = CustomColors.BLUE_HUE_SHIFT + + if (PLOT.length < 3) { + Log.show(s"Data.length == ${data.length}") + + val scatterPlot: ScatterPlot = ScatterPlot(data, Res.getLastLoadedTextureID, pointColor) + + Log("[Regions] - Adding 3D plot to new region") + val i = regions.length + addRegion(Region(i)) + regions(i).addPlot(scatterPlot) + repositionRegions() + + + val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) + regions(i).gui = Some(gui) + regions(i).add(gui.object3D) + //gui.object3D.position.setX(gui.object3D.position.x - 0.8) + + //gui.object3D.rotateY(3.14 / 4) + + addPlot(scatterPlot) + addAxes(regions(i).maybeGetAxes().get) + addGUI(gui) + + } + } + + /*---- End New ----*/ + def plot2D3D(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { if (data.isEmpty) return DATA = DATA :+ data diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index 6f5e3ef..6085908 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -2,7 +2,6 @@ package vrdv.obj3D import facade.Dat import facade.Dat.{GuiButton, GuiSlider} -import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter import vrdv.obj3D.plots._ @@ -24,11 +23,6 @@ class DatGui { // 0: HPD Folder, 1: SPS Folder var folders: Array[Dat.GUI] = Array() - var samples: js.Object = js.Dynamic.literal( - "someBoolean" → false, - "someValue" → "a" - ) - def addFolder(folder: Dat.GUI): Unit = { object3D.addFolder(folder) folders = folders :+ folder @@ -85,43 +79,7 @@ class DatGui { object DatGui { - def initialMenu: DatGui = { - val gui = new DatGui() - - gui.object3D.position.set(0, 2, -3) - - gui.object3D.addButton(() => { - Log.show("Graph 1 button clicked!") - }) - Button(0, gui.object3D).setLabels("Create", "Graph 1") - - gui.object3D.addButton((() => { - Log.show("Graph 2 button clicked!") - })) - Button(1, gui.object3D).setLabels("Create", "Graph 2") - - gui.object3D.addButton(() => { - Log.show("Graph 3 button clicked!") - }) - Button(2, gui.object3D).setLabels("Create", "Graph 3") - - gui - } - - def sample: DatGui = { - val gui = new DatGui() - // # Checkbox sample - gui.object3D.add(gui.samples, "someBoolean") - - // # Drop-down sample - // NOTE: Position of selected value is lower than it should be. - val dropDownOptions = js.Array("a", "b", "c") - gui.object3D.add(gui.samples, "someValue", dropDownOptions) - - gui - } - - def plotDetailsMenu(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { + def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { val gui = new DatGui() createHighlightedPointDataFolder(gui, plot) createSelectedPointsDataFolder(gui, plot, mc) @@ -157,24 +115,6 @@ object DatGui { Button(3, embeddingFolder).setLabels("Embed!", "Embed xVar") gui.object3D.addFolder(embeddingFolder) - val testFolder = Dat.GUIVR.create("Testing") - testFolder.addButton(() => { - Log.show("Test button clicked!") - }) - Button(0, testFolder).setLabels("TestButton!", "Test button.") - gui.object3D.addFolder(testFolder) - - gui - } - - def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { - plotDetailsMenu(plot, axes, mc) - } - - def apply(title: String): Dat.GUI = { - val gui = Dat.GUIVR.create(title) - gui.position.set(-0.8, 1.4, -2) - //gui.rotateY(3.14/4 * 1.1) gui } diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala index e54216b..ed1d3f8 100644 --- a/src/main/scala/vrdv/obj3D/DatGuiW.scala +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -29,6 +29,10 @@ class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { object3D.addButton(function) WButton(idx, object3D).setLabels(name, description) } + + def setVisible(vis: Boolean): Unit = { + object3D.visible = vis + } } object DatGuiW { diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index 905bac3..3f55e15 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -1,15 +1,18 @@ package vrdv.obj3D import util.Log +import vrdv.model.Plotter /** * Created by Wade McDonald 2018-11-01 */ -class InitialMenu() +class InitialMenu(plotter: Plotter) extends DatGuiW("Welcome", 0, 2, -3) { - addButton((() => { Log.show("Graph 1 button clicked!") }), "Create", "Graph 1") - addButton((() => { Log.show("Graph 2 button clicked!") }), "Create", "Graph 2") - addButton((() => { Log.show("Graph 3 button clicked!") }), "Create", "Graph 3") + override def setVisible(vis: Boolean): Unit = super.setVisible(vis) + + addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 1") + addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 2") + addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 3") } \ No newline at end of file diff --git a/src/main/scala/vrdv/package.scala b/src/main/scala/vrdv/package.scala index 9b824b0..342e136 100644 --- a/src/main/scala/vrdv/package.scala +++ b/src/main/scala/vrdv/package.scala @@ -63,7 +63,8 @@ package object vrdv { if(maybeModelManager.isEmpty) return val modelManager = maybeModelManager.get if(data.isEmpty) Log.show(" Empty data on plot request") - else modelManager.plotter.plot2D3D(FileAsText(data).collect(), CustomColors.BLUE_HUE_SHIFT) + //else modelManager.plotter.plot2D3D(FileAsText(data).collect(), CustomColors.BLUE_HUE_SHIFT) + else modelManager.plotter.setupData(FileAsText(data).collect(), CustomColors.BLUE_HUE_SHIFT) } /** From 1c1074c5306b041a49ebf40195e7f62ab7a60f12 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 2 Nov 2018 15:03:42 -0600 Subject: [PATCH 07/28] Tweaking GUI position with multiple graphs --- src/main/scala/vrdv/model/Plotter.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index e48cc7c..8df05b5 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -75,11 +75,15 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) regions(i).gui = Some(gui) - regions(i).add(gui.object3D) - //gui.object3D.position.setX(gui.object3D.position.x - 0.8) + //regions(i).add(gui.object3D) + scene.add(gui.object3D) + gui.object3D.position.setX(regions(i).object3D.position.x) + gui.object3D.position.setY(regions(i).object3D.position.y + 1.0) + gui.object3D.position.setZ(regions(i).object3D.position.z) //gui.object3D.rotateY(3.14 / 4) + addPlot(scatterPlot) addAxes(regions(i).maybeGetAxes().get) addGUI(gui) From a54965e9f99c1dbae183e13c6246fe6bb2515651 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 2 Nov 2018 20:16:41 -0600 Subject: [PATCH 08/28] Button Event Handlers Working --- .../vrdv/input/oculus/OculusController.scala | 12 +++---- .../input/oculus/OculusControllerLeft.scala | 35 +++++++++++++++---- .../input/oculus/OculusControllerRight.scala | 27 ++++++++++---- .../scala/vrdv/input/oculus/package.scala | 13 +++++-- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index 7c24a69..e9a2c6c 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -202,18 +202,18 @@ abstract class OculusController(vrc: VRController) extends input.Device { Log("Grip Press Ended") }) - */ - setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { - Log("Thumbrest Touch Began - event: " + event.`type`) + Log.show("Thumbrest Touch Began - event: " + event.`type`) }) setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { - Log("Thumbrest Touch Ended - event: " + event.`type`) + Log.show("Thumbrest Touch Ended - event: " + event.`type`) }) - setEventListener(Input.Home_PressEnded, (event: Event) => { - Log("Home Button Pressed - event: " + event.`type`)//; Log(event) + */ + + setEventListener("", (event: Event) => { + Log.show("Event: " + event.`type`) }) } // end of initCommonEventListeners diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala index f9c7e4e..d4ca525 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala @@ -2,6 +2,7 @@ package vrdv.input.oculus import facade.Dat import facade.IFThree.VRController +import org.scalajs.dom.raw.Event import util.Log import vrdv.model.PlotterModelManager @@ -35,25 +36,47 @@ class OculusControllerLeft(vrc: VRController, val mc: PlotterModelManager) exten // Setup events unique for this controller - /* -- Unused inputs + // -- Unused inputs setEventListener(Input.Left.X_PressBegan, (event: Event) => { - Log("X Press Began") + Log.show("X Press Began") }) setEventListener(Input.Left.X_PressEnded, (event: Event) => { - Log("X Press Ended") + Log.show("X Press Ended") }) setEventListener(Input.Left.Y_PressBegan, (event: Event) => { - Log("Y Press Began") + Log.show("Y Press Began") }) setEventListener(Input.Left.Y_PressEnded, (event: Event) => { - Log("Y Press Ended") + Log.show("Y Press Ended") }) - */ + setEventListener(Input.Left.Menu_PressBegan, (event: Event) => { + Log.show("Home Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Left.Menu_PressEnded, (event: Event) => { + Log.show("Home Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Left.Thumbstick_PressBegan, (event: Event) => { + Log.show("Left Thumbstick Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Left.Thumbstick_PressEnded, (event: Event) => { + Log.show("Left Thumbstick Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Left.ThumbRest_TouchBegan, (event: Event) => { + Log.show("Left Thumbrest Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Left.ThumbRest_TouchEnded, (event: Event) => { + Log.show("Left Thumbrest Touch Ended - event: " + event.`type`) + }) } diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala index 6a91247..21d635b 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala @@ -2,6 +2,7 @@ package vrdv.input.oculus import facade.Dat import facade.IFThree.VRController +import org.scalajs.dom.raw.Event import util.Log import vrdv.model.PlotterModelManager @@ -34,25 +35,39 @@ class OculusControllerRight(vrc: VRController, val mc: PlotterModelManager) exte // Setup events unique for this controller - /* -- Unused inputs + // -- Unused inputs setEventListener(Input.Right.A_PressBegan, (event: Event) => { - Log("A Press Began") + Log.show("A Press Began") }) setEventListener(Input.Right.A_PressEnded, (event: Event) => { - Log("A Press Ended") + Log.show("A Press Ended") }) setEventListener(Input.Right.B_PressBegan, (event: Event) => { - Log("B Press Began") + Log.show("B Press Began") }) setEventListener(Input.Right.B_PressEnded, (event: Event) => { - Log("B Press Ended") + Log.show("B Press Ended") }) - */ + setEventListener(Input.Right.Thumbstick_PressBegan, (event: Event) => { + Log.show("Right Thumbstick Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Right.Thumbstick_PressEnded, (event: Event) => { + Log.show("Right Thumbstick Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Right.ThumbRest_TouchBegan, (event: Event) => { + Log.show("Right Thumbrest Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Right.ThumbRest_TouchEnded, (event: Event) => { + Log.show("Right Thumbrest Touch Ended - event: " + event.`type`) + }) } diff --git a/src/main/scala/vrdv/input/oculus/package.scala b/src/main/scala/vrdv/input/oculus/package.scala index 17cbd17..78c2c71 100644 --- a/src/main/scala/vrdv/input/oculus/package.scala +++ b/src/main/scala/vrdv/input/oculus/package.scala @@ -24,15 +24,18 @@ package object oculus { val Axes_Changed: String = "thumbstick axes changed" val Disconnected: String = "vr controller disconnected" - val Home_PressBegan: String = "home press began" - val Home_PressEnded: String = "home press ended" - object Left { // Event ID's specific to the Left controller val X_PressBegan: String = "X press began" val X_PressEnded: String = "X press ended" val Y_PressBegan: String = "Y press began" val Y_PressEnded: String = "Y press ended" + val Thumbstick_PressBegan: String = "thumbstick press began" + val Thumbstick_PressEnded: String = "thumbstick press ended" + val ThumbRest_TouchBegan: String = "thumbrest touch began" + val ThumbRest_TouchEnded: String = "thumbrest touch ended" + val Menu_PressBegan: String = "menu press began" + val Menu_PressEnded: String = "menu press ended" } object Right { @@ -41,6 +44,10 @@ package object oculus { val A_PressEnded: String = "A press ended" val B_PressBegan: String = "B press began" val B_PressEnded: String = "B press ended" + val Thumbstick_PressBegan: String = "thumbstick press began" + val Thumbstick_PressEnded: String = "thumbstick press ended" + val ThumbRest_TouchBegan: String = "thumbrest touch began" + val ThumbRest_TouchEnded: String = "thumbrest touch ended" } // These touch events for Oculus Controls are not registering. (Firefox 61.0.1) diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 61dcdea..3f7ba15 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - //renderer.vr.enabled = true + renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 2c6a980c1e552fa45d5a9f52b694cd3d9393cca9 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 2 Nov 2018 21:02:14 -0600 Subject: [PATCH 09/28] More touch event handlers --- .../vrdv/input/oculus/OculusController.scala | 4 ---- .../input/oculus/OculusControllerLeft.scala | 24 +++++++++++++++++++ .../input/oculus/OculusControllerRight.scala | 24 +++++++++++++++++++ .../scala/vrdv/input/oculus/package.scala | 12 ++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index e9a2c6c..613d827 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -212,10 +212,6 @@ abstract class OculusController(vrc: VRController) extends input.Device { */ - setEventListener("", (event: Event) => { - Log.show("Event: " + event.`type`) - }) - } // end of initCommonEventListeners } diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala index d4ca525..d870e9e 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala @@ -70,6 +70,14 @@ class OculusControllerLeft(vrc: VRController, val mc: PlotterModelManager) exten Log.show("Left Thumbstick Button Pressed - event: " + event.`type`) }) + setEventListener(Input.Left.Thumbstick_TouchBegan, (event: Event) => { + Log.show("Left Thumbstick Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Left.Thumbstick_TouchEnded, (event: Event) => { + Log.show("Left Thumbstick Touch Ended - event: " + event.`type`) + }) + setEventListener(Input.Left.ThumbRest_TouchBegan, (event: Event) => { Log.show("Left Thumbrest Touch Began - event: " + event.`type`) }) @@ -78,6 +86,22 @@ class OculusControllerLeft(vrc: VRController, val mc: PlotterModelManager) exten Log.show("Left Thumbrest Touch Ended - event: " + event.`type`) }) + setEventListener(Input.Left.X_TouchBegan, (event: Event) => { + Log.show("X Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Left.X_TouchEnded, (event: Event) => { + Log.show("X Touch Ended - event: " + event.`type`) + }) + + setEventListener(Input.Left.Y_TouchBegan, (event: Event) => { + Log.show("Y Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Left.Y_TouchEnded, (event: Event) => { + Log.show("Y Touch Ended - event: " + event.`type`) + }) + } def update(): Unit = vrc.update() diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala index 21d635b..0532e28 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala @@ -65,10 +65,34 @@ class OculusControllerRight(vrc: VRController, val mc: PlotterModelManager) exte Log.show("Right Thumbrest Touch Began - event: " + event.`type`) }) + setEventListener(Input.Right.Thumbstick_PressBegan, (event: Event) => { + Log.show("Right Thumbstick Button Pressed - event: " + event.`type`) + }) + + setEventListener(Input.Right.Thumbstick_PressEnded, (event: Event) => { + Log.show("Right Thumbstick Button Pressed - event: " + event.`type`) + }) + setEventListener(Input.Right.ThumbRest_TouchEnded, (event: Event) => { Log.show("Right Thumbrest Touch Ended - event: " + event.`type`) }) + setEventListener(Input.Right.A_TouchBegan, (event: Event) => { + Log.show("A Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Right.A_TouchEnded, (event: Event) => { + Log.show("A Touch Ended - event: " + event.`type`) + }) + + setEventListener(Input.Right.B_TouchBegan, (event: Event) => { + Log.show("B Touch Began - event: " + event.`type`) + }) + + setEventListener(Input.Right.B_TouchEnded, (event: Event) => { + Log.show("B Touch Ended - event: " + event.`type`) + }) + } def update(): Unit = vrc.update() diff --git a/src/main/scala/vrdv/input/oculus/package.scala b/src/main/scala/vrdv/input/oculus/package.scala index 78c2c71..28c557c 100644 --- a/src/main/scala/vrdv/input/oculus/package.scala +++ b/src/main/scala/vrdv/input/oculus/package.scala @@ -30,8 +30,14 @@ package object oculus { val X_PressEnded: String = "X press ended" val Y_PressBegan: String = "Y press began" val Y_PressEnded: String = "Y press ended" + val X_TouchBegan: String = "X touch began" + val X_TouchEnded: String = "X touch ended" + val Y_TouchBegan: String = "Y touch began" + val Y_TouchEnded: String = "Y touch ended" val Thumbstick_PressBegan: String = "thumbstick press began" val Thumbstick_PressEnded: String = "thumbstick press ended" + val Thumbstick_TouchBegan: String = "thumbstick touch began" + val Thumbstick_TouchEnded: String = "thumbstick touch ended" val ThumbRest_TouchBegan: String = "thumbrest touch began" val ThumbRest_TouchEnded: String = "thumbrest touch ended" val Menu_PressBegan: String = "menu press began" @@ -44,8 +50,14 @@ package object oculus { val A_PressEnded: String = "A press ended" val B_PressBegan: String = "B press began" val B_PressEnded: String = "B press ended" + val A_TouchBegan: String = "A touch began" + val A_TouchEnded: String = "A touch ended" + val B_TouchBegan: String = "B touch began" + val B_TouchEnded: String = "B touch ended" val Thumbstick_PressBegan: String = "thumbstick press began" val Thumbstick_PressEnded: String = "thumbstick press ended" + val Thumbstick_TouchBegan: String = "thumbstick touch began" + val Thumbstick_TouchEnded: String = "thumbstick touch ended" val ThumbRest_TouchBegan: String = "thumbrest touch began" val ThumbRest_TouchEnded: String = "thumbrest touch ended" } From 4eab720ba6d2c7808c8525af98a38e38e6191df8 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Sat, 3 Nov 2018 13:45:59 -0600 Subject: [PATCH 10/28] Added events to controls for toggle ray, clear selection, toggle GUIs. --- .../vrdv/input/oculus/OculusController.scala | 21 ++++++++++--------- .../input/oculus/OculusControllerLeft.scala | 20 ++++++++++-------- .../input/oculus/OculusControllerRight.scala | 20 ++++++++++-------- src/main/scala/vrdv/model/Plotter.scala | 5 +++++ src/main/scala/vrdv/obj3D/DatGui.scala | 2 +- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index 613d827..d486901 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -109,11 +109,12 @@ abstract class OculusController(vrc: VRController) extends input.Device { setEventListener(Input.Primary_ValueChanged, (event: Event) => { Log("Primary Value Changed")//; Log(event) val value = primaryValue(event.target) + if(value > 0.05) { - inputDetails.arrow.visible = true + //inputDetails.arrow.visible = true inputDevice.pressed(true) } else { - inputDetails.arrow.visible = false + //inputDetails.arrow.visible = false inputDevice.pressed(false) } @@ -156,6 +157,14 @@ abstract class OculusController(vrc: VRController) extends input.Device { } }) + setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { + inputDetails.arrow.visible = true + }) + + setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { + inputDetails.arrow.visible = false + }) + setAxesEventListener(Input.Axes_Changed, (event: AxesChangedEvent) => { Log("Axes Changed!") if(captured.nonEmpty) { @@ -202,14 +211,6 @@ abstract class OculusController(vrc: VRController) extends input.Device { Log("Grip Press Ended") }) - setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { - Log.show("Thumbrest Touch Began - event: " + event.`type`) - }) - - setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { - Log.show("Thumbrest Touch Ended - event: " + event.`type`) - }) - */ } // end of initCommonEventListeners diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala index d870e9e..42c1a57 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerLeft.scala @@ -36,22 +36,22 @@ class OculusControllerLeft(vrc: VRController, val mc: PlotterModelManager) exten // Setup events unique for this controller - // -- Unused inputs - - setEventListener(Input.Left.X_PressBegan, (event: Event) => { - Log.show("X Press Began") + setEventListener(Input.Left.Y_PressEnded, (event: Event) => { + mc.plotter.clearSelections() }) setEventListener(Input.Left.X_PressEnded, (event: Event) => { - Log.show("X Press Ended") + mc.plotter.toggleGuiVisibility }) - setEventListener(Input.Left.Y_PressBegan, (event: Event) => { - Log.show("Y Press Began") + /* -- Unused inputs + + setEventListener(Input.Left.X_PressBegan, (event: Event) => { + Log.show("X Press Began") }) - setEventListener(Input.Left.Y_PressEnded, (event: Event) => { - Log.show("Y Press Ended") + setEventListener(Input.Left.Y_PressBegan, (event: Event) => { + Log.show("Y Press Began") }) setEventListener(Input.Left.Menu_PressBegan, (event: Event) => { @@ -102,6 +102,8 @@ class OculusControllerLeft(vrc: VRController, val mc: PlotterModelManager) exten Log.show("Y Touch Ended - event: " + event.`type`) }) + */ + } def update(): Unit = vrc.update() diff --git a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala index 0532e28..1719ad2 100644 --- a/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala +++ b/src/main/scala/vrdv/input/oculus/OculusControllerRight.scala @@ -35,22 +35,22 @@ class OculusControllerRight(vrc: VRController, val mc: PlotterModelManager) exte // Setup events unique for this controller - // -- Unused inputs - - setEventListener(Input.Right.A_PressBegan, (event: Event) => { - Log.show("A Press Began") + setEventListener(Input.Right.B_PressEnded, (event: Event) => { + mc.plotter.clearSelections() }) setEventListener(Input.Right.A_PressEnded, (event: Event) => { - Log.show("A Press Ended") + mc.plotter.toggleGuiVisibility }) - setEventListener(Input.Right.B_PressBegan, (event: Event) => { - Log.show("B Press Began") + /* -- Unused inputs + + setEventListener(Input.Right.A_PressBegan, (event: Event) => { + Log.show("A Press Began") }) - setEventListener(Input.Right.B_PressEnded, (event: Event) => { - Log.show("B Press Ended") + setEventListener(Input.Right.B_PressBegan, (event: Event) => { + Log.show("B Press Began") }) setEventListener(Input.Right.Thumbstick_PressBegan, (event: Event) => { @@ -93,6 +93,8 @@ class OculusControllerRight(vrc: VRController, val mc: PlotterModelManager) exte Log.show("B Touch Ended - event: " + event.`type`) }) + */ + } def update(): Unit = vrc.update() diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index 8df05b5..ba6137a 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -41,6 +41,10 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { private val initialMenu = new InitialMenu(this) + def toggleGuiVisibility: Unit = { + Log.show("Toggle GUI visibility.") + } + def setupData(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { if (data.isEmpty) return DATA = DATA :+ data @@ -389,6 +393,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { val plot = r.plot.get for(p <- plot.selectedPointIndices) PointOperations.deselect(plot, p) plot.selectedPointIndices = plot.selectedPointIndices.empty + PointOperations.updateSelectedSummary(plot) } } } diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index 6085908..f8ea39e 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -151,7 +151,7 @@ object DatGui { // A button for clearing set of selected points selectFolder.addButton(() => { plotter.clearSelections() - PointOperations.updateSelectedSummary(plot) + //PointOperations.updateSelectedSummary(plot) }) Button(3, selectFolder).setLabels("Clear", "Clear Selections") // 3 used b/c rows added above take up indices 0-2 From 85e3c6ea2af7f4c0ef92ba4e55339acae66ef499 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Sat, 3 Nov 2018 21:16:33 -0600 Subject: [PATCH 11/28] Tinkering with thumbrest for ray. --- .../vrdv/input/oculus/OculusController.scala | 4 ++++ src/main/scala/vrdv/input/oculus/package.scala | 15 +++++++++------ .../scala/vrdv/model/PlotterModelManager.scala | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index d486901..704c810 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -159,6 +159,10 @@ abstract class OculusController(vrc: VRController) extends input.Device { setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { inputDetails.arrow.visible = true + inputParser.passInput(new Point(Some(vrc), myCID) { + rc = inputDetails + persist = isTouched(event.target) + }) }) setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { diff --git a/src/main/scala/vrdv/input/oculus/package.scala b/src/main/scala/vrdv/input/oculus/package.scala index 28c557c..1866753 100644 --- a/src/main/scala/vrdv/input/oculus/package.scala +++ b/src/main/scala/vrdv/input/oculus/package.scala @@ -38,10 +38,10 @@ package object oculus { val Thumbstick_PressEnded: String = "thumbstick press ended" val Thumbstick_TouchBegan: String = "thumbstick touch began" val Thumbstick_TouchEnded: String = "thumbstick touch ended" - val ThumbRest_TouchBegan: String = "thumbrest touch began" - val ThumbRest_TouchEnded: String = "thumbrest touch ended" - val Menu_PressBegan: String = "menu press began" - val Menu_PressEnded: String = "menu press ended" + //val ThumbRest_TouchBegan: String = "thumbrest touch began" + //val ThumbRest_TouchEnded: String = "thumbrest touch ended" + //val Menu_PressBegan: String = "menu press began" + //val Menu_PressEnded: String = "menu press ended" } object Right { @@ -58,8 +58,8 @@ package object oculus { val Thumbstick_PressEnded: String = "thumbstick press ended" val Thumbstick_TouchBegan: String = "thumbstick touch began" val Thumbstick_TouchEnded: String = "thumbstick touch ended" - val ThumbRest_TouchBegan: String = "thumbrest touch began" - val ThumbRest_TouchEnded: String = "thumbrest touch ended" + //val ThumbRest_TouchBegan: String = "thumbrest touch began" + //val ThumbRest_TouchEnded: String = "thumbrest touch ended" } // These touch events for Oculus Controls are not registering. (Firefox 61.0.1) @@ -72,4 +72,7 @@ package object oculus { def primaryValue(target: Any): Double = target .asInstanceOf[js.Dynamic].getButton(1).value.asInstanceOf[Double] + def isTouched(target: Any): Boolean = target + .asInstanceOf[js.Dynamic].getButton(1).isTouched.asInstanceOf[Boolean] + } diff --git a/src/main/scala/vrdv/model/PlotterModelManager.scala b/src/main/scala/vrdv/model/PlotterModelManager.scala index c71ce76..fb84fb7 100644 --- a/src/main/scala/vrdv/model/PlotterModelManager.scala +++ b/src/main/scala/vrdv/model/PlotterModelManager.scala @@ -65,6 +65,7 @@ class PlotterModelManager extends ModelManager[Action, Result] with Room { case p: input.Point => // ============== lastPoint(p.cid) = p lastPress(p.cid).persist = false + //Possibly remove persist here to get it to work on thumbrest? if(p.persist) { if(p.source.nonEmpty) plotter.hoverAction(p.rc.updateRaycaster(p.source.get), select = false) else { From 862294b97c5ebb2a6b6b3c92b4cdc8b1c255169e Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Tue, 6 Nov 2018 14:54:19 -0600 Subject: [PATCH 12/28] Change to eventlisteners for thumbrest --- .../scala/vrdv/input/oculus/OculusController.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index d486901..65ad160 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -159,10 +159,20 @@ abstract class OculusController(vrc: VRController) extends input.Device { setEventListener(Input.ThumbRest_TouchBegan, (event: Event) => { inputDetails.arrow.visible = true + inputParser.passInput(new Point(Some(vrc), myCID) { + rc = inputDetails + magnitude = 1.0 + persist = true + }) }) setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { inputDetails.arrow.visible = false + inputParser.passInput(new Point(Some(vrc), myCID) { + rc = inputDetails + magnitude = 0.0 + persist = false + }) }) setAxesEventListener(Input.Axes_Changed, (event: AxesChangedEvent) => { From 358d7f6b4eb72f9cbebbe10e28e95830e013fb39 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Wed, 7 Nov 2018 15:44:08 -0600 Subject: [PATCH 13/28] Binding checkbox to variable --- src/main/scala/facade/Dat.scala | 10 ++++++- src/main/scala/vrdv/obj3D/DatGui.scala | 28 ++++++++++++++++++- src/main/scala/vrdv/obj3D/DatGuiW.scala | 30 +++++++++++++++++++++ src/main/scala/vrdv/obj3D/InitialMenu.scala | 18 ++++++++++++- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 5 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index 4efb75d..27d3936 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -25,12 +25,14 @@ object Dat { @js.native trait GUI extends Object3D { def add(something: js.Object): Unit = js.native - def add(something: js.Object, id: String): Unit = js.native + def add(something: js.Object, id: String): GuiComponent = js.native def add(something: js.Object, id: String, options: js.Array[String]): Unit = js.native // For drop-downs def add(something: js.Object, id: String, min: Double, max: Double): GuiSlider = js.native def addFolder(folder: GUI): GUI = js.native + def addCheckbox(something: js.Object, id: String): Unit = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native def addButton(id: String, fn: js.Function): Unit = js.native + def addDropdown(something: js.Object, id: String, options: js.Array[String]): Unit = js.native def open(): Unit = js.native def close(): Unit = js.native def removeFolder(gui: GUI): Unit = js.native @@ -46,9 +48,15 @@ object Dat { def updateObject(obj: js.Any): Unit = js.native } + @js.native + trait GuiCheckbox extends GuiComponent {} + @js.native trait GuiButton extends GuiComponent {} + @js.native + trait GuiDropdown extends GuiComponent {} + @js.native trait GuiComponent extends Object3D { def name(name: String): GuiSlider = js.native diff --git a/src/main/scala/vrdv/obj3D/DatGui.scala b/src/main/scala/vrdv/obj3D/DatGui.scala index f8ea39e..187c8a6 100644 --- a/src/main/scala/vrdv/obj3D/DatGui.scala +++ b/src/main/scala/vrdv/obj3D/DatGui.scala @@ -2,6 +2,7 @@ package vrdv.obj3D import facade.Dat import facade.Dat.{GuiButton, GuiSlider} +import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter import vrdv.obj3D.plots._ @@ -23,6 +24,11 @@ class DatGui { // 0: HPD Folder, 1: SPS Folder var folders: Array[Dat.GUI] = Array() + var samples: js.Object = js.Dynamic.literal( + "someBoolean" → false, + "someValue" → "a" + ) + def addFolder(folder: Dat.GUI): Unit = { object3D.addFolder(folder) folders = folders :+ folder @@ -79,6 +85,19 @@ class DatGui { object DatGui { + def sample: DatGui = { + val gui = new DatGui() + // # Checkbox sample + gui.object3D.add(gui.samples, "someBoolean") + + // # Drop-down sample + // NOTE: Position of selected value is lower than it should be. + val dropDownOptions = js.Array("a", "b", "c") + gui.object3D.add(gui.samples, "someValue", dropDownOptions) + + gui + } + def apply(plot: Plot3D, axes: CoordinateAxes, mc: Plotter): DatGui = { val gui = new DatGui() createHighlightedPointDataFolder(gui, plot) @@ -115,6 +134,13 @@ object DatGui { Button(3, embeddingFolder).setLabels("Embed!", "Embed xVar") gui.object3D.addFolder(embeddingFolder) + val testFolder = Dat.GUIVR.create("Testing") + testFolder.addButton(() => { + Log.show("Test button clicked!") + }) + Button(0, testFolder).setLabels("TestButton!", "Test button.") + gui.object3D.addFolder(testFolder) + gui } @@ -151,7 +177,7 @@ object DatGui { // A button for clearing set of selected points selectFolder.addButton(() => { plotter.clearSelections() - //PointOperations.updateSelectedSummary(plot) + PointOperations.updateSelectedSummary(plot) }) Button(3, selectFolder).setLabels("Clear", "Clear Selections") // 3 used b/c rows added above take up indices 0-2 diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala index ed1d3f8..9f1ba12 100644 --- a/src/main/scala/vrdv/obj3D/DatGuiW.scala +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -30,11 +30,41 @@ class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { WButton(idx, object3D).setLabels(name, description) } + def addCheckbox(something: js.Object, id: String, description: String): Unit = { + //val idx = object3D.children(0).children.length + object3D.add(something, id).name(description) + } + + def addDropdown(something: js.Object, id: String, options: js.Array[String]): Unit = { + val idx = object3D.children(0).children.length + object3D.addDropdown(something, id, options) + //WButton(idx, object3D).setLabel_Description(id) + //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].updateLabel(id) + //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].name(id) + + object3D.children(0).children(idx).name = id + } + def setVisible(vis: Boolean): Unit = { object3D.visible = vis } } +/* + def sample: DatGui = { + val gui = new DatGui() + // # Checkbox sample + gui.object3D.add(gui.samples, "someBoolean") + + // # Drop-down sample + // NOTE: Position of selected value is lower than it should be. + val dropDownOptions = js.Array("a", "b", "c") + gui.object3D.add(gui.samples, "someValue", dropDownOptions) + + gui + } + */ + object DatGuiW { def apply(title: String, xInit: Double, yInit: Double, zInit: Double): Dat.GUI = { diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index 3f55e15..ba1b0f1 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -3,6 +3,8 @@ package vrdv.obj3D import util.Log import vrdv.model.Plotter +import scala.scalajs.js + /** * Created by Wade McDonald 2018-11-01 @@ -12,7 +14,21 @@ class InitialMenu(plotter: Plotter) override def setVisible(vis: Boolean): Unit = super.setVisible(vis) + var gob: js.Array[String] = js.Array("First", "Second", "Third") + var gobValues: js.Array[String] = js.Array("1", "2", "3") + var testBool = false + var testString = "Initial value for testString." + + val checkValue: js.Object = js.Dynamic.literal( + "Test" → false + ) + def getCheckValue: Boolean = { + checkValue.asInstanceOf[js.Dynamic].selectDynamic("Test").asInstanceOf[Boolean] + } + addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 1") addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 2") - addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 3") + addButton(() => { Log.show(getCheckValue + " " + testString) }, "Create", "Graph 3") + addCheckbox(this.checkValue, "Test", "Test Checkbox") + addDropdown(gob,"Test Dropdown", gobValues) } \ No newline at end of file diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 3f7ba15..61dcdea 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - renderer.vr.enabled = true + //renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 6fd3dc7a2db1c4a1d17dd142fdb2fb9b7a5d135e Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Wed, 7 Nov 2018 17:19:41 -0600 Subject: [PATCH 14/28] tinkering --- src/main/scala/facade/Dat.scala | 6 ++-- src/main/scala/vrdv/obj3D/DatGuiW.scala | 11 +++---- src/main/scala/vrdv/obj3D/InitialMenu.scala | 32 ++++++++++++++++----- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index 27d3936..e25e985 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -24,15 +24,15 @@ object Dat { } @js.native trait GUI extends Object3D { - def add(something: js.Object): Unit = js.native + def add(something: js.Object): GuiComponent = js.native def add(something: js.Object, id: String): GuiComponent = js.native - def add(something: js.Object, id: String, options: js.Array[String]): Unit = js.native // For drop-downs + def add(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native // For drop-downs def add(something: js.Object, id: String, min: Double, max: Double): GuiSlider = js.native def addFolder(folder: GUI): GUI = js.native def addCheckbox(something: js.Object, id: String): Unit = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native def addButton(id: String, fn: js.Function): Unit = js.native - def addDropdown(something: js.Object, id: String, options: js.Array[String]): Unit = js.native + def addDropdown(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native def open(): Unit = js.native def close(): Unit = js.native def removeFolder(gui: GUI): Unit = js.native diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala index 9f1ba12..a3c2df4 100644 --- a/src/main/scala/vrdv/obj3D/DatGuiW.scala +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -1,7 +1,8 @@ package vrdv.obj3D import facade.Dat -import facade.Dat.{GuiButton, GuiSlider} +//import facade.Dat.{GuiButton, GuiSlider} +import facade.Dat._ import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter @@ -35,14 +36,14 @@ class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { object3D.add(something, id).name(description) } - def addDropdown(something: js.Object, id: String, options: js.Array[String]): Unit = { - val idx = object3D.children(0).children.length - object3D.addDropdown(something, id, options) + def addDropdown(something: js.Object, id: String, options: js.Array[String], description: String): GuiComponent = { + //val idx = object3D.children(0).children.length + object3D.addDropdown(something, id, options)//.name(description) //WButton(idx, object3D).setLabel_Description(id) //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].updateLabel(id) //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].name(id) - object3D.children(0).children(idx).name = id + //object3D.children(0).children(idx).name = id } def setVisible(vis: Boolean): Unit = { diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index ba1b0f1..caa7425 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -1,5 +1,6 @@ package vrdv.obj3D +import facade.Dat.{GuiComponent, GuiDropdown} import util.Log import vrdv.model.Plotter @@ -14,21 +15,38 @@ class InitialMenu(plotter: Plotter) override def setVisible(vis: Boolean): Unit = super.setVisible(vis) - var gob: js.Array[String] = js.Array("First", "Second", "Third") - var gobValues: js.Array[String] = js.Array("1", "2", "3") + var dropDownOptions: js.Array[String] = js.Array("First", "Second", "Third") + var dropDownOptionsNum: js.Array[String] = js.Array("1", "2", "3") var testBool = false var testString = "Initial value for testString." val checkValue: js.Object = js.Dynamic.literal( - "Test" → false + "Test" → false, + "String" → "Default stringValue" ) - def getCheckValue: Boolean = { - checkValue.asInstanceOf[js.Dynamic].selectDynamic("Test").asInstanceOf[Boolean] + + val stringValue: js.Object = js.Dynamic.literal( + "String" → "First" + ) + + def getCheckValue(name: String): String = { + checkValue.asInstanceOf[js.Dynamic].selectDynamic(name).toString() + } + + def getStringValue(name: String): String = { + stringValue.asInstanceOf[js.Dynamic].selectDynamic(name).toString() + } + + var dropdown = addDropdown(stringValue,"String", dropDownOptions, "Test Dropdown") + + def getDropDownString: String = { + dropdown.asInstanceOf[GuiDropdown].valueOf().toString() } addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 1") addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 2") - addButton(() => { Log.show(getCheckValue + " " + testString) }, "Create", "Graph 3") + addButton(() => { Log.show(getCheckValue("Test") + " " + getDropDownString) }, + "Create", "Graph 3") addCheckbox(this.checkValue, "Test", "Test Checkbox") - addDropdown(gob,"Test Dropdown", gobValues) + } \ No newline at end of file From 71ed394863acf66c07608e1da4e5ceff80acb821 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 8 Nov 2018 13:06:58 -0600 Subject: [PATCH 15/28] Working on new SettingsGui --- src/main/scala/facade/Dat.scala | 2 +- src/main/scala/vrdv/model/Plotter.scala | 9 +-- src/main/scala/vrdv/obj3D/DatGuiW.scala | 12 +--- src/main/scala/vrdv/obj3D/InitialMenu.scala | 34 +--------- src/main/scala/vrdv/obj3D/SettingsGui.scala | 72 +++++++++++++++++++++ 5 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 src/main/scala/vrdv/obj3D/SettingsGui.scala diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index e25e985..768213c 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -32,7 +32,7 @@ object Dat { def addCheckbox(something: js.Object, id: String): Unit = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native def addButton(id: String, fn: js.Function): Unit = js.native - def addDropdown(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native + def addDropdown(something: js.Object, id: String, options: js.Object): GuiComponent = js.native def open(): Unit = js.native def close(): Unit = js.native def removeFolder(gui: GUI): Unit = js.native diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index ba6137a..c333faa 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -6,7 +6,7 @@ import util.Log import vrdv.input.{Action, InputDetails, Interactions} import vrdv.obj3D.displays.{CSC_DefaultConfig, ColumnSelectionConsole} import vrdv.obj3D.plots._ -import vrdv.obj3D.{CustomColors, DatGui, DatGuiW, InitialMenu, Region} +import vrdv.obj3D.{CustomColors, DatGui, DatGuiW, SettingsGui, InitialMenu, Region} /** * Created by Dorian Thiessen on 2018-07-29. @@ -77,8 +77,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { repositionRegions() - val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) - regions(i).gui = Some(gui) + //val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) + val gui = new SettingsGui(scatterPlot, regions(i).maybeGetAxes().get, this) + //regions(i).gui = Some(gui) //regions(i).add(gui.object3D) scene.add(gui.object3D) gui.object3D.position.setX(regions(i).object3D.position.x) @@ -90,7 +91,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { addPlot(scatterPlot) addAxes(regions(i).maybeGetAxes().get) - addGUI(gui) + //addGUI(gui) } } diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala index a3c2df4..928f687 100644 --- a/src/main/scala/vrdv/obj3D/DatGuiW.scala +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -32,18 +32,12 @@ class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { } def addCheckbox(something: js.Object, id: String, description: String): Unit = { - //val idx = object3D.children(0).children.length object3D.add(something, id).name(description) } - def addDropdown(something: js.Object, id: String, options: js.Array[String], description: String): GuiComponent = { - //val idx = object3D.children(0).children.length - object3D.addDropdown(something, id, options)//.name(description) - //WButton(idx, object3D).setLabel_Description(id) - //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].updateLabel(id) - //object3D.children(0).children(idx).asInstanceOf[js.Dynamic].name(id) - - //object3D.children(0).children(idx).name = id + def addDropdown(something: js.Object, id: String, options: js.Array[String]): GuiComponent = { + //object3D.addDropdown(something, id, options) + object3D.add(something, id, options) } def setVisible(vis: Boolean): Unit = { diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index caa7425..f69876f 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -15,38 +15,8 @@ class InitialMenu(plotter: Plotter) override def setVisible(vis: Boolean): Unit = super.setVisible(vis) - var dropDownOptions: js.Array[String] = js.Array("First", "Second", "Third") - var dropDownOptionsNum: js.Array[String] = js.Array("1", "2", "3") - var testBool = false - var testString = "Initial value for testString." - - val checkValue: js.Object = js.Dynamic.literal( - "Test" → false, - "String" → "Default stringValue" - ) - - val stringValue: js.Object = js.Dynamic.literal( - "String" → "First" - ) - - def getCheckValue(name: String): String = { - checkValue.asInstanceOf[js.Dynamic].selectDynamic(name).toString() - } - - def getStringValue(name: String): String = { - stringValue.asInstanceOf[js.Dynamic].selectDynamic(name).toString() - } - - var dropdown = addDropdown(stringValue,"String", dropDownOptions, "Test Dropdown") - - def getDropDownString: String = { - dropdown.asInstanceOf[GuiDropdown].valueOf().toString() - } - addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 1") - addButton(() => { plotter.newPlot3DWithData }, "Create", "Graph 2") - addButton(() => { Log.show(getCheckValue("Test") + " " + getDropDownString) }, - "Create", "Graph 3") - addCheckbox(this.checkValue, "Test", "Test Checkbox") + addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 2") + addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 3") } \ No newline at end of file diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala new file mode 100644 index 0000000..50aa128 --- /dev/null +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -0,0 +1,72 @@ +package vrdv.obj3D + +import facade.Dat +import vrdv.input.InputDetails +import vrdv.model.Plotter +import vrdv.obj3D.plots.{CoordinateAxes, Plot3D} + +import scala.scalajs.js + +class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) + extends DatGuiW("Graph Settings", axes.position.x - 2.0, axes.position.y + 2.0, axes.position.z){ + + override def setVisible(vis: Boolean): Unit = super.setVisible(vis) + + val rawTau: js.Object = js.Dynamic.literal( + "TauOnes" -> 0, + "TauTens" -> 0, + "TauHundreds" -> 0) + + val filterRange: js.Object = js.Dynamic.literal( + "Start" → 0, + "End" → 0 + ) + + val raycasterThresholds: js.Object = js.Dynamic.literal( + "Right" → 0.1, + "Left" → 0.1 + ) + + val plotType: js.Object = js.Dynamic.literal( + "Graph Type" → "3D Scatter" + ) + val plotTypeOptions = js.Array("3D Scatter", "2D Scatter", "Shadow Manifold") + + def getTau: Int = + rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauOnes").asInstanceOf[Int] + + rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauTens").asInstanceOf[Int] + + rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauHundreds").asInstanceOf[Int] + + def getRange: Range = { + val start = filterRange.asInstanceOf[js.Dynamic].selectDynamic("Start").asInstanceOf[Int] + val end = filterRange.asInstanceOf[js.Dynamic].selectDynamic("End").asInstanceOf[Int] + start to end + } + + def getLeftThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Left").asInstanceOf[Float] + def getRightThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Right").asInstanceOf[Float] + + addDropdown(plotType, "Graph Type", plotTypeOptions) + + //Raycaster Thresholds Folder + val rcThresholdFolder = new DatGuiW("Selection Sensitivity", 0, 0, 0) + rcThresholdFolder.object3D.add(raycasterThresholds, "Left", 0, 0.1).step(0.001).name("Left") + rcThresholdFolder.object3D.add(raycasterThresholds, "Right", 0, 0.1).step(0.001).name("Right") + rcThresholdFolder.addButton(() => InputDetails.updateThresholds(getLeftThreshold, getRightThreshold), + "Update!", "Apply Threshold") + object3D.addFolder(rcThresholdFolder.object3D) + rcThresholdFolder.object3D.open() + + // + + setDefaultPosition() + + def setDefaultPosition(): Unit = { + val xPosDefault = axes.position.x - 2.0 + val yPosDefault = axes.position.y + 2.0 + val zPosDefault = axes.position.z + + object3D.position.set(xPosDefault, yPosDefault, zPosDefault) + object3D.updateMatrix() + } +} From 4a3ee7592138acc239573780bd9f3a6d855356aa Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 8 Nov 2018 13:24:41 -0600 Subject: [PATCH 16/28] Tinkering with getting UI to reposition --- src/main/scala/vrdv/obj3D/SettingsGui.scala | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 50aa128..fb86be4 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -1,6 +1,7 @@ package vrdv.obj3D import facade.Dat +import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter import vrdv.obj3D.plots.{CoordinateAxes, Plot3D} @@ -62,11 +63,15 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) setDefaultPosition() def setDefaultPosition(): Unit = { - val xPosDefault = axes.position.x - 2.0 - val yPosDefault = axes.position.y + 2.0 - val zPosDefault = axes.position.z + val xPosDefault: Double = axes.position.x - 2.0 + val yPosDefault: Double = axes.position.y + 2.0 + val zPosDefault: Double = axes.position.z - object3D.position.set(xPosDefault, yPosDefault, zPosDefault) - object3D.updateMatrix() + Log.show("Setting GUI position to: (" + xPosDefault + ", " + yPosDefault + ", " + zPosDefault + ")") + + //object3D.position.set(xPosDefault, yPosDefault, zPosDefault) + object3D.position.x = xPosDefault + object3D.position.y = yPosDefault + object3D.position.z = zPosDefault } } From 34f7f6a15e983197350a49c9115d08205f789eaf Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 8 Nov 2018 14:04:09 -0600 Subject: [PATCH 17/28] Thumb rest ray control working --- src/main/scala/vrdv/input/oculus/OculusController.scala | 6 +++++- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vrdv/input/oculus/OculusController.scala b/src/main/scala/vrdv/input/oculus/OculusController.scala index 704c810..13c525a 100644 --- a/src/main/scala/vrdv/input/oculus/OculusController.scala +++ b/src/main/scala/vrdv/input/oculus/OculusController.scala @@ -161,12 +161,16 @@ abstract class OculusController(vrc: VRController) extends input.Device { inputDetails.arrow.visible = true inputParser.passInput(new Point(Some(vrc), myCID) { rc = inputDetails - persist = isTouched(event.target) + persist = true }) }) setEventListener(Input.ThumbRest_TouchEnded, (event: Event) => { inputDetails.arrow.visible = false + inputParser.passInput(new Point(Some(vrc), myCID) { + rc = inputDetails + persist = false + }) }) setAxesEventListener(Input.Axes_Changed, (event: AxesChangedEvent) => { diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 61dcdea..3f7ba15 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - //renderer.vr.enabled = true + renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From c5e5db2595c5ec4bcf5338d0127ec65a0a27ed94 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 8 Nov 2018 17:24:29 -0600 Subject: [PATCH 18/28] Callback working on Dropdown --- src/main/scala/facade/Dat.scala | 3 +- src/main/scala/vrdv/model/Plotter.scala | 6 +++ .../vrdv/model/PlotterModelManager.scala | 1 - src/main/scala/vrdv/obj3D/InitialMenu.scala | 13 ++++-- src/main/scala/vrdv/obj3D/SettingsGui.scala | 45 ++++++++++++++++--- 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index 768213c..1ea07d0 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -32,7 +32,7 @@ object Dat { def addCheckbox(something: js.Object, id: String): Unit = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native def addButton(id: String, fn: js.Function): Unit = js.native - def addDropdown(something: js.Object, id: String, options: js.Object): GuiComponent = js.native + def addDropdown(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native def open(): Unit = js.native def close(): Unit = js.native def removeFolder(gui: GUI): Unit = js.native @@ -60,6 +60,7 @@ object Dat { @js.native trait GuiComponent extends Object3D { def name(name: String): GuiSlider = js.native + def onChange(callback: js.Function): GuiComponent = js.native } @js.native diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index c333faa..d6158e9 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -30,6 +30,8 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { def regions: Array[Region] = REGIONS + def getData: Array[Data] = DATA(0) + def numOccupied(): Int = regions.length def isFull: Boolean = numOccupied() == 4 @@ -220,6 +222,8 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } def setVisiblePointRange(start: Int, end: Int): Unit = { + //TODO Get any (including none) plot2Ds here and adjust them + /* val plot2D = PLOT(1) Log.show("Position:") Log.show(plot2D.getPoints.position) @@ -236,12 +240,14 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { val dist2FirstVisible = 1.0 / plot2D.visiblePoints * start points.translateX(prevDist2FirstVisible - dist2FirstVisible) + // 2. Scale plot (x) proportional to | end - start | Log.show("Scale: ") Log.show(points.scale) val scaleChange = (1.0*(prevEnd - prevStart)) / (1.0*(end - start)) Log.show(s"Scale Change: $scaleChange") points.scale.setX(scaleChange * points.scale.x) + */ } // Applies an axis change. Changes (1) plot point positions, (2) axes titles, and (3) gui labels diff --git a/src/main/scala/vrdv/model/PlotterModelManager.scala b/src/main/scala/vrdv/model/PlotterModelManager.scala index fb84fb7..c71ce76 100644 --- a/src/main/scala/vrdv/model/PlotterModelManager.scala +++ b/src/main/scala/vrdv/model/PlotterModelManager.scala @@ -65,7 +65,6 @@ class PlotterModelManager extends ModelManager[Action, Result] with Room { case p: input.Point => // ============== lastPoint(p.cid) = p lastPress(p.cid).persist = false - //Possibly remove persist here to get it to work on thumbrest? if(p.persist) { if(p.source.nonEmpty) plotter.hoverAction(p.rc.updateRaycaster(p.source.get), select = false) else { diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index f69876f..dabae70 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -15,8 +15,15 @@ class InitialMenu(plotter: Plotter) override def setVisible(vis: Boolean): Unit = super.setVisible(vis) - addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 1") - addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 2") - addButton(() => { plotter.newPlot3DWithData; setVisible(false) }, "Create", "Graph 3") + def addPlot: Unit = { + if(object3D.visible) { + plotter.newPlot3DWithData + setVisible(false) + } + } + + addButton(() => { addPlot }, "Create", "Graph 1") + addButton(() => { addPlot }, "Create", "Graph 2") + addButton(() => { addPlot }, "Create", "Graph 3") } \ No newline at end of file diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index fb86be4..8687e18 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -4,7 +4,7 @@ import facade.Dat import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter -import vrdv.obj3D.plots.{CoordinateAxes, Plot3D} +import vrdv.obj3D.plots.{CoordinateAxes, Plot3D, ScatterPlot, ShadowManifold} import scala.scalajs.js @@ -28,6 +28,12 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) "Left" → 0.1 ) + val axisData: js.Object = js.Dynamic.literal( + "xAxis" → plot.xVar, + "yAxis" → plot.yVar, + "zAxis" → plot.zVar + ) + val plotType: js.Object = js.Dynamic.literal( "Graph Type" → "3D Scatter" ) @@ -47,8 +53,12 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) def getLeftThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Left").asInstanceOf[Float] def getRightThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Right").asInstanceOf[Float] - addDropdown(plotType, "Graph Type", plotTypeOptions) + //def getAxisDataValue(axis: ) + val graphTypeDropdown = addDropdown(plotType, "Graph Type", plotTypeOptions) + graphTypeDropdown.onChange(() => {Log.show("Graph type menu changed.")}) + + /* //Raycaster Thresholds Folder val rcThresholdFolder = new DatGuiW("Selection Sensitivity", 0, 0, 0) rcThresholdFolder.object3D.add(raycasterThresholds, "Left", 0, 0.1).step(0.001).name("Left") @@ -56,9 +66,34 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) rcThresholdFolder.addButton(() => InputDetails.updateThresholds(getLeftThreshold, getRightThreshold), "Update!", "Apply Threshold") object3D.addFolder(rcThresholdFolder.object3D) - rcThresholdFolder.object3D.open() - - // + //rcThresholdFolder.object3D.open() + */ + + //Axes Folder + val axesFolder = new DatGuiW("Select Data", 0,0,0) + var axisTitles: js.Array[String] = js.Array() + for(d <- plotter.getData.map(_.id)) axisTitles = axisTitles :+ d + axesFolder.object3D.add(axisData, "xAxis", axisTitles) + axesFolder.object3D.add(axisData, "yAxis", axisTitles) + axesFolder.object3D.add(axisData, "zAxis", axisTitles) + object3D.addFolder(axesFolder.object3D) + axesFolder.object3D.open() + + //Filter Folder + val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) + filterFolder.object3D.add(filterRange, "Start", 0, plot.numPoints - 1).step(1).name("Start index") + filterFolder.object3D.add(filterRange, "End", 0, plot.numPoints - 1).step(1).name("End index") + filterFolder.addButton(() => plot match { + case sp: ScatterPlot ⇒ + val range = getRange + sp.setVisiblePointRange(range.start, range.end) + plotter.setVisiblePointRange(range.start, range.end) + case sm: ShadowManifold ⇒ + }, "Filter", "Time Filter") + object3D.addFolder(filterFolder.object3D) + filterFolder.object3D.open() + + //Positioning setDefaultPosition() From 21d54855c1fa36ff805ac61a07b3f7ee265d08de Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Thu, 8 Nov 2018 22:07:37 -0600 Subject: [PATCH 19/28] Progress on switching graph types --- src/main/scala/facade/Dat.scala | 2 +- src/main/scala/vrdv/model/Plotter.scala | 57 ++++++++++++---- src/main/scala/vrdv/obj3D/DatGuiW.scala | 2 +- src/main/scala/vrdv/obj3D/Region.scala | 30 ++++---- src/main/scala/vrdv/obj3D/SettingsGui.scala | 76 +++++++++++++++++---- 5 files changed, 126 insertions(+), 41 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index 1ea07d0..f99a62f 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -29,7 +29,7 @@ object Dat { def add(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native // For drop-downs def add(something: js.Object, id: String, min: Double, max: Double): GuiSlider = js.native def addFolder(folder: GUI): GUI = js.native - def addCheckbox(something: js.Object, id: String): Unit = js.native + def addCheckbox(something: js.Object, id: String): GuiComponent = js.native def addButton(fn: js.Function, id: String = "Button"): Unit = js.native def addButton(id: String, fn: js.Function): Unit = js.native def addDropdown(something: js.Object, id: String, options: js.Array[String]): GuiComponent = js.native diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index d6158e9..cddb42f 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -30,8 +30,6 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { def regions: Array[Region] = REGIONS - def getData: Array[Data] = DATA(0) - def numOccupied(): Int = regions.length def isFull: Boolean = numOccupied() == 4 @@ -41,6 +39,20 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { /*---- New 2018-11-02 ----*/ + def getData: Array[Data] = DATA(0) + def getPlotIndex(plot: Plot): Int = { + PLOT.indexOf(plot) + } + def getPlot(index: Int): Plot = PLOT(index) + def replacePlot(oldPlot: Plot, newPlot: Plot): Unit = { + val idx = getPlotIndex(oldPlot) + Log.show("[Plotter] replacing plot, idx = " + idx) + regions(idx).addPlot(newPlot) + AXES(idx) = regions(idx).maybeGetAxes().get + PLOT(idx) = newPlot + Log.show("[Plotter] index of new plot = " + getPlotIndex(newPlot)) + } + private val initialMenu = new InitialMenu(this) def toggleGuiVisibility: Unit = { @@ -98,6 +110,12 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } } + def newPlot2DWithData(columnNumber: Int): Plot = { + val xs = DATA(0)(columnNumber) + val plot2D = TimeSeriesPlot2D(xs) + plot2D + } + /*---- End New ----*/ def plot2D3D(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { @@ -255,10 +273,14 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Log.show("[requestAxisChange] start") if(columnIndex >= DATA(0).length) return + Log.show("[requestAxisChange] getting axes from region") + //AXES(plotIndex) = regions(plotIndex).maybeGetAxes().get + Log.show("[requestAxisChange] getting axes from Plotter plotIndex = " + plotIndex) val axes: CoordinateAxes = AXES(plotIndex) - val gui: DatGui = GUI(plotIndex) - var plot: Plot3D = null + //val gui: DatGui = GUI(plotIndex) + var plot: Plot = null + Log.show("[requestAxisChange] matching PLOT(plotIndex)") PLOT(plotIndex) match { case sm: ShadowManifold ⇒ val sp: ScatterPlot = ScatterPlot.fromShadowManifold(sm) @@ -269,20 +291,31 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { case _: ScatterPlot ⇒ plot = PLOT(plotIndex).asInstanceOf[ScatterPlot] plot.asInstanceOf[ScatterPlot].switchAxis(axisID, DATA(0)(columnIndex)) // assuming a single data source - gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) + //gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) + + case _: ScatterPlot2D ⇒ + plot = PLOT(plotIndex).asInstanceOf[ScatterPlot2D] + plot.asInstanceOf[ScatterPlot2D].switchAxis(axisID, DATA(0)(columnIndex)) + } - //case _: ScatterPlot2D ⇒ + //gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) + plot match { + case _: Plot3D => + axes.asInstanceOf[CoordinateAxes3D].setAxesTitles(plot.xVar, plot.yVar, plot.asInstanceOf[Plot3D].zVar) + case _: Plot2D => + axes.asInstanceOf[CoordinateAxes2D].setAxesTitles(plot.xVar, plot.yVar) } - gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) - axes.asInstanceOf[CoordinateAxes3D].setAxesTitles(plot.xVar, plot.yVar, plot.zVar) + /* // We set the new variable bound to the 3D Plots x axis to the 2D plots y axes if(axisID == XAxis) { PLOT(plotIndex + 1).asInstanceOf[ScatterPlot2D].switchAxis(YAxis, DATA(0)(columnIndex)) AXES(plotIndex + 1).asInstanceOf[CoordinateAxes2D].setAxisTitle(DATA(0)(columnIndex).id, YAxis) } + */ + Log.show("[requestAxisChange] Updating axis titles...") AXES(plotIndex) match { case a2D: CoordinateAxes2D ⇒ @@ -295,13 +328,13 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { axisID match { // Currently viewing a scatter-plot, so we can settle with modifying a single axis case XAxis => a3D.setAxisTitle(plot.xVar, XAxis) - gui.updateFolderLabels(x = plot.xVar) + //gui.updateFolderLabels(x = plot.xVar) case YAxis => a3D.setAxisTitle(plot.yVar, YAxis) - gui.updateFolderLabels(y = plot.yVar) + //gui.updateFolderLabels(y = plot.yVar) case ZAxis => - a3D.setAxisTitle(plot.zVar, ZAxis) - gui.updateFolderLabels(z = plot.zVar) + a3D.setAxisTitle(plot.asInstanceOf[Plot3D].zVar, ZAxis) + //gui.updateFolderLabels(z = plot.zVar) } } diff --git a/src/main/scala/vrdv/obj3D/DatGuiW.scala b/src/main/scala/vrdv/obj3D/DatGuiW.scala index 928f687..a0dde37 100644 --- a/src/main/scala/vrdv/obj3D/DatGuiW.scala +++ b/src/main/scala/vrdv/obj3D/DatGuiW.scala @@ -31,7 +31,7 @@ class DatGuiW(title: String, xInit: Double, yInit: Double, zInit: Double) { WButton(idx, object3D).setLabels(name, description) } - def addCheckbox(something: js.Object, id: String, description: String): Unit = { + def addCheckbox(something: js.Object, id: String, description: String): GuiComponent = { object3D.add(something, id).name(description) } diff --git a/src/main/scala/vrdv/obj3D/Region.scala b/src/main/scala/vrdv/obj3D/Region.scala index fd35a37..4eb1ac9 100644 --- a/src/main/scala/vrdv/obj3D/Region.scala +++ b/src/main/scala/vrdv/obj3D/Region.scala @@ -1,6 +1,7 @@ package vrdv.obj3D import org.scalajs.threejs.Object3D +import util.Log import vrdv.obj3D import vrdv.obj3D.plots._ @@ -19,22 +20,27 @@ case class Region(id: Int, object3D: Object3D = new Object3D()) { def maybeGetAxes(): Option[CoordinateAxes] = maybeAxes def addPlot(p: Plot): Unit = { + val axes: CoordinateAxes = + p match { + case p3D: Plot3D ⇒ + val axes: CoordinateAxes3D = default3DAxes() + axes.createAxesTitles(p3D.xVar, p3D.yVar, p3D.zVar) + axes + case p2D: Plot2D ⇒ + val axes = default2DAxes() + axes.createAxesTitles(p2D.xVar, p2D.yVar) + axes + } + // Remove previous plot if it exists and add the new one - if(plot.nonEmpty) remove(plot.get.getPoints) + if(plot.nonEmpty) { + remove(plot.get.getPoints) + Log.show("[Region] clearing region...") + for(c <- object3D.children) {object3D.remove(c)} + } plot = Some(p) object3D.add(p.getPoints) - var axes: CoordinateAxes = - p match { - case p3D: Plot3D ⇒ - val axes: CoordinateAxes3D = default3DAxes() - axes.createAxesTitles(p3D.xVar, p3D.yVar, p3D.zVar) - axes - case p2D: Plot2D ⇒ - val axes = default2DAxes() - axes.createAxesTitles(p2D.xVar, p2D.yVar) - axes - } maybeAxes = Some(axes) add(axes) } diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 8687e18..d36b09d 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -4,13 +4,15 @@ import facade.Dat import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter -import vrdv.obj3D.plots.{CoordinateAxes, Plot3D, ScatterPlot, ShadowManifold} +import vrdv.obj3D.plots.{CoordinateAxes, Plot3D, Plot, ScatterPlot, ShadowManifold} import scala.scalajs.js -class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) +class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) extends DatGuiW("Graph Settings", axes.position.x - 2.0, axes.position.y + 2.0, axes.position.z){ + var attachedPlot = plot + override def setVisible(vis: Boolean): Unit = super.setVisible(vis) val rawTau: js.Object = js.Dynamic.literal( @@ -20,7 +22,9 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) val filterRange: js.Object = js.Dynamic.literal( "Start" → 0, - "End" → 0 + "End" → 0, + "Snap 10" → false, + "Snap 100" → false ) val raycasterThresholds: js.Object = js.Dynamic.literal( @@ -29,9 +33,9 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) ) val axisData: js.Object = js.Dynamic.literal( - "xAxis" → plot.xVar, - "yAxis" → plot.yVar, - "zAxis" → plot.zVar + "xAxis" → attachedPlot.xVar, + "yAxis" → attachedPlot.yVar, + "zAxis" → attachedPlot.asInstanceOf[Plot3D].zVar ) val plotType: js.Object = js.Dynamic.literal( @@ -53,10 +57,24 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) def getLeftThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Left").asInstanceOf[Float] def getRightThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Right").asInstanceOf[Float] - //def getAxisDataValue(axis: ) - val graphTypeDropdown = addDropdown(plotType, "Graph Type", plotTypeOptions) - graphTypeDropdown.onChange(() => {Log.show("Graph type menu changed.")}) + .onChange(() => {Log.show("Graph type menu changed."); changeGraphType}) + + def changeGraphType: Unit = { + val gtString = plotType.asInstanceOf[js.Dynamic].selectDynamic("Graph Type").asInstanceOf[String] + val plotIndex = plotter.getPlotIndex(attachedPlot) + + gtString match { + case "3D Scatter" => { + + } + case "2D Scatter" => { + val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) + plotter.replacePlot(attachedPlot, plotter.newPlot2DWithData(columnID)) + attachedPlot = plotter.getPlot(plotIndex) + } + } + } /* //Raycaster Thresholds Folder @@ -73,17 +91,34 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) val axesFolder = new DatGuiW("Select Data", 0,0,0) var axisTitles: js.Array[String] = js.Array() for(d <- plotter.getData.map(_.id)) axisTitles = axisTitles :+ d - axesFolder.object3D.add(axisData, "xAxis", axisTitles) - axesFolder.object3D.add(axisData, "yAxis", axisTitles) - axesFolder.object3D.add(axisData, "zAxis", axisTitles) + axesFolder.addDropdown(axisData, "xAxis", axisTitles).onChange(() => callForAxisUpdate(0)) + axesFolder.addDropdown(axisData, "yAxis", axisTitles).onChange(() => callForAxisUpdate(1)) + axesFolder.addDropdown(axisData, "zAxis", axisTitles).onChange(() => callForAxisUpdate(2)) object3D.addFolder(axesFolder.object3D) + axesFolder.object3D.open() + def callForAxisUpdate(id: Int): Unit = { + val axisString = id match { + case 0 => "xAxis" + case 1 => "yAxis" + case 2 => "zAxis" + } + val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic(axisString)) + val plotIndex = plotter.getPlotIndex(attachedPlot) + Log.show("[SettingsGui] requesting axis change plotIndex = " + plotIndex) + plotter.requestAxisChange(plotIndex, id, columnID) + } + //Filter Folder val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) - filterFolder.object3D.add(filterRange, "Start", 0, plot.numPoints - 1).step(1).name("Start index") - filterFolder.object3D.add(filterRange, "End", 0, plot.numPoints - 1).step(1).name("End index") - filterFolder.addButton(() => plot match { + filterFolder.addCheckbox(filterRange, "Snap 10", "Snap to 10").onChange(() => setFilterStep) + filterFolder.addCheckbox(filterRange, "Snap 100", "Snap to 100").onChange(() => setFilterStep) + val filterLowSlider = filterFolder.object3D.add(filterRange, "Start", 0, attachedPlot.numPoints - 1) + .step(getFilterStep).name("Start index") + val filterHighSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) + .step(getFilterStep).name("End index") + filterFolder.addButton(() => attachedPlot match { case sp: ScatterPlot ⇒ val range = getRange sp.setVisiblePointRange(range.start, range.end) @@ -93,6 +128,17 @@ class SettingsGui(plot: Plot3D, axes: CoordinateAxes,plotter: Plotter) object3D.addFolder(filterFolder.object3D) filterFolder.object3D.open() + def setFilterStep: Unit = { + filterLowSlider.step(getFilterStep) + filterHighSlider.step(getFilterStep) + } + + def getFilterStep: Int = { + if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 100").asInstanceOf[Boolean]) 100 else + if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 10").asInstanceOf[Boolean]) 10 else 1 + } + + //Positioning setDefaultPosition() From 5fea0c011d6d471a08b843c9ad1655e6b1815569 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 9 Nov 2018 00:16:00 -0600 Subject: [PATCH 20/28] Switching between 3D and 2D Scatter Plots works --- src/main/scala/vrdv/model/Plotter.scala | 68 +++++++++++++-------- src/main/scala/vrdv/obj3D/InitialMenu.scala | 2 +- src/main/scala/vrdv/obj3D/SettingsGui.scala | 21 +++++-- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index cddb42f..4c9bee0 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -75,7 +75,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } } - def newPlot3DWithData: Unit = { + def initPlot3DWithData: Unit = { val data = DATA(0) val pointColor = CustomColors.BLUE_HUE_SHIFT @@ -110,6 +110,17 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } } + def newPlot3DWithData(xCol: Int, yCol: Int, zCol: Int): Plot = { + val data = DATA(0) + val pointColor = CustomColors.BLUE_HUE_SHIFT + val scatterPlot: ScatterPlot = ScatterPlot(data, Res.getLastLoadedTextureID, pointColor) + scatterPlot.switchAxis(0, data(xCol), true) + scatterPlot.switchAxis(1, data(yCol), true) + scatterPlot.switchAxis(2, data(zCol), true) + + scatterPlot + } + def newPlot2DWithData(columnNumber: Int): Plot = { val xs = DATA(0)(columnNumber) val plot2D = TimeSeriesPlot2D(xs) @@ -240,32 +251,35 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } def setVisiblePointRange(start: Int, end: Int): Unit = { - //TODO Get any (including none) plot2Ds here and adjust them - /* - val plot2D = PLOT(1) - Log.show("Position:") - Log.show(plot2D.getPoints.position) - val prevStart = plot2D.firstVisiblePointIndex - val prevEnd = plot2D.visiblePoints + prevStart - plot2D.setVisiblePointRange(start, end) - - // 1. Shift plot (-x) proportional to |start| - val numPoints = plot2D.numPoints - val points = plot2D.getPoints - val deltaT = 1.0 / numPoints // distance between points along x-axis - - val prevDist2FirstVisible = 1.0 / (prevEnd - prevStart) * prevStart - val dist2FirstVisible = 1.0 / plot2D.visiblePoints * start - points.translateX(prevDist2FirstVisible - dist2FirstVisible) - - - // 2. Scale plot (x) proportional to | end - start | - Log.show("Scale: ") - Log.show(points.scale) - val scaleChange = (1.0*(prevEnd - prevStart)) / (1.0*(end - start)) - Log.show(s"Scale Change: $scaleChange") - points.scale.setX(scaleChange * points.scale.x) - */ + + for(plot <- PLOT) { + plot match { + case plot2D: TimeSeriesPlot2D => { + Log.show("Position:") + Log.show(plot2D.getPoints.position) + val prevStart = plot2D.firstVisiblePointIndex + val prevEnd = plot2D.visiblePoints + prevStart + plot2D.setVisiblePointRange(start, end) + + // 1. Shift plot (-x) proportional to |start| + val numPoints = plot2D.numPoints + val points = plot2D.getPoints + val deltaT = 1.0 / numPoints // distance between points along x-axis + + val prevDist2FirstVisible = 1.0 / (prevEnd - prevStart) * prevStart + val dist2FirstVisible = 1.0 / plot2D.visiblePoints * start + points.translateX(prevDist2FirstVisible - dist2FirstVisible) + + + // 2. Scale plot (x) proportional to | end - start | + Log.show("Scale: ") + Log.show(points.scale) + val scaleChange = (1.0 * (prevEnd - prevStart)) / (1.0 * (end - start)) + Log.show(s"Scale Change: $scaleChange") + points.scale.setX(scaleChange * points.scale.x) + } + } + } } // Applies an axis change. Changes (1) plot point positions, (2) axes titles, and (3) gui labels diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index dabae70..b8c56c2 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -17,7 +17,7 @@ class InitialMenu(plotter: Plotter) def addPlot: Unit = { if(object3D.visible) { - plotter.newPlot3DWithData + plotter.initPlot3DWithData setVisible(false) } } diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index d36b09d..8c54970 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -4,7 +4,7 @@ import facade.Dat import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter -import vrdv.obj3D.plots.{CoordinateAxes, Plot3D, Plot, ScatterPlot, ShadowManifold} +import vrdv.obj3D.plots._ import scala.scalajs.js @@ -66,12 +66,20 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) gtString match { case "3D Scatter" => { - + val xCol = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) + val yCol = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("yAxis")) + val zCol = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("zAxis")) + plotter.replacePlot(attachedPlot, plotter.newPlot3DWithData(xCol, yCol, zCol)) + attachedPlot = plotter.getPlot(plotIndex) + val range = getRange + attachedPlot.setVisiblePointRange(range.start, range.end) } case "2D Scatter" => { - val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) + val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("yAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot2DWithData(columnID)) attachedPlot = plotter.getPlot(plotIndex) + val range = getRange + plotter.setVisiblePointRange(range.start, range.end) } } } @@ -119,9 +127,12 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) val filterHighSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) .step(getFilterStep).name("End index") filterFolder.addButton(() => attachedPlot match { - case sp: ScatterPlot ⇒ + case sp3d: ScatterPlot ⇒ + val range = getRange + sp3d.setVisiblePointRange(range.start, range.end) + plotter.setVisiblePointRange(range.start, range.end) + case _: ScatterPlot2D => val range = getRange - sp.setVisiblePointRange(range.start, range.end) plotter.setVisiblePointRange(range.start, range.end) case sm: ShadowManifold ⇒ }, "Filter", "Time Filter") diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 3f7ba15..61dcdea 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - renderer.vr.enabled = true + //renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 21be3fd7739a8d4ee56e8451fc500400a112b7d7 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 9 Nov 2018 03:15:52 -0600 Subject: [PATCH 21/28] Three plots spawn, time filter needs work --- src/main/scala/vrdv/model/Plotter.scala | 25 ++++++-- src/main/scala/vrdv/obj3D/InitialMenu.scala | 4 +- src/main/scala/vrdv/obj3D/SettingsGui.scala | 66 ++++++++++++--------- 3 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index 4c9bee0..ee1bdec 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -96,9 +96,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { //regions(i).gui = Some(gui) //regions(i).add(gui.object3D) scene.add(gui.object3D) - gui.object3D.position.setX(regions(i).object3D.position.x) - gui.object3D.position.setY(regions(i).object3D.position.y + 1.0) - gui.object3D.position.setZ(regions(i).object3D.position.z) + gui.object3D.position.setX(regions(i).object3D.position.x - 0.5) + gui.object3D.position.setY(regions(i).object3D.position.y + 0.5) + gui.object3D.position.setZ(regions(i).object3D.position.z + 1.0) //gui.object3D.rotateY(3.14 / 4) @@ -254,6 +254,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { for(plot <- PLOT) { plot match { + //TODO Case for Plot3D case plot2D: TimeSeriesPlot2D => { Log.show("Position:") Log.show(plot2D.getPoints.position) @@ -278,6 +279,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Log.show(s"Scale Change: $scaleChange") points.scale.setX(scaleChange * points.scale.x) } + case _: Any => } } } @@ -287,8 +289,6 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Log.show("[requestAxisChange] start") if(columnIndex >= DATA(0).length) return - Log.show("[requestAxisChange] getting axes from region") - //AXES(plotIndex) = regions(plotIndex).maybeGetAxes().get Log.show("[requestAxisChange] getting axes from Plotter plotIndex = " + plotIndex) val axes: CoordinateAxes = AXES(plotIndex) //val gui: DatGui = GUI(plotIndex) @@ -466,17 +466,32 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { case 1 => getPos(0).set(0, 1, -2) // north case 2 => + /* getPos(0).set(-1, 1, -1) // north west getPos(1).set(1, 1, -1) // north east + */ + getPos(0).set(0, 1, -2) // north + getPos(1).set(1.5, 1, -2) // north east case 3 => + /* getPos(0).set(-1, 1, -1) // north west getPos(1).set(1, 1, -1) // north east getPos(2).set(-2, 1, 0) // west + */ + getPos(0).set(0, 1, -2) // north + getPos(1).set(1.5, 1, -2) // north east + getPos(2).set(-1.5, 1, -2) // north west case 4 => + /* getPos(0).set(-1, 1, -1) // north west getPos(1).set(1, 1, -1) // north east getPos(2).set(-2, 1, 0) // west getPos(3).set(2, 1, 0) // east + */ + getPos(0).set(0, 1, -2) // north + getPos(1).set(1.5, 1, -2) // north east + getPos(2).set(-1.5, 1, -2) // north west + getPos(3).set(2, 1, 0) // east case _ => // Undefined for more regions } num diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index b8c56c2..4f1c348 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -18,7 +18,9 @@ class InitialMenu(plotter: Plotter) def addPlot: Unit = { if(object3D.visible) { plotter.initPlot3DWithData - setVisible(false) + //setVisible(false) + object3D.position.set(2, 1, 0) + object3D.rotation.y = -3.14 / 2.0 } } diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 8c54970..4b088ce 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -72,14 +72,20 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) plotter.replacePlot(attachedPlot, plotter.newPlot3DWithData(xCol, yCol, zCol)) attachedPlot = plotter.getPlot(plotIndex) val range = getRange - attachedPlot.setVisiblePointRange(range.start, range.end) + //attachedPlot.setVisiblePointRange(range.start, range.end) + xDropdown.visible = true + yDropdown.visible = true + zDropdown.visible = true } case "2D Scatter" => { val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("yAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot2DWithData(columnID)) attachedPlot = plotter.getPlot(plotIndex) val range = getRange - plotter.setVisiblePointRange(range.start, range.end) + //plotter.setVisiblePointRange(range.start, range.end) + xDropdown.visible = false + yDropdown.visible = true + zDropdown.visible = false } } } @@ -99,9 +105,9 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) val axesFolder = new DatGuiW("Select Data", 0,0,0) var axisTitles: js.Array[String] = js.Array() for(d <- plotter.getData.map(_.id)) axisTitles = axisTitles :+ d - axesFolder.addDropdown(axisData, "xAxis", axisTitles).onChange(() => callForAxisUpdate(0)) - axesFolder.addDropdown(axisData, "yAxis", axisTitles).onChange(() => callForAxisUpdate(1)) - axesFolder.addDropdown(axisData, "zAxis", axisTitles).onChange(() => callForAxisUpdate(2)) + val xDropdown = axesFolder.addDropdown(axisData, "xAxis", axisTitles).onChange(() => callForAxisUpdate(0)) + val yDropdown = axesFolder.addDropdown(axisData, "yAxis", axisTitles).onChange(() => callForAxisUpdate(1)) + val zDropdown = axesFolder.addDropdown(axisData, "zAxis", axisTitles).onChange(() => callForAxisUpdate(2)) object3D.addFolder(axesFolder.object3D) axesFolder.object3D.open() @@ -126,16 +132,7 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) .step(getFilterStep).name("Start index") val filterHighSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) .step(getFilterStep).name("End index") - filterFolder.addButton(() => attachedPlot match { - case sp3d: ScatterPlot ⇒ - val range = getRange - sp3d.setVisiblePointRange(range.start, range.end) - plotter.setVisiblePointRange(range.start, range.end) - case _: ScatterPlot2D => - val range = getRange - plotter.setVisiblePointRange(range.start, range.end) - case sm: ShadowManifold ⇒ - }, "Filter", "Time Filter") + filterFolder.addButton(() => applyFilter, "Filter", "Time Filter") object3D.addFolder(filterFolder.object3D) filterFolder.object3D.open() @@ -149,21 +146,34 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 10").asInstanceOf[Boolean]) 10 else 1 } + def applyFilter = { + attachedPlot match { + case sp3d: ScatterPlot ⇒ + val range = getRange + sp3d.setVisiblePointRange(range.start, range.end) + plotter.setVisiblePointRange(range.start, range.end) + case _: ScatterPlot2D => + val range = getRange + plotter.setVisiblePointRange(range.start, range.end) + case sm: ShadowManifold ⇒ + } + } - //Positioning - - setDefaultPosition() - - def setDefaultPosition(): Unit = { - val xPosDefault: Double = axes.position.x - 2.0 - val yPosDefault: Double = axes.position.y + 2.0 - val zPosDefault: Double = axes.position.z + //Reset button + //TODO Reset Button + //addButton(() => resetToDefaults, "Reset", "Reset to Defaults") - Log.show("Setting GUI position to: (" + xPosDefault + ", " + yPosDefault + ", " + zPosDefault + ")") + def resetToDefaults = { + //TODO needs work: controls don't reset display + Log.show("Reset to Defaults Button pressed.") + filterRange.asInstanceOf[js.Dynamic].updateDynamic("Start")(0) + filterRange.asInstanceOf[js.Dynamic].updateDynamic("End")(attachedPlot.numPoints - 1) + applyFilter - //object3D.position.set(xPosDefault, yPosDefault, zPosDefault) - object3D.position.x = xPosDefault - object3D.position.y = yPosDefault - object3D.position.z = zPosDefault + val plotIndex = plotter.getPlotIndex(attachedPlot) + Log.show("[SettingsGui] requesting axis change plotIndex = " + plotIndex) + plotter.requestAxisChange(plotIndex, 0, 0) + plotter.requestAxisChange(plotIndex, 1, 1) + plotter.requestAxisChange(plotIndex, 2, 2) } } From e7446a1bff4d9e3470ec6299df6826b6cd547b5f Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 9 Nov 2018 06:41:20 -0600 Subject: [PATCH 22/28] Three plots mostly working, shadow manifolds not changing axes correctly --- src/main/scala/vrdv/model/Plotter.scala | 76 ++++++++++++++++++--- src/main/scala/vrdv/model/package.scala | 4 +- src/main/scala/vrdv/obj3D/InitialMenu.scala | 2 + src/main/scala/vrdv/obj3D/SettingsGui.scala | 29 ++++++++ 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index ee1bdec..56a8816 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -18,9 +18,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { private var REGIONS: Array[Region] = Array() private var PLOT: Array[Plot] = Array() private var AXES: Array[CoordinateAxes] = Array() - private var GUI: Array[DatGui] = Array() + private var GUI: Array[DatGuiW] = Array() - def addGUI(gui: DatGui): Unit = GUI = GUI :+ gui + def addGUI(gui: DatGuiW): Unit = GUI = GUI :+ gui def addPlot(plot: Plot): Unit = PLOT = PLOT :+ plot def addAxes(axes: CoordinateAxes): Unit = AXES = AXES :+ axes def addRegion(r: Region): Unit = { @@ -40,9 +40,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { /*---- New 2018-11-02 ----*/ def getData: Array[Data] = DATA(0) - def getPlotIndex(plot: Plot): Int = { - PLOT.indexOf(plot) - } + def getPlotIndex(plot: Plot): Int = PLOT.indexOf(plot) def getPlot(index: Int): Plot = PLOT(index) def replacePlot(oldPlot: Plot, newPlot: Plot): Unit = { val idx = getPlotIndex(oldPlot) @@ -57,6 +55,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { def toggleGuiVisibility: Unit = { Log.show("Toggle GUI visibility.") + val vis = !GUI(0).object3D.visible + for(gui <- GUI) gui.setVisible(vis) + //initialMenu.setVisible(vis) } def setupData(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { @@ -93,6 +94,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { //val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) val gui = new SettingsGui(scatterPlot, regions(i).maybeGetAxes().get, this) + addGUI(gui) //regions(i).gui = Some(gui) //regions(i).add(gui.object3D) scene.add(gui.object3D) @@ -127,6 +129,62 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { plot2D } + def newShadowManifoldWithData(columnNumber: Int, tau: Int = 1): Plot = { + val data = DATA(0) + val pointColor = CustomColors.BLUE_HUE_SHIFT + val scatterPlot: ScatterPlot = ScatterPlot(data, Res.getLastLoadedTextureID, pointColor) + scatterPlot.switchAxis(0, data(columnNumber), true) + scatterPlot.switchAxis(1, data(columnNumber), true) + scatterPlot.switchAxis(2, data(columnNumber), true) + + val newSM: ShadowManifold = ShadowManifold.fromScatterPlot(scatterPlot)(tau, 0).get + newSM.fixScale() + newSM.setVisiblePointRange(0, newSM.numPoints - 2 * tau) + newSM.requestFullGeometryUpdate() + + newSM + } + + /* + def requestEmbedding(axisID: AxisID, columnIndex: Int, tau: Int, plotIndex: Int = 0): Unit = { + Log.show("[Plotter.requestEmbedding()]") + + /*var regionCreated: Boolean = false + if (plotIndex >= PLOT.length) { + regionCreated = true + val i = regions.length + addRegion(Region(i)) + repositionRegions() + }*/ + + val maybeNewSM: Option[ShadowManifold] = + PLOT(plotIndex) match { + case sm: ShadowManifold => + Log.show(s"embedding from SM->SM with columnIndex: $columnIndex (id: ${DATA(0)(columnIndex).id})") + ShadowManifold.fromShadowManifold(sm)(tau) + case sp: ScatterPlot => ShadowManifold.fromScatterPlot(sp)(tau, axisID) + } + + if (maybeNewSM.isEmpty) { + Log.show("[Plotter.requestEmbedding()] maybeNewSM.isEmpty == true") + return + } + + val newSM: ShadowManifold = maybeNewSM.get + PLOT(plotIndex) = newSM + newSM.fixScale() + newSM.setVisiblePointRange(0, newSM.numPoints - 2 * tau) + newSM.requestFullGeometryUpdate() + + Log.show(s"[Plotter.requestEmbedding()] (x, y, z) = (${newSM.xVar}, ${newSM.yVar}, ${newSM.zVar})") + + AXES(plotIndex) match { + case a2D: CoordinateAxes2D ⇒ a2D.setAxesTitles(newSM.xVar, newSM.yVar) + case a3D: CoordinateAxes3D ⇒ a3D.setAxesTitles(newSM.xVar, newSM.yVar, newSM.zVar) + } + } // -- eof + */ + /*---- End New ----*/ def plot2D3D(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { @@ -195,6 +253,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { * @param plot Some instance of a class that implements trait Plot. * @return The region the plot was added to if successful, otherwise None. */ + def addPlot3DToRegion(plot: Plot3D): Unit = { Log("[Regions] - Adding 3D plot to new region") val i = regions.length @@ -208,7 +267,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { addPlot(plot) addAxes(regions(i).maybeGetAxes().get) - addGUI(gui) + //addGUI(gui) } /** @@ -297,10 +356,11 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Log.show("[requestAxisChange] matching PLOT(plotIndex)") PLOT(plotIndex) match { case sm: ShadowManifold ⇒ + val tau = sm.tau val sp: ScatterPlot = ScatterPlot.fromShadowManifold(sm) - PLOT(plotIndex) = sp sp.switchAxis(axisID, DATA(0)(columnIndex)) // assuming a single data source - plot = sp + plot = ShadowManifold.fromScatterPlot(sp)(tau).get + PLOT(plotIndex) = plot case _: ScatterPlot ⇒ plot = PLOT(plotIndex).asInstanceOf[ScatterPlot] diff --git a/src/main/scala/vrdv/model/package.scala b/src/main/scala/vrdv/model/package.scala index fad3662..127fdad 100644 --- a/src/main/scala/vrdv/model/package.scala +++ b/src/main/scala/vrdv/model/package.scala @@ -80,13 +80,13 @@ package object model { val white: Color = new Color(0xffffff)//ColorKeywords.white) val floorMaterial: MeshLambertMaterial = new MeshLambertMaterial() floorMaterial.color = white - val floorGeometry: PlaneGeometry = new PlaneGeometry( 1, 1 ) + val floorGeometry: PlaneGeometry = new PlaneGeometry( 4, 4 ) // was width = 1, height = 1 val floor: Mesh = new Mesh(floorGeometry, floorMaterial) floor.receiveShadow = false floor.rotateX(-3.1415/2) // Add 6x6m Grid broken into 36 sections - val floorGrid: GridHelper = new GridHelperExt(1, 2, black, black) + val floorGrid: GridHelper = new GridHelperExt(4, 8, black, black) // was size = 1, step = 2 floorGrid.position.setY(0.001) floorGrid.material.linewidth = 2.0 scene.add(floorGrid) diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index 4f1c348..0c059b8 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -28,4 +28,6 @@ class InitialMenu(plotter: Plotter) addButton(() => { addPlot }, "Create", "Graph 2") addButton(() => { addPlot }, "Create", "Graph 3") + addButton(() => {plotter.toggleGuiVisibility}, "Hide", "Hide GUI") + } \ No newline at end of file diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 4b088ce..9c5dfef 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -87,6 +87,23 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) yDropdown.visible = true zDropdown.visible = false } + case "Shadow Manifold" => { + val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) + plotter.replacePlot(attachedPlot, plotter.newShadowManifoldWithData(columnID, getTau)) + attachedPlot = plotter.getPlot(plotIndex) + val range = getRange + //plotter.setVisiblePointRange(range.start, range.end) + xDropdown.visible = true + yDropdown.visible = false + zDropdown.visible = false + + /* + AXES(plotIndex) match { + case a2D: CoordinateAxes2D ⇒ a2D.setAxesTitles(newSM.xVar, newSM.yVar) + case a3D: CoordinateAxes3D ⇒ a3D.setAxesTitles(newSM.xVar, newSM.yVar, newSM.zVar) + } + */ + } } } @@ -124,6 +141,18 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) plotter.requestAxisChange(plotIndex, id, columnID) } + //Embedding Folder + val embeddingFolder = new DatGuiW("Embedding", 0,0,0) + embeddingFolder.object3D.add(rawTau, "TauOnes", 0, 10).step(1).name("Tau Ones") + embeddingFolder.object3D.add(rawTau, "TauTens", 0, 90).step(10).name("Tau Tens") + embeddingFolder.object3D.add(rawTau, "TauHundreds", 0, 900).step(100).name("Tau Hundreds") + embeddingFolder.addButton(() => plot match { + case sm: ShadowManifold ⇒ plotter.requestEmbedding(XAxis, sm.data.columnNumber, getTau)//, 1) + case sp: ScatterPlot ⇒ plotter.requestEmbedding(XAxis, sp.viewing(XAxis), getTau)//, 1) + }, "Embed!", "Embed Shadow Manifold") + object3D.addFolder(embeddingFolder.object3D) + embeddingFolder.object3D.open() + //Filter Folder val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) filterFolder.addCheckbox(filterRange, "Snap 10", "Snap to 10").onChange(() => setFilterStep) From 8950ce6a4d6eea4b77468eef8674299491690632 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 9 Nov 2018 12:20:24 -0600 Subject: [PATCH 23/28] For Demo to Team --- src/main/scala/facade/Dat.scala | 5 +++-- src/main/scala/vrdv/model/Plotter.scala | 7 +++++++ src/main/scala/vrdv/obj3D/Region.scala | 2 ++ src/main/scala/vrdv/obj3D/SettingsGui.scala | 12 ++++++------ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index f99a62f..6ba17c7 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -40,12 +40,13 @@ object Dat { @js.native trait GuiSlider extends GuiComponent { - def listen(): GuiSlider = js.native + def listen(): GuiComponent = js.native def min(n: Double): GuiSlider = js.native def max(n: Double): GuiSlider = js.native def step(n: Double): GuiSlider = js.native def updateValueLabel(label: String): Unit = js.native def updateObject(obj: js.Any): Unit = js.native + def updateSlider():Unit = js.native } @js.native @@ -59,7 +60,7 @@ object Dat { @js.native trait GuiComponent extends Object3D { - def name(name: String): GuiSlider = js.native + def name(name: String): GuiComponent = js.native def onChange(callback: js.Function): GuiComponent = js.native } diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index 56a8816..12fc5ef 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -39,6 +39,13 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { /*---- New 2018-11-02 ----*/ + //TODO Maybe don't filter these and check for isDefined when accessing? + def getPlots: Array[Plot] = regions.map(_.maybeGetPlot()).filter(_.isDefined).map(_.get) + def getAxes: Array[CoordinateAxes] = regions.map(_.maybeGetAxes()).filter(_.isDefined).map(_.get) + + def maybeGetRegionForPlot(plot: Plot): Option[Region] = + Option(regions.filter(r => r.maybeGetPlot().getOrElse(Unit) == plot)(0)) + def getData: Array[Data] = DATA(0) def getPlotIndex(plot: Plot): Int = PLOT.indexOf(plot) def getPlot(index: Int): Plot = PLOT(index) diff --git a/src/main/scala/vrdv/obj3D/Region.scala b/src/main/scala/vrdv/obj3D/Region.scala index 4eb1ac9..0617600 100644 --- a/src/main/scala/vrdv/obj3D/Region.scala +++ b/src/main/scala/vrdv/obj3D/Region.scala @@ -16,6 +16,8 @@ case class Region(id: Int, object3D: Object3D = new Object3D()) { var gui: Option[DatGui] = None obj3D.setMoveable(object3D) + def maybeGetPlot(): Option[Plot] = plot + private var maybeAxes: Option[CoordinateAxes] = None def maybeGetAxes(): Option[CoordinateAxes] = maybeAxes diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 9c5dfef..747f8fa 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -1,6 +1,6 @@ package vrdv.obj3D -import facade.Dat +import facade.Dat._ import util.Log import vrdv.input.InputDetails import vrdv.model.Plotter @@ -8,7 +8,7 @@ import vrdv.obj3D.plots._ import scala.scalajs.js -class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) +class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) extends DatGuiW("Graph Settings", axes.position.x - 2.0, axes.position.y + 2.0, axes.position.z){ var attachedPlot = plot @@ -157,10 +157,10 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes,plotter: Plotter) val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) filterFolder.addCheckbox(filterRange, "Snap 10", "Snap to 10").onChange(() => setFilterStep) filterFolder.addCheckbox(filterRange, "Snap 100", "Snap to 100").onChange(() => setFilterStep) - val filterLowSlider = filterFolder.object3D.add(filterRange, "Start", 0, attachedPlot.numPoints - 1) - .step(getFilterStep).name("Start index") - val filterHighSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) - .step(getFilterStep).name("End index") + val filterLowSlider: GuiSlider = filterFolder.object3D.add(filterRange, "Start", 0, attachedPlot.numPoints - 1) + .step(getFilterStep).name("Start index").asInstanceOf[GuiSlider] + val filterHighSlider: GuiSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) + .step(getFilterStep).name("End index").asInstanceOf[GuiSlider] filterFolder.addButton(() => applyFilter, "Filter", "Time Filter") object3D.addFolder(filterFolder.object3D) filterFolder.object3D.open() From c68e0602d10d194157c056f1a2572f7d364297f0 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Fri, 9 Nov 2018 12:27:54 -0600 Subject: [PATCH 24/28] Corrected Bug introduced previously --- src/main/scala/facade/Dat.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/facade/Dat.scala b/src/main/scala/facade/Dat.scala index 6ba17c7..6247ddd 100644 --- a/src/main/scala/facade/Dat.scala +++ b/src/main/scala/facade/Dat.scala @@ -40,7 +40,7 @@ object Dat { @js.native trait GuiSlider extends GuiComponent { - def listen(): GuiComponent = js.native + def listen(): GuiSlider = js.native def min(n: Double): GuiSlider = js.native def max(n: Double): GuiSlider = js.native def step(n: Double): GuiSlider = js.native @@ -60,7 +60,7 @@ object Dat { @js.native trait GuiComponent extends Object3D { - def name(name: String): GuiComponent = js.native + def name(name: String): GuiSlider = js.native def onChange(callback: js.Function): GuiComponent = js.native } From 6a4f27f2f6e95d08aa1452de7ac1d4b06b58341e Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Sat, 10 Nov 2018 22:06:23 -0600 Subject: [PATCH 25/28] Functionality ready for demo, some work needed on ui --- src/main/scala/vrdv/model/Plotter.scala | 91 +++++++++++------- src/main/scala/vrdv/obj3D/GlobalMenu.scala | 96 +++++++++++++++++++ src/main/scala/vrdv/obj3D/InitialMenu.scala | 11 ++- src/main/scala/vrdv/obj3D/Region.scala | 7 +- src/main/scala/vrdv/obj3D/SettingsGui.scala | 84 ++-------------- .../vrdv/obj3D/plots/ShadowManifold.scala | 39 +++++++- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 7 files changed, 212 insertions(+), 118 deletions(-) create mode 100644 src/main/scala/vrdv/obj3D/GlobalMenu.scala diff --git a/src/main/scala/vrdv/model/Plotter.scala b/src/main/scala/vrdv/model/Plotter.scala index 12fc5ef..69cfd98 100644 --- a/src/main/scala/vrdv/model/Plotter.scala +++ b/src/main/scala/vrdv/model/Plotter.scala @@ -2,11 +2,11 @@ package vrdv.model import org.scalajs.threejs.{Camera, Intersection, Scene, Vector3} import resources.{Data, Res} -import util.Log +import util.{Log, ScaleCenterProperties} import vrdv.input.{Action, InputDetails, Interactions} import vrdv.obj3D.displays.{CSC_DefaultConfig, ColumnSelectionConsole} import vrdv.obj3D.plots._ -import vrdv.obj3D.{CustomColors, DatGui, DatGuiW, SettingsGui, InitialMenu, Region} +import vrdv.obj3D._ /** * Created by Dorian Thiessen on 2018-07-29. @@ -47,7 +47,8 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Option(regions.filter(r => r.maybeGetPlot().getOrElse(Unit) == plot)(0)) def getData: Array[Data] = DATA(0) - def getPlotIndex(plot: Plot): Int = PLOT.indexOf(plot) + //def getPlotIndex(plot: Plot): Int = PLOT.indexOf(plot) + def getPlotIndex(plot: Plot): Int = getPlots.indexOf(plot) def getPlot(index: Int): Plot = PLOT(index) def replacePlot(oldPlot: Plot, newPlot: Plot): Unit = { val idx = getPlotIndex(oldPlot) @@ -59,6 +60,15 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } private val initialMenu = new InitialMenu(this) + private var globalMenu: GlobalMenu = null + + def showGlobalMenu: Unit = { + if(globalMenu == null) { + globalMenu = new GlobalMenu(this) + scene.add(globalMenu.object3D) + } + globalMenu.setVisible(true) + } def toggleGuiVisibility: Unit = { Log.show("Toggle GUI visibility.") @@ -76,10 +86,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { scene.add(initialMenu.object3D) } else { - val i = data.length - 1 - val shadowManifold: ShadowManifold = ShadowManifold(data(i), Res.getLastLoadedTextureID, pointColor) - addPlot3DToRegion(shadowManifold) - plot2D(false) + Log.show("[Plotter] [setupData] Error: less than 3 columns in dataset.") } } @@ -101,7 +108,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { //val gui = DatGui(scatterPlot, regions(i).maybeGetAxes().get, this) val gui = new SettingsGui(scatterPlot, regions(i).maybeGetAxes().get, this) + //TODO Fix This addGUI(gui) + //TODO add Gui to Region //regions(i).gui = Some(gui) //regions(i).add(gui.object3D) scene.add(gui.object3D) @@ -112,6 +121,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { //gui.object3D.rotateY(3.14 / 4) + //TODO Fix This addPlot(scatterPlot) addAxes(regions(i).maybeGetAxes().get) //addGUI(gui) @@ -138,13 +148,8 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { def newShadowManifoldWithData(columnNumber: Int, tau: Int = 1): Plot = { val data = DATA(0) - val pointColor = CustomColors.BLUE_HUE_SHIFT - val scatterPlot: ScatterPlot = ScatterPlot(data, Res.getLastLoadedTextureID, pointColor) - scatterPlot.switchAxis(0, data(columnNumber), true) - scatterPlot.switchAxis(1, data(columnNumber), true) - scatterPlot.switchAxis(2, data(columnNumber), true) - val newSM: ShadowManifold = ShadowManifold.fromScatterPlot(scatterPlot)(tau, 0).get + val newSM: ShadowManifold = ShadowManifold(data(columnNumber), tau) newSM.fixScale() newSM.setVisiblePointRange(0, newSM.numPoints - 2 * tau) newSM.requestFullGeometryUpdate() @@ -194,6 +199,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { /*---- End New ----*/ + /* def plot2D3D(data: Array[Data], pointColor: Double = CustomColors.BLUE_HUE_SHIFT): Unit = { if (data.isEmpty) return DATA = DATA :+ data @@ -291,6 +297,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { addPlot(plot) addAxes(regions(i).maybeGetAxes().get) } + */ def update(): Unit = { for (r <- regions if r.maybeGetAxes().nonEmpty) { @@ -318,7 +325,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { def setVisiblePointRange(start: Int, end: Int): Unit = { - for(plot <- PLOT) { + for(plot <- getPlots) { plot match { //TODO Case for Plot3D case plot2D: TimeSeriesPlot2D => { @@ -345,7 +352,9 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { Log.show(s"Scale Change: $scaleChange") points.scale.setX(scaleChange * points.scale.x) } - case _: Any => + case otherPlot: Plot => { + otherPlot.setVisiblePointRange(start, end) + } } } } @@ -356,29 +365,23 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { if(columnIndex >= DATA(0).length) return Log.show("[requestAxisChange] getting axes from Plotter plotIndex = " + plotIndex) - val axes: CoordinateAxes = AXES(plotIndex) + //val axes: CoordinateAxes = AXES(plotIndex) + val axes: CoordinateAxes = getAxes(plotIndex) //val gui: DatGui = GUI(plotIndex) - var plot: Plot = null + var plot: Plot = getPlots(plotIndex) - Log.show("[requestAxisChange] matching PLOT(plotIndex)") - PLOT(plotIndex) match { + Log.show("[requestAxisChange] matching plot") + plot match { case sm: ShadowManifold ⇒ - val tau = sm.tau - val sp: ScatterPlot = ScatterPlot.fromShadowManifold(sm) - sp.switchAxis(axisID, DATA(0)(columnIndex)) // assuming a single data source - plot = ShadowManifold.fromScatterPlot(sp)(tau).get - PLOT(plotIndex) = plot - - case _: ScatterPlot ⇒ - plot = PLOT(plotIndex).asInstanceOf[ScatterPlot] - plot.asInstanceOf[ScatterPlot].switchAxis(axisID, DATA(0)(columnIndex)) // assuming a single data source - //gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) - - case _: ScatterPlot2D ⇒ - plot = PLOT(plotIndex).asInstanceOf[ScatterPlot2D] - plot.asInstanceOf[ScatterPlot2D].switchAxis(axisID, DATA(0)(columnIndex)) + sm.asInstanceOf[ShadowManifold].switchAxis(axisID, DATA(0)(columnIndex), sm.tau) + //sm.updateEmbedding() + case sp: ScatterPlot ⇒ + sp.asInstanceOf[ScatterPlot].switchAxis(axisID, DATA(0)(columnIndex)) // assuming a single data source + case sp2D: ScatterPlot2D ⇒ + sp2D.asInstanceOf[ScatterPlot2D].switchAxis(axisID, DATA(0)(columnIndex)) } + Log.show("[requestAxisChange] setting axis titles") //gui.updateFolderLabels(plot.xVar, plot.yVar, plot.zVar) plot match { case _: Plot3D => @@ -386,7 +389,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { case _: Plot2D => axes.asInstanceOf[CoordinateAxes2D].setAxesTitles(plot.xVar, plot.yVar) } - + Log.show("[requestAxisChange] done changing axes") /* // We set the new variable bound to the 3D Plots x axis to the 2D plots y axes @@ -396,6 +399,7 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } */ + /* Log.show("[requestAxisChange] Updating axis titles...") AXES(plotIndex) match { @@ -419,8 +423,26 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } } + */ } // -- eof + def requestEmbeddingUpdate(plot: Plot, columnIndex: Int, tau: Int): Unit = { + Log.show("[Plotter] [requestEmbeddingUpdate] columnIndex = " + columnIndex + " tau = " + tau) + plot match { + case sm: ShadowManifold => sm.switchAxis(XAxis, getData(columnIndex), tau) + case sp: ScatterPlot => { + val newPlot: Plot = newShadowManifoldWithData(columnIndex, tau) + newPlot.asInstanceOf[ShadowManifold].updateEmbedding(tau) + replacePlot(sp, newPlot) + } + } + + AXES(getPlotIndex(plot)) match { + case a2D: CoordinateAxes2D ⇒ a2D.setAxesTitles(plot.xVar, plot.yVar) + case a3D: CoordinateAxes3D ⇒ a3D.setAxesTitles(plot.xVar, plot.yVar, plot.asInstanceOf[ShadowManifold].zVar) + } + } + def requestEmbedding(axisID: AxisID, columnIndex: Int, tau: Int, plotIndex: Int = 0): Unit = { Log.show("[Plotter.requestEmbedding()]") @@ -459,7 +481,6 @@ class Plotter(scene: Scene, camera: Camera) extends ModelComponent[Action] { } } // -- eof - // Point highlighting and such def hoverAction(laser: InputDetails, select: Boolean): Unit = { diff --git a/src/main/scala/vrdv/obj3D/GlobalMenu.scala b/src/main/scala/vrdv/obj3D/GlobalMenu.scala new file mode 100644 index 0000000..fc6f517 --- /dev/null +++ b/src/main/scala/vrdv/obj3D/GlobalMenu.scala @@ -0,0 +1,96 @@ +package vrdv.obj3D + +import facade.Dat.GuiSlider +import vrdv.model.Plotter +import vrdv.input.InputDetails + +import scala.scalajs.js + + +/** + * Created by Wade McDonald 2018-11-01 + */ +class GlobalMenu(plotter: Plotter) + extends DatGuiW("Global Menu", 2, 1, 0) { + + object3D.rotation.y = -3.14 / 2.0 + + override def setVisible(vis: Boolean): Unit = super.setVisible(vis) + + def addPlot: Unit = { + if(object3D.visible) { + plotter.initPlot3DWithData + //setVisible(false) + //object3D.position.set(2, 1, 0) + //object3D.rotation.y = -3.14 / 2.0 + } + } + + //addButton(() => { addPlot }, "Create", "Graph 1") + //addButton(() => { addPlot }, "Create", "Graph 2") + //addButton(() => { addPlot }, "Create", "Graph 3") + + //Filter Folder + val filterRange: js.Object = js.Dynamic.literal( + "Start" → 0, + "End" → 0, + "Snap 10" → false, + "Snap 100" → false + ) + + def getRange: Range = { + val start = filterRange.asInstanceOf[js.Dynamic].selectDynamic("Start").asInstanceOf[Int] + val end = filterRange.asInstanceOf[js.Dynamic].selectDynamic("End").asInstanceOf[Int] + start to end + } + + val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) + filterFolder.addCheckbox(filterRange, "Snap 10", "Snap to 10").onChange(() => setFilterStep) + filterFolder.addCheckbox(filterRange, "Snap 100", "Snap to 100").onChange(() => setFilterStep) + val numPoints = plotter.getPlot(0).numPoints + val filterLowSlider: GuiSlider = filterFolder.object3D.add(filterRange, "Start", 0, numPoints - 1) + .step(getFilterStep).name("Start index").asInstanceOf[GuiSlider] + val filterHighSlider: GuiSlider = filterFolder.object3D.add(filterRange, "End", 0, numPoints - 1) + .step(getFilterStep).name("End index").asInstanceOf[GuiSlider] + filterFolder.addButton(() => applyFilter, "Filter", "Time Filter") + object3D.addFolder(filterFolder.object3D) + filterFolder.object3D.open() + + def setFilterStep: Unit = { + filterLowSlider.step(getFilterStep) + filterHighSlider.step(getFilterStep) + } + + def getFilterStep: Int = { + if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 100").asInstanceOf[Boolean]) 100 + else if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 10").asInstanceOf[Boolean]) 10 + else 1 + } + + def applyFilter = { + val range = getRange + plotter.setVisiblePointRange(range.start, range.end) + } + + //Raycaster Thresholds Folder + + val raycasterThresholds: js.Object = js.Dynamic.literal( + "Right" → 0.1, + "Left" → 0.1 + ) + + def getLeftThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Left").asInstanceOf[Float] + def getRightThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Right").asInstanceOf[Float] + + val rcThresholdFolder = new DatGuiW("Selection Sensitivity", 0, 0, 0) + rcThresholdFolder.object3D.add(raycasterThresholds, "Left", 0, 0.1).step(0.001).name("Left") + rcThresholdFolder.object3D.add(raycasterThresholds, "Right", 0, 0.1).step(0.001).name("Right") + rcThresholdFolder.addButton(() => InputDetails.updateThresholds(getLeftThreshold, getRightThreshold), + "Update!", "Apply Threshold") + object3D.addFolder(rcThresholdFolder.object3D) + //rcThresholdFolder.object3D.open() + + //Hide Gui Button + addButton(() => {plotter.toggleGuiVisibility}, "Hide", "Hide GUI") + +} \ No newline at end of file diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index 0c059b8..48608ab 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -1,6 +1,6 @@ package vrdv.obj3D -import facade.Dat.{GuiComponent, GuiDropdown} +import facade.Dat.{GuiComponent, GuiDropdown, GuiSlider} import util.Log import vrdv.model.Plotter @@ -18,9 +18,10 @@ class InitialMenu(plotter: Plotter) def addPlot: Unit = { if(object3D.visible) { plotter.initPlot3DWithData - //setVisible(false) - object3D.position.set(2, 1, 0) - object3D.rotation.y = -3.14 / 2.0 + if(plotter.getPlots.length == 3) setVisible(false) + //object3D.position.set(2, 1, 0) + //object3D.rotation.y = -3.14 / 2.0 + plotter.showGlobalMenu } } @@ -28,6 +29,6 @@ class InitialMenu(plotter: Plotter) addButton(() => { addPlot }, "Create", "Graph 2") addButton(() => { addPlot }, "Create", "Graph 3") - addButton(() => {plotter.toggleGuiVisibility}, "Hide", "Hide GUI") + //addButton(() => {plotter.toggleGuiVisibility}, "Hide", "Hide GUI") } \ No newline at end of file diff --git a/src/main/scala/vrdv/obj3D/Region.scala b/src/main/scala/vrdv/obj3D/Region.scala index 0617600..3571796 100644 --- a/src/main/scala/vrdv/obj3D/Region.scala +++ b/src/main/scala/vrdv/obj3D/Region.scala @@ -37,12 +37,15 @@ case class Region(id: Int, object3D: Object3D = new Object3D()) { // Remove previous plot if it exists and add the new one if(plot.nonEmpty) { remove(plot.get.getPoints) - Log.show("[Region] clearing region...") - for(c <- object3D.children) {object3D.remove(c)} + Log.show("[Region] clearing region " + id) + for(c <- object3D.children) {if(Option(c).isDefined) object3D.remove(c)} } + + Log.show(("[Region] Adding plot...")) plot = Some(p) object3D.add(p.getPoints) + Log.show(("[Region] Adding axes...")) maybeAxes = Some(axes) add(axes) } diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 747f8fa..02d5a62 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -20,18 +20,6 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) "TauTens" -> 0, "TauHundreds" -> 0) - val filterRange: js.Object = js.Dynamic.literal( - "Start" → 0, - "End" → 0, - "Snap 10" → false, - "Snap 100" → false - ) - - val raycasterThresholds: js.Object = js.Dynamic.literal( - "Right" → 0.1, - "Left" → 0.1 - ) - val axisData: js.Object = js.Dynamic.literal( "xAxis" → attachedPlot.xVar, "yAxis" → attachedPlot.yVar, @@ -48,15 +36,6 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauTens").asInstanceOf[Int] + rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauHundreds").asInstanceOf[Int] - def getRange: Range = { - val start = filterRange.asInstanceOf[js.Dynamic].selectDynamic("Start").asInstanceOf[Int] - val end = filterRange.asInstanceOf[js.Dynamic].selectDynamic("End").asInstanceOf[Int] - start to end - } - - def getLeftThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Left").asInstanceOf[Float] - def getRightThreshold: Float = raycasterThresholds.asInstanceOf[js.Dynamic].selectDynamic("Right").asInstanceOf[Float] - val graphTypeDropdown = addDropdown(plotType, "Graph Type", plotTypeOptions) .onChange(() => {Log.show("Graph type menu changed."); changeGraphType}) @@ -71,8 +50,6 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) val zCol = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("zAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot3DWithData(xCol, yCol, zCol)) attachedPlot = plotter.getPlot(plotIndex) - val range = getRange - //attachedPlot.setVisiblePointRange(range.start, range.end) xDropdown.visible = true yDropdown.visible = true zDropdown.visible = true @@ -81,18 +58,16 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("yAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot2DWithData(columnID)) attachedPlot = plotter.getPlot(plotIndex) - val range = getRange - //plotter.setVisiblePointRange(range.start, range.end) xDropdown.visible = false yDropdown.visible = true zDropdown.visible = false } case "Shadow Manifold" => { val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) - plotter.replacePlot(attachedPlot, plotter.newShadowManifoldWithData(columnID, getTau)) + val sm = plotter.newShadowManifoldWithData(columnID, getTau) + sm.asInstanceOf[ShadowManifold].updateEmbedding(getTau) + plotter.replacePlot(attachedPlot, sm) attachedPlot = plotter.getPlot(plotIndex) - val range = getRange - //plotter.setVisiblePointRange(range.start, range.end) xDropdown.visible = true yDropdown.visible = false zDropdown.visible = false @@ -107,17 +82,6 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) } } - /* - //Raycaster Thresholds Folder - val rcThresholdFolder = new DatGuiW("Selection Sensitivity", 0, 0, 0) - rcThresholdFolder.object3D.add(raycasterThresholds, "Left", 0, 0.1).step(0.001).name("Left") - rcThresholdFolder.object3D.add(raycasterThresholds, "Right", 0, 0.1).step(0.001).name("Right") - rcThresholdFolder.addButton(() => InputDetails.updateThresholds(getLeftThreshold, getRightThreshold), - "Update!", "Apply Threshold") - object3D.addFolder(rcThresholdFolder.object3D) - //rcThresholdFolder.object3D.open() - */ - //Axes Folder val axesFolder = new DatGuiW("Select Data", 0,0,0) var axisTitles: js.Array[String] = js.Array() @@ -146,52 +110,23 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) embeddingFolder.object3D.add(rawTau, "TauOnes", 0, 10).step(1).name("Tau Ones") embeddingFolder.object3D.add(rawTau, "TauTens", 0, 90).step(10).name("Tau Tens") embeddingFolder.object3D.add(rawTau, "TauHundreds", 0, 900).step(100).name("Tau Hundreds") - embeddingFolder.addButton(() => plot match { - case sm: ShadowManifold ⇒ plotter.requestEmbedding(XAxis, sm.data.columnNumber, getTau)//, 1) - case sp: ScatterPlot ⇒ plotter.requestEmbedding(XAxis, sp.viewing(XAxis), getTau)//, 1) - }, "Embed!", "Embed Shadow Manifold") + embeddingFolder.addButton(() => updateEmbedding, "Embed!", "Embed Shadow Manifold") object3D.addFolder(embeddingFolder.object3D) embeddingFolder.object3D.open() - //Filter Folder - val filterFolder = new DatGuiW("Time Filter", 0, 0, 0) - filterFolder.addCheckbox(filterRange, "Snap 10", "Snap to 10").onChange(() => setFilterStep) - filterFolder.addCheckbox(filterRange, "Snap 100", "Snap to 100").onChange(() => setFilterStep) - val filterLowSlider: GuiSlider = filterFolder.object3D.add(filterRange, "Start", 0, attachedPlot.numPoints - 1) - .step(getFilterStep).name("Start index").asInstanceOf[GuiSlider] - val filterHighSlider: GuiSlider = filterFolder.object3D.add(filterRange, "End", 0, attachedPlot.numPoints - 1) - .step(getFilterStep).name("End index").asInstanceOf[GuiSlider] - filterFolder.addButton(() => applyFilter, "Filter", "Time Filter") - object3D.addFolder(filterFolder.object3D) - filterFolder.object3D.open() - - def setFilterStep: Unit = { - filterLowSlider.step(getFilterStep) - filterHighSlider.step(getFilterStep) + def updateEmbedding: Unit = { + Log.show("[SettingsGui] Updating embedding...") + val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) + plotter.requestEmbeddingUpdate(attachedPlot, columnID, getTau) } - def getFilterStep: Int = { - if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 100").asInstanceOf[Boolean]) 100 else - if(filterRange.asInstanceOf[js.Dynamic].selectDynamic("Snap 10").asInstanceOf[Boolean]) 10 else 1 - } - def applyFilter = { - attachedPlot match { - case sp3d: ScatterPlot ⇒ - val range = getRange - sp3d.setVisiblePointRange(range.start, range.end) - plotter.setVisiblePointRange(range.start, range.end) - case _: ScatterPlot2D => - val range = getRange - plotter.setVisiblePointRange(range.start, range.end) - case sm: ShadowManifold ⇒ - } - } //Reset button //TODO Reset Button //addButton(() => resetToDefaults, "Reset", "Reset to Defaults") + /* def resetToDefaults = { //TODO needs work: controls don't reset display Log.show("Reset to Defaults Button pressed.") @@ -205,4 +140,5 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) plotter.requestAxisChange(plotIndex, 1, 1) plotter.requestAxisChange(plotIndex, 2, 2) } + */ } diff --git a/src/main/scala/vrdv/obj3D/plots/ShadowManifold.scala b/src/main/scala/vrdv/obj3D/plots/ShadowManifold.scala index 0181900..8bdf2ad 100644 --- a/src/main/scala/vrdv/obj3D/plots/ShadowManifold.scala +++ b/src/main/scala/vrdv/obj3D/plots/ShadowManifold.scala @@ -1,7 +1,8 @@ package vrdv.obj3D.plots -import resources.Data +import resources.{Data, Res} import util.{Log, ScaleCenterProperties, Stats} +import vrdv.obj3D.CustomColors import scala.scalajs.js import scala.scalajs.js.typedarray.Float32Array @@ -49,9 +50,45 @@ case class ShadowManifold(var data: Data, var tau: Int, var scp: ScaleCenterProp scp = PointOperations.confineToRegion3D(points, (minX, minY, minZ), (maxX, maxY, maxZ)) } + + def switchAxis(axisID: AxisID, newColumn: Data, newTau: Int): Unit = { + assert(axisID == XAxis, s"[ShadowManifold] [switchAxis] - Attempted switching invalid axis: $axisID") + Log.show("[ShadowManifold] [switchAxis]") + varName = newColumn.id + data = newColumn + + tau = newTau + + updateEmbedding(tau) + } + + def updateEmbedding(newTau: Int): Unit = { + Log.show("[ShadowManifold] [updateEmbedding] tau = " + tau + ", newTau = " + newTau) + val positionsAttr = PointsUtils.positions(getPoints) + val positionsArr = positionsAttr.array.asInstanceOf[Float32Array] + + val firstIndex = 2 * newTau // (E - 1) * Tau + if(firstIndex >= positionsArr.length*3) { + Log.show("[ShadowManifold] [updateEmbedding] tau too high to generate shadow manifold") + return + } // Hard fail - tau too high to generate shadow manifold + for(pointIndex <- firstIndex until varValues.length) { + for(dimension <- 0 to 2) positionsArr((pointIndex - firstIndex)*3 + dimension) = varValues(pointIndex - newTau*dimension).toFloat + } + + Log.show(s"[ShadowManifold] [updateEmbedding] Shadow Manifold made with variable[$varName] with newTau $newTau has ${varValues.length - firstIndex} points.") + + fixScale() + + getPositions.needsUpdate = true + requestFullGeometryUpdate() + } } object ShadowManifold { + def apply(data: Data, tau: Int): ShadowManifold = { + apply(data, Res.getLastLoadedTextureID, CustomColors.BLUE_HUE_SHIFT, tau) + } def apply(data: Data, texture: Int, hue: Double, tau: Int = 1): ShadowManifold = { val (points, props, vStats): (Points, ScaleCenterProperties, Array[Stats]) = PointsBuilder() diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 61dcdea..3f7ba15 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - //renderer.vr.enabled = true + renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From b641b26ce28234750767ab35ab763cbcca693a2c Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Mon, 19 Nov 2018 14:18:01 -0600 Subject: [PATCH 26/28] Switching folders but UI is unresponsive after change. --- src/main/scala/vrdv/obj3D/SettingsGui.scala | 71 +++++++++++++++++---- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 02d5a62..180bed2 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -2,7 +2,7 @@ package vrdv.obj3D import facade.Dat._ import util.Log -import vrdv.input.InputDetails +import vrdv.input._ import vrdv.model.Plotter import vrdv.obj3D.plots._ @@ -50,17 +50,13 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) val zCol = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("zAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot3DWithData(xCol, yCol, zCol)) attachedPlot = plotter.getPlot(plotIndex) - xDropdown.visible = true - yDropdown.visible = true - zDropdown.visible = true + updateFoldersForGraphType("3D Scatter") } case "2D Scatter" => { val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("yAxis")) plotter.replacePlot(attachedPlot, plotter.newPlot2DWithData(columnID)) attachedPlot = plotter.getPlot(plotIndex) - xDropdown.visible = false - yDropdown.visible = true - zDropdown.visible = false + updateFoldersForGraphType("2D Scatter") } case "Shadow Manifold" => { val columnID = axisTitles.indexOf(axisData.asInstanceOf[js.Dynamic].selectDynamic("xAxis")) @@ -68,9 +64,7 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) sm.asInstanceOf[ShadowManifold].updateEmbedding(getTau) plotter.replacePlot(attachedPlot, sm) attachedPlot = plotter.getPlot(plotIndex) - xDropdown.visible = true - yDropdown.visible = false - zDropdown.visible = false + updateFoldersForGraphType("Shadow Manifold") /* AXES(plotIndex) match { @@ -82,7 +76,47 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) } } - //Axes Folder + def updateFoldersForGraphType(graphType: String = "3D Scatter"): Unit = { + //Remove any folders currently in the Gui + if(axesFolder.object3D.parent != null) { + axesFolder.object3D.parent.remove(axesFolder.object3D) + } + if(axesFolderXOnly.object3D.parent != null) { + axesFolderXOnly.object3D.parent.remove(axesFolderXOnly.object3D) + } + if(axesFolderYOnly.object3D.parent != null) { + axesFolderYOnly.object3D.parent.remove(axesFolderYOnly.object3D) + } + if(embeddingFolder.object3D.parent != null) { + embeddingFolder.object3D.parent.remove(embeddingFolder.object3D) + } + + //setup correct folders for graph type + graphType match { + case "3D Scatter" => + object3D.addFolder(axesFolder.object3D) + axesFolder.object3D.open() + + case "2D Scatter" => + object3D.addFolder(axesFolderYOnly.object3D) + axesFolderYOnly.object3D.close() + axesFolderYOnly.object3D.open() + + case "Shadow Manifold" => { + object3D.addFolder(axesFolderXOnly.object3D) + axesFolderXOnly.object3D.open() + object3D.addFolder(embeddingFolder.object3D) + embeddingFolder.object3D.open() + } + } + + object3D.close() + object3D.open() + + + } + + //Axes Folder XYZ val axesFolder = new DatGuiW("Select Data", 0,0,0) var axisTitles: js.Array[String] = js.Array() for(d <- plotter.getData.map(_.id)) axisTitles = axisTitles :+ d @@ -90,9 +124,20 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) val yDropdown = axesFolder.addDropdown(axisData, "yAxis", axisTitles).onChange(() => callForAxisUpdate(1)) val zDropdown = axesFolder.addDropdown(axisData, "zAxis", axisTitles).onChange(() => callForAxisUpdate(2)) object3D.addFolder(axesFolder.object3D) - axesFolder.object3D.open() + //Axes Folder X Only + val axesFolderXOnly = new DatGuiW("Select Data", 0,0,0) + axesFolderXOnly.addDropdown(axisData, "xAxis", axisTitles).onChange(() => callForAxisUpdate(0)) + //object3D.addFolder(axesFolderXOnly.object3D) + axesFolderXOnly.object3D.open() + + //Axes Folder Y Only + val axesFolderYOnly = new DatGuiW("Select Data", 0,0,0) + axesFolderYOnly.addDropdown(axisData, "yAxis", axisTitles).onChange(() => callForAxisUpdate(1)) + //object3D.addFolder(axesFolderYOnly.object3D) + axesFolderYOnly.object3D.open() + def callForAxisUpdate(id: Int): Unit = { val axisString = id match { case 0 => "xAxis" @@ -111,7 +156,7 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) embeddingFolder.object3D.add(rawTau, "TauTens", 0, 90).step(10).name("Tau Tens") embeddingFolder.object3D.add(rawTau, "TauHundreds", 0, 900).step(100).name("Tau Hundreds") embeddingFolder.addButton(() => updateEmbedding, "Embed!", "Embed Shadow Manifold") - object3D.addFolder(embeddingFolder.object3D) + //object3D.addFolder(embeddingFolder.object3D) embeddingFolder.object3D.open() def updateEmbedding: Unit = { diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 3f7ba15..61dcdea 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - renderer.vr.enabled = true + //renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR) From 5bedf578baf647c3412c5eda232fe36443a41121 Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Mon, 19 Nov 2018 19:01:25 -0600 Subject: [PATCH 27/28] Ready for demo? --- src/main/scala/vrdv/obj3D/InitialMenu.scala | 4 +- src/main/scala/vrdv/obj3D/SettingsGui.scala | 49 ++++++++++++++------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/main/scala/vrdv/obj3D/InitialMenu.scala b/src/main/scala/vrdv/obj3D/InitialMenu.scala index 48608ab..d74aa9a 100644 --- a/src/main/scala/vrdv/obj3D/InitialMenu.scala +++ b/src/main/scala/vrdv/obj3D/InitialMenu.scala @@ -19,8 +19,8 @@ class InitialMenu(plotter: Plotter) if(object3D.visible) { plotter.initPlot3DWithData if(plotter.getPlots.length == 3) setVisible(false) - //object3D.position.set(2, 1, 0) - //object3D.rotation.y = -3.14 / 2.0 + object3D.position.set(-2, 1, 1) + object3D.rotation.y = 3.14 / 2.0 plotter.showGlobalMenu } } diff --git a/src/main/scala/vrdv/obj3D/SettingsGui.scala b/src/main/scala/vrdv/obj3D/SettingsGui.scala index 180bed2..8dca54f 100644 --- a/src/main/scala/vrdv/obj3D/SettingsGui.scala +++ b/src/main/scala/vrdv/obj3D/SettingsGui.scala @@ -11,7 +11,7 @@ import scala.scalajs.js class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) extends DatGuiW("Graph Settings", axes.position.x - 2.0, axes.position.y + 2.0, axes.position.z){ - var attachedPlot = plot + var attachedPlot: Plot = plot override def setVisible(vis: Boolean): Unit = super.setVisible(vis) @@ -37,9 +37,9 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) rawTau.asInstanceOf[js.Dynamic].selectDynamic("TauHundreds").asInstanceOf[Int] val graphTypeDropdown = addDropdown(plotType, "Graph Type", plotTypeOptions) - .onChange(() => {Log.show("Graph type menu changed."); changeGraphType}) + .onChange(() => {Log.show("Graph type menu changed."); changeGraphType()}) - def changeGraphType: Unit = { + def changeGraphType(): Unit = { val gtString = plotType.asInstanceOf[js.Dynamic].selectDynamic("Graph Type").asInstanceOf[String] val plotIndex = plotter.getPlotIndex(attachedPlot) @@ -78,6 +78,7 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) def updateFoldersForGraphType(graphType: String = "3D Scatter"): Unit = { //Remove any folders currently in the Gui + /* if(axesFolder.object3D.parent != null) { axesFolder.object3D.parent.remove(axesFolder.object3D) } @@ -90,22 +91,40 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) if(embeddingFolder.object3D.parent != null) { embeddingFolder.object3D.parent.remove(embeddingFolder.object3D) } + */ //setup correct folders for graph type graphType match { - case "3D Scatter" => - object3D.addFolder(axesFolder.object3D) - axesFolder.object3D.open() + case "3D Scatter" => { + //object3D.addFolder(axesFolder.object3D) + //axesFolder.object3D.open() + xDropdown.visible = true + yDropdown.visible = true + zDropdown.visible = true + embeddingFolder.setVisible(false) + embeddingFolder.object3D.close() + } - case "2D Scatter" => - object3D.addFolder(axesFolderYOnly.object3D) - axesFolderYOnly.object3D.close() - axesFolderYOnly.object3D.open() + case "2D Scatter" => { + //object3D.addFolder(axesFolderYOnly.object3D) + //axesFolderYOnly.object3D.close() + //axesFolderYOnly.object3D.open() + xDropdown.visible = false + yDropdown.visible = true + zDropdown.visible = false + embeddingFolder.setVisible(false) + embeddingFolder.object3D.close() + } case "Shadow Manifold" => { - object3D.addFolder(axesFolderXOnly.object3D) - axesFolderXOnly.object3D.open() - object3D.addFolder(embeddingFolder.object3D) + //object3D.addFolder(axesFolderXOnly.object3D) + //axesFolderXOnly.object3D.open() + //object3D.addFolder(embeddingFolder.object3D) + //embeddingFolder.object3D.open() + xDropdown.visible = true + yDropdown.visible = false + zDropdown.visible = false + embeddingFolder.setVisible(true) embeddingFolder.object3D.open() } } @@ -156,8 +175,8 @@ class SettingsGui(plot: Plot, axes: CoordinateAxes, plotter: Plotter) embeddingFolder.object3D.add(rawTau, "TauTens", 0, 90).step(10).name("Tau Tens") embeddingFolder.object3D.add(rawTau, "TauHundreds", 0, 900).step(100).name("Tau Hundreds") embeddingFolder.addButton(() => updateEmbedding, "Embed!", "Embed Shadow Manifold") - //object3D.addFolder(embeddingFolder.object3D) - embeddingFolder.object3D.open() + object3D.addFolder(embeddingFolder.object3D) + embeddingFolder.object3D.close() def updateEmbedding: Unit = { Log.show("[SettingsGui] Updating embedding...") From 3c6445a675cc8d39d1172ba501036e49cb862b2f Mon Sep 17 00:00:00 2001 From: Wade McDonald Date: Mon, 26 Nov 2018 10:19:20 -0600 Subject: [PATCH 28/28] Ready for Testing --- src/main/scala/vrdv/view/ViewManager.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vrdv/view/ViewManager.scala b/src/main/scala/vrdv/view/ViewManager.scala index 61dcdea..3f7ba15 100644 --- a/src/main/scala/vrdv/view/ViewManager.scala +++ b/src/main/scala/vrdv/view/ViewManager.scala @@ -28,7 +28,7 @@ private[vrdv] class ViewManager(mc: RenderRequirements) extends SuppliesRenderer renderer.devicePixelRatio = window.devicePixelRatio //Comment out the next line to use keyboard controls in browser - VR will not work - //renderer.vr.enabled = true + renderer.vr.enabled = true renderer.vr.setAnimationLoop(renderVR) dom.window.requestAnimationFrame(renderNonVR)