⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guimltextctrl.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "gui/controls/guiMLTextCtrl.h"
#include "gui/containers/guiScrollCtrl.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "gui/core/guiCanvas.h"
#include "core/frameAllocator.h"
#include "core/unicode.h"
#ifdef TGE_RPG
#include "rpg/ui/gameIconMan.h"
#endif

IMPLEMENT_CONOBJECT(GuiMLTextCtrl);

const U32 GuiMLTextCtrl::csmTextBufferGrowthSize = 1024;

ConsoleMethod( GuiMLTextCtrl, setText, void, 3, 3,  "(string text)"
              "Set the text contained in the control.")
{
   object->setText(argv[2], dStrlen(argv[2]));
}

ConsoleMethod( GuiMLTextCtrl, getText, const char*, 2, 2, "Returns the text from the control, including ML.")
{
   return( object->getTextContent() );
}

ConsoleMethod( GuiMLTextCtrl, addText, void, 4, 4, "(string text, bool reformat)")
{
   object->addText(argv[2], dStrlen(argv[2]), dAtob(argv[3]));
}

ConsoleMethod( GuiMLTextCtrl, setCursorPosition, bool, 3, 3, "(int newPos)"
              "Offset in characters to set cursor's position to.")
{
   return object->setCursorPosition(dAtoi(argv[2]));
}

ConsoleMethod( GuiMLTextCtrl, scrollToTag, void, 3, 3, "(int tagID)"
              "Scroll down to a specified tag.")
{
   object->scrollToTag( dAtoi( argv[2] ) );
}

ConsoleMethod( GuiMLTextCtrl, scrollToTop, void, 2, 2, "Scroll to the top of the text.")
{
   object->scrollToTop();
}

ConsoleMethod( GuiMLTextCtrl, scrollToBottom, void, 2, 2, "Scroll to the top of the text.")
{
   object->scrollToBottom();
}

ConsoleFunction( StripMLControlChars, const char*, 2, 2, "(string val)"
                "Strip TorqueML control characters from the specified string, returning a 'clean' version.")
{
   return GuiMLTextCtrl::stripControlChars(argv[1]);
}

