From 7e191d0babbcb144b918b5faad3174ba6fd0d74f Mon Sep 17 00:00:00 2001 From: Sascha Nitsch Date: Sat, 12 Mar 2022 21:44:58 +0100 Subject: [PATCH] added profile generator --- .gitignore | 5 + profilegenerator/Gruntfile.js | 66 ++ profilegenerator/html/index.html | 205 ++++++ profilegenerator/less/main.less | 46 ++ profilegenerator/package.json | 17 + profilegenerator/ts/ProfileGenerator.ts | 702 +++++++++++++++++++ profilegenerator/ts/init.ts | 12 + profilegenerator/ts/window.ts | 11 + profilegenerator/webroot/index.html | 887 ++++++++++++++++++++++++ 9 files changed, 1951 insertions(+) create mode 100644 profilegenerator/Gruntfile.js create mode 100644 profilegenerator/html/index.html create mode 100644 profilegenerator/less/main.less create mode 100644 profilegenerator/package.json create mode 100644 profilegenerator/ts/ProfileGenerator.ts create mode 100644 profilegenerator/ts/init.ts create mode 100644 profilegenerator/ts/window.ts create mode 100644 profilegenerator/webroot/index.html diff --git a/.gitignore b/.gitignore index 0babea1..8580a2b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,8 @@ /electronics/fp-info-cache /spec.d /html +profilegenerator/.tscache +profilegenerator/node_modules +profilegenerator/tmp +profilegenerator/package-lock.json +profilegenerator/ts/.baseDir.ts diff --git a/profilegenerator/Gruntfile.js b/profilegenerator/Gruntfile.js new file mode 100644 index 0000000..f5528ff --- /dev/null +++ b/profilegenerator/Gruntfile.js @@ -0,0 +1,66 @@ +module.exports = function(grunt) { + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + ts: { + default: { + src: ['ts/**/*.ts'], + outDir: 'tmp/', + options: { + module: 'none', + sourceMap: false, + target: 'es6', + rootDir: 'ts/' + } + }, + }, + concat: { + js: { + src: ['tmp/**/*.js'], + dest: 'tmp/bootstrap.out' + }, + dist: { + src: ['html/index.html'], + dest: 'webroot/index.html', + }, + options: { + process: true + } + }, + watch: { + jsbootstrapts: { + files: ['ts/**/*.ts'], + tasks: ['ts', 'concat'] + }, + html: { + files: ['html/*'], + tasks: ['concat'] + }, + lessdefault: { + files: ['less/*.less'], + tasks: ['less:default', 'concat'] + }, + }, + less: { + default: { + options: { + "strictImports": true, + "compress": true + }, + files: { + "tmp/default.css": "less/main.less", + } + }, + }, + }); + + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-less'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks("grunt-ts"); + + // Default task(s). + grunt.registerTask('default', ['less', 'ts', 'concat', 'watch']); + grunt.registerTask('release', ['less', 'ts', 'concat']); + +}; diff --git a/profilegenerator/html/index.html b/profilegenerator/html/index.html new file mode 100644 index 0000000..6f799ab --- /dev/null +++ b/profilegenerator/html/index.html @@ -0,0 +1,205 @@ + + + +Cimdit Profile generator + + + + + +
+ + +

+

+ +

