浏览代码

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;
 				if( logDY > logTxt.textHeight ) logDY = logTxt.textHeight;
 				e.propagate = false;
 				e.propagate = false;
 			}
 			}
-		case EKeyDown:
+		case ETextInput:
 			if( e.charCode == shortKeyChar && !bg.visible )
 			if( e.charCode == shortKeyChar && !bg.visible )
 				show();
 				show();
 		default:
 		default:

+ 5 - 0
h2d/Interactive.hx

@@ -162,6 +162,8 @@ class Interactive extends Drawable implements hxd.SceneEvents.Interactive {
 			onKeyDown(e);
 			onKeyDown(e);
 		case ECheck:
 		case ECheck:
 			onCheck(e);
 			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 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) {
 		interactive.onKeyDown = function(e:hxd.Event) {
-
 			onKeyDown(e);
 			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) {
 		interactive.onFocusLost = function(e) {
 			cursorIndex = -1;
 			cursorIndex = -1;
@@ -193,6 +109,101 @@ class TextInput extends Text {
 		addChildAt(interactive, 0);
 		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() {
 	function cutSelection() {
 		if(selectionRange == null) return false;
 		if(selectionRange == null) return false;
 		cursorIndex = selectionRange.start;
 		cursorIndex = selectionRange.start;
@@ -348,6 +359,9 @@ class TextInput extends Text {
 	public dynamic function onKeyUp(e:hxd.Event) {
 	public dynamic function onKeyUp(e:hxd.Event) {
 	}
 	}
 
 
+	public dynamic function onTextInput(e:hxd.Event) {
+	}
+
 	public dynamic function onFocus(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);
 			onKeyDown(e);
 		case ECheck:
 		case ECheck:
 			onCheck(e);
 			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 onCheck( e : hxd.Event ) {
 	}
 	}
 
 
+	public dynamic function onTextInput( e : hxd.Event ) {
+	}
+
 }
 }

+ 3 - 1
hxd/Event.hx

@@ -12,6 +12,7 @@ enum EventKind {
 	EKeyDown;
 	EKeyDown;
 	EKeyUp;
 	EKeyUp;
 	EReleaseOutside;
 	EReleaseOutside;
+	ETextInput;
 	/**
 	/**
 		Used to check if we are still on the interactive if no EMove was triggered this frame.
 		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 EPush, ERelease, EReleaseOutside: ",button=" + button;
 		case EMove, EOver, EOut, EFocus, EFocusLost, ECheck: "";
 		case EMove, EOver, EOut, EFocus, EFocusLost, ECheck: "";
 		case EWheel: ",wheelDelta=" + wheelDelta;
 		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 EMove, ECheck: checkOver = true;
 		case EPush: cancelFocus = true; checkPush = true;
 		case EPush: cancelFocus = true; checkPush = true;
 		case ERelease: checkPush = true;
 		case ERelease: checkPush = true;
-		case EKeyUp, EKeyDown, EWheel:
+		case EKeyUp, EKeyDown, ETextInput, EWheel:
 			if( currentFocus != null ) {
 			if( currentFocus != null ) {
 				event.relX = event.relY = 0;
 				event.relX = event.relY = 0;
 				currentFocus.handleEvent(event);
 				currentFocus.handleEvent(event);
@@ -237,7 +237,7 @@ class SceneEvents {
 					mouseX = e.relX;
 					mouseX = e.relX;
 					mouseY = e.relY;
 					mouseY = e.relY;
 					lastTouch = e.touchId;
 					lastTouch = e.touchId;
-				case EKeyUp, EKeyDown, EWheel:
+				case EKeyUp, EKeyDown, ETextInput, EWheel:
 					if( !checkFocused ) {
 					if( !checkFocused ) {
 						checkFocused = true;
 						checkFocused = true;
 						checkFocus();
 						checkFocus();

+ 7 - 2
hxd/Stage.flash.hx

@@ -207,16 +207,21 @@ class Stage {
 	function onKeyUp(e:flash.events.KeyboardEvent) {
 	function onKeyUp(e:flash.events.KeyboardEvent) {
 		var ev = new Event(EKeyUp, mouseX, mouseY);
 		var ev = new Event(EKeyUp, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
 		ev.keyCode = e.keyCode;
-		ev.charCode = getCharCode(e);
 		event(ev);
 		event(ev);
 	}
 	}
 
 
 	function onKeyDown(e:flash.events.KeyboardEvent) {
 	function onKeyDown(e:flash.events.KeyboardEvent) {
 		var ev = new Event(EKeyDown, mouseX, mouseY);
 		var ev = new Event(EKeyDown, mouseX, mouseY);
 		ev.keyCode = e.keyCode;
 		ev.keyCode = e.keyCode;
-		ev.charCode = getCharCode(e);
 		event(ev);
 		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
 		// prevent escaping fullscreen in air
 		if( e.keyCode == flash.ui.Keyboard.ESCAPE ) e.preventDefault();
 		if( e.keyCode == flash.ui.Keyboard.ESCAPE ) e.preventDefault();
 		if( e.keyCode == "S".code && e.ctrlKey ) 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;
 	var shiftDown : Bool;
 
 
 	static var CODEMAP = [for( i in 0...2048 ) i];
 	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) {
 	function new(title:String, width:Int, height:Int) {
 		this.windowWidth = width;
 		this.windowWidth = width;
@@ -169,11 +168,6 @@ class Stage {
 			eh = new Event(EKeyDown);
 			eh = new Event(EKeyDown);
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			eh.keyCode = CODEMAP[e.keyCode];
 			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 ) {
 			if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
 				e.keyCode = eh.keyCode & 0xFF;
 				e.keyCode = eh.keyCode & 0xFF;
 				if( e.keyCode == K.SHIFT ) shiftDown = true;
 				if( e.keyCode == K.SHIFT ) shiftDown = true;
@@ -183,11 +177,6 @@ class Stage {
 			eh = new Event(EKeyUp);
 			eh = new Event(EKeyUp);
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
 			eh.keyCode = CODEMAP[e.keyCode];
 			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 ) {
 			if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
 				e.keyCode = eh.keyCode & 0xFF;
 				e.keyCode = eh.keyCode & 0xFF;
 				if( e.keyCode == K.SHIFT ) shiftDown = false;
 				if( e.keyCode == K.SHIFT ) shiftDown = false;
@@ -198,6 +187,17 @@ class Stage {
 			eh.wheelDelta = -e.wheelDelta;
 			eh.wheelDelta = -e.wheelDelta;
 		case GControllerAdded, GControllerRemoved, GControllerUp, GControllerDown, GControllerAxis:
 		case GControllerAdded, GControllerRemoved, GControllerUp, GControllerDown, GControllerAxis:
 			@:privateAccess hxd.Pad.onEvent( e );
 			@: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:
 		default:
 		}
 		}
 		if( eh != null ) event(eh);
 		if( eh != null ) event(eh);
@@ -205,38 +205,26 @@ class Stage {
 
 
 	static function initChars() : Void {
 	static function initChars() : Void {
 
 
-		inline function addKey(sdl, keyCode, charCode=0) {
+		inline function addKey(sdl, keyCode) {
 			CODEMAP[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
 		// 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 )
 		for( i in 0...26 )
 			addKey(97 + i, K.A + i);
 			addKey(97 + i, K.A + i);
 		for( i in 0...12 )
 		for( i in 0...12 )
 			addKey(1058 + i, K.F1 + i);
 			addKey(1058 + i, K.F1 + i);
 
 
 		// NUMPAD
 		// 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 )
 		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
 		// EXTRA
 		var keys = [
 		var keys = [

+ 6 - 1
hxd/Stage.js.hx

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