ConsoleMethod(GuiMLTextCtrl,forceReflow,void,2,2,"forces the text control to reflow the text after new text is added, possibly resizing the control.")
{
   if(!object->isAwake())
      Con::errorf("GuiMLTextCtrl::forceReflow can only be called on visible controls.");
   else
      object->reflow();
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::GuiMLTextCtrl()
{
   mIsEditCtrl = false;

   mCursorPosition     = 0;

   mMaxBufferSize = -1;
   mInitialText = StringTable->insert("");

   mSelectionActive = false;
   mSelectionStart  = 0;
   mSelectionEnd    = 0;

   mLineSpacingPixels = 2;
   mAllowColorChars = false;
   mBitmapList = 0;
   mBitmapRefList = 0;
   mFontList = 0;
   mDirty = true;
   mLineList = 0;
   mTagList = 0;
   mHitURL = 0;
   mActive = true;
   mAlpha = 1.0;

#ifdef TGE_RPG
	m_nLineHeightMin		= 0;
	m_nFontDefaultHeight	= 12;
	m_bCheckCursor		= true;

	dMemset(m_arCursors,0,sizeof(m_arCursors));
	m_cursorType	= CT_NORMAL;
	m_pCmdScriptFunc	= StringTable->getBlank();

#endif


   Sim::findObject("InputDeniedSound", mDeniedSound);
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::~GuiMLTextCtrl()
{
   mCursorPosition     = 0;

   mSelectionActive = false;
   mSelectionStart  = 0;
   mSelectionEnd    = 0;
   freeResources();
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::initPersistFields()
{
   Parent::initPersistFields();
   addField("lineSpacing",       TypeS32,    Offset(mLineSpacingPixels, GuiMLTextCtrl));
   addField("allowColorChars",   TypeBool,   Offset(mAllowColorChars,   GuiMLTextCtrl));
   addField("maxChars",          TypeS32,    Offset(mMaxBufferSize,     GuiMLTextCtrl));
   addField("deniedSound",       TypeAudioProfilePtr, Offset(mDeniedSound, GuiMLTextCtrl));
   addField("text",              TypeCaseString,  Offset( mInitialText, GuiMLTextCtrl ) );
#ifdef TGE_RPG
   addField("fontDefaultHeight", TypeS32,    Offset(m_nFontDefaultHeight, GuiMLTextCtrl));
   addField("lineHeightMin",     TypeS32,    Offset(m_nLineHeightMin, GuiMLTextCtrl));
   addField("cmdFunc",           TypeString, Offset( m_pCmdScriptFunc, GuiMLTextCtrl ) );
#endif
}

ConsoleMethod(GuiMLTextCtrl, setAlpha, void, 3, 3, "")
{
   object->setAlpha(dAtof(argv[2]));
}

//--------------------------------------------------------------------------

bool GuiMLTextCtrl::onAdd()
{
   if(!Parent::onAdd())
      return false;

   if (!mTextBuffer.length() && mInitialText[0] != 0)
      setText(mInitialText, dStrlen(mInitialText)+1);
   return true;
}


//--------------------------------------------------------------------------
bool GuiMLTextCtrl::onWake()
{
   if (Parent::onWake() == false)
      return false;

   mDirty = true;

#ifdef TGE_RPG
	if(!m_arCursors[CT_URL])
		Sim::findObject(CURSOR_HAND_TXT,m_arCursors[CT_URL]);
#endif

   return true;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::onPreRender()
{
   if(mDirty)
      reflow();
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::drawAtomText(bool sel, U32 start, U32 end, Atom *atom, Line *line, Point2I offset)
{
   GFont *font = atom->style->font->fontRes;
   U32 xOff = 0;
   if(start != atom->textStart)
   {
      // Get the string in UTF8 for length calcs (this is kinda silly - BJG)
      FrameTemp<UTF8> tmp( (start - atom->textStart) * 3 + 1 );
      StringBuffer tmpBuff = mTextBuffer.substring(atom->textStart, start - atom->textStart);
      tmpBuff.get(tmp, (start - atom->textStart) * 3 + 1 );
      xOff += font->getStrNWidth(tmp, start - atom->textStart );
   }

   Point2I drawPoint(offset.x + atom->xStart + xOff, offset.y + atom->yStart);

   ColorI color;
   if(atom->url)
   { 
      if(atom->url->mouseDown)
         color = atom->style->linkColorHL;
      else
         color = atom->style->linkColor;
   }
   else
      color = atom->style->color;
       
	/// Chinese
   //FrameTemp<UTF8> tmp( (end - start) * 3 + 1 );
   //StringBuffer tmpBuff = mTextBuffer.substring(start, end-start);
   //tmpBuff.get(tmp, (end - start) * 3 + 1 );
	UTF16* tmp = mTextBuffer.getBuffer(start);

   if(!sel)
   {
      if(atom->style->shadowOffset.x || atom->style->shadowOffset.y)
      {
         ColorI shadowColor = atom->style->shadowColor;
         shadowColor.alpha = shadowColor.alpha * mAlpha;
         dglSetBitmapModulation(shadowColor);


#ifdef TGE_RPG
			if(atom->style->shadowOffset.x)
			{
				Point2I ptDraw(drawPoint.x + atom->style->shadowOffset.x, drawPoint.y);
				dglDrawTextN(font, ptDraw, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);

				ptDraw.x = drawPoint.x - atom->style->shadowOffset.x;
				dglDrawTextN(font, ptDraw, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);
			}

			if(atom->style->shadowOffset.y)
			{
				Point2I ptDraw(drawPoint.x , drawPoint.y+ atom->style->shadowOffset.y);
				dglDrawTextN(font, ptDraw, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);

				ptDraw.y = drawPoint.y - atom->style->shadowOffset.y;
				dglDrawTextN(font, ptDraw, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);
			}

         //dglDrawTextN(font, drawPoint + atom->style->shadowOffset, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);
#else
         dglDrawTextN(font, drawPoint + atom->style->shadowOffset, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);
#endif
      }

      color.alpha = color.alpha * mAlpha;
      dglSetBitmapModulation(color);
      dglDrawTextN(font, drawPoint, tmp, end-start, mAllowColorChars ? mProfile->mFontColors : NULL);

      //if the atom was "clipped", see if we need to draw a "..." at the end
      if (atom->isClipped)
      {
         Point2I p2 = drawPoint;
         p2.x += font->getStrNWidthPrecise(tmp, end-start);
         dglDrawTextN(font, p2, "...", 3, mAllowColorChars ? mProfile->mFontColors : NULL);
      }
   }
   else
   {
      RectI rect;
      rect.point.x = drawPoint.x;
      rect.point.y = line->y + offset.y;
      rect.extent.x = font->getStrNWidth(tmp, end - atom->textStart) + 1;
      rect.extent.y = line->height + 1;
      
      dglDrawRectFill(rect, mProfile->mFillColorHL);
      dglSetBitmapModulation( mProfile->mFontColorHL );  // over-ride atom color:
      dglDrawTextN(font, drawPoint, tmp, end - atom->textStart, mAllowColorChars ? mProfile->mFontColors : NULL);

      //if the atom was "clipped", see if we need to draw a "..." at the end
      if (atom->isClipped)
      {
         Point2I p2 = drawPoint;
         p2.x += font->getStrNWidthPrecise(tmp, end - atom->textStart);
         dglDrawTextN(font, p2, "...", 3, mAllowColorChars ? mProfile->mFontColors : NULL);
      }
   }

   if(atom->url && !atom->url->noUnderline)
   {
      drawPoint.y += atom->baseLine + 2;
      Point2I p2 = drawPoint;
      p2.x += font->getStrNWidthPrecise(tmp, end - atom->textStart);
      dglDrawLine(drawPoint, p2, color);
   }
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::onRender(Point2I offset, const RectI& updateRect)
{
   Parent::onRender(offset, updateRect);
   // draw all the bitmaps
   for(BitmapRef *walk = mBitmapRefList; walk; walk = walk->next)
   {
      RectI screenBounds = *walk;
      screenBounds.point += offset;
      if(!screenBounds.overlaps(updateRect))
         continue;
      dglClearBitmapModulation();
#ifdef TGE_RPG
		dglDrawBitmapSR(walk->bitmap->bitmapHandle,screenBounds.point ,walk->bitmap->bmpRect);
#else
      dglDrawBitmap(walk->bitmap->bitmapHandle, screenBounds.point);
#endif
      //dglDrawRectFill(screenBounds, mProfile->mWallFillColor);
   }

   // draw all the text and dividerStyles
   for(Line *lwalk = mLineList; lwalk; lwalk = lwalk->next)
   {
      RectI lineRect(offset.x, offset.y + lwalk->y, mBounds.extent.x, lwalk->height);

      if(!lineRect.overlaps(updateRect))
         continue;

      if(lwalk->divStyle)
         dglDrawRectFill(lineRect, mProfile->mFillColorHL);

      for(Atom *awalk = lwalk->atomList; awalk; awalk = awalk->next)
      {
         if(!mSelectionActive || mSelectionEnd < awalk->textStart || mSelectionStart >= awalk->textStart + awalk->len)
            drawAtomText(false, awalk->textStart, awalk->textStart + awalk->len, awalk, lwalk, offset);
         else
         {
            U32 selectionStart = getMax(awalk->textStart, mSelectionStart);
            U32 selectionEnd = getMin(awalk->textStart + awalk->len, mSelectionEnd + 1);

            // draw some unselected text
            if(selectionStart > awalk->textStart)
               drawAtomText(false, awalk->textStart, selectionStart, awalk, lwalk, offset);

            // draw the selection
            drawAtomText(true, selectionStart, selectionEnd, awalk, lwalk, offset);

            if(selectionEnd < awalk->textStart + awalk->len)
               drawAtomText(false, selectionEnd, awalk->textStart + awalk->len, awalk, lwalk, offset);
         }
      }
   }
   dglClearBitmapModulation();
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::freeLineBuffers()
{
   mViewChunker.freeBlocks();
   mLineList = NULL;
   mBitmapRefList = NULL;
   mTagList = NULL;
   mHitURL = 0;
   mDirty = true;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::freeResources()
{
   for(Font* walk = mFontList; walk; walk = walk->next)
   {
      delete[] walk->faceName;
      walk->fontRes = 0;
   }

   for(Bitmap* bwalk = mBitmapList; bwalk; bwalk = bwalk->next)
      bwalk->bitmapHandle = 0;

   mFontList = NULL;
   mBitmapList = NULL;
   mResourceChunker.freeBlocks();
   mDirty = true;

   freeLineBuffers();
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::onSleep()
{
   freeResources();
   Parent::onSleep();
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::inspectPostApply()
{
   Parent::inspectPostApply();

   if (mInitialText[0] != 0)
      setText(mInitialText, dStrlen(mInitialText));

   if (mLineSpacingPixels < 0)
      mLineSpacingPixels = 0;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::resize( const Point2I& newPosition, const Point2I& newExtent )
{
   Parent::resize( newPosition, newExtent );
   //Con::executef( this, 3, "onResize", Con::getIntArg( newExtent.x ), Con::getIntArg( newExtent.y ) );
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::parentResized(const Point2I& oldParentExtent,
                                  const Point2I& newParentExtent)
{
   Parent::parentResized(oldParentExtent, newParentExtent);
   mDirty = true;
}

//--------------------------------------------------------------------------
U32 GuiMLTextCtrl::getNumChars() const
{
   return mTextBuffer.length();
}

//--------------------------------------------------------------------------
U32 GuiMLTextCtrl::getText(char* pBuffer, const U32 bufferSize) const
{
   mTextBuffer.get(pBuffer, bufferSize);

   return getMin(mTextBuffer.length(), bufferSize);
}

//--------------------------------------------------------------------------
const char* GuiMLTextCtrl::getTextContent()
{
   if ( mTextBuffer.length() > 0 )
   {
      char* returnString = Con::getReturnBuffer( mTextBuffer.length() + 1 );
      mTextBuffer.get(returnString, mTextBuffer.length() );
      return returnString;
   }

   return( "" );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -