/**
* Copyright 2008 - 2012
*
* 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.3.3
*/
package com.mygame;
import loon.LRelease;
import loon.LTexture;
import loon.action.sprite.SpriteBatch;
import loon.action.sprite.SpriteBatch.SpriteEffects;
import loon.canvas.LColor;
import loon.geom.RectBox;
import loon.geom.Vector2f;
public class Painter implements LRelease {
private int clipH;
private int clipW;
private int clipX;
private int clipY;
private boolean disposed;
private boolean doClip;
private int int_angle;
private float opacity;
private int savedAngle;
private float savedScaleX;
private float savedScaleY;
private float savedTranslateX;
private float savedTranslateY;
private float scaleX;
private float scaleY;
public SpriteBatch batch;
private LColor tmp_color;
private float translateX;
private float translateY;
private boolean translations;
public Painter(SpriteBatch batch) {
this.batch = batch;
this.setOpacity(1f);
}
private boolean applyClip(Vector2f pos, RectBox src, Vector2f origin,
Vector2f scale) {
int width = (int) (src.width * scale.x);
int height = (int) (src.height * scale.y);
int sx = (int) (pos.x * scale.x);
int sy = (int) (pos.y * scale.y);
if (sx < this.clipX) {
int offsetX = (int) (((this.clipX - sx)) / scale.x);
if (offsetX >= src.width) {
return false;
}
src.x += offsetX;
src.width -= offsetX;
origin.x = width / 2;
}
if (width > (this.clipX + this.clipW)) {
int offsetWidth = (int) ((((width - this.clipX) - this.clipW)) / scale.x);
if (offsetWidth >= src.width) {
return false;
}
src.width -= offsetWidth;
}
if (sy < this.clipY) {
int offsetY = (int) (((this.clipY - sy)) / scale.y);
if (offsetY >= src.height) {
return false;
}
src.y += offsetY;
src.height -= offsetY;
origin.y = height / 2;
}
if (height > (this.clipY + this.clipH)) {
int offsetHeight = (int) ((((height - this.clipY) - this.clipH)) / scale.y);
if (offsetHeight >= src.height) {
return false;
}
src.height -= offsetHeight;
}
return true;
}
private boolean applyClipFlipped(Vector2f pos, RectBox src,
Vector2f origin, Vector2f scale) {
int width = (int) (src.width * scale.x);
int height = (int) (src.height * scale.y);
int sx = (int) (pos.x * scale.x);
int sy = (int) (pos.y * scale.y);
if (sx < this.clipX) {
int offsetX = (int) (((this.clipX - sx)) / scale.x);
if (offsetX >= src.width) {
return false;
}
src.width -= offsetX;
origin.x = width / 2;
}
if (width > (this.clipX + this.clipW)) {
int offsetWidth = (int) ((((width - this.clipX) - this.clipW)) / scale.x);
if (offsetWidth >= src.width) {
return false;
}
src.x += offsetWidth;
src.width -= offsetWidth;
}
if (sy < this.clipY) {
int offsetY = (int) (((this.clipY - sy)) / scale.y);
if (offsetY >= src.height) {
return false;
}
src.y += offsetY;
src.height -= offsetY;
origin.y = height / 2;
}
if (height > (this.clipY + this.clipH)) {
int offsetHeight = (int) ((((height - this.clipY) - this.clipH)) / scale.y);
if (offsetHeight >= src.height) {
return false;
}
src.height -= offsetHeight;
}
return true;
}
public void begin() {
this.batch.begin();
this.translateX = 0f;
this.translateY = 0f;
this.scaleX = 1f;
this.scaleY = 1f;
this.int_angle = 0;
this.translations = false;
this.removeClip();
}
private void checkIfTranslate() {
if (((this.translateX != 0f) || (this.translateY != 0f))
|| (((this.scaleX != 1f) || (this.scaleY != 1f)) || (this.int_angle != 0))) {
this.translations = true;
} else {
this.translations = false;
}
}
public void close() {
this.disposed = true;
}
public void draw(LTexture texture, Vector2f pos, Vector2f origin,
RectBox src) {
if (this.doClip) {
Vector2f scale = new Vector2f(1f, 1f);
if (!this.applyClip(pos, src, origin, scale)) {
return;
}
}
this.translatePos(pos);
tmp_scale.set(this.scaleX, this.scaleY);
this.batch.draw(texture, tmp_location, src, this.tmp_color,
this.int_angle, origin, tmp_scale, SpriteEffects.None);
}
public void drawScaled(LTexture texture, Vector2f pos, Vector2f origin,
Vector2f scale, RectBox src) {
this.translatePos(pos);
tmp_scale.set(scale.x * this.scaleX, scale.y * this.scaleY);
this.batch.draw(texture, tmp_location, src, this.tmp_color,
this.int_angle, origin, scale, SpriteEffects.None);
}
public void drawScaled(LTexture texture, Vector2f pos, Vector2f origin,
Vector2f scale, RectBox src, boolean flip) {
if (this.doClip) {
boolean flag = false;
if (flip) {
flag = this.applyClipFlipped(pos, src, origin, scale);
} else {
flag = this.applyClip(pos, src, origin, scale);
}
if (!flag) {
return;
}
}
this.translatePos(pos);
tmp_scale.set(scale.x * this.scaleX, scale.y * this.scaleY);
this.batch.draw(texture, tmp_location, src, this.tmp_color,
this.int_angle, origin, scale,
flip ? SpriteEffects.FlipHorizontally : SpriteEffects.None);
}
public void drawScaledRotated(LTexture texture, Vector2f pos,
Vector2f origin, Vector2f scale, float angle, RectBox src) {
this.translatePos(pos);
angle += this.int_angle;
tmp_scale.set(scale.x * this.scaleX, scale.y * this.scaleY);
this.batch.draw(texture, tmp_location, src, this.tmp_color, angle,
origin, tmp_scale, SpriteEffects.None);
}
private Vector2f tmp_scale = new Vector2f();
public void drawScaledRotated(LTexture texture, Vector2f pos,
Vector2f origin, Vector2f scale, final float angle, RectBox src,
boolean flip) {
this.translatePos(pos);
float rotation = angle;
rotation += this.int_angle;
tmp_scale.set(scale.x * this.scaleX, scale.y * this.scaleY);
this.batch.draw(texture, tmp_location, src, this.tmp_color, rotation,
origin, tmp_scale, flip ? SpriteEffects.FlipHorizontally
: SpriteEffects.None);
}
public void end() {
this.batch.end();
}
public void removeClip() {
this.doClip = false;
}
public void restore() {
this.translateX = this.savedTranslateX;
this.translateY = this.savedTranslateY;
this.scaleX = this.savedScaleX;
this.scaleY = this.savedScaleY;
this.int_angle = this.savedAngle;
this.checkIfTranslate();
}
public void rotate(int aAngle) {
this.int_angle = aAngle;
this.checkIfTranslate();
}
public void save() {
this.savedTranslateX = this.translateX;
this.savedTranslateY = this.translateY;
this.savedScaleX = this.scaleX;
this.savedScaleY = this.scaleY;
this.savedAngle = this.int_angle;
}
public void scale(float x, float y) {
this.scaleX = x * this.scaleX;
this.scaleY = y * this.scaleY;
this.checkIfTranslate();
}
public void setClip(int x, int y, int w, int h) {
this.doClip = true;
this.clipX = x;
this.clipY = y;
this.clipW = w;
this.clipH = h;
}
public void setOpacity(float aOpacity) {
this.opacity = aOpacity;
this.tmp_color = LColor.white.mul(opacity);
}
public void translate(float x, float y) {
this.translateX += x * this.scaleX;
this.translateY += y * this.scaleY;
this.checkIfTranslate();
}
private Vector2f tmp_location = new Vector2f();
private void translatePos(Vector2f pos) {
tmp_location.set(pos.x, pos.y);
if (this.translations) {
tmp_location.x *= this.scaleX;
tmp_location.y *= this.scaleY;
tmp_location.x += this.translateX;
tmp_location.y += this.translateY;
if (this.int_angle != 0) {
float x = tmp_location.x;
float y = tmp_location.y;
tmp_location.x = ((x * GameUtils.cos(this.int_angle)) - (y * GameUtils
.sin(this.int_angle))) / 8192f;
tmp_location.y = ((x * GameUtils.sin(this.int_angle)) + (y * GameUtils
.cos(this.int_angle))) / 8192f;
}
}
}
public boolean isDisposed() {
return disposed;
}
}