Ver código fonte

Text scrolling works

Marko Pintera 12 anos atrás
pai
commit
7a5029c741

+ 2 - 0
BansheeEngine/Include/BsGUIInputBox.h

@@ -58,6 +58,7 @@ namespace BansheeEngine
 		bool mInputCursorSet;
 		bool mDragInProgress;
 		bool mIsMultiline;
+		CM::Int2 mTextOffset;
 
 		IMAGE_SPRITE_DESC mImageDesc;
 		CM::WString mText;
@@ -79,6 +80,7 @@ namespace BansheeEngine
 
 		void showCaret();
 		void hideCaret();
+		void scrollTextToCaret();
 
 		void showSelection(CM::UINT32 startChar);
 		void clearSelection();

+ 3 - 4
BansheeEngine/Include/BsGUIInputCaret.h

@@ -19,7 +19,7 @@ namespace BansheeEngine
 
 		ImageSprite* getSprite() const { return mCaretSprite; }
 		void updateText(const TEXT_SPRITE_DESC& textDesc);
-		void updateSprite();
+		void updateSprite(const CM::Int2& offset);
 
 		void moveCaretToStart();
 		void moveCaretLeft();
@@ -30,6 +30,8 @@ namespace BansheeEngine
 		void moveCaretToChar(CM::UINT32 charIdx, CaretPos caretPos);
 
 		CM::UINT32 getCharIdxAtCaretPos() const;
+		CM::Int2 getCaretPosition(const CM::Int2& offset) const;
+		CM::UINT32 getCaretHeight() const;
 
 	private:
 		CM::UINT32 mCaretPos;
@@ -37,8 +39,5 @@ namespace BansheeEngine
 		ImageSprite* mCaretSprite;
 
 		TEXT_SPRITE_DESC mTextDesc;
-
-		CM::Int2 getCaretPosition(const CM::Int2& offset) const;
-		CM::UINT32 getCaretHeight() const;
 	};
 }

+ 55 - 3
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -131,7 +131,7 @@ namespace BansheeEngine
 		if(mCaretShown && GUIManager::instance().getCaretBlinkState())
 		{
 			mInputCaret->updateText(textDesc);
-			mInputCaret->updateSprite();
+			mInputCaret->updateSprite(mTextOffset);
 		}
 
 		if(mSelectionShown)
@@ -305,6 +305,8 @@ namespace BansheeEngine
 			else
 				mInputCaret->moveCaretToStart();
 
+			scrollTextToCaret();
+
 			clearSelection();
 			markAsDirty();
 
@@ -360,6 +362,7 @@ namespace BansheeEngine
 						mInputCaret->updateText(getTextDesc());
 
 						mInputCaret->moveCaretToChar(mSelectionStart, CARET_BEFORE);
+						scrollTextToCaret();
 
 						clearSelection();
 					}
@@ -373,6 +376,7 @@ namespace BansheeEngine
 							mInputCaret->updateText(getTextDesc());
 
 							mInputCaret->moveCaretLeft();
+							scrollTextToCaret();
 						}
 					}
 
@@ -391,6 +395,7 @@ namespace BansheeEngine
 						mText.erase(mText.begin() + mSelectionStart, mText.begin() + mSelectionEnd);
 						mInputCaret->updateText(getTextDesc());
 						mInputCaret->moveCaretToChar(mSelectionStart, CARET_BEFORE);
+						scrollTextToCaret();
 
 						clearSelection();
 					}
