//----------------------------------------------------------------// bool MOAIVertexFormat::ComputeBounds ( void* buffer, u32 size, USRect& bounds ) { u32 total = this->mVertexSize ? ( size / this->mVertexSize ) : 0; if ( !total ) return false; u32 coordAttributeIdx = this->mAttributeUseTable [ ARRAY_VERTEX ].mAttrID; if ( coordAttributeIdx >= this->mTotalAttributes ) return false; MOAIVertexAttribute& coordAttr = this->mAttributes [ coordAttributeIdx ]; if ( coordAttr.mType != GL_FLOAT ) return false; // TODO: handle other types if ( coordAttr.mSize < 2 ) return false; buffer = ( void* )(( size_t )buffer + coordAttr.mOffset ); USVec2D* coord = ( USVec2D* )buffer; bounds.Init ( *coord ); bounds.Inflate ( 0.0000001f ); // prevent 'empty' bounds on cardinal direction lines or single vertex objects for ( u32 i = 1; i < total; ++i ) { buffer = ( void* )(( size_t )buffer + this->mVertexSize ); coord = ( USVec2D* )buffer; bounds.Grow ( *coord ); } return true; }
//----------------------------------------------------------------// USRect MOAIGfxQuadListDeck2D::GetBounds ( u32 idx, MOAIDeckRemapper* remapper ) { USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); u32 size = this->mSprites.Size (); if ( size ) { idx = remapper ? remapper->Remap ( idx ) : idx; idx = ( idx - 1 ) % size; USSprite& sprite = this->mSprites [ idx ]; if ( sprite.mTotalPairs ) { USSpritePair prim = this->mPairs [ sprite.mBasePair ]; USQuad& baseQuad = this->mQuads [ prim.mQuadID ]; baseQuad.GetBounds ( rect ); for ( u32 i = 1; i < sprite.mTotalPairs; ++i ) { prim = this->mPairs [ sprite.mBasePair + i ]; USQuad& quad = this->mQuads [ prim.mQuadID ]; rect.Grow ( quad.mV [ 0 ]); rect.Grow ( quad.mV [ 1 ]); rect.Grow ( quad.mV [ 2 ]); rect.Grow ( quad.mV [ 3 ]); } } } return rect; }
//----------------------------------------------------------------// USRect MOAIDeck::GetBounds ( u32 idx, MOAIDeckRemapper* remapper ) { UNUSED ( idx ); UNUSED ( remapper ); USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); return rect; }
//----------------------------------------------------------------// USRect MOAIQuadBrush::GetUVBounds () { USRect rect; rect.Init ( this->mUV [ 0 ]); rect.Grow ( this->mUV [ 1 ]); rect.Grow ( this->mUV [ 2 ]); rect.Grow ( this->mUV [ 3 ]); return rect; }
//----------------------------------------------------------------// USRect MOAIQuadBrush::GetVtxBounds () { USRect rect; rect.Init ( this->mVtx [ 0 ]); rect.Grow ( this->mVtx [ 1 ]); rect.Grow ( this->mVtx [ 2 ]); rect.Grow ( this->mVtx [ 3 ]); return rect; }
//----------------------------------------------------------------// USRect USGLQuad::GetVtxBounds () { USRect rect; rect.Init ( this->mVtx [ 0 ]); rect.Grow ( this->mVtx [ 1 ]); rect.Grow ( this->mVtx [ 2 ]); rect.Grow ( this->mVtx [ 3 ]); return rect; }
//----------------------------------------------------------------// USRect USGLQuad::GetUVBounds () { USRect rect; rect.Init ( this->mUV [ 0 ]); rect.Grow ( this->mUV [ 1 ]); rect.Grow ( this->mUV [ 2 ]); rect.Grow ( this->mUV [ 3 ]); return rect; }
//----------------------------------------------------------------// USRect MOAIMesh::GetBounds ( u32 idx, MOAIDeckRemapper* remapper ) { UNUSED ( idx ); UNUSED ( remapper ); if ( this->mVertexBuffer ) { return this->mVertexBuffer->GetBounds (); } USRect bounds; bounds.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); return bounds; }
//----------------------------------------------------------------// USRect MOAISurfaceDeck2D::GetRect ( u32 idx, MOAIDeckRemapper* remapper ) { idx = remapper ? remapper->Remap ( idx ) : idx; idx = idx - 1; if ( idx < this->mBrushes.Size ()) { return this->mBrushes [ idx ].mBounds; } USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); return rect; }
USRect MOAISurfaceDeck2D::GetRect () { u32 size = this->mBrushes.Size (); USRect totalRect; totalRect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); for ( int i = 0; i < size; ++i ) { totalRect.Grow ( this->mBrushes [ i ].mBounds ); } return totalRect; }
//----------------------------------------------------------------// USBox MOAIGfxQuadDeck2D::ComputeMaxBounds () { USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); u32 size = this->mQuads.Size (); for ( u32 i = 0; i < size; ++i ) { rect.Grow ( this->mQuads [ i ].GetVtxBounds ()); } USBox bounds; bounds.Init ( rect.mXMin, rect.mYMax, rect.mXMax, rect.mYMin, 0.0f, 0.0f ); return bounds; }
USRect MOAIGfxQuadDeck2D::GetRect ( ) { u32 size = this->mQuads.Size (); USRect totalRect; totalRect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); for ( u32 i = 0; i < size; ++i ) { MOAIQuadBrush& quad = this->mQuads [ i ]; USRect rect = quad.GetVtxBounds (); totalRect.Grow ( rect ); } return totalRect; }
//----------------------------------------------------------------// bool USFrustum::GetXYSectRect ( const USAffine3D& mtx, USRect& rect ) const { u32 nHits = 0; USVec2D hits [ 12 ]; USVec3D nlt = this->mPoints [ NEAR_LT_POINT ]; USVec3D nrt = this->mPoints [ NEAR_RT_POINT ]; USVec3D nrb = this->mPoints [ NEAR_RB_POINT ]; USVec3D nlb = this->mPoints [ NEAR_LB_POINT ]; USVec3D flt = this->mPoints [ FAR_LT_POINT ]; USVec3D frt = this->mPoints [ FAR_RT_POINT ]; USVec3D frb = this->mPoints [ FAR_RB_POINT ]; USVec3D flb = this->mPoints [ FAR_LB_POINT ]; mtx.Transform ( nlt ); mtx.Transform ( nrt ); mtx.Transform ( nrb ); mtx.Transform ( nlb ); mtx.Transform ( flt ); mtx.Transform ( frt ); mtx.Transform ( frb ); mtx.Transform ( flb ); if ( _vecToXYPlane ( nlt, flt, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nrt, frt, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nrb, frb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nlb, flb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nlt, nrt, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nrt, nrb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nrb, nlb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( nlb, nlt, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( flt, frt, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( frt, frb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( frb, flb, hits [ nHits ])) ++nHits; if ( _vecToXYPlane ( flb, flt, hits [ nHits ])) ++nHits; if ( nHits ) { rect.Init ( hits [ 0 ]); for ( u32 i = 1; i < nHits; ++i ) { rect.Grow ( hits [ i ]); } return true; } return false; }
//----------------------------------------------------------------// USBox MOAISurfaceDeck2D::ComputeMaxBounds () { u32 size = this->mBrushes.Size (); USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); for ( u32 i = 0; i < size; ++i ) { rect.Grow ( this->mBrushes [ i ].mBounds ); } USBox bounds; bounds.Init ( rect.mXMin, rect.mYMax, rect.mXMax, rect.mYMin, 0.0f, 0.0f ); return bounds; }
//----------------------------------------------------------------// USRect MOAIGfxQuadDeck2D::GetBounds ( u32 idx, MOAIDeckRemapper* remapper ) { u32 size = this->mQuads.Size (); if ( size ) { idx = remapper ? remapper->Remap ( idx ) : idx; idx = ( idx - 1 ) % size; MOAIQuadBrush& quad = this->mQuads [ idx ]; return quad.GetVtxBounds (); } USRect rect; rect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); return rect; }
//----------------------------------------------------------------// USRect MOAIGlyph::GetRect ( float x, float y ) const { USRect rect; x += ( this->mBearingX ); y -= ( this->mBearingY ); rect.Init ( x, y, x + this->mWidth, y + this->mHeight ); return rect; }
//----------------------------------------------------------------// USRect MOAIScissorRect::GetScissorRect ( const USMatrix4x4& worldToWndMtx ) const { USVec3D vtx3D [ 4 ]; vtx3D [ 0 ].mX = this->mRect.mXMin; vtx3D [ 0 ].mY = this->mRect.mYMin; vtx3D [ 0 ].mZ = 0.0f; vtx3D [ 1 ].mX = this->mRect.mXMin; vtx3D [ 1 ].mY = this->mRect.mYMax; vtx3D [ 1 ].mZ = 0.0f; vtx3D [ 2 ].mX = this->mRect.mXMax; vtx3D [ 2 ].mY = this->mRect.mYMax; vtx3D [ 2 ].mZ = 0.0f; vtx3D [ 3 ].mX = this->mRect.mXMax; vtx3D [ 3 ].mY = this->mRect.mYMin; vtx3D [ 3 ].mZ = 0.0f; USMatrix4x4 mtx; mtx.Init ( this->GetLocalToWorldMtx ()); mtx.Append ( worldToWndMtx ); mtx.Project ( vtx3D [ 0 ]); mtx.Project ( vtx3D [ 1 ]); mtx.Project ( vtx3D [ 2 ]); mtx.Project ( vtx3D [ 3 ]); USRect scissorRect; scissorRect.Init ( vtx3D [ 0 ]); scissorRect.Grow ( vtx3D [ 1 ]); scissorRect.Grow ( vtx3D [ 2 ]); scissorRect.Grow ( vtx3D [ 3 ]); if ( this->mScissorRect ) { USRect parentRect = this->mScissorRect->GetScissorRect ( worldToWndMtx ); parentRect.Clip ( scissorRect ); } return scissorRect; }
//----------------------------------------------------------------// void MOAIDraw::DrawRay ( float x, float y, float dx, float dy ) { USVec2D loc ( x, y ); USVec2D vec ( dx, dy ); USMatrix4x4 mtx = MOAIGfxDevice::Get ().GetViewProjMtx (); USMatrix4x4 invMtx; invMtx.Inverse ( mtx ); mtx.Transform ( loc ); mtx.TransformVec ( vec ); USRect viewRect; viewRect.Init ( -1.0f, -1.0f, 1.0f, 1.0f ); USVec2D p0; USVec2D p1; if ( viewRect.GetIntersection ( loc, vec, p0, p1 )) { invMtx.Transform ( p0 ); invMtx.Transform ( p1 ); MOAIGfxDevice& gfxDevice = MOAIGfxDevice::Get (); gfxDevice.BeginPrim ( GL_LINES ); gfxDevice.WriteVtx ( p0.mX, p0.mY, 0.0f ); gfxDevice.WriteFinalColor4b (); gfxDevice.WriteVtx ( p1.mX, p1.mY, 0.0f ); gfxDevice.WriteFinalColor4b (); gfxDevice.EndPrim (); } }
//----------------------------------------------------------------// void MOAIDraw::DrawAxisGrid ( USVec2D loc, USVec2D vec, float size ) { USMatrix4x4 mtx = MOAIGfxDevice::Get ().GetViewProjMtx (); USMatrix4x4 invMtx; invMtx.Inverse ( mtx ); // Set the axis to the grid length so we can get the length back post-transform vec.SetLength ( size ); mtx.Transform ( loc ); mtx.TransformVec ( vec ); // Get the axis unit vector USVec2D norm = vec; size = norm.NormSafe (); // Get the axis normal USVec2D perpNorm ( norm.mY, -norm.mX ); // Project the corners of the viewport onto the axis to get the mix/max bounds float dot; float min; float max; USVec2D corner; // left, top corner.Init ( -1.0f, 1.0f ); corner.Sub ( loc ); dot = norm.Dot ( corner ); min = dot; max = dot; // right, top corner.Init ( 1.0f, 1.0f ); corner.Sub ( loc ); dot = norm.Dot ( corner ); min = ( dot < min ) ? dot : min; max = ( dot > max ) ? dot : max; // right, bottom corner.Init ( 1.0f, -1.0f ); corner.Sub ( loc ); dot = norm.Dot ( corner ); min = ( dot < min ) ? dot : min; max = ( dot > max ) ? dot : max; // left, bottom corner.Init ( -1.0f, -1.0f ); corner.Sub ( loc ); dot = norm.Dot ( corner ); min = ( dot < min ) ? dot : min; max = ( dot > max ) ? dot : max; // Get the start andstop grids s32 start = ( s32 )( min / size ) - 1; s32 stop = ( s32 )( max / size ) + 1; // Set the pen to the first... USVec2D pen = norm; pen.Scale (( float )start * size ); pen.Add ( loc ); // Step along the axis to draw perpendicular grid lines USRect viewRect; viewRect.Init ( -1.0f, -1.0f, 1.0f, 1.0f ); for ( ; start < stop; ++start ) { USVec2D p0; USVec2D p1; if ( viewRect.GetIntersection ( pen, perpNorm, p0, p1 )) { invMtx.Transform ( p0 ); invMtx.Transform ( p1 ); MOAIDraw::DrawLine ( p0, p1 ); } pen.Add ( vec ); } }
//----------------------------------------------------------------// void MOAITextDesigner::BuildLayout ( MOAITextBox& textBox ) { if ( !textBox.mStyleMap.GetTop ()) return; this->mStr = textBox.mText; this->mIdx = textBox.mCurrentPageIdx; this->mStyleSpan = 0; this->mStyle = 0; int tokenIdx = this->mIdx; int lineIdx = this->mIdx; float width = textBox.mFrame.Width (); float height = textBox.mFrame.Height (); u32 lineStart = 0; u32 lineSize = 0; u32 tokenStart = 0; u32 tokenSize = 0; USRect lineRect; lineRect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); USRect tokenRect; tokenRect.Init ( 0.0f, 0.0f, 0.0f, 0.0f ); float tokenAscent = 0.0f; float lineAscent = 0.0f; USVec2D pen; pen.Init ( 0.0f, 0.0f ); MOAIGlyph* glyph = 0; MOAIGlyph* prevGlyph = 0; textBox.mMore = true; bool more = true; while ( more ) { u32 c = this->NextChar ( textBox ); float scale = textBox.mGlyphScale * ( this->mStyle ? this->mStyle->mScale : 1.0f ); bool acceptToken = false; bool acceptLine = false; if ( MOAIFont::IsControl ( c )) { if ( c == '\n' ) { tokenIdx = this->mIdx - 1; tokenStart = textBox.mSprites.GetTop (); acceptToken = true; acceptLine = true; if ( !tokenRect.Height ()) { tokenRect.mYMax += this->mDeck->mHeight * scale; } } else if ( c == 0 ) { textBox.mMore = false; tokenIdx = this->mIdx - 1; tokenStart = textBox.mSprites.GetTop (); acceptToken = true; acceptLine = true; more = false; } } else { glyph = this->mDeck->GetGlyph ( c ); if ( !glyph ) continue; if ( glyph->mAdvanceX == 0.0f ) continue; // apply kerning if ( prevGlyph ) { MOAIKernVec kernVec = prevGlyph->GetKerning ( glyph->mCode ); pen.mX += kernVec.mX * scale; } prevGlyph = glyph; if ( MOAIFont::IsWhitespace ( c )) { if ( tokenSize ) { acceptToken = true; } } else { float glyphBottom = pen.mY + ( this->mDeck->mHeight * scale ); // handle new token if ( !tokenSize ) { tokenIdx = this->mIdx - 1; tokenStart = textBox.mSprites.GetTop (); tokenRect.Init ( pen.mX, pen.mY, pen.mX, glyphBottom ); tokenAscent = this->mDeck->mAscent * scale; } // check for overrun float glyphRight = pen.mX + (( glyph->mBearingX + glyph->mWidth ) * scale ); bool overrun = glyphRight > width; acceptLine = ( lineSize && overrun ); if ( acceptLine || !overrun ) { textBox.PushSprite ( this->mIdx - 1, *glyph, *this->mStyle, pen.mX, pen.mY, scale ); tokenRect.mXMax = glyphRight; tokenSize++; } } pen.mX += glyph->mAdvanceX * scale; } if ( acceptToken ) { lineRect.Grow ( tokenRect ); lineSize += tokenSize; lineAscent = tokenAscent > lineAscent ? tokenAscent : lineAscent; tokenSize = 0; } if ( acceptLine ) { textBox.PushLine ( lineStart, lineSize, lineRect, lineAscent ); // end line pen.mY += lineRect.Height () + textBox.mLineSpacing; lineRect.Init ( 0.0f, pen.mY, 0.0f, pen.mY ); // next line lineIdx = tokenIdx; lineStart = tokenStart; lineSize = 0; lineAscent = 0.0f; prevGlyph = 0; if ( tokenSize ){ // slide the current token (if any) back to the origin for ( u32 i = 0; i < tokenSize; ++i ) { MOAITextSprite& sprite = textBox.mSprites [ tokenStart + i ]; sprite.mX -= tokenRect.mXMin; sprite.mY = pen.mY; } pen.mX -= tokenRect.mXMin; tokenRect.Init ( 0.0f, pen.mY, tokenRect.Width (), pen.mY + tokenRect.Height ()); } else { pen.mX = 0.0f; tokenRect.Init ( 0.0f, pen.mY, 0.0f, pen.mY + this->mDeck->mHeight ); } } // if we overrun height, then back up to the start of the current line if ( tokenRect.mYMax > height ) { textBox.mSprites.SetTop ( lineStart ); textBox.mNextPageIdx = lineIdx; more = false; } } if ( textBox.mSprites.GetTop () == 0 ) { textBox.mMore = false; return; } float yOff = textBox.mFrame.mYMin; float layoutHeight = lineRect.mYMax; switch ( textBox.mVAlign ) { case MOAITextBox::CENTER_JUSTIFY: yOff = ( yOff + ( height * 0.5f )) - ( layoutHeight * 0.5f ); case MOAITextBox::LEFT_JUSTIFY: break; case MOAITextBox::RIGHT_JUSTIFY: yOff = textBox.mFrame.mYMax - layoutHeight; } u32 totalLines = textBox.mLines.GetTop (); for ( u32 i = 0; i < totalLines; ++i ) { MOAITextLine& line = textBox.mLines [ i ]; float xOff = textBox.mFrame.mXMin; float lineWidth = line.mRect.Width (); switch ( textBox.mHAlign ) { case MOAITextBox::CENTER_JUSTIFY: xOff = ( xOff + ( width * 0.5f )) - ( lineWidth * 0.5f ); case MOAITextBox::LEFT_JUSTIFY: break; case MOAITextBox::RIGHT_JUSTIFY: xOff = textBox.mFrame.mXMax - lineWidth; } line.mRect.Offset ( xOff, yOff ); float spriteYOff = yOff + line.mAscent; MOAIAnimCurve* curve = 0; if ( textBox.mCurves ) { curve = textBox.mCurves [ i % textBox.mCurves.Size ()]; } for ( u32 j = 0; j < line.mSize; ++j ) { MOAITextSprite& sprite = textBox.mSprites [ line.mStart + j ]; sprite.mX += xOff; if ( curve ) { sprite.mY += spriteYOff + curve->GetFloatValue (( sprite.mX - textBox.mFrame.mXMin ) / width ); } else { sprite.mY += spriteYOff; } } } }
//----------------------------------------------------------------// void MOAIStretchPatch2D::DrawStretch ( u32 idx, float xStretch, float yStretch ) { USRect uvRect; u32 totalUVRects = this->mUVRects.Size (); idx = ( idx - 1 ) % totalUVRects; if ( totalUVRects == 0 ) { uvRect.Init ( 0.0f, 1.0f, 1.0f, 0.0f ); } else { uvRect = this->mUVRects [ idx ]; } float nativeWidth = this->mRect.Width (); float nativeHeight = this->mRect.Height (); float rectWidth = nativeWidth * xStretch; float rectHeight = nativeHeight * yStretch; float xMin = this->mRect.mXMin * xStretch; float yMin = this->mRect.mYMin * yStretch; float uMin = uvRect.mXMin; float vMin = uvRect.mYMin; // scale for x patches float xPatchScale = 1.0f; float xStretchPatchScale = 1.0f; if ( rectWidth > nativeWidth ) { xStretchPatchScale = ( rectWidth - ( nativeWidth * this->mXFix )) / ( nativeWidth * this->mXFlex ); } else { xPatchScale = rectWidth / nativeWidth; xStretchPatchScale = xPatchScale; } // scale for y patches float yPatchScale = 1.0f; float yStretchPatchScale = 1.0f; if ( rectHeight > nativeHeight ) { yStretchPatchScale = ( rectHeight - ( nativeHeight * this->mYFix )) / ( nativeHeight * this->mYFlex ); } else { yPatchScale = rectHeight / nativeHeight; yStretchPatchScale = yPatchScale; } u32 totalRows = this->mRows.Size (); u32 totalCols = this->mCols.Size (); MOAIQuadBrush quad; float uSpan = uvRect.mXMax - uvRect.mXMin; float vSpan = uvRect.mYMax - uvRect.mYMin; float y = yMin; float v = vMin; for ( u32 i = 0; i < totalRows; ++i ) { MOAIStretchPatchSpan& row = this->mRows [ i ]; float vStep = row.mPercent * vSpan; float h = nativeHeight * row.mPercent; if ( row.mCanStretch ) { h *= yStretchPatchScale; } else { h *= yPatchScale; } float x = xMin; float u = uMin; for ( u32 j = 0; j < totalCols; ++j ) { MOAIStretchPatchSpan& col = this->mCols [ j ]; float uStep = col.mPercent * uSpan; float w = nativeWidth * col.mPercent; if ( col.mCanStretch ) { w *= xStretchPatchScale; } else { w *= xPatchScale; } quad.SetVerts ( x, y, x + w, y + h ); quad.SetUVs ( u, v, u + uStep, v + vStep ); quad.Draw (); x += w; u += uStep; } y += h; v += vStep; } }