mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 21:46:50 +02:00
238 lines
8.4 KiB
JavaScript
238 lines
8.4 KiB
JavaScript
// EnumMeta.js -- helper module that maps related enum values to printable names and ids
|
|
|
|
/* eslint-env commonjs */
|
|
/* global DriveKeys, console */
|
|
|
|
var VERSION = '0.0.1';
|
|
var WANT_DEBUG = false;
|
|
|
|
function _debugPrint() {
|
|
// eslint-disable-next-line no-console
|
|
(typeof Script === 'object' ? print : console.log)('EnumMeta | ' + [].slice.call(arguments).join(' '));
|
|
}
|
|
|
|
var debugPrint = WANT_DEBUG ? _debugPrint : function(){};
|
|
|
|
try {
|
|
/* global process */
|
|
if (process.title === 'node') {
|
|
_defineNodeJSMocks();
|
|
}
|
|
} catch (e) { /* eslint-disable-line empty-block */ }
|
|
|
|
_debugPrint(VERSION);
|
|
|
|
// FIXME: C++ emits this action event, but doesn't expose it yet to scripting
|
|
// (ie: as Actions.ZOOM or Actions.TranslateCameraZ)
|
|
var ACTION_TRANSLATE_CAMERA_Z = {
|
|
actionName: 'TranslateCameraZ',
|
|
actionID: 12,
|
|
driveKeyName: 'ZOOM'
|
|
};
|
|
|
|
module.exports = {
|
|
version: VERSION,
|
|
DriveKeyNames: invertKeys(DriveKeys),
|
|
Controller: {
|
|
Hardware: Object.keys(Controller.Hardware).reduce(function(names, prop) {
|
|
names[prop+'Names'] = invertKeys(Controller.Hardware[prop]);
|
|
return names;
|
|
}, {}),
|
|
ActionNames: _getActionNames(),
|
|
StandardNames: invertKeys(Controller.Standard)
|
|
},
|
|
getDriveKeyNameFromActionName: getDriveKeyNameFromActionName,
|
|
getActionNameFromDriveKeyName: getActionNameFromDriveKeyName,
|
|
eventKeyText2KeyboardName: eventKeyText2KeyboardName,
|
|
keyboardName2eventKeyText: keyboardName2eventKeyText,
|
|
ACTION_TRANSLATE_CAMERA_Z: ACTION_TRANSLATE_CAMERA_Z,
|
|
INVALID_ACTION_ID: Controller.findAction('INVALID_ACTION_ID_FOO')
|
|
};
|
|
|
|
_debugPrint('///'+VERSION, Object.keys(module.exports));
|
|
|
|
var actionsMapping = {}, driveKeyMapping = {};
|
|
|
|
initializeMappings(actionsMapping, driveKeyMapping);
|
|
|
|
function invertKeys(object) {
|
|
if (!object) {
|
|
return object;
|
|
}
|
|
return Object.keys(object).reduce(function(out, key) {
|
|
out[object[key]] = key;
|
|
return out;
|
|
}, {});
|
|
}
|
|
|
|
function _getActionNames() {
|
|
var ActionNames = invertKeys(Controller.Hardware.Actions);
|
|
ActionNames[ACTION_TRANSLATE_CAMERA_Z.actionID] = ACTION_TRANSLATE_CAMERA_Z.actionName;
|
|
function mapActionName(actionName) {
|
|
var actionKey = Controller.Hardware.Actions[actionName],
|
|
actionID = Controller.findAction(actionName),
|
|
similarName = eventKeyText2KeyboardName(actionName),
|
|
existingName = ActionNames[actionID];
|
|
|
|
var keyName = actionName;
|
|
|
|
if (actionID === module.exports.INVALID_ACTION_ID) {
|
|
_debugPrint('actionID === INVALID_ACTION_ID', actionName);
|
|
}
|
|
switch (actionName) {
|
|
case 'StepTranslateX': actionName = 'StepTranslate'; break;
|
|
case 'StepTranslateY': actionName = 'StepTranslate'; break;
|
|
case 'StepTranslateZ': actionName = 'StepTranslate'; break;
|
|
case 'ACTION1': actionName = 'PrimaryAction'; break;
|
|
case 'ACTION2': actionName = 'SecondaryAction'; break;
|
|
}
|
|
debugPrint(keyName, actionName, actionKey, actionID);
|
|
|
|
similarName = similarName.replace('Lateral','Strafe').replace(/^(?:Longitudinal|Vertical)/, '');
|
|
if (actionID in ActionNames) {
|
|
// check if overlap is just BoomIn <=> BOOM_IN
|
|
if (similarName !== existingName && actionName !== existingName) {
|
|
throw new Error('assumption failed: overlapping actionID:'+JSON.stringify({
|
|
actionID: actionID,
|
|
actionKey: actionKey,
|
|
actionName: actionName,
|
|
similarName: similarName,
|
|
keyName: keyName,
|
|
existingName: existingName
|
|
},0,2));
|
|
}
|
|
} else {
|
|
ActionNames[actionID] = actionName;
|
|
ActionNames[actionKey] = keyName;
|
|
}
|
|
}
|
|
// first map non-legacy (eg: Up and not VERTICAL_UP) actions
|
|
Object.keys(Controller.Hardware.Actions).filter(function(name) {
|
|
return /[a-z]/.test(name);
|
|
}).sort().reverse().forEach(mapActionName);
|
|
// now legacy actions
|
|
Object.keys(Controller.Hardware.Actions).filter(function(name) {
|
|
return !/[a-z]/.test(name);
|
|
}).sort().reverse().forEach(mapActionName);
|
|
|
|
return ActionNames;
|
|
}
|
|
|
|
// attempts to brute-force translate an Action name into a DriveKey name
|
|
// eg: _translateActionName('TranslateX') === 'TRANSLATE_X'
|
|
// eg: _translateActionName('Yaw') === 'YAW'
|
|
function _translateActionName(name, _index) {
|
|
name = name || '';
|
|
var key = name;
|
|
var re = new RegExp('[A-Z][a-z0-9]+', 'g');
|
|
key = key.replace(re, function(Word) {
|
|
return Word.toUpperCase()+'_';
|
|
})
|
|
.replace(/_$/, '');
|
|
|
|
if (key in DriveKeys) {
|
|
debugPrint('getDriveKeyFromEventName', _index, name, key, DriveKeys[key]);
|
|
return key;
|
|
}
|
|
}
|
|
|
|
function getActionNameFromDriveKeyName(driveKeyName) {
|
|
return driveKeyMapping[driveKeyName];
|
|
}
|
|
// maps an action lookup value to a DriveKey name
|
|
// eg: actionName: 'Yaw' === 'YAW'
|
|
// actionKey: Controller.Actions.Yaw => 'YAW'
|
|
// actionID: Controller.findAction('Yaw') => 'YAW'
|
|
function getDriveKeyNameFromActionName(lookupValue) {
|
|
if (lookupValue === ACTION_TRANSLATE_CAMERA_Z.actionName ||
|
|
lookupValue === ACTION_TRANSLATE_CAMERA_Z.actionID) {
|
|
return ACTION_TRANSLATE_CAMERA_Z.driveKeyName;
|
|
}
|
|
if (typeof lookupValue === 'string') {
|
|
lookupValue = Controller.findAction(lookupValue);
|
|
}
|
|
return actionsMapping[lookupValue];
|
|
}
|
|
|
|
// maps a Controller.key*Event event.text -> Controller.Hardware.Keyboard[name]
|
|
// eg: ('Page Up') === 'PgUp'
|
|
// eg: ('LEFT') === 'Left'
|
|
function eventKeyText2KeyboardName(text) {
|
|
if (eventKeyText2KeyboardName[text]) {
|
|
// use memoized value
|
|
return eventKeyText2KeyboardName[text];
|
|
}
|
|
var keyboardName = (text||'').toUpperCase().split(/[ _]/).map(function(WORD) {
|
|
return WORD.replace(/([A-Z])(\w*)/g, function(_, A, b) {
|
|
return (A.toUpperCase() + b.toLowerCase());
|
|
});
|
|
}).join('').replace('Page','Pg');
|
|
return eventKeyText2KeyboardName[text] = eventKeyText2KeyboardName[keyboardName] = keyboardName;
|
|
}
|
|
|
|
// maps a Controller.Hardware.Keyboard[name] -> Controller.key*Event event.text
|
|
// eg: ('PgUp') === 'PAGE UP'
|
|
// eg: ('Shift') === 'SHIFT'
|
|
function keyboardName2eventKeyText(keyName) {
|
|
if (keyboardName2eventKeyText[keyName]) {
|
|
// use memoized value
|
|
return keyboardName2eventKeyText[keyName];
|
|
}
|
|
var text = keyName.replace('Pg', 'Page');
|
|
var caseWords = text.match(/[A-Z][a-z0-9]+/g) || [ text ];
|
|
var eventText = caseWords.map(function(str) {
|
|
return str.toUpperCase();
|
|
}).join('_');
|
|
return keyboardName2eventKeyText[keyName] = eventText;
|
|
}
|
|
|
|
function initializeMappings(actionMap, driveKeyMap) {
|
|
_debugPrint('creating mapping');
|
|
var ref = ACTION_TRANSLATE_CAMERA_Z;
|
|
actionMap[ref.actionName] = actionMap[ref.actionID] = ref.driveKeyName;
|
|
actionMap.BoomIn = 'ZOOM';
|
|
actionMap.BoomOut = 'ZOOM';
|
|
|
|
Controller.getActionNames().sort().reduce(
|
|
function(out, name, index, arr) {
|
|
var actionKey = arr[index];
|
|
var actionID = Controller.findAction(name);
|
|
var value = actionID in out ? out[actionID] : _translateActionName(name, index);
|
|
if (value !== undefined) {
|
|
var prefix = (actionID in out ? '+++' : '---');
|
|
debugPrint(prefix + ' Action2DriveKeyName['+name+'('+actionID+')] = ' + value);
|
|
driveKeyMap[value] = driveKeyMap[value] || name;
|
|
}
|
|
out[name] = out[actionID] = out[actionKey] = value;
|
|
return out;
|
|
}, actionMap);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// mocks for litmus testing using Node.js command line tools
|
|
function _defineNodeJSMocks() {
|
|
/* eslint-disable no-global-assign */
|
|
DriveKeys = {
|
|
TRANSLATE_X: 12345
|
|
};
|
|
Controller = {
|
|
getActionNames: function() {
|
|
return Object.keys(this.Hardware.Actions);
|
|
},
|
|
findAction: function(name) {
|
|
return this.Hardware.Actions[name] || 4095;
|
|
},
|
|
Hardware: {
|
|
Actions: {
|
|
TranslateX: 54321
|
|
},
|
|
Application: {
|
|
Grounded: 1
|
|
},
|
|
Keyboard: {
|
|
A: 65
|
|
}
|
|
}
|
|
};
|
|
/* eslint-enable no-global-assign */
|
|
}
|