/** * Copyright 2008 - 2010 * * 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.1 */ package loon.component; import loon.LSystem; import loon.LTexture; import loon.action.map.Field2D; import loon.action.sprite.ISprite; import loon.action.sprite.Sprites; import loon.canvas.Canvas; import loon.canvas.Image; import loon.geom.RectBox; import loon.opengl.GLEx; import loon.utils.ArrayMap; import loon.utils.LIterator; import loon.utils.MathUtils; import loon.utils.timer.LTimer; public class LLayer extends ActorLayer { private Sprites _sprites; private float width; private float height; private float colorAlpha; private float actorX; private float actorY; private float actorWidth; private float actorHeight; protected boolean actorDrag, pressed; private Actor dragActor; private LTimer timer = new LTimer(0); private boolean isTouchClick; private Actor thing = null; private boolean isListener = false; private boolean isVSync; private int paintSeq = 0; public LLayer(int w, int h) { this(0, 0, w, h); } public LLayer(int w, int h, int size) { this(0, 0, w, h, true, size); } public LLayer(int w, int h, boolean bounded) { this(0, 0, w, h, bounded); } public LLayer(int x, int y, int w, int h) { this(x, y, w, h, true); } public LLayer(int x, int y, int w, int h, boolean bounded) { this(x, y, w, h, bounded, 1); } public LLayer(int x, int y, int w, int h, boolean bounded, int size) { super(x, y, w, h, size, bounded); this.setLocation(x, y); this.actorDrag = true; this.visible = true; this.customRendering = true; this.isTouchClick = true; this._isLimitMove = true; this.isVSync = true; this.setElastic(true); this.setLocked(true); this.setLayer(100); } private void allocateSprites() { if (_sprites == null) { this._sprites = new Sprites(getScreen() == null ? LSystem .getProcess().getScreen() : getScreen(), getWidth(), getHeight()); } } public LLayer addSprite(ISprite s) { allocateSprites(); _sprites.add(s); return this; } public LLayer addSprite(ISprite... s) { for (int i = 0; i < s.length; i++) { addSprite(s[i]); } return this; } public LLayer addSpriteAt(ISprite s, float x, float y) { allocateSprites(); _sprites.addAt(s, x, y); return this; } public LLayer removeSprite(ISprite s) { allocateSprites(); _sprites.remove(s); return this; } public LLayer removeSprite(int idx) { allocateSprites(); _sprites.remove(idx); return this; } public LLayer removeSpriteName(String name) { allocateSprites(); _sprites.removeName(name); return this; } public LLayer removeSpriteAll() { allocateSprites(); _sprites.removeAll(); return this; } public void setVSync(boolean vsync) { this.isVSync = vsync; } public boolean isVSync() { return isVSync; } public void downClick(int x, int y) { if (Click != null) { Click.DownClick(this, x, y); } } public void upClick(int x, int y) { if (Click != null) { Click.UpClick(this, x, y); } } public void drag(int x, int y) { if (Click != null) { Click.DragClick(this, x, y); } } public void downKey() { } public void upKey() { } /** * 设定动作触发延迟时间 * * @param delay */ public void setDelay(long delay) { timer.setDelay(delay); } /** * 返回动作触发延迟时间 * * @return */ public long getDelay() { return timer.getDelay(); } /** * 动作处理 * * @param elapsedTime */ @Override public void action(long elapsedTime) { } @Override public void update(long elapsedTime) { if (visible) { super.update(elapsedTime); if (timer.action(this.elapsedTime = elapsedTime)) { action(elapsedTime); if (!isVSync) { LIterator<Actor> it = objects.iterator(); for (; it.hasNext();) { thing = (Actor) it.next(); if (!thing.visible) { continue; } thing.update(elapsedTime); } } if (_sprites != null) { _sprites.update(elapsedTime); } } } } @Override public void createCustomUI(GLEx g, int x, int y, int w, int h) { if (!visible) { return; } paintObjects(g, x, y, x + w, y + h); if (x == 0 && y == 0) { paint(g); if (_sprites != null) { _sprites.paint(g, x, y, w, h); } } else { try { g.translate(x, y); paint(g); if (_sprites != null) { _sprites.paint(g, x, y, w, h); } } finally { g.translate(-x, -y); } } } public void paint(GLEx g) { } public void paintObjects(GLEx g, int minX, int minY, int maxX, int maxY) { synchronized (objects) { LIterator<Actor> it = objects.iterator(); for (; it.hasNext();) { thing = it.next(); if (!thing.visible) { continue; } isListener = (thing.actorListener != null); if (isVSync) { if (isListener) { thing.actorListener.update(elapsedTime); } thing.update(elapsedTime); } RectBox rect = thing.getRectBox(); actorX = minX + thing.getX(); actorY = minY + thing.getY(); actorWidth = rect.width; actorHeight = rect.height; if (actorX + actorWidth < minX || actorX > maxX || actorY + actorHeight < minY || actorY > maxY) { continue; } LTexture actorImage = thing.getImage(); if (actorImage != null) { width = actorImage.getWidth(); height = actorImage.getHeight(); thing.setLastPaintSeqNum(paintSeq++); colorAlpha = thing.getAlpha(); if (colorAlpha != 1f) { g.setAlpha(colorAlpha); } g.draw(actorImage, actorX, actorY, width, height, baseColor == null ? thing.filterColor : baseColor .mul(thing.filterColor), thing .getRotation(), thing.scaleX, thing.scaleY, thing.flipX, thing.flipY); if (colorAlpha != 1f) { g.setAlpha(1f); } } if (thing.isConsumerDrawing) { if (actorX == 0 && actorY == 0) { thing.draw(g); if (isListener) { thing.actorListener.draw(g); } } else { try { g.saveTx(); g.translate(actorX, actorY); thing.draw(g); if (isListener) { thing.actorListener.draw(g); } } finally { g.translate(-actorX, -actorY); g.restoreTx(); } } } } } } public void moveCamera(Actor actor) { moveCamera(actor.x(), actor.y()); } public void centerOn(final Actor object) { object.setLocation(getWidth() / 2 - object.getWidth() / 2, getHeight() / 2 - object.getHeight() / 2); } public void topOn(final Actor object) { object.setLocation(getWidth() / 2 - object.getWidth() / 2, 0); } public void leftOn(final Actor object) { object.setLocation(0, getHeight() / 2 - object.getHeight() / 2); } public void rightOn(final Actor object) { object.setLocation(getWidth() - object.getWidth(), getHeight() / 2 - object.getHeight() / 2); } public void bottomOn(final Actor object) { object.setLocation(getWidth() / 2 - object.getWidth() / 2, getHeight() - object.getHeight()); } public void setField2DBackground(Field2D field, ArrayMap pathMap) { setField2DBackground(field, pathMap, null); } public void setField2DBackground(Field2D field, ArrayMap pathMap, String fileName) { setField2D(field); Image background = null; if (fileName != null) { Image tmp = Image.createImage(fileName); background = setTileBackground(tmp, true); if (tmp != null) { tmp.close(); tmp = null; } } else { background = Image.createImage((int) getWidth(), (int) getHeight()); } Canvas g = background.getCanvas(); for (int i = 0; i < field.getWidth(); i++) { for (int j = 0; j < field.getHeight(); j++) { int index = field.getType(j, i); Object o = pathMap.get(index); if (o != null) { if (o instanceof Image) { g.draw(((Image) o), field.tilesToWidthPixels(i), field.tilesToHeightPixels(j)); } else if (o instanceof Actor) { addObject(((Actor) o), field.tilesToWidthPixels(i), field.tilesToHeightPixels(j)); } } } } g.close(); setBackground(background.texture()); if (background != null) { background.close(); background = null; } } public void setTileBackground(String fileName) { setTileBackground(Image.createImage(fileName)); } public void setTileBackground(Image image) { setTileBackground(image, false); } public Image setTileBackground(Image image, boolean isReturn) { if (image == null) { return null; } int layerWidth = (int) getWidth(); int layerHeight = (int) getHeight(); int tileWidth = image.getWidth(); int tileHeight = image.getHeight(); Image tempImage = Image.createImage(layerWidth, layerHeight); Canvas g = tempImage.getCanvas(); for (int x = 0; x < layerWidth; x += tileWidth) { for (int y = 0; y < layerHeight; y += tileHeight) { g.draw(image, x, y); } } g.close(); if (isReturn) { return tempImage; } setBackground(tempImage.texture()); if (tempImage != null) { tempImage.close(); tempImage = null; } return null; } public int getScroll(RectBox visibleRect, int orientation, int direction) { int cellSize = this.getCellSize(); double scrollPos = 0.0D; if (orientation == 0) { if (direction < 0) { scrollPos = visibleRect.getMinX(); } else if (direction > 0) { scrollPos = visibleRect.getMaxX(); } } else if (direction < 0) { scrollPos = visibleRect.getMinY(); } else if (direction > 0) { scrollPos = visibleRect.getMaxY(); } int increment = MathUtils.abs((int) MathUtils.IEEEremainder(scrollPos, cellSize)); if (increment == 0) { increment = cellSize; } return increment; } public Actor getClickActor() { return dragActor; } @Override protected void processTouchEntered() { this.pressed = true; } @Override protected void processTouchExited() { this.pressed = false; } @Override protected void processKeyPressed() { if (this.isSelected()) { this.downKey(); } } @Override protected void processKeyReleased() { if (this.isSelected()) { this.upKey(); } } @Override protected void processTouchPressed() { if (!isTouchClick) { return; } super.processTouchPressed(); if (!input.isMoving()) { int dx = this.input.getTouchX() - this.getScreenX(); int dy = this.input.getTouchY() - this.getScreenY(); dragActor = getSynchronizedObject(dx, dy); if (dragActor != null) { if (dragActor.isClick()) { dragActor.downClick(dx, dy); if (dragActor.actorListener != null) { dragActor.actorListener.downClick(dx, dy); } } } this.downClick(dx, dy); } } @Override protected void processTouchReleased() { if (!isTouchClick) { return; } super.processTouchReleased(); if (!input.isMoving()) { int dx = this.input.getTouchX() - this.getScreenX(); int dy = this.input.getTouchY() - this.getScreenY(); dragActor = getSynchronizedObject(dx, dy); if (dragActor != null) { if (dragActor.isClick()) { dragActor.upClick(dx, dy); if (dragActor.actorListener != null) { dragActor.actorListener.upClick(dx, dy); } } } this.upClick(dx, dy); this.dragActor = null; } } @Override protected void processTouchDragged() { int dropX = 0; int dropY = 0; if (!locked) { boolean moveActor = false; if (actorDrag) { synchronized (objects) { dropX = this.input.getTouchX() - this.getScreenX(); dropY = this.input.getTouchY() - this.getScreenY(); if (dragActor == null) { dragActor = getSynchronizedObject(dropX, dropY); } if (dragActor != null && dragActor.isDrag()) { synchronized (dragActor) { objects.sendToFront(dragActor); RectBox rect = dragActor.getBoundingRect(); int dx = dropX - (rect.width / 2); int dy = dropY - (rect.height / 2); if (dragActor.getLLayer() != null) { dragActor.setLocation(dx, dy); dragActor.drag(dropX, dropY); if (dragActor.actorListener != null) { dragActor.actorListener.drag(dropX, dropY); } } moveActor = true; } } } } if (!moveActor) { synchronized (input) { dropX = this.input.getTouchDX(); dropY = this.input.getTouchDY(); if (isNotMoveInScreen(dropX + this.x(), dropY + this.y())) { return; } if (getContainer() != null) { getContainer().sendToFront(this); } this.move(dropX, dropY); this.drag(dropX, dropY); } } } else { if (!actorDrag) { return; } synchronized (objects) { dropX = this.input.getTouchX() - this.getScreenX(); dropY = this.input.getTouchY() - this.getScreenY(); if (dragActor == null) { dragActor = getSynchronizedObject(dropX, dropY); } if (dragActor != null && dragActor.isDrag()) { synchronized (dragActor) { objects.sendToFront(dragActor); RectBox rect = dragActor.getBoundingRect(); int dx = dropX - (rect.width / 2); int dy = dropY - (rect.height / 2); if (dragActor.getLLayer() != null) { dragActor.setLocation(dx, dy); dragActor.drag(dropX, dropY); if (dragActor.actorListener != null) { dragActor.actorListener.drag(dropX, dropY); } } } } } } super.dragClick(); } public boolean isTouchPressed() { return this.pressed; } public boolean isActorDrag() { return actorDrag; } public void setActorDrag(boolean actorDrag) { this.actorDrag = actorDrag; } public boolean isLimitMove() { return _isLimitMove; } public void setLimitMove(boolean isLimitMove) { this._isLimitMove = isLimitMove; } public boolean isTouchClick() { return isTouchClick; } public void setTouchClick(boolean isTouchClick) { this.isTouchClick = isTouchClick; } public int getLayerTouchX() { return this.input.getTouchX() - this.getScreenX(); } public int getLayerTouchY() { return this.input.getTouchY() - this.getScreenY(); } @Override public void createUI(GLEx g, int x, int y, LComponent component, LTexture[] buttonImage) { } @Override public void close() { super.close(); if (collisionChecker != null) { collisionChecker.dispose(); collisionChecker = null; } if (objects != null) { Object[] o = objects.toActors(); for (int i = 0; i < o.length; i++) { Actor actor = (Actor) o[i]; if (actor != null) { actor.close(); actor = null; } } } if (_sprites != null) { _sprites.close(); } _sprites = null; } @Override public String getUIName() { return "Layer"; } }