package okj.easy.graphics.graphics2d;
import org.ege.utils.SpriteBackend;
import org.ege.utils.Updater;
import org.ege.utils.exception.EasyGEngineRuntimeException;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Animator;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.IdentityMap;
import com.badlogic.gdx.utils.IdentityMap.Values;
/**
* NSpriter.java {@link NManager}
*
* Created on: Oct 12, 2012 Author: Trung
*/
public class NSpriter extends NManager implements Animator, SpriteBackend, Disposable
{
// =========================================
// sprite params
private final IdentityMap<NativeSpriteBackend, NScaler> mScaler;
// ========================================
// Config
private final Array<NativeSpriteBackend> mDrawable;
private final Array<NativeSpriteBackend> mRunnable;
// =======================================
// param
private boolean RUN;
private NativeSpriteBackend mOriginSprite;
private float mOriginWidth;
private float mOriginHeight;
// =======================================
private float x;
private float y;
private float w;
private float h;
private Array<Updater> mUpdater = new Array<Updater>(0);
/**
* Construct a spriter with given sprite limit ( should override this method)
*
* @param limit
*/
protected NSpriter(long address, NWorld world)
{
super(address, world);
mScaler = new IdentityMap<NativeSpriteBackend, NSpriter.NScaler>(13);
mDrawable = new Array<NativeSpriteBackend>(13);
mRunnable = new Array<NativeSpriteBackend>(13);
}
/******************************************************** NManager method ********************************************************/
@Deprecated
/**
* This method shouldn't be call directly
*/
public void clear ()
{
super.clear();
}
@Override
public void remove (NativeSpriteBackend sprite)
{
super.remove(sprite);
mDrawable.removeValue(sprite, true);
mRunnable.removeValue(sprite, true);
}
public void removeFromDrawableRunnable (NativeSpriteBackend sprite)
{
mDrawable.removeValue(sprite, true);
mRunnable.removeValue(sprite, true);
}
/******************************************************** Layer manage ********************************************************/
private NScaler calculateScaler (NativeSpriteBackend sprite, float x, float y, float width,
float height)
{
NScaler scale = null;
if (mScaler.get(sprite) == null) {
scale = new NScaler();
mScaler.put(sprite, scale);
} else
scale = mScaler.get(sprite);
scale.sprite = sprite;
scale.xRatio = x / mOriginWidth;
scale.yRatio = y / mOriginHeight;
scale.widthRatio = width / mOriginWidth;
scale.heightRatio = height / mOriginHeight;
return scale;
}
public void bindOriginLayer (NativeSpriteBackend sprite, float originWidth, float originHeight)
{
manage(sprite);
w = mOriginWidth = originWidth;
h = mOriginHeight = originHeight;
this.x = 0;
this.y = 0;
mOriginSprite = sprite;
calculateScaler(sprite, 0, 0, w, h);
refresh();
}
public void bindOriginLayer (NativeSpriteBackend sprite)
{
manage(sprite);
w = mOriginWidth = (sprite.getWidth() == 0 ? 1 : sprite.getWidth());
h = mOriginHeight = (sprite.getHeight() == 0 ? 1 : sprite.getHeight());
this.x = 0;
this.y = 0;
mOriginSprite = sprite;
calculateScaler(sprite, 0, 0, w, h);
refresh();
}
public void bindLayer (NativeSpriteBackend sprite, float x, float y, float width, float height)
{
manage(sprite);
if (mSpriteList.size == 0) {
w = mOriginWidth = sprite.getWidth();
h = mOriginHeight = sprite.getHeight();
this.x = sprite.getX();
this.y = sprite.getY();
mOriginSprite = sprite;
calculateScaler(sprite, 0, 0, w, h);
} else {
final NScaler scale = calculateScaler(sprite, x, y, width, height);
scale.apply();
}
}
public void bindLayer (NativeSpriteBackend sprite)
{
manage(sprite);
if (mSpriteList.size == 0) {
bindOriginLayer(sprite);
} else {
final NScaler scale = calculateScaler(sprite, sprite.getX(), sprite.getY(),
sprite.getWidth(), sprite.getHeight());
scale.apply();
}
}
public void bindLayer (NativeSpriteBackend sprite, int id, float x, float y, float width,
float height)
{
if (id > mSpriteList.size)
return;
else if (id == mSpriteList.size) {
bindLayer(sprite, x, y, width, height);
}
manage(sprite);
mScaler.remove(mSpriteList.removeIndex(id));
if (id == 0) {
w = mOriginWidth = sprite.getWidth();
h = mOriginHeight = sprite.getHeight();
this.x = sprite.getX();
this.y = sprite.getY();
mOriginSprite = sprite;
calculateScaler(sprite, 0, 0, w, h);
refresh();
} else {
final NScaler scale = calculateScaler(sprite, x, y, width, height);
scale.apply();
}
}
public void apply (NativeSpriteBackend sprite, float x, float y, float width, float height)
{
if (!mSpriteList.contains(sprite, true))
return;
if (sprite != mOriginSprite) {
NScaler scale = mScaler.get(sprite);
scale.xRatio = x / mOriginWidth;
scale.yRatio = y / mOriginHeight;
scale.widthRatio = width / mOriginWidth;
scale.heightRatio = height / mOriginHeight;
scale.apply();
} else {
setSize(width, height);
}
}
public void apply (NativeSpriteBackend sprite, float width, float height)
{
if (!mSpriteList.contains(sprite, true))
return;
if (sprite != mOriginSprite) {
NScaler scale = mScaler.get(sprite);
scale.widthRatio = width / mOriginWidth;
scale.heightRatio = height / mOriginHeight;
scale.apply();
} else {
setSize(width, height);
}
}
public NativeSpriteBackend getSprite (int id)
{
return mSpriteList.get(id);
}
public int getLayerId (NativeSpriteBackend sprite)
{
return mSpriteList.indexOf(sprite, true);
}
/******************************************************** Color method ********************************************************/
public void setColor (float r, float g, float b, float a)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setColor(r, g, b, a);
}
public void setColor (Color color)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setColor(color);
}
public void setColor (Color[] color, int[] layer)
{
if (color.length != layer.length)
throw new EasyGEngineRuntimeException("Color length must be the same with layer length");
int j = 0;
for (NativeSpriteBackend sprite : mSpriteList) {
sprite.setColor(color[j]);
j++;
}
}
public void setColor (Color color, int[] layer)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setColor(color);
}
public void setColor (float r, float g, float b, float a, int[] layer)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setColor(r, g, b, a);
}
public NSpriter setColor (Color color, int layer)
{
mSpriteList.get(layer).setColor(color);
return this;
}
public NSpriter setColor (float r, float g, float b, float a, int layer)
{
mSpriteList.get(layer).setColor(r, g, b, layer);
return this;
}
/******************************************************** Configuration ********************************************************/
@Override
public void setBounds (float x, float y, float width, float height)
{
final float deltaX = x - this.x;
final float deltaY = y - this.y;
this.x = x;
this.y = y;
this.w = width;
this.h = height;
mOriginSprite.setSize(width, height);
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translate(deltaX, deltaY);
refresh();
}
@Override
public void setSize (float width, float height)
{
this.w = width;
this.h = height;
mOriginSprite.setSize(width, height);
refresh();
}
@Override
public void setPosition (float x, float y)
{
final float deltaX = x - this.x;
final float deltaY = y - this.y;
this.x = x;
this.y = y;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translate(deltaX, deltaY);
}
public void setX (float x)
{
final float deltaX = x - this.x;
this.x = x;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translateX(deltaX);
}
@Override
public void setY (float y)
{
final float deltaY = y - this.y;
this.y = y;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translateY(deltaY);
}
@Override
public void translate (float xAmount, float yAmount)
{
this.x += xAmount;
this.y += yAmount;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translate(xAmount, yAmount);
}
@Override
public void translateX (float xAmount)
{
this.x += xAmount;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translateX(xAmount);
}
@Override
public void translateY (float yAmount)
{
this.y += yAmount;
for (NativeSpriteBackend sprite : mSpriteList)
sprite.translateY(yAmount);
}
// ------------------------------------------------------
@Override
public void setOrigin (float originX, float originY)
{
mOriginSprite.setOrigin(originX, originY);
float newOriginX;
float newOriginY;
for (NativeSpriteBackend sprite : mSpriteList) {
newOriginX = sprite.getX() - x;
newOriginY = sprite.getY() - y;
sprite.setOrigin(originX - newOriginX, originY - newOriginY);
}
}
public void setOrigin (int layer, float originX, float originY)
{
mSpriteList.get(layer).setOrigin(originX, originY);
}
// ------------------------------------------------------
@Override
public void setRotation (float degree)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setRotation(degree);
}
public NSpriter setRotation (int layer, float degree)
{
mSpriteList.get(layer).setRotation(degree);
return this;
}
// ------------------------------------------------------
@Override
public void rotate (float degree)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.rotate(degree);
}
public void rotate (int layer, float degree)
{
mSpriteList.get(layer).rotate(degree);
}
// ------------------------------------------------------
@Override
public void setScale (float scaleXY)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setScale(scaleXY);
}
@Override
public void setScale (float scaleX, float scaleY)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.setScale(scaleX, scaleY);
}
@Override
public void scale (float amount)
{
for (NativeSpriteBackend sprite : mSpriteList)
sprite.scale(amount);
}
public void setScale (int layer, float scaleXY)
{
mSpriteList.get(layer).setScale(scaleXY);
}
public void setScale (int layer, float scaleX, float scaleY)
{
mSpriteList.get(layer).setScale(scaleX, scaleY);
}
public void scale (int layer, float amount)
{
mSpriteList.get(layer).scale(amount);
}
/******************************************************** Getter ********************************************************/
@Override
public float[] getVertices ()
{
return mOriginSprite.getVertices();
}
@Override
public float getX ()
{
return x;
}
public float getX (int layer)
{
return mSpriteList.get(layer).getX();
}
@Override
public float getCenterX ()
{
return mOriginSprite.getCenterX();
}
public float getCenterX (int layer)
{
return mSpriteList.get(layer).getCenterX();
}
@Override
public float getY ()
{
return y;
}
public float getY (int layer)
{
return mSpriteList.get(layer).getY();
}
@Override
public float getCenterY ()
{
return mOriginSprite.getCenterY();
}
public float getCenterY (int layer)
{
return mSpriteList.get(layer).getCenterY();
}
@Override
public float getWidth ()
{
return w;
}
public float getWidth (int layer)
{
return mSpriteList.get(layer).getWidth();
}
@Override
public float getHeight ()
{
return h;
}
public float getHeight (int layer)
{
return mSpriteList.get(layer).getHeight();
}
@Override
public float getOriginX ()
{
return mOriginSprite.getOriginX();
}
public float getOriginX (int layer)
{
return mSpriteList.get(layer).getOriginX();
}
@Override
public float getOriginY ()
{
return mOriginSprite.getOriginY();
}
public float getOriginY (int layer)
{
return mSpriteList.get(layer).getOriginY();
}
@Override
public float getRotation ()
{
return mOriginSprite.getRotation();
}
public float getRotation (int layer)
{
return mSpriteList.get(layer).getRotation();
}
@Override
public float getScaleX ()
{
return mOriginSprite.getScaleX();
}
public float getScaleX (int layer)
{
return mSpriteList.get(layer).getScaleX();
}
@Override
public float getScaleY ()
{
return mOriginSprite.getScaleY();
}
public float getScaleY (int layer)
{
return mSpriteList.get(layer).getScaleY();
}
public int getSize ()
{
return mSpriteList.size;
}
/********************************************************
*
********************************************************/
@Deprecated
public Rectangle getBoundingRectangle ()
{
return null;
}
@Deprecated
public float[] getBoundingFloatRect (float offset)
{
return null;
}
@Deprecated
public Circle getBoundingCircle ()
{
return null;
}
/******************************************************** Drawing method ********************************************************/
public NSpriter setDrawableLayer (NativeSpriteBackend... list)
{
mDrawable.clear();
for (NativeSpriteBackend s : list) {
if (mSpriteList.contains(s, true) && !mDrawable.contains(s, true))
mDrawable.add(s);
}
return this;
}
public NSpriter addDrawableLayer (NativeSpriteBackend s)
{
if (mSpriteList.contains(s, true) && !mDrawable.contains(s, true))
mDrawable.add(s);
return this;
}
public NSpriter removeDrawableLayer (NativeSpriteBackend... list)
{
for (NativeSpriteBackend s : list)
mDrawable.removeValue(s, true);
return this;
}
public Array<NativeSpriteBackend> getDrawbleLayer ()
{
return mDrawable;
}
public void clearDrawable ()
{
stop();
mDrawable.clear();
}
public void draw (SpriteBatch batch)
{
for (NativeSpriteBackend s : mDrawable) {
s.draw(batch);
}
}
@Override
public void draw (SpriteBatch batch, float alpha)
{
for (NativeSpriteBackend s : mDrawable)
s.draw(batch, alpha);
}
/******************************************************** Animator method ********************************************************/
public NSpriter setRunnableLayer (NativeSpriteBackend... list)
{
mRunnable.clear();
for (NativeSpriteBackend s : list) {
if (mSpriteList.contains(s, true) && !mRunnable.contains(s, true))
mRunnable.add(s);
}
return this;
}
public NSpriter addRunnableLayer (NativeSpriteBackend s)
{
if (mSpriteList.contains(s, true) && !mRunnable.contains(s, true))
mRunnable.add(s);
return this;
}
public NSpriter removeRunnableLayer (NativeSpriteBackend... list)
{
for (NativeSpriteBackend s : list)
mRunnable.removeValue(s, true);
return this;
}
public void clearRunnable ()
{
mRunnable.clear();
}
public Array<NativeSpriteBackend> getRunnableLayer ()
{
return mRunnable;
}
public void setFrameDuration (float frameDuration)
{
for (NativeSpriteBackend s : mRunnable)
((Animator) s).setFrameDuration(frameDuration);
}
public void start ()
{
RUN = true;
for (NativeSpriteBackend s : mRunnable)
((Animator) s).start();
}
public void start (float frameDuration)
{
RUN = true;
for (NativeSpriteBackend s : mRunnable)
((Animator) s).start(frameDuration);
}
@Override
public void start (float frameDuration, int playMode)
{
RUN = true;
for (NativeSpriteBackend s : mRunnable)
((Animator) s).start(frameDuration, playMode);
}
@Override
public void pause ()
{
RUN = false;
}
@Override
public boolean isRunning ()
{
return RUN;
}
public void stop ()
{
RUN = false;
resetFrame();
}
public void switchState ()
{
RUN = !RUN;
}
public void resetFrame ()
{
for (NativeSpriteBackend s : mRunnable)
((Animator) s).resetFrame();
}
public void resetFrame (NativeSpriteBackend... layers)
{
for (NativeSpriteBackend s : layers)
((Animator) s).resetFrame();
}
public void update (float delta)
{
for (int i = 0; i < mSpriteList.size; i++)
mSpriteList.get(i).update(delta);
// ============= update updatable =============
for (int i = 0, n = mUpdater.size; i < n; i++) {
final Updater tmp = mUpdater.get(i);
if (!tmp.isStoped())
tmp.update(this, delta);
else {
mUpdater.removeValue(tmp, true);
--i;
--n;
}
}
}
public void postUpdater (Updater updater)
{
if (mUpdater.contains(updater, true))
return;
updater.start();
this.mUpdater.add(updater);
}
public int sizeUpdater ()
{
return mUpdater.size;
}
public void noUpdater ()
{
this.mUpdater.clear();
}
/********************************************************
*
********************************************************/
@Override
public void reset ()
{
stop();
clear();
mScaler.clear();
mDrawable.clear();
mRunnable.clear();
}
@Override
public void dispose ()
{
super.dispose();
mScaler.clear();
mDrawable.clear();
mRunnable.clear();
mOriginSprite = null;
}
private void refresh ()
{
Values<NScaler> list = mScaler.values();
for (NScaler s : list)
s.apply();
}
class NScaler
{
float xRatio;
float yRatio;
float widthRatio;
float heightRatio;
NativeSpriteBackend sprite;
void apply ()
{
sprite.setBounds(x + xRatio * w, y + yRatio * h, widthRatio * w, heightRatio * h);
}
String info ()
{
return "xRatio : " + xRatio + " " + "yRatio : " + yRatio + " " + "widthRatio : "
+ widthRatio + " " + "heightRatio : " + heightRatio + " ";
}
}
}