浏览代码

added ETextInput (replaces EKeyDown/Up for text edition)

ncannasse 8 年之前
父节点
当前提交
197d6cb29b
共有 9 个文件被更改,包括 152 次插入128 次删除
  1. 1 1
      h2d/Console.hx
  2. 5 0
      h2d/Interactive.hx
  3. 103 89
      h2d/TextInput.hx
  4. 5 0
      h3d/scene/Interactive.hx
  5. 3 1
      hxd/Event.hx
  6. 2 2
      hxd/SceneEvents.hx
  7. 7 2
      hxd/Stage.flash.hx
  8. 20 32
      hxd/Stage.hl.hx
  9. 6 1
      hxd/Stage.js.hx

+ 1 - 1
h2d/Console.hx

@@ -87,7 +87,7 @@ class Console extends h2d.Sprite {
 				if( logDY > logTxt.textHeight ) logDY = logTxt.textHeight;
 				e.propagate = false;
 			}
-		case EKeyDown:
+		case ETextInput:
 			if( e.charCode == shortKeyChar && !bg.visible )
 				show();
 		default:

+ 5 - 0
h2d/Interactive.hx

@@ -162,6 +162,8 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 			onKeyDown(e);
 		case ECheck:
 			onCheck(e);
+		case ETextInput:
+			onTextInput(e);
 		}
 	}
 
@@ -263,4 +265,7 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 	public dynamic function onCheck( e : hxd.Event ) {
 	}
 
+	public dynamic function onTextInput( e : hxd.Event ) {
+	}
+
 }

+ 103 - 89
h2d/TextInput.hx

