/** Returns the transform for this group's coordinate system. */ protected Matrix4 computeTransform () { Affine2 worldTransform = this.worldTransform; float originX = this.originX; float originY = this.originY; float rotation = this.rotation; float scaleX = this.scaleX; float scaleY = this.scaleY; worldTransform.setToTrnRotScl(x + originX, y + originY, rotation, scaleX, scaleY); if (originX != 0 || originY != 0) worldTransform.translate(-originX, -originY); // Find the first parent that transforms. Group parentGroup = parent; while (parentGroup != null) { if (parentGroup.transform) break; parentGroup = parentGroup.parent; } if (parentGroup != null) worldTransform.preMul(parentGroup.worldTransform); computedTransform.set(worldTransform); return computedTransform; }
/** Sets the transform matrix to be used by this Batch. Even if this is called inside a {@link #begin()}/{@link #end()} block, * the current batch is <em>not</em> flushed to the GPU. Instead, for every subsequent draw() the vertices will be transformed * on the CPU to match the original batch matrix. This adjustment must be performed until the matrices are realigned by * restoring the original matrix, or by calling {@link #flushAndSyncTransformMatrix()} or {@link #end()}. */ public void setTransformMatrix (Affine2 transform) { Matrix4 realMatrix = super.getTransformMatrix(); if (checkEqual(realMatrix, transform)) { adjustNeeded = false; } else { virtualMatrix.setAsAffine(transform); if (isDrawing()) { adjustNeeded = true; // adjust = inverse(real) x virtual // real x adjust x vertex = virtual x vertex if (haveIdentityRealMatrix) { adjustAffine.set(transform); } else { adjustAffine.set(realMatrix).inv().mul(transform); } } else { realMatrix.setAsAffine(transform); haveIdentityRealMatrix = checkIdt(realMatrix); } } }
@Override public void write(Kryo kryo, Output output, Affine2 affine2) { output.writeFloat(affine2.m00); output.writeFloat(affine2.m01); output.writeFloat(affine2.m02); output.writeFloat(affine2.m10); output.writeFloat(affine2.m11); output.writeFloat(affine2.m12); }
@Override public Affine2 read(Kryo kryo, Input input, Class<Affine2> type) { Affine2 affine2 = new Affine2(); affine2.m00 = input.readFloat(); affine2.m01 = input.readFloat(); affine2.m02 = input.readFloat(); affine2.m10 = input.readFloat(); affine2.m11 = input.readFloat(); affine2.m12 = input.readFloat(); return affine2; }
@Override public void draw (TextureRegion region, float width, float height, Affine2 transform) { float[] vertices = tempVertices; vertices[U1] = region.getU(); vertices[V1] = region.getV2(); vertices[U2] = region.getU(); vertices[V2] = region.getV(); vertices[U3] = region.getU2(); vertices[V3] = region.getV(); vertices[U4] = region.getU2(); vertices[V4] = region.getV2(); float color = this.color; vertices[C1] = color; vertices[C2] = color; vertices[C3] = color; vertices[C4] = color; // construct corner points vertices[X1] = transform.m02; vertices[Y1] = transform.m12; vertices[X2] = transform.m01 * height + transform.m02; vertices[Y2] = transform.m11 * height + transform.m12; vertices[X3] = transform.m00 * width + transform.m01 * height + transform.m02; vertices[Y3] = transform.m10 * width + transform.m11 * height + transform.m12; vertices[X4] = transform.m00 * width + transform.m02; vertices[Y4] = transform.m10 * width + transform.m12; draw(region.getTexture(), vertices, 0, 20); }
@Override public void draw (TextureRegion region, float width, float height, Affine2 transform) { if (!adjustNeeded) { super.draw(region, width, height, transform); } else { drawAdjusted(region, width, height, transform); } }
private void drawAdjusted (Texture texture, float[] spriteVertices, int offset, int count) { if (!drawing) throw new IllegalStateException("CpuSpriteBatch.begin must be called before draw."); if (texture != lastTexture) switchTexture(texture); Affine2 t = adjustAffine; int copyCount = Math.min(vertices.length - idx, count); do { count -= copyCount; while (copyCount > 0) { float x = spriteVertices[offset]; float y = spriteVertices[offset + 1]; vertices[idx] = t.m00 * x + t.m01 * y + t.m02; // x vertices[idx + 1] = t.m10 * x + t.m11 * y + t.m12; // y vertices[idx + 2] = spriteVertices[offset + 2]; // color vertices[idx + 3] = spriteVertices[offset + 3]; // u vertices[idx + 4] = spriteVertices[offset + 4]; // v idx += Sprite.VERTEX_SIZE; offset += Sprite.VERTEX_SIZE; copyCount -= Sprite.VERTEX_SIZE; } if (count > 0) { super.flush(); copyCount = Math.min(vertices.length, count); } } while (count > 0); }
private static boolean checkEqual (Matrix4 matrix, Affine2 affine) { final float[] val = matrix.getValues(); // matrix is assumed to be 2D transformation return (val[Matrix4.M00] == affine.m00 && val[Matrix4.M10] == affine.m10 && val[Matrix4.M01] == affine.m01 && val[Matrix4.M11] == affine.m11 && val[Matrix4.M03] == affine.m02 && val[Matrix4.M13] == affine.m12); }
@Override public Affine2 copy (Kryo kryo, Affine2 original) { return new Affine2(original); }
@Override public void draw(TextureRegion region, float width, float height, Affine2 transform) { }
/** Draws a rectangle transformed by the given matrix. */ public void draw (TextureRegion region, float width, float height, Affine2 transform);
private static void checkEqual (Matrix3 matrix, Affine2 affine) { checkEqual(matrix, new Matrix3().set(affine)); }
private static void checkEqual (Affine2 a, Affine2 b) { checkEqual(new Matrix3().set(a), new Matrix3().set(b)); }