[Scummvm-cvs-logs] SF.net SVN: scummvm:[33827] scummvm/branches/gsoc2008-vkeybd

kenny-d at users.sourceforge.net kenny-d at users.sourceforge.net
Wed Aug 13 16:33:18 CEST 2008


Revision: 33827
          http://scummvm.svn.sourceforge.net/scummvm/?rev=33827&view=rev
Author:   kenny-d
Date:     2008-08-13 14:33:17 +0000 (Wed, 13 Aug 2008)

Log Message:
-----------
Keymapper WIP:
* Further improvement of automatic mapping
* Remap dialog - added timeout feature

Modified Paths:
--------------
    scummvm/branches/gsoc2008-vkeybd/backends/keymapper/action.cpp
    scummvm/branches/gsoc2008-vkeybd/backends/keymapper/keymap-manager.cpp
    scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.cpp
    scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.h
    scummvm/branches/gsoc2008-vkeybd/gui/theme-config.cpp

Modified: scummvm/branches/gsoc2008-vkeybd/backends/keymapper/action.cpp
===================================================================
--- scummvm/branches/gsoc2008-vkeybd/backends/keymapper/action.cpp	2008-08-13 13:40:28 UTC (rev 33826)
+++ scummvm/branches/gsoc2008-vkeybd/backends/keymapper/action.cpp	2008-08-13 14:33:17 UTC (rev 33827)
@@ -50,7 +50,7 @@
 	assert(_parent);
 	if (_hwKey) _parent->unregisterMapping(this);
 	_hwKey = key;
-	if (_hwKey) _parent->registerMapping(this, key);
+	if (_hwKey) _parent->registerMapping(this, _hwKey);
 }
 
 const HardwareKey *Action::getMappedKey() const {

Modified: scummvm/branches/gsoc2008-vkeybd/backends/keymapper/keymap-manager.cpp
===================================================================
--- scummvm/branches/gsoc2008-vkeybd/backends/keymapper/keymap-manager.cpp	2008-08-13 13:40:28 UTC (rev 33826)
+++ scummvm/branches/gsoc2008-vkeybd/backends/keymapper/keymap-manager.cpp	2008-08-13 14:33:17 UTC (rev 33827)
@@ -92,64 +92,107 @@
 		automaticMap(map);
 }
 
