[Scummvm-cvs-logs] scummvm master -> c28e101cdbfcc28f080da245e49f5b764bb8fc44

m-kiewitz m_kiewitz at users.sourceforge.net
Mon Feb 1 01:35:10 CET 2016


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
c28e101cdb AGI: implement predictive dialog


Commit: c28e101cdbfcc28f080da245e49f5b764bb8fc44
    https://github.com/scummvm/scummvm/commit/c28e101cdbfcc28f080da245e49f5b764bb8fc44
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2016-02-01T01:34:36+01:00

Commit Message:
AGI: implement predictive dialog

Changed paths:
    engines/agi/agi.h
    engines/agi/cycle.cpp
    engines/agi/keyboard.cpp
    engines/agi/op_cmd.cpp
    engines/agi/text.cpp
    engines/agi/text.h



diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 1e6001d..9d220d2 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -231,8 +231,7 @@ struct gameIdList {
 
 struct Mouse {
 	int button;
-	int x;
-	int y;
+	Common::Point pos;
 };
 
 // Used by AGI Mouse protocol 1.0 for v27 (i.e. button pressed -variable).
@@ -942,7 +941,12 @@ public:
 	void cleanKeyboard();
 
 	int16 getSpecialMenuControllerSlot();
+
+	bool handleMouseClicks(uint16 &key);
 	bool handleController(uint16 key);
+
+	bool showPredictiveDialog();
+
 	uint16 agiGetKeypress();
 	int waitKey();
 	int waitAnyKey();
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 6506ee2..67a238d 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -206,8 +206,8 @@ int AgiEngine::mainCycle(bool onlyCheckForEvents) {
 	//
 	// We run AGIMOUSE always as a side effect
 	//if (getFeatures() & GF_AGIMOUSE) {
-		setVar(VM_VAR_MOUSE_X, _mouse.x / 2);
-		setVar(VM_VAR_MOUSE_Y, _mouse.y);
+		setVar(VM_VAR_MOUSE_X, _mouse.pos.x / 2);
+		setVar(VM_VAR_MOUSE_Y, _mouse.pos.y);
 	//}
 
 	switch (_game.inputMode) {
@@ -245,21 +245,27 @@ int AgiEngine::mainCycle(bool onlyCheckForEvents) {
 		setVar(VM_VAR_KEY, keyAscii);
 	}
 
+	handleMouseClicks(key);
+
 	if (!cycleInnerLoopIsActive()) {
 		// no inner loop active at the moment, regular processing
 		switch (_game.inputMode) {
 		case INPUTMODE_NORMAL:
-			if (!handleController(key)) {
-				if (key == 0 || (!_text->promptIsEnabled()))
-					break;
-
-				_text->promptCharPress(key);
+			if (key) {
+				if (!handleController(key)) {
+					if ((key) && (_text->promptIsEnabled())) {
+						_text->promptCharPress(key);
+					}
+				}
 			}
 			break;
 		case INPUTMODE_NONE:
-			handleController(key);
-			if (key)
-				_game.keypress = key;
+			if (key) {
+				handleController(key);
+				if (key) {
+					_game.keypress = key;
+				}
+			}
 			break;
 		default:
 			break;
@@ -274,7 +280,6 @@ int AgiEngine::mainCycle(bool onlyCheckForEvents) {
 		switch (_game.cycleInnerLoopType) {
 		case CYCLE_INNERLOOP_GETSTRING: // loop called from TextMgr::stringEdit()
 		case CYCLE_INNERLOOP_GETNUMBER:
-			//handleController(key);
 			if (key) {
 				_text->stringCharPress(key);
 			}
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 2a5f801..07aec98 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -68,52 +68,16 @@ void AgiEngine::processEvents() {
 
 	while (_eventMan->pollEvent(event)) {
 		switch (event.type) {
-		case Common::EVENT_PREDICTIVE_DIALOG: {
-			GUI::PredictiveDialog _predictiveDialog;
-			_predictiveDialog.runModal();
-#if 0
-			strcpy(_predictiveResult, _predictiveDialog.getResult());
-			if (strcmp(_predictiveResult, "")) {
-				if (_game.inputMode == INPUTMODE_NORMAL) {
-					//strcpy((char *)_game.inputBuffer, _predictiveResult);
-					//handleKeys(KEY_ENTER);
-					// TODO: repair predictive
-				} else if (_game.inputMode == INPUTMODE_GETSTRING) {
-					strcpy(_game.strings[_stringdata.str], _predictiveResult);
-					newInputMode(INPUTMODE_NORMAL);
-					//_gfx->printCharacter(_stringdata.x + strlen(_game.strings[_stringdata.str]) + 1,
-					//		_stringdata.y, ' ', 15, 0);
-				} else if (_game.inputMode == INPUTMODE_NONE) {
-					for (int n = 0; _predictiveResult[n]; n++)
-						keyEnqueue(_predictiveResult[n]);
-				}
-			}
-#endif
-			/*
-			if (predictiveDialog()) {
-				if (_game.inputMode == INPUT_NORMAL) {
-					strcpy((char *)_game.inputBuffer, _predictiveResult);
-					handleKeys(KEY_ENTER);
-				} else if (_game.inputMode == INPUT_GETSTRING) {
-					strcpy(_game.strings[_stringdata.str], _predictiveResult);
-					newInputMode(INPUT_NORMAL);
-					_gfx->printCharacter(_stringdata.x + strlen(_game.strings[_stringdata.str]) + 1,
-							_stringdata.y, ' ', _game.colorFg, _game.colorBg);
-				} else if (_game.inputMode == INPUT_NONE) {
-					for (int n = 0; _predictiveResult[n]; n++)
-						keyEnqueue(_predictiveResult[n]);
-				}
-			}
-			*/
-			}
+		case Common::EVENT_PREDICTIVE_DIALOG:
+			showPredictiveDialog();
 			break;
 		case Common::EVENT_LBUTTONDOWN:
 			if (_game.mouseEnabled) {
 				key = AGI_MOUSE_BUTTON_LEFT;
 				_mouse.button = kAgiMouseButtonLeft;
 				keyEnqueue(key);
-				_mouse.x = event.mouse.x;
-				_mouse.y = event.mouse.y;
+				_mouse.pos.x = event.mouse.x;
+				_mouse.pos.y = event.mouse.y;
 			}
 			break;
 		case Common::EVENT_RBUTTONDOWN:
@@ -121,8 +85,8 @@ void AgiEngine::processEvents() {
 				key = AGI_MOUSE_BUTTON_RIGHT;
 				_mouse.button = kAgiMouseButtonRight;
 				keyEnqueue(key);
-				_mouse.x = event.mouse.x;
-				_mouse.y = event.mouse.y;
+				_mouse.pos.x = event.mouse.x;
+				_mouse.pos.y = event.mouse.y;
 			}
 			break;
 		case Common::EVENT_WHEELUP:
@@ -139,20 +103,20 @@ void AgiEngine::processEvents() {
 			break;
 		case Common::EVENT_MOUSEMOVE:
 			if (_game.mouseEnabled) {
-				_mouse.x = event.mouse.x;
-				_mouse.y = event.mouse.y;
+				_mouse.pos.x = event.mouse.x;
+				_mouse.pos.y = event.mouse.y;
 
 				if (!_game.mouseFence.isEmpty()) {
-					if (_mouse.x < _game.mouseFence.left)
-						_mouse.x = _game.mouseFence.left;
-					if (_mouse.x > _game.mouseFence.right)
-						_mouse.x = _game.mouseFence.right;
-					if (_mouse.y < _game.mouseFence.top)
-						_mouse.y = _game.mouseFence.top;
-					if (_mouse.y > _game.mouseFence.bottom)
-						_mouse.y = _game.mouseFence.bottom;
-
-					g_system->warpMouse(_mouse.x, _mouse.y);
+					if (_mouse.pos.x < _game.mouseFence.left)
+						_mouse.pos.x = _game.mouseFence.left;
+					if (_mouse.pos.x > _game.mouseFence.right)
+						_mouse.pos.x = _game.mouseFence.right;
+					if (_mouse.pos.y < _game.mouseFence.top)
+						_mouse.pos.y = _game.mouseFence.top;
+					if (_mouse.pos.y > _game.mouseFence.bottom)
+						_mouse.pos.y = _game.mouseFence.bottom;
+
+					g_system->warpMouse(_mouse.pos.x, _mouse.pos.y);
 				}
 			}
 
@@ -161,8 +125,8 @@ void AgiEngine::processEvents() {
 		case Common::EVENT_RBUTTONUP:
 			if (_game.mouseEnabled) {
 				_mouse.button = kAgiMouseButtonUp;
-				_mouse.x = event.mouse.x;
-				_mouse.y = event.mouse.y;
+				_mouse.pos.x = event.mouse.x;
+				_mouse.pos.y = event.mouse.y;
 			}
 			break;
 		case Common::EVENT_KEYDOWN:
@@ -347,6 +311,86 @@ int16 AgiEngine::getSpecialMenuControllerSlot() {
 	return -1;
 }
 
+bool AgiEngine::handleMouseClicks(uint16 &key) {
+	// No mouse click? -> exit
+	if (key != AGI_MOUSE_BUTTON_LEFT)
+		return false;
+
+	Common::Rect displayLineRect(DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
+	int16 statusRow = _text->statusRow_Get();
+
+	displayLineRect.moveTo(0, statusRow * FONT_DISPLAY_HEIGHT);
+
+	if (displayLineRect.contains(_mouse.pos)) {
+	    if (getFlag(VM_FLAG_MENUS_WORK) && _menu->isAvailable()) {
+			warning("click on status line -> menu TODO");
+			// TODO: menu
+			// This should be done in a better way as in simulate ESC key
+			// Sierra seems to have hardcoded it in some way, but we would have to verify, what flags
+			// they checked. The previous way wasn't accurate. Mouse support for menu is missing atm anyway.
+			//if ((getflag(VM_FLAG_MENUS_WORK) || (getFeatures() & GF_MENUS)) && _mouse.y <= CHAR_LINES) {
+			//	newInputMode(INPUTMODE_MENU);
+			//	return true;
+			//}
+			key = 0; // eat event
+			return true;
+	    }
+	}
+
+	if (_text->promptIsEnabled() && (!cycleInnerLoopIsActive()) ) {
+		// Prompt is currently enabled, but no inner loop is active
+		int16 promptRow = _text->promptRow_Get();
+
+		displayLineRect.moveTo(0, promptRow * FONT_DISPLAY_HEIGHT);
+
+		if (displayLineRect.contains(_mouse.pos)) {
+			// and user clicked within the line of the prompt
+		    showPredictiveDialog();
+
+		    key = 0; // eat event
+		    return true;
+		}
+	}
+
+	if (cycleInnerLoopIsActive()) {
+		// inner loop active, check what kind of loop it is. Then process / forward it
+		switch (_game.cycleInnerLoopType) {
+		case CYCLE_INNERLOOP_GETSTRING:
+		case CYCLE_INNERLOOP_GETNUMBER: {
+			// process in here
+			int16 stringRow, stringColumn, stringMaxLen;
+
+			_text->stringPos_Get(stringRow, stringColumn);
+			stringMaxLen = _text->stringGetMaxLen();
+
+			Common::Rect displayRect(stringMaxLen * FONT_DISPLAY_WIDTH, FONT_DISPLAY_HEIGHT);
+			displayRect.moveTo(stringColumn * FONT_DISPLAY_WIDTH, stringRow * FONT_DISPLAY_HEIGHT);
+
+			if (displayRect.contains(_mouse.pos)) {
+				// user clicked inside the input space
+			    showPredictiveDialog();
+
+			    key = 0; // eat event
+			    return true;
+			}
+			break;
+		}
+		case CYCLE_INNERLOOP_INVENTORY:
+			// TODO: forward
+			break;
+		case CYCLE_INNERLOOP_MENU:
+			// TODO: forward
+			break;
+		case CYCLE_INNERLOOP_SYSTEMUI_SELECTSAVEDGAMESLOT:
+			// TODO: forward
+			break;
+		default:
+			break;
+		}
+	}
+	return false;
+}
+
 bool AgiEngine::handleController(uint16 key) {
 	ScreenObjEntry *screenObjEgo = &_game.screenObjTable[SCREENOBJECTS_EGO_ENTRY];
 
@@ -407,51 +451,6 @@ bool AgiEngine::handleController(uint16 key) {
 		}
 	}
 
-	if (key == AGI_MOUSE_BUTTON_LEFT) {
-		// call mouse when click is done on status bar
-		// TODO
-		// This should be done in a better way as in simulate ESC key
-		// Sierra seems to have hardcoded it in some way, but we would have to verify, what flags
-		// they checked. The previous way wasn't accurate. Mouse support for menu is missing atm anyway.
-		//if ((getflag(VM_FLAG_MENUS_WORK) || (getFeatures() & GF_MENUS)) && _mouse.y <= CHAR_LINES) {
-		//	newInputMode(INPUTMODE_MENU);
-		//	return true;
-		//}
-	}
-
-	// Show predictive dialog if the user clicks on input area
-	if (key == AGI_MOUSE_BUTTON_LEFT &&
-			(int)_mouse.y >= _text->promptRow_Get() * FONT_DISPLAY_HEIGHT &&
-			(int)_mouse.y <= (_text->promptRow_Get() + 1) * FONT_DISPLAY_HEIGHT) {
-		GUI::PredictiveDialog _predictiveDialog;
-		_predictiveDialog.runModal();
-#if 0
-		strcpy(_predictiveResult, _predictiveDialog.getResult());
-		if (strcmp(_predictiveResult, "")) {
-			if (_game.inputMode == INPUTMODE_NONE) {
-				for (int n = 0; _predictiveResult[n]; n++)
-					keyEnqueue(_predictiveResult[n]);
-			} else {
-				//strcpy((char *)_game.inputBuffer, _predictiveResult);
-				//handleKeys(KEY_ENTER);
-				// TODO
-			}
-		}
-#endif
-		/*
-		if (predictiveDialog()) {
-			if (_game.inputMode == INPUT_NONE) {
-				for (int n = 0; _predictiveResult[n]; n++)
-					keyEnqueue(_predictiveResult[n]);
-			} else {
-				strcpy((char *)_game.inputBuffer, _predictiveResult);
-				handleKeys(KEY_ENTER);
-			}
-		}
-		*/
-		return true;
-	}
-
 	int16 newDirection = 0;
 
 	switch (key) {
@@ -498,8 +497,8 @@ bool AgiEngine::handleController(uint16 key) {
 						//v->flags |= fAdjEgoXY;
 						// setting fAdjEgoXY here will at least break "climbing the log" in SQ2
 						// in case you walked to the log by using the mouse, so don't!!!
-						int16 egoDestinationX = _mouse.x;
-						int16 egoDestinationY = _mouse.y;
+						int16 egoDestinationX = _mouse.pos.x;
+						int16 egoDestinationY = _mouse.pos.y;
 						adjustPosToGameScreen(egoDestinationX, egoDestinationY);
 
 						screenObjEgo->motionType = kMotionEgo;
@@ -534,6 +533,41 @@ bool AgiEngine::handleController(uint16 key) {
 	return false;
 }
 
+bool AgiEngine::showPredictiveDialog() {
+	GUI::PredictiveDialog predictiveDialog;
+
+	inGameTimerPause();
+	predictiveDialog.runModal();
+	inGameTimerResume();
+
+	Common::String predictiveResult(predictiveDialog.getResult());
+	uint16 predictiveResultLen = predictiveResult.size();
+	if (predictiveResult.size()) {
+		// User actually entered something
+		for (int16 resultPos = 0; resultPos < predictiveResultLen; resultPos++) {
+			keyEnqueue(predictiveResult[resultPos]);
+		}
+		if (!cycleInnerLoopIsActive()) {
+			if (_text->promptIsEnabled()) {
+				// add ENTER, when the input is probably meant for the prompt
+				keyEnqueue(AGI_KEY_ENTER);
+			}
+		} else {
+			switch (_game.cycleInnerLoopType) {
+			case CYCLE_INNERLOOP_GETSTRING:
+			case CYCLE_INNERLOOP_GETNUMBER:
+				// add ENTER, when the input is probably meant for GetString/GetNumber
+				keyEnqueue(AGI_KEY_ENTER);
+				break;
+			default:
+				break;
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
 int AgiEngine::waitKey() {
 	int key = 0;
 
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 4b82d24..f36090d 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -1851,8 +1851,7 @@ void cmdConfigureScreen(AgiGame *state, uint8 *parameter) {
 	uint16 promptRow = parameter[1];
 	uint16 statusRow = parameter[2];
 
-	state->_vm->_text->configureScreen(lineMinPrint);
-
+	textMgr->configureScreen(lineMinPrint);
 	textMgr->statusRow_Set(statusRow);
 	textMgr->promptRow_Set(promptRow);
 }
@@ -2256,8 +2255,8 @@ void cmdPushScript(AgiGame *state, uint8 *parameter) {
 	// We run AGIMOUSE always as a side effect
 	//if (getFeatures() & GF_AGIMOUSE || true) {
 	vm->setVar(VM_VAR_MOUSE_BUTTONSTATE, state->_vm->_mouse.button);
-	vm->setVar(VM_VAR_MOUSE_X, state->_vm->_mouse.x / 2);
-	vm->setVar(VM_VAR_MOUSE_Y, state->_vm->_mouse.y);
+	vm->setVar(VM_VAR_MOUSE_X, vm->_mouse.pos.x / 2);
+	vm->setVar(VM_VAR_MOUSE_Y, vm->_mouse.pos.y);
 	/*} else {
 		if (getVersion() >= 0x2915) {
 			debug(0, "push.script");
@@ -2277,8 +2276,8 @@ void cmdMousePosn(AgiGame *state, uint8 *parameter) {
 	AgiEngine *vm = state->_vm;
 	uint16 destVarNr1 = parameter[0];
 	uint16 destVarNr2 = parameter[1];
-	int16 mouseX = state->_vm->_mouse.x;
-	int16 mouseY = state->_vm->_mouse.y;
+	int16 mouseX = vm->_mouse.pos.x;
+	int16 mouseY = vm->_mouse.pos.y;
 
 	state->_vm->adjustPosToGameScreen(mouseX, mouseY);
 
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 8806aee..c6c0f93 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -64,6 +64,8 @@ TextMgr::TextMgr(AgiEngine *vm, Words *words, GfxMgr *gfx) {
 	promptDisable();
 	promptReset();
 
+	_inputStringRow = 0;
+	_inputStringColumn = 0;
 	_inputStringMaxLen = 0;
 	_inputStringCursorPos = 0;
 	_inputString[0] = 0;
@@ -107,16 +109,21 @@ void TextMgr::charPos_Set(int16 row, int16 column) {
 	_textPos.column = column;
 }
 
-void TextMgr::charPos_Get(TextPos_Struct *posPtr) {
-	posPtr->row    = _textPos.row;
-	posPtr->column = _textPos.column;
-}
-
 void TextMgr::charPos_Set(TextPos_Struct *posPtr) {
 	_textPos.row    = posPtr->row;
 	_textPos.column = posPtr->column;
 }
 
+void TextMgr::charPos_Get(int16 &row, int16 &column) {
+	row = _textPos.row;
+	column = _textPos.column;
+}
+
+void TextMgr::charPos_Get(TextPos_Struct *posPtr) {
+	posPtr->row    = _textPos.row;
+	posPtr->column = _textPos.column;
+}
+
 void TextMgr::charPos_Push() {
 	if (_textPosArrayCount < TEXTPOSARRAY_MAX) {
 		charPos_Get(&_textPosArray[_textPosArrayCount]);
@@ -735,9 +742,21 @@ void TextMgr::stringSet(const char *text) {
 	_inputString[sizeof(_inputString) - 1] = 0; // terminator
 }
 
+void TextMgr::stringPos_Get(int16 &row, int16 &column) {
+	row = _inputStringRow;
+	column = _inputStringColumn;
+}
+int16 TextMgr::stringGetMaxLen() {
+	return _inputStringMaxLen;
+}
+
 void TextMgr::stringEdit(int16 stringMaxLen) {
 	int16 inputStringLen = strlen((const char *)_inputString);
 
+	// Remember current position for predictive dialog
+	_inputStringRow = _textPos.row;
+	_inputStringColumn = _textPos.column;
+
 	// Caller can set the input string
 	_inputStringCursorPos = 0;
 	while (_inputStringCursorPos < inputStringLen) {
diff --git a/engines/agi/text.h b/engines/agi/text.h
index b42f098..febb50f 100644
--- a/engines/agi/text.h
+++ b/engines/agi/text.h
@@ -107,8 +107,9 @@ public:
 
 	void charPos_Clip(int16 &row, int16 &column);
 	void charPos_Set(int16 row, int16 column);
-	void charPos_Get(TextPos_Struct *posPtr);
 	void charPos_Set(TextPos_Struct *posPtr);
+	void charPos_Get(int16 &row, int16 &column);
+	void charPos_Get(TextPos_Struct *posPtr);
 	void charPos_Push();
 	void charPos_Pop();
 	void charPos_SetInsideWindow(int16 windowRow, int16 windowColumn);
@@ -181,12 +182,16 @@ public:
 	void promptClear(); // for AGI1
 	void promptRememberForAutoComplete(bool entered = false); // for auto-completion
 
+	int16 _inputStringRow;
+	int16 _inputStringColumn;
 	bool  _inputStringEntered;
 	int16 _inputStringMaxLen;
 	int16 _inputStringCursorPos;
 	byte  _inputString[42];
 
 	bool stringWasEntered();
+	void stringPos_Get(int16 &row, int16 &column);
+	int16 stringGetMaxLen();
 	void stringSet(const char *text);
 	void stringEdit(int16 stringMaxLen);
 	void stringCharPress(int16 newChar);






More information about the Scummvm-git-logs mailing list