package com.junerking.ui.actor; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Matrix3; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.Touchable; import com.junerking.ui.UISettings; public class UIWidgetGroup extends UIWidget { public UIWidgetGroup() { super(); } public UIWidgetGroup(String name) { super(name); } protected ArrayList<UIWidget> child_list = new ArrayList<UIWidget>(); public ArrayList<UIWidget> getChildrenList() { return child_list; } @Override public UIWidget findWidgetByName(String name) { if (this.name != null && this.name.equals(name)) { return this; } for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null) continue; UIWidget result = child.findWidgetByName(name); if (result != null) return result; } return null; } @Override public UIWidget findWidgetByTag(int tag_id) { if (this.tag != -1 && this.tag == tag_id) return this; for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null) continue; UIWidget result = child.findWidgetByTag(tag_id); if (result != null) return result; } return null; } @Override public UIWidget findActionWidgetByTag(int action_tag_id) { if (this.action_tag != -1 && this.action_tag == action_tag_id) return this; for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null) continue; UIWidget result = child.findActionWidgetByTag(action_tag_id); if (result != null) return result; } return null; } @Override public void prepare() { super.prepare(); for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null) continue; child.prepare(); } } public void clear() { child_list.clear(); } public void setStage(Stage stage) { super.setStage(stage); for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null) continue; child.setStage(stage); } } //========================================================================== public void addActor(UIWidget actor) { if (actor == null) return; int flag = -1; String new_name = actor.getName(); for (int i = 0; i < child_list.size(); i++) { UIWidget child = child_list.get(i); if (child == actor) { flag = 1; break; } if (isNameSame(child.getName(), new_name)) { flag = 2; break; } } if (flag == -1) { child_list.add(actor); actor.setParentWidget(this); return; } if (UISettings.DEBUG) { if (flag == 1) { new RuntimeException("this widget is added before!!!").printStackTrace(); } else if (flag == 2) { new RuntimeException("this widget has same name with others").printStackTrace(); } } } public void addActor(ArrayList<UIWidget> new_child_list, boolean clear) { if (clear) child_list.clear(); if (new_child_list == null) return; for (int i = 0, n = new_child_list.size(); i < n; i++) { addActor(new_child_list.get(i)); } } //========================================================================== @Override public void act(float delta) { super.act(delta); for (int i = 0; i < child_list.size(); i++) { UIWidget item = child_list.get(i); if (item != null) { item.act(delta); } } for (int i = 0; i < child_list.size(); i++) { UIWidget item = child_list.get(i); if (item != null && item.isMarkedRemove()) { item.setParentWidget(null); child_list.remove(i); --i; } } } private final Matrix3 localTransform = new Matrix3(); private final Matrix3 worldTransform = new Matrix3(); private final Matrix4 batchTransform = new Matrix4(); private final Matrix4 oldBatchTransform = new Matrix4(); private final Matrix4 tempBatchTransform = new Matrix4(); public boolean transform = true; private Rectangle cullingArea; public void draw(SpriteBatch batch, float parentAlpha) { if (child_list.size() == 0) return; if (transform) applyTransform(batch, computeTransform()); drawChildren(batch, parentAlpha); if (transform) resetTransform(batch); } protected void drawChildren(SpriteBatch batch, float parentAlpha) { parentAlpha *= getColor().a; Rectangle cullingArea = this.cullingArea; if (cullingArea != null) { // Draw children only if inside culling area. float cullLeft = cullingArea.x; float cullRight = cullLeft + cullingArea.width; float cullBottom = cullingArea.y; float cullTop = cullBottom + cullingArea.height; if (transform) { for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null || !child.isVisible()) continue; float x = child.getX(), y = child.getY(); if (x <= cullRight && y <= cullTop && x + child.getWidth() >= cullLeft && y + child.getHeight() >= cullBottom) child.draw(batch, parentAlpha); } batch.flush(); } else { // No transform for this group, offset each child. float offsetX = getX(), offsetY = getY(); setX(0); setY(0); for (int i = 0, n = child_list.size(); i < n; i++) { UIWidget child = child_list.get(i); if (child == null || !child.isVisible()) continue; float x = child.getX(), y = child.getY(); if (x <= cullRight && y <= cullTop && x + child.getWidth() >= cullLeft && y + child.getHeight() >= cullBottom) { child.setX(x + offsetX); child.setY(y + offsetY); child.draw(batch, parentAlpha); child.setX(x); child.setY(y); } } setX(offsetX); setY(offsetY); } } else { // No culling, draw all children. if (transform) { for (int i = 0, n = child_list.size(); i < n; i++) { Actor child = child_list.get(i); if (child == null || !child.isVisible()) continue; child.draw(batch, parentAlpha); } batch.flush(); } else { // No transform for this group, offset each child. float offsetX = getX(), offsetY = getY(); setX(0); setY(0); for (int i = 0, n = child_list.size(); i < n; i++) { Actor child = child_list.get(i); if (child == null || !child.isVisible()) continue; float x = child.getX(), y = child.getY(); child.setX(x + offsetX); child.setY(y + offsetY); child.draw(batch, parentAlpha); child.setX(x); child.setY(y); } setX(offsetX); setY(offsetY); } } } protected void applyTransform(SpriteBatch batch, Matrix4 transform) { oldBatchTransform.set(batch.getTransformMatrix()); batch.setTransformMatrix(tempBatchTransform.set(oldBatchTransform).mul(transform)); // System.out.println(name + "\n" + batch.getTransformMatrix()); } protected Matrix4 computeTransform() { float originX = getOriginX(); float originY = getOriginY(); float rotation = getRotation(); float scaleX = getScaleX(); float scaleY = getScaleY(); if (originX != 0 || originY != 0) localTransform.setToTranslation(originX, originY); else localTransform.idt(); if (rotation != 0) localTransform.rotate(rotation); if (scaleX != 1 || scaleY != 1) localTransform.scale(scaleX, scaleY); if (originX != 0 || originY != 0) localTransform.translate(-originX, -originY); localTransform.trn(getX(), getY()); // Find the first parent that transforms. Group parentGroup = getParent(); while (parentGroup != null) { if (parentGroup.transform) break; parentGroup = parentGroup.getParent(); } if (parentGroup != null) { worldTransform.set(parentGroup.worldTransform); worldTransform.mul(localTransform); } else { worldTransform.set(localTransform); } // System.out.println("== " + worldTransform); batchTransform.set(worldTransform); return batchTransform; } protected void resetTransform(SpriteBatch batch) { batch.setTransformMatrix(oldBatchTransform); } public void setCullingArea(Rectangle cullingArea) { this.cullingArea = cullingArea; } //========================================================================== public void sortChildren(Comparator<Actor> comparator) { Collections.sort(child_list, comparator); } //========================================================================== protected final Vector2 point = new Vector2(); //touch事件的分发 @Override public Actor hit(float x, float y, boolean touchable) { for (int i = child_list.size() - 1; i >= 0; i--) { UIWidget child = child_list.get(i); if (child == null || !child.isVisible() || child.touchable == Touchable.disabled) continue; child.parentToLocalCoordinates(point.set(x, y)); Actor hit = child.hit(point.x, point.y, touchable); if (hit != null) { return hit; } } return super.hit(x, y, touchable); } }