/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* 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 the 'Xith3D Project Group' 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) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.scenegraph;
import org.jagatoo.util.arrays.ArrayUtils;
import org.xith3d.render.ScissorRect;
import org.xith3d.render.ClipperInfo;
/**
* the {@link InheritedNodeAttributes} class holds references to inherited
* {@link Node}s like lights, fog, etc.
* Each SceneGraph {@link Node} carries an instance of this class,
* which is automatically updated and which is read-only for non-scenegraph
* classes.
*
* @author Marvin Froehlich (aka Qudus)
*/
public final class InheritedNodeAttributes
{
private static final int MAX_LIGHTS = 8;
private static final int MAX_FOGS = 1;
private Light[] lights = new Light[ 8 ];
private int numLights = 0;
private int numEffectiveLights = 0;
private Fog[] fogs = new Fog[ 8 ];
private int numFogs = 0;
private int numEffectiveFogs = 0;
private ScissorRect scissorRect = null;
private ClipperInfo clipper = null;
private boolean lightsDirty = false;
private boolean fogsDirty = false;
protected final void addLight( Light light )
{
if ( lights.length <= numLights )
{
Light[] tmp = new Light[ lights.length + 1 ];
System.arraycopy( lights, 0, tmp, 0, lights.length );
lights = tmp;
}
lights[ numLights++ ] = light;
this.numEffectiveLights = Math.min( numLights, MAX_LIGHTS );
lightsDirty = true;
}
protected final void removeLight( Light light )
{
int index = ArrayUtils.indexOf( lights, light, true );
if ( index >= 0 )
{
System.arraycopy( lights, index + 1, lights, index, numLights - index - 1 );
lights[ --numLights ] = null;
this.numEffectiveLights = Math.min( numLights, MAX_LIGHTS );
}
lightsDirty = true;
}
/**
* @return the number of (inherited) {@link Light}s in the owning Node.
*/
public final int getLightsCount()
{
return ( numLights );
}
/**
* @return the number of (inherited) {@link Light}s in the owning Node,
* but with a maximum of 8.
*/
public final int getEffectiveLightsCount()
{
return ( numEffectiveLights );
}
/**
* @return the i-th (inherited) {@link Light} in the owning Node.
*/
public final Light getLight( int index )
{
return ( lights[ index ] );
}
public final boolean getLightsDirty()
{
return ( lightsDirty );
}
public final void setLightsClean()
{
lightsDirty = false;
}
protected final void addFog( Fog fog )
{
if ( fogs.length <= numFogs )
{
Fog[] tmp = new Fog[ fogs.length + 1 ];
System.arraycopy( fogs, 0, tmp, 0, fogs.length );
fogs = tmp;
}
fogs[ numFogs++ ] = fog;
numEffectiveFogs = Math.min( numFogs, MAX_FOGS );
fogsDirty = true;
}
protected final void removeFog( Fog fog )
{
int index = ArrayUtils.indexOf( fogs, fog, true );
if ( index >= 0 )
{
System.arraycopy( fogs, index + 1, fogs, index, numFogs - index - 1 );
fogs[ --numFogs ] = null;
this.numEffectiveFogs = Math.min( numFogs, MAX_FOGS );
}
fogsDirty = true;
}
/**
* @return the number of (inherited) {@link Fog}s in the owning Node.
*/
public final int getFogsCount()
{
return ( numFogs );
}
/**
* @return the number of (inherited) {@link Fog}s in the owning Node,
* but with a maximum of 1.
*/
public final int getEffectiveFogsCount()
{
return ( numEffectiveFogs );
}
/**
* @return the i-th (inherited) {@link Fog} in the owning Node.
*/
public final Fog getFog( int index )
{
return ( fogs[ index ] );
}
public final boolean getFogsDirty()
{
return ( fogsDirty );
}
public final void setFogsClean()
{
fogsDirty = false;
}
protected final void setScissorRect( ScissorRect scissorRect )
{
this.scissorRect = scissorRect;
}
/**
* @return the (inherited) {@link ScissorRect} of the owning Node.
*/
public final ScissorRect getScissorRect()
{
return ( scissorRect );
}
protected final void setClipper( ClipperInfo clipper )
{
this.clipper = clipper;
}
/**
* @return the (inherited) {@link ClipperInfo} of the owning Node.
*/
public final ClipperInfo getClipper()
{
return ( clipper );
}
protected void merge( InheritedNodeAttributes toMerge )
{
for ( int i = 0; i < toMerge.getLightsCount(); i++ )
{
final Light light = toMerge.getLight( i );
if ( !ArrayUtils.contains( lights, light, true ) )
addLight( light );
}
for ( int i = 0; i < toMerge.getFogsCount(); i++ )
{
final Fog fog = toMerge.getFog( i );
if ( !ArrayUtils.contains( fogs, fog, true ) )
addFog( fog );
}
if ( this.scissorRect == null )
this.scissorRect = toMerge.scissorRect;
if ( this.clipper == null )
this.clipper = toMerge.clipper;
}
protected void unmerge( InheritedNodeAttributes toUnmerge )
{
for ( int i = 0; i < toUnmerge.getLightsCount(); i++ )
{
removeLight( toUnmerge.getLight( i ) );
}
for ( int i = 0; i < toUnmerge.getFogsCount(); i++ )
{
removeFog( toUnmerge.getFog( i ) );
}
if ( this.scissorRect == toUnmerge.getScissorRect() )
this.scissorRect = null;
if ( this.clipper == toUnmerge.getClipper() )
this.clipper = null;
}
public InheritedNodeAttributes()
{
}
}