com.hdcookbook.grin
Class Feature

java.lang.Object
  extended by com.hdcookbook.grin.Feature
Direct Known Subclasses:
Assembly, Box, FixedImage, FontStripText, Group, ImageSequence, InterpolatedModel, Modifier, Playlist, SEGenericFeature, Text

public abstract class Feature
extends java.lang.Object

Represents a feature. A feature is a thing that presents some sort of UI. A segment presents some number of features, and features can be shared between segments.

Author:
Bill Foote (http://jovial.com)

Field Summary
protected  java.lang.String name
          The name of this feature within the show.
protected  Show show
           
 
Constructor Summary
protected Feature(Show show)
           
 
Method Summary
 void activate()
          Called by the show when this feature becomes activated, that is, when it starts presenting.
abstract  void addDisplayAreas(RenderContext context)
          Add all of the areas that are displayed for this feature with the current frame.
 void addSubgraph(java.util.HashSet set)
          This is an implementation method that is not intended to be called direction by applications.
protected static Command[] cloneCommands(Command[] commands, java.util.HashMap clones)
          Clone a command array within a feature.
protected static Feature clonedReference(Feature f, java.util.HashMap clones)
          Return a reference to the feature f for use within a reference.
 Feature cloneSubgraph(java.util.HashMap clones)
          Clone the subgraph of a scene graph, rooted at this feature.
protected  Feature createClone(java.util.HashMap clones)
          This is an implementation method that should not be called direction by applications; applications should call cloneSubgraph().
 void deactivate()
          Called by the show when this feature is no longer being presented by whatever contains it.
abstract  void destroy()
          Free any resources held by this feature.
 void destroyClonedSubgraph()
          Destroy a subgraph of features that was created with cloneSubgraph().
 java.lang.String getName()
          All public features have a name.
abstract  int getX()
          Get the upper-left hand corner of this feature as presently displayed.
abstract  int getY()
          Get the upper-left hand corner of this feature as presently displayed Return Integer.MAX_VALUE if this feature has no visible representation.
abstract  void initialize()
          Initialize this feature.
protected  void initializeClone(Feature original, java.util.HashMap clones)
          This is an implementation method that should not be called direction by applications; it is called from cloneSubgraph().
 boolean isSetup()
          Check to see if this feature has been set up, or has a pending request to be set up.
 Feature makeNewClone(java.util.HashMap clones)
          This is an implementation method that should not be called direction by applications; applications should call cloneSubgraph().
abstract  void markDisplayAreasChanged()
          Mark the display areas of this feature as modified for the next call to addDisplayAreas.
abstract  boolean needsMoreSetup()
          This is where the feaure says whether or not it needs more setup.
abstract  void nextFrame()
          Called from Segment with the Show lock held, to advance us to the state we should be in for the next frame.
abstract  void paintFrame(java.awt.Graphics2D gr)
          Paint the current state of this feature to gr.
 void resetFeature()
          Called from the ResetFeatureCommand, this should reset the internal state of the feature to what it was when first activated.
protected  void sendFeatureSetup()
          When a feature finishes its setup, it should call this to tell the show about it.
protected abstract  void setActivateMode(boolean mode)
          Change the activated mode of this feature.
 void setName(java.lang.String name)
          Sets a name for this feature.
protected abstract  int setSetupMode(boolean mode)
          Change the setup mode of this feature.
 int setup()
          Called by the show when it's time to begin setting up this feature.
 java.lang.String toString()
           
 void unsetup()
          Called by the show when this feature is no longer needed by whatever contains it.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

show

protected Show show

name

protected java.lang.String name
The name of this feature within the show. This is set to null for private features in the binary file.

Constructor Detail

Feature

protected Feature(Show show)
Parameters:
show - The show this feature is attached to. The value can be null, as long as it's set to a real value before the feature is used.
Method Detail

setName

public void setName(java.lang.String name)
Sets a name for this feature. All public features have a name. Private features might or might not have a name; if they do, it's just for debugging. This method should only be called when a feature is first created.


getName

public java.lang.String getName()
All public features have a name. Private features might or might not have a name; if they do, it's just for debugging.

Returns:
the name of this feature, or null if it is not known.

getX

public abstract int getX()
Get the upper-left hand corner of this feature as presently displayed. Return Integer.MAX_VALUE if this feature has no visible representation.

Returns:
the x coordinate

getY

public abstract int getY()
Get the upper-left hand corner of this feature as presently displayed Return Integer.MAX_VALUE if this feature has no visible representation.

Returns:
the y coordinate

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object
Returns:
a developer-friendly description of this feature, for debugging

initialize

public abstract void initialize()
Initialize this feature. This is called on show initialization. A show will initialize all of its features after it initializes the segments. Clients of the GRIN framework should never call this method directly. Custom feature extensions must implement this method.


destroy

public abstract void destroy()
Free any resources held by this feature. It is the opposite of initialize().

Features are deactivated before they are destroyed. For example, the last segment a show is in when the show is destroyed will probably be active, but it is deactivated and unsetup() is called in Show.destroy() before the features are destroyed.

Cloned features are handled a little differently. They have destroy() called from within Feature.destroyClonedSubgraph(). Since cloned fetures are exempt from the setup/unsetup lifecycle, the cloned feature will not be activated, but will be in a setup state when destroy() is called. Features that support cloning must therefore release any resources they acquired in createClone() or initializeClone() during the call to destroy().

Clients of the GRIN framework should never call this method directly. Custom feature extensions must implement this method.


setSetupMode

protected abstract int setSetupMode(boolean mode)
Change the setup mode of this feature. The new mode will always be different than the old. Clients of the GRIN framework should never call this method directly. Custom feature extensions must implement this method.

This method must return a guaranteed lower bound for the number of times it will send a feature setup command as a result of this call. That is, it must send at least as many feature setup commands to the segment as the number returned; sending an accurate number makes the setup process more efficient, since the time it takes to process a command scales with the number of features in a segment. When mode is false, 0 should be returned.


setActivateMode

protected abstract void setActivateMode(boolean mode)
Change the activated mode of this feature. The new mode will always be different than the old. Clients of the GRIN framework should never call this method directly. Custom feature extensions must implement this method.


needsMoreSetup

public abstract boolean needsMoreSetup()
This is where the feaure says whether or not it needs more setup. Calls to this are synchronized within the init manager to avoid race conditions. The implementation of this method must not call outside code or call any animation manager methods. For a given setup cycle, this method is called only after setup(). Clients of the GRIN framework should never call this method directly. Custom feature extensions must implement this method.

See Also:
SetupClient.needsMoreSetup()

setup

public final int setup()
Called by the show when it's time to begin setting up this feature. This might be called from the show multiple times; each call will eventually be matched by a call to unsetup(). Clients of the GRIN framework should never call this method directly, and it should not be overridden.

Returns:
A lower bound on the number of setup commands that will be generated due to this call.
See Also:
unsetup()

unsetup

public final void unsetup()
Called by the show when this feature is no longer needed by whatever contains it. When the last call to setup() has been matched by a call to unsetup(), it's time to unload this feature's assets.

See Also:
setup()

isSetup

public final boolean isSetup()
Check to see if this feature has been set up, or has a pending request to be set up.


activate

public final void activate()
Called by the show when this feature becomes activated, that is, when it starts presenting. These nest, so this can be called mutliple times. When the last call to activate() is undone by a call to deactivate(), that means this feature is no longer being shown. Clients of the GRIN framework should never call this method directly, and it should not be overridden.

See Also:
deactivate()

deactivate

public final void deactivate()
Called by the show when this feature is no longer being presented by whatever contains it. Clients of the GRIN framework should never call this method directly, and it should not be overridden.

See Also:
activate()

sendFeatureSetup

protected void sendFeatureSetup()
When a feature finishes its setup, it should call this to tell the show about it. This happens in the setup thread. If this is done, then the feature should return the number of commands it can generate from setSetupMode.

See Also:
setSetupMode(boolean)

addDisplayAreas

public abstract void addDisplayAreas(RenderContext context)
Add all of the areas that are displayed for this feature with the current frame. This will be called exactly once per frame displayed on each activated feature.

A feature that displays something needs to maintain a record of it in a DrawRecord. The animation framework uses this to track what needs to be erased and drawn from frame to frame.

Clients of the GRIN framework should not call this method directly. Feature subclasses must implement this method.

Parameters:
context - The context for tracking rendering state
See Also:
DrawRecord

markDisplayAreasChanged

public abstract void markDisplayAreasChanged()
Mark the display areas of this feature as modified for the next call to addDisplayAreas. This can be called by a parent node on its children, e.g. when the parent is deactivated. This is necessary because a parent node might modify the drawing of its children (e.g. by setting an alpha value), and a parent might be taken out of a render tree when its children are not.

See also Issue 121

See Also:
addDisplayAreas(com.hdcookbook.grin.animator.RenderContext)

paintFrame

public abstract void paintFrame(java.awt.Graphics2D gr)
Paint the current state of this feature to gr. Clients of the GRIN framework should not call this method directly. Feature subclasses must implement this method.

Parameters:
gr - The place to paint to.

nextFrame

public abstract void nextFrame()
Called from Segment with the Show lock held, to advance us to the state we should be in for the next frame.


resetFeature

public final void resetFeature()
Called from the ResetFeatureCommand, this should reset the internal state of the feature to what it was when first activated.


cloneSubgraph

public final Feature cloneSubgraph(java.util.HashMap clones)
Clone the subgraph of a scene graph, rooted at this feature. This node, any child nodes, and other children below this node in the scene graph are copied. The original feature must have been initialized and setup must have completed, and it must not currently be activated (that is, visible). The cloned feature will not be subject to the setup/unsetup lifecycle. The feature being cloned might be activated or not.

The resulting cloned feature will already be initialized, but the caller is responsible for ensuring that destroyClonedSubgraph() is called on the top node of all cloned feature subgraphs.

A cloned feature can be used by adding it to the set of visible features in a group using Group.resetVisibleFeatures().

A scene graph can contain a reference to another feature, either by a direct reference, like the model attached to a Translator, or with a command that refers to a feature, like an activate_part command directed to an assembly. In either case, if the reffered-to feature is in the subgraph being cloned, then the clone is what will be referred to. If the referred-to feature is outside the subgraph being cloned, then the original feature will be referred to. It's the caller's responsibility to ensure that this results in a scene graph that gives valid behavior; usually this means that any referred-to feature that carries state (like a translation's model) should be in the set of features being cloned.

Parameters:
clones - A map from original feature to its clone, which should initially be empty. When this method completes it will be populated with all cloned features, including the top node of the cloned subgraph. You can use this map to locate the clones of features in your graph, e.g. named features that you've previously looked up. This must not be null. The key of each entry is the original feature, and the value is its clone.
Throws:
java.lang.UnsupportedOperationException - if this feature's class doesn't implement cloneFeature(), or if any features or commands this feature refers to doesn't implement cloning. All built-in GRIN commands and features features do implement cloning, but extension subclasses might not. The implementation of cloneFeature() in the Feature superclass always throws this exception.
java.lang.IllegalStateException - may be thrown if the feature has not been initialized and set up, if the feature is currently activated (that is, visible), or if the feature has been destroyed.
See Also:
Group.resetVisibleParts(com.hdcookbook.grin.Feature[]), initialize(), destroyClonedSubgraph()

makeNewClone

public final Feature makeNewClone(java.util.HashMap clones)
This is an implementation method that should not be called direction by applications; applications should call cloneSubgraph().

Make a clone of this feature if a new one is required, that is, if it hasn't already been cloned. This method checks to see if this feature has already been cloned, and if so, returns the previous clone. Otherwise, it calls createClone() to create that clone, then adds it into the clones map.

See the documentation of cloneSubgraph() for a list of runtime exceptions this method can throw.

Note that in previous versions of GRIN, subclasses of Feature that supported cloning were supposed to override this method. If you've just upgraded GRIN and gotten a compile-time error for overriding a final method, then you need to change the name of your overridden method to createClone(), make it protected, and make sure that you remove the code from your method that used to add clones to the clones map.

Parameters:
clones - A map from original feature to cloned feature. Entries are added by makeNewClone()
Throws:
java.lang.UnsupportedOperationException - as specified in Feature.cloneSubgraph()
java.lang.IllegalStateException - as specified in Feature.cloneSubgraph()
See Also:
cloneSubgraph(java.util.HashMap), createClone(java.util.HashMap)

createClone

protected Feature createClone(java.util.HashMap clones)
This is an implementation method that should not be called direction by applications; applications should call cloneSubgraph(). New subclasses of Feature that wish to support cloning must override this method.

Create a new clone of this feature. This method creates a new instance of this feature, and creates new instances of any sub-features, but it does not initialize the feature. This method is called from Feature.makeNewClone().

See the documentation of cloneSubgraph() for a list of runtime exceptions this method can throw. Subclasses that wish to support cloning must override this method.

Parameters:
clones - A map from original feature to cloned feature. Entries are added by Feature.makeNewClone().
Throws:
java.lang.UnsupportedOperationException - as specified in Feature.cloneSubgraph()
java.lang.IllegalStateException - as specified in Feature.cloneSubgraph()
See Also:
makeNewClone(java.util.HashMap), cloneSubgraph(java.util.HashMap)

initializeClone

protected void initializeClone(Feature original,
                               java.util.HashMap clones)
This is an implementation method that should not be called direction by applications; it is called from cloneSubgraph(). New subclasses of Feature may override this method.

Initialize this cloned feature from its original. This is called after the entire subgraph has been cloned, so the HashMap containing the set of clones will be complete. See the documentation of cloneSubgraph() for a list of runtime exceptions this method can throw. Subclasses that wish to support cloning must override this method.

If this feature doesn't need initialization it's OK for a feature to not implement it; the default version of this method does nothing. Typically, you only need to implement this for features that have references to other features that aren't sub-features, or that have commands that might have references to other features.

See Also:
cloneSubgraph(java.util.HashMap)

destroyClonedSubgraph

public final void destroyClonedSubgraph()
Destroy a subgraph of features that was created with cloneSubgraph(). Application code that creates new features using cloneSubgraph() must destroy the set of cloned features by calling this method on the top node of each cloned subgraph. In other words, every call to cloneSubgraph() should be balanced by a call to destroyClonedSubgraph(). This should be done when the cloned subgraph is not part of any group, but before the containing show is destroyed.

This method will cause destroy() to be called on every feature that's a member of the cloned subgraph.

See Also:
cloneSubgraph(java.util.HashMap)

addSubgraph

public void addSubgraph(java.util.HashSet set)
This is an implementation method that is not intended to be called direction by applications. New subclasses of Feature may override this method, and must overrride it if they have children.

Add this node and all of its descendent nodes to the given set. The superclass definition of this method adds the current node. Any node types that have children should override this method to call the superclass version, then recursively invoke this method on each child.


clonedReference

protected static Feature clonedReference(Feature f,
                                         java.util.HashMap clones)
Return a reference to the feature f for use within a reference. If some other feature contains a reference to this feature (other than an "owning" parent-child reference), then this method will give a reference to a clone of the feature being called, if one was made, or if not, to this original feature.

Parameters:
f - The feature reference. This may be null.

cloneCommands

protected static Command[] cloneCommands(Command[] commands,
                                         java.util.HashMap clones)
Clone a command array within a feature. This is used by some features' implementation of makeNewClone().

Parameters:
commands - The array to clone. May be null.
clones - A map from original feature to their clones.
Throws:
java.lang.UnsupportedOperationException - as specified in Feature.cloneSubgraph()
java.lang.IllegalStateException - as specified in Feature.cloneSubgraph()