package photoflockr;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.Group;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Color;
import javafx.scene.transform.Transform;
import java.lang.Math;
public class Sprite extends CustomNode {
override var blocksMouse = true;
override var hover on replace {
if (hover and not fullScreen) {
onEnter();
} else {
onLeave();
}
}
public var boid: Boid;
public var screenHeight: Number;
public var screenWidth: Number;
public var fullScreen: Boolean;
public var clickAction: function(tag: String): Void;
public var heading: Number;
var largeImageUrl: String = bind boid.largeImageUrl;
var imageUrl: String = bind boid.imageUrl on replace {
if (imageUrl != null and not imageUrl.equals(image.url)) {
image = Image {
placeholder: image
url: imageUrl
backgroundLoading: true
}
}
}
var image: Image;
var largeImage: Image;
var screenAlpha: Number = 1.0;
var alpha: Number = 1.0;
var textAlpha: Number = 0.0;
var spriteHeading: Number;
var spriteX: Number = bind if (not selected) boidx else x;
var spriteY: Number = bind if (not selected) boidy else y;
var boidx: Number = bind boid.loc.x;
var boidy: Number = bind boid.loc.y;
var x: Number;
var y: Number;
var boidHeading: Number;
var selected: Boolean = false;
var radius: Number = bind boid.radius;
var largeImageFade: Number = 0.0;
var tagList = TagList {
translateX: bind radius * 2 * alpha
height: 150
width: 150
textOpacity: bind textAlpha
clickAction: function(s: String): Void {
this.doClick(s);
}
}
var boidSelected: Boolean = bind boid.selected on replace {
if (not boid.selected and fullScreen) {
fullScreenTimeline.stop();
fadeTimeline.stop();
largeImage = null;
largeImageFade = 0;
x = boidx;
y = boidy;
nonFullScreenTimeline.play();
} else if (boid.selected and sizeof boid.tags > 0) {
tagList.tags = boid.tags[0..30];
}
}
var largeImageProgress = bind largeImage.progress on replace {
if (largeImage != null and largeImageProgress == 100) {
fadeTimeline.play();
}
}
var fadeTimeline = Timeline {
keyFrames:
[ at (0s) { largeImageFade => 0.0 },
at (1s) { largeImageFade => 1.0 } ]
}
var scaleTimeline = Timeline {
keyFrames:
[KeyFrame {
time: 0s
values:
[alpha => 1.0,
spriteHeading => boidHeading,
textAlpha => 0.0]
},
KeyFrame {
time: 0.5s
values:
[alpha => 2.0 tween Interpolator.EASEOUT,
spriteHeading => 0.0 tween Interpolator.EASEOUT,
textAlpha => 0.0]
action: function() {
spriteHeading = 0.0;
alpha = 2.0;
}
},
KeyFrame {
time: 1s
values: textAlpha => 1.0 tween Interpolator.EASEOUT
}]
}
var unscaleTimeline = Timeline {
keyFrames:
[KeyFrame {
time: 0s
values:
[alpha => 2.0,
spriteHeading => 0.0];
},
KeyFrame {
time: 0.5s
values:
[alpha => 1.0 tween Interpolator.EASEOUT,
spriteHeading => boidHeading tween Interpolator.EASEOUT];
action: function() {
fullScreen = false;
selected = false;
textAlpha = 0;
alpha = 1.0;
spriteHeading = boidHeading;
boid.returnToFlocking();
}
}]
}
var fullScreenTimeline = Timeline {
keyFrames:
[KeyFrame {
time: 0s
values:
[alpha => 2.0,
x => boidx,
y => boidy]
},
KeyFrame {
time: 0.5s
values:
[alpha => screenAlpha tween Interpolator.EASEOUT,
x => 0.0 tween Interpolator.EASEOUT,
y => 0.0 tween Interpolator.EASEOUT]
}]
}
var nonFullScreenTimeline = Timeline {
keyFrames:
[KeyFrame {
time: 0s
values:
[alpha => screenAlpha,
spriteHeading => 0.0,
x => 0.0,
y => 0.0]
},
KeyFrame {
time: 0.5s
values:
[alpha => 1.0 tween Interpolator.EASEOUT,
x => boidx tween Interpolator.EASEOUT,
y => boidy tween Interpolator.EASEOUT,
spriteHeading => boidHeading tween Interpolator.EASEOUT]
action: function() {
fullScreen = false;
selected = false;
textAlpha = 0;
boid.returnToFlocking();
}
}]
}
function doClick(s: String): Void {
clickAction(s);
onLeave();
}
public function doSelect(): Void {
if (not fullScreen and alpha == 2.0) {
nonFullScreenTimeline.stop();
var sx = screenWidth / (radius * 2);
var sy = screenHeight / (radius * 2);
fullScreen = true;
screenAlpha = Math.max(sx, sy);
fullScreenTimeline.play();
if (largeImageUrl != null) {
fadeTimeline.stop();
largeImage = Image {
url: largeImageUrl
backgroundLoading: true
}
largeImageFade = 0.0;
}
} else if (fullScreen) {
fadeTimeline.stop();
largeImage = null;
largeImageFade = 0;
fullScreenTimeline.stop();
x = boidx;
y = boidy;
nonFullScreenTimeline.play();
}
}
public function onEnter(): Void {
unscaleTimeline.stop();
boidHeading = heading;
spriteHeading = heading;
x = spriteX;
y = spriteY;
textAlpha = 0;
selected = true;
boid.selectYourself();
scaleTimeline.play();
}
public function onLeave(): Void {
if (not fullScreen) {
scaleTimeline.stop();
textAlpha = 0;
unscaleTimeline.play();
}
}
override public function create(): Node {
Group {
transforms: bind Transform.translate(spriteX, spriteY)
content:
[Group {
transforms: bind [ Transform.scale(alpha, alpha),
Transform.rotate(if (not selected) heading
else spriteHeading, radius, radius) ]
content: [
Rectangle {
height: radius*2
width: radius*2
fill: Color.BLACK
smooth: false
},
ImageView {
opacity: bind 1.0 - largeImageFade
image: bind image
smooth: true
onMouseClicked: function(e) {
this.doSelect();
}
},
Rectangle {
transforms: bind Transform.scale(1.0/alpha, 1.0/alpha);
stroke: Color.GRAY
height: bind radius*2*alpha
width: bind radius*2*alpha
fill: Color.color(0, 0, 0, 0);
strokeWidth: 1
}
]
},
Group {
opacity: bind largeImageFade
visible: bind largeImage != null
content:
[Rectangle {
height: screenHeight
width: screenWidth
fill: Color.BLACK
visible: bind largeImageFade == 1.0
},
ImageView {
image: bind largeImage
smooth: true
}]
},
Group {
visible: bind alpha == 2.0
content: bind tagList
}]
}
}
}