private void AddedToStageHandler(DisplayObject target, DisplayObject currentTarget) { _started = true; _waitFrames = 3; AddTestObjects(40); SparrowSharpApp.ShowStats = true; }
/// <summary> /// Returns the movement of the touch between the current and previous location. /// </summary> public Point MovementInSpace(DisplayObject space) { Matrix transformationMatrix = Target.Stage.TransformationMatrixToSpace(space); Point curLoc = transformationMatrix.TransformPoint(GlobalX, GlobalY); Point preLoc = transformationMatrix.TransformPoint(PreviousGlobalX, PreviousGlobalY); curLoc.SubtractPoint(preLoc); return curLoc; }
/// <summary> /// Draws an object onto the texture, adhering its properties for position, scale, rotation and alpha. /// </summary> public void DrawObject(DisplayObject obj) { DrawBundled(delegate { _renderSupport.PushState(obj.TransformationMatrix, obj.Alpha, obj.BlendMode); obj.Render(_renderSupport); _renderSupport.PopState(); }); }
/// Gets a set of Touch objects that originated over a certain target. public List<Touch> TouchesWithTarget (DisplayObject target) { List<Touch> touchesFound = new List<Touch> (); foreach (Touch touch in _touches) { if (target == touch.Target || (target is DisplayObjectContainer && ((DisplayObjectContainer)target).ContainsChild(touch.Target))) { touchesFound.Add(touch); } } return touchesFound; }
void OnEnterFrame(DisplayObject target, float passedTime) { totalTime += passedTime; frameCount++; if (totalTime > 1000) { FramesPerSecond = Math.Round(frameCount / (totalTime/1000), 1); frameCount = 0; totalTime = 0; Update(); } }
private void AddedToStageHandler(DisplayObject target, DisplayObject currentTarget) { AddChild(txt); txt.Y = 25; SparrowSharpApp.ShowStats = true; if (mRectangle != null) { mMinX = mRectangle.X; mMinY = mRectangle.Y; mMaxX = mRectangle.X + mRectangle.Width - 26; mMaxY = mRectangle.Y + mRectangle.Height - 37; }else{ mMaxX = Stage.Width - 26; mMaxY = Stage.Height - 37; } Count = mCount; EnterFrame += EnterFrameHandler; Stage.Touch += MyTouchHandler; }
/// <summary> /// Adds a child to the container at a certain index. /// </summary> public void AddChild(DisplayObject child, int index) { if (index >= 0 && index <= _children.Count) { child.RemoveFromParent(); _children.Insert(index, child); child.Parent = this; child.InvokeAdded(child, this); if (Stage != null) { child.BroadcastAddedToStageEvent(this); } } else { throw new IndexOutOfRangeException("Invalid child index " + index); } }
private void AddedToStageHandler(DisplayObject target, DisplayObject currentTarget) { /* RenderTexture tex = new RenderTexture (400, 300, 0xf1ff00ff); tex.DrawBundled(delegate { for (int i=0; i<12; ++i) { Image img = new Image(textures[i%3]); //img.Rotation = (2 * (float)Math.PI / 12) * i; img.X = i * 30; tex.DrawObject(img); } }); AddChild (new Image(tex));*/ _started = true; _waitFrames = 3; AddTestObjects(1); ///SparrowSharpApp.ShowStats = true; }
private void EnterFrameHandler(DisplayObject target, float passedTime) { if (!_started) return; _elapsed += passedTime / 1000; ++_frameCount; if (_frameCount % _waitFrames == 0) { float targetFPS = 60; float realFPS = _waitFrames / _elapsed; //Console.WriteLine ("FPS: " + realFPS); if (realFPS >= targetFPS) { int numObjects = _failCount != 0 ? 5 : 25; AddTestObjects(numObjects); _failCount = 0; } else { ++_failCount; if (_failCount > 15) _waitFrames = 5; // slow down creation process to be more exact if (_failCount > 20) _waitFrames = 10; if (_failCount == 25) BenchmarkComplete(); // target fps not reached for a while } _elapsed = _frameCount = 0; } for (int i = 0; i < _container.NumChildren; i++) { DisplayObject child = _container.GetChild(i); child.Rotation += 0.05f; } }
/// <summary> /// Adds a child to the container. It will be at the topmost position. /// </summary> public void AddChild(DisplayObject child) { AddChild(child, _children.Count); }
internal virtual void InvokeKeyDown(DisplayObject target, DisplayObject currentTarget) { if (KeyDown != null) { KeyDown(target, currentTarget); } }
void OnAddedToStage(DisplayObject target, DisplayObject currentTarget) { FramesPerSecond = NumDrawCalls = 0; Update(); }
public override Rectangle GetBounds(DisplayObject targetSpace) { return(MeshUtil.CalculateBounds(_vertexData, this, targetSpace)); }
internal virtual void InvokeAdded(DisplayObject target, DisplayObject currentTarget) { if (Added != null) { Added(target, currentTarget); } }
public override Rectangle BoundsInSpace(DisplayObject targetSpace) { Point bottomRight; if (targetSpace == this) { // optimization bottomRight = _vertexData.PositionAt(3); return new Rectangle(0.0f, 0.0f, bottomRight.X, bottomRight.Y); } else if (targetSpace == Parent && Rotation == 0.0f) { // optimization float scaleX = ScaleX; float scaleY = ScaleY; bottomRight = _vertexData.PositionAt(3); Rectangle resultRect = new Rectangle(X - PivotX * scaleX, Y - PivotY * scaleY, bottomRight.X * ScaleX, bottomRight.Y * ScaleY); if (scaleX < 0.0f) { resultRect.Width *= -1.0f; resultRect.X -= resultRect.Width; } if (scaleY < 0.0f) { resultRect.Height *= -1.0f; resultRect.Top -= resultRect.Height; } return resultRect; } else { Matrix transformationMatrix = TransformationMatrixToSpace(targetSpace); return _vertexData.BoundsAfterTransformation(transformationMatrix, 0, 4); } }
/// <summary> /// Analyses an object that is made up exclusively of quads (or other containers) and saves the /// resulting quad batches into the specified an array; batches inside that array are reused. /// </summary> public static List<QuadBatch> Compile(DisplayObject displayObject, List<QuadBatch> quadBatches = null) { if (quadBatches == null) { quadBatches = new List<QuadBatch>(); } Matrix identity = Matrix.Create(); identity.Identity(); Compile(displayObject, quadBatches, -1, identity, 1.0f, Sparrow.Display.BlendMode.AUTO); return quadBatches; }
public override void Render(Painter painter) { int numChildren = _children.Count; uint frameId = painter.FrameId; bool cacheEnabled = frameId != 0; bool selfOrParentChanged = _lastParentOrSelfChangeFrameID == frameId; for (int i = 0; i < numChildren; ++i) { DisplayObject child = _children[i]; if (child._hasVisibleArea) { if (selfOrParentChanged) { child._lastParentOrSelfChangeFrameID = frameId; } if (child._lastParentOrSelfChangeFrameID != frameId && child._lastChildChangeFrameID != frameId && child._tokenFrameID == frameId - 1 && cacheEnabled) { painter.PushState(SCacheToken); painter.DrawFromCache(child._pushToken, child._popToken); painter.PopState(child._popToken); child._pushToken.CopyFrom(SCacheToken); } else { BatchToken pushToken = cacheEnabled ? child._pushToken : null; BatchToken popToken = cacheEnabled ? child._popToken : null; FragmentFilter filter = child._filter; DisplayObject mask = child._mask; painter.PushState(pushToken); painter.SetStateTo(child.TransformationMatrix, child.Alpha, child.BlendMode); if (mask != null) { painter.DrawMask(mask, child); } if (filter != null) { filter.Render(painter); } else { child.Render(painter); } if (mask != null) { painter.EraseMask(mask, child); } painter.PopState(popToken); } if (cacheEnabled) { child._tokenFrameID = frameId; } } } }
override public Rectangle BoundsInSpace(DisplayObject targetSpace) { Matrix matrix = targetSpace == this ? null : TransformationMatrixToSpace(targetSpace); return(_vertexData.BoundsAfterTransformation(matrix, 0, _numQuads * 4)); }
public static int Compile(DisplayObject displayObject, List <QuadBatch> quadBatches, int quadBatchID, Matrix transformationMatrix, float alpha, uint blendMode) { bool isRootObject = false; float objectAlpha = displayObject.Alpha; Quad quad = displayObject is Quad ? (Quad)displayObject : null; QuadBatch batch = displayObject is QuadBatch ? (QuadBatch)displayObject : null; DisplayObjectContainer container = displayObject is DisplayObjectContainer ? (DisplayObjectContainer)displayObject : null; if (quadBatchID == -1) { isRootObject = true; quadBatchID = 0; objectAlpha = 1.0f; blendMode = displayObject.BlendMode; if (quadBatches.Count == 0) { quadBatches.Add(new QuadBatch()); } else { quadBatches[0].Reset(); } } if (container != null) { Matrix childMatrix = Matrix.Create(); childMatrix.Identity(); int numChildren = container.NumChildren; for (int i = 0; i < numChildren; i++) { DisplayObject child = container.GetChild(i); if (child.HasVisibleArea) { uint childBlendMode = child.BlendMode; if (childBlendMode == Sparrow.Display.BlendMode.AUTO) { childBlendMode = blendMode; } childMatrix.CopyFromMatrix(transformationMatrix); childMatrix.PrependMatrix(child.TransformationMatrix); quadBatchID = Compile(child, quadBatches, quadBatchID, childMatrix, alpha * objectAlpha, childBlendMode); } } } else if (quad != null) { Texture texture = quad.Texture; bool tinted = quad.Tinted; bool pma = quad.PremultipliedAlpha; QuadBatch currentBatch = quadBatches[quadBatchID]; if (currentBatch.IsStateChange(tinted, texture, alpha * objectAlpha, pma, blendMode, 1)) { quadBatchID++; if (quadBatches.Count <= quadBatchID) { quadBatches.Add(new QuadBatch()); } currentBatch = quadBatches[quadBatchID]; currentBatch.Reset(); } currentBatch.AddQuad(quad, alpha * objectAlpha, blendMode, transformationMatrix); } else if (batch != null) { Texture texture = quad.Texture; bool tinted = quad.Tinted; bool pma = quad.PremultipliedAlpha; int numQuads = batch.NumQuads; QuadBatch currentBatch = quadBatches[quadBatchID]; if (currentBatch.IsStateChange(tinted, texture, alpha * objectAlpha, pma, blendMode, numQuads)) { quadBatchID++; if (quadBatches.Count <= quadBatchID) { quadBatches.Add(new QuadBatch()); } currentBatch = quadBatches[quadBatchID]; currentBatch.Reset(); } currentBatch.AddQuadBatch(batch, alpha * objectAlpha, blendMode, transformationMatrix); } else { throw new InvalidOperationException("Unsupported display object"); } if (!isRootObject) { return(quadBatchID); } // remove unused batches for (int i = quadBatches.Count - 1; i > quadBatchID; --i) { quadBatches.RemoveAt(quadBatches.Count - 1); } return(quadBatchID); }
private void CalcBounds(DisplayObject obj, Stage stage, float scale, bool intersectWithStage, out Rectangle bounds, out Rectangle boundsPOT) { float marginX; float marginY; // optimize for full-screen effects if (obj == stage || obj == SparrowSharpApp.Root) { marginX = marginY = 0; bounds = new Rectangle(0, 0, stage.Width, stage.Height); } else { marginX = MarginX; marginY = MarginY; bounds = obj.BoundsInSpace(stage); } if (intersectWithStage) bounds = bounds.Intersection(stage.Bounds); boundsPOT = null; Rectangle result = bounds; if (!result.IsEmpty()) { // the bounds are a rectangle around the object, in stage coordinates, // and with an optional margin. bounds.Inflate(marginX, marginY); // To fit into a POT-texture, we extend it towards the right and bottom. int minSize = (int)(MIN_TEXTURE_SIZE / scale); float minWidth = result.Width > minSize ? result.Width : minSize; float minHeight = result.Height > minSize ? result.Height : minSize; boundsPOT = new Rectangle(result.X, result.Top, NumberUtil.NextPowerOfTwo(minWidth * scale) / scale, NumberUtil.NextPowerOfTwo(minHeight * scale) / scale); } }
/// <summary> /// Moves a child to a certain index. Children at and after the replaced position move up. /// throws ArgumentException if the child is not found /// </summary> public void SetChildIndex(DisplayObject child, int index) { int oldIndex = _children.IndexOf(child); if (oldIndex == -1) { throw new ArgumentException("child not found"); } _children.RemoveAt(oldIndex); _children.Insert(index, child); }
/// <summary> /// Adds a child to the container. It will be at the topmost position. /// </summary> public void AddChild(DisplayObject child) { AddChild(child, _children.Count); }
override public Rectangle BoundsInSpace(DisplayObject targetSpace) { int numChildren = _children.Count; if (numChildren == 0) { Matrix transformationMatrix = TransformationMatrixToSpace(targetSpace); Point transformedPoint = transformationMatrix.TransformPoint(X, Y); return new Rectangle(transformedPoint.X, transformedPoint.Y); } else if (numChildren == 1) { return _children[0].BoundsInSpace(targetSpace); } else { float minX = float.MaxValue, maxX = -float.MaxValue, minY = float.MaxValue, maxY = -float.MaxValue; foreach (DisplayObject child in _children) { Rectangle childBounds = child.BoundsInSpace(targetSpace); minX = Math.Min(minX, childBounds.X); maxX = Math.Max(maxX, childBounds.X + childBounds.Width); minY = Math.Min(minY, childBounds.Top); maxY = Math.Max(maxY, childBounds.Top + childBounds.Height); } return new Rectangle(minX, minY, maxX - minX, maxY - minY); } }
/// <summary> /// Swaps the indexes of two children. /// </summary> public void SwapChild(DisplayObject child1, DisplayObject child2) { int index1 = _children.IndexOf(child1); int index2 = _children.IndexOf(child2); SwapChildrenAt(index1, index2); }
/// <summary> /// Removes a child from the container. If the object is not a child, nothing happens. /// </summary> public void RemoveChild(DisplayObject child) { int index = _children.IndexOf(child); if (index != -1) { RemoveChildAt(index); } }
/// <summary> /// Applies the filter on a certain display object, rendering the output into the current render /// target. This method is called automatically by Sparrow's rendering system for the object the /// filter is attached to. /// </summary> public void RenderObject(DisplayObject obj, RenderSupport support) { // bottom layer if (Mode == FragmentFilterMode.Above) { obj.Render(support); } // center layer if (_cacheRequested) { _cacheRequested = false; _cache = RenderPasses(obj, support, true); DisposePassTextures(); } if (_cache != null) { _cache.Render(support); } else { RenderPasses(obj, support, false); } // top layer if (Mode == FragmentFilterMode.Below) { obj.Render(support); } }
private void AddedToStageHandler(DisplayObject target, DisplayObject currentTarget) { _started = true; _waitFrames = 3; AddTestObjects(100); }
private QuadBatch RenderPasses(DisplayObject obj, RenderSupport support, bool intoCache) { Texture cacheTexture = null; Stage stage = obj.Stage; float scale = Resolution; if (stage == null) { throw new InvalidOperationException("Filtered object must be on the stage."); } // the bounds of the object in stage coordinates Rectangle boundsPOT; Rectangle bounds; CalcBounds(obj, stage, scale, !intoCache, out bounds, out boundsPOT); if (bounds.IsEmpty()) { DisposePassTextures(); return intoCache ? new QuadBatch() : null; } UpdateBuffers(boundsPOT); UpdatePassTextures((int)boundsPOT.Width, (int)boundsPOT.Height, scale); support.FinishQuadBatch(); support.AddDrawCalls(NumPasses); support.PushState(Matrix.Create(), 1.0f, BlendMode.AUTO); // save original projection matrix and render target _projMatrix.CopyFromMatrix(support.ProjectionMatrix); Texture previousRenderTarget = support.RenderTarget; // use cache? if (intoCache) { cacheTexture = CreateTexture((int)boundsPOT.Width, (int)boundsPOT.Height, scale); } // draw the original object into a texture support.RenderTarget = _passTextures[0]; SparrowSharpApp.Context.ScissorBox = null; // we want the entire texture cleared support.Clear(); support.BlendMode = BlendMode.NORMAL; support.SetupOrthographicProjection(boundsPOT.Left, boundsPOT.Right, boundsPOT.Bottom, boundsPOT.Top); obj.Render(support); support.FinishQuadBatch(); // prepare drawing of actual filter passes support.ApplyBlendMode(true); support.ModelViewMatrix.Identity(); support.PushClipRect(bounds); GL.BindBuffer (BufferTarget.ArrayBuffer, _vertexBufferName); GL.BindBuffer (BufferTarget.ElementArrayBuffer, _indexBufferName); GL.EnableVertexAttribArray (VertexPosID); GL.VertexAttribPointer (VertexPosID, 2, VertexAttribPointerType.Float, false, Vertex.SIZE, (IntPtr)Vertex.POSITION_OFFSET); GL.EnableVertexAttribArray (TexCoordsID); GL.VertexAttribPointer (TexCoordsID, 2, VertexAttribPointerType.Float, false, Vertex.SIZE, (IntPtr)Vertex.TEXTURE_OFFSET); // draw all passes for (int i = 0; i < NumPasses; ++i) { if (i < NumPasses - 1) { // intermediate pass // draw into pass texture support.RenderTarget = PassTextureForPass(i + 1); support.Clear(); } else { // final pass if (intoCache) { // draw into cache texture support.RenderTarget = cacheTexture; support.Clear(); } else { // draw into back buffer, at original (stage) coordinates support.RenderTarget = previousRenderTarget; support.ProjectionMatrix = _projMatrix; support.ModelViewMatrix.Translate(OffsetX, OffsetY); support.BlendMode = obj.BlendMode; support.ApplyBlendMode(true); } } Texture passTexture = PassTextureForPass(i); GL.ActiveTexture (TextureUnit.Texture0); GL.BindTexture (TextureTarget.Texture2D, passTexture.Name); ActivateWithPass (i, passTexture, support.MvpMatrix); GL.DrawElements (BeginMode.Triangles, 6, DrawElementsType.UnsignedShort, IntPtr.Zero); DeactivateWithPass(i, passTexture); } GL.DisableVertexAttribArray(VertexPosID); GL.DisableVertexAttribArray(TexCoordsID); support.PopState(); support.PopClipRect(); QuadBatch cache = null; if (intoCache) { // restore support settings support.RenderTarget = previousRenderTarget; support.ProjectionMatrix = _projMatrix; // Create an image containing the cache. To have a display object that contains // the filter output in object coordinates, we wrap it in a QuadBatch: that way, // we can modify it with a transformation matrix. cache = new QuadBatch(); Image image = new Image(cacheTexture); Matrix matrix = stage.TransformationMatrixToSpace(obj); // Note: the next line was originally: // matrix.Translate (bounds.X + OffsetX, bounds.Y + OffsetY); // this seems like a sparrow-s bug; fix is from Starling matrix.PrependTranslation(bounds.X + OffsetX, bounds.Top + OffsetY); cache.AddQuad(image, 1.0f, BlendMode.AUTO, matrix); } return cache; }
/// <summary> /// Converts the previous location of a touch to the local coordinate system of a display object. /// </summary> public Point PreviousLocationInSpace(DisplayObject space) { Matrix transformationMatrix = Target.Stage.TransformationMatrixToSpace(space); return transformationMatrix.TransformPoint(PreviousGlobalX, PreviousGlobalY); }
override public Rectangle BoundsInSpace(DisplayObject targetSpace) { return _hitArea.BoundsInSpace(targetSpace); }
/// <summary> /// Returns the index of a child within the container. Returns -1 if the child is not within this container /// </summary> public int GetChildIndex(DisplayObject child) { return(_children.IndexOf(child)); }
private void EnterFrameHandler(DisplayObject target, float passedTime) { mCount = mBunnies.Count; var arr = mBunnies.ToArray(); //for (int i=0;i<mBunnies.Count;i++) { mBunny = mBunnies[i]; foreach (Bunny mBunny in mBunnies) { mBunny.X += mBunny.SpeedX; mBunny.Y += mBunny.SpeedY; mBunny.SpeedY += mGravity; //b.alpha = 0.3 + 0.7 * b.y / maxY; if (mBunny.X > mMaxX) { mBunny.SpeedX *= -1; mBunny.X = mMaxX; } else if (mBunny.X < mMinX) { mBunny.SpeedX *= -1; mBunny.X = mMinX; } if (mBunny.Y > mMaxY) { mBunny.SpeedY *= -0.8f; mBunny.Y = mMaxY; if (random.NextDouble() > 0.5) mBunny.SpeedY -= 3 + (float)random.NextDouble() * 4; } else if (mBunny.Y < mMinY) { mBunny.SpeedY = 0; mBunny.Y = mMinY; } } }
/// <summary> /// Creates a matrix that represents the transformation from the local coordinate system to another. /// </summary> public Matrix TransformationMatrixToSpace(DisplayObject targetSpace) { DisplayObject currentObject; Matrix selfMatrix; Matrix targetMatrix; if (targetSpace == this) { Matrix identity = Matrix.Create(); identity.Identity(); return identity; } else if (targetSpace == _parent || (targetSpace == null && _parent == null)) { Matrix transformationMatrix = Matrix.Create(); transformationMatrix.CopyFromMatrix(TransformationMatrix); return transformationMatrix; } else if (targetSpace == null || targetSpace == Root) { // targetSpace 'null' represents the target coordinate of the base object. // -> move up from this to base selfMatrix = Matrix.Create(); selfMatrix.Identity(); currentObject = this; while (currentObject != targetSpace) { selfMatrix.AppendMatrix(currentObject.TransformationMatrix); currentObject = currentObject.Parent; } return selfMatrix; } else if (targetSpace.Parent == this) { targetMatrix = Matrix.Create(); targetMatrix.CopyFromMatrix(targetSpace.TransformationMatrix); targetMatrix.Invert(); return targetMatrix; } // 1.: Find a common parent of this and the target coordinate space. List<DisplayObject> ancestors = new List<DisplayObject>(); int count = 0; DisplayObject commonParent = null; currentObject = this; while (currentObject != null && count < MAX_DISPLAY_TREE_DEPTH) { ancestors.Add(currentObject); currentObject = currentObject.Parent; count++; } currentObject = targetSpace; while (currentObject != null && commonParent == null) { for (int i = 0; i < count; ++i) { if (currentObject == ancestors[i]) { commonParent = ancestors[i]; break; } } currentObject = currentObject.Parent; } if (commonParent == null) { throw new Exception("Object not connected to target"); } // 2.: Move up from this to common parent selfMatrix = Matrix.Create(); selfMatrix.Identity(); currentObject = this; while (currentObject != commonParent) { selfMatrix.AppendMatrix(currentObject.TransformationMatrix); currentObject = currentObject.Parent; } // 3.: Now move up from target until we reach the common parent targetMatrix = Matrix.Create(); targetMatrix.Identity(); currentObject = targetSpace; while (currentObject != null && currentObject != commonParent) { targetMatrix.AppendMatrix(currentObject.TransformationMatrix); currentObject = currentObject.Parent; } // 4.: Combine the two matrices targetMatrix.Invert(); selfMatrix.AppendMatrix(targetMatrix); return selfMatrix; }
override public Rectangle BoundsInSpace(DisplayObject targetSpace) { Matrix matrix = targetSpace == this ? null : TransformationMatrixToSpace(targetSpace); return _vertexData.BoundsAfterTransformation(matrix, 0, _numQuads * 4); }
/// <summary> /// Returns a rectangle that completely encloses the object as it appears in another coordinate system. /// </summary> public abstract Rectangle BoundsInSpace(DisplayObject targetSpace);
public static int Compile(DisplayObject displayObject, List<QuadBatch> quadBatches, int quadBatchID, Matrix transformationMatrix, float alpha, uint blendMode) { bool isRootObject = false; float objectAlpha = displayObject.Alpha; Quad quad = displayObject is Quad ? (Quad)displayObject : null; QuadBatch batch = displayObject is QuadBatch ? (QuadBatch)displayObject : null; DisplayObjectContainer container = displayObject is DisplayObjectContainer ? (DisplayObjectContainer)displayObject : null; if (quadBatchID == -1) { isRootObject = true; quadBatchID = 0; objectAlpha = 1.0f; blendMode = displayObject.BlendMode; if (quadBatches.Count == 0) { quadBatches.Add(new QuadBatch()); } else { quadBatches[0].Reset(); } } if (container != null) { Matrix childMatrix = Matrix.Create(); childMatrix.Identity(); int numChildren = container.NumChildren; for (int i = 0; i < numChildren; i++) { DisplayObject child = container.GetChild(i); if (child.HasVisibleArea) { uint childBlendMode = child.BlendMode; if (childBlendMode == Sparrow.Display.BlendMode.AUTO) { childBlendMode = blendMode; } childMatrix.CopyFromMatrix(transformationMatrix); childMatrix.PrependMatrix(child.TransformationMatrix); quadBatchID = Compile(child, quadBatches, quadBatchID, childMatrix, alpha * objectAlpha, childBlendMode); } } } else if (quad != null) { Texture texture = quad.Texture; bool tinted = quad.Tinted; bool pma = quad.PremultipliedAlpha; QuadBatch currentBatch = quadBatches[quadBatchID]; if (currentBatch.IsStateChange(tinted, texture, alpha * objectAlpha, pma, blendMode, 1)) { quadBatchID++; if (quadBatches.Count <= quadBatchID) { quadBatches.Add(new QuadBatch()); } currentBatch = quadBatches[quadBatchID]; currentBatch.Reset(); } currentBatch.AddQuad(quad, alpha * objectAlpha, blendMode, transformationMatrix); } else if (batch != null) { Texture texture = quad.Texture; bool tinted = quad.Tinted; bool pma = quad.PremultipliedAlpha; int numQuads = batch.NumQuads; QuadBatch currentBatch = quadBatches[quadBatchID]; if (currentBatch.IsStateChange(tinted, texture, alpha * objectAlpha, pma, blendMode, numQuads)) { quadBatchID++; if (quadBatches.Count <= quadBatchID) { quadBatches.Add(new QuadBatch()); } currentBatch = quadBatches[quadBatchID]; currentBatch.Reset(); } currentBatch.AddQuadBatch(batch, alpha * objectAlpha, blendMode, transformationMatrix); } else { throw new InvalidOperationException("Unsupported display object"); } if (!isRootObject) { return quadBatchID; } // remove unused batches for (int i = quadBatches.Count - 1; i > quadBatchID; --i) { quadBatches.RemoveAt(quadBatches.Count - 1); } return quadBatchID; }
/// <summary> /// Returns the bounds of the container's clipRect in the given coordinate space, or /// null if the sprite doens't have a clipRect. /// </summary> public Rectangle ClipRectInSpace(DisplayObject targetSpace) { if (ClipRect == null) { return(null); } float minX = float.MaxValue; float maxX = -float.MaxValue; float minY = float.MaxValue; float maxY = -float.MaxValue; float clipLeft = ClipRect.Left; float clipRight = ClipRect.Right; float clipTop = ClipRect.Top; float clipBottom = ClipRect.Bottom; Matrix transform = TransformationMatrixToSpace(targetSpace); float x = 0; float y = 0; for (int i = 0; i < 4; ++i) { switch (i) { case 0: x = clipLeft; y = clipTop; break; case 1: x = clipLeft; y = clipBottom; break; case 2: x = clipRight; y = clipTop; break; case 3: x = clipRight; y = clipBottom; break; } Point transformedPoint = transform.TransformPoint(x, y); if (minX > transformedPoint.X) { minX = transformedPoint.X; } if (maxX < transformedPoint.X) { maxX = transformedPoint.X; } if (minY > transformedPoint.Y) { minY = transformedPoint.Y; } if (maxY < transformedPoint.Y) { maxY = transformedPoint.Y; } } return(new Rectangle(minX, minY, maxX - minX, maxY - minY)); // TODO: negative value checks? }