Jelajahi Sumber

Selection seems to be working even for empty lines

Marko Pintera 12 tahun lalu
induk
melakukan
ea6b8bdada
1 mengubah file dengan 134 tambahan dan 47 penghapusan
  1. 134 47
      BansheeEngine/Source/BsGUIInputBox.cpp

+ 134 - 47
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -436,11 +436,13 @@ namespace BansheeEngine
 			{
 			{
 				if(ev.isShiftDown())
 				if(ev.isShiftDown())
 				{
 				{
+					bool caretMovedDueToNewline = false;
 					if(!mSelectionShown)
 					if(!mSelectionShown)
 					{
 					{
 						if(isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)))
 						if(isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)))
 						{
 						{
 							mInputCaret->moveCaretLeft();
 							mInputCaret->moveCaretLeft();
+							caretMovedDueToNewline = true;
 						}
 						}
 
 
 						showSelection(getCaretSelectionCharIdx(SelectionDir::Left));
 						showSelection(getCaretSelectionCharIdx(SelectionDir::Left));
@@ -451,12 +453,32 @@ namespace BansheeEngine
 						mInputCaret->moveCaretLeft();
 						mInputCaret->moveCaretLeft();
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 
 
-						if (isNewlineChar(charIdx) && mInputCaret->getCaretPos() > 0)
+						if(!caretMovedDueToNewline) // Only move if we didn't already move due to newline, so we don't move twice
 						{
 						{
-							mInputCaret->moveCaretLeft();
-							charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
-						} 
+							if (isNewlineChar(charIdx) && mInputCaret->getCaretPos() > 0)
+							{
+								mInputCaret->moveCaretLeft();
+
+								charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
+								// Reverse caret movement if previous char was a newline, and this one is as well
+								// so we don't skip a line
+								if (isNewlineChar(charIdx)) 
+								{
+									mInputCaret->moveCaretRight();
+								}
+							} 
+						}
+						else
+						{
+							// Reverse caret movement if previous char was a newline, and this one is as well
+							// so we don't skip a line
+							if (isNewlineChar(charIdx)) 
+							{
+								mInputCaret->moveCaretRight();
+							}
+						}
 
 
+						charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						mSelectionStart = std::min(mSelectionEnd, charIdx);
 						mSelectionStart = std::min(mSelectionEnd, charIdx);
 					}
 					}
 					else
 					else
@@ -464,12 +486,33 @@ namespace BansheeEngine
 						mInputCaret->moveCaretLeft();
 						mInputCaret->moveCaretLeft();
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 
 
-						if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)) && mInputCaret->getCaretPos() > 0)
+						if(!caretMovedDueToNewline) // Only move if we didn't already move due to newline, so we don't move twice
 						{
 						{
-							mInputCaret->moveCaretLeft();
-							charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
-						} 
+							if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)) 
+								&& mInputCaret->getCaretPos() > 0)
+							{
+								mInputCaret->moveCaretLeft();
+
+								charIdx = getCaretSelectionCharIdx(SelectionDir::Right);
+								// Reverse caret movement if previous char was a newline, and this one is as well
+								// so we don't skip a line
+								if (isNewlineChar(charIdx)) 
+								{
+									mInputCaret->moveCaretRight();
+								}
+							} 
+						}
+						else
+						{
+							// Reverse caret movement if previous char was a newline, and this one is as well
+							// so we don't skip a line
+							if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right))) 
+							{
+								mInputCaret->moveCaretRight();
+							}
+						}
 
 
+						charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						mSelectionEnd = std::max(mSelectionStart, charIdx);
 						mSelectionEnd = std::max(mSelectionStart, charIdx);
 					}
 					}
 
 
