The DisplayObject class is the base class for all objects that are rendered on the screen. In Sparrow, all displayable objects are organized in a display tree. Only objects that are part of the display tree will be displayed (rendered). The display tree consists of leaf nodes (Image, Quad) that will be rendered directly to the screen, and of container nodes (subclasses of DisplayObjectContainer, like Sprite). A container is simply a display object that has child nodes - which can, again, be either leaf nodes or other containers. A display object has properties that define its position in relation to its parent ('X', 'Y'), as well as its rotation, skewing and scaling factors. Use the 'Alpha' and 'Visible' properties to make an object translucent or invisible. Every display object may be the target of touch events. If you don't want an object to be touchable, you can disable the `Touchable` property. When it's disabled, neither the object nor its children will receive any more touch events. **Points vs. Pixels** All sizes and distances are measured in points. What this means in pixels depends on the contentScaleFactor of the device. **Transforming coordinates** Within the display tree, each object has its own local coordinate system. If you rotate a container, you rotate that coordinate system - and thus all the children of the container. Sometimes you need to know where a certain point lies relative to another coordinate system. That's the purpose of the method 'TransformationMatrixToSpace'. It will create a matrix that represents the transformation of a point in one coordinate system to another. **Subclassing DisplayObject** As DisplayObject is an abstract class, you can't instantiate it directly, but have to use one of its subclasses instead. However, you can create custom display objects as well. That's especially useful when you want to create an object with a custom render function. You will need to implement the following methods when you subclass DisplayObject: - void Render ( RenderSupport support); - Rectangle BoundsInSpace ( DisplayObject targetSpace); Have a look at Quad for a sample implementation of those methods.
        private void AddedToStageHandler(DisplayObject target, DisplayObject currentTarget)
        {
            _started = true;
            _waitFrames = 3;
            AddTestObjects(40);

            SparrowSharpApp.ShowStats = true;
        }
Exemple #2
0
 /// <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;    
            }
        }
Exemple #10
0
 /// <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();
 }
Exemple #13
0
 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);
     }
 }
Exemple #15
0
        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;
        }
Exemple #17
0
        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;
                    }
                }
            }
        }
Exemple #18
0
        override public Rectangle BoundsInSpace(DisplayObject targetSpace)
        {
            Matrix matrix = targetSpace == this ? null : TransformationMatrixToSpace(targetSpace);

            return(_vertexData.BoundsAfterTransformation(matrix, 0, _numQuads * 4));
        }
Exemple #19
0
        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;
        }
Exemple #29
0
 /// <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);
 }
Exemple #31
0
 /// <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;
        }
Exemple #37
0
        /// <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?
        }