+// TODO:
+// - current weaknesses:
+//     - if an action finds a key with required type / category but a parent 
+//       action with higher priority is using it, that key is never used
 void KeymapManager::automaticMap(Keymap *map) {
-	List<Action*> actions(map->getActions()), unmapped;
+	// Create local copies of action and key lists.
+	List<Action*> actions(map->getActions());
+	List<const HardwareKey*> keys(_hardwareKeys->getHardwareKeys());
+
 	List<Action*>::iterator actIt;
-	List<const HardwareKey*> keys = _hardwareKeys->getHardwareKeys();
 	List<const HardwareKey*>::iterator keyIt, selectedKey;
+	
+	// Remove actions and keys from local lists that have already been mapped.
+	actIt = actions.begin();
+	while (actIt != actions.end()) {
+		Action *act = *actIt;
+		const HardwareKey *key = act->getMappedKey();
+		if (key) {
+			keys.remove(key);
+			actIt = actions.erase(actIt);
+		} else {
+			++actIt;
+		}
+	}
 
-	// sort by priority
+	// Sort remaining actions by priority.
 	ActionPriorityComp priorityComp;
 	sort(actions.begin(), actions.end(), priorityComp);
 	
-	for (actIt = actions.begin(); actIt != actions.end(); actIt++) {
+	// First mapping pass:
+	// - Match if a key's preferred type or category is same as the action's.
+	// - Priority is given to:
+	//     - keys that match type over category.
+	//     - keys that have not been used by parent maps.
+	// - If a key has been used by a parent map the new action must have a
+	//   higher priority than the parent action.
+	// - As soon as the number of skipped actions equals the number of keys 
+	//   remaining we stop matching. This means that the second pass will assign keys
+	//   to these higher priority skipped actions.
+	uint skipped = 0;
+	actIt = actions.begin();
+	while (actIt != actions.end() && skipped < keys.size()) {
 		selectedKey = keys.end();
-		int keyScore = 0;
+		int matchRank = 0;
 		Action *act = *actIt;
-		for (keyIt = keys.begin(); keyIt != keys.end(); keyIt++) {
+		for (keyIt = keys.begin(); keyIt != keys.end(); ++keyIt) {
 			if ((*keyIt)->preferredType == act->type) {
 				Action *parentAct = getParentMappedAction(map, (*keyIt)->key);
 				if (!parentAct) {
 					selectedKey = keyIt;
 					break;
-				} else if (parentAct->priority <= act->priority && keyScore < 3) {
+				} else if (parentAct->priority <= act->priority && matchRank < 3) {
 					selectedKey = keyIt;
-					keyScore = 3;
+					matchRank = 3;
 				}
-			} else if ((*keyIt)->preferredCategory == act->category && keyScore < 2) {
+			} else if ((*keyIt)->preferredCategory == act->category && matchRank < 2) {
 				Action *parentAct = getParentMappedAction(map, (*keyIt)->key);
 				if (!parentAct) {
 					selectedKey = keyIt;
-					keyScore = 2;
-				} else if (parentAct->priority <= act->priority && keyScore < 1) {
+					matchRank = 2;
+				} else if (parentAct->priority <= act->priority && matchRank < 1) {
 					selectedKey = keyIt;
-					keyScore = 1;
+					matchRank = 1;
 				}
 			}
 		}
 		if (selectedKey != keys.end()) {
+			// Map action and delete action & key from local lists.
 			act->mapKey(*selectedKey);
 			keys.erase(selectedKey);
-		} else
-			unmapped.push_back(act);
+			actIt = actions.erase(actIt);
+		} else {
+			// Skip action (will be mapped in next pass).
+			++actIt;
+			++skipped;
+		}
 	}
 
-	for (actIt = unmapped.begin(); actIt != unmapped.end(); actIt++) {
+	// Second mapping pass:
+	// - Maps any remaining actions to keys
+	// - priority given to:
+	//     - keys that have no parent action
+	//     - keys whose parent action has lower priority than the new action
+	//     - keys whose parent action has the lowest priority
+	// - is guarantees to match a key if one is available
+	for (actIt = actions.begin(); actIt != actions.end(); ++actIt) {
 		selectedKey = keys.end();
-		int keyScore = 0;
-		int lowestPriority = 0; //dummy value
+		int matchRank = 0;
+		int lowestPriority = 0;
 		Action *act = *actIt;
-		for (keyIt = keys.begin(); keyIt != keys.end(); keyIt++) {
+		for (keyIt = keys.begin(); keyIt != keys.end(); ++keyIt) {
 			Action *parentAct = getParentMappedAction(map, (*keyIt)->key);
 			if (!parentAct) {
 				selectedKey = keyIt;
 				break;
-			} else if (keyScore < 2) {
+			} else if (matchRank < 2) {
 				if (parentAct->priority <= act->priority) {
-					keyScore = 2;
+					matchRank = 2;
 					selectedKey = keyIt;
-				} else if (parentAct->priority < lowestPriority || keyScore == 0) {
-					keyScore = 1;
+				} else if (parentAct->priority < lowestPriority || matchRank == 0) {
+					matchRank = 1;
 					lowestPriority = parentAct->priority;
 					selectedKey = keyIt;
 				}
@@ -158,8 +201,9 @@
 		if (selectedKey != keys.end()) {
 			act->mapKey(*selectedKey);
 			keys.erase(selectedKey);
-		} else // no keys left 
+		} else {// no match = no keys left 
 			return;
+		}
 	}
 }
 

Modified: scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.cpp
===================================================================
--- scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.cpp	2008-08-13 13:40:28 UTC (rev 33826)
+++ scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.cpp	2008-08-13 14:33:17 UTC (rev 33827)
@@ -35,7 +35,7 @@
 };
 
 RemapDialog::RemapDialog()
-	: Dialog("remap"), _activeRemapAction(0), _topAction(0) {
+	: Dialog("remap"), _activeRemapAction(0), _topAction(0), _remapTimeout(0) {
 
 	const int screenW = g_system->getOverlayWidth();
 	const int screenH = g_system->getOverlayHeight();
@@ -112,15 +112,16 @@
 }
 
 void RemapDialog::startRemapping(uint i) {
-
+	_remapTimeout = getMillis() + kRemapTimeoutDelay;
 	_activeRemapAction = _currentActions[_topAction + i].action;
 	_keymapWidgets[i].keyButton->setLabel("...");
 	_keymapWidgets[i].keyButton->draw();
+	_keymapper->setEnabled(false);
 
-	_keymapper->setEnabled(false);
 }
 
 void RemapDialog::stopRemapping() {
+	_topAction = -1;
 	refreshKeymap();
 	_activeRemapAction = 0;
 	_keymapper->setEnabled(true);
@@ -136,9 +137,21 @@
 	} else {
 		GUI::Dialog::handleKeyDown(state);
 	}
+}
 
+void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
+	if (_activeRemapAction)
+		stopRemapping();
+	else
+		Dialog::handleMouseDown(x, y, button, clickCount);
 }
 
+void RemapDialog::handleTickle() {
+	if (_activeRemapAction && getMillis() > _remapTimeout)
+		stopRemapping();
+	Dialog::handleTickle();
+}
+
 void RemapDialog::loadKeymap() {
 	_currentActions.clear();
 	if (_activeKeymaps->size() > 0 && _kmPopUp->getSelected() == 0) {

Modified: scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.h
===================================================================
--- scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.h	2008-08-13 13:40:28 UTC (rev 33826)
+++ scummvm/branches/gsoc2008-vkeybd/backends/keymapper/remap-dialog.h	2008-08-13 14:33:17 UTC (rev 33827)
@@ -42,6 +42,8 @@
 	virtual void open();
 	virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
 	virtual void handleKeyUp(Common::KeyState state);
+	virtual void handleMouseDown(int x, int y, int button, int clickCount);
+	virtual void handleTickle();
 
 protected:
 	struct ActionWidgets {
@@ -77,6 +79,8 @@
 
 	Array<ActionWidgets> _keymapWidgets;
 	Action *_activeRemapAction;
+	uint32 _remapTimeout;
+	static const uint32 kRemapTimeoutDelay = 3000;
 
 };
 

Modified: scummvm/branches/gsoc2008-vkeybd/gui/theme-config.cpp
===================================================================
--- scummvm/branches/gsoc2008-vkeybd/gui/theme-config.cpp	2008-08-13 13:40:28 UTC (rev 33826)
+++ scummvm/branches/gsoc2008-vkeybd/gui/theme-config.cpp	2008-08-13 14:33:17 UTC (rev 33827)
@@ -374,11 +374,11 @@
 "scummsaveload_extinfo.visible=true\n"
 "\n"
 "# Keymapper remap dialog\n"
-"remap=8 8 (w - 16) (h / 5)\n"
+"remap=(w / 4) (h / 4) (w / 2) (h / 2)\n"
 "remap_spacing=10\n"
-"remap_popup=remap_spacing remap_spacing (parent.w - remap_spacing * 2) (kLineHeight + 2)\n"
+"remap_popup=remap_spacing remap_spacing (prev.w - remap_spacing * 2) (kLineHeight + 2)\n"
 "remap_popup_labelW=buttonWidth\n"
-"remap_col_count=3\n"
+"remap_col_count=2\n"
 "remap_keymap_area=remap_spacing (remap_popup.y + remap_popup.h + remap_spacing) (remap.w - remap_spacing * 2) (remap.h - self.y - remap_spacing)\n"
 "############################################\n"
 "[chooser]\n"


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list