fenfire-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fenfire-dev] Repost^5: PEG animation_api--mudyc


From: Matti Katila
Subject: [Fenfire-dev] Repost^5: PEG animation_api--mudyc
Date: Fri, 7 Nov 2003 14:43:26 +0200 (EET)

==========================================================================
PEG animation_api--mudyc: Animation Layer API 
==========================================================================

:Authors:  mudyc
:Date-Created: 2003-09-27
:Last-Modified: $Date: 2003/10/26 19:57:18 $
:Revision: $Revision: 1.21 $
:Status:   Current
:Stakeholders: mudyc, tjl, benja
:Scope:    Minor
:Type:     Policy, Interface


We have a very powerful system for drawing on the screen and animating.
In larger programs, where it's quite easy to create bugs,
the current API is misused more often. To make it easier to
debug the animation and events, I propose that we make a new layer for 
calling the animation routines.

Instead of calling::

    AbstractUpdateManager.chg()

directly, let us have a new API which is::

    anim.animate()
    anim.switchVS()
    anim.rerenderVS()

where ``anim`` is an instance of ``AnimationAPI``.


Issues
======

ISSUE: How can we make sure that no other object calls the public method 
AbstractUpdateManager.chg()?

   RESOLVED: Use the source, Luke. Yes, we have source and we can 
   use the command ``grep`` to search trough source tree. After all, 
   this is easy to convert as a simple test.


ISSUE: If we don't want people to see AbstractUpdateManager
should we hide some of it's methods to package private?

    RESOLVED: Issue can be solved later because this PEG
    still gives a plenty of room for handling it in future. 
    Implementing the interfaace in demo framework also makes 
    it much more easier to use than old way and increments readability
    of source.


ISSUE: What about requesting a longer or shorter animation time,
or a non-standard animation curve (i.e. linear instead of the
vibrating exponential)?
Should this be covered by the animation API or bypassed to
AbstractUpdateManager? If there's a particular change that
should happen with a faster animation time (e.g. a menu closing)

    RESOLVED: Later. It's easy to add this feature into AnimationAPI:

        a) when we know issues with it,
        b) we have prototype of it and
        c) we have used the prototype in real program.
    
    This PEG is not about substitute of AbstractUpdateManager.
    This PEG is about handling one window and vobscenes close to it.


ISSUE: Should the default be to animate or not to animate?

    RESOLVED: Again, this is not about substitute of AbstractUpdateManager.
    Although, chg method should not called directly we explicitly call:
    'animation with time', '"animation" with very short time' or 'reuse
    VobScene'.


ISSUE: What package should this interface be in?
libvob.view doesn't feel right - this isn't a view. How about
libvob proper?

    RESOLVED: The author of this PEG doesn't want to overload 
    the count of files in org.nongnu.libvob but is satisfied 
    if the author of libvob wants the interface to be in there.


Introduction
============

We heavily use the ``demo framework`` in our applications, see
vob.putil.demo. ``Demo framework`` basicly is libvob using one window;
including dynamic realoading of jython source and switching 
between demo scenes. One window is obivious to get more 
testing with irregular edge.

The animation seen in the window is made with one or two VobScenes.
Although, VobScene is very close to *one* window we have no interfaces
to handle them per *one* window.

This PEG tries to be a solution to provide an interface
for handling VobScenes per *one* window instead of
current UpdateManager which handles multiple windows and timing.

Currently we use AbstactUpdateManager directly from programs.
This is bad thing 'cause of it can prevent proper animation, e.g., 
by setting no animation even animation should be seen. 


Changes
=======

Create a new animation layer which encapsulates 
AbstractUpdateManager method calls, i.e, chg and setNoAnimation.
The new layer will be the only one that takes care of reusing VobScenes.
**No other objects are allowed to call the above named UpdateManager 
methods in the source tree, except small demos.**

WindowAnimation should be implemented with java and 
used in ``demo framework``.

For safety of event handling, possibility to check if 
VobScene has changed, i.e. screen has updated,
from previous animate or switchVS method 
is added into the animation layer.
For example if we need to wait until something draws
on screen, all events before we have the correct 
screen needs to be passed trough without handling.

Implementations of WindowAnimation should print out stack
traces when debugging is enabled, to allow the programmer
to see how the updates were initiated.

