001//License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside.gui.imageinfo; 003 004import org.openstreetmap.josm.plugins.streetside.cubemap.CameraTransformer; 005import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBox; 006 007import javafx.application.Platform; 008import javafx.embed.swing.JFXPanel; 009import javafx.scene.Group; 010import javafx.scene.PerspectiveCamera; 011import javafx.scene.PointLight; 012import javafx.scene.Scene; 013import javafx.scene.control.Label; 014import javafx.scene.SceneAntialiasing; 015import javafx.scene.control.TextArea; 016import javafx.scene.image.Image; 017import javafx.scene.input.KeyCode; 018import javafx.scene.input.MouseEvent; 019import javafx.scene.layout.VBox; 020import javafx.scene.paint.Color; 021import javafx.scene.text.Font; 022import javafx.scene.text.FontWeight; 023 024@SuppressWarnings("restriction") 025public class ThreeSixtyDegreeViewerPanel extends JFXPanel { 026 027 private static final long serialVersionUID = -4940350009018422000L; 028 029 private static Scene cubemapScene; 030 031 private static Scene defaultScene; 032 private static Scene loadingScene; 033 034 private static Group root; 035 private static Group subGroup; 036 private static CubemapBox cubemapBox; 037 private static PerspectiveCamera camera; 038 private static CameraTransformer cameraTransform = new CameraTransformer(); 039 040 private static double mousePosX; 041 private static double mousePosY; 042 private static double mouseOldX; 043 private static double mouseOldY; 044 private static double mouseDeltaX; 045 private static double mouseDeltaY; 046 private static double cameraDistance = 5000; 047 048 private static Image front; 049 private static Image right; 050 private static Image back; 051 private static Image left; 052 private static Image up; 053 private static Image down; 054 055 public ThreeSixtyDegreeViewerPanel() { 056 057 } 058 059 public void initialize() { 060 061 root = new Group(); 062 063 camera = new PerspectiveCamera(true); 064 cameraTransform.setTranslate(0, 0, 0); 065 cameraTransform.getChildren().addAll(camera); 066 camera.setNearClip(0.1); 067 camera.setFarClip(1000000.0); 068 camera.setFieldOfView(42); 069 camera.setTranslateZ(-cameraDistance); 070 final PointLight light = new PointLight(Color.WHITE); 071 072 cameraTransform.getChildren().add(light); 073 light.setTranslateX(camera.getTranslateX()); 074 light.setTranslateY(camera.getTranslateY()); 075 light.setTranslateZ(camera.getTranslateZ()); 076 077 root.getChildren().add(cameraTransform); 078 079 final double size = 100000D; 080 081 cubemapBox = new CubemapBox(front, right, back, left, up, down, size, camera); 082 083 subGroup = new Group(); 084 subGroup.getChildren().add(cameraTransform); 085 086 createLoadingScene(); 087 088 Platform.runLater(new Runnable() { 089 @Override 090 public void run() { 091 setScene(createDefaultScene()); 092 } 093 }); 094 } 095 096 private static Scene createDefaultScene() { 097 098 TextArea textArea = new TextArea(); 099 textArea.setText("No Streetside image selected."); 100 101 VBox vbox = new VBox(textArea); 102 103 root = new Group(); 104 105 camera = new PerspectiveCamera(true); 106 cameraTransform.setTranslate(0, 0, 0); 107 cameraTransform.getChildren().addAll(camera); 108 camera.setNearClip(0.1); 109 camera.setFarClip(1000000.0); 110 camera.setFieldOfView(42); 111 camera.setTranslateZ(-cameraDistance); 112 final PointLight light = new PointLight(Color.WHITE); 113 114 cameraTransform.getChildren().add(light); 115 light.setTranslateX(camera.getTranslateX()); 116 light.setTranslateY(camera.getTranslateY()); 117 light.setTranslateZ(camera.getTranslateZ()); 118 119 root.getChildren().add(cameraTransform); 120 121 final double size = 100000D; 122 123 cubemapBox = new CubemapBox(null, null, null, null, null, null, size, camera); 124 125 subGroup = new Group(); 126 subGroup.getChildren().add(cameraTransform); 127 128 cubemapScene = new Scene(new Group(root), 1024, 668, true, SceneAntialiasing.BALANCED); 129 cubemapScene.setFill(Color.TRANSPARENT); 130 cubemapScene.setCamera(camera); 131 132 cubemapScene.setOnKeyPressed(event -> { 133 double change = 10.0; 134 if (event.isShiftDown()) { 135 change = 50.0; 136 } 137 final KeyCode keycode = event.getCode(); 138 139 if (keycode == KeyCode.W) { 140 camera.setTranslateZ(camera.getTranslateZ() + change); 141 } 142 if (keycode == KeyCode.S) { 143 camera.setTranslateZ(camera.getTranslateZ() - change); 144 } 145 146 if (keycode == KeyCode.A) { 147 camera.setTranslateX(camera.getTranslateX() - change); 148 } 149 if (keycode == KeyCode.D) { 150 camera.setTranslateX(camera.getTranslateX() + change); 151 } 152 }); 153 154 cubemapScene.setOnMousePressed((MouseEvent me) -> { 155 mousePosX = me.getSceneX(); 156 mousePosY = me.getSceneY(); 157 mouseOldX = me.getSceneX(); 158 mouseOldY = me.getSceneY(); 159 }); 160 cubemapScene.setOnMouseDragged((MouseEvent me) -> { 161 mouseOldX = mousePosX; 162 mouseOldY = mousePosY; 163 mousePosX = me.getSceneX(); 164 mousePosY = me.getSceneY(); 165 mouseDeltaX = mousePosX - mouseOldX; 166 mouseDeltaY = mousePosY - mouseOldY; 167 168 double modifier = 10.0; 169 final double modifierFactor = 0.1; 170 171 if (me.isControlDown()) { 172 modifier = 0.1; 173 } 174 if (me.isShiftDown()) { 175 modifier = 50.0; 176 } 177 if (me.isPrimaryButtonDown()) { 178 cameraTransform.ry.setAngle( 179 ((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180 180 ); // + 181 cameraTransform.rx.setAngle( 182 ((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540) % 360 - 180 183 ); // - 184 185 } else if (me.isSecondaryButtonDown()) { 186 final double z = camera.getTranslateZ(); 187 final double newZ = z + mouseDeltaX * modifierFactor * modifier; 188 camera.setTranslateZ(newZ); 189 } else if (me.isMiddleButtonDown()) { 190 cameraTransform.t.setX(cameraTransform.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3); // - 191 cameraTransform.t.setY(cameraTransform.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3); // - 192 } 193 }); 194 195 root.getChildren().addAll(cubemapBox, subGroup); 196 root.setAutoSizeChildren(true); 197 198 subGroup.setAutoSizeChildren(true); 199 200 // prevent content from disappearing after resizing 201 Platform.setImplicitExit(false); 202 203 defaultScene = new Scene(vbox, 200, 100); 204 return defaultScene; 205 } 206 207 private static void createLoadingScene() { 208 Label label = new Label(" Loading..."); 209 label.setFont(Font.font(null, FontWeight.BOLD, 14)); 210 VBox vbox = new VBox(label); 211 loadingScene = new Scene(vbox, 200, 100); 212 } 213 214 public CubemapBox getCubemapBox() { 215 if (cubemapBox == null) { 216 // shouldn't happen 217 initialize(); 218 } 219 return cubemapBox; 220 } 221 222 public Scene getDefaultScene() { 223 return defaultScene; 224 } 225 226 public Scene getCubemapScene() { 227 return cubemapScene; 228 } 229 230 public Scene getLoadingScene() { 231 return loadingScene; 232 } 233}