//
// $Id$

package com.threerings.jme.effect;

import com.jme.scene.Node;
import com.jme.system.DisplaySystem;

import com.jmex.bui.BWindow;

import com.threerings.jme.util.LinearTimeFunction;
import com.threerings.jme.util.TimeFunction;

/**
 * Slides a window onto the center of the screen from offscreen or offscreen
 * from the center of the screen.
 */
public class WindowSlider extends Node
{
    public static final int FROM_TOP = 0;
    public static final int FROM_RIGHT = 1;
    public static final int TO_TOP = 2;
    public static final int TO_RIGHT = 3;

    public WindowSlider (BWindow window, int mode, float duration)
    {
        super("slider");

        DisplaySystem ds = DisplaySystem.getDisplaySystem();
        int swidth = ds.getWidth(), sheight = ds.getHeight();
        int wwidth = window.getWidth(), wheight = window.getHeight();

        int start = 0, end = 0;
        switch (mode) {
        case FROM_TOP:
            start = sheight+wheight;
            end = (sheight-wheight)/2;
            window.setLocation((swidth-wwidth)/2, start);
            break;

        case FROM_RIGHT:
            start = swidth+wwidth;
            end = (swidth-wwidth)/2;
            window.setLocation(start, (sheight-wheight)/2);
            break;

        case TO_TOP:
            start = (sheight-wheight)/2;
            end = sheight+wheight;
            window.setLocation((swidth-wwidth)/2, start);
            break;

        case TO_RIGHT:
            start = (swidth-wwidth)/2;
            end = swidth+wwidth;
            window.setLocation(start, (sheight-wheight)/2);
            break;
        }

        _mode = mode;
        _window = window;
        _tfunc = new LinearTimeFunction(start, end, duration);
    }

    /**
     * Allows some number of ticks to be skipped to give the window that is
     * being slid a chance to be layed out before we start keeping track of
     * time. The layout may be expensive and cause the frame rate to drop for a
     * frame or two, thus booching our smooth sliding onto the screen.
     */
    public void setSkipTicks (int skipTicks)
    {
        _skipTicks = skipTicks;
    }

    // documentation inherited
    public void updateGeometricState (float time, boolean initiator)
    {
        super.updateGeometricState(time, initiator);

        // skip ticks as long as we need to
        if (_skipTicks-- > 0) {
            return;
        }

        if (_mode % 2 == 1) {
            _window.setLocation((int)_tfunc.getValue(time), _window.getY());
        } else {
            _window.setLocation(_window.getX(), (int)_tfunc.getValue(time));
        }

        if (_tfunc.isComplete()) {
            slideComplete();
        }
    }

    /**
     * Called (only once) when we have reached the end of our slide.
     * Automatically detaches this effect from the hierarchy.
     */
    protected void slideComplete ()
    {
        getParent().detachChild(this);
    }

    protected int _mode;
    protected BWindow _window;
    protected TimeFunction _tfunc;

    // skip two frames by default as that generally handles the normal window
    // layout process
    protected int _skipTicks = 2;
}

@@ -562,16 +562,423 @@
 T = 3;%0A%0A
+    /**%0A     * Creates a window slider with the specified mode and window that will%0A     * slide the window either onto or off of the screen in the specified%0A     * number of seconds.%0A     *%0A     * @param dx an offset applied to the starting or destination position%0A     * along the x axis (starting for sliding off, destination for sliding on).%0A     * @param dy an offset applied along the y axis.%0A     */%0A
     publ
@@ -1034,16 +1034,57 @@
 duration
+,%0A                         int dx, int dy
 )%0A    %7B%0A
@@ -1448,32 +1448,37 @@
 eight-wheight)/2
+ + dy
 ;%0A            wi
@@ -1503,32 +1503,37 @@
 swidth-wwidth)/2
+ + dx
 , start);%0A      
@@ -1633,32 +1633,37 @@
 swidth-wwidth)/2
+ + dx
 ;%0A            wi
@@ -1697,32 +1697,37 @@
 eight-wheight)/2
+ + dy
 );%0A            b
@@ -1793,16 +1793,21 @@
 eight)/2
+ + dy
 ;%0A      
@@ -1883,16 +1883,21 @@
 width)/2
+ + dx
 , start)
@@ -1978,16 +1978,21 @@
 width)/2
+ + dx
 ;%0A      
@@ -2075,16 +2075,21 @@
 eight)/2
+ + dy
 );%0A     
@@ -2899,32 +2899,56 @@
 urn;%0A        %7D%0A%0A
+        int winx, winy;%0A
         if (_mod
@@ -2973,36 +2973,23 @@
         
-_
 win
-dow.setLocation(
+x = 
 (int)_tf
@@ -3006,17 +3006,36 @@
 ue(time)
-,
+;%0A            winy =
  _window
@@ -3041,17 +3041,16 @@
 w.getY()
-)
 ;%0A      
@@ -3076,43 +3076,49 @@
     
-_
 win
-dow.setLocation(_window.getX(),
+x = _window.getX();%0A            winy =
  (in
@@ -3140,17 +3140,16 @@
 ue(time)
-)
 ;%0A      
@@ -3143,32 +3143,73 @@
 time);%0A        %7D
+%0A        _window.setLocation(winx, winy);
 %0A%0A        if (_t

Allow an offset to be specified for not-quite centered windows.