+
+ + + \ No newline at end of file diff --git a/profilegenerator/less/main.less b/profilegenerator/less/main.less new file mode 100644 index 0000000..06990e4 --- /dev/null +++ b/profilegenerator/less/main.less @@ -0,0 +1,46 @@ +textarea { + width:100%; +} +#string { + height:5vh; +} + +.codeEditor, .lineCounter { + font-family: courier new, courier, monospace; + margin: 0; + padding: 10px 0; + height: 75vh; + border-radius: 0; + resize: none; + line-height: 1.2; + outline: none; + box-sizing: border-box; +} + +.codeEditor { + padding-left: calc(3.5rem + 5px); + width:100%; + background-color:#272822; + border-color:#272822; + color:#ffffff; +} + +.lineCounter { + display: flex; + border-color: transparent; + overflow-y: hidden; + text-align: right; + box-shadow: none; + color: #707070; + background-color: #d8d8d8; + position: absolute; + width: 3.5rem; + background-color:#3E3D32; + border-color:#3E3D32; + color:#928869; +} + +.lineCounter:focus-visible, +.codeEditor:focus-visible { + outline:none; + } diff --git a/profilegenerator/package.json b/profilegenerator/package.json new file mode 100644 index 0000000..471c403 --- /dev/null +++ b/profilegenerator/package.json @@ -0,0 +1,17 @@ +{ + "name": "profilegenerator", + "version": "1.0.0", + "description": "create profile string via browser", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "GrumpyDeveloper https://contentnation.net/grumpydevelop", + "license": "MIT", + "devDependencies": { + "grunt": "^1.4.1", + "grunt-contrib-concat": "^2.0.0", + "grunt-contrib-less": "^3.0.0", + "grunt-contrib-watch": "^1.1.0", + "grunt-ts": "^4.0.1" + } +} diff --git a/profilegenerator/ts/ProfileGenerator.ts b/profilegenerator/ts/ProfileGenerator.ts new file mode 100644 index 0000000..6938019 --- /dev/null +++ b/profilegenerator/ts/ProfileGenerator.ts @@ -0,0 +1,702 @@ +type ProfileJson = { + name: string; + customimage?: string; + mappedbuttons?: EntityJson[]; + mappedaxis?: EntityJson[]; + mappedrotary?: EntityJson[]; + macros?: Array; +} + +type EntityJson = { + source: number; + type: string; + target?: number; + axis?: number; + value?: number; + macro?: number; +} + +type EntityProfileString = { + bytes: number; + count: number; + string: string; +}; + +/** + * Main application class + */ +class ProfileGenerator { + private json : HTMLTextAreaElement; + private jsonCounter : HTMLTextAreaElement; + private generatejson : HTMLButtonElement; + private generatestring : HTMLButtonElement; + private error : HTMLParagraphElement; + private profile : HTMLTextAreaElement; + private lineCountCache: number; + + private profileEnum : Array = [ + "MAPPING_NONE", + "JOYSTICK_BUTTON", + "JOYSTICK_AXIS", + "MOUSE_BUTTON", + "MOUSE_REL_X_AXIS", + "MOUSE_REL_Y_AXIS", + "MOUSE_REL_WHEEL", + "NEXT_PROFILE", + "PREV_PROFILE", + "SWITCH_PROFILE", + "MACRO_PRESS", + "MACRO_RELEASE" + ]; + private macroEnum: Array = [ + "MACRO_NULL", + "MACRO_SPEED", + "MACRO_DELAY", + "MACRO_KEY_PRESS", + "MACRO_KEY_RELEASE", + "MACRO_JOY_PRESS", + "MACRO_JOY_RELEASE", + "MACRO_MOUSE_PRESS", + "MACRO_MOUSE_RELEASE", + "MACRO_MOUSE_WHEEL", + "MACRO_TYPE", + "MACRO_MOUSE_REL_X", + "MACRO_MOUSE_REL_Y", + "MACRO_MOUSE_REL_X_AXIS", + "MACRO_MOUSE_REL_Y_AXIS" + ]; + + private keyLookup = { + "KEY_RESERVED":0, + "KEY_ERROR_ROLLOVER":1, + "KEY_POST_FAIL":2, + "KEY_ERROR_UNDEFINED":3, + "KEY_A":4, + "KEY_B":5, + "KEY_C":6, + "KEY_D":7, + "KEY_E":8, + "KEY_F":9, + "KEY_G":10, + "KEY_H":11, + "KEY_I":12, + "KEY_J":13, + "KEY_K":14, + "KEY_L":15, + "KEY_M":16, + "KEY_N":17, + "KEY_O":18, + "KEY_P":19, + "KEY_Q":20, + "KEY_R":21, + "KEY_S":22, + "KEY_T":23, + "KEY_U":24, + "KEY_V":25, + "KEY_W":26, + "KEY_X":27, + "KEY_Y":28, + "KEY_Z":29, + "KEY_1":30, + "KEY_2":31, + "KEY_3":32, + "KEY_4":33, + "KEY_5":34, + "KEY_6":35, + "KEY_7":36, + "KEY_8":37, + "KEY_9":38, + "KEY_0":39, + "KEY_ENTER":40, + "KEY_RETURN":40, + "KEY_ESC":41, + "KEY_BACKSPACE":42, + "KEY_TAB":43, + "KEY_SPACE":44, + "KEY_MINUS":45, + "KEY_EQUAL":46, + "KEY_LEFT_BRACE":47, + "KEY_RIGHT_BRACE":48, + "KEY_BACKSLASH":49, + "KEY_NON_US_NUM":50, + "KEY_SEMICOLON":51, + "KEY_QUOTE":52, + "KEY_TILDE":53, + "KEY_COMMA":54, + "KEY_PERIOD":55, + "KEY_SLASH":56, + "KEY_CAPS_LOCK":0x39, + "KEY_F1":0x3A, + "KEY_F2":0x3B, + "KEY_F3":0x3C, + "KEY_F4":0x3D, + "KEY_F5":0x3E, + "KEY_F6":0x3F, + "KEY_F7":0x40, + "KEY_F8":0x41, + "KEY_F9":0x42, + "KEY_F10":0x43, + "KEY_F11":0x44, + "KEY_F12":0x45, + "KEY_PRINT":0x46, + "KEY_PRINTSCREEN":0x46, + "KEY_SCROLL_LOCK":0x47, + "KEY_PAUSE":0x48, + "KEY_INSERT":0x49, + "KEY_HOME":0x4A, + "KEY_PAGE_UP":0x4B, + "KEY_DELETE":0x4C, + "KEY_END":0x4D, + "KEY_PAGE_DOWN":0x4E, + "KEY_RIGHT_ARROW":0x4F, + "KEY_LEFT_ARROW":0x50, + "KEY_DOWN_ARROW":0x51, + "KEY_UP_ARROW":0x52, + "KEY_RIGHT":0x4F, + "KEY_LEFT":0x50, + "KEY_DOWN":0x51, + "KEY_UP":0x52, + "KEY_NUM_LOCK":0x53, + "KEYPAD_DIVIDE":0x54, + "KEYPAD_MULTIPLY":0x55, + "KEYPAD_SUBTRACT":0x56, + "KEYPAD_ADD":0x57, + "KEYPAD_ENTER":0x58, + "KEYPAD_1":0x59, + "KEYPAD_2":0x5A, + "KEYPAD_3":0x5B, + "KEYPAD_4":0x5C, + "KEYPAD_5":0x5D, + "KEYPAD_6":0x5E, + "KEYPAD_7":0x5F, + "KEYPAD_8":0x60, + "KEYPAD_9":0x61, + "KEYPAD_0":0x62, + "KEYPAD_DOT":0x63, + "KEY_NON_US":0x64, + "KEY_APPLICATION":0x65, + "KEY_MENU":0x65, + "KEY_POWER":0x66, + "KEY_PAD_EQUALS":0x67, + "KEY_F13":0x68, + "KEY_F14":0x69, + "KEY_F15":0x6A, + "KEY_F16":0x6B, + "KEY_F17":0x6C, + "KEY_F18":0x6D, + "KEY_F19":0x6E, + "KEY_F20":0x6F, + "KEY_F21":0x70, + "KEY_F22":0x71, + "KEY_F23":0x72, + "KEY_F24":0x73, + "KEY_EXECUTE":0x74, + "KEY_HELP":0x75, + "KEY_MENU2":0x76, + "KEY_SELECT":0x77, + "KEY_STOP":0x78, + "KEY_AGAIN":0x79, + "KEY_UNDO":0x7A, + "KEY_CUT":0x7B, + "KEY_COPY":0x7C, + "KEY_PASTE":0x7D, + "KEY_FIND":0x7E, + "KEY_MUTE":0x7F, + "KEY_VOLUME_MUTE":0x7F, + "KEY_VOLUME_UP":0x80, + "KEY_VOLUME_DOWN":0x81, + "KEY_LOCKING_CAPS_LOCK":0x82, + "KEY_LOCKING_NUM_LOCK":0x83, + "KEY_LOCKING_SCROLL_LOCK":0x84, + "KEYPAD_COMMA":0x85, + "KEYPAD_EQUAL_SIGN":0x86, + "KEY_INTERNATIONAL1":0x87, + "KEY_INTERNATIONAL2":0x88, + "KEY_INTERNATIONAL3":0x89, + "KEY_INTERNATIONAL4":0x8A, + "KEY_INTERNATIONAL5":0x8B, + "KEY_INTERNATIONAL6":0x8C, + "KEY_INTERNATIONAL7":0x8D, + "KEY_INTERNATIONAL8":0x8E, + "KEY_INTERNATIONAL9":0x8F, + "KEY_LANG1":0x90, + "KEY_LANG2":0x91, + "KEY_LANG3":0x92, + "KEY_LANG4":0x93, + "KEY_LANG5":0x94, + "KEY_LANG6":0x95, + "KEY_LANG7":0x96, + "KEY_LANG8":0x97, + "KEY_LANG9":0x98, + "KEY_ALTERNATE_ERASE":0x99, + "KEY_SYSREQ_ATTENTION":0x9A, + "KEY_CANCEL":0x9B, + "KEY_CLEAR":0x9C, + "KEY_PRIOR":0x9D, + "KEY_RETURN2":0x9E, + "KEY_SEPARATOR":0x9F, + "KEY_OUT":0xA0, + "KEY_OPER":0xA1, + "KEY_CLEAR_AGAIN":0xA2, + "KEY_CRSEL_PROPS":0xA3, + "KEY_EXSEL":0xA4, + "KEY_PAD_00":0xB0, + "KEY_PAD_000":0xB1, + "KEY_THOUSANDS_SEPARATOR":0xB2, + "KEY_DECIMAL_SEPARATOR":0xB3, + "KEY_CURRENCY_UNIT":0xB4, + "KEY_CURRENCY_SUB_UNIT":0xB5, + "KEYPAD_LEFT_BRACE":0xB6, + "KEYPAD_RIGHT_BRACE":0xB7, + "KEYPAD_LEFT_CURLY_BRACE":0xB8, + "KEYPAD_RIGHT_CURLY_BRACE":0xB9, + "KEYPAD_TAB":0xBA, + "KEYPAD_BACKSPACE":0xBB, + "KEYPAD_A":0xBC, + "KEYPAD_B":0xBD, + "KEYPAD_C":0xBE, + "KEYPAD_D":0xBF, + "KEYPAD_E":0xC0, + "KEYPAD_F":0xC1, + "KEYPAD_XOR":0xC2, + "KEYPAD_CARET":0xC3, + "KEYPAD_PERCENT":0xC4, + "KEYPAD_LESS_THAN":0xC5, + "KEYPAD_GREATER_THAN":0xC6, + "KEYPAD_AMPERSAND":0xC7, + "KEYPAD_DOUBLEAMPERSAND":0xC8, + "KEYPAD_PIPE":0xC9, + "KEYPAD_DOUBLEPIPE":0xCA, + "KEYPAD_COLON":0xCB, + "KEYPAD_POUND_SIGN":0xCC, + "KEYPAD_SPACE":0xCD, + "KEYPAD_AT_SIGN":0xCE, + "KEYPAD_EXCLAMATION_POINT":0xCF, + "KEYPAD_MEMORY_STORE":0xD0, + "KEYPAD_MEMORY_RECALL":0xD1, + "KEYPAD_MEMORY_CLEAR":0xD2, + "KEYPAD_MEMORY_ADD":0xD3, + "KEYPAD_MEMORY_SUBTRACT":0xD4, + "KEYPAD_MEMORY_MULTIPLY":0xD5, + "KEYPAD_MEMORY_DIVIDE":0xD6, + "KEYPAD_PLUS_MINUS":0xD7, + "KEYPAD_CLEAR":0xD8, + "KEYPAD_CLEAR_ENTRY":0xD9, + "KEYPAD_BINARY":0xDA, + "KEYPAD_OCTAL":0xDB, + "KEYPAD_DECIMAL":0xDC, + "KEYPAD_HEXADECIMAL":0xDD, + "KEY_LEFT_CTRL":0xE0, + "KEY_LEFT_SHIFT":0xE1, + "KEY_LEFT_ALT":0xE2, + "KEY_LEFT_GUI":0xE3, + "KEY_LEFT_WINDOWS":0xE3, + "KEY_RIGHT_CTRL":0xE4, + "KEY_RIGHT_SHIFT":0xE5, + "KEY_RIGHT_ALT":0xE6, + "KEY_RIGHT_GUI":0xE7, + "KEY_RIGHT_WINDOWS":0xE7, + }; + constructor() { + this.json = document.getElementById("json"); + this.jsonCounter = document.getElementById("jsoncounter"); + this.profile = document.getElementById("string"); + this.generatejson = document.getElementById("generatejson"); + this.generatestring = document.getElementById("generatestring"); + this.error = document.getElementById("error"); + this.generatestring.addEventListener("click", this.createProfile.bind(this)); + this.generatejson.addEventListener("click", this.createJson.bind(this)); + this.lineCountCache = 0; + this.json.addEventListener('scroll', () => { + this.jsonCounter.scrollTop = this.json.scrollTop; + this.jsonCounter.scrollLeft = this.json.scrollLeft; + }); + this.json.addEventListener('input', () => { + this.line_counter(); + }); + + this.line_counter(); + } + createProfile(event: Event) { + event.preventDefault(); + var input = this.json.value; + var json = {}; + try { + json = JSON.parse(input); + } catch (e) { + this.error.innerHTML = e.message; + return false; + } + var profiles = []; + var lengths = []; + var profileCount = 0; + for (var pNum in json) { + var p = this.parseProfile(json[pNum]) + profiles.push(p[1]); + lengths.push(p[0]); + ++profileCount; + } + profiles.unshift(this.hexString(profileCount)); + var length = 3; + for (var i = 0; i < lengths.length; ++i) { + length += lengths[i]; + } + profiles.unshift(this.hexString(length >> 8) + this.hexString(length & 255)); + this.profile.value = "cimdit:F" + profiles.join(""); + return false; + } + + hexString(input: number) : string { + if (input < 0) { + input += 256; + } + var hex = input.toString(16); + if (hex.length < 2) { + hex = "0" + hex; + } + return hex; + } + + parseProfile(json: Object) { + var out = ""; + var length = 2; + // get name + var tmp = json["name"]; + for (var pos in tmp) { + out += this.hexString(tmp.charCodeAt(pos)); + } + out += "00"; + length += out.length/2; + // custom image + if (json["customimage"]) { + out += "01"; + out += json["customimage"]; + length += 513; + } else { + out += "00"; + ++length; + } + // add buttons + if (json["mappedbuttons"] instanceof Array) { + var buttons = this.map(json["mappedbuttons"]); + out += this.hexString(buttons.count); + out += buttons.string; + length += buttons.bytes + 1; + } else { + out += "00"; + ++length; + } + // add axis + if (json["mappedaxis"] instanceof Array) { + var axis = this.map(json["mappedaxis"]); + out += this.hexString(axis.count); + out += axis.string; + length += axis.bytes + 1; + } else { + out += "00"; + ++length; + } + // add rotary + if (json["mappedrotary"] instanceof Array) { + var rotary = this.map(json["mappedrotary"]); + out += this.hexString(rotary.count); + out += rotary.string; + length += rotary.bytes + 1; + } else { + out += "00"; + ++length; + } + // add macro sequences + if (json["macros"] instanceof Array) { + var macro = this.createMacroString(json["macros"]); + out += this.hexString(macro.count); + out += macro.string; + length += macro.bytes + 1; + } else { + out += "00"; + ++length; + } + out = this.hexString(length >> 8) + this.hexString(length & 255) + out; + return [length, out]; + } + + map(entities: Array) : EntityProfileString { + var out =""; + var bytes = 0 + var count = 0; + for (var i = 0; i < entities.length; ++i) { + var entity = entities[i]; + try { + var tmp = this.hexString(entity.source); + tmp += this.hexString(this.profileEnum.indexOf(entity.type)); + if (entity.target !== undefined) { + tmp += this.hexString(entity.target); + } else if (entity.axis !== undefined) { + tmp += this.hexString(entity.axis); + } else if (entity.value !== undefined) { + tmp += this.hexString(entity.value); + } else if (entity.macro !== undefined) { + tmp += this.hexString(entity.macro); + } else { + tmp += "00"; + } + out += tmp; + bytes += 3; + ++count; + } catch(e) { + // print error + console.log(e); + } + } + return {bytes: bytes, count: count, string: out}; + } + + createMacroString(macros: any[][]) : EntityProfileString { + var bytes = 0; + var out = ""; + for (var i = 0; i < macros.length; ++i) { + var macro = macros[i]; + var append = false; + for (var j = 0; j < macro.length; ++j) { + var token = macro[j]; + if (token === "MACRO_SPEED" || token === "MACRO_MOUSE_WHEEL" || token.toString().match(/^MACRO_(JOY|MOUSE)_(PRESS|RELEASE)$/)) { // expect an unsigned integer variable + if (append) { + append = false; + out += "00"; + ++bytes; + } + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]); + bytes += 2; + } else if (token === "MACRO_DELAY") { // expect an 16 bit integer variable + if (append) { + append = false; + out += "00"; + ++bytes; + } + var value = macro[++j]; + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString((value >> 8)) + this.hexString(value & 255); + bytes += 3; + } else if (token.toString().match(/^MACRO_KEY_(PRESS|RELEASE)$/) || token === "MACRO_TYPE") { // followed by a list of keys/buttons + if (append) { + append = false; + out += "00"; + ++bytes; + } + out += this.hexString(this.macroEnum.indexOf(token)); + append = true; + ++bytes; + } else if (token === "MACRO_MOUSE_REL_X" || token === "MACRO_MOUSE_REL_Y") { // expect one integer values + if (append) { + append = false; + out += "00"; + ++bytes; + } + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]); + bytes +=2; + } else if (token === "MACRO_MOUSE_REL_X_AXIS" || token === "MACRO_MOUSE_REL_Y_AXIS") { // expect one two integer values, joystick axis and speed if axis != -1 + if (append) { + append = false; + out += "00"; + ++bytes; + } + if (macro[j + 1] == -1) { + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]); + bytes +=2; + } else { + out += this.hexString(this.macroEnum.indexOf(token)) + this.hexString(macro[++j]) + this.hexString(macro[++j]); + bytes +=3; + } + } else { + if (typeof(token) === "number") { + out += this.hexString(token); + ++bytes; + } else { + if (token.startsWith("KEY_")) { + out += this.hexString(this.keyLookup[token]); + ++bytes; + } else { + for (var k = 0; k < token.length; ++k) { + out += this.hexString(this.keyLookup["KEY_" + token[k].toUpperCase()]); + ++bytes; + } + } + } + } + } + if (append) { + append = false; + out += "00"; + ++bytes; + } + out += "00"; + ++bytes; + } + return {bytes: bytes, count: macros.length, string: out}; + } + + fromHexS(input: string) : number { + var ret = parseInt(input, 16); + if (ret>127) ret -= 256; + return ret; + } + fromHexU(input: string) : number { + return parseInt(input, 16); + } + createJson(event: Event) { + event.preventDefault(); + var string = this.profile.value; + // strip cimdit command + string = string.replace("cimdit:F",""); + var tokens = string.match(/.{1,2}/g); + // parse token list + // ignore first 2 entries (length) + tokens.shift(); + tokens.shift(); + var json : ProfileJson[]; + json = []; + var numProfile = this.fromHexU(tokens.shift()); + for (var i = 0; i < numProfile; ++i) { + json.push(this.createProfileFromTokens(tokens)); + } + this.json.value = JSON.stringify(json,null," "); + return false; + } + createProfileFromTokens(tokens) : ProfileJson { + // var bytes = tokens.shift() * 255 + tokens.shift() - 2; + tokens.shift(); tokens.shift(); + var name = ""; + var char: number; + do { + char = this.fromHexU(tokens.shift()); + if (char) + name += String.fromCharCode(char); + } while (char !== 0 && tokens.length > 0); + var ret:ProfileJson = {name: name}; + var customImage = tokens.shift(); + if (customImage != "00") { + var cu = ""; + for (var i = 0; i < 512; ++i) { + cu += tokens.shift(); + } + ret.customimage = cu; + } + var mappedButtons:EntityJson[] = []; + var numButtons = this.fromHexU(tokens.shift()); + for (var i = 0; i < numButtons; ++i) { + mappedButtons.push(this.createEntityFromTokens(tokens)); + } + ret.mappedbuttons = mappedButtons; + var mappedAxis:EntityJson[] = []; + var numAxis = this.fromHexU(tokens.shift()); + for (var i = 0; i < numAxis; ++i) { + mappedAxis.push(this.createEntityFromTokens(tokens)); + } + ret.mappedaxis = mappedAxis; + var mappedRotary:EntityJson[] = []; + var numRotary = this.fromHexU(tokens.shift()); + for (var i = 0; i < numRotary; ++i) { + mappedRotary.push(this.createEntityFromTokens(tokens)); + } + ret.mappedrotary = mappedRotary; + var macros : Array = []; + var numMacro = this.fromHexU(tokens.shift()); + for (var i = 0; i < numMacro; ++i) { + macros.push(this.createMacrosFromTokens(tokens)); + } + ret.macros = macros; + return ret; + } + createEntityFromTokens(tokens) :EntityJson{ + var entity: EntityJson = {source: this.fromHexU(tokens.shift()), type: this.profileEnum[this.fromHexU(tokens.shift())]}; + if (entity.type === 'JOYSTICK_BUTTON' || entity.type === 'MOUSE_BUTTON') { + entity.target = this.fromHexU(tokens.shift()); + } else if (entity.type === 'JOYSTICK_AXIS') { + entity.axis = this.fromHexU(tokens.shift()); + } else if (entity.type === 'MOUSE_REL_X_AXIS' || entity.type === 'MOUSE_REL_Y_AXIS' || entity.type === 'MOUSE_REL_WHEEL') { + entity.value = this.fromHexS(tokens.shift()); + } else if (entity.type === 'MACRO_PRESS' || entity.type === 'MACRO_RELEASE') { + entity.macro = this.fromHexU(tokens.shift()); + } else { + tokens.shift(); + } + return entity; + } + + getKey(input: number) : string { + return Object.keys(this.keyLookup).find(k=>this.keyLookup[k]===input); + } + + createMacrosFromTokens(tokens: Array) : Array { + var macro : Array = []; + do { + var token = this.macroEnum[this.fromHexU(tokens.shift())]; + if (token !== "MACRO_NULL") { + macro.push(token); + } + switch(token) { + case "MACRO_NULL": + break; + case "MACRO_SPEED": // read in 1 extra numberic value 8 bit + case "MACRO_JOY_PRESS": + case "MACRO_JOY_RELEASE": + case "MACRO_MOUSE_PRESS": + case "MACRO_MOUSE_RELEASE": + case "MACRO_MOUSE_WHEEL": + macro.push(this.fromHexU(tokens.shift())); + break; + case "MACRO_DELAY": // read in 1 extra numberic value 16 bit + macro.push((this.fromHexU(tokens.shift())<<8) + this.fromHexU(tokens.shift())); + break; + case "MACRO_KEY_PRESS": // one or more keys + case "MACRO_KEY_RELEASE": + case "MACRO_TYPE": + var next: number; + var tmp = ""; + do { + next = this.fromHexU(tokens.shift()); + if (next != 0) { + var k = this.getKey(next); + if (k.match(/^KEY_\S$/)) { + tmp += k[4].toLowerCase(); + } else { + if (tmp !== "") + macro.push(tmp); + tmp = ""; + macro.push(k); + } + } + } while (next != 0); + if (tmp !== "") { + macro.push(tmp); + } + break; + case "MACRO_MOUSE_REL_X": + case "MACRO_MOUSE_REL_Y": // one bytes + var next :number = this.fromHexS(tokens.shift()); + macro.push(next); + break; + case "MACRO_MOUSE_REL_X_AXIS": + case "MACRO_MOUSE_REL_Y_AXIS": // one or 2 bytes + var next :number = this.fromHexS(tokens.shift()); + macro.push(next); + if (next != -1) { + macro.push(this.fromHexS(tokens.shift())); + } + break; + } + } while (token !== "MACRO_NULL" && tokens.length > 0); + return macro; + } + + line_counter() { + var lineCount = this.json.value.split('\n').length; + var outarr = new Array(); + if (this.lineCountCache != lineCount) { + for (var x = 0; x < lineCount; x++) { + outarr[x] = (x + 1); + } + this.jsonCounter.value = outarr.join('\n'); + } + this.lineCountCache = lineCount; + } +} \ No newline at end of file diff --git a/profilegenerator/ts/init.ts b/profilegenerator/ts/init.ts new file mode 100644 index 0000000..d21054e --- /dev/null +++ b/profilegenerator/ts/init.ts @@ -0,0 +1,12 @@ +/// +/// +/** + * Main entry function + */ + +/// create our class as soon as the document is loaded +document.addEventListener("readystatechange", function(event: Event) { + if (!window.pg) { + window.pg = new ProfileGenerator(); + } +}); diff --git a/profilegenerator/ts/window.ts b/profilegenerator/ts/window.ts new file mode 100644 index 0000000..e95def3 --- /dev/null +++ b/profilegenerator/ts/window.ts @@ -0,0 +1,11 @@ +/// + +/** + * extend Window to make our global instance available (for debugging purposes) + */ +interface Window { + /** + * our instance + */ + pg: ProfileGenerator; +} diff --git a/profilegenerator/webroot/index.html b/profilegenerator/webroot/index.html new file mode 100644 index 0000000..45a0aab --- /dev/null +++ b/profilegenerator/webroot/index.html @@ -0,0 +1,887 @@ + + + +Cimdit Profile generator + + + + + +
+ + +

+

+ +

+
+ + + \ No newline at end of file