@@ -496,11 +539,13 @@ namespace BansheeEngine
 			{
 			{
 				if(ev.isShiftDown())
 				if(ev.isShiftDown())
 				{
 				{
+					bool caretMovedDueToNewline = false;
 					if(!mSelectionShown)
 					if(!mSelectionShown)
 					{
 					{
 						if(isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Left)))
 						if(isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Left)))
 						{
 						{
 							mInputCaret->moveCaretRight();
 							mInputCaret->moveCaretRight();
+							caretMovedDueToNewline = true;
 						}
 						}
 
 
 						showSelection(getCaretSelectionCharIdx(SelectionDir::Left));
 						showSelection(getCaretSelectionCharIdx(SelectionDir::Left));
@@ -511,13 +556,33 @@ namespace BansheeEngine
 						mInputCaret->moveCaretRight();
 						mInputCaret->moveCaretRight();
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 
 
-						UINT32 maxCaretPos = mInputCaret->getMaxCaretPos();
-						if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)) && mInputCaret->getCaretPos() <= maxCaretPos)
+						if(!caretMovedDueToNewline) // Only move if we didn't already move due to newline, so we don't move twice
 						{
 						{
-							mInputCaret->moveCaretRight();
-							charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
-						} 
+							UINT32 maxCaretPos = mInputCaret->getMaxCaretPos();
+							if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right)) && mInputCaret->getCaretPos() <= maxCaretPos)
+							{
+								mInputCaret->moveCaretRight();
+
+								charIdx = getCaretSelectionCharIdx(SelectionDir::Right);
+								// Reverse caret movement if previous char was a newline, and this one is as well
+								// so we don't skip a line
+								if (isNewlineChar(charIdx)) 
+								{
+									mInputCaret->moveCaretLeft();
+								}
+							} 
+						}
+						else
+						{
+							// Reverse caret movement if previous char was a newline, and this one is as well
+							// so we don't skip a line
+							if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right))) 
+							{
+								mInputCaret->moveCaretLeft();
+							}
+						}
 
 
+						charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						mSelectionEnd = std::max(mSelectionStart, charIdx);
 						mSelectionEnd = std::max(mSelectionStart, charIdx);
 					}
 					}
 					else
 					else
@@ -525,14 +590,33 @@ namespace BansheeEngine
 						mInputCaret->moveCaretRight();
 						mInputCaret->moveCaretRight();
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						UINT32 charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 
 
-						UINT32 maxCaretPos = mInputCaret->getMaxCaretPos();
-						if (isNewlineChar(charIdx) && mInputCaret->getCaretPos() <= maxCaretPos)
+						if(!caretMovedDueToNewline) // Only move if we didn't already move due to newline, so we don't move twice
 						{
 						{
-							mInputCaret->moveCaretRight();
-							charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
-						} 
-
+							UINT32 maxCaretPos = mInputCaret->getMaxCaretPos();
+							if (isNewlineChar(charIdx) && mInputCaret->getCaretPos() <= maxCaretPos)
+							{
+								mInputCaret->moveCaretRight();
+
+								charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
+								// Reverse caret movement if previous char was a newline, and this one is as well
+								// so we don't skip a line
+								if (isNewlineChar(charIdx)) 
+								{
+									mInputCaret->moveCaretLeft();
+								}
+							} 
+						}
+						else
+						{
+							// Reverse caret movement if previous char was a newline, and this one is as well
+							// so we don't skip a line
+							if (isNewlineChar(getCaretSelectionCharIdx(SelectionDir::Right))) 
+							{
+								mInputCaret->moveCaretLeft();
+							}
+						}
 
 
+						charIdx = getCaretSelectionCharIdx(SelectionDir::Left);
 						mSelectionStart = std::min(mSelectionEnd, charIdx);
 						mSelectionStart = std::min(mSelectionEnd, charIdx);
 					}
 					}
 
 
@@ -768,8 +852,17 @@ namespace BansheeEngine
 
 
 		UINT32 endLine = startLine;
 		UINT32 endLine = startLine;
 		if(mSelectionEnd > 0)
 		if(mSelectionEnd > 0)