Let's define the following interface: ::

    package org.nongnu.libvob;
    import org.nongnu.libvob.VobScene;

    /** An interface for providing common tool set for animation 
     *  and animation debugging information.
     *  This interface encapsulates the low-level animation interface
     *  such as AbstractUpdateManagers' chg and setNoAnimation methods. 
     * <p>
     *  This interface sets strict policy for several routines:
     * <ol><li>
     *      The previously shown vobscene should not be stored 
     *      anywhere else. If a VobScene is saved in other place than 
     *      here, it could prevent the GC to clean old VobScenes.
     *      By using only the correct 'previous' VobScene
     *      program can not get the famous 'invalid coorsys' bug.
     * </li>
     * <li>
     *      No other objects should call the low-level animation 
     *      interface in AbstractUpdateManager. This could prevent
     *      proper animation, e.g., by setting no animation even when
     *      animation should be done.
     * </li></ol>
     * <p>
     *  Methods <code>animate</code> , <code>switchVS</code> and 
     *  <code>rerender</code> are pending state methods, i.e., 
     *  the time when the operation of the method is accomplished 
     *  is (undetermined) soon but not immediately. 
     * <p>
     *
     * Examples:
     * <ol><li>
     * Example: When you want to interpolate a red box from left to right
     * you could do it, like:
     * <pre>
     *  class Scene:
     *      """ Example scene to animate red box from left to right 
     *      and backwards.
     *      """
     *      def __init__(self, windowAnimation):
     *          self.windowAnimation = windowAnimation
     *          self.keyHit = 0
     *          self.left = 100
     *          self.right = 500
     *      def scene(self, vs):
     *          if self.keyHit == 0:
     *              cs = vs.orthoBoxCS(0, "RedBox", 0,self.left,
     *                      50, 1,1, 100,100)
     *          else:
     *              cs = vs.orthoBoxCS(0, "RedBox", 0,self.right,
     *                      50, 1,1, 100,100)
     *          vs.put(vob.vobs.RectBgVob(java.awt.Color.red), cs)
     *      def key(self, key):
     *          self.keyHit = 1 - self.keyHit
     *          self.windowAnimation.animate()
     * </pre>
     * </li><li>
     * Example: When you want to pop a red box from left to right.
     *  The point of example is to use creation of new scene without
     *  animation:
     * <pre>
     *  class Scene:
     *      """ Example scene to pop red box from left to right 
     *      and backwards.
     *      """
     *      def __init__(self, windowAnimation):
     *          self.windowAnimation = windowAnimation
     *          self.keyHit = 0
     *          self.left = 100
     *          self.right = 500
     *      def scene(self, vs):
     *          if self.keyHit == 0:
     *              cs = vs.orthoBoxCS(0, "RedBox", 0,self.left,
     *                      50, 1,1, 100,100)
     *          else:
     *              cs = vs.orthoBoxCS(0, "RedBox", 0,self.right,
     *                      50, 1,1, 100,100)
     *          vs.put(vob.vobs.RectBgVob(java.awt.Color.red), cs)
     *      def key(self, key):
     *          self.keyHit = 1 - self.keyHit
     *          self.windowAnimation.switchVS()
     * </pre>
     * </li><li>
     * Example: Another way to pop a red box from left to right.
     *  This way is like ten times faster than previous example 
     *  where we created a new scene. In this example we set
     *  coordinate system parameters instead:
     * <pre>
     *  class Scene:
     *      """ Example scene to pop red box from left to right 
     *      and backwards.
     *      """
     *      def __init__(self, windowAnimation):
     *          self.windowAnimation = windowAnimation
     *          self.keyHit = 0
     *          self.left = 100
     *          self.right = 500
     *      def scene(self, vs):
     *          if self.windowAnimation.getCurrentVS() != None: return
     *          cs = vs.orthoBoxCS(0, "RedBox", 0,self.left,
     *              50, 1,1, 100,100)
     *          vs.put(vob.vobs.RectBgVob(java.awt.Color.red), cs)
     *      def key(self, key):
     *          self.keyHit = 1 - self.keyHit
     *
     *          vs = self.windowAnimation.getCurrentVS()
     *          cs = vs.matcher.getCS(0, "RedBox")
     *          if self.keyHit == 0:
     *              vs.coords.setOrthoBoxParams(cs, 0,self.left,
     *                   50, 1,1, 100,100)
     *          else:
     *              vs.coords.setOrthoBoxParams(cs, 0,self.right,
     *                   50, 1,1, 100,100)
     *          self.windowAnimation.rerender()
     * </pre>
     * </li><li>
     *  Example: Quite a difficult example where we start to drag 
     *  red box around the scene that may end to be yellow one.
     *  Point of the example is to use both (fast) rerendering of one 
     *  scene and switch scene when it's unavoidable.
     * <p>
     *  The main problem in example is that when handling mouse event you
     *  don't know what is drawn in the current window: a yellow or red
     *  box? We try to guess *the position of the moon* from previous 
     *  event if we even have a one.
     *
     * <pre>
     *  class Scene:
     *      """ Example scene to drag the red or yellow box around.
     *      In left the box is red but in right it is yellow.
     *      """
     *      def __init__(self, windowAnimation):
     *          self.windowAnimation = windowAnimation
     *          self.half = 300
     *          self.ev = None
     *      def scene(self, vs):
     *          # this is an event grabbing example, really.
     *          self.evenrGrabberDraw(vs)
     *      def eventGrabberDraw(self, vs):
     *          if self.ev != None:
     *              cs = vs.orthoBoxCS(0, "Box", 0,
     *                  self.ev.getX(),self.ev.getY(), 1,1, 100,100)
     *          else:
     *              cs = vs.orthoBoxCS(0, "Box", 0,10,10, 1,1, 100,100)
     *          if self.ev.getX() < self.half:
     *              vs.put(vob.vobs.RectBgVob(java.awt.Color.red), cs)
     *          else:
     *              vs.put(vob.vobs.RectBgVob(java.awt.Color.yellow), cs)
     *      def mouse(self, ev):
     *          if self.ev == None: self.ev = ev
     *          vs = self.windowAnimation.getCurrentVS()
     *          cs = vs.matcher.getCS(0, "Box")
     *          if self.ev.getX() < self.half and ev.getX() < self.half:
     *              vs.coords.setOrthoBoxParams(cs, 0,ev.getX(),ev.getY(),
     *                  1,1, 100,100)
     *              if not self.windowAnimation.hasSceneReplacementPending():
     *                  self.windowAnimation.rerender()
     *          elif self.ev.getX() > self.half and ev.getX() > self.half:
     *              vs.coords.setOrthoBoxParams(cs, 0,ev.getX(),ev.getY(),
     *                  1,1, 100,100)
     *              if not self.windowAnimation.hasSceneReplacementPending():
     *                  self.windowAnimation.rerender()
     *          else:
     *              self.windowAnimation.switchVS()
     *          self.ev = ev
     * </pre>
     * </li> </ol>
     */
    public interface WindowAnimation {


        /** Animate to next VobScene by creating a new VobScene.
         *  The interpolation time between current screen and VobScene
         *  (screen after animations) in future is set via 
         *  AbstractUpdateManager.
         *  This method is pending, i.e., next screen update is soon 
         *  but not immediately.
         * <p> 
         *  Animation between scenes is done between keys, i.e., key "A" in 
         *  current visible scene will animate to where 
         *  key "A" is in scene in future.
         *
         * @see AbstractUpdateManager
         * @see VobMatcher
         */
        void animate();


        /** Switch to next VobScene by creating a new VobScene.
         * The switch is fast and no animation is seen. 
         * This method is pending, i.e., next screen update is soon 
         * but not immediately.
         */
        void switchVS();


        /** Rerender the current VobScene. 
         * This method is pending, i.e., next screen update is soon 
         * but not immediately.
         * <p>
         * Changes in next frame are seen if coordinate system
         * parameters are set. Rerendering the current VobScene 
         * is much faster than creating a new VobScene, 
         * so e.g., any drag actions should be implemented to use
         * this method. 
         * <p>
         * Implementation note:
         * <ol><li>
         *  Even though new coordinate systems can be created, the current 
         *  coorder implementation uses finite range of coordinate systems. 
         *  Creating too many new coordinate systems leads to
         *  undefined behauviour.
         * </li><li>
         *  If there's a vob which needs to be removed,
         *  it's usually faster to set coordinate system parameters 
         *  to zero than generate a new scene without the accursed vob.
         * </li></ol>
         * @see VobCoorder
         */
        void rerender();
 

        /** Get the current visible vobscene. 
         * <p>
         * Prgogramming note: When programming, you create vobscenes
         * for future usually, so this returns the current visible
         * vobscene, e.g., to set coordinate system parameters or 
         * use activated coordinate systems to catch mouse events.
         */
        VobScene getCurrentVS();


        /** Returns true if there are pending methods that 
         *  create a new VobScene which has not yet been updated
         *  within window. The methods that create a new VobScene
         *  are <code>animate</code> and <code>switchVS</code>.
         * <p>
         * Programming note:
         *  In some situations when handling the events the programmer 
         *  needs to know whether the VobScene is new or the still the old one,
         *  e.g., when waiting to move some new vob you
         *  you need to pass all events trough before the screen has updated.
         */
        boolean hasSceneReplacementPending();
    } 








reply via email to

[Prev in Thread] Current Thread [Next in Thread]