package stu.tnt.gdx.graphics.graphics2d; import stu.tnt.gdx.utils.Animator; import stu.tnt.gdx.utils.Updater; import stu.tnt.gdx.utils.exception.EasyGEngineRuntimeException; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Circle; import com.badlogic.gdx.math.Rectangle; 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(Batch batch) { for (NativeSpriteBackend s : mDrawable) { s.draw(batch); } } @Override public void draw(Batch 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, Animation.PlayMode 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; } @Override public void removeUpdater(Updater updater) { mUpdater.removeValue(updater, true); } 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 + " "; } } /******************** deprecated ********************/ @Deprecated public int getFrameNumber() { return 0; } @Deprecated public TextureRegion[] getFrames() { return null; } }