/*
* CubeFace.java
*
* Represents a face on the CubeNode UI component.
*
* Developed by James L. Weaver (jim.weaver#javafxpert.com) to demonstrate the
* use of 3D features in the JavaFX 2.0 API
*/
package javafxpert.cube;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.effect.PerspectiveTransformBuilder;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.ImageViewBuilder;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.TilePaneBuilder;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafxpert.model.CubeModel;
/**
*
* @author Jim Weaver
*/
public class CubeFace extends Parent {
static double FACE_HUE = 211;
static double FACE_SAT = 0.25;
static int FRONT_FACE = 1;
static int RIGHT_FACE = 2;
static int REAR_FACE = 3;
static int LEFT_FACE = 0;
static int TOP_FACE = 4;
static int BOTTOM_FACE = 5;
public static double edgeLength = 512;
public static double radius = edgeLength * 0.5;
CubeModel cubeModel = CubeModel.instance;
Rectangle faceRect;
Node node;
SimpleDoubleProperty zPos = new SimpleDoubleProperty(0);
public CubeFace(CubeModel model, int face) {
getChildren().addAll(createFaceRectangle(), createMapTiles(face));
zPos.addListener(new ChangeListener<Object>() {
public void changed(ObservableValue<?> ov, Object oldValue,
Object newValue) {
faceRect.setFill(computeFaceHSB());
}
});
}
final Rectangle createFaceRectangle() {
faceRect = RectangleBuilder.create().width(edgeLength)
.height(edgeLength).fill(Color.TRANSPARENT).build();
return faceRect;
}
Node createMapTiles(int face) {
if (face == FRONT_FACE || face == RIGHT_FACE || face == REAR_FACE
|| face == LEFT_FACE) {
return createSideMapTiles(face);
} else if (face == TOP_FACE) {
StackPane stackPane = StackPaneBuilder.create().build();
for (int side = 0; side <= 3; side++) {
stackPane.getChildren().add(createTopMapTiles(side));
}
ImageView mapTile = ImageViewBuilder
.create()
.image(new Image(
"http://mt3.google.com/vt/v=w2.97&x=2&y=8&z=4"))
.fitWidth(CubeFace.edgeLength / 4)
.fitHeight(CubeFace.edgeLength / 4).build();
mapTile.opacityProperty().bind(cubeModel.mapOpacity);
stackPane.getChildren().add(mapTile);
return stackPane;
} else if (face == BOTTOM_FACE) {
StackPane stackPane = StackPaneBuilder.create().build();
for (int side = 0; side <= 3; side++) {
stackPane.getChildren().add(createBottomMapTiles(side));
}
ImageView mapTile = ImageViewBuilder
.create()
.image(new Image(
"http://mt3.google.com/vt/v=w2.97&x=2&y=15&z=4"))
.fitWidth(CubeFace.edgeLength / 4)
.fitHeight(CubeFace.edgeLength / 4).build();
mapTile.opacityProperty().bind(cubeModel.mapOpacity);
stackPane.getChildren().add(mapTile);
return stackPane;
} else {
return null;
}
}
Node createSideMapTiles(int sideNum) {
TilePane tilePane;
int xOffset = sideNum * 2;
tilePane = TilePaneBuilder.create().prefColumns(2).prefRows(2).build();
for (int y = 3; y <= 4; y++) {
for (int x = xOffset; x <= xOffset + 1; x++) {
int xm = (x + 1) % 8;
ImageView mapTile = ImageViewBuilder
.create()
.image(new Image("http://mt3.google.com/vt/v=w2.97&x="
+ xm + "&y=" + y + "&z=3"))
.fitWidth(CubeFace.edgeLength / 2)
.fitHeight(CubeFace.edgeLength / 2).build();
mapTile.opacityProperty().bind(cubeModel.mapOpacity);
tilePane.getChildren().add(mapTile);
}
}
return tilePane;
}
Node createTopMapTiles(int sideNum) {
TilePane tilePane;
int xOffset = sideNum * 2;
tilePane = TilePaneBuilder
.create()
.rotate((450 - sideNum * 90) % 360)
.prefColumns(2)
.prefRows(3)
.effect(PerspectiveTransformBuilder.create()
.ulx(edgeLength * 0.375).uly(edgeLength * 0.625)
.urx(edgeLength * 0.625).ury(edgeLength * 0.625).llx(0)
.lly(edgeLength).lrx(edgeLength).lry(edgeLength)
.build()).build();
for (int y = 0; y <= 2; y++) {
for (int x = xOffset; x <= xOffset + 1; x++) {
int xm = (x + 1) % 8;
ImageView mapTile = ImageViewBuilder
.create()
.image(new Image("http://mt3.google.com/vt/v=w2.97&x="
+ xm + "&y=" + y + "&z=3"))
.fitWidth(CubeFace.edgeLength / 2)
.fitHeight(CubeFace.edgeLength / 3).build();
mapTile.opacityProperty().bind(cubeModel.mapOpacity);
tilePane.getChildren().add(mapTile);
}
}
return tilePane;
}
Node createBottomMapTiles(int sideNum) {
TilePane tilePane;
int xOffset = (sideNum + 1) * 2;
tilePane = TilePaneBuilder
.create()
.rotate((sideNum * 90) % 360)
.prefColumns(2)
.prefRows(3)
.effect(PerspectiveTransformBuilder.create().ulx(0).uly(0)
.urx(edgeLength).ury(0).llx(edgeLength * 0.375)
.lly(edgeLength * 0.375).lrx(edgeLength * 0.625)
.lry(edgeLength * 0.375).build()).build();
for (int y = 5; y <= 7; y++) {
for (int x = xOffset; x <= xOffset + 1; x++) {
int xm = (x + 1) % 8;
ImageView mapTile = ImageViewBuilder
.create()
.image(new Image("http://mt3.google.com/vt/v=w2.97&x="
+ xm + "&y=" + y + "&z=3"))
.fitWidth(CubeFace.edgeLength / 2)
.fitHeight(CubeFace.edgeLength / 3).build();
mapTile.opacityProperty().bind(cubeModel.mapOpacity);
tilePane.getChildren().add(mapTile);
}
}
return tilePane;
}
Paint computeFaceHSB() {
Paint color = Color.hsb(FACE_HUE, FACE_SAT,
Math.abs(-zPos.getValue() / (radius * 2)) + 0.40);
return color;
}
}