| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- //
- // Urho3D Engine
- // Copyright (c) 2008-2011 Lasse Öörni
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #include "Precompiled.h"
- #include "PixelShader.h"
- #include "Renderer.h"
- #include "Texture.h"
- #include "UIElement.h"
- #include "VertexShader.h"
- #include "DebugNew.h"
- void UIBatch::begin(std::vector<UIQuad>* quads)
- {
- if (quads)
- {
- mQuads = quads;
- mQuadStart = mQuads->size();
- mQuadCount = 0;
- }
- }
- void UIBatch::addQuad(UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY)
- {
- if (!mQuads)
- return;
-
- static UIQuad quad;
- const IntVector2& screenPos = element.getScreenPosition();
-
- quad.mLeft = x + screenPos.mX;
- quad.mTop = y + screenPos.mY;
- quad.mRight = quad.mLeft + width;
- quad.mBottom = quad.mTop + height;
- quad.mLeftUV = texOffsetX;
- quad.mTopUV = texOffsetY;
- quad.mRightUV = texOffsetX + width;
- quad.mBottomUV = texOffsetY + height;
-
- if (element.hasColorGradient())
- {
- quad.mTopLeftColor = getInterpolatedColor(element, x, y);
- quad.mTopRightColor = getInterpolatedColor(element, x + width, y);
- quad.mBottomLeftColor = getInterpolatedColor(element, x, y + height);
- quad.mBottomRightColor = getInterpolatedColor(element, x + width, y + height);
- }
- else
- {
- Color color = element.getColor(C_TOPLEFT);
- color.mA *= element.getDerivedOpacity();
- // If alpha is 0, nothing will be rendered, so exit without adding the quad
- if (color.mA <= 0.0f)
- return;
- unsigned uintColor = getD3DColor(color);
- quad.mTopLeftColor = uintColor;
- quad.mTopRightColor = uintColor;
- quad.mBottomLeftColor = uintColor;
- quad.mBottomRightColor = uintColor;
- }
-
- mQuads->push_back(quad);
- mQuadCount++;
- }
- void UIBatch::addQuad(UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth,
- int texHeight)
- {
- if (!mQuads)
- return;
-
- static UIQuad quad;
- const IntVector2& screenPos = element.getScreenPosition();
-
- quad.mLeft = x + screenPos.mX;
- quad.mTop = y + screenPos.mY;
- quad.mRight = quad.mLeft + width;
- quad.mBottom = quad.mTop + height;
- quad.mLeftUV = texOffsetX;
- quad.mTopUV = texOffsetY;
- quad.mRightUV = texOffsetX + texWidth;
- quad.mBottomUV = texOffsetY + texHeight;
-
- if (element.hasColorGradient())
- {
- quad.mTopLeftColor = getInterpolatedColor(element, x, y);
- quad.mTopRightColor = getInterpolatedColor(element, x + width, y);
- quad.mBottomLeftColor = getInterpolatedColor(element, x, y + height);
- quad.mBottomRightColor = getInterpolatedColor(element, x + width, y + height);
- }
- else
- {
- Color color = element.getColor(C_TOPLEFT);
- color.mA *= element.getDerivedOpacity();
- // If alpha is 0, nothing will be rendered, so exit without adding the quad
- if (color.mA <= 0.0f)
- return;
- unsigned uintColor = getD3DColor(color);
- quad.mTopLeftColor = uintColor;
- quad.mTopRightColor = uintColor;
- quad.mBottomLeftColor = uintColor;
- quad.mBottomRightColor = uintColor;
- }
-
- mQuads->push_back(quad);
- mQuadCount++;
- }
- void UIBatch::addQuad(UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth,
- int texHeight, const Color& color)
- {
- if (!mQuads)
- return;
-
- static UIQuad quad;
- const IntVector2& screenPos = element.getScreenPosition();
-
- quad.mLeft = x + screenPos.mX;
- quad.mTop = y + screenPos.mY;
- quad.mRight = quad.mLeft + width;
- quad.mBottom = quad.mTop + height;
- quad.mLeftUV = texOffsetX;
- quad.mTopUV = texOffsetY;
- quad.mRightUV = texOffsetX + texWidth;
- quad.mBottomUV = texOffsetY + texHeight;
-
- Color derivedColor(color.mR, color.mG, color.mB, color.mA * element.getDerivedOpacity());
- // If alpha is 0, nothing will be rendered, so exit without adding the quad
- if (derivedColor.mA <= 0.0f)
- return;
- unsigned uintColor = getD3DColor(derivedColor);
- quad.mTopLeftColor = uintColor;
- quad.mTopRightColor = uintColor;
- quad.mBottomLeftColor = uintColor;
- quad.mBottomRightColor = uintColor;
-
- mQuads->push_back(quad);
- mQuadCount++;
- }
- bool UIBatch::merge(const UIBatch& batch)
- {
- if ((batch.mBlendMode != mBlendMode) ||
- (batch.mScissor != mScissor) ||
- (batch.mTexture != mTexture) ||
- (batch.mQuads != mQuads) ||
- (batch.mQuadStart != mQuadStart + mQuadCount))
- return false;
-
- mQuadCount += batch.mQuadCount;
- return true;
- }
- void UIBatch::draw(Renderer* renderer, VertexShader* vs, PixelShader* ps) const
- {
- if ((!mQuads) || (!mQuadCount))
- return;
-
- // Use alpha test if not alpha blending
- if ((mBlendMode != BLEND_ALPHA) && (mBlendMode != BLEND_ADDALPHA) && (mBlendMode != BLEND_PREMULALPHA))
- renderer->setAlphaTest(true, CMP_GREATEREQUAL, 0.5f);
- else
- renderer->setAlphaTest(false);
-
- renderer->setBlendMode(mBlendMode);
- renderer->setScissorTest(true, mScissor);
- renderer->setTexture(0, mTexture);
- renderer->setVertexShader(vs);
- renderer->setPixelShader(ps);
-
- static const Vector2 posAdjust(0.5f, 0.5f);
- Vector2 invScreenSize(1.0f / (float)renderer->getWidth(), 1.0f / (float)renderer->getHeight());
-
- const std::vector<UIQuad>& quads = *mQuads;
-
- if (mTexture)
- {
- Vector2 invTextureSize(1.0f / (float)mTexture->getWidth(), 1.0f / (float)mTexture->getHeight());
-
- renderer->beginImmediate(TRIANGLE_LIST, mQuadCount * 6, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1);
- float* dest = (float*)renderer->getImmediateDataPtr();
-
- for (unsigned i = mQuadStart; i < mQuadStart + mQuadCount; ++i)
- {
- const UIQuad& quad = quads[i];
- static Vector2 topLeft, bottomRight, topLeftUV, bottomRightUV;
-
- topLeft = (Vector2((float)quad.mLeft, (float)quad.mTop) - posAdjust) * invScreenSize;
- bottomRight = (Vector2((float)quad.mRight, (float)quad.mBottom) - posAdjust) * invScreenSize;
- topLeftUV = Vector2((float)quad.mLeftUV, (float)quad.mTopUV) * invTextureSize;
- bottomRightUV = Vector2((float)quad.mRightUV, (float)quad.mBottomUV) * invTextureSize;
-
- *dest++ = topLeft.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopLeftColor; dest++;
- *dest++ = topLeftUV.mX; *dest++ = topLeftUV.mY;
-
- *dest++ = bottomRight.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopRightColor; dest++;
- *dest++ = bottomRightUV.mX; *dest++ = topLeftUV.mY;
-
- *dest++ = topLeft.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomLeftColor; dest++;
- *dest++ = topLeftUV.mX; *dest++ = bottomRightUV.mY;
-
- *dest++ = bottomRight.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopRightColor; dest++;
- *dest++ = bottomRightUV.mX; *dest++ = topLeftUV.mY;
-
- *dest++ = bottomRight.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomRightColor; dest++;
- *dest++ = bottomRightUV.mX; *dest++ = bottomRightUV.mY;
-
- *dest++ = topLeft.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomLeftColor; dest++;
- *dest++ = topLeftUV.mX; *dest++ = bottomRightUV.mY;
- }
-
- renderer->endImmediate();
- }
- else
- {
- renderer->beginImmediate(TRIANGLE_LIST, mQuadCount * 6, MASK_POSITION | MASK_COLOR);
- float* dest = (float*)renderer->getImmediateDataPtr();
-
- for (unsigned i = mQuadStart; i < mQuadStart + mQuadCount; ++i)
- {
- const UIQuad& quad = quads[i];
- static Vector2 topLeft, bottomRight, topLeftUV, bottomRightUV;
-
- topLeft = (Vector2((float)quad.mLeft, (float)quad.mTop) - posAdjust) * invScreenSize;
- bottomRight = (Vector2((float)quad.mRight, (float)quad.mBottom) - posAdjust) * invScreenSize;
-
- *dest++ = topLeft.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopLeftColor; dest++;
-
- *dest++ = bottomRight.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopRightColor; dest++;
-
- *dest++ = topLeft.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomLeftColor; dest++;
-
- *dest++ = bottomRight.mX; *dest++ = topLeft.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mTopRightColor; dest++;
-
- *dest++ = bottomRight.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomRightColor; dest++;
-
- *dest++ = topLeft.mX; *dest++ = bottomRight.mY; *dest++ = 0.0f;
- *((unsigned*)dest) = quads[i].mBottomLeftColor; dest++;
- }
-
- renderer->endImmediate();
- }
- }
- void UIBatch::addOrMerge(const UIBatch& batch, std::vector<UIBatch>& batches)
- {
- if (!batch.mQuadCount)
- return;
-
- if (!batches.size())
- batches.push_back(batch);
- else
- {
- if (batches.back().merge(batch))
- return;
- else
- batches.push_back(batch);
- }
- }
- unsigned UIBatch::getInterpolatedColor(UIElement& element, int x, int y)
- {
- const IntVector2& size = element.getSize();
-
- if ((size.mX) && (size.mY))
- {
- float cLerpX = clamp((float)x / (float)size.mX, 0.0f, 1.0f);
- float cLerpY = clamp((float)y / (float)size.mY, 0.0f, 1.0f);
-
- Color topColor = element.getColor(C_TOPLEFT).lerp(element.getColor(C_TOPRIGHT), cLerpX);
- Color bottomColor = element.getColor(C_BOTTOMLEFT).lerp(element.getColor(C_BOTTOMRIGHT), cLerpX);
- Color color = topColor.lerp(bottomColor, cLerpY);
- color.mA *= element.getDerivedOpacity();
- return getD3DColor(color);
- }
- else
- {
- Color color = element.getColor(C_TOPLEFT);
- color.mA *= element.getDerivedOpacity();
- return getD3DColor(color);
- }
- }
|