@@ -429,6 +434,7 @@ namespace BansheeEngine
 				{
 					clearSelection();
 					mInputCaret->moveCaretLeft();
+					scrollTextToCaret();
 
 					markAsDirty();
 					return true;
@@ -454,6 +460,7 @@ namespace BansheeEngine
 				{
 					clearSelection();
 					mInputCaret->moveCaretRight();
+					scrollTextToCaret();
 
 					markAsDirty();
 					return true;
@@ -473,6 +480,7 @@ namespace BansheeEngine
 				{
 					clearSelection();
 					mInputCaret->moveCaretUp();
+					scrollTextToCaret();
 
 					markAsDirty();
 					return true;
@@ -492,6 +500,7 @@ namespace BansheeEngine
 				{
 					clearSelection();
 					mInputCaret->moveCaretDown();
+					scrollTextToCaret();
 
 					markAsDirty();
 					return true;
@@ -508,6 +517,7 @@ namespace BansheeEngine
 						mInputCaret->updateText(getTextDesc());
 
 						mInputCaret->moveCaretToChar(mSelectionStart, CARET_BEFORE);
+						scrollTextToCaret();
 						clearSelection();
 					}
 
@@ -515,6 +525,7 @@ namespace BansheeEngine
 					mInputCaret->updateText(getTextDesc());
 
 					mInputCaret->moveCaretRight();
+					scrollTextToCaret();
 
 					markAsDirty();
 					return true;
@@ -548,6 +559,7 @@ namespace BansheeEngine
 			mInputCaret->updateText(getTextDesc());
 
 			mInputCaret->moveCaretRight();
+			scrollTextToCaret();
 
 			markAsDirty();
 			return true;
@@ -580,6 +592,46 @@ namespace BansheeEngine
 		markAsDirty();
 	}
 
+	void GUIInputBox::scrollTextToCaret()
+	{
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+
+		Int2 caretPos = mInputCaret->getCaretPosition(textDesc.offset);
+		UINT32 caretHeight = mInputCaret->getCaretHeight();
+		UINT32 caretWidth = 1;
+		INT32 caretRight = caretPos.x + (INT32)caretWidth;
+		INT32 caretBottom = caretPos.y + (INT32)caretHeight;
+
+		INT32 left = textDesc.offset.x - mTextOffset.x;
+		INT32 right = left + (INT32)textDesc.width;
+		INT32 top = textDesc.offset.y - mTextOffset.y;
+		INT32 bottom = top + (INT32)textDesc.height;
+
+		Int2 offset;
+		if(caretPos.x < left)
+		{
+			offset.x = left - caretPos.x;
+		}
+		else if(caretRight > right)
+		{
+			offset.x = -(caretRight - right);
+		}
+
+		if(caretPos.y < top)
+		{
+			offset.y = top - caretPos.y;
+		}
+		else if(caretBottom > bottom)
+		{
+			offset.y = -(caretBottom - bottom);
+		}
+
+		mTextOffset += offset;
+		mInputCaret->updateText(getTextDesc());
+
+		markAsDirty();
+	}
+
 	void GUIInputBox::showSelection(UINT32 startChar)
 	{
 		mSelectionStart = startChar;
@@ -689,10 +741,10 @@ namespace BansheeEngine
 		textDesc.fontSize = mStyle->fontSize;
 
 		Rect textBounds = getTextBounds();
-		textDesc.offset = Int2(textBounds.x, textBounds.y);
+		textDesc.offset = Int2(textBounds.x, textBounds.y) + mTextOffset;
 		textDesc.width = textBounds.width;
 		textDesc.height = textBounds.height;
-		textDesc.clipRect = Rect(0, 0, textDesc.width, textDesc.height);
+		textDesc.clipRect = Rect(-mTextOffset.x, -mTextOffset.y, textDesc.width, textDesc.height);
 		textDesc.horzAlign = mStyle->textHorzAlign;
 		textDesc.vertAlign = mStyle->textVertAlign;
 

+ 4 - 2
BansheeEngine/Source/BsGUIInputCaret.cpp

@@ -25,17 +25,19 @@ namespace BansheeEngine
 	void GUIInputCaret::updateText(const TEXT_SPRITE_DESC& textDesc)
 	{
 		mTextDesc = textDesc;
+		mTextDesc.clipRect = Rect(0, 0, 0, 0); // No clipping otherwise we don't know position of chars
+		// outside of the element, which is something we need when moving the cursor
 
 		mTextSprite->update(mTextDesc);
 	}
 
-	void GUIInputCaret::updateSprite()
+	void GUIInputCaret::updateSprite(const CM::Int2& offset)
 	{
 		IMAGE_SPRITE_DESC mCaretDesc;
 		mCaretDesc.offset = getCaretPosition(mTextDesc.offset);
 		mCaretDesc.width = 1;
 		mCaretDesc.height = getCaretHeight();
-		mCaretDesc.clipRect = Rect(-mCaretDesc.offset.x + mTextDesc.offset.x, -mCaretDesc.offset.y + mTextDesc.offset.y, 
+		mCaretDesc.clipRect = Rect(-mCaretDesc.offset.x + mTextDesc.offset.x - offset.x, -mCaretDesc.offset.y + mTextDesc.offset.y - offset.y, 
 			mTextDesc.width, mTextDesc.height);
 		mCaretDesc.texture = GUIManager::instance().getCaretTexture();
 

+ 0 - 5
CamelotCore/Source/CmTextUtility.cpp

@@ -394,11 +394,6 @@ namespace CamelotFramework
 					if(!lastWord.isSpacer())
 						curLine->addWord(lastWord);
 				}
-				else
-				{
-					// Nothing else we can do, chars don't fit so we are done
-					break;
-				}
 			}
 
 			charIdx++;

+ 1 - 10
TODO.txt

@@ -8,7 +8,7 @@ I still re-create GUIWidget mesh every frame instead of just updating it.
 
 MAJOR ISSUE: writeSubresource/readSubresoure doesn't require a shared ptr to GpuResourceData which means it could get destroyed while still in command queue. Right now it only works because I block right after I call those methods, which ensures nothing is destroyed.
   - When fixed, make sure I remove blocking calls after writeSubresource where they're not needed (GUIManager for example)
-I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will wait a single frame.
+I call waitUntilLoaded too many times. Sometimes 5-6 times in a single function. Each of those calls will be extremely slow.
 GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
 
 IMMEDIATE:
@@ -23,11 +23,6 @@ IMMEDIATE:
 	- SpriteTexture keeps a static reference to DUmmyTexture which I need to release before shutdown
 
 TextBox needed elements:
- - Inputting clipped text breaks my input caret algorithm because entire text lines and text quads get culled
-  - Yet another reason I should split TextSprite functionality I need for caret into a separate class
-  - I can always include proper amount of lines + valid start/end chars
-  - And for quads I can use some internal offsets
- - Up/Down arrow keys should move cursor up/down
  - Drag mouse to update selection
  - Text scroll. Typing outside of textbox should scroll the text so caret is visible.
  - Get DebugCamera to ignore input if GUI has already processed it
@@ -51,10 +46,6 @@ I need to be able to provide smaller bounds used for UI input
  - Add padding - reduces the size of the element and that is used for input
  - Add margins - spacing that is added when laying out multiple controls after each other
 
-Figure out how to deal with callbacks properly. I recently eliminated them from Input but I'll need them for my GUI elements...
- - How do I implement them? I really don't want to do Unitys approach to GUI
- - If I do figure out a good way to keep callbacks, maybe rethink Input and re-add them?
-
  - My test model is rendering back faces. I need to flip them.
   - Although more than likely I am loading the model incorrectly since it works in Unity?
   - I probably want to determine front faces based on normals