import javafx.animation.Interpolator; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.animation.TimelineBuilder; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.scene.Parent; import javafx.scene.input.MouseEvent; import javafx.scene.transform.Rotate; import javafx.scene.transform.RotateBuilder; import javafx.scene.transform.TranslateBuilder; import javafx.util.Duration; import javafxpert.cube.FaceType; public class PhotoNode extends Parent { double dragPressedAngleX; double dragPressedAngleY; double dragStartOffsetX; double dragStartOffsetY; PhotoFace rearFace; PhotoFace bottomFace; PhotoFace leftFace; PhotoFace rightFace; PhotoFace topFace; PhotoFace frontFace; SimpleDoubleProperty angleX = new SimpleDoubleProperty(0); SimpleDoubleProperty angleY = new SimpleDoubleProperty(0); public PhotoNode() { angleX.addListener(new InvalidationListener() { @Override public void invalidated(Observable ov) { arrangeFacesZOrder(); } }); angleY.addListener(new ChangeListener<Object>() { public void changed(ObservableValue<?> ov, Object oldValue, Object newValue) { arrangeFacesZOrder(); } }); rearFace = new PhotoFace(FaceType.REAR); rearFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(PhotoFace.edgeLength) .build(), RotateBuilder.create().angle(180.0).axis(Rotate.Y_AXIS) .pivotX(PhotoFace.edgeLength / 2).build()); bottomFace = new PhotoFace(FaceType.BOTTOM); bottomFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(PhotoFace.edgeLength) .build(), RotateBuilder.create().angle(90.0).axis(Rotate.X_AXIS) .pivotY(PhotoFace.edgeLength).build()); leftFace = new PhotoFace(FaceType.LEFT); leftFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(PhotoFace.edgeLength) .build(), RotateBuilder.create().angle(90.0).axis(Rotate.Y_AXIS) .pivotX(0).build()); rightFace = new PhotoFace(FaceType.RIGHT); rightFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(PhotoFace.edgeLength) .build(), RotateBuilder.create().angle(-90.0).axis(Rotate.Y_AXIS) .pivotX(PhotoFace.edgeLength).build()); topFace = new PhotoFace(FaceType.TOP); topFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(PhotoFace.edgeLength) .build(), RotateBuilder.create().angle(-90.0).axis(Rotate.X_AXIS) .pivotX(0).build()); frontFace = new PhotoFace(FaceType.FRONT); frontFace.getTransforms().setAll( TranslateBuilder.create().x(0).y(0).z(0).build()); getChildren().addAll(rearFace, topFace, leftFace, rightFace, bottomFace, frontFace); Rotate xRotate; Rotate yRotate; getTransforms().setAll( xRotate = RotateBuilder.create().axis(Rotate.X_AXIS) .pivotX(PhotoFace.edgeLength * 0.5) .pivotY(PhotoFace.edgeLength * 0.5) .pivotZ(PhotoFace.edgeLength * 0.5).build(), yRotate = RotateBuilder.create().axis(Rotate.Y_AXIS) .pivotX(PhotoFace.edgeLength * 0.5) .pivotY(PhotoFace.edgeLength * 0.5) .pivotZ(PhotoFace.edgeLength * 0.5).build()); xRotate.angleProperty().bind(angleX); yRotate.angleProperty().bind(angleY); this.setOnMousePressed(new EventHandler<MouseEvent>() { public void handle(MouseEvent me) { dragPressedAngleX = angleX.getValue(); dragPressedAngleY = angleY.getValue(); dragStartOffsetX = me.getScreenX() - getScene().getWindow().getX(); dragStartOffsetY = me.getScreenY() - getScene().getWindow().getY(); } }); this.setOnMouseDragged(new EventHandler<MouseEvent>() { public void handle(MouseEvent me) { angleY.setValue((((me.getScreenX() - getScene().getWindow() .getX()) - dragStartOffsetX)) / 3 * -1 + dragPressedAngleY); angleX.setValue((((me.getScreenY() - getScene().getWindow() .getY()) - dragStartOffsetY)) / 3 + dragPressedAngleX); } }); goHomePosition(); } final void arrangeFacesZOrder() { rearFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleY.getValue() + 0))); bottomFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleX.getValue() + 270))); leftFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleY.getValue() + 270))); rightFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleY.getValue() + 90))); topFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleX.getValue() + 90))); frontFace.zPos.setValue(PhotoFace.radius * Math.cos(Math.toRadians(angleY.getValue() + 180))); } public void goHomePosition() { Timeline homeTimeline = TimelineBuilder .create() .keyFrames( new KeyFrame(new Duration(1000.0), new KeyValue(angleX, 30, Interpolator.EASE_BOTH), new KeyValue( angleY, -40, Interpolator.EASE_BOTH))).build(); homeTimeline.play(); } }