+		{
 			endLine = mTextSprite->getLineForChar(mSelectionEnd - 1);
 			endLine = mTextSprite->getLineForChar(mSelectionEnd - 1);
 
 
+			// Newline chars should count on the second line, but that not how the sprite reports them, so fix that
+			if(endLine < (mTextSprite->getNumLines() - 1))
+			{
+				if((mSelectionEnd - 1) == (mTextSprite->getLineDesc(endLine).endChar - 1)) 
+					endLine++;
+			}
+		}
+
 		{
 		{
 			const SpriteLineDesc& lineDesc = mTextSprite->getLineDesc(startLine);
 			const SpriteLineDesc& lineDesc = mTextSprite->getLineDesc(startLine);
 			
 			
@@ -784,24 +877,19 @@ namespace BansheeEngine
 					endCharIdx -= 1;
 					endCharIdx -= 1;
 			}
 			}
 
 
-#ifdef CM_DEBUG_MODE
-			if(isNewlineChar(startCharIdx))
-				CM_EXCEPT(InternalErrorException, "Selection marker placed on newline. That's not allowed");
-
-			if(isNewlineChar(endCharIdx))
-				CM_EXCEPT(InternalErrorException, "Selection marker placed on newline. That's not allowed");
-#endif
-
-			Rect startChar = mTextSprite->getCharRect(startCharIdx);
-			Rect endChar = mTextSprite->getCharRect(endCharIdx);
+			if(!isNewlineChar(startCharIdx) && !isNewlineChar(endCharIdx))
+			{
+				Rect startChar = mTextSprite->getCharRect(startCharIdx);
+				Rect endChar = mTextSprite->getCharRect(endCharIdx);
 
 
-			Rect selectionRect;
-			selectionRect.x = startChar.x;
-			selectionRect.y = lineDesc.lineYStart;
-			selectionRect.height = lineDesc.lineHeight;
-			selectionRect.width = (endChar.x + endChar.width) - startChar.x;
+				Rect selectionRect;
+				selectionRect.x = startChar.x;
+				selectionRect.y = lineDesc.lineYStart;
+				selectionRect.height = lineDesc.lineHeight;
+				selectionRect.width = (endChar.x + endChar.width) - startChar.x;
 
 
-			selectionRects.push_back(selectionRect);
+				selectionRects.push_back(selectionRect);
+			}
 		}
 		}
 
 
 		for(UINT32 i = startLine + 1; i < endLine; i++)
 		for(UINT32 i = startLine + 1; i < endLine; i++)
@@ -833,21 +921,20 @@ namespace BansheeEngine
 			if(lineDesc.startChar != lineDesc.endChar && !isNewlineChar(lineDesc.startChar))
 			if(lineDesc.startChar != lineDesc.endChar && !isNewlineChar(lineDesc.startChar))
 			{
 			{
 				UINT32 endCharIdx = mSelectionEnd - 1;
 				UINT32 endCharIdx = mSelectionEnd - 1;
-#ifdef CM_DEBUG_MODE
-				if(isNewlineChar(endCharIdx))
-					CM_EXCEPT(InternalErrorException, "Selection marker placed on newline. That's not allowed");
-#endif
 
 
-				Rect startChar = mTextSprite->getCharRect(lineDesc.startChar);
-				Rect endChar = mTextSprite->getCharRect(endCharIdx);
+				if(!isNewlineChar(endCharIdx))
+				{
+					Rect startChar = mTextSprite->getCharRect(lineDesc.startChar);
+					Rect endChar = mTextSprite->getCharRect(endCharIdx);
 
 
-				Rect selectionRect;
-				selectionRect.x = startChar.x;
-				selectionRect.y = lineDesc.lineYStart;
-				selectionRect.height = lineDesc.lineHeight;
-				selectionRect.width = (endChar.x + endChar.width) - startChar.x;
+					Rect selectionRect;
+					selectionRect.x = startChar.x;
+					selectionRect.y = lineDesc.lineYStart;
+					selectionRect.height = lineDesc.lineHeight;
+					selectionRect.width = (endChar.x + endChar.width) - startChar.x;
 
 
-				selectionRects.push_back(selectionRect);
+					selectionRects.push_back(selectionRect);
+				}
 			}
 			}
 		}
 		}