All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bladecoder.engine.model.AtlasRenderer Maven / Gradle / Ivy

There is a newer version: 4.3.1
Show newest version
/*******************************************************************************
 * Copyright 2014 Rafael Garcia Moreno.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.bladecoder.engine.model;

import java.util.ArrayList;
import java.util.HashMap;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;
import com.bladecoder.engine.actions.ActionCallback;
import com.bladecoder.engine.actions.ActionCallbackQueue;
import com.bladecoder.engine.anim.AnimationDesc;
import com.bladecoder.engine.anim.AtlasAnimationDesc;
import com.bladecoder.engine.anim.FATween;
import com.bladecoder.engine.anim.Tween;
import com.bladecoder.engine.assets.EngineAssetManager;
import com.bladecoder.engine.util.EngineLogger;
import com.bladecoder.engine.util.RectangleRenderer;
import com.bladecoder.engine.util.SerializationHelper;
import com.bladecoder.engine.util.SerializationHelper.Mode;

public class AtlasRenderer extends AnimationRenderer {

	private AtlasRegion tex;
	private FATween faTween;

	private int currentFrameIndex;

	public AtlasRenderer() {

	}

	@Override
	public String[] getInternalAnimations(AnimationDesc anim) {
		retrieveSource(anim.source);

		TextureAtlas atlas = EngineAssetManager.getInstance().getTextureAtlas(anim.source);

		Array animations = atlas.getRegions();
		ArrayList l = new ArrayList();

		for (int i = 0; i < animations.size; i++) {
			AtlasRegion a = animations.get(i);
			if (!l.contains(a.name))
				l.add(a.name);
		}

		return l.toArray(new String[l.size()]);
	}

	@Override
	public void update(float delta) {
		if (faTween != null) {
			faTween.update(delta);
			if (faTween.isComplete()) {
				faTween = null;
				computeBbox();
			}
		}
	}

	public void setFrame(int i) {
		currentFrameIndex = i;
		tex = ((AtlasAnimationDesc) currentAnimation).regions.get(i);
	}

	@Override
	public void draw(SpriteBatch batch, float x, float y, float scale, float rotation, Color tint) {

		float dx = getAlignDx(getWidth(), orgAlign);
		float dy = getAlignDy(getHeight(), orgAlign);
		
		if (tex == null) {			
			RectangleRenderer.draw(batch, x + dx * scale , y + dy * scale, getWidth() * scale, getHeight() * scale, Color.RED);
			
			return;
		}



		x = x + tex.offsetX + dx;
		y = y + tex.offsetY + dy;

		if (tint != null)
			batch.setColor(tint);

		batch.draw(tex, x, y, -dx - tex.offsetX, -dy - tex.offsetY, tex.packedWidth, tex.packedHeight,
				flipX ? -scale : scale, scale, rotation);

		if (tint != null)
			batch.setColor(Color.WHITE);
	}

	@Override
	public float getWidth() {
		if (tex == null)
			return super.getWidth();

		return tex.originalWidth;
	}

	@Override
	public float getHeight() {
		if (tex == null)
			return super.getHeight();

		return tex.originalHeight;
	}

	@Override
	public void startAnimation(String id, Tween.Type repeatType, int count, ActionCallback cb) {

		if (id == null)
			id = initAnimation;

		AtlasAnimationDesc fa = getAnimation(id);

		if (fa == null) {
			EngineLogger.error("AnimationDesc not found: " + id);

			return;
		}

		if (currentAnimation != null && currentAnimation.disposeWhenPlayed) {
			disposeSource(currentAnimation.source);
			((AtlasAnimationDesc) currentAnimation).regions = null;
		}

		currentAnimation = fa;

		// If the source is not loaded. Load it.
		if (fa.regions == null) {

			retrieveFA(fa);

			if (fa.regions == null || fa.regions.size == 0) {
				EngineLogger.error(currentAnimation.id + " has no regions in ATLAS " + currentAnimation.source);
				fanims.remove(currentAnimation.id);
			}
		}

		if (fa.regions.size == 1 || fa.duration == 0.0) {

			setFrame(0);
			computeBbox();

			if (cb != null) {
				ActionCallbackQueue.add(cb);
			}

			return;
		}

		if (repeatType == Tween.Type.SPRITE_DEFINED) {
			repeatType = currentAnimation.animationType;
			count = currentAnimation.count;
		}

		faTween = new FATween();
		faTween.start(this, repeatType, count, currentAnimation.duration, cb);

		if (repeatType == Tween.Type.REVERSE)
			setFrame(getNumFrames() - 1);
		else
			setFrame(0);

		computeBbox();
	}

	public int getNumFrames() {
		return ((AtlasAnimationDesc) currentAnimation).regions.size;
	}

	private AtlasAnimationDesc getAnimation(String id) {
		AnimationDesc fa = fanims.get(id);
		flipX = false;

		if (fa == null) {
			// Search for flipped
			String flipId = AnimationDesc.getFlipId(id);

			fa = fanims.get(flipId);

			if (fa != null)
				flipX = true;
			else {
				// search for .left if .frontleft not found and viceversa
				StringBuilder sb = new StringBuilder();

				if (id.endsWith(AnimationDesc.FRONTLEFT)) {
					sb.append(id.substring(0, id.lastIndexOf('.') + 1));
					sb.append(AnimationDesc.LEFT);
				} else if (id.endsWith(AnimationDesc.FRONTRIGHT)) {
					sb.append(id.substring(0, id.lastIndexOf('.') + 1));
					sb.append(AnimationDesc.RIGHT);
				} else if (id.endsWith(AnimationDesc.BACKLEFT) || id.endsWith(AnimationDesc.BACKRIGHT)) {
					sb.append(id.substring(0, id.lastIndexOf('.') + 1));
					sb.append(AnimationDesc.BACK);
				} else if (id.endsWith(AnimationDesc.LEFT)) {
					sb.append(id.substring(0, id.lastIndexOf('.') + 1));
					sb.append(AnimationDesc.FRONTLEFT);
				} else if (id.endsWith(AnimationDesc.RIGHT)) {
					sb.append(id.substring(0, id.lastIndexOf('.') + 1));
					sb.append(AnimationDesc.FRONTRIGHT);
				}

				String s = sb.toString();

				fa = fanims.get(s);

				if (fa == null) {
					// Search for flipped
					flipId = AnimationDesc.getFlipId(s);

					fa = fanims.get(flipId);

					if (fa != null)
						flipX = true;
				}
			}
		}

		return (AtlasAnimationDesc) fa;
	}

	@Override
	public void startAnimation(String id, Tween.Type repeatType, int count, ActionCallback cb, String direction) {
		StringBuilder sb = new StringBuilder(id);

		// if dir==null gets the current animation direction
		if (direction == null) {
			int idx = getCurrentAnimationId().indexOf('.');

			if (idx != -1) {
				String dir = getCurrentAnimationId().substring(idx);
				sb.append(dir);
			}
		} else {
			sb.append('.');
			sb.append(direction);
		}

		String anim = sb.toString();

		if (getAnimation(anim) == null) {
			anim = id;
		}

		startAnimation(anim, repeatType, count, null);
	}

	@Override
	public void startAnimation(String id, Tween.Type repeatType, int count, ActionCallback cb, Vector2 p0, Vector2 pf) {
		startAnimation(id, repeatType, count, cb,
				AnimationDesc.getDirectionString(p0, pf, AnimationDesc.getDirs(id, fanims)));
	}

	private void loadSource(String source) {
		CacheEntry entry = sourceCache.get(source);

		if (entry == null) {
			entry = new CacheEntry();
			sourceCache.put(source, entry);
		}

		if (entry.refCounter == 0)
			EngineAssetManager.getInstance().loadAtlas(source);

		entry.refCounter++;
	}

	private void retrieveFA(AtlasAnimationDesc fa) {
		retrieveSource(fa.source);
		fa.regions = EngineAssetManager.getInstance().getRegions(fa.source, fa.id);
	}

	private void retrieveSource(String source) {
		CacheEntry entry = sourceCache.get(source);

		if (entry == null || entry.refCounter < 1) {
			loadSource(source);
			EngineAssetManager.getInstance().finishLoading();
		}
	}

	private void disposeSource(String source) {
		CacheEntry entry = sourceCache.get(source);

		if (entry.refCounter == 1) {
			EngineAssetManager.getInstance().disposeAtlas(source);
		}

		entry.refCounter--;
	}

	@Override
	public void loadAssets() {
		for (AnimationDesc fa : fanims.values()) {
			if (fa.preload)
				loadSource(fa.source);
		}

		if (currentAnimation != null && !currentAnimation.preload) {
			loadSource(currentAnimation.source);
		} else if (currentAnimation == null && initAnimation != null) {
			String a = initAnimation;

			if (flipX) {
				a = AnimationDesc.getFlipId(a);
			}

			AnimationDesc fa = fanims.get(a);

			if (fa != null && !fa.preload)
				loadSource(fa.source);
		}
	}

	@Override
	public void retrieveAssets() {
		for (AnimationDesc fa : fanims.values()) {
			if (fa.preload)
				retrieveFA((AtlasAnimationDesc) fa);
		}

		if (currentAnimation != null && !currentAnimation.preload) {
			retrieveFA((AtlasAnimationDesc) currentAnimation);
		} else if (currentAnimation == null && initAnimation != null) {
			String a = initAnimation;

			if (flipX) {
				a = AnimationDesc.getFlipId(a);
			}

			AtlasAnimationDesc fa = (AtlasAnimationDesc) fanims.get(a);

			if (fa != null && !fa.preload)
				retrieveFA(fa);
		}

		if (currentAnimation != null) {
			setFrame(currentFrameIndex);
		} else if (initAnimation != null) {
			startAnimation(initAnimation, Tween.Type.SPRITE_DEFINED, 1, null);
		}

		computeBbox();
	}

	@Override
	public void dispose() {
		for (String key : sourceCache.keySet()) {
			if (sourceCache.get(key).refCounter > 0)
				EngineAssetManager.getInstance().disposeAtlas(key);
		}

		sourceCache.clear();
	}

	@Override
	public void write(Json json) {
		super.write(json);

		if (SerializationHelper.getInstance().getMode() == Mode.MODEL) {

		} else {
			json.writeValue("currentFrameIndex", currentFrameIndex);

			if(faTween != null)
				json.writeValue("faTween", faTween);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void read(Json json, JsonValue jsonData) {
		super.read(json, jsonData);

		if (SerializationHelper.getInstance().getMode() == Mode.MODEL) {
			fanims = json.readValue("fanims", HashMap.class, AtlasAnimationDesc.class, jsonData);
		} else {

			currentFrameIndex = json.readValue("currentFrameIndex", Integer.class, jsonData);
			faTween = json.readValue("faTween", FATween.class, jsonData);

			if (faTween != null)
				faTween.setTarget(this);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy