Skip to content

Commit 2f17070

Browse files
committed
readme
1 parent a844928 commit 2f17070

4 files changed

Lines changed: 61 additions & 31 deletions

File tree

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
1+
<div align="center">
2+
<img src="https://i.imgur.com/NrHcaGC.png" alt="flex 2">
3+
<br>
4+
</div>
5+
<br>
6+
17
## Flex 2
28

39
Flex 2 is a multi-purpose art and mapping editor for the Sega Megadrive. The original Flex was a web app, which gave it several limitations. A full rewrite for desktop opens up the ability to use real project files, as well as various other niceties.
410

11+
There is a fair amount of hidden behaviour in this application, reading this document is highly recommended before use.
12+
513
## UI
614

15+
16+
717
## Controls
818

19+
Most of the keyboard shortcuts are listed on the Mappings tab at the bottom. Some commands take a multiplier, so <kbd>32</kbd>+<kbd>Up</kbd> will moved the selected mappings 32 pixels up, or <kbd>8</kbd>+<kbd>n t</kbd> will add either new tiles.
20+
921
### Inputs
1022

1123
## Mapping Editor
@@ -24,4 +36,4 @@ Flex 2 is a multi-purpose art and mapping editor for the Sega Megadrive. The ori
2436

2537
## Download
2638

27-
https://github.com/kirjavascript/Flex2/releases
39+
The latest version can be found at: https://github.com/kirjavascript/Flex2/releases

flex2.idea

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,13 @@ change sprite scroll speed
2121
drawing mode fill !
2222
S - scroll to sprite
2323
s3k sonic mapping definition / conversion tools
24+
add flex.json to sonic 2 disassembly
2425
==
2526

2627
check version in documentation tab (move code)
27-
add flex.json to sonic 2 disassembly
28-
search (filter)
2928
logo / have default as logo?
30-
counts for commands
31-
real command modes
29+
markdown keyboard shortcuts
3230

3331
====
3432

35-
object collapse state persistance
3633
create new file | newFactory={(path)=>{}}

modules/controls/commands.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const commands = [
6262
},
6363
},
6464
{
65-
map: 'n t', name: 'New Tile', color: 'green',
65+
map: 'n t', name: 'New Tile', color: 'green', count: true,
6666
func: () => {
6767
environment.tiles.push(
6868
Array.from({length: 64}).fill((0|Math.random()*15)+1)
@@ -115,11 +115,11 @@ export const commands = [
115115

116116
[
117117
{
118-
map: 'mod+a', name: 'Select All',
118+
map: 'mod+a', name: 'Select All', noMultiplier: true,
119119
func: () => { mappingState.selectAll(); },
120120
},
121121
{
122-
map: 'mod+d', name: 'Select None',
122+
map: 'mod+d', name: 'Select None', noMultiplier: true,
123123
func: () => { mappingState.selectNone(); },
124124
},
125125
],
@@ -203,19 +203,19 @@ export const commands = [
203203

204204
[
205205
{
206-
map: 'e', name: 'Export PNG', color: 'blue',
206+
map: 'e', name: 'Export PNG', color: 'blue', noMultiplier: true,
207207
func: () => {
208208
exportPNG();
209209
},
210210
},
211211
{
212-
map: 'i', name: 'Import Over Sprite', color: 'blue',
212+
map: 'i', name: 'Import Over Sprite', color: 'blue', noMultiplier: true,
213213
func: () => {
214214
importImg();
215215
},
216216
},
217217
{
218-
map: 's', name: 'Import Spritesheet', color: 'blue',
218+
map: 's', name: 'Import Spritesheet', color: 'blue', noMultiplier: true,
219219
func: () => {
220220
importState.newImport();
221221
},
@@ -251,7 +251,7 @@ export const commands = [
251251
},
252252
},
253253
{
254-
map: 'd u', name: 'Delete Unused Tiles', color: 'red',
254+
map: 'd u', name: 'Delete Unused Tiles', color: 'red', noMultiplier: true,
255255
func: () => {
256256
mappingState.deleteUnusedTiles();
257257
},
@@ -262,18 +262,18 @@ export const commands = [
262262

263263
[
264264
{
265-
map: 'mod+z', name: 'Undo', color: 'magenta',
265+
map: 'mod+z', name: 'Undo', color: 'magenta', noMultiplier: true,
266266
func: () => { undo(); },
267267
},
268268
{
269-
map: 'mod+r', name: 'Redo', color: 'magenta',
269+
map: 'mod+r', name: 'Redo', color: 'magenta', noMultiplier: true,
270270
func: () => { redo(); },
271271
},
272272
],
273273

274274
[
275275
{
276-
map: 'r', name: 'Raw Editor', color: 'white',
276+
map: 'r', name: 'Raw Editor', color: 'white', noMultiplier: true,
277277
func: () => {
278278
mappingState.rawEditor.active = !mappingState.rawEditor.active;
279279
},
@@ -282,13 +282,13 @@ export const commands = [
282282

283283
[
284284
{
285-
map: 'm', name: '[mode]', color: 'orange',
285+
map: 'm', name: '[mode]', color: 'orange', noMultiplier: true,
286286
func: () => {
287287
mappingState.toggleMode();
288288
},
289289
},
290290
{
291-
map: 'D', name: '[dplcs]', color: 'orange',
291+
map: 'D', name: '[dplcs]', color: 'orange', noMultiplier: true,
292292
func: () => {
293293
mappingState.toggleDPLCs();
294294
},
@@ -306,53 +306,53 @@ export const commands = [
306306
func: () => { environment.config.currentSprite -= getDistance(); },
307307
},
308308
{
309-
map: '<', name: 'First Sprite', color: 'yellow',
309+
map: '<', name: 'First Sprite', color: 'yellow', noMultiplier: true,
310310
func: () => { environment.config.currentSprite = 0; },
311311
},
312312
{
313-
map: '>', name: 'Last Sprite', color: 'yellow',
313+
map: '>', name: 'Last Sprite', color: 'yellow', noMultiplier: true,
314314
func: () => { environment.config.currentSprite = environment.mappings.length -1; },
315315
},
316316
],
317317

318318
[
319319
{
320-
map: 'A', name: 'Autoarrange Tiles', color: 'yellow',
320+
map: 'A', name: 'Autoarrange Tiles', color: 'yellow', noMultiplier: true,
321321
func: () => { mappingState.arrangeTilesBySpriteOrder(); },
322322
},
323323
],
324324

325325

326326
[
327327
{
328-
map: 'u a', name: 'Unload Art', color: 'red',
328+
map: 'u a', name: 'Unload Art', color: 'red', noMultiplier: true,
329329
func: () => { environment.tiles.replace([]); },
330330
},
331331
{
332-
map: 'u m', name: 'Unload Mappings', color: 'red',
332+
map: 'u m', name: 'Unload Mappings', color: 'red', noMultiplier: true,
333333
func: () => {
334334
environment.mappings.replace([]);
335335
environment.config.dplcsEnabled &&
336336
environment.dplcs.replace([]);
337337
},
338338
},
339339
{
340-
map: 'u p', name: 'Unload Palettes', color: 'red',
340+
map: 'u p', name: 'Unload Palettes', color: 'red', noMultiplier: true,
341341
func: () => { environment.resetPalettes(); },
342342
},
343343
],
344344

345345
[
346346
{
347-
map: 't', name: 'Transparency', color: 'magenta',
347+
map: 't', name: 'Transparency', color: 'magenta', noMultiplier: true,
348348
func: () => { environment.config.transparency = !environment.config.transparency; },
349349
},
350350
{
351-
map: '=', name: 'Reset Pan/Zoom', color: 'magenta',
351+
map: '=', name: 'Reset Pan/Zoom', color: 'magenta', noMultiplier: true,
352352
func: () => { mappingState.resetPanAndZoom(); },
353353
},
354354
{
355-
map: 'g', name: 'Guidelines', color: 'magenta',
355+
map: 'g', name: 'Guidelines', color: 'magenta', noMultiplier: true,
356356
func: () => { mappingState.guidelines.enabled = !mappingState.guidelines.enabled; },
357357
},
358358
],

modules/controls/keyboard.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
11
import Mousetrap from 'mousetrap';
2+
import { environment } from '#store/environment';
23
import { commands } from './commands';
34
import flatten from 'lodash/flatten';
45

56
// load commands
67
flatten(commands)
7-
.forEach(({map, func, hasShift}) => {
8-
if (hasShift) {
9-
Mousetrap.bind([map, `shift+${map}`], func);
8+
.forEach((obj) => {
9+
if (obj.hasShift) {
10+
Mousetrap.bind([obj.map, `shift+${obj.map}`], () => doCommand(obj));
1011
}
1112
else {
12-
Mousetrap.bind(map, func);
13+
Mousetrap.bind(obj.map, () => doCommand(obj));
1314
}
1415
});
16+
17+
// handle multiplier
18+
let multiplier = '';
19+
Mousetrap.bind(['0','1','2','3','4','5','6','7','8','9'], (e) => {
20+
multiplier += String(e.key);
21+
});
22+
Mousetrap.bind('esc', () => {
23+
multiplier = '';
24+
});
25+
function doCommand(obj) {
26+
environment.doAction(() => {
27+
if (!obj.noMultiplier && multiplier) {
28+
for (let i = 0; i < +multiplier; i++) obj.func();
29+
multiplier = '';
30+
}
31+
else {
32+
obj.func();
33+
}
34+
});
35+
}

0 commit comments

Comments
 (0)