public void UpdateTransform() { Debug.Assert(m_pobBatchNode != null, "updateTransform is only valid when CCSprite is being rendered using an CCSpriteBatchNode"); // recaculate matrix only if it is dirty if (Dirty) { // If it is not visible, or one of its ancestors is not visible, then do nothing: if (!m_bIsVisible || (m_pParent != null && m_pParent != m_pobBatchNode && ((CCSprite)m_pParent).m_bShouldBeHidden)) { m_sQuad.BottomRight.Vertices = m_sQuad.TopLeft.Vertices = m_sQuad.TopRight.Vertices = m_sQuad.BottomLeft.Vertices = new CCVertex3F(0, 0, 0); m_bShouldBeHidden = true; } else { m_bShouldBeHidden = false; if (m_pParent == null || m_pParent == m_pobBatchNode) { m_transformToBatch = NodeToParentTransform(); } else { Debug.Assert((m_pParent as CCSprite) != null, "Logic error in CCSprite. Parent must be a CCSprite"); m_transformToBatch = CCAffineTransform.CCAffineTransformConcat(NodeToParentTransform(), ((CCSprite)m_pParent). m_transformToBatch); } // // calculate the Quad based on the Affine Matrix // CCSize size = m_obRect.Size; float x1 = m_obOffsetPosition.X; float y1 = m_obOffsetPosition.Y; float x2 = x1 + size.Width; float y2 = y1 + size.Height; float x = m_transformToBatch.tx; float y = m_transformToBatch.ty; float cr = m_transformToBatch.a; float sr = m_transformToBatch.b; float cr2 = m_transformToBatch.d; float sr2 = -m_transformToBatch.c; float ax = x1 * cr - y1 * sr2 + x; float ay = x1 * sr + y1 * cr2 + y; float bx = x2 * cr - y1 * sr2 + x; float by = x2 * sr + y1 * cr2 + y; float cx = x2 * cr - y2 * sr2 + x; float cy = x2 * sr + y2 * cr2 + y; float dx = x1 * cr - y2 * sr2 + x; float dy = x1 * sr + y2 * cr2 + y; m_sQuad.BottomLeft.Vertices = new CCVertex3F(ax, ay, m_fVertexZ); m_sQuad.BottomRight.Vertices = new CCVertex3F(bx, by, m_fVertexZ); m_sQuad.TopLeft.Vertices = new CCVertex3F(dx, dy, m_fVertexZ); m_sQuad.TopRight.Vertices = new CCVertex3F(cx, cy, m_fVertexZ); } m_pobTextureAtlas.UpdateQuad(ref m_sQuad, m_uAtlasIndex); m_bRecursiveDirty = false; m_bDirty = false; } // recursively iterate over children if (m_bHasChildren) { CCNode[] elements = m_pChildren.Elements; if (m_pobBatchNode != null) { for (int i = 0, count = m_pChildren.count; i < count; i++) { ((CCSprite)elements[i]).UpdateTransform(); } } else { for (int i = 0, count = m_pChildren.count; i < count; i++) { var sprite = elements[i] as CCSprite; if (sprite != null) { sprite.UpdateTransform(); } } } } }
public virtual CCAffineTransform NodeToParentTransform() { if (m_bIsTransformDirty) { // Translate values float x = m_tPosition.X; float y = m_tPosition.Y; if (m_bIgnoreAnchorPointForPosition) { x += m_tAnchorPointInPoints.X; y += m_tAnchorPointInPoints.Y; } // Rotation values float c = 1, s = 0; if (m_fRotation != 0.0f) { float radians = -CCMacros.CCDegreesToRadians(m_fRotation); c = (float)Math.Cos(radians); s = (float)Math.Sin(radians); } bool needsSkewMatrix = (m_fSkewX != 0f || m_fSkewY != 0f); // optimization: // inline anchor point calculation if skew is not needed if (!needsSkewMatrix && !m_tAnchorPointInPoints.Equals(CCPoint.Zero)) { x += c * -m_tAnchorPointInPoints.X * m_fScaleX + -s * -m_tAnchorPointInPoints.Y * m_fScaleY; y += s * -m_tAnchorPointInPoints.X * m_fScaleX + c * -m_tAnchorPointInPoints.Y * m_fScaleY; } // Build Transform Matrix //m_tTransform = new CCAffineTransform( // c * m_fScaleX, s * m_fScaleX, // -s * m_fScaleY, c * m_fScaleY, // x, y); // Build Transform Matrix m_tTransform.a = c * m_fScaleX; m_tTransform.b = s * m_fScaleX; m_tTransform.c = -s * m_fScaleY; m_tTransform.d = c * m_fScaleY; m_tTransform.tx = x; m_tTransform.ty = y; // XXX: Try to inline skew // If skew is needed, apply skew and then anchor point if (needsSkewMatrix) { var skewMatrix = new CCAffineTransform( 1.0f, (float)Math.Tan(CCMacros.CCDegreesToRadians(m_fSkewY)), (float)Math.Tan(CCMacros.CCDegreesToRadians(m_fSkewX)), 1.0f, 0.0f, 0.0f); m_tTransform = CCAffineTransform.CCAffineTransformConcat(skewMatrix, m_tTransform); // adjust anchor point if (!m_tAnchorPointInPoints.Equals(CCPoint.Zero)) { m_tTransform = CCAffineTransform.CCAffineTransformTranslate(m_tTransform, -m_tAnchorPointInPoints.X, -m_tAnchorPointInPoints.Y); } } m_bIsTransformDirty = false; } return(m_tTransform); }