@@ -70,96 +70,12 @@ class TextInput extends Text {
 			}
 		};
 		interactive.onKeyDown = function(e:hxd.Event) {
-
 			onKeyDown(e);
-
-			if( e.cancel || cursorIndex < 0 )
-				return;
-
-			var oldIndex = cursorIndex;
-			var oldText = text;
-
-			switch( e.keyCode ) {
-			case K.LEFT:
-				if( cursorIndex > 0 )
-					cursorIndex--;
-			case K.RIGHT:
-				if( cursorIndex < text.length )
-					cursorIndex++;
-			case K.HOME:
-				cursorIndex = 0;
-			case K.END:
-				cursorIndex = text.length;
-			case K.BACKSPACE, K.DELETE if( selectionRange != null ):
-				if( !canEdit ) return;
-				beforeChange();
-				cutSelection();
-				onChange();
-			case K.DELETE:
-				if( cursorIndex < text.length && canEdit ) {
-					beforeChange();
-					text = text.substr(0, cursorIndex) + text.substr(cursorIndex + 1);
-					onChange();
-				}
-			case K.BACKSPACE:
-				if( cursorIndex > 0 && canEdit ) {
-					beforeChange();
-					cursorIndex--;
-					text = text.substr(0, cursorIndex) + text.substr(cursorIndex + 1);
-					onChange();
-				}
-			case K.ENTER, K.NUMPAD_ENTER:
-				cursorIndex = -1;
-				interactive.blur();
-				return;
-			case K.Z if( K.isDown(K.CTRL) ):
-				if( undo.length > 0 && canEdit ) {
-					redo.push(curHistoryState());
-					setState(undo.pop());
-				}
-				return;
-			case K.Y if( K.isDown(K.CTRL) ):
-				if( redo.length > 0 && canEdit ) {
-					undo.push(curHistoryState());
-					setState(redo.pop());
-				}
-				return;
-			default:
-				if( e.charCode != 0 && canEdit ) {
-					beforeChange();
-					if( selectionRange != null )
-						cutSelection();
-					text = text.substr(0, cursorIndex) + String.fromCharCode(e.charCode) + text.substr(cursorIndex);
-					cursorIndex++;
-					onChange();
-				}
-			}
-
-			cursorBlink = 0.;
-
-			if( K.isDown(K.SHIFT) && text == oldText ) {
-
-				if( cursorIndex == oldIndex ) return;
-
-				if( selectionRange == null )
-					selectionRange = oldIndex < cursorIndex ? { start : oldIndex, length : cursorIndex - oldIndex } : { start : cursorIndex, length : oldIndex - cursorIndex };
-				else if( oldIndex == selectionRange.start ) {
-					selectionRange.length += oldIndex - cursorIndex;
-					selectionRange.start = cursorIndex;
-				} else
-					selectionRange.length += cursorIndex - oldIndex;
-
-				if( selectionRange.length == 0 )
-					selectionRange = null;
-				else if( selectionRange.length < 0 ) {
-					selectionRange.start += selectionRange.length;
-					selectionRange.length = -selectionRange.length;
-				}
-				selectionSize = 0;
-
-			} else
-				selectionRange = null;
-
+			handleKey(e);
+		};
+		interactive.onTextInput = function(e:hxd.Event) {
+			onTextInput(e);
+			handleKey(e);
 		};
 		interactive.onFocusLost = function(e) {
 			cursorIndex = -1;
@@ -193,6 +109,101 @@ class TextInput extends Text {
 		addChildAt(interactive, 0);
 	}
 
+	function handleKey( e : hxd.Event ) {
+		if( e.cancel || cursorIndex < 0 )
+			return;
+
+		var oldIndex = cursorIndex;
+		var oldText = text;
+
+		switch( e.keyCode ) {
+		case K.LEFT:
+			if( cursorIndex > 0 )
+				cursorIndex--;
+		case K.RIGHT:
+			if( cursorIndex < text.length )
+				cursorIndex++;
+		case K.HOME:
+			cursorIndex = 0;
+		case K.END:
+			cursorIndex = text.length;
+		case K.BACKSPACE, K.DELETE if( selectionRange != null ):
+			if( !canEdit ) return;
+			beforeChange();
+			cutSelection();
+			onChange();
+		case K.DELETE:
+			if( cursorIndex < text.length && canEdit ) {
+				beforeChange();
+				text = text.substr(0, cursorIndex) + text.substr(cursorIndex + 1);
+				onChange();
+			}
+		case K.BACKSPACE:
+			if( cursorIndex > 0 && canEdit ) {
+				beforeChange();
+				cursorIndex--;
+				text = text.substr(0, cursorIndex) + text.substr(cursorIndex + 1);
+				onChange();
+			}
+		case K.ENTER, K.NUMPAD_ENTER:
+			cursorIndex = -1;
+			interactive.blur();
+			return;
+		case K.Z if( K.isDown(K.CTRL) ):
+			if( undo.length > 0 && canEdit ) {
+				redo.push(curHistoryState());
+				setState(undo.pop());
+			}
+			return;
+		case K.Y if( K.isDown(K.CTRL) ):
+			if( redo.length > 0 && canEdit ) {
+				undo.push(curHistoryState());
+				setState(redo.pop());
+			}
+			return;
+		default:
+			if( e.kind == EKeyDown )
+				return;
+			if( e.charCode != 0 && canEdit ) {
+
+				if( !font.hasChar(e.charCode) ) return; // don't allow chars not supported by font
+
+				beforeChange();
+				if( selectionRange != null )
+					cutSelection();
+				text = text.substr(0, cursorIndex) + String.fromCharCode(e.charCode) + text.substr(cursorIndex);
+				cursorIndex++;
+				onChange();
+			}
+		}
+
+		cursorBlink = 0.;
+
+		if( K.isDown(K.SHIFT) && text == oldText ) {
+
+			if( cursorIndex == oldIndex ) return;
+
+			if( selectionRange == null )
+				selectionRange = oldIndex < cursorIndex ? { start : oldIndex, length : cursorIndex - oldIndex } : { start : cursorIndex, length : oldIndex - cursorIndex };
+			else if( oldIndex == selectionRange.start ) {
+				selectionRange.length += oldIndex - cursorIndex;
+				selectionRange.start = cursorIndex;
+			} else
+				selectionRange.length += cursorIndex - oldIndex;
+
+			if( selectionRange.length == 0 )
+				selectionRange = null;
+			else if( selectionRange.length < 0 ) {
+				selectionRange.start += selectionRange.length;
+				selectionRange.length = -selectionRange.length;
+			}
+			selectionSize = 0;
+
+		} else
+			selectionRange = null;
+
+	}
+
 	function cutSelection() {
 		if(selectionRange == null) return false;
 		cursorIndex = selectionRange.start;
@@ -348,6 +359,9 @@ class TextInput extends Text {
 	public dynamic function onKeyUp(e:hxd.Event) {
 	}
 
+	public dynamic function onTextInput(e:hxd.Event) {
+	}
+
 	public dynamic function onFocus(e:hxd.Event) {
 	}
 

+ 5 - 0
h3d/scene/Interactive.hx

@@ -96,6 +96,8 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 			onKeyDown(e);
 		case ECheck:
 			onCheck(e);
+		case ETextInput:
+			onTextInput(e);
 		}
 	}
 
@@ -160,4 +162,7 @@ class Interactive extends Object implements hxd.SceneEvents.Interactive {
 	public dynamic function onCheck( e : hxd.Event ) {
 	}
 
+	public dynamic function onTextInput( e : hxd.Event ) {
+	}
+
 }

+ 3 - 1
hxd/Event.hx

@@ -12,6 +12,7 @@ enum EventKind {
 	EKeyDown;
 	EKeyUp;
 	EReleaseOutside;
+	ETextInput;
 	/**
 		Used to check if we are still on the interactive if no EMove was triggered this frame.
 	**/
@@ -49,7 +50,8 @@ class Event {
 		case EPush, ERelease, EReleaseOutside: ",button=" + button;
 		case EMove, EOver, EOut, EFocus, EFocusLost, ECheck: "";
 		case EWheel: ",wheelDelta=" + wheelDelta;
-		case EKeyDown, EKeyUp: ",keyCode=" + keyCode+",charCode=" + charCode;
+		case EKeyDown, EKeyUp: ",keyCode=" + keyCode;
+		case ETextInput: ",charCode=" + charCode;
 		}
 	}
 

+ 2 - 2
hxd/SceneEvents.hx

@@ -106,7 +106,7 @@ class SceneEvents {
 		case EMove, ECheck: checkOver = true;
 		case EPush: cancelFocus = true; checkPush = true;
 		case ERelease: checkPush = true;
-		case EKeyUp, EKeyDown, EWheel:
+		case EKeyUp, EKeyDown, ETextInput, EWheel:
 			if( currentFocus != null ) {
 				event.relX = event.relY = 0;
 				currentFocus.handleEvent(event);
@@ -237,7 +237,7 @@ class SceneEvents {
 					mouseX = e.relX;
 					mouseY = e.relY;
 					lastTouch = e.touchId;
-				case EKeyUp, EKeyDown, EWheel:
+				case EKeyUp, EKeyDown, ETextInput, EWheel:
 					if( !checkFocused ) {
 						checkFocused = true;
 						checkFocus();

+ 7 - 2
hxd/Stage.flash.hx

@@ -207,16 +207,21 @@ class Stage {
 	function onKeyUp(e:flash.events.KeyboardEvent) {
 		var ev = new Event(EKeyUp, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
-		ev.charCode = getCharCode(e);
 		event(ev);
 	}
 
 	function onKeyDown(e:flash.events.KeyboardEvent) {
 		var ev = new Event(EKeyDown, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
-		ev.charCode = getCharCode(e);
 		event(ev);
 
+		var charCode = getCharCode(e);
+		if( charCode != 0 ) {
+			var ev = new Event(ETextInput, mouseX, mouseY);
+			ev.charCode = charCode;
+			event(ev);
+		}
+
 		// prevent escaping fullscreen in air
 		if( e.keyCode == flash.ui.Keyboard.ESCAPE ) e.preventDefault();
 		if( e.keyCode == "S".code && e.ctrlKey ) e.preventDefault();

+ 20 - 32
hxd/Stage.hl.hx

@@ -25,7 +25,6 @@ class Stage {
 	var shiftDown : Bool;
 
 	static var CODEMAP = [for( i in 0...2048 ) i];
-	static var CHARMAP = [for( i in 0...2048 ) 0];
 
 	function new(title:String, width:Int, height:Int) {
 		this.windowWidth = width;
@@ -169,11 +168,6 @@ class Stage {
 			eh = new Event(EKeyDown);
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			eh.keyCode = CODEMAP[e.keyCode];
-			eh.charCode = CHARMAP[e.keyCode];
-			if( eh.charCode == ":".code && shiftDown )
-				eh.charCode = "/".code;
-			if( eh.charCode >= 'a'.code && eh.charCode <= 'z'.code && shiftDown )
-				eh.charCode += 'A'.code - 'a'.code;
 			if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
 				e.keyCode = eh.keyCode & 0xFF;
 				if( e.keyCode == K.SHIFT ) shiftDown = true;
@@ -183,11 +177,6 @@ class Stage {
 			eh = new Event(EKeyUp);
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			eh.keyCode = CODEMAP[e.keyCode];
-			eh.charCode = CHARMAP[e.keyCode];
-			if( eh.charCode == ":".code && shiftDown )
-				eh.charCode = "/".code;
-			if( eh.charCode >= 'a'.code && eh.charCode <= 'z'.code && shiftDown )
-				eh.charCode += 'A'.code - 'a'.code;
 			if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
 				e.keyCode = eh.keyCode & 0xFF;
 				if( e.keyCode == K.SHIFT ) shiftDown = false;
@@ -198,6 +187,17 @@ class Stage {
 			eh.wheelDelta = -e.wheelDelta;
 		case GControllerAdded, GControllerRemoved, GControllerUp, GControllerDown, GControllerAxis:
 			@:privateAccess hxd.Pad.onEvent( e );
+		case TextInput:
+			eh = new Event(ETextInput, mouseX, mouseY);
+			var c = e.keyCode & 0xFF;
+			eh.charCode = if( c < 0x7F )
+				c;
+			else if( c < 0xE0 )
+				((c & 0x3F) << 6) | ((e.keyCode >> 8) & 0x7F);
+			else if( c < 0xF0 )
+				((c & 0x1F) << 12) | (((e.keyCode >> 8) & 0x7F) << 6) | ((e.keyCode >> 16) & 0x7F);
+			else
+				((c & 0x0F) << 18) | (((e.keyCode >> 8) & 0x7F) << 12) | (((e.keyCode >> 16) & 0x7F) << 6) | ((e.keyCode >> 24) & 0x7F);
 		default:
 		}
 		if( eh != null ) event(eh);
@@ -205,38 +205,26 @@ class Stage {
 
 	static function initChars() : Void {
 
-		inline function addKey(sdl, keyCode, charCode=0) {
+		inline function addKey(sdl, keyCode) {
 			CODEMAP[sdl] = keyCode;
-			if( charCode != 0 ) CHARMAP[sdl] = charCode;
 		}
 
-		/*
-			SDL 2.0 does not allow to get the charCode from a key event.
-			let's for now do a simple mapping, even if not very efficient
-		*/
-
 		// ASCII
-		CHARMAP[K.BACKSPACE] = 8;
-		CHARMAP[K.TAB] = 9;
-		CHARMAP[K.ENTER] = 13;
-		for( i in 32...127 )
-			CHARMAP[i] = i;
 		for( i in 0...26 )
 			addKey(97 + i, K.A + i);
 		for( i in 0...12 )
 			addKey(1058 + i, K.F1 + i);
 
 		// NUMPAD
-
-		addKey(1084, K.NUMPAD_DIV, "/".code);
-		addKey(1085, K.NUMPAD_MULT, "*".code);
-		addKey(1086, K.NUMPAD_SUB, "-".code);
-		addKey(1087, K.NUMPAD_ADD, "+".code);
-		addKey(1088, K.NUMPAD_ENTER, 13);
+		addKey(1084, K.NUMPAD_DIV);
+		addKey(1085, K.NUMPAD_MULT);
+		addKey(1086, K.NUMPAD_SUB);
+		addKey(1087, K.NUMPAD_ADD);
+		addKey(1088, K.NUMPAD_ENTER);
 		for( i in 0...9 )
-			addKey(1089 + i, K.NUMPAD_1 + i, "1".code + i);
-		addKey(1098, K.NUMPAD_0, "0".code);
-		addKey(1099, K.NUMPAD_DOT, ".".code);
+			addKey(1089 + i, K.NUMPAD_1 + i);
+		addKey(1098, K.NUMPAD_0);
+		addKey(1099, K.NUMPAD_DOT);
 
 		// EXTRA
 		var keys = [

+ 6 - 1
hxd/Stage.js.hx

@@ -36,6 +36,7 @@ class Stage {
 		js.Browser.window.addEventListener("mousewheel", onMouseWheel);
 		js.Browser.window.addEventListener("keydown", onKeyDown);
 		js.Browser.window.addEventListener("keyup", onKeyUp);
+		js.Browser.window.addEventListener("keypress", onKeyPress);
 		canvas.addEventListener("mousedown", function(e) {
 			onMouseDown(e);
 			e.stopPropagation();
@@ -168,13 +169,17 @@ class Stage {
 	function onKeyUp(e:js.html.KeyboardEvent) {
 		var ev = new Event(EKeyUp, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
-		ev.charCode = e.charCode;
 		event(ev);
 	}
 
 	function onKeyDown(e:js.html.KeyboardEvent) {
 		var ev = new Event(EKeyDown, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
+		event(ev);
+	}
+
+	function onKeyPress(e:js.html.KeyboardEvent) {
+		var ev = new Event(ETextInput, mouseX, mouseY);
 		ev.charCode = e.charCode;
 		event(ev);
 	}