mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 11:53:53 +00:00
834 lines
22 KiB
C++
834 lines
22 KiB
C++
/*!
|
||
@file
|
||
@author Albert Semenov
|
||
@date 09/2009
|
||
@module
|
||
*/
|
||
/*
|
||
This file is part of MyGUI.
|
||
|
||
MyGUI is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
MyGUI is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include "MyGUI_Precompiled.h"
|
||
#include "MyGUI_EditText.h"
|
||
#include "MyGUI_RenderItem.h"
|
||
#include "MyGUI_FontManager.h"
|
||
#include "MyGUI_RenderManager.h"
|
||
#include "MyGUI_LanguageManager.h"
|
||
#include "MyGUI_TextIterator.h"
|
||
#include "MyGUI_IRenderTarget.h"
|
||
#include "MyGUI_FontData.h"
|
||
#include "MyGUI_CommonStateInfo.h"
|
||
|
||
namespace MyGUI
|
||
{
|
||
|
||
const size_t VERTEX_IN_QUAD = 6;
|
||
const size_t SIMPLETEXT_COUNT_VERTEX = 32 * VERTEX_IN_QUAD;
|
||
|
||
MYGUI_FORCEINLINE void DrawQuad(
|
||
MyGUI::Vertex*& _buff,
|
||
float v_left,
|
||
float v_top,
|
||
float v_rignt,
|
||
float v_bottom,
|
||
float v_z,
|
||
MyGUI::uint32 _colour,
|
||
float t_left,
|
||
float t_top,
|
||
float t_right,
|
||
float t_bottom,
|
||
size_t& _count)
|
||
{
|
||
_buff[0].x = v_left;
|
||
_buff[0].y = v_top;
|
||
_buff[0].z = v_z;
|
||
_buff[0].colour = _colour;
|
||
_buff[0].u = t_left;
|
||
_buff[0].v = t_top;
|
||
|
||
_buff[1].x = v_left;
|
||
_buff[1].y = v_bottom;
|
||
_buff[1].z = v_z;
|
||
_buff[1].colour = _colour;
|
||
_buff[1].u = t_left;
|
||
_buff[1].v = t_bottom;
|
||
|
||
_buff[2].x = v_rignt;
|
||
_buff[2].y = v_top;
|
||
_buff[2].z = v_z;
|
||
_buff[2].colour = _colour;
|
||
_buff[2].u = t_right;
|
||
_buff[2].v = t_top;
|
||
|
||
_buff[3].x = v_rignt;
|
||
_buff[3].y = v_top;
|
||
_buff[3].z = v_z;
|
||
_buff[3].colour = _colour;
|
||
_buff[3].u = t_right;
|
||
_buff[3].v = t_top;
|
||
|
||
_buff[4].x = v_left;
|
||
_buff[4].y = v_bottom;
|
||
_buff[4].z = v_z;
|
||
_buff[4].colour = _colour;
|
||
_buff[4].u = t_left;
|
||
_buff[4].v = t_bottom;
|
||
|
||
_buff[5].x = v_rignt;
|
||
_buff[5].y = v_bottom;
|
||
_buff[5].z = v_z;
|
||
_buff[5].colour = _colour;
|
||
_buff[5].u = t_right;
|
||
_buff[5].v = t_bottom;
|
||
|
||
_buff += VERTEX_IN_QUAD;
|
||
_count += VERTEX_IN_QUAD;
|
||
}
|
||
|
||
EditText::EditText() :
|
||
ISubWidgetText(),
|
||
mEmptyView(false),
|
||
mCurrentColour(0x00FFFFFF),
|
||
mInverseColour(0x00000000),
|
||
mCurrentAlpha(0xFF000000),
|
||
mTextOutDate(false),
|
||
mTextAlign(Align::Default),
|
||
mColour(Colour::White),
|
||
mAlpha(ALPHA_MAX),
|
||
mFont(nullptr),
|
||
mTexture(nullptr),
|
||
mFontHeight(0),
|
||
mBackgroundNormal(true),
|
||
mStartSelect(0),
|
||
mEndSelect(0),
|
||
mCursorPosition(0),
|
||
mVisibleCursor(false),
|
||
mInvertSelect(true),
|
||
mNode(nullptr),
|
||
mRenderItem(nullptr),
|
||
mCountVertex(SIMPLETEXT_COUNT_VERTEX),
|
||
mIsAddCursorWidth(true),
|
||
mShiftText(false),
|
||
mWordWrap(false),
|
||
mOldWidth(0)
|
||
{
|
||
mVertexFormat = RenderManager::getInstance().getVertexFormat();
|
||
|
||
mCurrentColour = texture_utility::toColourARGB(mColour);
|
||
texture_utility::convertColour(mCurrentColour, mVertexFormat);
|
||
|
||
mCurrentColour = (mCurrentColour & 0x00FFFFFF) | mCurrentAlpha;
|
||
mInverseColour = mCurrentColour ^ 0x00FFFFFF;
|
||
}
|
||
|
||
EditText::~EditText()
|
||
{
|
||
}
|
||
|
||
void EditText::setVisible(bool _visible)
|
||
{
|
||
if (mVisible == _visible) return;
|
||
mVisible = _visible;
|
||
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::_correctView()
|
||
{
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::_setAlign(const IntCoord& _oldcoord, bool _update)
|
||
{
|
||
_setAlign(_oldcoord.size(), _update);
|
||
}
|
||
|
||
void EditText::_setAlign(const IntSize& _oldsize, bool _update)
|
||
{
|
||
|
||
if (mWordWrap)
|
||
{
|
||
// передается старая координата всегда
|
||
int width = mCroppedParent->getWidth();
|
||
if (mOldWidth != width)
|
||
{
|
||
mOldWidth = width;
|
||
mTextOutDate = true;
|
||
}
|
||
}
|
||
|
||
// необходимо разобраться
|
||
bool need_update = true;//_update;
|
||
|
||
// первоначальное выравнивание
|
||
if (mAlign.isHStretch())
|
||
{
|
||
// растягиваем
|
||
mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
|
||
need_update = true;
|
||
mIsMargin = true; // при изменении размеров все пересчитывать
|
||
}
|
||
else if (mAlign.isRight())
|
||
{
|
||
// двигаем по правому краю
|
||
mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
|
||
need_update = true;
|
||
}
|
||
else if (mAlign.isHCenter())
|
||
{
|
||
// выравнивание по горизонтали без растяжения
|
||
mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
|
||
need_update = true;
|
||
}
|
||
|
||
if (mAlign.isVStretch())
|
||
{
|
||
// растягиваем
|
||
mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
|
||
need_update = true;
|
||
mIsMargin = true; // при изменении размеров все пересчитывать
|
||
}
|
||
else if (mAlign.isBottom())
|
||
{
|
||
// двигаем по нижнему краю
|
||
mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
|
||
need_update = true;
|
||
}
|
||
else if (mAlign.isVCenter())
|
||
{
|
||
// выравнивание по вертикали без растяжения
|
||
mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
|
||
need_update = true;
|
||
}
|
||
|
||
if (need_update)
|
||
{
|
||
mCurrentCoord = mCoord;
|
||
_updateView();
|
||
}
|
||
|
||
}
|
||
|
||
void EditText::_updateView()
|
||
{
|
||
bool margin = _checkMargin();
|
||
|
||
mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
|
||
|
||
mCurrentCoord.left = mCoord.left + mMargin.left;
|
||
mCurrentCoord.top = mCoord.top + mMargin.top;
|
||
|
||
// вьюпорт стал битым
|
||
if (margin)
|
||
{
|
||
// проверка на полный выход за границу
|
||
if (_checkOutside())
|
||
{
|
||
// запоминаем текущее состояние
|
||
mIsMargin = margin;
|
||
|
||
// обновить перед выходом
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// мы обрезаны или были обрезаны
|
||
if ((mIsMargin) || (margin))
|
||
{
|
||
mCurrentCoord.width = _getViewWidth();
|
||
mCurrentCoord.height = _getViewHeight();
|
||
}
|
||
|
||
// запоминаем текущее состояние
|
||
mIsMargin = margin;
|
||
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::setCaption(const UString& _value)
|
||
{
|
||
mCaption = _value;
|
||
mTextOutDate = true;
|
||
|
||
// если вершин не хватит, делаем реалок, с учетом выделения * 2 и курсора
|
||
size_t need = (mCaption.size() * 2 + 2) * VERTEX_IN_QUAD;
|
||
if (mCountVertex < need)
|
||
{
|
||
mCountVertex = need + SIMPLETEXT_COUNT_VERTEX;
|
||
if (nullptr != mRenderItem) mRenderItem->reallockDrawItem(this, mCountVertex);
|
||
}
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
const UString& EditText::getCaption()
|
||
{
|
||
return mCaption;
|
||
}
|
||
|
||
void EditText::setTextColour(const Colour& _value)
|
||
{
|
||
if (mColour == _value) return;
|
||
mColour = _value;
|
||
mCurrentColour = texture_utility::toColourARGB(mColour);
|
||
|
||
texture_utility::convertColour(mCurrentColour, mVertexFormat);
|
||
|
||
mCurrentColour = (mCurrentColour & 0x00FFFFFF) | mCurrentAlpha;
|
||
mInverseColour = mCurrentColour ^ 0x00FFFFFF;
|
||
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
const Colour& EditText::getTextColour()
|
||
{
|
||
return mColour;
|
||
}
|
||
|
||
void EditText::setAlpha(float _value)
|
||
{
|
||
if (mAlpha == _value) return;
|
||
mAlpha = _value;
|
||
mCurrentAlpha = ((uint8)(mAlpha*255) << 24);
|
||
mCurrentColour = (mCurrentColour & 0x00FFFFFF) | mCurrentAlpha;
|
||
mInverseColour = mCurrentColour ^ 0x00FFFFFF;
|
||
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
float EditText::getAlpha()
|
||
{
|
||
return mAlpha;
|
||
}
|
||
|
||
void EditText::setFontName(const std::string& _value)
|
||
{
|
||
mTexture = 0;
|
||
mFont = FontManager::getInstance().getByName(_value);
|
||
if (mFont != nullptr)
|
||
{
|
||
mTexture = mFont->getTextureFont();
|
||
|
||
// если надо, устанавливаем дефолтный размер шрифта
|
||
if (mFont->getDefaultHeight() != 0)
|
||
{
|
||
mFontHeight = mFont->getDefaultHeight();
|
||
}
|
||
}
|
||
|
||
mTextOutDate = true;
|
||
|
||
// если мы были приаттаченны, то удаляем себя
|
||
if (nullptr != mRenderItem)
|
||
{
|
||
mRenderItem->removeDrawItem(this);
|
||
mRenderItem = nullptr;
|
||
}
|
||
|
||
// если есть текстура, то приаттачиваемся
|
||
if (nullptr != mTexture && nullptr != mNode)
|
||
{
|
||
mRenderItem = mNode->addToRenderItem(mTexture, this);
|
||
mRenderItem->addDrawItem(this, mCountVertex);
|
||
}
|
||
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
const std::string& EditText::getFontName()
|
||
{
|
||
return mFont->getResourceName();
|
||
}
|
||
|
||
void EditText::setFontHeight(int _value)
|
||
{
|
||
mFontHeight = _value;
|
||
mTextOutDate = true;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
int EditText::getFontHeight()
|
||
{
|
||
return mFontHeight;
|
||
}
|
||
|
||
void EditText::createDrawItem(ITexture* _texture, ILayerNode * _node)
|
||
{
|
||
mNode = _node;
|
||
// если уже есть текстура, то атачимся, актуально для смены леера
|
||
if (nullptr != mTexture)
|
||
{
|
||
MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
|
||
|
||
mRenderItem = mNode->addToRenderItem(mTexture, this);
|
||
mRenderItem->addDrawItem(this, mCountVertex);
|
||
}
|
||
}
|
||
|
||
void EditText::destroyDrawItem()
|
||
{
|
||
if (nullptr != mRenderItem)
|
||
{
|
||
mRenderItem->removeDrawItem(this);
|
||
mRenderItem = nullptr;
|
||
}
|
||
mNode = nullptr;
|
||
}
|
||
|
||
size_t EditText::getTextSelectionStart()
|
||
{
|
||
return mStartSelect;
|
||
}
|
||
|
||
size_t EditText::getTextSelectionEnd()
|
||
{
|
||
return mEndSelect;
|
||
}
|
||
|
||
void EditText::setTextSelection(size_t _start, size_t _end)
|
||
{
|
||
mStartSelect=_start;
|
||
mEndSelect=_end;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
bool EditText::getSelectBackground()
|
||
{
|
||
return mBackgroundNormal;
|
||
}
|
||
|
||
void EditText::setSelectBackground(bool _normal)
|
||
{
|
||
if (mBackgroundNormal == _normal) return;
|
||
mBackgroundNormal = _normal;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
bool EditText::isVisibleCursor()
|
||
{
|
||
return mVisibleCursor;
|
||
}
|
||
|
||
void EditText::setVisibleCursor(bool _value)
|
||
{
|
||
if (mVisibleCursor == _value) return;
|
||
mVisibleCursor = _value;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
size_t EditText::getCursorPosition()
|
||
{
|
||
return mCursorPosition;
|
||
}
|
||
|
||
void EditText::setCursorPosition(size_t _index)
|
||
{
|
||
if (mCursorPosition == _index) return;
|
||
mCursorPosition = _index;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::setTextAlign(Align _value)
|
||
{
|
||
mTextAlign = _value;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
Align EditText::getTextAlign()
|
||
{
|
||
return mTextAlign;
|
||
}
|
||
|
||
IntSize EditText::getTextSize()
|
||
{
|
||
// если нуно обновить, или изменились пропорции экрана
|
||
if (mTextOutDate) updateRawData();
|
||
|
||
IntSize size = mTextView.getViewSize();
|
||
// плюс размер курсора
|
||
if (mIsAddCursorWidth)
|
||
size.width += 2;
|
||
return size;
|
||
}
|
||
|
||
void EditText::setViewOffset(const IntPoint& _point)
|
||
{
|
||
mViewOffset = _point;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
IntPoint EditText::getViewOffset()
|
||
{
|
||
return mViewOffset;
|
||
}
|
||
|
||
size_t EditText::getCursorPosition(const IntPoint& _point)
|
||
{
|
||
if (nullptr == mFont) return 0;
|
||
if (mTextOutDate) updateRawData();
|
||
|
||
IntPoint point = _point;
|
||
point -= mCroppedParent->getAbsolutePosition();
|
||
point += mViewOffset;
|
||
point -= mCoord.point();
|
||
|
||
return mTextView.getCursorPosition(point);
|
||
}
|
||
|
||
IntCoord EditText::getCursorCoord(size_t _position)
|
||
{
|
||
if (nullptr == mFont) return IntCoord();
|
||
if (mTextOutDate) updateRawData();
|
||
|
||
IntPoint point = mTextView.getCursorPoint(_position);
|
||
point += mCroppedParent->getAbsolutePosition();
|
||
point -= mViewOffset;
|
||
point += mCoord.point();
|
||
|
||
return IntCoord(point.left, point.top, 2, mFontHeight);
|
||
}
|
||
|
||
void EditText::setShiftText(bool _value)
|
||
{
|
||
if (mShiftText == _value) return;
|
||
mShiftText = _value;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::setWordWrap(bool _value)
|
||
{
|
||
mWordWrap = _value;
|
||
mTextOutDate = true;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
void EditText::updateRawData()
|
||
{
|
||
if (nullptr == mFont) return;
|
||
// сбрасывам флаги
|
||
mTextOutDate = false;
|
||
|
||
int width = -1;
|
||
if (mWordWrap)
|
||
{
|
||
width = mCoord.width;
|
||
// обрезать слова нужно по шарине, которую мы реально используем
|
||
if (mIsAddCursorWidth)
|
||
width -= 2;
|
||
}
|
||
|
||
mTextView.update(mCaption, mFont, mFontHeight, mTextAlign, mVertexFormat, width);
|
||
}
|
||
|
||
void EditText::setStateData(IStateInfo* _data)
|
||
{
|
||
EditTextStateInfo* data = _data->castType<EditTextStateInfo>();
|
||
if (data->getColour() != Colour::Zero) setTextColour(data->getColour());
|
||
setShiftText(data->getShift());
|
||
}
|
||
|
||
void EditText::doRender()
|
||
{
|
||
if (nullptr == mFont) return;
|
||
if (!mVisible || mEmptyView) return;
|
||
|
||
bool _update = mRenderItem->getCurrentUpdate();
|
||
if (_update) mTextOutDate = true;
|
||
|
||
if (mTextOutDate) updateRawData();
|
||
|
||
Vertex* _vertex = mRenderItem->getCurrentVertextBuffer();
|
||
|
||
const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
|
||
|
||
// колличество отрисованных вершин
|
||
size_t vertex_count = 0;
|
||
|
||
// текущие цвета
|
||
uint32 colour_current = mCurrentColour;
|
||
uint32 colour = mCurrentColour;
|
||
uint32 colour_inverse = mInverseColour;
|
||
|
||
GlyphInfo* back_glyph = mFont->getGlyphInfo(mBackgroundNormal ? FontCodeType::Selected : FontCodeType::SelectedBack);
|
||
|
||
float vertex_z = info.maximumDepth;
|
||
|
||
const VectorLineInfo& data = mTextView.getData();
|
||
|
||
int left = - mViewOffset.left + mCoord.left;
|
||
int top = - mViewOffset.top + mCoord.top;
|
||
int width = 0;
|
||
const int height = mFontHeight;
|
||
|
||
size_t index = 0;
|
||
for (VectorLineInfo::const_iterator line=data.begin(); line!=data.end(); ++line)
|
||
{
|
||
left = line->offset - mViewOffset.left + mCoord.left;
|
||
for (VectorCharInfo::const_iterator sim=line->simbols.begin(); sim!=line->simbols.end(); ++sim)
|
||
{
|
||
if (sim->isColour())
|
||
{
|
||
colour = sim->getColour() | (colour & 0xFF000000);
|
||
colour_inverse = colour ^ 0x00FFFFFF;
|
||
continue;
|
||
}
|
||
|
||
// смещение текстуры для фона
|
||
bool select = !((index >= mEndSelect) || (index < mStartSelect));
|
||
|
||
uint32 back_colour = 0;
|
||
|
||
// выделение символа
|
||
if (!select || !mInvertSelect)
|
||
{
|
||
colour_current = colour;
|
||
back_colour = colour | 0x00FFFFFF;
|
||
}
|
||
else
|
||
{
|
||
colour_current = colour_inverse;
|
||
back_colour = colour_inverse;
|
||
}
|
||
|
||
bool draw = true;
|
||
|
||
// текущие размеры
|
||
MyGUI::FloatRect texture_rect = sim->getUVRect();
|
||
width = sim->getWidth();
|
||
|
||
// конечные размеры
|
||
int result_left = left;
|
||
int result_top = top;
|
||
int result_right = left + width;
|
||
int result_bottom = top + height;
|
||
|
||
float texture_width = texture_rect.right - texture_rect.left;
|
||
float texture_height = texture_rect.bottom - texture_rect.top;
|
||
|
||
// символ залазиет влево
|
||
if (left < mCurrentCoord.left)
|
||
{
|
||
// символ вообще не виден
|
||
if (left + width <= mCurrentCoord.left)
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_left = mCurrentCoord.left;
|
||
texture_rect.left += (texture_width * (float)(result_left - left) / (float)width);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вправо
|
||
if (left + width > mCurrentCoord.right())
|
||
{
|
||
// символ вообще не виден
|
||
if (left >= mCurrentCoord.right())
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_right = mCurrentCoord.right();
|
||
texture_rect.right -= (texture_width * (float)((left + width) - result_right) / (float)width);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вверх
|
||
if (top < mCurrentCoord.top)
|
||
{
|
||
// символ вообще не виден
|
||
if (top + height <= mCurrentCoord.top)
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_top = mCurrentCoord.top;
|
||
texture_rect.top += (texture_height * (float)(result_top - top) / (float)height);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вниз
|
||
if (top + height > mCurrentCoord.bottom())
|
||
{
|
||
// символ вообще не виден
|
||
if (top >= mCurrentCoord.bottom())
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_bottom = mCurrentCoord.bottom();
|
||
texture_rect.bottom -= (texture_height * (float)((top + height) - result_bottom) / (float)height);
|
||
}
|
||
}
|
||
|
||
if (draw)
|
||
{
|
||
int pix_left = mCroppedParent->getAbsoluteLeft() - info.leftOffset + result_left;
|
||
int pix_top = mCroppedParent->getAbsoluteTop() - info.topOffset + (mShiftText ? 1 : 0) + result_top;
|
||
|
||
float real_left = ((info.pixScaleX * (float)(pix_left) + info.hOffset) * 2) - 1;
|
||
float real_top = - (((info.pixScaleY * (float)(pix_top) + info.vOffset) * 2) - 1);
|
||
float real_right = ((info.pixScaleX * (float)(pix_left + result_right - result_left) + info.hOffset) * 2) - 1;
|
||
float real_bottom = - (((info.pixScaleY * (float)(pix_top + result_bottom - result_top) + info.vOffset) * 2) - 1);
|
||
|
||
// если нужно рисуем выделение
|
||
if (select)
|
||
{
|
||
const FloatRect& background_current = back_glyph->uvRect;
|
||
DrawQuad(_vertex, real_left, real_top, real_right, real_bottom, vertex_z, back_colour,
|
||
background_current.left, background_current.top, background_current.left, background_current.top, vertex_count);
|
||
}
|
||
|
||
DrawQuad(_vertex, real_left, real_top, real_right, real_bottom, vertex_z, colour_current,
|
||
texture_rect.left, texture_rect.top, texture_rect.right, texture_rect.bottom, vertex_count);
|
||
}
|
||
|
||
left += width;
|
||
index++;
|
||
}
|
||
|
||
top += height;
|
||
index++;
|
||
}
|
||
|
||
if (mVisibleCursor)
|
||
{
|
||
MyGUI::IntPoint point = mTextView.getCursorPoint(mCursorPosition);
|
||
point -= mViewOffset;
|
||
point += mCoord.point();
|
||
|
||
bool draw = true;
|
||
|
||
GlyphInfo* cursor_glyph = mFont->getGlyphInfo(FontCodeType::Cursor);
|
||
MyGUI::FloatRect texture_rect = cursor_glyph->uvRect;
|
||
left = point.left;
|
||
top = point.top;
|
||
width = 2;//cursor_glyph->width;
|
||
|
||
// конечные размеры
|
||
int result_left = left;
|
||
int result_top = top;
|
||
int result_width = width;
|
||
int result_height = height;
|
||
|
||
// символ залазиет влево
|
||
if (left < mCurrentCoord.left)
|
||
{
|
||
// символ вообще не виден
|
||
if (left + width <= mCurrentCoord.left)
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_left = mCurrentCoord.left;
|
||
result_width = width - (mCurrentCoord.left - left);
|
||
|
||
float texture_width = texture_rect.right - texture_rect.left;
|
||
texture_rect.left = texture_rect.right - (texture_width * (float)result_width / (float)width);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вправо
|
||
if (left + width > mCurrentCoord.right())
|
||
{
|
||
// символ вообще не виден
|
||
if (left >= mCurrentCoord.right())
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_width = mCurrentCoord.right() - left;
|
||
|
||
float texture_width = texture_rect.right - texture_rect.left;
|
||
texture_rect.right = texture_rect.left + (texture_width * (float)result_width / (float)width);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вверх
|
||
if (top < mCurrentCoord.top)
|
||
{
|
||
// символ вообще не виден
|
||
if (top + height <= mCurrentCoord.top)
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_top = mCurrentCoord.top;
|
||
result_height = height - (mCurrentCoord.top - top);
|
||
|
||
float texture_height = texture_rect.bottom - texture_rect.top;
|
||
texture_rect.top = texture_rect.bottom - (texture_height * (float)result_height / (float)height);
|
||
}
|
||
}
|
||
|
||
// символ залазиет вниз
|
||
if (top + height > mCurrentCoord.bottom())
|
||
{
|
||
// символ вообще не виден
|
||
if (top >= mCurrentCoord.bottom())
|
||
{
|
||
draw = false;
|
||
}
|
||
// символ обрезан
|
||
else
|
||
{
|
||
result_height = mCurrentCoord.bottom() - top;
|
||
|
||
float texture_height = texture_rect.bottom - texture_rect.top;
|
||
texture_rect.bottom = texture_rect.top + (texture_height * (float)result_height / (float)height);
|
||
}
|
||
}
|
||
|
||
if (draw)
|
||
{
|
||
int pix_left = mCroppedParent->getAbsoluteLeft() - info.leftOffset + result_left;
|
||
int pix_top = mCroppedParent->getAbsoluteTop() - info.topOffset + (mShiftText ? 1 : 0) + result_top;
|
||
|
||
float real_left = ((info.pixScaleX * (float)(pix_left) + info.hOffset) * 2) - 1;
|
||
float real_top = - (((info.pixScaleY * (float)(pix_top) + info.vOffset) * 2) - 1);
|
||
float real_right = ((info.pixScaleX * (float)(pix_left + result_width) + info.hOffset) * 2) - 1;
|
||
float real_bottom = - (((info.pixScaleY * (float)(pix_top + result_height) + info.vOffset) * 2) - 1);
|
||
|
||
DrawQuad(_vertex, real_left, real_top, real_right, real_bottom, vertex_z, colour_current | 0x00FFFFFF,
|
||
texture_rect.left, texture_rect.top, texture_rect.right, texture_rect.bottom, vertex_count);
|
||
}
|
||
}
|
||
|
||
// колличество реально отрисованных вершин
|
||
mRenderItem->setLastVertexCount(vertex_count);
|
||
}
|
||
|
||
void EditText::setInvertSelected(bool _value)
|
||
{
|
||
if (mInvertSelect == _value) return;
|
||
mInvertSelect = _value;
|
||
if (nullptr != mNode) mNode->outOfDate(mRenderItem);
|
||
}
|
||
|
||
} // namespace MyGUI
|