/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
* Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Oracle Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package videopuzzle;
import java.lang.Math;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.input.*;
import javafx.scene.image.*;
import javafx.scene.media.*;
import javafx.scene.paint.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.effect.*;
import javafx.fxd.Duplicator;
class HintButton extends CustomNode {
public-init var masterImage:Node;
public-init var xoff = 0;
public-init var yoff = 0;
public-init var piece:Piece;
override public function create():Node {
var upArrow = Duplicator.duplicate(masterImage) as ImageView;
upArrow.visible = true;
upArrow.onMousePressed = function(e:MouseEvent):Void { puzzle.triggerHint(prow+yoff,pcol+xoff,true); }
upArrow.onMouseReleased = function(e:MouseEvent):Void { puzzle.triggerHint(prow+yoff,pcol+xoff,false); }
upArrow.x = 0; upArrow.y = 0;
upArrow.translateX = (pw/2)+(pw/2) * xoff;
upArrow.translateY = (ph/2)+(ph/2) * yoff;
var w = upArrow.image.width;
var h = upArrow.image.height;
upArrow.x = -w/2 + w/2 * -xoff;
upArrow.y = -h/2 + h/2 * -yoff;
if(xoff == -1) { upArrow.visible = piece.pcol > 0; }
if(xoff == 1) { upArrow.visible = piece.pcol < piece.puzzle.pieceCols-1; }
if(yoff == -1) { upArrow.visible = piece.prow > 0; }
if(yoff == 1) { upArrow.y = -upArrow.image.height; upArrow.visible = piece.prow < piece.puzzle.pieceRows-1; }
return upArrow;
}
}
public class Piece extends CustomNode {
public var px = 0.0;
public var py = 0.0;
public var pw = 100;
public var ph = 100;
public var prow = 0;
public var pcol = 0;
public var video:MediaPlayer;
public var puzzle:Puzzle;
public override var blocksMouse = true;
var startX = 0.0;
var startY = 0.0;
var active = false;
var near = false;
public var placed = false;
public var hintShowing = false;
public var hintControlShowing = false;
override public function create():Node {
var bds = Rectangle2D {
minX: px
minY: py
width: pw
height: ph
};
return Group {
content: [
Rectangle {
width: pw-1
height: ph-1
fill: Color.RED
cache: true
opacity: bind if(active) { 1.0 } else { 0.0 }
effect:DropShadow {
radius: 20
offsetX: 10
offsetY: 10
}
}
MediaView {
mediaPlayer: bind video
viewport: bds
},
Rectangle {
width: pw-1
height: ph-1
stroke: bind Color.rgb(255,255,0, if(near) { 0.7 } else { 0.0 })
strokeWidth: 5
fill: bind Color.rgb(255,255,100, if(active) {0.3} else {0.0})
}
ImageView {
image: puzzle.dragTargetImage
visible: bind (this == puzzle.selectedPiece)
translateX: (pw - puzzle.dragTargetImage.width)/2
translateY: (ph - puzzle.dragTargetImage.height)/2
}
Group {
visible: bind hintShowing
content:[
Rectangle {
width: pw-1
height: ph-1
fill: Color.rgb(255,255,255,0.5)
}
]
}
Group {
visible: bind hintControlShowing
blocksMouse: true
content: [
HintButton {
xoff: 0
yoff: -1
masterImage: puzzle.ui.arrow_up
piece: this
}
HintButton {
xoff: 0
yoff: 1
masterImage: puzzle.ui.arrow_down
piece: this
}
HintButton {
xoff: -1
yoff: 0
masterImage: puzzle.ui.arrow_left
piece: this
}
HintButton {
xoff: 1
yoff: 0
masterImage: puzzle.ui.arrow_right
piece: this
}
]
}
]
}
}
override var onMousePressed = function(e:MouseEvent):Void {
if(placed) return;
startX = e.sceneX-translateX;
startY = e.sceneY-translateY;
active = true;
delete this from puzzle.pieces;
insert this into puzzle.pieces;
puzzle.selectedPiece = this;
}
override var onMouseDragged = function(e:MouseEvent):Void {
if(placed) return;
var tx = e.sceneX-startX;
var ty = e.sceneY-startY;
if(tx > 0-pw and ty > 0-ph
and tx < 750-pw and ty < 440-ph) {
translateX = tx;
translateY = ty;
}
if(isNearDropSpot()) {
near = true;
} else {
near = false;
}
}
override var onMouseReleased = function(e:MouseEvent):Void {
if(placed) return;
active = false;
if(isNearDropSpot()) {
snapToDropSpot();
near = false;
delete this from puzzle.pieces;
insert this before puzzle.pieces[0];
placed = true;
}
if(puzzle.hintVisible) {
puzzle.toggleHint();
puzzle.toggleHint();
}
}
function isNearDropSpot():Boolean {
var xdiff = Math.abs(translateX - px);
var ydiff = Math.abs(translateY - py);
if(xdiff < 10 and ydiff < 10) {
return true;
}
return false;
}
function snapToDropSpot() {
translateX = px;
translateY = py;
}
}