@Override protected Animation next () { // if our target layer is no longer active, we're done return (_layer.parent() == null) ? null : _next; }
/** * Whether a GroupLayer hierarchy contains another layer somewhere in its depths. */ public static boolean contains (GroupLayer group, Layer layer) { while (layer != null) { layer = layer.parent(); if (layer == group) return true; } return false; }
/** * Returns the depth of the given layer in its local scene graph. A root layer (one with null * parent) will always return 0. */ public static int graphDepth (Layer layer) { int depth = -1; while (layer != null) { layer = layer.parent(); depth++; } return depth; }
/** * Returns the index of the given layer within its parent, or -1 if the parent is null. */ public static int indexInParent (Layer layer) { GroupLayer parent = layer.parent(); if (parent == null) return -1; for (int ii = parent.children()-1; ii >= 0; ii--) { if (parent.childAt(ii) == layer) return ii; } throw new AssertionError(); }
/** * Converts the supplied point from screen coordinates to coordinates * relative to the specified layer. The results are stored into {@code into} * , which is returned for convenience. */ public static Point screenToLayer(Layer layer, XY point, Point into) { Layer parent = layer.parent(); XY cur = (parent == null) ? point : screenToLayer(parent, point, into); return parentToLayer(layer, cur, into); }
/** * Converts the supplied point from coordinates relative to the specified parent to coordinates * relative to the specified child layer. The results are stored into {@code into}, which is * returned for convenience. */ public static Point parentToLayer(Layer parent, Layer layer, XY point, Point into) { into.set(point); Layer immediateParent = layer.parent(); if (immediateParent != parent) parentToLayer(parent, immediateParent, into, into); parentToLayer(layer, into, into); return into; }
/** * Removes {@code layer} from its current parent and adds it to {@code target}, modifying its * transform in the process so that it stays in the same position on the screen. */ public static void reparent (Layer layer, GroupLayer target) { Point pos = new Point(layer.tx(), layer.ty()); LayerUtil.layerToScreen(layer.parent(), pos, pos); target.add(layer); LayerUtil.screenToLayer(layer.parent(), pos, pos); layer.setTranslation(pos.x, pos.y); }
@Override public void willInit (int count) { // concatenate the transform of all layers above our target layer xform.setTransform(1, 0, 0, 1, 0, 0); Layer xlayer = layer; while (xlayer != null) { Transforms.multiply(xlayer.transform(), xform, xform); xlayer = xlayer.parent(); } xform.get(_matrix); } @Override public void init (int index, float[] data, int start) {
/** * Converts the supplied point from coordinates relative to the specified * child layer to coordinates relative to the specified parent layer. The * results are stored into {@code into}, which is returned for convenience. */ public static Point layerToParent(Layer layer, Layer parent, XY point, Point into) { into.set(point); while (layer != parent) { if (layer == null) { throw new IllegalArgumentException( "Failed to find parent, perhaps you passed parent, layer instead of " + "layer, parent?"); } into.x -= layer.originX(); into.y -= layer.originY(); layer.transform().transform(into, into); layer = layer.parent(); } return into; }
private void notifyCancel (Layer except, CaptureMode exceptMode, E source) { E oldEvent = event; event = newCancelEvent(source); try { if (bubble) { Depth depth = Depth.BELOW; for (Layer target = hitLayer; target != null; target = target.parent()) { if (target == except) depth = Depth.AT; else if (depth == Depth.AT) depth = Depth.ABOVE; if (exceptMode != null && exceptMode.allow(depth)) continue; dispatch(target); } } else { if (hitLayer != except) dispatch(hitLayer); } } finally { this.event = oldEvent; } }
/** * Adds a layer to the bottom of the group. Because the {@link Layer} hierarchy is a tree, if * {@code child} is already a child of another {@link GroupLayer}, it will be removed before * being added to this {@link GroupLayer}. */ public void add(Layer child) { // optimization if we're requested to add a child that's already added GroupLayer parent = child.parent(); if (parent == this) return; // if this child has equal or greater depth to the last child, we can append directly and avoid // a log(N) search; this is helpful when all children have the same depth int count = children.size(), index; if (count == 0 || children.get(count-1).depth() <= child.depth()) index = count; // otherwise find the appropriate insertion point via binary search else index = findInsertion(child.depth()); // remove the child from any existing parent, preventing multiple parents if (parent != null) parent.remove(child); children.add(index, child); child.setParent(this); if (state.get() == State.ADDED) child.onAdd(); // if this child is active, we need to become active if (child.interactive()) setInteractive(true); }
void dispatch (E event) { // if this interaction has been manually canceled, ignore further dispatch requests if (canceled) return; assert event != null; LayerUtil.screenToLayer(hitLayer, local.set(event.x, event.y), local); this.event = event; try { if (bubble) { Depth depth = Depth.BELOW; for (Layer target = hitLayer; target != null; target = target.parent()) { if (target == capturingLayer) depth = Depth.AT; else if (depth == Depth.AT) depth = Depth.ABOVE; if (captureMode != null && !captureMode.allow(depth)) continue; dispatch(target); // the above dispatch may have caused a capture, in which case capturing layer will have // just been set and we need to update our depth accordingly if (target == capturingLayer) depth = Depth.AT; } } else { dispatch(hitLayer); } } finally { this.event = null; } local.set(0, 0); }