├── .gitignore ├── README.md ├── bin ├── dnd-to-gml │ ├── gminfo.png │ ├── gmvisualizer.css │ └── index.html └── gmvisualizer │ ├── gminfo.png │ ├── gmvisualizer.css │ ├── img │ ├── __minis.bat │ └── __split.bat │ └── index.html ├── dnd-to-gml-web.hxproj ├── dnd-to-gml.hxproj ├── gmvisualizer.hxproj └── src ├── Code.hx ├── Conf.hx ├── Info.hx ├── Main.hx ├── Node.hx ├── NodeType.hx ├── OutputMode.hx ├── StringReader.hx ├── app ├── DNDtoGML.hx └── DNDtoGMLjs.hx ├── data ├── BBStyle.hx ├── BuiltInConstants.hx ├── BuiltinFunctions.hx ├── BuiltinVariables.hx ├── DataActions.hx ├── DataEvents.hx ├── DataGML.hx ├── DataGMX.hx ├── DataInfo.hx └── GMCIcons.hx ├── matcher ├── Match.hx ├── MatchNode.hx └── MatchResult.hx └── types ├── NodeAction.hx ├── NodeBracket.hx ├── NodeClose.hx ├── NodeComment.hx ├── NodeEvent.hx ├── NodeHeader.hx ├── NodeOpen.hx ├── NodeSeparator.hx ├── NodeText.hx ├── code ├── NodeCode.hx ├── NodeCodeBlock.hx ├── NodeCodeRaw.hx └── NodeCodeScript.hx └── gmx ├── NodeGmxAction.hx ├── NodeGmxComment.hx ├── NodeGmxEvent.hx └── NodeGmxObject.hx /.gitignore: -------------------------------------------------------------------------------- 1 | # Primary script: 2 | bin/*/script.js 3 | # Packaged icons and stylesheet: 4 | bin/*/*.zip 5 | # 6 | bin/img/*.png 7 | # 8 | bin/bin.zip 9 | # 10 | cs/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GameMaker' Visualizer is a program that manipulates "object information" output from YoYo Games' GameMaker (both Studio and older versions) to produce a variety of outputs. 2 | 3 | You can check out the live version (and/or support the development) via [project's itch.io page](http://yellowafterlife.itch.io/gmvisualizer). 4 | 5 | ### Usage 6 | Instructions vary depending on the area of the interest. 7 | * If using BB mode for highlighting code, no additional setup or configuration is needed - the program will output a bunch of tags which will function fine on majority of forums and wbsites with BB/UBB code support. 8 | 9 | If you want to also display DnD icons, you will need to download the provided `pkg.zip`, upload the icon directory (`img`) containing DnD icons somewhere, and set the Icon URL format string to point to that location. Depending on the particular BB code format, you may also need to change several options to match the expected format. 10 | 11 | * If you want to display snippets of DnD or GML on a site/blog, you'll need to upload `gminfo.png` and `gmvisualizer.css` to your site, and include the CSS file on the pages of interest. Stylesheet can be customized to fit the blog theme, obviously. 12 | 13 | * For converting DnD blocks to GML, no additional setup is required. Code is output in "object information" format and displayed in highlighted form in the preview box for convenience. 14 | 15 | ### Special syntax 16 | For quick use as a highlighter for code snippets, I have included two "special cases" in the program's algorithm: 17 | 18 | Inserting a single expression preceded with "```" will highlight it as an inline expression. 19 | 20 | Inserting a piece of code with first line containing nothing but "```" will highlight it as a multi-line snippet (bearing similarity to "execute code" block but having no icon/indentation). 21 | 22 | ### Notes on source code 23 | The primary purpose of this repository is to allow anyone interested (and/or familiar with [Haxe](http://haxe.org/)) to peek at the program's structure or take a shot at modifying it to do new tricks. 24 | 25 | Program is kept largely modular - at most times you would want to create a new `Info` instance, `readString` a snippet into it, and `print` it into one of the formats supported. Currently setup is done via a static `Conf` class. `Main` class can be used as example of usage. 26 | 27 | While the `Main` class will only compile under JS target, the rest of the source has no platform-specific references and should compile fine under the most platforms. 28 | 29 | ## License 30 | GameMaker' Visualizer is licensed under [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/) license. 31 | -------------------------------------------------------------------------------- /bin/dnd-to-gml/gminfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YAL-GameMaker-Tools/GMVisualizer/51d018f48098cb42772507780c4c86d0e2900503/bin/dnd-to-gml/gminfo.png -------------------------------------------------------------------------------- /bin/dnd-to-gml/gmvisualizer.css: -------------------------------------------------------------------------------- 1 | .gminfo { 2 | background: white; 3 | border: 1px solid #d0d0d0; 4 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 5 | padding: 4px !important; 6 | margin-top: 4px; 7 | } 8 | /** object info header */ 9 | .gminfo h2 { 10 | font-size: 112.5%; 11 | margin-top: 4px; 12 | margin-bottom: 2px; 13 | border-bottom: 1px solid #ddd; 14 | padding-bottom: 2px; 15 | } 16 | .gminfo span.event-icon, .gminfo span.action-icon { 17 | background-image: url(gminfo.png); 18 | } 19 | .gminfo .event-icon { 20 | float: left; 21 | width: 16px; 22 | height: 16px; 23 | margin-right: 4px; 24 | } 25 | .gminfo .action-icon { 26 | float: left; 27 | width: 24px; 28 | height: 24px; 29 | margin-right: 4px; 30 | } 31 | .gminfo img.action-icon { 32 | display: inline-block; 33 | vertical-align: middle; 34 | } 35 | .gminfo span.action-icon { 36 | overflow: hidden; 37 | text-indent: -9999px; 38 | } 39 | .gminfo p, .gminfo ul { 40 | margin: 0; 41 | padding-left: 24px; 42 | } 43 | .gminfo ul, .gminfo li { 44 | list-style: none; 45 | } 46 | .gminfo li { 47 | margin: 2px 0; 48 | } 49 | .gminfo div { 50 | margin-bottom: 2px; 51 | } 52 | .gminfo .event { 53 | margin-top: 6px; 54 | } 55 | .gminfo .event > p { 56 | padding-left: 0; 57 | line-height: 16px; 58 | border-bottom: 1px solid #ddd; 59 | padding-bottom: 2px; 60 | font-weight: bold; 61 | } 62 | .gminfo .event > ul { 63 | padding-left: 16px; 64 | padding-bottom: 4px; 65 | padding-top: 2px; 66 | margin-bottom: 0; 67 | } 68 | /** action block container */ 69 | .gminfo .action { 70 | line-height: 24px; 71 | } 72 | /** "relative" keyword */ 73 | .gminfo .relative { 74 | color: #080; 75 | } 76 | /** "not" keyword */ 77 | .gminfo .not { 78 | color: #080; 79 | } 80 | /** resource index */ 81 | .gminfo .ri { 82 | color: rgb(0, 120, 170); 83 | } 84 | /** a word from a [] set */ 85 | .gminfo .set { 86 | color: #080; 87 | } 88 | /** a small box representing a color. decimal value is hidden inside. */ 89 | .gminfo .colorbox { 90 | width: 14px; 91 | height: 14px; 92 | border: 1px solid #444; 93 | text-indent: -9999px; 94 | display: inline-block; 95 | overflow: hidden; 96 | position: relative; 97 | top: 3px; 98 | } 99 | /** "for other object" / "for all *" prefix */ 100 | .gminfo .with { 101 | color: #777; 102 | } 103 | 104 | .gminfo .comment { 105 | font-style: italic; 106 | color: #777; 107 | } 108 | .gminfo .comment > .prefix { 109 | width: 0; 110 | text-indent: -9999px; 111 | display: inline-block; 112 | } 113 | /* Code ahead */ 114 | .gminfo .code.mono { 115 | font-family: Consolas, monospace; 116 | font-size: 12px; 117 | line-height: 1.25; 118 | margin: 0; 119 | } 120 | .gminfo .action > .code.mono { 121 | margin-left: 28px; 122 | } 123 | /** */ 124 | .gminfo .code .kw, .gminfo .code .sp { 125 | color: #008; 126 | font-weight: bold; 127 | } 128 | /** comments */ 129 | .gminfo .code .co { color: #888; } 130 | /** numbers */ 131 | .gminfo .code .nu { color: #00F; } 132 | /** hex numbers */ 133 | .gminfo .code .nx { color: #00F; } 134 | /** strings */ 135 | .gminfo .code .st { color: #00F; } 136 | /** resource indexes */ 137 | .gminfo .code .ri { color: #0078AA; } 138 | /** standard/built-in variable */ 139 | .gminfo .code .sv { color: #800; } 140 | /** standard/built-in function */ 141 | .gminfo .code .sf { color: #800; } 142 | /** user-defined variable name */ 143 | .gminfo .code .uv { color: #408; } 144 | /** user-defined script/function */ 145 | .gminfo .code .uf { color: #808; } 146 | /** user-defined field (inst.field) */ 147 | .gminfo .code .fd { color: #408; } 148 | /** preprocessor */ 149 | .gminfo .code .pp { color: #0078AA; } 150 | /** trailing code in GMX */ 151 | .gminfo .code .error { color: rgb(250,50,50); } -------------------------------------------------------------------------------- /bin/dnd-to-gml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DnD to GML 6 | 7 | 8 | 94 | 95 | 96 | 112 | 113 | 118 | 119 | 127 |
97 | 102 | 103 | 104 | by YellowAfterlife 105 | 106 | Save output 107 | · 108 | Offline/multi-file version 109 | · 110 | Donate 111 |
114 | 115 | 116 | 117 |
120 |
121 |
122 | Visualization of converted object will be displayed here. 123 |
124 |
125 |
126 |
128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /bin/gmvisualizer/gminfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YAL-GameMaker-Tools/GMVisualizer/51d018f48098cb42772507780c4c86d0e2900503/bin/gmvisualizer/gminfo.png -------------------------------------------------------------------------------- /bin/gmvisualizer/gmvisualizer.css: -------------------------------------------------------------------------------- 1 | .gminfo { 2 | background: white; 3 | border: 1px solid #d0d0d0; 4 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); 5 | padding: 4px !important; 6 | margin-top: 4px; 7 | } 8 | /** object info header */ 9 | .gminfo h2 { 10 | font-size: 112.5%; 11 | margin-top: 4px; 12 | margin-bottom: 2px; 13 | border-bottom: 1px solid #ddd; 14 | padding-bottom: 2px; 15 | } 16 | .gminfo span.event-icon, .gminfo span.action-icon { 17 | background-image: url(gminfo.png); 18 | } 19 | .gminfo .event-icon { 20 | float: left; 21 | width: 16px; 22 | height: 16px; 23 | margin-right: 4px; 24 | } 25 | .gminfo .action-icon { 26 | float: left; 27 | width: 24px; 28 | height: 24px; 29 | margin-right: 4px; 30 | } 31 | .gminfo img.action-icon { 32 | display: inline-block; 33 | vertical-align: middle; 34 | } 35 | .gminfo span.action-icon { 36 | overflow: hidden; 37 | text-indent: -9999px; 38 | } 39 | .gminfo p, .gminfo ul { 40 | margin: 0; 41 | padding-left: 24px; 42 | } 43 | .gminfo ul, .gminfo li { 44 | list-style: none; 45 | } 46 | .gminfo li { 47 | margin: 2px 0; 48 | } 49 | .gminfo div { 50 | margin-bottom: 2px; 51 | } 52 | .gminfo .event { 53 | margin-top: 6px; 54 | } 55 | .gminfo .event > p { 56 | padding-left: 0; 57 | line-height: 16px; 58 | border-bottom: 1px solid #ddd; 59 | padding-bottom: 2px; 60 | font-weight: bold; 61 | } 62 | .gminfo .event > ul { 63 | padding-left: 16px; 64 | padding-bottom: 4px; 65 | padding-top: 2px; 66 | margin-bottom: 0; 67 | } 68 | /** action block container */ 69 | .gminfo .action { 70 | line-height: 24px; 71 | } 72 | /** "relative" keyword */ 73 | .gminfo .relative { 74 | color: #080; 75 | } 76 | /** "not" keyword */ 77 | .gminfo .not { 78 | color: #080; 79 | } 80 | /** resource index */ 81 | .gminfo .ri { 82 | color: rgb(0, 120, 170); 83 | } 84 | /** a word from a [] set */ 85 | .gminfo .set { 86 | color: #080; 87 | } 88 | /** a small box representing a color. decimal value is hidden inside. */ 89 | .gminfo .colorbox { 90 | width: 14px; 91 | height: 14px; 92 | border: 1px solid #444; 93 | text-indent: -9999px; 94 | display: inline-block; 95 | overflow: hidden; 96 | position: relative; 97 | top: 3px; 98 | } 99 | /** "for other object" / "for all *" prefix */ 100 | .gminfo .with { 101 | color: #777; 102 | } 103 | 104 | .gminfo .comment { 105 | font-style: italic; 106 | color: #777; 107 | } 108 | .gminfo .comment > .prefix { 109 | width: 0; 110 | text-indent: -9999px; 111 | display: inline-block; 112 | } 113 | /* Code ahead */ 114 | .gminfo .code.mono { 115 | font-family: Consolas, monospace; 116 | font-size: 12px; 117 | line-height: 1.25; 118 | margin: 0; 119 | } 120 | .gminfo .action > .code.mono { 121 | margin-left: 28px; 122 | } 123 | /** */ 124 | .gminfo .code .kw, .gminfo .code .sp { 125 | color: #008; 126 | font-weight: bold; 127 | } 128 | /** comments */ 129 | .gminfo .code .co { color: #888; } 130 | /** numbers */ 131 | .gminfo .code .nu { color: #00F; } 132 | /** hex numbers */ 133 | .gminfo .code .nx { color: #00F; } 134 | /** strings */ 135 | .gminfo .code .st { color: #00F; } 136 | /** resource indexes */ 137 | .gminfo .code .ri { color: #0078AA; } 138 | /** standard/built-in variable */ 139 | .gminfo .code .sv { color: #800; } 140 | /** standard/built-in function */ 141 | .gminfo .code .sf { color: #800; } 142 | /** user-defined variable name */ 143 | .gminfo .code .uv { color: #408; } 144 | /** user-defined script/function */ 145 | .gminfo .code .uf { color: #808; } 146 | /** user-defined field (inst.field) */ 147 | .gminfo .code .fd { color: #408; } 148 | /** preprocessor */ 149 | .gminfo .code .pp { color: #0078AA; } 150 | /** trailing code in GMX */ 151 | .gminfo .code .error { color: rgb(250,50,50); } -------------------------------------------------------------------------------- /bin/gmvisualizer/img/__split.bat: -------------------------------------------------------------------------------- 1 | rem types: 2 | convert ../gminfo.png -crop 16x16+0+384 t0.png 3 | convert ../gminfo.png -crop 16x16+16+384 t1.png 4 | convert ../gminfo.png -crop 16x16+32+384 t2.png 5 | convert ../gminfo.png -crop 16x16+48+384 t3.png 6 | convert ../gminfo.png -crop 16x16+64+384 t4.png 7 | convert ../gminfo.png -crop 16x16+80+384 t5.png 8 | convert ../gminfo.png -crop 16x16+96+384 t6.png 9 | convert ../gminfo.png -crop 16x16+112+384 t7.png 10 | convert ../gminfo.png -crop 16x16+128+384 t8.png 11 | convert ../gminfo.png -crop 16x16+144+384 t9.png 12 | convert ../gminfo.png -crop 16x16+160+384 t10.png 13 | convert ../gminfo.png -crop 16x16+176+384 t11.png 14 | rem actions: 15 | convert ../gminfo.png -crop 24x24+0+0 000.png 16 | convert ../gminfo.png -crop 24x24+32+0 001.png 17 | convert ../gminfo.png -crop 24x24+64+0 002.png 18 | convert ../gminfo.png -crop 24x24+96+0 003.png 19 | convert ../gminfo.png -crop 24x24+128+0 004.png 20 | convert ../gminfo.png -crop 24x24+160+0 005.png 21 | convert ../gminfo.png -crop 24x24+192+0 006.png 22 | convert ../gminfo.png -crop 24x24+224+0 007.png 23 | convert ../gminfo.png -crop 24x24+256+0 008.png 24 | convert ../gminfo.png -crop 24x24+288+0 009.png 25 | convert ../gminfo.png -crop 24x24+320+0 010.png 26 | convert ../gminfo.png -crop 24x24+352+0 011.png 27 | convert ../gminfo.png -crop 24x24+384+0 012.png 28 | convert ../gminfo.png -crop 24x24+416+0 013.png 29 | convert ../gminfo.png -crop 24x24+448+0 014.png 30 | convert ../gminfo.png -crop 24x24+480+0 015.png 31 | convert ../gminfo.png -crop 24x24+512+0 016.png 32 | convert ../gminfo.png -crop 24x24+544+0 017.png 33 | convert ../gminfo.png -crop 24x24+0+32 100.png 34 | convert ../gminfo.png -crop 24x24+32+32 101.png 35 | convert ../gminfo.png -crop 24x24+64+32 102.png 36 | convert ../gminfo.png -crop 24x24+96+32 103.png 37 | convert ../gminfo.png -crop 24x24+128+32 104.png 38 | convert ../gminfo.png -crop 24x24+160+32 105.png 39 | convert ../gminfo.png -crop 24x24+192+32 106.png 40 | convert ../gminfo.png -crop 24x24+224+32 107.png 41 | convert ../gminfo.png -crop 24x24+256+32 108.png 42 | convert ../gminfo.png -crop 24x24+288+32 109.png 43 | convert ../gminfo.png -crop 24x24+320+32 110.png 44 | convert ../gminfo.png -crop 24x24+352+32 111.png 45 | convert ../gminfo.png -crop 24x24+384+32 112.png 46 | convert ../gminfo.png -crop 24x24+416+32 113.png 47 | convert ../gminfo.png -crop 24x24+448+32 114.png 48 | convert ../gminfo.png -crop 24x24+480+32 115.png 49 | convert ../gminfo.png -crop 24x24+512+32 116.png 50 | convert ../gminfo.png -crop 24x24+544+32 117.png 51 | convert ../gminfo.png -crop 24x24+0+64 200.png 52 | convert ../gminfo.png -crop 24x24+32+64 201.png 53 | convert ../gminfo.png -crop 24x24+64+64 202.png 54 | convert ../gminfo.png -crop 24x24+96+64 203.png 55 | convert ../gminfo.png -crop 24x24+128+64 204.png 56 | convert ../gminfo.png -crop 24x24+160+64 205.png 57 | convert ../gminfo.png -crop 24x24+192+64 206.png 58 | convert ../gminfo.png -crop 24x24+224+64 207.png 59 | convert ../gminfo.png -crop 24x24+256+64 208.png 60 | convert ../gminfo.png -crop 24x24+288+64 209.png 61 | convert ../gminfo.png -crop 24x24+320+64 210.png 62 | convert ../gminfo.png -crop 24x24+352+64 211.png 63 | convert ../gminfo.png -crop 24x24+384+64 212.png 64 | convert ../gminfo.png -crop 24x24+416+64 213.png 65 | convert ../gminfo.png -crop 24x24+448+64 214.png 66 | convert ../gminfo.png -crop 24x24+480+64 215.png 67 | convert ../gminfo.png -crop 24x24+512+64 216.png 68 | convert ../gminfo.png -crop 24x24+544+64 217.png 69 | convert ../gminfo.png -crop 24x24+0+96 300.png 70 | convert ../gminfo.png -crop 24x24+32+96 301.png 71 | convert ../gminfo.png -crop 24x24+64+96 302.png 72 | convert ../gminfo.png -crop 24x24+96+96 303.png 73 | convert ../gminfo.png -crop 24x24+128+96 304.png 74 | convert ../gminfo.png -crop 24x24+160+96 305.png 75 | convert ../gminfo.png -crop 24x24+192+96 306.png 76 | convert ../gminfo.png -crop 24x24+224+96 307.png 77 | convert ../gminfo.png -crop 24x24+256+96 308.png 78 | convert ../gminfo.png -crop 24x24+288+96 309.png 79 | convert ../gminfo.png -crop 24x24+320+96 310.png 80 | convert ../gminfo.png -crop 24x24+352+96 311.png 81 | convert ../gminfo.png -crop 24x24+384+96 312.png 82 | convert ../gminfo.png -crop 24x24+416+96 313.png 83 | convert ../gminfo.png -crop 24x24+448+96 314.png 84 | convert ../gminfo.png -crop 24x24+480+96 315.png 85 | convert ../gminfo.png -crop 24x24+512+96 316.png 86 | convert ../gminfo.png -crop 24x24+544+96 317.png 87 | convert ../gminfo.png -crop 24x24+0+128 400.png 88 | convert ../gminfo.png -crop 24x24+32+128 401.png 89 | convert ../gminfo.png -crop 24x24+64+128 402.png 90 | convert ../gminfo.png -crop 24x24+96+128 403.png 91 | convert ../gminfo.png -crop 24x24+128+128 404.png 92 | convert ../gminfo.png -crop 24x24+160+128 405.png 93 | convert ../gminfo.png -crop 24x24+192+128 406.png 94 | convert ../gminfo.png -crop 24x24+224+128 407.png 95 | convert ../gminfo.png -crop 24x24+256+128 408.png 96 | convert ../gminfo.png -crop 24x24+288+128 409.png 97 | convert ../gminfo.png -crop 24x24+320+128 410.png 98 | convert ../gminfo.png -crop 24x24+352+128 411.png 99 | convert ../gminfo.png -crop 24x24+384+128 412.png 100 | convert ../gminfo.png -crop 24x24+416+128 413.png 101 | convert ../gminfo.png -crop 24x24+448+128 414.png 102 | convert ../gminfo.png -crop 24x24+480+128 415.png 103 | convert ../gminfo.png -crop 24x24+512+128 416.png 104 | convert ../gminfo.png -crop 24x24+544+128 417.png 105 | convert ../gminfo.png -crop 24x24+0+160 500.png 106 | convert ../gminfo.png -crop 24x24+32+160 501.png 107 | convert ../gminfo.png -crop 24x24+64+160 502.png 108 | convert ../gminfo.png -crop 24x24+96+160 503.png 109 | convert ../gminfo.png -crop 24x24+128+160 504.png 110 | convert ../gminfo.png -crop 24x24+160+160 505.png 111 | convert ../gminfo.png -crop 24x24+192+160 506.png 112 | convert ../gminfo.png -crop 24x24+224+160 507.png 113 | convert ../gminfo.png -crop 24x24+256+160 508.png 114 | convert ../gminfo.png -crop 24x24+288+160 509.png 115 | convert ../gminfo.png -crop 24x24+320+160 510.png 116 | convert ../gminfo.png -crop 24x24+352+160 511.png 117 | convert ../gminfo.png -crop 24x24+384+160 512.png 118 | convert ../gminfo.png -crop 24x24+416+160 513.png 119 | convert ../gminfo.png -crop 24x24+448+160 514.png 120 | convert ../gminfo.png -crop 24x24+480+160 515.png 121 | convert ../gminfo.png -crop 24x24+512+160 516.png 122 | convert ../gminfo.png -crop 24x24+544+160 517.png 123 | convert ../gminfo.png -crop 24x24+0+192 600.png 124 | convert ../gminfo.png -crop 24x24+32+192 601.png 125 | convert ../gminfo.png -crop 24x24+64+192 602.png 126 | convert ../gminfo.png -crop 24x24+96+192 603.png 127 | convert ../gminfo.png -crop 24x24+128+192 604.png 128 | convert ../gminfo.png -crop 24x24+160+192 605.png 129 | convert ../gminfo.png -crop 24x24+192+192 606.png 130 | convert ../gminfo.png -crop 24x24+224+192 607.png 131 | convert ../gminfo.png -crop 24x24+256+192 608.png 132 | convert ../gminfo.png -crop 24x24+288+192 609.png 133 | convert ../gminfo.png -crop 24x24+320+192 610.png 134 | convert ../gminfo.png -crop 24x24+352+192 611.png 135 | convert ../gminfo.png -crop 24x24+384+192 612.png 136 | convert ../gminfo.png -crop 24x24+416+192 613.png 137 | convert ../gminfo.png -crop 24x24+448+192 614.png 138 | convert ../gminfo.png -crop 24x24+480+192 615.png 139 | convert ../gminfo.png -crop 24x24+512+192 616.png 140 | convert ../gminfo.png -crop 24x24+544+192 617.png 141 | convert ../gminfo.png -crop 24x24+0+224 700.png 142 | convert ../gminfo.png -crop 24x24+32+224 701.png 143 | convert ../gminfo.png -crop 24x24+64+224 702.png 144 | convert ../gminfo.png -crop 24x24+96+224 703.png 145 | convert ../gminfo.png -crop 24x24+128+224 704.png 146 | convert ../gminfo.png -crop 24x24+160+224 705.png 147 | convert ../gminfo.png -crop 24x24+192+224 706.png 148 | convert ../gminfo.png -crop 24x24+224+224 707.png 149 | convert ../gminfo.png -crop 24x24+256+224 708.png 150 | convert ../gminfo.png -crop 24x24+288+224 709.png 151 | convert ../gminfo.png -crop 24x24+320+224 710.png 152 | convert ../gminfo.png -crop 24x24+352+224 711.png 153 | convert ../gminfo.png -crop 24x24+384+224 712.png 154 | convert ../gminfo.png -crop 24x24+416+224 713.png 155 | convert ../gminfo.png -crop 24x24+448+224 714.png 156 | convert ../gminfo.png -crop 24x24+480+224 715.png 157 | convert ../gminfo.png -crop 24x24+512+224 716.png 158 | convert ../gminfo.png -crop 24x24+544+224 717.png 159 | convert ../gminfo.png -crop 24x24+0+256 800.png 160 | convert ../gminfo.png -crop 24x24+32+256 801.png 161 | convert ../gminfo.png -crop 24x24+64+256 802.png 162 | convert ../gminfo.png -crop 24x24+96+256 803.png 163 | convert ../gminfo.png -crop 24x24+128+256 804.png 164 | convert ../gminfo.png -crop 24x24+160+256 805.png 165 | convert ../gminfo.png -crop 24x24+192+256 806.png 166 | convert ../gminfo.png -crop 24x24+224+256 807.png 167 | convert ../gminfo.png -crop 24x24+256+256 808.png 168 | convert ../gminfo.png -crop 24x24+288+256 809.png 169 | convert ../gminfo.png -crop 24x24+320+256 810.png 170 | convert ../gminfo.png -crop 24x24+352+256 811.png 171 | convert ../gminfo.png -crop 24x24+384+256 812.png 172 | convert ../gminfo.png -crop 24x24+416+256 813.png 173 | convert ../gminfo.png -crop 24x24+448+256 814.png 174 | convert ../gminfo.png -crop 24x24+480+256 815.png 175 | convert ../gminfo.png -crop 24x24+512+256 816.png 176 | convert ../gminfo.png -crop 24x24+544+256 817.png -------------------------------------------------------------------------------- /bin/gmvisualizer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GameMaker' Visualizer 6 | 7 | 8 | 75 | 76 |
77 | 78 |
79 | Print: 80 | 81 | 82 | 83 | 84 | 85 | 86 | Preview: 87 |
88 |
89 | Settings: 90 |
91 |

92 | Definitive Resource Prefixes: 93 |
94 |

95 |

96 | 97 | BB code options: 98 |

130 |

131 |

132 | 133 | GML generator options: 134 |

147 |

148 |
149 |
150 | Program by YellowAfterlife (Twitter · Tumblr · VK). GameMaker © YoYo Games. 151 | Licenced Creative Commons License 152 |
153 | 154 |
155 | 156 | -------------------------------------------------------------------------------- /dnd-to-gml-web.hxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /dnd-to-gml.hxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /gmvisualizer.hxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/Code.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class Code { 8 | public static var isFunc:Map; 9 | public static var isVar:Map; 10 | public static var isInst:Map; 11 | public static var isStd:Map; 12 | public static var resPfx:Array = []; 13 | public static var end:String = null; 14 | public static function init() { 15 | var t:Array, m:Map; 16 | // 17 | isFunc = m = new Map(); 18 | t = data.BuiltinFunctions.get().split("|"); 19 | for (s in t) m[s] = true; 20 | // 21 | isVar = m = new Map(); 22 | isInst = new Map(); 23 | t = data.BuiltinVariables.global().split("|"); 24 | for (s in t) m[s] = true; 25 | t = data.BuiltinVariables.instance().split("|"); 26 | for (s in t) { 27 | m[s] = true; 28 | isInst[s] = true; 29 | } 30 | t = data.BuiltInConstants.get().split("|"); 31 | for (s in t) m[s] = true; 32 | // 33 | isStd = m = new Map(); 34 | for (s in isVar.keys()) m[s] = isVar[s]; 35 | for (s in isFunc.keys()) m[s] = isFunc[s]; 36 | } 37 | public static var multiline:Bool = false; 38 | public static var node:CodeNode; 39 | public static function readNode(s:StringReader, list:Array):Bool { 40 | var ofs:Int; 41 | inline function add(v:CodeNode):Bool { 42 | list.push(node = v); 43 | return false; 44 | } 45 | inline function part(start:Int, end:Int):String { 46 | return s.str.substring(start, end); 47 | } 48 | while (!s.eof) { 49 | var last:Int = s.pos; 50 | var c:Int = s.charAt(s.pos++); 51 | inline function addHex() { 52 | while (s.cond) { 53 | switch (s.charAt(++s.pos)) { 54 | case"0".code, "1".code, "2".code, "3".code, "4".code, 55 | "5".code, "6".code, "7".code, "8".code, "9".code, 56 | "a".code, "b".code, "c".code, "d".code, "e".code, "f".code, 57 | "A".code, "B".code, "C".code, "D".code, "E".code, "F".code: 58 | continue; 59 | default: 60 | } 61 | break; 62 | } 63 | return add(CoNumber(part(last, s.pos), CnHexadecimal)); 64 | } 65 | switch (c) { 66 | case " ".code, "\t".code, "\r".code, "\n".code: //{ 67 | if ((c == "\r".code || c == "\n".code) && !multiline) return true; 68 | s.pos--; 69 | while (!s.eof) { 70 | s.pos++; 71 | switch (s.curr) { 72 | case " ".code, "\t".code: continue; 73 | case "\r".code, "\n".code: 74 | if (multiline) continue; 75 | }; break; 76 | }; list.push(CoSpace(part(last, s.pos))); 77 | var e = end; 78 | if (e != null && s.skipEqual(e)) return true; 79 | if (multiline && s.str.substr(s.pos, 14) == "if expression ") { 80 | var s_pos = s.pos; 81 | var ln = s.str.indexOf("\n", s_pos); 82 | var i:Int = s.str.indexOf("is true\n", s_pos); 83 | if (i >= 0 && i < ln) { 84 | return true; 85 | } else { 86 | i = s.str.indexOf("is not true\n", s_pos); 87 | if (i >= 0 && i < ln) return true; 88 | } 89 | } 90 | //} whitespace 91 | case ".".code: //{ 92 | c = s.curr; 93 | if (c >= "0".code && c <= "9".code) { // .05 94 | s.pos--; do { 95 | c = s.charAt(++s.pos); 96 | } while (c >= "0".code && c <= "9".code); 97 | return add(CoNumber(s.str.substring(last, s.pos), CnDecimal)); 98 | } else return add(CoDot); 99 | //} "." 100 | case ",".code: return add(CoComma); 101 | case ";".code: return add(CoSemico); 102 | case ":".code: 103 | if (s.curr == "=".code) { 104 | s.pos++; 105 | return add(CoOp(":=")); 106 | } else return add(CoColon); 107 | case "=".code: 108 | if (s.curr == "=".code) { 109 | s.pos++; 110 | return add(CoOp("==")); 111 | } else return add(CoAOp("=")); 112 | case "!".code: 113 | if (s.curr == "=".code) { 114 | s.pos++; 115 | return add(CoOp("!=")); 116 | } else return add(CoUOp("!")); 117 | case "+".code, "-".code: 118 | if (s.curr == c) { // ++/-- 119 | return add(CoOp(part(last, ++s.pos))); 120 | } else if (s.curr == "=".code) { 121 | return add(CoAOp(part(last, ++s.pos))); 122 | } else return add(CoOp(part(last, s.pos))); 123 | case "*".code, "%".code: 124 | if (s.curr == "=".code) { 125 | s.pos++; 126 | return add(CoAOp(part(last, ++s.pos))); 127 | } else return add(CoOp(part(last, s.pos))); 128 | case "/".code: //{ 129 | switch (s.curr) { 130 | case "=".code: s.pos++; return add(CoAOp("/=")); 131 | case "/".code: // comment line 132 | while (s.cond) { 133 | switch (s.charAt(++s.pos)) { 134 | case "\r".code, "\n".code: 135 | default: continue; 136 | } 137 | break; 138 | } 139 | add(CoComment(part(last, s.pos))); 140 | case "*".code: // multi-line comment 141 | while (s.cond) { 142 | var c0 = c; 143 | c = s.charAt(++s.pos); 144 | if (c == "/".code && c0 == "*".code) break; 145 | } 146 | add(CoComment(part(last, ++s.pos))); 147 | default: return add(CoOp("/")); 148 | } 149 | //} "/" 150 | case "<".code, ">".code: 151 | if (c == "<".code && s.curr == ">".code) s.pos++; 152 | else if (s.curr == c || s.curr == "=".code) s.pos++; 153 | return add(CoOp(part(last, s.pos))); 154 | case "&".code, "|".code, "^".code: 155 | if (s.curr == "=".code) { 156 | return add(CoAOp(part(last, ++s.pos))); 157 | } else if (s.curr == c) s.pos++; 158 | return add(CoOp(part(last, s.pos))); 159 | case '"'.code, "'".code: 160 | while (!s.eof) { 161 | if (s.curr == c) break; 162 | s.pos++; 163 | } 164 | if (s.eof) return true; 165 | s.pos++; 166 | return add(CoString(part(last, s.pos))); 167 | case "$".code: s.pos--; return addHex(); 168 | case "@".code, "#".code, "?".code: return add(CoAAC(c)); 169 | case "~".code: return add(CoUOp("~")); 170 | case "(".code: return add(CoPar0); 171 | case ")".code: return add(CoPar1); 172 | case "[".code: return add(CoSqb0); 173 | case "]".code: return add(CoSqb1); 174 | case "{".code: return add(CoCub0); 175 | case "}".code: return add(CoCub1); 176 | default: 177 | if((c >= "a".code && c <= "z".code) 178 | || (c >= "A".code && c <= "Z".code) 179 | || (c == "_".code)) { // ident 180 | s.pos--; 181 | do { 182 | s.pos++; 183 | c = s.curr; 184 | } while ((c == "_".code) 185 | || (c >= "a".code && c <= "z".code) 186 | || (c >= "A".code && c <= "Z".code) 187 | || (c >= "0".code && c <= "9".code)); 188 | var word = s.str.substring(last, s.pos); 189 | switch (word) { 190 | case"var", "globalvar", "if", "then", "else", 191 | "exit", "return", "break", "continue", "goto", 192 | "for", "while", "do", "until", "repeat", "with", 193 | "switch", "case", "default", "enum", 194 | "todo": 195 | node = CoKeyword(word); 196 | case "self", "other", "global", "local", "all", "noone": 197 | node = CoWord(word, CwStdSpec); 198 | case "and", "or", "xor", "div", "mod": 199 | node = CoOp(word); 200 | case "not": node = CoUOp(word); 201 | default: 202 | if (isStd[word]) { 203 | node = CoWord(word, CwStdVar); 204 | } else { 205 | var res = false; 206 | for (v in resPfx) { 207 | if (StringTools.startsWith(word, v)) { 208 | res = true; 209 | break; 210 | } 211 | } 212 | node = CoWord(word, res ? CwResource : CwUserVar); 213 | } 214 | } 215 | list.push(node); 216 | return false; 217 | } else if ((c >= "0".code && c <= "9".code) || c == ".".code) { 218 | var dot = false; 219 | if (s.curr == "x".code) return addHex(); 220 | s.pos--; 221 | do { 222 | c = s.charAt(++s.pos); 223 | if (c == ".".code && !dot) { 224 | dot = true; 225 | s.pos++; 226 | c = s.curr; 227 | } 228 | } while (c >= "0".code && c <= "9".code); 229 | node = CoNumber(s.str.substring(last, s.pos), CnDecimal); 230 | list.push(node); 231 | return false; 232 | } else return true; 233 | } 234 | } 235 | return true; 236 | } 237 | /// Forbid suffixes 238 | public static inline var NO_SFX:Int = 0x1; 239 | /// Forbid trailing operators 240 | public static inline var NO_OPS:Int = 0x2; 241 | /// Forbid func() 242 | public static inline var NO_CALL:Int = 0x4; 243 | /// Forbid post-increment/decrement 244 | public static inline var NO_PCR:Int = 0x8; 245 | /** 246 | * Reads a single expression ("value"). 247 | * @param s StringReader to read from. 248 | * @param list List to push CodeNodes to. 249 | * @param dont Forbidden structures (see NO_*) 250 | * @return 251 | */ 252 | public static function readExpr(s:StringReader, list:Array, dont:Int = 0):Bool { 253 | // 254 | var pos0:Int, len0:Int; 255 | inline function store() { pos0 = s.pos; len0 = list.length; } 256 | inline function rewind() { 257 | s.pos = pos0; 258 | list.splice(len0, list.length - len0); 259 | return true; 260 | } 261 | // 262 | var pos1:Int, len1:Int; 263 | inline function storeAlt() { pos1 = s.pos; len1 = list.length; } 264 | inline function rewindAlt() { 265 | s.pos = pos1; 266 | list.splice(len1, list.length - len1); 267 | return true; 268 | } 269 | // prefix: 270 | store(); 271 | do { 272 | if (readNode(s, list)) return rewind(); 273 | switch (node) { 274 | case CoOp(s) : 275 | switch (s) { 276 | case "+", "-", "++", "--": continue; 277 | } 278 | case CoUOp(_): continue; 279 | default: 280 | } 281 | break; 282 | } while (!s.eof); 283 | // value: 284 | var index = list.length - 1; 285 | switch (node) { 286 | // constants: 287 | case CoNumber(_): 288 | case CoString(_): 289 | // potential variable/object/function: 290 | case CoWord(s, _): 291 | case CoPar0: //{ (expr) 292 | if (readExpr(s, list, 0)) return rewind(); 293 | if (readNode(s, list)) return rewind(); 294 | switch (node) { 295 | case CoPar1: 296 | default: return rewind(); 297 | } 298 | dont |= NO_SFX; 299 | //} 300 | default: return rewind(); 301 | } 302 | // suffix: 303 | var proc = true; 304 | while (proc && !s.eof) { 305 | store(); 306 | /// rewinds to the last saved point, but does not terminate parsing. 307 | inline function sfx_rewind():Void { 308 | s.pos = pos0; 309 | list.splice(len0, list.length - len0); 310 | proc = false; 311 | } 312 | if (readNode(s, list)) { 313 | sfx_rewind(); 314 | break; 315 | } 316 | switch (node) { 317 | case CoOp("++"), CoOp("--"): //{ ++/-- 318 | if ((dont & NO_PCR) == 0) { 319 | dont |= NO_SFX | NO_PCR; 320 | } else { 321 | rewind(); 322 | proc = false; 323 | } 324 | //} 325 | case CoOp(_), CoAOp("="): //{ + ... 326 | if ((dont & NO_OPS) == 0) { 327 | while (!s.eof) { 328 | if (readExpr(s, list, NO_OPS)) { 329 | sfx_rewind(); 330 | break; 331 | } 332 | dont |= NO_SFX; 333 | store(); 334 | if (s.eof) break; 335 | if (readNode(s, list)) { 336 | sfx_rewind(); 337 | break; 338 | } 339 | switch (node) { 340 | case CoAOp("="): continue; 341 | case CoOp(_): continue; 342 | default: 343 | } 344 | sfx_rewind(); 345 | break; 346 | } 347 | } else { 348 | rewind(); 349 | proc = false; 350 | } 351 | //} 352 | case CoPar0: //{ func(...) 353 | if ((dont & (NO_SFX | NO_CALL)) == 0) { 354 | switch (list[index]) { 355 | case CoWord(id, t): 356 | var seenComma = true; 357 | while (proc && s.cond) { 358 | var ppos = s.pos; 359 | var plen = list.length; 360 | if (readNode(s, list)) return rewind(); 361 | switch (node) { 362 | case CoComma: // ",": Error on duplicate commas, else OK 363 | if (seenComma) return rewind(); 364 | seenComma = true; 365 | continue; 366 | case CoPar1: // "(": End parsing. 367 | proc = false; 368 | default: // step back and parse as an expression: 369 | s.pos = ppos; 370 | list.splice(plen, list.length - plen); 371 | if (readExpr(s, list, 0)) return rewind(); 372 | seenComma = false; 373 | continue; 374 | } 375 | break; 376 | } 377 | switch (t) { 378 | case CwStdVar: list[index] = CoWord(id, CwStdFunc); 379 | case CwUserVar: list[index] = CoWord(id, CwUserFunc); 380 | default: 381 | } 382 | proc = true; 383 | dont |= NO_SFX; 384 | default: sfx_rewind(); 385 | } 386 | } else sfx_rewind(); 387 | //} func 388 | case CoDot: //{ expr.property 389 | if (readNode(s, list)) return rewind(); 390 | switch (node) { 391 | case CoWord(id, t): 392 | switch (t) { 393 | case CwUserVar: 394 | list[list.length - 1] = CoWord(id, CwField); 395 | default: 396 | } 397 | default: return rewind(); 398 | } 399 | dont |= NO_CALL; 400 | //} expr.property 401 | case CoSqb0: //{ expr[...] 402 | if ((dont & NO_SFX) == 0) { 403 | // check for array access chars: 404 | storeAlt(); 405 | if (readNode(s, list)) return rewind(); 406 | switch (node) { 407 | case CoAAC(_), CoOp("|"): 408 | default: rewindAlt(); 409 | } 410 | // 411 | if (readExpr(s, list, 0)) return rewind(); 412 | if (readNode(s, list)) return rewind(); 413 | switch (node) { 414 | case CoComma: // [i, j] 415 | if (readExpr(s, list)) return rewind(); 416 | if (readNode(s, list)) return rewind(); 417 | switch (node) { 418 | case CoSqb1: dont |= NO_SFX; 419 | default: return rewind(); 420 | } 421 | case CoSqb1: dont |= NO_SFX; 422 | default: return rewind(); 423 | } 424 | } else sfx_rewind(); 425 | //} expr[...] 426 | default: sfx_rewind(); 427 | } 428 | } 429 | return false; 430 | } 431 | static function readSemico(s:StringReader, list:Array):Void { 432 | var pos0:Int, len0:Int; 433 | inline function store() { pos0 = s.pos; len0 = list.length; } 434 | inline function rewind() { 435 | s.pos = pos0; 436 | list.splice(len0, list.length - len0); 437 | return true; 438 | } 439 | // catch semicolons: 440 | store(); 441 | while (s.cond) { 442 | if (readNode(s, list)) { 443 | rewind(); 444 | break; 445 | } 446 | switch (node) { 447 | case CoSemico: 448 | store(); 449 | continue; 450 | default: rewind(); 451 | }; break; 452 | } 453 | } 454 | /** 455 | * Reads a "single-line" expression (function call, assignment, if-then-else, ...) 456 | */ 457 | public static function readLine(s:StringReader, list:Array):Bool { 458 | // 459 | var pos0:Int, len0:Int; 460 | inline function store() { pos0 = s.pos; len0 = list.length; } 461 | inline function rewind() { 462 | s.pos = pos0; 463 | list.splice(len0, list.length - len0); 464 | return true; 465 | } 466 | // 467 | var pos1:Int, len1:Int; 468 | inline function storeAlt() { pos1 = s.pos; len1 = list.length; } 469 | inline function rewindAlt() { 470 | s.pos = pos1; 471 | list.splice(len1, list.length - len1); 472 | return true; 473 | } 474 | // 475 | store(); 476 | if (readNode(s, list)) return rewind(); 477 | switch (node) { 478 | case CoWord(_), CoPar0: //{ CoWord 479 | rewind(); 480 | if (readExpr(s, list, NO_OPS | NO_CALL | NO_PCR)) return rewind(); 481 | storeAlt(); 482 | if (readNode(s, list)) { 483 | rewindAlt(); 484 | } else switch (node) { 485 | case CoPar0, CoOp("++"), CoOp("--"): // "word(" 486 | rewind(); 487 | if (readExpr(s, list, 0)) return rewind(); 488 | case CoAOp(_): // "word += " 489 | if (readExpr(s, list, 0)) return rewind(); 490 | default: return rewind(); 491 | } 492 | //} 493 | case CoOp("++"), CoOp("--"): //{ ++var, --var 494 | rewind(); 495 | if (readExpr(s, list, NO_OPS | NO_CALL)) return rewind(); 496 | //} 497 | case CoKeyword(kw): //{ 498 | switch (kw) { 499 | case "break", "continue", "exit": 500 | case "return", "goto": //{ [word] expr 501 | if (readExpr(s, list)) return rewind(); 502 | //} 503 | case "if": //{ if-then-else 504 | // condition: 505 | if (readExpr(s, list, 0)) return rewind(); 506 | // "then" optional: 507 | storeAlt(); 508 | if (readNode(s, list)) return rewind(); 509 | switch (node) { 510 | case CoKeyword("then"): 511 | default: rewindAlt(); 512 | } 513 | // then-expression: 514 | if (readLine(s, list)) return rewind(); 515 | // "else"-branch (optional): 516 | storeAlt(); 517 | if (readNode(s, list)) { 518 | rewindAlt(); 519 | } else switch (node) { 520 | case CoKeyword("else"): 521 | // else-expression: 522 | if (readLine(s, list)) return rewind(); 523 | default: rewindAlt(); 524 | } 525 | //} if 526 | case "with", "repeat", "while": //{ kw (value) block; 527 | if (readExpr(s, list, 0)) return rewind(); 528 | if (readLine(s, list)) return rewind(); 529 | //} 530 | case "do": //{ do block until value 531 | if (readLine(s, list)) return rewind(); 532 | if (readNode(s, list)) return rewind(); 533 | switch (node) { 534 | case CoKeyword("until"): 535 | if (readExpr(s, list)) return rewind(); 536 | default: return rewind(); 537 | } 538 | //} 539 | case "for": //{ for (block; expr; block) block 540 | // "(": 541 | if (readNode(s, list)) return rewind(); 542 | switch (node) { 543 | case CoPar0: 544 | default: return rewind(); 545 | } 546 | // init: 547 | if (readLine(s, list)) return rewind(); 548 | // cond: 549 | if (readExpr(s, list)) return rewind(); 550 | readSemico(s, list); 551 | // post: 552 | if (readLine(s, list)) return rewind(); 553 | // ")": 554 | if (readNode(s, list)) return rewind(); 555 | switch (node) { 556 | case CoPar1: 557 | default: return rewind(); 558 | } 559 | // in-loop: 560 | if (readLine(s, list)) return rewind(); 561 | //} 562 | case "switch": //{ switch value ... 563 | if (readExpr(s, list)) return rewind(); 564 | if (readLine(s, list)) return rewind(); 565 | //} 566 | case "case": //{ case value: 567 | if (readExpr(s, list)) return rewind(); 568 | if (readNode(s, list)) return rewind(); 569 | switch (node) { 570 | case CoColon: 571 | default: return rewind(); 572 | } 573 | //} 574 | case "default", "todo": //{ default: 575 | if (readNode(s, list)) return rewind(); 576 | switch (node) { 577 | case CoColon: 578 | default: return rewind(); 579 | } 580 | //} 581 | case "var", "globalvar": //{ 582 | while (s.cond) { 583 | storeAlt(); 584 | if (readNode(s, list)) { 585 | rewindAlt(); 586 | break; 587 | } 588 | switch (node) { 589 | case CoComma: continue; 590 | case CoWord(_, _): 591 | var pos2 = s.pos; 592 | var len2 = list.length; 593 | inline function rewindVar() { 594 | s.pos = pos2; 595 | list.splice(len2, list.length - len2); 596 | } 597 | if (!readNode(s, list)) { 598 | switch (node) { 599 | case CoAOp(_): // name = value 600 | if (!readExpr(s, list, 0)) continue; 601 | case CoSemico: 602 | rewindVar(); 603 | // [break] 604 | case CoPar0: 605 | rewindAlt(); 606 | // [break] 607 | default: 608 | rewindVar(); 609 | continue; 610 | } 611 | } else rewindAlt(); 612 | default: rewindAlt(); 613 | } // switch (node) 614 | break; 615 | } 616 | //} 617 | case "enum": //{ enum { v1, v2 = 10 } 618 | // enum name: 619 | if (readNode(s, list)) return rewind(); 620 | switch (node) { 621 | case CoWord(_, _): 622 | default: return rewind(); 623 | } 624 | // `{`: 625 | if (readNode(s, list)) return rewind(); 626 | switch (node) { 627 | case CoCub0: 628 | default: return rewind(); 629 | } 630 | while (s.cond) { 631 | if (readNode(s, list)) return rewind(); 632 | switch (node) { 633 | case CoComma: continue; 634 | case CoWord(_, _): 635 | storeAlt(); 636 | if (readNode(s, list)) return rewind(); 637 | switch (node) { 638 | case CoAOp(_): 639 | if (readExpr(s, list)) return rewind(); 640 | default: rewindAlt(); 641 | } 642 | continue; 643 | case CoCub1: // advance 644 | default: return rewind(); 645 | } 646 | break; 647 | } 648 | //} 649 | default: return rewind(); 650 | } 651 | //} CoKeyword 652 | case CoCub0: //{ "{ ... }" 653 | if (readLines(s, list)) return rewind(); 654 | if (readNode(s, list)) return rewind(); 655 | switch (node) { 656 | case CoCub1: 657 | default: return rewind(); 658 | } 659 | //} 660 | default: return rewind(); 661 | } 662 | readSemico(s, list); 663 | return false; 664 | } 665 | public static function readLines(s:StringReader, list:Array):Bool { 666 | // 667 | var pos0:Int, len0:Int; 668 | inline function store() { pos0 = s.pos; len0 = list.length; } 669 | inline function rewind() { 670 | s.pos = pos0; 671 | list.splice(len0, list.length - len0); 672 | return true; 673 | } 674 | // 675 | while (s.cond) { 676 | store(); 677 | if (readNode(s, list)) { 678 | rewind(); 679 | break; 680 | } 681 | switch (node) { 682 | case CoCub1: // "}" 683 | rewind(); 684 | return false; 685 | default: 686 | rewind(); 687 | if (!readLine(s, list)) continue; 688 | }; break; 689 | } 690 | // post-catch trailing comments 691 | store(); 692 | var trail = true; 693 | while (trail && s.cond) { 694 | var start:Int = s.pos++; 695 | var c:Int = s.charAt(start); 696 | switch (c) { 697 | case " ".code, "\t".code, "\r".code, "\n".code: 698 | s.pos--; 699 | while (s.cond) { 700 | switch (s.charAt(++s.pos)) { 701 | case " ".code, "\t".code, "\r".code, "\n".code: continue; 702 | default: 703 | }; break; 704 | }; list.push(CoSpace(s.str.substring(start, s.pos))); 705 | case ";".code: list.push(CoSemico); store(); 706 | case "/".code: //{ 707 | switch (s.curr) { 708 | case "/".code: 709 | while (s.cond) { 710 | switch (s.charAt(++s.pos)) { 711 | case "\r".code, "\n".code: // [break] 712 | default: continue; 713 | }; break; 714 | } 715 | list.push(CoComment(s.str.substring(start, s.pos))); 716 | store(); 717 | case "*".code: 718 | while (s.cond) { 719 | var c0 = c; 720 | c = s.charAt(++s.pos); 721 | if (c0 == "*".code && c == "/".code) break; 722 | } 723 | if (s.cond) { 724 | list.push(CoComment(s.str.substring(start, ++s.pos))); 725 | store(); 726 | } else trail = false; 727 | default: trail = false; 728 | } // switch 729 | //} "/" 730 | default: trail = false; 731 | } // switch @ trail 732 | } 733 | rewind(); 734 | // 735 | return false; 736 | } 737 | 738 | public static function print(node:CodeNode, mode:OutputMode, ?pre:Bool) { 739 | inline function escape(str:String) { 740 | return StringTools.htmlEscape(str); 741 | } 742 | var html = switch (mode) { 743 | case OmHTML: true; 744 | default: false; 745 | } 746 | inline function bbs(style:String, value:String) { 747 | return data.BBStyle.get(style, value); 748 | } 749 | inline function wrap(s:String, v:String) { 750 | return switch (mode) { 751 | case OmHTML: '$v'; 752 | case OmBB: data.BBStyle.get('code $s', v); 753 | default: v; 754 | } 755 | } 756 | return switch (node) { 757 | case CoSpace(s), CoElse(s): 758 | if (html) { 759 | if (!pre) { 760 | s = StringTools.replace(s, " ", " "); 761 | s = StringTools.replace(s, "\n", "
"); 762 | } 763 | if (node.match(CoElse(_))) { 764 | s = wrap("error", s); 765 | } 766 | s; 767 | } else s; 768 | case CoComma: ','; 769 | case CoDot: '.'; 770 | case CoColon: ':'; 771 | case CoSemico: ';'; 772 | case CoComment(s): wrap("co", escape(s)); 773 | case CoWord(s, t): 774 | switch (t) { 775 | case CwNormal: wrap("id", s); 776 | case CwStdVar: wrap("sv", s); 777 | case CwStdFunc: wrap("sf", s); 778 | case CwStdSpec: wrap("sp", s); 779 | case CwUserVar: wrap("uv", s); 780 | case CwUserFunc: wrap("uf", s); 781 | case CwField: wrap("fd", s); 782 | case CwResource: wrap("ri", s); 783 | } 784 | case CoKeyword(s): wrap("kw", s); 785 | case CoNumber(s, t): 786 | switch (t) { 787 | case CnDecimal: wrap("nu", s); 788 | case CnHexadecimal: wrap("nx", s); 789 | } 790 | case CoString(s): wrap("st", escape(s)); 791 | case CoAOp(s): wrap("op", html ? escape(s) : s); 792 | case CoOp(s), CoUOp(s): 793 | switch (s) { 794 | case "and", "or", "xor", "not", "div", "mod": 795 | wrap("kw", s); 796 | default: wrap("op", html ? escape(s) : s); 797 | } 798 | case CoAAC(c): wrap("op", String.fromCharCode(c)); 799 | case CoPar0: "("; 800 | case CoPar1: ")"; 801 | case CoSqb0: "["; 802 | case CoSqb1: "]"; 803 | case CoCub0: "{"; 804 | case CoCub1: "}"; 805 | case CoHash: "#"; 806 | } 807 | } 808 | public static function printNodes(nodes:Array, mode:OutputMode):String { 809 | var r = ""; 810 | for (node in nodes) r += print(node, mode); 811 | return r; 812 | } 813 | } 814 | 815 | enum CodeNode { 816 | CoSpace(s:String); // whitespace 817 | CoComma; // , 818 | CoDot; // . 819 | CoColon; // : 820 | CoSemico; // ; 821 | CoComment(s:String); // "//" / "/* */" 822 | CoWord(s:String, t:CodeWordType); // word 823 | CoKeyword(s:String); // keyword 824 | CoNumber(s:String, t:CodeNumberType); // 34.1 825 | CoString(s:String); // "words" 826 | CoOp(s:String); // + 827 | CoAOp(s:String); // += 828 | CoUOp(s:String); // ~/!/.. 829 | CoAAC(c:Int); // array access chars 830 | CoPar0; // ( 831 | CoPar1; // ) 832 | CoSqb0; // [ 833 | CoSqb1; // ] 834 | CoCub0; // { 835 | CoCub1; // } 836 | CoHash; // # 837 | CoElse(s:String); // anything else 838 | } 839 | 840 | enum CodeNumberType { 841 | CnDecimal; 842 | CnHexadecimal; 843 | } 844 | 845 | enum CodeWordType { 846 | /// "id": Anything that doesn't fall into other category 847 | CwNormal; 848 | /// "sv": Built-in variable 849 | CwStdVar; 850 | /// "sf": Built-in function 851 | CwStdFunc; 852 | /// "sp": Built-in special (self/other/global/local/all/noone) 853 | CwStdSpec; 854 | /// "uv": User-defined variable 855 | CwUserVar; 856 | /// "uf": User-defined function 857 | CwUserFunc; 858 | /// "fd": Field access (inst.field) 859 | CwField; 860 | /// "ri": Resource index 861 | CwResource; 862 | } 863 | -------------------------------------------------------------------------------- /src/Conf.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | @:publicFields class Conf { 8 | static var iconURL:String = "./img/{id}.png"; 9 | static inline function getIconURL(s:String) { 10 | return StringTools.replace(iconURL, "{id}", s); 11 | } 12 | static var miniIcons:Bool = true; 13 | static var resPfx(default, set):String; 14 | static function set_resPfx(v:String):String { 15 | if (resPfx != v) { 16 | resPfx = v; 17 | Code.resPfx = v.split("|"); 18 | } 19 | return v; 20 | } 21 | //{ HTML options 22 | static var htmlIcon:Int = htmlIconSpan; 23 | static inline var htmlIconImg:Int = 0; 24 | static inline var htmlIconSpan:Int = 1; 25 | /// Whether to use CSS (as opposed to inline styles). 26 | static var htmlModern:Bool = true; 27 | /// Whether to fill out text inside the icons for copying. 28 | static var htmlIconText:Bool = false; 29 | //} 30 | //{ BB code options 31 | /// whether to use "[img=$s]" instead of "[img]$s[/img]". 32 | static var bbImgAlt:Bool = false; 33 | static function bbGetIndent(n:Int):String { 34 | var r:String = ""; 35 | switch (bbIndentMode) { 36 | case bbIndentModeString: 37 | while (--n >= 0) r += bbIndentString; 38 | default: 39 | } 40 | return r; 41 | } 42 | /// whether to use ":GM#:" smileys for icons if possible 43 | static var bbGMC:Bool = false; 44 | /// 45 | static var bbIndentMode:Int = 0; 46 | static inline var bbIndentModeString:Int = 0; 47 | static inline var bbIndentModeList:Int = 1; 48 | // 49 | static var bbIndentString:String = " "; 50 | // 51 | static var bbListType:Int = 0; 52 | static inline var bbListTypeStar2:Int = 0; 53 | static inline var bbListTypeStar1:Int = 1; 54 | static inline var bbListTypeLi:Int = 2; 55 | //} 56 | //{ GML options 57 | static var gmlIndentString:String = " "; 58 | static function gmlGetIndent(n:Int):String { 59 | var r:String = ""; 60 | while (--n >= 0) r += gmlIndentString; 61 | return r; 62 | } 63 | static var gmlIndentMode:GmlIndentMode = KNR; 64 | static var gmlNewAudio:Bool = false; 65 | //} 66 | } 67 | @:enum abstract GmlIndentMode(Int) from Int to Int { 68 | 69 | /** Allman, brace-on-new-line */ 70 | var BSD = 0; 71 | 72 | /** K&R, brace-on-same-line*/ 73 | var KNR = 1; 74 | 75 | /** Whitesmiths, brace-on-new-line-indented */ 76 | var WSM = 2; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/Info.hx: -------------------------------------------------------------------------------- 1 | package; 2 | import data.*; 3 | import types.*; 4 | using StringTools; 5 | 6 | /** 7 | * ... 8 | * @author YellowAfterlife 9 | */ 10 | class Info { 11 | public var nodes:Array; 12 | 13 | /** Whether to "unpack" single-action branches from begin/end blocks. */ 14 | public var optPostFix:Bool = true; 15 | 16 | /** Whether to detect open/close blocks based on indentation changes. */ 17 | public var optIndent:Bool = true; 18 | 19 | public function new() { 20 | nodes = []; 21 | } 22 | 23 | static function postfix(list:Array) { 24 | var i = list.length; 25 | while (--i >= 0) { 26 | var node:Node = list[i]; 27 | if(i >= 2 && node.type == NodeClose.inst 28 | && list[i - 2].type == NodeOpen.inst) { 29 | var expr = list[i - 1]; 30 | expr.indent--; 31 | i -= 2; 32 | list.splice(i, 3); 33 | list.insert(i, expr); 34 | } 35 | if (node.nodes != null) postfix(node.nodes); 36 | } 37 | } 38 | 39 | public function read(s:StringReader) { 40 | var i:Int, n:Int; 41 | var atl = NodeType.nodeTypes; 42 | var atc = atl.length; 43 | var etl = types.NodeEvent.eventTypes; 44 | var etc = etl.length; 45 | var list = nodes; 46 | var tabs:Int = 0; 47 | var next:Int; // next indent level 48 | var atOpen = types.NodeOpen.inst; 49 | var atClose = types.NodeClose.inst; 50 | inline function unindent() { 51 | if (optIndent) while (next < tabs) { 52 | var acb = new Node(atClose); 53 | acb.indent = tabs; 54 | list.push(acb); 55 | tabs--; 56 | } 57 | } 58 | while (!s.eof) { 59 | s.readWhileIn("\r\n"); 60 | next = 0; 61 | while (!s.eof) { 62 | var c = s.curr; 63 | if (c == " ".code) { 64 | next++; 65 | s.pos++; 66 | } else if (c == "\t".code) { 67 | next += 4; 68 | s.pos++; 69 | } else break; 70 | } 71 | next = Std.int(next / 6); 72 | // 73 | var pos = s.pos; 74 | var action:Node = null; 75 | i = 0; while (i < atc) { 76 | action = atl[i++].read(s); 77 | if (action == null) { 78 | s.pos = pos; 79 | } else break; 80 | } 81 | if (action != null) { 82 | if (optIndent) { 83 | if (next > tabs) { 84 | var d = next - tabs; 85 | if (!action.type.isIndent || d > 1) 86 | while (--d >= 0) { 87 | var acb = new Node(atOpen); 88 | var acp = list.length - d; 89 | list.insert(acp, acb); 90 | for (i in acp ... list.length) list[i].indent++; 91 | tabs++; 92 | acb.indent = tabs; 93 | } 94 | } else if (next < tabs) unindent(); 95 | } else if (action.type == atClose) tabs--; 96 | action.indent = tabs; 97 | list.push(action); 98 | if (!optIndent && action.type == atOpen) tabs++; 99 | } else { // no action 100 | var event:Node = null; 101 | i = 0; while (i < etc) { 102 | event = etl[i++].read(s); 103 | if (event == null) { 104 | s.pos = pos; 105 | } else break; 106 | } 107 | if (event != null) { 108 | next = 0; 109 | unindent(); 110 | list = event.nodes; 111 | if (list == null) { 112 | event.nodes = list = []; 113 | } 114 | nodes.push(event); 115 | } else { // no event 116 | if ((action = types.NodeHeader.inst.read(s)) != null) { 117 | // header 118 | next = 0; 119 | unindent(); 120 | nodes.push(action); 121 | list = nodes; 122 | } else if ((action = types.NodeSeparator.inst.read(s)) != null) { 123 | // separator 124 | next = 0; 125 | unindent(); 126 | list = nodes; 127 | } else { 128 | var text:String = s.readUntilChar("\n".code); 129 | if (text != "") { 130 | list.push(new Node(NodeType.nodeTypeText, { values: [text] } )); 131 | } 132 | } 133 | } 134 | } 135 | } // while (!s.eof) 136 | // fix unclosed indents: 137 | next = 0; 138 | unindent(); 139 | // swipe to remove single-block openings: 140 | if (optPostFix) postfix(nodes); 141 | } 142 | public function readString(s:String) { 143 | var n:Int = s.length; 144 | while (n >= 0) { 145 | switch (s.charCodeAt(n)) { 146 | case "\r".code, "\n".code, " ".code: 147 | n--; 148 | continue; 149 | default: 150 | } 151 | break; 152 | } 153 | if (n < s.length) s = s.substring(0, n); 154 | s += "\n"; 155 | read(new StringReader(s)); 156 | } 157 | public static function fromString(s:String):Info { 158 | var r = new Info(); 159 | r.readString(s); 160 | return r; 161 | } 162 | public static var isGMX:Bool = false; 163 | public static function printNodes(nodes:Array, mode:OutputMode, tabc:Int):String { 164 | var r:String = "", first:Bool = true, ln:String; 165 | if (nodes.length == 0) return r; 166 | switch (mode) { 167 | case OutputMode.OmHTML: { 168 | ln = StringTools.rpad("\n", "\t", tabc + 1); 169 | for (node in nodes) { 170 | if (first) first = false; else r += ln; 171 | if (node.nodes == null) { 172 | r += node.type.print(node, mode); 173 | } else { 174 | r += '

' 175 | + ln + '\t' + node.type.print(node, mode) 176 | + ln + '

    ' 177 | + ln + '\t' + printNodes(node.nodes, mode, tabc + 1) 178 | + ln + '
'; 179 | } 180 | } 181 | }; 182 | case OutputMode.OmBB: { 183 | ln = "\n"; 184 | if (Conf.bbIndentMode == Conf.bbIndentModeList) r += '[list]$ln'; 185 | for (node in nodes) { 186 | if (first) first = false; else r += ln; 187 | if (node.nodes == null) { 188 | r += Conf.bbGetIndent(node.indent); 189 | r += BBStyle.get("node", node.type.print(node, mode)); 190 | } else { 191 | r += BBStyle.get("event p", node.type.print(node, mode)) 192 | + ln + BBStyle.get("event ul", printNodes(node.nodes, mode, tabc + 1)); 193 | } 194 | } 195 | if (Conf.bbIndentMode == Conf.bbIndentModeList) r += '$ln[/list]'; 196 | }; 197 | case OutputMode.OmGML, OmGmxGml: { 198 | ln = "\n"; 199 | var last:Node = null; 200 | var indentMode = Conf.gmlIndentMode; 201 | var index:Int = -1; 202 | while (++index < nodes.length) { 203 | var node:Node = nodes[index]; 204 | var indentLevel:Int = node.indent; 205 | var concat:Bool = false; 206 | var result:String = null; 207 | switch (node.name) { 208 | case "control: Start Block": { 209 | if (indentMode == KNR && last != null && last.type.isIndent) { 210 | // `if ()\n{` -> `if () {` 211 | concat = true; 212 | } else if (isGMX) { 213 | if (indentMode == WSM) indentLevel++; 214 | } else { 215 | if (indentMode != WSM) indentLevel--; 216 | } 217 | }; 218 | case "control: End Block": { 219 | if (isGMX) { 220 | if (indentMode == WSM) indentLevel++; 221 | } else { 222 | if (indentMode != WSM) indentLevel--; 223 | } 224 | }; 225 | case "control: Else": { 226 | if (indentMode == KNR && last != null && ( 227 | last.name == "control: End Block" 228 | || r.fastCodeAt(r.length - 1) == "}".code 229 | )) { 230 | // `}\nelse` -> `} else` 231 | concat = true; 232 | } 233 | }; 234 | default: { 235 | if (node.isIndent && last != null) { 236 | if (last.isIndent && node.match.with != null) { 237 | // with-if expressions have to be surrounded by brackets. 238 | var i:Int = index; 239 | var brackets:Int = 0; 240 | var loop:Bool = true; 241 | while (loop && i < nodes.length) { 242 | switch (nodes[i].name) { 243 | case "control: Start Block": brackets++; 244 | case "control: End Block": 245 | if (--brackets == 0) { 246 | if (i + 1 < nodes.length 247 | && nodes[i + 1].name == "control: Else") { 248 | // 249 | } else loop = false; 250 | } 251 | } // switch (nodes[i].name) 252 | i++; 253 | } // while (i < nodes.length) 254 | var acb:Node; 255 | acb = new Node(NodeOpen.inst); acb.indent = node.indent; 256 | nodes.insert(index, acb); 257 | acb = new Node(NodeClose.inst); acb.indent = node.indent; 258 | nodes.insert(i + 1, acb); 259 | i += 2; while (--i >= index) nodes[i].indent++; 260 | index -= 1; 261 | continue; 262 | } else if (last.type.name == "control: Else") { 263 | // `else\nif` -> `else if` 264 | concat = true; 265 | } 266 | } // if (node.isIndent && last != null) 267 | else if (last != null && last.isIndent) { 268 | result = node.type.print(node, mode); 269 | if (result.indexOf("\n") >= 0 || ( 270 | indentMode == KNR 271 | //&& index + 1 < nodes.length 272 | //&& nodes[index + 1].type.name == "control: Else" 273 | )) { 274 | concat = indentMode == KNR; 275 | var tab = Conf.gmlIndentString; 276 | result = "{\n" + tab 277 | + result.replace("\n", "\n" + tab) 278 | + "\n}"; 279 | } 280 | } 281 | }; // default 282 | } // switch (node.name) 283 | var indent:String = Conf.gmlGetIndent(indentLevel); 284 | var prefix:String = concat ? " " : (first ? "" : ln) + indent; 285 | var s = result != null ? result : node.type.print(node, mode); 286 | //if (s.length < 200) trace(indentLevel, s); 287 | var sl = s.length; 288 | //if (sl > 0 && s.charCodeAt(sl - 1) == "\n".code) s = s.substring(0, sl - 1); 289 | if (s.length > 0) { 290 | s = StringTools.replace(s, "\n", "\n" + indent); 291 | r += prefix + s; 292 | if (first) first = false; 293 | } 294 | // todo: augment print() calls instead? 295 | if (mode != OutputMode.OmGmxGml 296 | && node.nodes != null && node.nodes.length > 0) { 297 | r += ln + "execute code:" + ln; 298 | r += ln + printNodes(node.nodes, mode, tabc + 1); 299 | } 300 | // 301 | last = node; 302 | } 303 | }; // case OmGML 304 | default: 305 | } // switch (mode) 306 | return r; 307 | } 308 | public function print(mode:OutputMode):String { 309 | var r = printNodes(nodes, mode, 0); 310 | switch (mode) { 311 | case OmHTML: 312 | if (nodes.length > 1) r = '\n$r\n'; 313 | return '
$r
'; 314 | default: return r; 315 | } 316 | } 317 | 318 | public static function init() { 319 | Code.init(); 320 | // register node types: 321 | var nodeTypes = new Array(); 322 | DataActions.run(nodeTypes); 323 | DataGML.run(); 324 | DataInfo.run(nodeTypes); 325 | NodeEvent.eventTypes = data.DataEvents.get(); 326 | DataGMX.run(nodeTypes); 327 | NodeType.nodeTypes = nodeTypes; 328 | NodeType.nodeTypeText = new types.NodeText("@L"); 329 | NodeType.nodeTypeText.name = "Text"; 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /src/Main.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | import js.Browser; 4 | import js.html.DivElement; 5 | import js.html.DragEvent; 6 | import js.html.Element; 7 | import js.html.Event; 8 | import js.html.FileReader; 9 | import js.html.InputElement; 10 | import js.html.TextAreaElement; 11 | import js.html.UListElement; 12 | import js.Lib; 13 | import types.NodeEvent; 14 | 15 | /** 16 | * ... 17 | * @author YellowAfterlife 18 | */ 19 | 20 | class Main { 21 | inline function findId(id:String, ?c:Class):T { 22 | return cast Browser.document.getElementById(id); 23 | } 24 | // 25 | var btHTMLc:InputElement; 26 | var btHTMLm:InputElement; 27 | var btBB:InputElement; 28 | var btGML:InputElement; 29 | var btGMXGML:InputElement; 30 | var source:TextAreaElement; 31 | var outText:TextAreaElement; 32 | var outHTML:DivElement; 33 | // 34 | function load() { 35 | if (Browser.window.localStorage == null) return; 36 | var s:String; 37 | inline function f(k:String):Bool { 38 | return (s = Browser.window.localStorage.getItem(k)) != null; 39 | } 40 | inline function q(id:String):InputElement { 41 | return cast Browser.document.getElementById(id); 42 | } 43 | inline function r(id:String, v:String) q(id).value = v; 44 | inline function cb(id:String, v:Bool) q(id).checked = v; 45 | if (f("iconURL")) r("icon_url", s); 46 | if (f("miniIcons")) cb("small_icons", s == "1"); 47 | if (f("resPfx")) r("res_pfx", s); 48 | // 49 | if (f("bbImgAlt")) cb("bb_img_alt", s == "1"); 50 | if (f("bbGMC")) cb("bb_gmc_icons", s == "1"); 51 | if (f("bbIndentMode")) cb("bb_indent_list", s == "1"); 52 | if (f("bbIndentString")) r("bb_indent_text", s); 53 | if (f("bbListType")) switch (s) { 54 | case "0": cb("bb_list_mode_s2", true); 55 | case "1": cb("bb_list_mode_s1", true); 56 | case "2": cb("bb_list_mode_li", true); 57 | } 58 | // 59 | if (f("gmlIndentMode")) switch (s) { 60 | case "0": cb("gml_style_0", true); 61 | case "1": cb("gml_style_1", true); 62 | case "2": cb("gml_style_2", true); 63 | } 64 | } 65 | function save() { 66 | if (Browser.window.localStorage == null) return; 67 | inline function f(k:String, v:String) { 68 | Browser.window.localStorage.setItem(k, v); 69 | } 70 | inline function b(v:Bool) return v ? "1" : "0"; 71 | // 72 | f("miniIcons", b(Conf.miniIcons)); 73 | f("iconURL", Conf.iconURL); 74 | f("resPfx", Conf.resPfx); 75 | // 76 | f("bbImgAlt", b(Conf.bbImgAlt)); 77 | f("bbGMC", b(Conf.bbGMC)); 78 | f("bbIndentMode", "" + Conf.bbIndentMode); 79 | f("bbIndentString", Conf.bbIndentString); 80 | f("bbListType", "" + Conf.bbListType); 81 | // 82 | f("gmlIndentMode", "" + Conf.gmlIndentMode); 83 | } 84 | function update() { 85 | inline function q(id:String):InputElement { 86 | return cast Browser.document.getElementById(id); 87 | } 88 | inline function f(id:String):String return q(id).value; 89 | inline function cb(id:String):Bool return q(id).checked; 90 | var v:String; 91 | Conf.miniIcons = cb("small_icons"); 92 | Conf.resPfx = f("res_pfx"); 93 | Conf.iconURL = f("icon_url"); 94 | // 95 | Conf.bbImgAlt = cb("bb_img_alt"); 96 | Conf.bbGMC = cb("bb_gmc_icons"); 97 | Conf.bbIndentMode = cb("bb_indent_list") ? Conf.bbIndentModeList : Conf.bbIndentModeString; 98 | Conf.bbIndentString = f("bb_indent_text"); 99 | if (cb("bb_list_mode_s2")) Conf.bbListType = Conf.bbListTypeStar2; 100 | if (cb("bb_list_mode_s1")) Conf.bbListType = Conf.bbListTypeStar1; 101 | if (cb("bb_list_mode_li")) Conf.bbListType = Conf.bbListTypeLi; 102 | // 103 | if (cb("gml_style_0")) Conf.gmlIndentMode = 0; 104 | if (cb("gml_style_1")) Conf.gmlIndentMode = 1; 105 | if (cb("gml_style_2")) Conf.gmlIndentMode = 2; 106 | // 107 | save(); 108 | } 109 | function regSection(name:String) { 110 | var cb:InputElement = findId(name + "_cb"); 111 | var ul:UListElement = findId(name + "_ul"); 112 | cb.onchange = function(_) { 113 | ul.style.display = cb.checked ? "" : "none"; 114 | }; 115 | } 116 | function new() { 117 | // 118 | source = findId("source"); 119 | outText = findId("out_text"); 120 | outHTML = findId("out_html"); 121 | // 122 | regSection("bb_section"); 123 | regSection("gml_section"); 124 | // buttons: 125 | findId("print_clear", InputElement).onclick = function(_) { 126 | outHTML.innerHTML = outText.value = ""; 127 | }; 128 | btHTMLm = findId("print_html_m"); 129 | btHTMLm.onclick = function(_) { 130 | update(); 131 | var inf = Info.fromString(source.value); 132 | outHTML.innerHTML = outText.value = inf.print(OutputMode.OmHTML); 133 | }; 134 | btBB = findId("print_bb"); 135 | btBB.onclick = function(_) { 136 | update(); 137 | var inf = Info.fromString(source.value); 138 | var b0 = inf.print(OutputMode.OmBB); 139 | b0 = StringTools.replace(b0, "\t", " "); 140 | // replace sequences of spaces with alternating #160-#32s: 141 | var i:Int = 0, n:Int = b0.length; 142 | var b1 = ""; 143 | var nbsp = String.fromCharCode(160); 144 | while (i < n) { 145 | var c = b0.charAt(i++); 146 | switch (c) { 147 | case " ", "\n": 148 | switch (b0.charAt(i)) { 149 | case " ": // seq! 150 | var alt:Bool; 151 | if (c == "\n") { 152 | b1 += "\n" + nbsp; 153 | alt = true; 154 | } else { 155 | b1 += nbsp + " "; 156 | alt = false; 157 | } 158 | while (i < n) { 159 | c = b0.charAt(++i); 160 | switch (c) { 161 | case " ": 162 | alt = !alt; 163 | b1 += alt ? nbsp : " "; 164 | continue; 165 | default: 166 | }; break; 167 | } 168 | default: b1 += c; 169 | } 170 | default: b1 += c; 171 | } 172 | } 173 | // 174 | outText.value = b1; 175 | outHTML.innerHTML = inf.print(OutputMode.OmHTML); 176 | }; 177 | // 178 | btGML = findId("print_gml"); 179 | btGML.onclick = function(_) { 180 | update(); 181 | var inf = new Info(); 182 | inf.optPostFix = false; // dont cut single-action brackets (for now) 183 | inf.readString(source.value); 184 | var gml = inf.print(OutputMode.OmGML); 185 | outText.value = gml; 186 | // prepend just-actions output so that it highlights: 187 | if (inf.nodes.length > 0 && inf.nodes[0].nodes == null) gml = "```\n" + gml; 188 | // show highlighted preview: 189 | var inf2 = Info.fromString(gml); 190 | outHTML.innerHTML = inf2.print(OutputMode.OmHTML); 191 | } 192 | // 193 | btGMXGML = findId("print_gmxgml"); 194 | btGMXGML.onclick = function(_) { 195 | update(); 196 | var inf = new Info(); 197 | inf.optPostFix = false; // dont cut single-action brackets (for now) 198 | inf.readString(source.value); 199 | outText.value = inf.print(OutputMode.OmGmxGml); 200 | }; 201 | // 202 | load(); 203 | // 204 | (function allowFileDragAndDrop() { 205 | function cancelDefault(e:Event) { 206 | e.preventDefault(); 207 | return false; 208 | } 209 | Browser.document.body.addEventListener("dragover", cancelDefault); 210 | Browser.document.body.addEventListener("dragenter", cancelDefault); 211 | Browser.document.body.addEventListener("drop", function(e:DragEvent) { 212 | e.preventDefault(); 213 | var dt = e.dataTransfer; 214 | for (file in dt.files) { 215 | var reader = new FileReader(); 216 | reader.onloadend = function(_) { 217 | source.value = reader.result; 218 | }; 219 | reader.readAsText(file); 220 | } 221 | return false; 222 | }); 223 | })(); 224 | // auto-test: 225 | if (source.value != "") btGML.onclick(null); 226 | } 227 | static function main() { 228 | Info.init(); 229 | new Main(); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/Node.hx: -------------------------------------------------------------------------------- 1 | package; 2 | import matcher.*; 3 | /** 4 | * Represents a parsed node, such as an action or line of text. 5 | * @author YellowAfterlife 6 | */ 7 | class Node { 8 | /// node type 9 | public var type:NodeType; 10 | /// matched values 11 | public var match:MatchResult; 12 | /// indentation level 13 | public var indent(default, set):Int = 0; 14 | private function set_indent(v) { 15 | indent = v; 16 | return v; 17 | } 18 | /// child nodes (for event type) 19 | public var nodes:Array; 20 | /// purpose-specific data 21 | public var extra:Any = null; 22 | 23 | public function new(type:NodeType, ?match:MatchResult) { 24 | this.type = type; 25 | if (match != null) { 26 | this.match = match; 27 | } else this.match = { }; 28 | } 29 | 30 | public var name(get, never):String; 31 | inline function get_name() return type.name; 32 | 33 | public var isIndent(get, never):Bool; 34 | inline function get_isIndent() return type.isIndent; 35 | } 36 | -------------------------------------------------------------------------------- /src/NodeType.hx: -------------------------------------------------------------------------------- 1 | package; 2 | import matcher.*; 3 | /** 4 | * Represents a node type, determining 5 | * @author YellowAfterlife 6 | */ 7 | class NodeType { 8 | public static var nodeTypes:Array; 9 | public static var nodeTypeText:NodeType; 10 | public var name:String; 11 | 12 | /// matching sequence 13 | public var nodes:Array; 14 | 15 | /// Whether this node changes indentation 16 | public var isIndent:Bool = false; 17 | 18 | public function new(code:String) { 19 | nodes = Match.parse(code); 20 | } 21 | 22 | public function read(s:StringReader):Node { 23 | var m = Match.read(s, nodes); 24 | if (m == null) return null; 25 | return new Node(this, m); 26 | } 27 | 28 | private inline function printNodes(v:Node, mode:OutputMode):String { 29 | return Match.print(nodes, v.match, mode); 30 | } 31 | 32 | public function print(v:Node, mode:OutputMode):String { 33 | var r = printNodes(v, mode); 34 | switch (mode) { 35 | case OutputMode.OmHTML: 36 | return '
  • $r
  • '; 37 | default: return r; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/OutputMode.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | /** 4 | * @author YellowAfterlife 5 | */ 6 | enum abstract OutputMode(Int) { 7 | var OmHTML; 8 | var OmBB; 9 | var OmGML; 10 | var OmText; 11 | var OmGmxGml; 12 | } 13 | -------------------------------------------------------------------------------- /src/StringReader.hx: -------------------------------------------------------------------------------- 1 | package; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class StringReader { 8 | /// Input string 9 | public var str:String; 10 | /// Current position 11 | public var pos:Int; 12 | /// Input length 13 | public var len:Int; 14 | /// Charcode of the current symbol 15 | public var curr(get, never):Int; 16 | inline function get_curr() return StringTools.fastCodeAt(str, pos); 17 | /// Whether end of inupt has been reached yet 18 | public var eof(get, never):Bool; 19 | inline function get_eof() return pos >= len; 20 | /// Do you ever get a feeling that you only ever use "!eof"? 21 | public var cond(get, never):Bool; 22 | inline function get_cond() return pos < len; 23 | public function new(s:String) { 24 | str = StringTools.replace(s, "\r\n", "\n"); 25 | pos = 0; 26 | len = str.length; 27 | } 28 | public inline function charAt(i:Int):Int return str.charCodeAt(i); 29 | public inline function skipEqual(s:String):Bool { 30 | var n = s.length; 31 | if (str.substr(pos, n) == s) { 32 | pos += n; 33 | return true; 34 | } else return false; 35 | } 36 | public function readWhileIn(chars:String):String { 37 | var p0:Int = pos; 38 | while (pos < len) { 39 | if (chars.indexOf(str.charAt(pos)) < 0) break; 40 | pos++; 41 | } 42 | return str.substring(p0, pos); 43 | } 44 | public function readUntilIn(chars:String):String { 45 | var p0:Int = pos; 46 | while (pos < len) { 47 | if (chars.indexOf(str.charAt(pos)) >= 0) break; 48 | pos++; 49 | } 50 | return str.substring(p0, pos); 51 | } 52 | public function readUntilChar(c:Int):String { 53 | var p0:Int = pos; 54 | while (pos < len) { 55 | if (str.charCodeAt(pos) == c) break; 56 | pos++; 57 | } 58 | return str.substring(p0, pos); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/app/DNDtoGML.hx: -------------------------------------------------------------------------------- 1 | package app; 2 | import haxe.io.Path; 3 | import sys.FileSystem; 4 | import sys.io.File; 5 | import types.gmx.NodeGmxAction.dndCounter; 6 | import types.NodeAction.gmlCounter; 7 | 8 | /** 9 | * ... 10 | * @author YellowAfterlife 11 | */ 12 | class DNDtoGML { 13 | public static function main():Int { 14 | var args = Sys.args(); 15 | // 16 | var quiet = false; 17 | var output = true; 18 | inline function exit(code:Int) { 19 | if (!quiet) { 20 | Sys.println("Press any key to exit."); 21 | Sys.stdin().readByte(); 22 | } 23 | Sys.exit(code); 24 | return code; 25 | } 26 | // 27 | var i = args.length; 28 | while (--i >= 0) switch (args[i].toLowerCase()) { 29 | case "/q": quiet = true; args.splice(i, 1); 30 | case "/dryrun": output = false; args.splice(i, 1); 31 | default: 32 | } 33 | var path = args.shift(); 34 | if (path == null) { 35 | Sys.println("Use: DNDtoGML [path to project]"); 36 | Sys.println("Optional flags:"); 37 | Sys.println(" /Q: Suspend 'Press any key to exit'"); 38 | Sys.println("Dragging a .project.gmx over the executable works too."); 39 | return exit(0); 40 | } 41 | // 42 | if (!FileSystem.exists(path)) { 43 | Sys.println('Couldn\'t find a file or a directory at `$path`'); 44 | return exit(1); 45 | } 46 | // 47 | if (!FileSystem.isDirectory(path)) { 48 | path = Path.directory(path); 49 | if (path == "") path = "."; 50 | } 51 | // 52 | var obj1 = Path.join([path, "objects"]); 53 | if (!FileSystem.exists(obj1)) { 54 | Sys.println('Couldn\'t find a directory at `$obj1`'); 55 | return exit(1); 56 | } 57 | // 58 | var obj0 = Path.join([path, "objects@" + DateTools.format(Date.now(), "%Y-%m-%d_%H-%M-%S")]); 59 | if (output) FileSystem.createDirectory(obj0); 60 | // 61 | Info.init(); 62 | dndCounter = 0; 63 | gmlCounter = 0; 64 | // read "use new audio system" setting from config: 65 | var cfg = Path.join([path, "Configs", "Default.config.gmx"]); 66 | if (FileSystem.exists(cfg)) try { 67 | var xmlRoot = Xml.parse(File.getContent(cfg)); 68 | for (xmlConfig in xmlRoot.elementsNamed("Config")) { 69 | for (xmlOptions in xmlConfig.elementsNamed("Options")) { 70 | for (xmlAudio in xmlOptions.elementsNamed("option_use_new_audio")) { 71 | switch (xmlAudio.firstChild().toString().toLowerCase()) { 72 | case "0", "false": Conf.gmlNewAudio = false; 73 | default: Conf.gmlNewAudio = true; 74 | } 75 | } 76 | } 77 | } 78 | } catch (_:Dynamic) { 79 | // 80 | } 81 | // 82 | for (lp in FileSystem.readDirectory(obj1)) { 83 | if (StringTools.endsWith(lp.toLowerCase(), ".object.gmx")) { 84 | var op = '$obj1/$lp'; 85 | if (output) File.copy(op, '$obj0/$lp'); 86 | var gmx0 = File.getContent(op); 87 | // 88 | var inf = new Info(); 89 | inf.optPostFix = false; 90 | inf.readString(gmx0); 91 | var gmx1 = inf.print(OutputMode.OmGmxGml); 92 | // 93 | if (output) File.saveContent(op, gmx1); 94 | } 95 | } 96 | // 97 | Sys.println("Converted " + dndCounter + " DnD blocks into " + gmlCounter + " lines of GML."); 98 | return exit(0); 99 | /*var path = Sys.args()[0]; 100 | if (path == null) { 101 | Sys.println("Use: 102 | }*/ 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/app/DNDtoGMLjs.hx: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import js.Browser; 4 | import js.html.AnchorElement; 5 | import js.html.Blob; 6 | import js.html.DivElement; 7 | import js.html.DragEvent; 8 | import js.html.Element; 9 | import js.html.Event; 10 | import js.html.FileList; 11 | import js.html.FileReader; 12 | import js.html.InputElement; 13 | import js.html.SelectElement; 14 | import js.html.TextAreaElement; 15 | import js.html.UListElement; 16 | import js.Lib; 17 | import js.html.URL; 18 | import types.NodeEvent; 19 | 20 | /** 21 | * ... 22 | * @author YellowAfterlife 23 | */ 24 | 25 | class DNDtoGMLjs { 26 | static inline function findId(id:String, ?c:Class):T { 27 | return cast Browser.document.getElementById(id); 28 | } 29 | // 30 | var source:TextAreaElement = findId("source"); 31 | var outText:TextAreaElement = findId("out_text"); 32 | var outHTML:DivElement = findId("out_html"); 33 | var codeStyle:SelectElement = findId("codestyle"); 34 | var picker:InputElement = findId("picker"); 35 | var saver:AnchorElement = findId("saver"); 36 | // 37 | function load() { 38 | var ls = Browser.window.localStorage; 39 | if (ls == null) return; 40 | var s:String; 41 | // 42 | s = ls.getItem("gmvisualizer.gmlIndentMode"); 43 | if (s != null) codeStyle.selectedIndex = Std.parseInt(s); 44 | // 45 | } 46 | function save() { 47 | var ls = Browser.window.localStorage; 48 | if (ls == null) return; 49 | // 50 | ls.setItem("gmvisualizer.gmlIndentMode", "" + Conf.gmlIndentMode); 51 | #if (debug) 52 | ls.setItem("gmvisualizer.source", source.value); 53 | #end 54 | } 55 | function update() { 56 | Conf.gmlIndentMode = codeStyle.selectedIndex; 57 | // 58 | save(); 59 | } 60 | function regSection(name:String) { 61 | var cb:InputElement = findId(name + "_cb"); 62 | var ul:UListElement = findId(name + "_ul"); 63 | cb.onchange = function(_) { 64 | ul.style.display = cb.checked ? "" : "none"; 65 | }; 66 | } 67 | function new() { 68 | // buttons: 69 | var filename = "some.object.gmx"; 70 | var objectURL = null; 71 | function proc() { 72 | update(); 73 | var inf = new Info(); 74 | inf.optPostFix = false; // dont cut single-action brackets (for now) 75 | inf.readString(source.value); 76 | var gmx = inf.print(OutputMode.OmGmxGml); 77 | outText.value = gmx; 78 | // 79 | saver.download = filename; 80 | try { 81 | var blob = new Blob([gmx], { type: "xml" }); 82 | if (objectURL != null) URL.revokeObjectURL(objectURL); 83 | objectURL = URL.createObjectURL(blob); 84 | saver.href = objectURL; 85 | } catch (_:Dynamic) { 86 | saver.href = "data:application/xml;charset=utf-8," + StringTools.urlEncode(gmx); 87 | } 88 | // prepend just-actions output so that it highlights: 89 | if (inf.nodes.length > 0 && inf.nodes[0].nodes == null) gmx = "```\n" + gmx; 90 | // show highlighted preview: 91 | var inf2 = Info.fromString(gmx); 92 | outHTML.innerHTML = inf2.print(OutputMode.OmHTML); 93 | } 94 | source.addEventListener("change", function(_) proc()); 95 | codeStyle.addEventListener("change", function(_) proc()); 96 | // 97 | load(); 98 | // 99 | function readFiles(files:FileList) { 100 | for (file in files) { 101 | var reader = new FileReader(); 102 | reader.onloadend = function(_) { 103 | filename = file.name; 104 | source.value = reader.result; 105 | proc(); 106 | return; 107 | }; 108 | reader.readAsText(file); 109 | } 110 | } 111 | picker.addEventListener("change", function(_) readFiles(picker.files)); 112 | // 113 | function cancelDefault(e:Event) { 114 | e.preventDefault(); 115 | return false; 116 | } 117 | Browser.document.body.addEventListener("dragover", cancelDefault); 118 | Browser.document.body.addEventListener("dragenter", cancelDefault); 119 | Browser.document.body.addEventListener("drop", function(e:DragEvent) { 120 | e.preventDefault(); 121 | readFiles(e.dataTransfer.files); 122 | return false; 123 | }); 124 | // auto-test: 125 | #if (debug) 126 | (function() { 127 | var src = Browser.window.localStorage.getItem("gmvisualizer.source"); 128 | if (src != null) source.value = src; 129 | })(); 130 | #end 131 | if (source.value != "") proc(); 132 | } 133 | static function main() { 134 | Info.init(); 135 | new DNDtoGMLjs(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/data/BBStyle.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | 3 | /** 4 | * Handles mapping styles to BB code sequences. 5 | * @author YellowAfterlife 6 | */ 7 | class BBStyle { 8 | public static inline function img(url:String):String { 9 | if (Conf.bbImgAlt) { 10 | return '[img=$url]'; 11 | } else { 12 | return '[img]$url[/img]'; 13 | } 14 | } 15 | public static function get(name:String, v:String):String { 16 | return switch (name) { 17 | // 18 | case "h2": '[b]$v[/b]'; 19 | case "event p": '[b]$v[/b]'; //'[quote="$v"]'; 20 | case "event ul": '$v\n';// '$v[/quote]'; 21 | case "node": 22 | if (Conf.bbIndentMode == Conf.bbIndentModeList) { 23 | switch (Conf.bbListType) { 24 | case Conf.bbListTypeStar2: '[*]$v[/*]'; 25 | case Conf.bbListTypeStar1: '[*]$v'; 26 | case Conf.bbListTypeLi: '[li]$v[/li]'; 27 | default: v; 28 | } 29 | } else v; 30 | case "ri": '[color=#0078AA]$v[/color]'; 31 | case "relative": '[color=#008800]$v[/color]'; 32 | case "not": '[color=#008800]$v[/color]'; 33 | case "set": '[color=#008800]$v[/color]'; 34 | case "with": '[color=#777777]$v[/color]'; 35 | case "comment": '[i]$v[/i]'; 36 | case "comment prefix": '[color=#888888]$v[/color]'; 37 | case "mono": '[font=monospace]$v[/font]'; 38 | case "code mono": get("code", get("mono", v)); 39 | case "code co": '[color=#888888]$v[/color]'; 40 | case "code kw": '[b][color=#000088]$v[/color][/b]'; 41 | case "code sp": '[b][color=#000088]$v[/color][/b]'; 42 | case "code nu": '[color=#0000FF]$v[/color]'; 43 | case "code nx": '[color=#0000FF]$v[/color]'; 44 | case "code st": '[color=#0000FF]$v[/color]'; 45 | case "code ri": '[color=#0078AA]$v[/color]'; 46 | case "code sv": '[color=#880000]$v[/color]'; 47 | case "code sf": '[color=#880000]$v[/color]'; 48 | case "code uv": '[color=#440088]$v[/color]'; 49 | case "code uf": '[color=#880088]$v[/color]'; 50 | case "code fd": '[color=#440088]$v[/color]'; 51 | case "code pp": '[color=#0078AA]$v[/color]'; 52 | default: v; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/data/BuiltInConstants.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class BuiltInConstants { 8 | public static function get() 9 | return "ANSI_CHARSET|ARABIC_CHARSET|BALTIC_CHARSET|CHINESEBIG5_CHARSET|DEFAULT_CHARSET|EASTEUROPE_CHARSET|GB2312_CHARSET|GM_build_date|GM_version|GREEK_CHARSET|HANGEUL_CHARSET|HEBREW_CHARSET|JOHAB_CHARSET|MAC_CHARSET|OEM_CHARSET|RUSSIAN_CHARSET|SHIFTJIS_CHARSET|SYMBOL_CHARSET|THAI_CHARSET|TURKISH_CHARSET|VIETNAMESE_CHARSET|_sine|achievement_achievement_info|achievement_challenge_completed|achievement_challenge_completed_by_remote|achievement_challenge_launched|achievement_challenge_list_received|achievement_challenge_received|achievement_filter_all_players|achievement_filter_favorites_only|achievement_filter_friends_only|achievement_friends_info|achievement_leaderboard_info|achievement_msg_result|achievement_our_info|achievement_pic_loaded|achievement_player_info|achievement_purchase_info|achievement_show_achievement|achievement_show_bank|achievement_show_friend_picker|achievement_show_leaderboard|achievement_show_profile|achievement_show_purchase_prompt|achievement_show_ui|achievement_type_achievement_challenge|achievement_type_score_challenge|all|asset_background|asset_font|asset_object|asset_path|asset_room|asset_script|asset_sound|asset_sprite|asset_timeline|asset_unknown|audio_3d|audio_falloff_exponent_distance|audio_falloff_exponent_distance_clamped|audio_falloff_inverse_distance|audio_falloff_inverse_distance_clamped|audio_falloff_linear_distance|audio_falloff_linear_distance_clamped|audio_falloff_none|audio_mono|audio_new_system|audio_old_system|audio_stereo|bm_add|bm_dest_alpha|bm_dest_color|bm_dest_colour|bm_inv_dest_alpha|bm_inv_dest_color|bm_inv_dest_colour|bm_inv_src_alpha|bm_inv_src_color|bm_inv_src_colour|bm_max|bm_normal|bm_one|bm_src_alpha|bm_src_alpha_sat|bm_src_color|bm_src_colour|bm_subtract|bm_zero|browser_chrome|browser_firefox|browser_ie|browser_ie_mobile|browser_not_a_browser|browser_opera|browser_safari|browser_safari_mobile|browser_tizen|browser_unknown|browser_windows_store|buffer_bool|buffer_f16|buffer_f32|buffer_f64|buffer_fast|buffer_fixed|buffer_generalerror|buffer_grow|buffer_invalidtype|buffer_network|buffer_outofbounds|buffer_outofspace|buffer_s16|buffer_s32|buffer_s8|buffer_seek_end|buffer_seek_relative|buffer_seek_start|buffer_string|buffer_text|buffer_u16|buffer_u32|buffer_u64|buffer_u8|buffer_vbuffer|buffer_wrap|button_type|c_aqua|c_black|c_blue|c_dkgray|c_fuchsia|c_gray|c_green|c_lime|c_ltgray|c_maroon|c_navy|c_olive|c_orange|c_purple|c_red|c_silver|c_teal|c_white|c_yellow|cr_appstart|cr_arrow|cr_beam|cr_cross|cr_default|cr_drag|cr_handpoint|cr_help|cr_hourglass|cr_hsplit|cr_multidrag|cr_no|cr_nodrop|cr_none|cr_size_all|cr_size_nesw|cr_size_ns|cr_size_nwse|cr_size_we|cr_sqlwait|cr_uparrow|cr_vsplit|device_emulator|device_ios_ipad|device_ios_ipad_retina|device_ios_iphone|device_ios_iphone5|device_ios_iphone6|device_ios_iphone6plus|device_ios_iphone_retina|device_ios_unknown|device_tablet|display_landscape|display_landscape_flipped|display_portrait|display_portrait_flipped|dll_cdecl|dll_stdcall|ds_type_grid|ds_type_list|ds_type_map|ds_type_priority|ds_type_queue|ds_type_stack|ef_cloud|ef_ellipse|ef_explosion|ef_firework|ef_flare|ef_rain|ef_ring|ef_smoke|ef_smokeup|ef_snow|ef_spark|ef_star|ev_alarm|ev_animation_end|ev_boundary|ev_close_button|ev_collision|ev_create|ev_destroy|ev_draw|ev_draw_begin|ev_draw_end|ev_draw_post|ev_draw_pre|ev_end_of_path|ev_game_end|ev_game_start|ev_global_left_button|ev_global_left_press|ev_global_left_release|ev_global_middle_button|ev_global_middle_press|ev_global_middle_release|ev_global_press|ev_global_release|ev_global_right_button|ev_global_right_press|ev_global_right_release|ev_gui|ev_gui_begin|ev_gui_end|ev_joystick1_button1|ev_joystick1_button2|ev_joystick1_button3|ev_joystick1_button4|ev_joystick1_button5|ev_joystick1_button6|ev_joystick1_button7|ev_joystick1_button8|ev_joystick1_down|ev_joystick1_left|ev_joystick1_right|ev_joystick1_up|ev_joystick2_button1|ev_joystick2_button2|ev_joystick2_button3|ev_joystick2_button4|ev_joystick2_button5|ev_joystick2_button6|ev_joystick2_button7|ev_joystick2_button8|ev_joystick2_down|ev_joystick2_left|ev_joystick2_right|ev_joystick2_up|ev_keyboard|ev_keypress|ev_keyrelease|ev_left_button|ev_left_press|ev_left_release|ev_middle_button|ev_middle_press|ev_middle_release|ev_mouse|ev_mouse_enter|ev_mouse_leave|ev_mouse_wheel_down|ev_mouse_wheel_up|ev_no_button|ev_no_more_health|ev_no_more_lives|ev_other|ev_outside|ev_right_button|ev_right_press|ev_right_release|ev_room_end|ev_room_start|ev_step|ev_step_begin|ev_step_end|ev_step_normal|ev_trigger|ev_user0|ev_user1|ev_user10|ev_user11|ev_user12|ev_user13|ev_user14|ev_user15|ev_user2|ev_user3|ev_user4|ev_user5|ev_user6|ev_user7|ev_user8|ev_user9|fa_archive|fa_bottom|fa_center|fa_directory|fa_hidden|fa_left|fa_middle|fa_readonly|fa_right|fa_sysfile|fa_top|fa_volumeid|false|fb_login_default|fb_login_fallback_to_webview|fb_login_forcing_webview|fb_login_no_fallback_to_webview|forcing_safari|global|gp_axislh|gp_axislv|gp_axisrh|gp_axisrv|gp_face1|gp_face2|gp_face3|gp_face4|gp_padd|gp_padl|gp_padr|gp_padu|gp_select|gp_shoulderl|gp_shoulderlb|gp_shoulderr|gp_shoulderrb|gp_start|gp_stickl|gp_stickr|iap_available|iap_canceled|iap_ev_consume|iap_ev_product|iap_ev_purchase|iap_ev_restore|iap_ev_storeload|iap_failed|iap_purchased|iap_refunded|iap_status_available|iap_status_loading|iap_status_processing|iap_status_restoring|iap_status_unavailable|iap_status_uninitialised|iap_storeload_failed|iap_storeload_ok|iap_unavailable|input_type|lb_disp_none|lb_disp_numeric|lb_disp_time_ms|lb_disp_time_sec|lb_sort_ascending|lb_sort_descending|lb_sort_none|leaderboard_type_number|leaderboard_type_time_mins_secs|local|matrix_projection|matrix_view|matrix_world|mb_any|mb_left|mb_middle|mb_none|mb_right|network_config_connect_timeout|network_config_disable_reliable_udp|network_config_enable_reliable_udp|network_config_use_non_blocking_socket|network_socket_bluetooth|network_socket_tcp|network_socket_udp|network_type_connect|network_type_data|network_type_disconnect|network_type_non_blocking_connect|noone|of_challenge_lose|of_challenge_tie|of_challenge_win|os_3ds|os_android|os_bb10|os_ios|os_linux|os_macosx|os_ps3|os_ps4|os_psp|os_psvita|os_symbian|os_tizen|os_unknown|os_wiiu|os_win32|os_win8native|os_windows|os_winphone|os_xbox360|os_xboxone|other|ov_achievements|ov_community|ov_friends|ov_gamegroup|ov_players|ov_settings|path_action_continue|path_action_restart|path_action_reverse|path_action_stop|phy_debug_render_aabb|phy_debug_render_collision_pairs|phy_debug_render_coms|phy_debug_render_core_shapes|phy_debug_render_joints|phy_debug_render_obb|phy_debug_render_shapes|phy_joint_anchor_1_x|phy_joint_anchor_1_y|phy_joint_anchor_2_x|phy_joint_anchor_2_y|phy_joint_angle|phy_joint_angle_limits|phy_joint_damping_ratio|phy_joint_frequency|phy_joint_length_1|phy_joint_length_2|phy_joint_lower_angle_limit|phy_joint_max_force|phy_joint_max_length|phy_joint_max_motor_force|phy_joint_max_motor_torque|phy_joint_max_torque|phy_joint_motor_force|phy_joint_motor_speed|phy_joint_motor_torque|phy_joint_reaction_force_x|phy_joint_reaction_force_y|phy_joint_reaction_torque|phy_joint_speed|phy_joint_translation|phy_joint_upper_angle_limit|phy_particle_data_flag_category|phy_particle_data_flag_colour|phy_particle_data_flag_position|phy_particle_data_flag_typeflags|phy_particle_data_flag_velocity|phy_particle_flag_colourmixing|phy_particle_flag_elastic|phy_particle_flag_powder|phy_particle_flag_spring|phy_particle_flag_tensile|phy_particle_flag_viscous|phy_particle_flag_wall|phy_particle_flag_water|phy_particle_flag_zombie|phy_particle_group_flag_rigid|phy_particle_group_flag_solid|pi|pr_linelist|pr_linestrip|pr_pointlist|pr_trianglefan|pr_trianglelist|pr_trianglestrip|ps_change_all|ps_change_motion|ps_change_shape|ps_deflect_horizontal|ps_deflect_vertical|ps_distr_gaussian|ps_distr_invgaussian|ps_distr_linear|ps_force_constant|ps_force_linear|ps_force_quadratic|ps_shape_diamond|ps_shape_ellipse|ps_shape_line|ps_shape_rectangle|pt_shape_circle|pt_shape_cloud|pt_shape_disk|pt_shape_explosion|pt_shape_flare|pt_shape_line|pt_shape_pixel|pt_shape_ring|pt_shape_smoke|pt_shape_snow|pt_shape_spark|pt_shape_sphere|pt_shape_square|pt_shape_star|se_chorus|se_compressor|se_echo|se_equalizer|se_flanger|se_gargle|se_none|se_reverb|self|text_type|timezone_local|timezone_utc|true|ty_real|ty_string|ugc_filetype_community|ugc_filetype_microtrans|ugc_list_Favorited|ugc_list_Followed|ugc_list_Published|ugc_list_Subscribed|ugc_list_UsedOrPlayed|ugc_list_VotedDown|ugc_list_VotedOn|ugc_list_VotedUp|ugc_list_WillVoteLater|ugc_match_AllGuides|ugc_match_Artwork|ugc_match_Collections|ugc_match_ControllerBindings|ugc_match_IntegratedGuides|ugc_match_Items|ugc_match_Items_Mtx|ugc_match_Items_ReadyToUse|ugc_match_Screenshots|ugc_match_UsableInGame|ugc_match_Videos|ugc_match_WebGuides|ugc_query_AcceptedForGameRankedByAcceptanceDate|ugc_query_CreatedByFollowedUsersRankedByPublicationDate|ugc_query_CreatedByFriendsRankedByPublicationDate|ugc_query_FavoritedByFriendsRankedByPublicationDate|ugc_query_NotYetRated|ugc_query_RankedByNumTimesReported|ugc_query_RankedByPublicationDate|ugc_query_RankedByTextSearch|ugc_query_RankedByTotalVotesAsc|ugc_query_RankedByTrend|ugc_query_RankedByVote|ugc_query_RankedByVotesUp|ugc_result_success|ugc_sortorder_CreationOrderAsc|ugc_sortorder_CreationOrderDesc|ugc_sortorder_ForModeration|ugc_sortorder_LastUpdatedDesc|ugc_sortorder_SubscriptionDateDesc|ugc_sortorder_TitleAsc|ugc_sortorder_VoteScoreDesc|ugc_visiblity_friends_only|ugc_visiblity_private|ugc_visiblity_public|use_system_account|vertex_type_colour|vertex_type_float1|vertex_type_float2|vertex_type_float3|vertex_type_float4|vertex_type_ubyte4|vertex_usage_binormal|vertex_usage_blendindices|vertex_usage_blendweight|vertex_usage_colour|vertex_usage_depth|vertex_usage_fog|vertex_usage_normal|vertex_usage_position|vertex_usage_psize|vertex_usage_sample|vertex_usage_tangent|vertex_usage_textcoord|vk_add|vk_alt|vk_anykey|vk_backspace|vk_control|vk_decimal|vk_delete|vk_divide|vk_down|vk_end|vk_enter|vk_escape|vk_f1|vk_f10|vk_f11|vk_f12|vk_f2|vk_f3|vk_f4|vk_f5|vk_f6|vk_f7|vk_f8|vk_f9|vk_home|vk_insert|vk_lalt|vk_lcontrol|vk_left|vk_lshift|vk_multiply|vk_nokey|vk_numpad0|vk_numpad1|vk_numpad2|vk_numpad3|vk_numpad4|vk_numpad5|vk_numpad6|vk_numpad7|vk_numpad8|vk_numpad9|vk_pagedown|vk_pageup|vk_pause|vk_printscreen|vk_ralt|vk_rcontrol|vk_return|vk_right|vk_rshift|vk_shift|vk_space|vk_subtract|vk_tab|vk_up"; 10 | } -------------------------------------------------------------------------------- /src/data/BuiltinVariables.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class BuiltinVariables { 8 | public static function global() { 9 | return "application_surface|argument|argument0|argument1|argument10|argument11|argument12|argument13|argument14|argument15|argument2|argument3|argument4|argument5|argument6|argument7|argument8|argument9|argument_count|argument_relative|async_load|background_alpha|background_blend|background_color|background_colour|background_foreground|background_height|background_hspeed|background_htiled|background_index|background_showcolor|background_showcolour|background_visible|background_vspeed|background_vtiled|background_width|background_x|background_xscale|background_y|background_yscale|browser_height|browser_width|caption_health|caption_lives|caption_score|current_day|current_hour|current_minute|current_month|current_second|current_time|current_weekday|current_year|cursor_sprite|debug_mode|delta_time|display_aa|error_last|error_occurred|event_action|event_data|event_number|event_object|event_type|fps|fps_real|game_display_name|game_id|game_project_name|game_save_id|gamemaker_pro|gamemaker_registered|gamemaker_version|health|iap_data|instance_count|instance_id|keyboard_key|keyboard_lastchar|keyboard_lastkey|keyboard_string|lives|mouse_button|mouse_lastbutton|mouse_x|mouse_y|os_browser|os_device|os_type|os_version|pointer_invalid|pointer_null|program_directory|room|room_caption|room_first|room_height|room_last|room_persistent|room_speed|room_width|score|secure_mode|show_health|show_lives|show_score|temp_directory|transition_color|transition_kind|transition_steps|undefined|view_angle|view_current|view_enabled|view_hborder|view_hport|view_hspeed|view_hview|view_object|view_surface_id|view_vborder|view_visible|view_vspeed|view_wport|view_wview|view_xport|view_xview|view_yport|view_yview|webgl_enabled|working_directory"; 10 | } 11 | public static function instance() { 12 | return "alarm|bbox_bottom|bbox_left|bbox_right|bbox_top|depth|direction|friction|gravity|gravity_direction|hspeed|id|image_alpha|image_angle|image_blend|image_index|image_number|image_single|image_speed|image_xscale|image_yscale|mask_index|object_index|path_endaction|path_index|path_orientation|path_position|path_positionprevious|path_scale|path_speed|persistent|phy_active|phy_angular_damping|phy_angular_velocity|phy_bullet|phy_col_normal_x|phy_col_normal_y|phy_collision_points|phy_collision_x|phy_collision_y|phy_com_x|phy_com_y|phy_dynamic|phy_fixed_rotation|phy_inertia|phy_kinematic|phy_linear_damping|phy_linear_velocity_x|phy_linear_velocity_y|phy_mass|phy_position_x|phy_position_xprevious|phy_position_y|phy_position_yprevious|phy_rotation|phy_sleeping|phy_speed|phy_speed_x|phy_speed_y|solid|speed|sprite_height|sprite_index|sprite_width|sprite_xoffset|sprite_yoffset|timeline_index|timeline_loop|timeline_position|timeline_running|timeline_speed|visible|vspeed|x|xprevious|xstart|y|yprevious|ystart"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/data/DataActions.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | import types.*; 3 | import types.code.*; 4 | 5 | /** 6 | * ... 7 | * @author YellowAfterlife 8 | */ 9 | class DataActions { 10 | public static function run(list:Array):Void { 11 | /// Number comparison options (without brackets) 12 | var ncmp:String = "equal to|smaller than|larger than" // 8.x 13 | + "|less than or equal to|greater than or equal to|less than|greater than"; 14 | var r:NodeType; 15 | var section:String = ""; 16 | /// 17 | inline function id(name:String):String { 18 | return section + ": " + name; 19 | } 20 | /// Adds a node type. 21 | inline function add(name:String, code:String, ico:Int) { 22 | list.push(r = new NodeAction(id(name), code, ico)); 23 | } 24 | /// Adds a control (indenting) node type. 25 | inline function ctl(name:String, code:String, ico:Int) { 26 | list.push(r = new NodeAction(id(name), code, ico)); 27 | r.isIndent = true; 28 | } 29 | list.push(new NodeAction("Unknown Action", "Unknown Action", 8)); 30 | //{ 01_move 31 | section = "move"; 32 | add("Move Fixed", "@wstart moving in directions @e with speed set @rto @e", 0); 33 | add("Move Free", "@wset speed @rto @{eu} and direction to @e", 1); 34 | add("Move Towards", "@wstart moving @rin the direction of position (@e,@e) with speed @e", 2); 35 | add("Speed Horizontal", "@wset the horizontal speed @rto @e", 100); 36 | add("Speed Vertical", "@wset the vertical speed @rto @e", 101); 37 | add("Set Gravity", "@wset the gravity @rto @e in direction @e", 102); 38 | add("Reverse Horizontal", "@wreverse horizontal direction", 200); 39 | add("Reverse Vertical", "@wreverse vertical direction", 201); 40 | add("Set Friction", "@wset the friction @rto @e", 202); 41 | add("Jump to Position", "@wjump to @rposition (@e,@e)", 300); // GM8 42 | add("Jump to Position", "@wjump @rto position (@e,@e)", 300); // GMS 43 | add("Jump to Start", "@wjump to the start position", 301); 44 | add("Jump to Random", "@wjump to a random position with hor snap @{eu} and vert snap @e", 302); 45 | add("Align to Grid", "@walign position to a grid with cells of @e by @e pixels", 400); 46 | add("Wrap Screen", "@wwrap @[horizontal|vertical|in both directions] when an instance moves outside the room", 401); 47 | add("Move to Contact", "@wmove in direction @e at most @e till a contact with @[solid objects|all objects]", 500); 48 | add("Bounce", "@wbounce @[not precisely|precisely] against @[solid objects|all objects]", 501); 49 | add("Set Path", "@wset the @[relative|absolute] path to @i with speed @{eu} and at the end @[stop|continue from start|continue from here|reverse]", 600); 50 | add("End Path", "@wend the path", 601); 51 | add("Path Position", "@wset the position on the path @rto @e", 700); 52 | add("Path Speed", "@wset the speed for the path @rto @e", 701); 53 | add("Step Towards", "@wperform a step @rtowards position (@e,@e) with speed @e stop at @[solid only|all instances]", 800); 54 | add("Step Avoiding", "@wperform a step @rtowards position (@e,@e) with speed @e avoiding @[solid only|all instances]", 801); 55 | //} 56 | //{ 02_main1 57 | section = "main1"; 58 | add("Create Moving", "@wcreate instance of object @i at @rposition (@e,@e) with speed @e in direction @e", 4); 59 | add("Create Instance", "@wcreate instance of object @i at @rposition (@e,@e)", 3); 60 | add("Create Random", "@wcreate instance of object @i, @i, @i, or @i at @rposition (@e,@e)", 5); 61 | add("Change Instance", "@wchange the instance into object @i, @[yes|not|no] performing events", 103); 62 | add("Destroy Instance", "@wdestroy the instance", 104); 63 | add("Destroy at Position", "kill all instances at @rposition (@e,@e)", 105); 64 | add("Change Sprite", "@wset the sprite to @i with subimage @{eu} and speed @e", 203); 65 | add("Transform Sprite", "@wscale the sprite with @e in the xdir, @e in the ydir, rotate over @e, and @[no mirroring|mirror horizontally|flip vertically|mirror and flip]", 204); 66 | add("Color Sprite", "@wblend the sprite with color @c and alpha value @e", 205); 67 | add("Play Sound", "play sound @i; looping: @[play|loop]", 303); 68 | add("Stop Sound", "stop sound @i", 304); 69 | ctl("Check Sound", "if sound @i is @Nplaying", 305); 70 | { // GM<=8.1 room actions 71 | var efl = "|Create from left|Create from right|Create from top|Create from bottom|Create from center|Shift from left|Shift from right|Shift from top|Shift from bottom|Interlaced from left|Interlaced from right|Interlaced from top|Interlaced from bottom|Push from left|Push from right|Push from top|Push from bottom|Rotate left|Rotate right|Blend|Fade out and in"; 72 | add("Previous Room", 'go to previous room with transition effect @[$efl]', 403); 73 | add("Next Room", 'go to next room with transition effect @[$efl]', 404); 74 | add("Restart Room", 'restart the current room with transition effect @[$efl]', 405); 75 | add("Different Room", 'go to room @i with transition effect @[$efl]', 503); 76 | } 77 | // GMS room actions: 78 | add("Previous Room", "Go to previous room", 403); 79 | add("Next Room", "Go to next room", 404); 80 | add("Restart Room", "Restart the current room", 405); 81 | add("Different Room", "Go to room @i", 503); 82 | ctl("Check Previous", "if previous room exists", 504); 83 | ctl("Check Next", "if next room exists", 505); 84 | //} 85 | //{ 03_main2 86 | section = "main2"; 87 | add("Set Alarm", "@wset @[Alarm 0|Alarm 1|Alarm 2|Alarm 3|Alarm 4|Alarm 5|Alarm 6|Alarm 7|Alarm 8|Alarm 9|Alarm 10|Alarm 11] @rto @e", 6); 88 | add("Sleep", "sleep @e milliseconds; redrawing the screen: @[true|false]", 7); 89 | // 90 | add("Set Time Line", "@wset time line @i at position @e, @[Start Immediately|Don't Start] and @[Don't Loop|Loop]", 106); 91 | add("Time Line Position", "@wset the time line position @rto @e[true|false]", 107); 92 | add("Time Line Speed", "@wset the speed of the time line @rto @e[true|false]", 108); 93 | add("Start Time Line", "@wstart or resume the current time line", 206); 94 | add("Pause Time Line", "@wpause the current time line", 207); 95 | add("Stop Time Line", "@wstop and reset the current time line", 208); 96 | // 97 | add("Display Message", "display message: @L", 306); 98 | add("Show Info", "show the game info", 307); 99 | add("Open URL", "Open a URL: @L", 308); 100 | // 101 | add("Splash Text", "show the text in file @L", 406); 102 | add("Splash Image", "show the image in file @L", 407); 103 | add("Splash Web", "show the webpage @{su} in @[Game Window|Browser]", 408); 104 | add("Splash Video", "show the video in file @{su} @[0|Don't Loop|Loop]", 506); 105 | add("Splash Settings", "change splash settings: caption: @{su}, @[Game Window|Normal Window|Full Screen], @[Show|Don't Show] close button, @[Close|Don't Close] on escape key, @[Close|Don't Close] on mouse button", 507); 106 | // 107 | add("Restart Game", "restart the game", 606); 108 | add("End Game", "end the game", 607); 109 | add("Save Game", "save the game in the file @L", 706); 110 | add("Load Game", "load the game from the file @L", 707); 111 | // 112 | add("Replace Sprite", "replace the sprite @i with the image in file @{su} with @e subimages", 806); 113 | add("Replace Background", "replace the background @i with the image in file @L", 808); 114 | //} 115 | //{ 04_control 116 | section = "control"; 117 | ctl("Check Empty", "@wif @rposition (@e,@e) is @Ncollision free for @[Only solid|solid|all] objects", 9); 118 | ctl("Check Collision", "@wif @rposition (@e,@e) gives @Na collision with @[Only solid|solid|all] objects", 10); 119 | ctl("Check Object", "@wif at @rposition (@e,@e) there is @Nobject @i", 11); 120 | ctl("Test Instance Count", "if number of objects @i is @N@[equal to|smaller than|larger than|Equal to|Smaller than|Larger than] @e", 109); 121 | ctl("Test Chance", "with a chance of 1 out of @e do @Nperform the next action", 110); 122 | // GMS uses a variant with duplicate spaces?: 123 | ctl("Test Chance", "with a chance of 1 out of @e do @N perform the next action", 110); 124 | ctl("Check Question", "if the player does @Nsay yes to the question: @L", 111); 125 | ctl("Test Expression", "@wif expression @e is @Ntrue", 209); 126 | ctl("Check Mouse", "if @[no|left|right|middle] mouse button is @Npressed", 210); 127 | ctl("Check Grid", "@wif object is @Naligned with grid with cells of @e by @e pixels", 211); 128 | r = types.NodeOpen.inst = new types.NodeOpen(id("Start Block"), "start of a block", 309); 129 | list.push(r); 130 | ctl("Else", "else", 310); 131 | add("Exit Event", "exit this event", 311); 132 | r = types.NodeClose.inst = new types.NodeClose(id("End Block"), "end of a block", 409); 133 | list.push(r); 134 | ctl("Repeat", "repeat next action (block) @e times", 410); 135 | add("Call Parent Event", "call the inherited event of the parent object", 411); 136 | list.push(new types.code.NodeCodeBlock(id("Execute Code"), "@wexecute code:\n\n@{code}", 509)); 137 | //{ 138 | add("Execute Script", "@wexecute script @i with arguments (@e,@e,@e,@e,@e)", 510); 139 | //} 140 | list.push(new types.NodeComment(id("Comment"), "COMMENT: @L", 511)); 141 | add("Set Variable", "@wset variable @e @rto @e", 609); 142 | add("Draw Variable", "@wat @rposition (@e,@e) draw the value of: @e", 611); 143 | //} 144 | //{ 05_score 145 | add("Set Score", "set the score @rto @e", 12); 146 | ctl("Test Score", 'if score is @N@[$ncmp] @e', 13); 147 | add("Draw Score", "at @rposition (@e,@e) draw the value of score with caption @L", 14); 148 | add("Show Highscore", "show the highscore table\n" 149 | + "@]background: @i\n" 150 | + "@]@[don't show|show] the border\n" 151 | + "@]new color: @c, other color: @c\n" 152 | + "@]Font: @{su},@e,@e,@e,@e,@e,@e", 112); 153 | // name,size,color,bold,italic,underline,strikeout 154 | add("Clear Highscore", "clear the highscore table", 113); 155 | add("Set Lives", "set the number of lives @rto @e", 212); 156 | ctl("Test Lives", 'If lives are @N@[$ncmp] @e', 213); 157 | add("Draw Lives", "at @rposition (@e,@e) draw the number of lives with caption @L", 214); 158 | add("Draw Life Images", "draw the lives @rat (@e,@e) with sprite @i", 312); 159 | add("Set Health", "set the health @rto @e", 412); 160 | ctl("Test Health", 'if health is @N@[$ncmp] @e', 413); 161 | add("Draw Health", "draw the health bar with @rsize (@e,@e,@e,@e) with back color @[none|black|gray|silver|white|maroon|green|olive|navy|purple|teal|red|lime|yellow|blue|fuchsia|aqua] and bar color @[green to red|white to black|black|gray|silver|white|maroon|green|olive|navy|purple|teal|red|lime|yellow|blue|fuchsia|aqua]", 414); 162 | add("Score Caption", "set the information in the window caption:\n" 163 | + "@]@[don't show|show] score with caption @L\n" 164 | + "@]@[don't show|show] lives with caption @L\n" 165 | + "@]@[don't show|show] health with caption @L", 512); 166 | //} 167 | //{ 06_extra 168 | add("Create Part System", "Create a particle system at drawing depth @i.", 15); 169 | add("Part System Destroy", "Destroy particle system.", 16); 170 | add("Part System Clear", "Clear particle system of all particles.", 17); 171 | add("Part Type Create", "Create particle of type @[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15], shape of @[pixel|disk|square|line|star|circle|ring|sphere|flare|spark|explosion|cloud|smoke|snow] and sprite @i, with min/max size @e and @e where size increment is @e.", 115); 172 | add("Part Type Color", "Set the color of particle type @[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15] where color mixing is @[mixed|changing] with colors @c and @c and start and end alpha of @e and @e.", 116); 173 | add("Part Type Life", "Set the life of particle type @i, with a min and max life of @e and @e.", 117); 174 | add("Part Type Speed", "Set the speed of particle type @i, with a min/max speed of @e and @e, min/max direction of @e and @e with a friction of @e.", 215); 175 | add("Part Type Gravity", "Set the gravity of particle type @i, with gravity strength of @e and gravity direction of @e.", 216); 176 | add("Part Type Secondary", "Tell particle type @i to emit particle type of @i for step count @e with a death particle type of @i and a death count of @e.", 217); 177 | add("Create Part Emitter", "Create a particle emittter with an ID of @i, shape of @i and an area defined by vertices (@e,@e) and (@e,@e).", 315); 178 | add("Destroy Part Emitter", "Destroy particle emitter with an ID of @i.", 316); 179 | add("Emitter Burst", "For emiiter with an ID of @i, burst particles of type @i, with a count of @e.", 317); 180 | add("Emitter Stream", "For emitter with an ID of @i, stream particles of type @i, with a count of @e.", 415); 181 | add("Draw Cursor", "draw cursor with sprite @i and @[don't show|show] system cursor.", 515); 182 | //} 183 | //{ 07_draw 184 | add("Draw Self", "@wDraw the instance", 20); 185 | add("Draw Sprite", "@wat @rposition (@e,@e) draw image @e of sprite @i", 18); 186 | add("Draw Background", "at @rposition (@e,@e) draw background @i; tiled: @[true|false]", 19); 187 | // 188 | add("Draw Text Scaled", "@wat @rposition (@e,@e) draw text: @{su} scaled horizontally with @e, vertically with @e, and rotated over @e degrees", 119); 189 | add("Draw Text", "@wat @rposition (@e,@e) draw text: @L", 118); 190 | // 191 | add("Draw Rectangle", "@wdraw rectangle with @rvertices (@e,@e) and (@e,@e), @[filled|outline]", 218); 192 | add("Horizontal Gradient", "@wdraw a horizontal gradient filled rectangle with @rvertices (@e,@e) and (@e,@e) and colors @c to @c", 219); 193 | add("Vertical Gradient", "@wdraw a vertical gradient filled rectangle with @rvertices (@e,@e) and (@e,@e) and colors @c to @c", 220); 194 | // 195 | add("Draw Ellipse", "@wdraw an ellipse with @rvertices (@e,@e) and (@e,@e), @[filled|outline]", 318); 196 | add("Gradient Ellipse", "@wdraw a gradient filled ellipse with @rvertices (@e,@e) and (@e,@e) and colors @c and @c", 319); 197 | // 198 | add("Draw Line", "@wdraw a line @rbetween (@e,@e) and (@e,@e)", 418); 199 | add("Draw Arrow", "@wdraw an arrow @rbetween (@e,@e) and (@e,@e) with size @e", 419); 200 | // 201 | add("Set Color", "set the drawing color to @c", 518); 202 | add("Set Font", "set the font for drawing text to @i and align @[left|center|right]", 519); 203 | add("Set Full Screen", "set screen mode to: @[switch|window|fullscreen]", 520); 204 | // 205 | add("Take Snapshot", "take a snapshot image of the game and store it in the file @L", 618); 206 | add("Create Effect", "@wcreate a @[small|medium|large] effect of type @[explosion|ring|ellipse|firework|smoke|smoke up|star|spark|flare|cloud|rain|snow] @rat (@e,@e) of@]color @c @[below objects|above objects]", 619); 207 | //} 208 | //{ low priority 209 | section = "control"; 210 | ctl("Test Variable", '@wif @e is @N@[$ncmp] @e', 610); 211 | //} 212 | //{ non-standard 213 | list.push(new NodeCodeRaw("GML block", "```\n@{code}", -1)); 214 | list.push(new NodeCodeRaw("GML line", "```@e", -1)); 215 | list.push(new NodeCodeScript("GML script", "#define @L\n@{code}", -1)); 216 | //} 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /src/data/DataEvents.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | import types.NodeEvent; 3 | 4 | /** 5 | * ... 6 | * @author YellowAfterlife 7 | */ 8 | class DataEvents { 9 | public static function get():Array { 10 | var events = []; 11 | inline function add(id:String, icon:Int) { 12 | events.push(new NodeEvent(id, icon)); 13 | } 14 | add("Create Event:", 0); 15 | add("Destroy Event:", 1); 16 | for (i in 0 ... 12) add('Alarm Event for alarm $i:', 2); 17 | add("Begin Step Event:", 3); 18 | add("Step Event:", 3); 19 | add("End Step Event:", 3); 20 | add("Draw Event:", 5); 21 | add("Collision Event with object @i:", 6); 22 | // 23 | for (b in ["Left", "Right", "Middle"]) { 24 | for (t in ["Button", "Pressed", "Released"]) { 25 | add('Mouse Event for $b $t:', 7); 26 | add('Mouse Event for Glob $b $t:', 7); 27 | } 28 | } 29 | for (m in ["", "No Button", "Mouse Enter", "Mouse Leave", 30 | "Mouse Wheel Up", "Mouse Wheel Down"]) { 31 | add('Mouse Event for $m:', 7); 32 | } 33 | //add( 34 | for (i in 0 ... 3) { 35 | var et = ["Keyboard", "Key Press", "Key Release"][i]; 36 | var ei = 8 + i; 37 | add(et + " Event for @i Key:", ei); 38 | add(et + " Event for @i-key Key:", ei); 39 | } 40 | // other events: 41 | for (i in 0 ... 16) add('Other Event: User Defined $i:', 4); 42 | for (i in 0 ... 8) { 43 | add('Other Event: Outside View $i:', 4); 44 | add('Other Event: Boundary View $i:', 4); 45 | } 46 | for (s in ["Outside Room", "Intersect Boundary", 47 | "Game Start", "Game End", "Room Start", "Room End", 48 | "No More Lives", "No More Health", 49 | "Animation End", "End Of Path", "Close Button"]) { 50 | add('Other Event: $s:', 4); 51 | } 52 | add("Unknown Event (@{su}:@{su}):", 4); 53 | return events; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/data/DataGML.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | import matcher.MatchResult; 3 | import types.NodeAction; 4 | import Code; 5 | import data.DataGML.DataGMLTools.*; 6 | using data.DataGML.DataGMLTools; 7 | /** 8 | * ... 9 | * @author YellowAfterlife 10 | */ 11 | class DataGML { 12 | static var moveFixedDirs = [225, 270, 315, 180, 0, 0, 135, 90, 45]; 13 | public static function run() { 14 | var section:String; 15 | var f:MatchResult->String; 16 | inline function add(name:String, func:MatchResult->String):Void { 17 | NodeAction.actions[section + ": " + name].gmlFunc = func; 18 | } 19 | inline function add2(s1:String, s2:String, f1:MatchResult->String) { 20 | f = f1; 21 | NodeAction.actions[section + ": " + s1].gmlFunc = f; 22 | NodeAction.actions[section + ": " + s2].gmlFunc = f; 23 | } 24 | inline function addx(s:String, func:MatchResult->String):Void { 25 | f = func; 26 | NodeAction.actions[section + ": " + s].gmlFunc = f; 27 | NodeAction.actions[section + ": " + s + "1"].gmlFunc = f; 28 | } 29 | //{ 01_move 30 | section = "move"; 31 | add("Move Fixed", function(m) { 32 | var c:CodeNode = m.values[0][0]; 33 | var s:String; 34 | var op = octx(m, []); 35 | switch (c) { 36 | case CoNumber(d, _) if (d.length == 9): { 37 | inline function dc(i:Int):Bool { 38 | return (d.charCodeAt(i) == "1".code); 39 | } 40 | var n:Int = 0; 41 | var i:Int; 42 | i = -1; while (++i < 9) if (dc(i)) n++; 43 | if (n == 0) return ""; 44 | var dcx = dc(4); 45 | if (dcx) { 46 | if (n == 1) return '${op}speed = 0;\n${op}direction = 0;'; 47 | s = xrna(m, "speed", 1); 48 | if (s != "") s += ";\n\t"; 49 | s = 'if (random($n) < 1) {\n\tspeed = 0;\n\tdirection = 0;\n} else {\n\t$s'; 50 | n--; 51 | } else { 52 | s = xrna(m, '${op}speed', 1); 53 | if (s != "") s += ";\n"; 54 | } 55 | if (n > 1) { 56 | s += '${op}direction = choose('; 57 | n = 0; i = -1; 58 | while (++i < 9) if (i != 4 && dc(i)) { 59 | if (++n > 1) s += ", "; 60 | s += moveFixedDirs[i]; 61 | } 62 | s += ");"; 63 | } else { 64 | i = -1; while (++i < 9) if (i != 4 && dc(i)) { 65 | s += '${op}direction = ' + moveFixedDirs[i]; 66 | } 67 | } 68 | if (dcx) s += ";\n}"; 69 | return s; 70 | }; 71 | default: 72 | } 73 | // this fallback should not ever trigger under normal conditions. 74 | s = 'action_move("' + xs(m, 0) + '", ' + xs(m, 1) + ');'; 75 | if (m.relative) { 76 | s = 'argument_relative = true;\n$s\nargument_relative = false;'; 77 | } 78 | return s; 79 | }); 80 | add("Move Free", function(m) { 81 | var s = m.relative ? "motion_add" : "motion_set"; 82 | return s + "(" + xs(m, 1) + ", " + xs(m, 0) + ");"; 83 | }); 84 | add("Move Towards", function(m) { 85 | return 'move_towards_point(${xrn(m, "x", 0)}, ${xrn(m, "y", 1)}, ${xs(m, 2)});'; 86 | }); 87 | add("Speed Horizontal", function(m) return xrna(m, "hspeed", 0).sc()); 88 | add("Speed Vertical", function(m) return xrna(m, "vspeed", 0).sc()); 89 | add("Set Gravity", function(m) { 90 | return join(xrna(m, "gravity", 0), ";\n", xrna(m, "gravity_direction", 1)).sc(); 91 | }); 92 | add("Reverse Horizontal", function(_) return "hspeed *= -1;"); 93 | add("Reverse Vertical", function(_) return "vspeed *= -1;"); 94 | add("Set Friction", function(m) return xrna(m, "friction", 0).sc()); 95 | // 96 | addx("Jump to Position", function(m) { 97 | var op = octx(m, [0, 1]); 98 | return join(xrna(m, op + "x", 0), ";\n", xrna(m, op + "y", 1)).sc(); 99 | }); 100 | add("Jump to Start", function(m) { 101 | var op = octx(m, []); 102 | return '${op}x = ${op}xstart;' 103 | + '\n${op}x = ${op}ystart;'; 104 | }); 105 | add("Jump to Random", function(m) { 106 | return "action_move_random(" + xs(m, 0) + ", " + xs(m, 1) + ");"; 107 | }); 108 | // 109 | add("Align to Grid", function(m) { 110 | //return "action_snap(" + xs(m, 0) + ", " + xs(m, 1) + ")"; 111 | var op = octx(m, [0, 1]); 112 | var gx = xs(m, 0); 113 | var gy = xs(m, 1); 114 | return '${op}x = floor(${op}x / $gx) * $gx;' 115 | + '\n${op}y = floor(${op}y / $gy) * $gy;'; 116 | }); 117 | add("Wrap Screen", function(m) { 118 | var s = vs(m, 0); 119 | var i; switch (s) { 120 | case "horizontal": i = 0; 121 | case "vertical": i = 1; 122 | default: i = 2; 123 | } 124 | return 'action_wrap($i /* $s */);'; 125 | }); 126 | // 127 | add("Move to Contact", function(m) { 128 | return "move_contact_" + (vs(m, 2) == "all objects" ? "all" : "solid") 129 | + "(" + xs(m, 0) + ", " + xs(m, 1) + ");"; 130 | }); 131 | add("Bounce", function(m) { 132 | return "move_bounce_" + (vs(m, 1) == "all objects" ? "all" : "solid") 133 | + "(" + (vs(m, 0) == "precisely" ? "true" : "false") + ");"; 134 | }); 135 | // 136 | add("Set Path", function(m) { 137 | var s = vs(m, 3), i:Int, e:String; 138 | switch (s) { 139 | case "continue from start": i = 1; e = "restart"; 140 | case "continue from here": i = 2; e = "continue"; 141 | case "reverse": i = 3; e = "reverse"; 142 | default: i = 0; e = "stop"; 143 | } 144 | var pt = vr(m, 1); 145 | return 'path_start($pt, ${xs(m,2)}, $i /* $e */, ${vb(m,3,"absolute")});'; 146 | }); 147 | add("End Path", function(m) return "path_end();"); 148 | add("Path Position", function(m) return xrna(m, "path_position", 0).sc()); 149 | add("Path Speed", function(m) return xrna(m, "path_speed", 0).sc()); 150 | // 151 | add("Step Towards", function(m) { 152 | return 'mp_linear_step(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xs(m,2)}, ' 153 | + vb(m, 3, "all instances") + ");"; 154 | }); 155 | add("Step Avoiding", function(m) { 156 | return 'mp_potential_step(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xs(m,2)}, ' 157 | + vb(m, 3, "all instances") + ");"; 158 | }); 159 | //} 160 | //{ 02_main1 161 | section = "main1"; 162 | add("Create Instance", function(m) { 163 | var op = octx(m, [1, 2]); 164 | var ox = xrn(m, op + "x", 1); 165 | var oy = xrn(m, op + "y", 2); 166 | return 'instance_create($ox, $oy, ${vr(m,0)});'; 167 | }); 168 | add("Create Moving", function(m) { 169 | return 'var __newinst__;' 170 | +'\n__newinst__ = instance_create(${xrn(m,"x",1)}, ${xrn(m,"y",2)}, ${vr(m,0)});' 171 | +'\n__newinst__.speed = ${xs(m,3)};' 172 | +'\n__newinst__.direction = ${xs(m,4)};'; 173 | }); 174 | add("Create Random", function(m) { 175 | var found = 0; 176 | var choose = ""; 177 | for (i in 0 ... 4) { 178 | var obj = vr(m, i); 179 | switch (obj) { 180 | case "-1", "-100": { }; 181 | default: { 182 | if (found > 0) choose += ", "; 183 | choose += obj; 184 | found += 1; 185 | }; 186 | } 187 | } 188 | if (found == 0) return ""; // not a valid action 189 | if (found > 1) choose = "choose(" + choose + ")"; 190 | var op = octx(m, [4, 5]); 191 | var ox = xrn(m, op + "x", 4); 192 | var oy = xrn(m, op + "y", 5); 193 | return 'instance_create($ox, $oy, $choose);'; 194 | }); 195 | add("Change Instance", function(m) return 'instance_change(${vr(m,0)}, ${vb(m,1,"yes")});'); 196 | add("Destroy Instance", function(_) return "instance_destroy();"); 197 | add("Destroy at Position", function(m) { 198 | var op = octx(m, [4, 5]); 199 | var ox = xrn(m, op + "x", 0); 200 | var oy = xrn(m, op + "y", 1); 201 | return 'action_kill_position($ox, $oy)'; 202 | //return 'if (position_meeting(${xrn(m,"x",0)},${xrn(m,"y",1)},id)) { instance_destroy(); }'; 203 | }); 204 | add("Change Sprite", function(m) { 205 | var op = octx(m, [0, 1, 2]); 206 | return '${op}sprite_index = ${vr(m,0)};' 207 | + '\n${xva(m,op+"image_index",1)};' 208 | + '\n${xva(m,op+"image_speed",2)};'; 209 | }); 210 | add("Transform Sprite", function(m) { 211 | var x = xs(m, 0); 212 | var y = xs(m, 1); 213 | switch (vs(m, 3)) { 214 | case "mirror horizontally": x = "-" + x; 215 | case "flip vertically": y = "-" + y; 216 | case "mirror and flip": x = "-" + x; y = "-" + y; 217 | } 218 | if (StringTools.startsWith(x, "--")) x = x.substring(2); 219 | if (StringTools.startsWith(y, "--")) y = y.substring(2); 220 | var op = octx(m, [0, 1, 2]); 221 | return '${op}image_xscale = $x;' 222 | +'\n${op}image_yscale = $y;' 223 | +'\n${op}image_angle = ${xs(m,2)};'; 224 | }); 225 | add("Color Sprite", function(m) { 226 | var op = octx(m, [1]); 227 | return '${op}image_blend = ${vcol(m,0)};' 228 | +'\n${op}image_alpha = ${xs(m,1)};'; 229 | }); 230 | // 231 | add("Play Sound", function(m) { 232 | var sound = vr(m, 0); 233 | var loop = (vb(m, 1, "loop") == "true"); 234 | if (Conf.gmlNewAudio) { 235 | return 'audio_play_sound($sound, 0, $loop);'; 236 | } else { 237 | return 'sound_${loop?"loop":"play"}($sound);'; 238 | } 239 | }); 240 | add("Stop Sound", function(m) { 241 | var sound = vr(m, 0); 242 | if (Conf.gmlNewAudio) { 243 | return 'audio_stop_sound($sound);'; 244 | } else return 'sound_stop($sound);'; 245 | }); 246 | add("Check Sound", function(m) { 247 | var fn = (Conf.gmlNewAudio ? "audio_is_playing" : "sound_isplaying"); 248 | return 'if (${xn(m)}$fn(${vr(m,0)}))'; 249 | }); 250 | // todo: pre-GMS transition actions 251 | add("Previous Room1", function(_) return 'room_goto_previous();'); 252 | add("Next Room1", function(_) return 'room_goto_next();'); 253 | add("Restart Room1", function(_) return 'room_restart();'); 254 | add("Different Room1", function(m) return 'room_goto(${vr(m,0)});'); 255 | // 256 | add("Check Previous", function(m) return 'if (${xn(m)}room_exists(room_previous(room)))'); 257 | add("Check Next", function(m) return 'if (${xn(m)}room_exists(room_next(room)))'); 258 | //} 259 | //{ 03_main2 260 | section = "main2"; 261 | add("Set Alarm", function(m) { 262 | var ai:String = m.values[0]; 263 | var op = octx(m, [1]); 264 | return xrna(m, op + "alarm[" + ai.substring(6) + "]", 1).sc(); 265 | }); 266 | add("Sleep", function(m) return 'sleep(${xs(m,0)});'); 267 | 268 | //timelines 269 | add("Set Time Line", function(m) { 270 | var op = octx(m, [0, 1, 2, 3]); 271 | var tlRun = m.values[2] == "Start Immediately"; 272 | var tlLoop = m.values[3] == "Loop"; 273 | return '${op}timeline_index = ${vr(m,0)};' 274 | +'\n${op}timeline_position = ${xs(m,1)};' 275 | +'\n${op}timeline_running = $tlRun;' 276 | +'\n${op}timeline_loop = $tlLoop;'; 277 | }); 278 | add("Time Line Position", function(m) { 279 | var ai:String = m.values[0]; 280 | return xrna(m, octx(m, [1]) + "timeline_position", m.values[1]).sc(); 281 | }); 282 | add("Time Line Speed", function(m) { 283 | var ai:String = m.values[0]; 284 | return xrna(m, octx(m, [1]) + "timeline_speed", m.values[1]).sc(); 285 | }); 286 | add("Start Time Line", function(m) { 287 | return octx(m, []) + 'timeline_running = true;'; 288 | }); 289 | add("Pause Time Line", function(m) return 'timeline_running = false;'); 290 | add("Stop Time Line", function(m) { 291 | var op = octx(m, []); 292 | return '${op}timeline_running = false;' 293 | +'\n${op}timeline_position = 0;'; 294 | }); 295 | // 296 | add("Display Message", function(m) return 'show_message(${ss(vs(m,0))});'); 297 | add("Show Info", function(_) return 'show_info();'); 298 | add("Open URL", function(m) return 'url_open(${vstr(m,0)});'); 299 | // 300 | add("Restart Game", function(m) return "game_restart();"); 301 | add("End Game", function(m) return "game_end();"); 302 | add("Save Game", function(m) return 'game_save(${ss(vs(m,0))});'); 303 | add("Load Game", function(m) return 'game_load(${ss(vs(m,0))});'); 304 | add("Replace Sprite", function(m) return 'sprite_replace(${vr(m,0)}, ${ss(vs(m,1))}, ${xs(m,2)}, false, false, 0, 0);'); 305 | add("Replace Background", function(m) return 'background_replace(${vr(m,0)}, ${ss(vs(m,1))}, false, false);'); 306 | //} 307 | //{ 04_control 308 | section = "control"; 309 | inline function check_func(m) { 310 | return "place_" + (vs(m, 2) == "all" ? "empty" : "free") + "(" 311 | + xrn(m, "x", 0) + ", " + xrn(m, "y", 1) + ")"; 312 | } 313 | add("Check Empty", function(m) { 314 | return "if (" + cs(m.not, "!") + check_func(m) + ")"; 315 | }); 316 | add("Check Collision", function(m) { 317 | return "if (" + cs(!m.not, "!") + check_func(m) + ")"; 318 | }); 319 | add("Check Object", function(m) { 320 | return 'if (${xn(m)}place_meeting(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vr(m,2)}))'; 321 | }); 322 | // 323 | add("Test Instance Count", function(m) { 324 | return 'if (instance_number(${vr(m,0)}) ${vcmp(m,1)} ${xs(m,2)})'; 325 | }); 326 | addx("Test Chance", function(m) { 327 | return 'if (random(${xs(m,0)}) ${m.not ? ">=" : "<"} 1)'; 328 | }); 329 | add("Check Question", function(m) { 330 | return 'if (${xn(m)}show_question("${vs(m,0)}"))'; 331 | }); 332 | // 333 | add("Test Expression", function(m) return 'if ${xn(m)}(${xs(m,0)})'); 334 | add("Check Mouse", function(m) { 335 | var s = 'if (${xn(m)}mouse_check_button('; 336 | s += switch (vs(m, 0)) { 337 | case "no": "mb_none"; 338 | case "right": "mb_right"; 339 | case "middle": "mb_middle"; 340 | default: "mb_left"; 341 | } 342 | return s + '))'; 343 | }); 344 | add("Check Grid", function(m) { 345 | var op = octx(m, [0, 1]); 346 | var gx = xs(m, 0); 347 | var gy = xs(m, 1); 348 | return 'if (${op}x == (floor(x/$gx) * $gx) && ${op}y == (floor(x/$gy) * $gy))'; 349 | }); 350 | // 351 | add("Start Block", function(_) return "{"); 352 | add("Else", function(_) return "else"); 353 | add("Exit Event", function(_) return "exit;"); 354 | add("End Block", function(_) return "}"); 355 | add("Repeat", function(m) return "repeat (" + xs(m, 0) + ")"); 356 | add("Call Parent Event", function(m) return "event_inherited();"); 357 | // 358 | add("Execute Code", function(m) return xs(m, 0)); 359 | //{ 360 | add("Execute Script", function(m) { 361 | var arg1 = xs(m, 1).length == 0; 362 | var arg2 = xs(m, 2).length == 0; 363 | var arg3 = xs(m, 3).length == 0; 364 | var arg4 = xs(m, 4).length == 0; 365 | var arg5 = xs(m, 5).length == 0; 366 | 367 | if ( arg1 && arg2 && arg3 && arg4 && arg5 ) { 368 | return '${vr(m,0)}();'; 369 | } else if ( arg2 && arg3 && arg4 && arg5 ) { 370 | return '${vr(m,0)}(${xs(m,1)});'; 371 | } else if ( arg3 && arg4 && arg5 ) { 372 | return '${vr(m,0)}(${xs(m,1)}, ${xs(m,2)});'; 373 | } else if ( arg4 && arg5 ) { 374 | return '${vr(m,0)}(${xs(m,1)}, ${xs(m,2)}, ${xs(m,3)});'; 375 | } else if ( arg5 ) { 376 | return '${vr(m,0)}(${xs(m,1)}, ${xs(m,2)}, ${xs(m,3)}, ${xs(m,4)});'; 377 | } else { 378 | return '${vr(m,0)}(${xs(m,1)}, ${xs(m,2)}, ${xs(m,3)}, ${xs(m,4)}, ${xs(m,5)});'; 379 | } 380 | }); 381 | //} 382 | add("Comment", function(m) return "// " + m.values[0]); 383 | // 384 | add("Set Variable", function(m) { 385 | var op = octx(m, [1]); 386 | return '$op${xs(m,0)} ${cs(m.relative, "+")}= ${xs(m,1)};'; 387 | }); 388 | add("Test Variable", function(m) { 389 | var op = octx(m, [2]); // not checking expr#0 because it's the variable to check 390 | return 'if ($op${xs(m, 0)} ${vcmp(m, 1)} ${xs(m, 2)})'; 391 | }); 392 | add("Draw Variable", function(m) { 393 | return 'draw_text(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xs(m,2)});'; 394 | }); 395 | //} 396 | //{ 05_score 397 | add("Set Score", function(m) return xrna(m, "score", 0).sc()); 398 | add("Test Score", function(m) return 'if (score ${vcmp(m,0)} ${xs(m,1)})'); 399 | add("Draw Score", function(m) { 400 | return 'draw_text(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vstr(m,2)} + string(score));'; 401 | }); 402 | // 403 | add("Show Highscore", function(m) { 404 | var s = vs(m, 4); 405 | if ('\'"'.indexOf(s.charAt(0)) < 0) s = '"$s"'; 406 | var fs = Std.parseInt(xs(m, 7)) + Std.parseInt(xs(m, 8)) * 2; 407 | return 'highscore_set_background(${vr(m,0)});' 408 | +'\nhighscore_set_border(${vb(m,1,"show")});' 409 | +'\nhighscore_set_colors(c_white, ${vcol(m,2)}, ${vcol(m,3)});' 410 | +'\nhighscore_set_font($s, ${xs(m,5)}, $fs);' 411 | +'\nhighscore_show(score);'; 412 | }); 413 | add("Clear Highscore", function(m) return "highscore_clear();"); 414 | // 415 | add("Set Lives", function(m) return xrna(m, "lives", 0).sc()); 416 | add("Test Lives", function(m) return 'if (lives ${vcmp(m,0)} ${xs(m,1)})'); 417 | add("Draw Lives", function(m) { 418 | return 'draw_text(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vstr(m,2)} + string(lives));'; 419 | }); 420 | add("Draw Life Images", function(m) { 421 | return 'action_draw_life_images(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vr(m,2)});'; 422 | }); 423 | // 424 | add("Set Health", function(m) return xrna(m, "health", 0).sc()); 425 | add("Test Health", function(m) return 'if (health ${vcmp(m,0)} ${xs(m,1)})'); 426 | add("Draw Health", function(m) { 427 | var s = 'draw_healthbar(${xrn(m,"x",0)}, ${xrn(m,"y",1)},' 428 | + ' ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, health, '; 429 | var bc = vs(m, 4); 430 | switch (bc) { 431 | case "none": s += "-1"; 432 | default: s += "c_" + bc; 433 | } 434 | s += ", "; 435 | var fc = vs(m, 5); 436 | switch (fc) { 437 | case "green to red": s += "c_red, c_green"; 438 | case "white to black": s += "c_black, c_white"; 439 | default: s += 'c_$fc, c_$fc'; 440 | } 441 | return s + ", 0, " + sb(bc != "none") + ", false);"; 442 | }); 443 | add("Score Caption", function(m) { 444 | return 'show_score = ${vb(m,0,"show")};' 445 | +'\ncaption_score = ${vstr(m,1)};' 446 | +'\nshow_lives = ${vb(m,2,"show")};' 447 | +'\ncaption_lives = ${vstr(m,3)};' 448 | +'\nshow_health = ${vb(m,4,"show")};' 449 | +'\ncaption_health = ${vstr(m,5)};'; 450 | }); 451 | //} 452 | //{ 06_extra 453 | inline function part_type(m:MatchResult, i:Int) { 454 | switch( vs(m, i) ) { 455 | case "type 0": return "0"; 456 | case "type 1": return "1"; 457 | case "type 2": return "2"; 458 | case "type 3": return "3"; 459 | case "type 4": return "4"; 460 | case "type 5": return "5"; 461 | case "type 6": return "6"; 462 | case "type 7": return "7"; 463 | case "type 8": return "8"; 464 | case "type 9": return "9"; 465 | case "type 10": return "10"; 466 | case "type 11": return "11"; 467 | case "type 12": return "12"; 468 | case "type 13": return "13"; 469 | case "type 14": return "14"; 470 | case "type 15": return "15"; 471 | default: return "0"; 472 | } 473 | } 474 | 475 | //1[pixel|disk|square|line|star|circle|ring|sphere|flare|spark|explosion|cloud|smoke|snow] 476 | inline function part_shape(m:MatchResult, i:Int) { 477 | switch( vs(m, i) ) { 478 | case "pixel": return "0 /* pixel */"; 479 | case "disk": return "1 /* disk */"; 480 | case "square": return "2 /* square */"; 481 | case "line": return "3 /* line */"; 482 | case "star": return "4 /* star */"; 483 | case "circle": return "5 /* circle */"; 484 | case "ring": return "6 /* ring */"; 485 | case "sphere": return "7 /* sphere */"; 486 | case "flare": return "8 /* flare */"; 487 | case "spark": return "9 /* spark */"; 488 | case "explosion": return "10 /* explosion */"; 489 | case "cloud": return "11 /* cloud */"; 490 | case "smoke": return "12 /* smoke */"; 491 | case "snow": return "13 /* snow */"; 492 | default: return "0 /* pixel */"; 493 | } 494 | } 495 | 496 | inline function emitter_type(m:MatchResult, i:Int) { 497 | switch( vs(m, i) ) { 498 | case "emitter 0": return "0"; 499 | case "emitter 1": return "1"; 500 | case "emitter 2": return "2"; 501 | case "emitter 3": return "3"; 502 | case "emitter 4": return "4"; 503 | case "emitter 5": return "5"; 504 | case "emitter 6": return "6"; 505 | case "emitter 7": return "7"; 506 | default: return "0"; 507 | } 508 | } 509 | 510 | inline function emitter_shape(m:MatchResult, i:Int) { 511 | switch( vs(m, i) ) { 512 | case "rectangle": return "0 /* rectangle */"; 513 | case "ellipse": return "1 /* ellipse */"; 514 | case "diamond": return "2 /* diamond */"; 515 | case "line": return "3 /* line */"; 516 | default: return "0 /* rectangle */"; 517 | } 518 | } 519 | 520 | add("Create Part System", function(m) return 'action_partsyst_create(${xs(m,0)});' ); 521 | add("Part System Destroy", function(_) return 'action_partsyst_destroy();'); 522 | add("Part System Clear", function(_) return 'action_partsyst_clear();'); 523 | add("Part Type Create", function(m) return 'action_parttype_create(${part_type(m,0)}, ${part_shape(m,1)}, ${vr(m,2)}, ${xs(m,3)}, ${xs(m,4)}, ${xs(m,5)});'); 524 | add("Part Type Color", function(m) return 'action_parttype_color(${part_type(m,0)}, ${vb(m,1,"changing")}, ${vcol(m,2)}, ${vcol(m,3)}, ${xs(m,4)}, ${xs(m,5)});'); 525 | add("Part Type Life", function(m) return 'action_parttype_life(${part_type(m,0)}, ${xs(m,1)}, ${xs(m,2)});'); 526 | add("Part Type Speed", function(m) return 'action_parttype_speed(${part_type(m,0)}, ${xs(m,1)}, ${xs(m,2)}, ${xs(m,3)}, ${xs(m,4)}, ${xs(m,5)});'); 527 | add("Part Type Gravity", function(m) return 'action_parttype_gravity(${part_type(m,0)}, ${xs(m,1)}, ${xs(m,2)});'); 528 | add("Part Type Secondary", function(m) return 'action_parttype_secondary(${part_type(m,0)}, ${part_type(m,1)}, ${xs(m,2)}, ${part_type(m,3)}, ${xs(m,4)});'); 529 | add("Create Part Emitter", function(m) return 'action_partemit_create(${emitter_type(m,0)}, ${emitter_shape(m,1)}, ${xs(m,2)}, ${xs(m,3)}, ${xs(m,4)}, ${xs(m,5)});'); 530 | add("Destroy Part Emitter", function(m) return 'action_partemit_destroy(${emitter_type(m,0)});'); 531 | add("Emitter Burst", function(m) return 'action_partemit_burst(${emitter_type(m,0)}, ${part_type(m,1)}, ${xs(m,2)});'); 532 | add("Emitter Stream", function(m) return 'action_partemit_stream(${emitter_type(m,0)}, ${part_type(m,1)}, ${xs(m,2)});'); 533 | // 534 | add("Draw Cursor", function(m) { 535 | var s = 'cursor_sprite = ${vr(m,0)};'; 536 | if ( vb(m,1,"show") == "true" ) { 537 | s += '\nwindow_set_cursor(cr_default);'; 538 | } else { 539 | s += '\nwindow_set_cursor(cr_none);'; 540 | } 541 | return s; 542 | }); 543 | //} 544 | //{ 07_draw 545 | add("Draw Self", function(m) return 'draw_self();'); 546 | add("Draw Sprite", function(m) { 547 | return 'draw_sprite(${vr(m,3)}, ${xs(m,2)}, ${xrn(m,"x",0)}, ${xrn(m,"y",1)});'; 548 | }); 549 | add("Draw Background", function(m) { 550 | return "draw_background" + (vs(m, 3) == "true" ? "_tiled" : "") 551 | + '(${vr(m,2)}, ${xrn(m,"x",0)}, ${xrn(m,"y",1)});'; 552 | }); 553 | // 554 | add("Draw Text", function(m) { 555 | return 'draw_text(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vstr(m,2)});'; 556 | }); 557 | add("Draw Text Scaled", function(m) { 558 | return 'draw_text_transformed(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${vstr(m,2)},' 559 | + ' ${xs(m,3)}, ${xs(m,4)}, ${xs(m,5)});'; 560 | }); 561 | // 562 | add("Draw Rectangle", function(m) { 563 | return 'draw_rectangle(${xrn(m,"x",0)}, ${xrn(m,"y",1)},' 564 | + ' ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${vb(m,4,"outline")});'; 565 | }); 566 | add("Horizontal Gradient", function(m) { 567 | return 'action_draw_gradient_hor(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${xs(m,4)}, ${xs(m,5)});'; 568 | }); 569 | add("Vertical Gradient", function(m) { 570 | return 'action_draw_gradient_vert(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${xs(m,4)}, ${xs(m,5)});'; 571 | }); 572 | // 573 | add("Draw Ellipse", function(m) { 574 | return 'action_draw_ellipse(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${vb(m,4,"outline")});'; 575 | }); 576 | add("Gradient Ellipse", function(m) { 577 | return 'action_draw_ellipse_gradient(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${xs(m,4)}, ${xs(m,5)});'; 578 | }); 579 | // 580 | add("Draw Line", function(m) { 581 | return 'draw_line(${xrn(m,"x",0)}, ${xrn(m,"y",1)}, ${xrn(m,"x",2)}, ${xrn(m,"y",3)});'; 582 | }); 583 | add("Draw Arrow", function(m) { 584 | return 'draw_arrow(${xrn(m,"x",0)}, ${xrn(m,"y",1)},' 585 | + ' ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, ${xs(m,4)});'; 586 | }); 587 | // 588 | add("Set Color", function(m) { 589 | return 'draw_set_color(${vcol(m,0)});'; 590 | }); 591 | add("Set Font", function(m) { 592 | return 'draw_set_font(${vr(m,0)});' 593 | +'\ndraw_set_halign(fa_${vs(m,1)});'; 594 | }); 595 | add("Set Full Screen", function(m) { 596 | return switch (vs(m, 0)) { 597 | case "window": "window_set_fullscreen(false);"; 598 | case "fullscreen": "window_set_fullscreen(true);"; 599 | default: "window_set_fullscreen(!window_get_fullscreen());"; 600 | } 601 | }); 602 | add("Take Snapshot", function(m) return 'screen_save(${vstr(m,0)})'); 603 | add("Create Effect", function(m) { 604 | var s = "effect_create_" + (vs(m, 5) == "above objects" ? "above" : "below") + '('; 605 | var t = vs(m, 1); 606 | s += switch (t) { 607 | case "smoke up": "ef_smokeup"; 608 | default: "ef_" + t; 609 | } 610 | s += ', ${xrn(m,"x",2)}, ${xrn(m,"y",3)}, '; 611 | s += switch (vs(m, 0)) { 612 | case "medium": "1"; 613 | case "large": "2"; 614 | default: "0"; 615 | } 616 | return s + ', ${vcol(m,4)});'; 617 | }); 618 | //} 619 | } 620 | } 621 | 622 | class DataGMLTools { 623 | /// appends a semicolon to `s` if non-empty 624 | public static function sc(s:String) { 625 | return s != "" ? s + ";" : s; 626 | } 627 | /// separates `a` and `b` by `s` if both are non-empty 628 | public static function join(a:String, s:String, b:String) { 629 | return (a != "" && b != "") ? a + s + b : a + b; 630 | } 631 | /// conditional string 632 | public static inline function cs(c:Bool, s:String) return (c ? s : ""); 633 | /// boolean->string 634 | public static inline function sb(c:Bool) return c ? "true" : "false"; 635 | /// resource->string 636 | public static function sr(s:String) return s == "" ? "-1" : s; 637 | /// string->string 638 | public static function ss(s:String) { 639 | switch (s.charCodeAt(0)) { 640 | case "'".code, '"'.code: return s; 641 | } 642 | if (s.indexOf('"') < 0) { 643 | return '"$s"'; 644 | } else if (s.indexOf("'") < 0) { 645 | return "'" + s + "'"; 646 | } else { 647 | return '/* $s */'; 648 | } 649 | } 650 | 651 | //{ 652 | /// value string 653 | public static inline function vs(m:MatchResult, i:Int):String return m.values[i]; 654 | /// value boolean 655 | public static inline function vb(m:MatchResult, i:Int, s:String) return sb(m.values[i] == s); 656 | /// value resource 657 | public static inline function vr(m:MatchResult, i:Int) return sr(m.values[i]); 658 | /// value comparison 659 | public static function vcmp(m:MatchResult, i:Int) { 660 | return switch (vs(m, i)) { 661 | case "equal to": m.not ? "!=" : "=="; 662 | case "smaller than", "less than": m.not ? ">=" : "<"; 663 | case "larger than", "greater than": m.not ? "<=" : ">"; 664 | case "less than or equal to": m.not ? ">" : "<="; 665 | case "greater than or equal to": m.not ? "<" : ">="; 666 | default: m.not ? "!?" : "?"; 667 | } 668 | } 669 | /// value color (BGR 24-bit) 670 | public static inline function vcol(m:MatchResult, i:Int) { 671 | return "$" + StringTools.hex(m.values[i], 6); 672 | } 673 | public static inline function vstr(m:MatchResult, i:Int) return ss(vs(m, i)); 674 | //} 675 | 676 | /** expression string */ 677 | public static inline function xs(m:MatchResult, index:Int) { 678 | return Code.printNodes(m.values[index], OutputMode.OmGML); 679 | } 680 | 681 | /** expression-value-assign */ 682 | public static function xva(m:MatchResult, s:String, index:Int) { 683 | var x:String = xs(m, index); 684 | return x != s ? '$s = $x' : ''; 685 | } 686 | 687 | /** 688 | * expression-relative-number 689 | */ 690 | public static function xrn(m:MatchResult, s:String, index:Int) { 691 | var x:String = xs(m, index); 692 | if (m.relative) { 693 | if (x.charCodeAt(0) == "-".code) { 694 | return s + " - " + x.substring(1); 695 | } else { 696 | return x != "0" ? s + " + " + x : s; 697 | } 698 | } else { 699 | return x; 700 | } 701 | } 702 | 703 | /** 704 | * expression-relative-number-assign 705 | */ 706 | public static function xrna(m:MatchResult, s:String, index:Int) { 707 | var x:String = xs(m, index); 708 | if (m.relative) { 709 | if (x != "0") return '$s += $x'; 710 | } else { 711 | if (x != s) return '$s = $x'; 712 | }; return ""; 713 | } 714 | 715 | /** Expression-not: returns "!" or "" based on not-flag */ 716 | public static inline function xn(m:MatchResult) return m.not ? "!" : ""; 717 | 718 | /** Returns an other-prefix for apply-to if needed. */ 719 | public static function octx(m:MatchResult, valueIndexes:Array) { 720 | if (m.with != "other") return ""; 721 | for (i in valueIndexes) { 722 | var cc:Array = m.values[i]; 723 | for (c in cc) switch (c) { 724 | case CoWord(s, t): { 725 | switch (t) { 726 | case CwStdSpec: { 727 | switch (s) { 728 | case "self", "other": return ""; 729 | default: 730 | } 731 | }; 732 | case CwStdVar: if (Code.isInst[s]) return ""; 733 | case CwStdFunc: return ""; // can have side-effects 734 | case CwUserVar: return ""; // variables apply to `self` by default 735 | case CwUserFunc: return ""; // scripts may depend on context 736 | default: 737 | } 738 | }; 739 | default: { }; 740 | } 741 | } 742 | return "other/* apply to */."; 743 | } 744 | } 745 | -------------------------------------------------------------------------------- /src/data/DataGMX.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | import types.gmx.NodeGmxEvent; 3 | import types.NodeAction; 4 | import types.NodeEvent; 5 | import types.gmx.*; 6 | 7 | /** 8 | * ... 9 | * @author YellowAfterlife 10 | */ 11 | class DataGMX { 12 | public static function run(list:Array) { 13 | var lib:Int = 0; 14 | var events = NodeEvent.eventTypes; 15 | function add(id:Int, lid:Int, ?ord:String):Void { 16 | var action = NodeAction.iconMap.get(id); 17 | if (action == null) trace('No action for $id/$lid.'); 18 | list.push(new NodeGmxAction("" 19 | + "@s1" 20 | + "@s" + lid + "" 21 | + "@s@{ml}", 22 | action, ord)); 23 | } 24 | function event(type:Int, numb:Int, name:String, icon:Int) { 25 | var match = '@{ml}'; 30 | events.push(new NodeGmxEvent(match, icon, name)); 31 | } 32 | list.push(new NodeGmxComment()); 33 | //{ Events 34 | event(0, 0, "Create Event", 0); 35 | event(1, 0, "Destroy Event", 1); 36 | event(3, 0, "Step Event", 3); 37 | event(7, 7, "Other Event: Animation End", 4); 38 | for (i in 0 ... 12) event(2, i, 'Alarm Event for alarm $i', 2); 39 | for (i in 0 ... 16) event(7, 10 + i, "Other Event: User Defined " + i, 4); 40 | events.push(new NodeGmxCollisionEvent( 41 | '@{ml}', 42 | 6, "")); 43 | events.push(new NodeGmxEventAny( 44 | '@{ml}', 45 | 4, "")); 46 | //} 47 | //{ move 48 | add(0, 101, "0e1e"); // Move Fixed 49 | add(1, 102, "1e0e"); // Move Free 50 | add(2, 105, "0e1e2e"); // Move Towards 51 | add(100, 103, "0e"); // Speed Horizontal 52 | add(101, 104, "0e"); // Speed Vertical 53 | add(102, 107, "1e0e"); // Set Gravity 54 | add(200, 113); // Reverse Horizontal 55 | add(201, 114); // Reverse Vertical 56 | add(202, 108, "0e"); // Set Friction 57 | add(300, 109, "0e1e"); // Jump to Position 58 | add(301, 110); // Jump to Start 59 | add(302, 111, "0e1e"); // Jump to Random 60 | add(400, 117, "0e1e"); // Align to Grid 61 | add(401, 112, "0[horizontal|vertical|in both directions]"); // Wrap Screen 62 | add(500, 116, "0e1e2[solid objects|all objects]"); // Move to Contact 63 | add(501, 115, "0[not precisely|precisely]1[solid objects|all objects]"); // Bounce 64 | add(600, 119, "3[relative|absolute]0*1e2[stop|continue from start|continue from here|reverse]"); // Set Path 65 | add(601, 124); // End Path 66 | add(700, 122, "0e"); // Path Position 67 | add(701, 123, "0e"); // Path Speed 68 | add(800, 120, "0e1e2e3[solid only|all instances]"); // Step Towards 69 | add(801, 121, "0e1e2e3[solid only|all instances]"); // Step Avoiding 70 | //} 71 | //{ main1 72 | add(3, 201, "0*1e2e"); // Create Instance 73 | add(4, 206, "0*1e2e3e4e"); // Create Moving 74 | add(5, 207, "0*1*2*3*4e5e"); // Create Random 75 | add(103, 202, "0*1[not|yes]"); // Change Instance 76 | add(104, 203); // Destroy Instance 77 | add(105, 204, "0e1e"); // Destroy at Position 78 | add(203, 541, "0*1e2e"); // Change Sprite 79 | add(204, 542, "0e1e2e3[no mirroring|mirror horizontally|flip vertically|mirror and flip]"); // Transform Sprite 80 | add(205, 543, "0*1e"); // Color Sprite 81 | add(303, 211, "0*1[play|loop]"); // Play Sound 82 | add(304, 212, "0*"); // Stop Sound 83 | add(305, 213, "0*"); // Check Sound 84 | add(403, 221); // Previous Room 85 | add(404, 222); // Next Room 86 | add(405, 223); // Restart Room 87 | add(503, 224, "0*"); // Different Room 88 | add(504, 225); // Check Previous 89 | add(505, 226); // Check Next 90 | //} 91 | //{ main2 92 | add(6, 301, "1[Alarm 0|Alarm 1|Alarm 2|Alarm 3|Alarm 4|Alarm 5|Alarm 6|Alarm 7|Alarm 8|Alarm 9|Alarm 10|Alarm 11]0e"); // Set Alarm 93 | add(106, 305, "0*1e2[Start Immediately|Don't Start]3[Don't Loop|Loop]"); // Set Time Line 94 | add(107, 304, "0e"); // Time Line Position 95 | add(108, 309, "0e"); // Time Line Speed 96 | add(206, 306); // Start Time Line 97 | add(207, 307); // Pause Time Line 98 | add(208, 308); // Stop Time Line 99 | add(306, 321, "0*"); // Display Message 100 | add(308, 322, "0*"); // Open URL 101 | add(606, 331); // Restart Game 102 | add(607, 332); // End Game 103 | add(706, 333, "0*"); // Save Game 104 | add(707, 334, "0*"); // Load Game 105 | add(806, 803, "0*1*2e"); // Replace Sprite 106 | add(808, 805, "0*1*"); // Replace Background 107 | //} 108 | //{ control 109 | add(9, 401, "0e1e2[Only solid|All]"); // Check Empty 110 | add(10, 402, "0e1e2[Only solid|All]"); // Check Collision 111 | add(11, 403, "1e2e0*"); // Check Object 112 | add(109, 404, "0*2[equal to|smaller than|larger than]1e"); // Test Instance Count 113 | add(110, 405, "0e"); // Test Chance 114 | add(111, 407, "0*"); // Check Question 115 | add(209, 408, "0e"); // Test Expression 116 | add(210, 409, "0[no|left|right|middle]"); // Check Mouse 117 | add(211, 410, "0e1e"); // Check Grid 118 | add(309, 422); // Start Block 119 | add(310, 421); // Else 120 | add(311, 425); // Exit Event 121 | add(409, 424); // End Block 122 | add(410, 423, "0e"); // Repeat 123 | add(411, 604); // Call Parent Event 124 | add(509, 603, "0E"); // Execute Code 125 | add(510, 601, "0*1e2e3e4e5e"); // Execute Script 126 | add(511, 605, "0*"); // Comment 127 | add(609, 611, "0e1e"); // Set Variable 128 | add(610, 612, "0e2[equal to|less than|greater than|less than or equal to|greater than or equal to]1e"); // Test Variable 129 | add(611, 613, "1e2e0e"); // Draw Variable 130 | //} 131 | //{ score 132 | add(12, 701, "0e"); // Set Score 133 | add(13, 702, "1[equal to|smaller than|larger than]0e"); // Test Score 134 | add(14, 703, "0e1e2*"); // Draw Score 135 | add(113, 707); // Clear Highscore 136 | add(212, 711, "0e"); // Set Lives 137 | add(213, 712, "1[equal to|smaller than|larger than]0e"); // Test Lives 138 | add(214, 713, "0e1e2*"); // Draw Lives 139 | add(312, 714, "0e1e2*"); // Draw Life Images 140 | add(412, 721, "0e"); // Set Health 141 | add(413, 722, "1[equal to|smaller than|larger than]0e"); // Test Health 142 | add(414, 723, "0e1e2e3e4[none|black|gray|silver|white|maroon|green|olive|navy|purple|teal|red|lime|yellow|blue|fuchsia|aqua]5[green to red|white to black|black|gray|silver|white|maroon|green|olive|navy|purple|teal|red|lime|yellow|blue|fuchsia|aqua]"); // Draw Health 143 | //} 144 | //{ extra 145 | add(15, 820, "0e"); // Create Part System 146 | add(16, 821); // Destroy Part System 147 | add(17, 822); // Clear Part System 148 | add(115, 823, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1[pixel|disk|square|line|star|circle|ring|sphere|flare|spark|explosion|cloud|smoke|snow]2*3e4e5e"); // Create Particle 149 | add(116, 824, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1[mixed|changing]2*3*4e5e"); // Particle Color 150 | add(117, 826, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1e2e"); // Particle Life 151 | add(215, 827, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1e2e3e4e5e"); // Particle Speed 152 | add(216, 828, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1e2e"); // Particle Gravity 153 | add(217, 829, "0[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]1[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]2e3[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]4e"); // Particle Secondary 154 | add(315, 831, "0[emitter 0|emitter 1|emitter 2|emitter 3|emitter 4|emitter 5|emitter 6|emitter 7]1[rectangle|ellipse|diamond|line]2e3e4e5e"); // Create Emitter 155 | add(316, 832, "0[emitter 0|emitter 1|emitter 2|emitter 3|emitter 4|emitter 5|emitter 6|emitter 7]"); // Destroy Emitter 156 | add(317, 833, "0[emitter 0|emitter 1|emitter 2|emitter 3|emitter 4|emitter 5|emitter 6|emitter 7]1[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]2e"); // Burst from Emitter 157 | add(415, 834, "0[emitter 0|emitter 1|emitter 2|emitter 3|emitter 4|emitter 5|emitter 6|emitter 7]1[type 0|type 1|type 2|type 3|type 4|type 5|type 6|type 7|type 8|type 9|type 10|type 11|type 12|type 13|type 14|type 15]2e"); // Stream from Emitter 158 | add(515, 801, "0*1[don't show|show]"); // Set Cursor 159 | //} 160 | //{ draw 161 | add(20, 500); // Draw Self 162 | add(18, 501, "1e2e3e0*"); // Draw Sprite 163 | add(19, 502, "1e2e0*3*"); // Draw Background 164 | add(118, 514, "1e2e0*"); // Draw Text 165 | add(119, 519, "1e2e0*3e4e5e"); // Draw Scaled Text 166 | add(218, 511, "0e1e2e3e4[filled|outline]"); // Draw Rectangle 167 | 168 | add(219, 516, "0e1e2e3e4e5e"); // Horizontal Gradient 169 | add(220, 517, "0e1e2e3e4e5e"); // Vertical Gradient 170 | add(318, 512, "0e1e2e3e4[filled|outline]"); // Draw Ellipse 171 | add(319, 518, "0e1e2e3e4e5e"); // Gradient Ellipse 172 | 173 | add(418, 513, "0e1e2e3e"); // Draw Line 174 | add(419, 515, "0e1e2e3e4e"); // Draw Arrow 175 | add(518, 524, "0*"); // Set Color 176 | add(519, 526, "0*1[left|center|right]"); // Set Font 177 | add(520, 531, "0[switch|window|fullscreen]"); // Set Full Screen 178 | add(618, 802, "0*"); // Take Snapshot 179 | add(619, 532, "3[small|medium|large]0[explosion|ring|ellipse|firework|smoke|smoke up|star|spark|flare|cloud|rain|snow]1e2e4*5[below objects|above objects]"); // Create Effect 180 | //} 181 | list.push(new NodeGmxObject("@{ml}@{ml}", -1)); 182 | list.push(new NodeGmxObject("@{ml}@{ml}@{ml}", 1)); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/data/DataInfo.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class DataInfo { 8 | public static function run(list:Array) { 9 | var r:NodeType; 10 | inline function add(code:String) { 11 | list.push(r = new NodeType(code)); 12 | } 13 | add("Sprite: @i"); 14 | add("Sprite: "); 15 | add("Solid: @e"); 16 | add("Visible: @e"); 17 | add("Depth: @e"); 18 | add("Persistent: @e"); 19 | add("Parent: @i"); 20 | add("Parent: "); 21 | add("Mask: @i"); 22 | add("Mask: "); 23 | add("Children:"); 24 | // physics: 25 | add("No Physics Object"); 26 | add("Start Awake: @e"); 27 | add("Is Kinematic: @e"); 28 | add("Is Sensor: @e"); 29 | add("Density: @e"); 30 | add("Restitution: @e"); 31 | add("Group: @e"); 32 | add("Linear Damping: @e"); 33 | add("Angular Damping: @e"); 34 | add("Friction: @e"); 35 | add("Shape: @e"); 36 | // header: 37 | types.NodeHeader.inst = new types.NodeHeader(); 38 | types.NodeSeparator.inst = new types.NodeSeparator(); 39 | } 40 | } -------------------------------------------------------------------------------- /src/data/GMCIcons.hx: -------------------------------------------------------------------------------- 1 | package data; 2 | 3 | /** 4 | * Defines mappings between object info texture sheet and GMC :GM#: smiley codes. 5 | * @author YellowAfterlife 6 | */ 7 | @:publicFields 8 | class GMCIcons { 9 | static function action(id:Int):String { 10 | var i:Int = switch (id) { 11 | case 0: 2; 12 | case 1: 3; 13 | case 2: 4; 14 | case 100: 5; 15 | case 101: 6; 16 | case 102: 7; 17 | case 200: 8; 18 | case 201: 9; 19 | case 202: 10; 20 | case 300: 11; 21 | case 301: 12; 22 | case 302: 13; 23 | case 400: 14; 24 | case 401: 138; 25 | case 500: 15; 26 | case 501: 16; 27 | case 600: 17; 28 | case 601: 18; 29 | case 700: 19; 30 | case 701: 20; 31 | case 800: 21; 32 | case 801: 22; 33 | // main 1: 34 | case 3: 23; 35 | case 4: 24; 36 | case 5: 134; 37 | case 103: 25; 38 | case 104: 26; 39 | case 105: 27; 40 | case 203: 28; 41 | case 204: 29; 42 | case 205: 30; 43 | case 303: 31; 44 | case 304: 32; 45 | case 305: 33; 46 | case 403: 34; 47 | case 404: 35; 48 | case 405: 36; 49 | case 503: 37; 50 | case 504: 38; 51 | case 505: 39; 52 | // main 2: 53 | case 6: 40; 54 | case 7: 41; 55 | case 106: 42; 56 | case 107: 43; 57 | case 306: 44; 58 | case 307: 45; 59 | case 606: 47; 60 | case 607: 48; 61 | case 706: 49; 62 | case 707: 50; 63 | case 806: 135; 64 | case 807: 52; 65 | case 808: 53; 66 | // control: 67 | case 9: 54; 68 | case 10: 55; 69 | case 11: 56; 70 | case 109: 57; 71 | case 110: 58; 72 | case 111: 59; 73 | case 209: 60; 74 | case 210: 61; 75 | case 211: 62; 76 | case 309: 63; 77 | case 310: 64; 78 | case 311: 65; 79 | case 409: 66; 80 | case 410: 67; 81 | case 411: 68; 82 | case 509: 69; 83 | case 510: 70; 84 | case 511: 71; 85 | case 609: 72; 86 | case 610: 73; 87 | case 611: 74; 88 | // score: 89 | case 12: 75; 90 | case 13: 76; 91 | case 14: 77; 92 | case 112: 78; 93 | case 113: 79; 94 | case 212: 80; 95 | case 213: 81; 96 | case 214: 82; 97 | case 312: 83; 98 | case 412: 84; 99 | case 413: 85; 100 | case 414: 86; 101 | case 512: 87; 102 | // extras: 103 | // [screw this tab for time being] 104 | // draw: 105 | case 18: 108; 106 | case 19: 109; 107 | case 118: 110; 108 | case 119: 111; 109 | case 218: 112; 110 | case 219: 113; 111 | case 220: 114; 112 | case 318: 115; 113 | case 319: 116; 114 | case 418: 117; 115 | case 419: 118; 116 | case 518: 119; 117 | case 519: 120; 118 | case 520: 121; 119 | case 618: 122; 120 | case 619: 137; 121 | default: -1; 122 | } 123 | if (i == -1) return null; 124 | var s:String = Std.string(i); 125 | while (s.length < 3) s = "0" + s; 126 | return ":GM" + s + ":"; 127 | } 128 | static function event(id:Int):String { 129 | var i:Int = switch (id) { 130 | case 0: 123; 131 | case 1: 124; 132 | case 2: 125; 133 | case 3: 126; 134 | case 4: 130; 135 | case 5: 131; 136 | case 6: 127; 137 | case 7: 129; 138 | case 8: 128; 139 | case 9: 132; 140 | case 10: 133; 141 | case 11: 130; 142 | case 12: 130; 143 | default: -1; 144 | } 145 | if (i == -1) return null; 146 | return ":GM" + i + ":"; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/matcher/Match.hx: -------------------------------------------------------------------------------- 1 | package matcher; 2 | import data.BBStyle; 3 | import matcher.MatchNode; 4 | import Code; 5 | /** 6 | * ... 7 | * @author YellowAfterlife 8 | */ 9 | class Match { 10 | /** 11 | * Creates a MatchNode list from given code. 12 | * Supported tags are: 13 | * "@w": Optional "for *" prefix 14 | * "@r": Optional "relative " 15 | * "@N": Optional "not " 16 | * "@[word1|word2]": Value set (any of listed) 17 | * "@L": String spanning until the end of line 18 | * "@i": Resource index (or "") 19 | * "@c": A 24-bit color (BBGGRR) 20 | * "@e": An expression 21 | * "@{code}": Multi-line expression 22 | * "@{eu}": "cautious" expression (stops at the next text node) 23 | * "@{su}": "cautious" string (ditto above) 24 | * @param s Code to parse from 25 | */ 26 | public static function parse(s:String):Array { 27 | var pos:Int = 0; 28 | var len:Int = s.length; 29 | var ofs:Int = 0; 30 | var nodes = []; 31 | while (pos < len) { 32 | var c = s.charCodeAt(pos); 33 | if (c == "\n".code) { 34 | if (pos > ofs) nodes.push(MnText(s.substring(ofs, pos))); 35 | nodes.push(MnLN); 36 | pos++; 37 | ofs = pos; 38 | } else if (c == "@".code) { 39 | if (pos > ofs) nodes.push(MnText(s.substring(ofs, pos))); 40 | pos++; 41 | switch (s.charCodeAt(pos++)) { 42 | case "r".code: nodes.push(MnRelative); 43 | case "N".code: nodes.push(MnNot); 44 | case "L".code: nodes.push(MnEOL); 45 | case "i".code: nodes.push(MnResource); 46 | case "w".code: nodes.push(MnWith); 47 | case "c".code: nodes.push(MnColor); 48 | case "]".code: nodes.push(MnSpaces); 49 | case "s".code: nodes.push(MnWhitespace); 50 | case "e".code: { 51 | nodes.push(MnExpr); 52 | if (s.charCodeAt(pos) == " ".code) { 53 | pos++; 54 | nodes.push(MnSpaces); 55 | } 56 | }; 57 | case "{".code: { 58 | ofs = pos; 59 | pos = s.indexOf("}", ofs); 60 | switch (s.substring(ofs, pos++)) { 61 | case "code": nodes.push(MnCode); 62 | case "su": nodes.push(MnStringUntil); 63 | case "ml": nodes.push(MnMultiline); 64 | case "eu": 65 | nodes.push(MnExprUntil); 66 | if (s.charCodeAt(pos) == " ".code) { 67 | pos++; 68 | nodes.push(MnSpaces); 69 | } 70 | default: throw "Unknown {type} " + s.substring(ofs, pos); 71 | } 72 | }; 73 | case "[".code: { 74 | ofs = pos; 75 | pos = s.indexOf("]", ofs); 76 | nodes.push(MnSet(s.substring(ofs, pos).split("|"))); 77 | pos++; 78 | }; 79 | default: throw "Unknown type " + s.charAt(pos - 1); 80 | } 81 | ofs = pos; 82 | } else pos++; 83 | } 84 | if (pos > ofs) nodes.push(MnText(s.substring(ofs, pos))); 85 | return nodes; 86 | } 87 | 88 | public static function read(r:StringReader, nodes:Array):MatchResult { 89 | var r_str = r.str; 90 | var out:MatchResult = { }; 91 | var values:Array = null; 92 | inline function add(value:Dynamic) { 93 | if (values == null) { 94 | out.values = values = [value]; 95 | } else values.push(value); 96 | } 97 | // 98 | inline function substr(pos:Int, len:Int):String { 99 | return r_str.substr(pos, len); 100 | } 101 | // 102 | var node:MatchNode; 103 | var nn = nodes.length; 104 | for (ni in 0 ... nn) 105 | switch (node = nodes[ni]) { 106 | case MnText(s): { 107 | var n:Int = s.length; 108 | if (substr(r.pos, n) != s) return null; 109 | r.pos += n; 110 | }; 111 | case MnSpaces: r.readWhileIn(" \t"); 112 | case MnWhitespace: r.readWhileIn(" \t\r\n"); 113 | case MnLN: { 114 | switch (r.curr) { 115 | case "\r".code: 116 | r.pos++; 117 | if (r.curr == "\n".code) r.pos++; 118 | case "\n".code: r.pos++; 119 | default: return null; 120 | } 121 | }; 122 | case MnSet(list): { 123 | var c:Int = list.length; 124 | var i:Int = 0; 125 | while (i < c) { 126 | var item:String = list[i]; 127 | var n:Int = item.length; 128 | if (substr(r.pos, n) == item) { 129 | r.pos += n; 130 | add(item); 131 | break; 132 | } else i++; 133 | } 134 | if (i >= c) return null; 135 | }; 136 | case MnWith: { 137 | if (substr(r.pos, 4) == "for ") { 138 | r.pos += 4; 139 | if (substr(r.pos, 4) == "all ") { 140 | r.pos += 4; 141 | var p0 = r.pos; 142 | out.with = r.readUntilIn("\n:"); 143 | if (r.curr == ":".code) { 144 | r.pos++; 145 | r.readWhileIn(" \t"); 146 | } else r.pos = p0; 147 | } else if (substr(r.pos, 13) == "other object:") { 148 | r.pos += 13; 149 | out.with = "other"; 150 | r.readWhileIn(" \t"); 151 | } 152 | } 153 | }; 154 | case MnNot: { 155 | if (substr(r.pos, 4) == "not ") { 156 | r.pos += 4; out.not = true; 157 | } 158 | }; 159 | case MnRelative: { 160 | if (substr(r.pos, 9) == "relative ") { 161 | r.pos += 9; out.relative = true; 162 | } 163 | }; 164 | case MnColor: { 165 | var c = r.curr; 166 | if (c >= "0".code && c <= "9".code) { 167 | var ofs = r.pos; 168 | do { 169 | r.pos++; 170 | c = r.curr; 171 | } while (c >= "0".code && c <= "9".code); 172 | add(Std.parseInt(r_str.substring(ofs, r.pos))); 173 | } else return null; 174 | }; 175 | case MnEOL: { 176 | add(r.readUntilChar("\n".code)); 177 | }; 178 | case MnStringUntil, MnMultiline: { 179 | var s:String = "\n"; 180 | if (ni + 1 < nn) switch (nodes[ni + 1]) { 181 | case MnText(s1): s = s1; 182 | default: 183 | } 184 | var sl = s.length; 185 | var c1 = s.charCodeAt(0); 186 | var p0 = r.pos; 187 | var noML = (node == MnStringUntil); 188 | while (r.cond) { 189 | var c = r.curr; 190 | if (c == c1 && substr(r.pos, sl) == s) { 191 | add(r_str.substring(p0, r.pos)); 192 | break; 193 | } else if (noML && (c == "\n".code || c == "\r".code)) { 194 | return null; 195 | } else r.pos++; 196 | } 197 | if (r.eof) return null; 198 | }; 199 | case MnExpr: { 200 | var list = []; 201 | Code.readExpr(r, list, 0); 202 | add(list); 203 | }; 204 | case MnExprUntil: { 205 | var list = []; 206 | if (ni + 1 < nn) switch (nodes[ni + 1]) { 207 | case MnSpaces: 208 | if (ni + 2 < nn) switch (nodes[ni + 2]) { 209 | case MnText(s): Code.end = s; 210 | default: 211 | } 212 | case MnText(s): Code.end = s; 213 | default: 214 | } 215 | Code.readExpr(r, list, 0); 216 | Code.end = null; 217 | add(list); 218 | }; 219 | case MnCode: { 220 | var list = []; 221 | Code.multiline = true; 222 | Code.readLines(r, list); 223 | Code.multiline = false; 224 | add(list); 225 | }; 226 | case MnResource: { 227 | var c = r.curr; 228 | if((c >= "a".code && c <= "z".code) 229 | || (c >= "A".code && c <= "Z".code) 230 | || (c == "_".code)) { 231 | var ofs = r.pos; 232 | do { 233 | r.pos++; 234 | c = r.curr; 235 | } while ((c == "_".code) 236 | || (c >= "a".code && c <= "z".code) 237 | || (c >= "A".code && c <= "Z".code) 238 | || (c >= "0".code && c <= "9".code)); 239 | add(r_str.substring(ofs, r.pos)); 240 | } else if (c == "<".code) { 241 | var inner = r.readUntilIn(">\n"); 242 | if (r.curr == ">".code) { 243 | r.pos++; 244 | add(inner + ">"); 245 | } else return null; 246 | } else return null; 247 | }; 248 | } // switch (node) 249 | return out; 250 | } 251 | public static function print(nodes:Array, m:MatchResult, mode:OutputMode):String { 252 | var values = m.values; 253 | var vi:Int = 0; 254 | var r:String = ""; 255 | inline function next():Dynamic { 256 | return values[vi++]; 257 | } 258 | switch (mode) { 259 | case OutputMode.OmHTML: { 260 | inline function htmlEscape(text:String):String { 261 | return StringTools.htmlEscape(text); 262 | } 263 | for (n in nodes) switch (n) { 264 | case MnText(s): r += htmlEscape(s); 265 | case MnSet(_): 266 | var s = next(); 267 | r += '' + htmlEscape(s) + ''; 268 | case MnNot: if (m.not) r += 'not '; 269 | case MnRelative: if (m.relative) r += 'relative '; 270 | case MnSpaces: r += " "; 271 | case MnWhitespace: r += "\n"; 272 | case MnLN: r += "
    "; 273 | case MnWith: 274 | var m_with = m.with; 275 | if (m_with == null) continue; 276 | r += ''; 277 | if (m_with == "other") { 278 | r += 'for other object: '; 279 | } else { 280 | r += 'for all ' + htmlEscape(m_with) + ': '; 281 | } 282 | r += ''; 283 | case MnExpr, MnCode, MnExprUntil: 284 | var list:Array = next(); 285 | r += ''; 286 | for (codenode in list) r += Code.print(codenode, mode); 287 | r += ''; 288 | case MnColor: 289 | var c:Int = next(); 290 | var s:String = '(' + (c & 255) + ", " + ((c >> 8) & 255) + ", " + (c >> 16) + ')'; 291 | r += '$c'; 292 | case MnResource: r += '' + htmlEscape(next()) + ''; 293 | case MnEOL, MnStringUntil, MnMultiline: r += htmlEscape(next()); 294 | } // switch (n) 295 | }; // HTML 296 | case OutputMode.OmBB: { 297 | inline function bbs(s:String, v:String) { 298 | return BBStyle.get(s, v); 299 | } 300 | for (n in nodes) switch (n) { 301 | case MnText(s): r += s; 302 | case MnSpaces: r += " "; 303 | case MnWhitespace: r += "\n"; 304 | case MnLN: r += "\n"; 305 | case MnSet(_): r += bbs("set", next()); 306 | case MnNot: if (m.not) r += bbs("not", "not") + " "; 307 | case MnRelative: if (m.relative) r += bbs("relative", "relative") + " "; 308 | case MnWith: 309 | var m_with = m.with; 310 | if (m_with == "other") { 311 | r += bbs("with", "for " + bbs("other", "other object")) + ": "; 312 | } else if (m_with != null) { 313 | r += bbs("with", "for all " + bbs("ri", m_with)) + ": "; 314 | } 315 | case MnExpr, MnCode, MnExprUntil: 316 | var list:Array = next(), s = ""; 317 | for (n in list) s += Code.print(n, mode); 318 | r += bbs("expr", s); 319 | case MnColor: 320 | r += next(); 321 | case MnResource: r += bbs("ri", next()); 322 | case MnEOL, MnStringUntil, MnMultiline: r += next(); 323 | } 324 | }; // BB 325 | default: { 326 | for (n in nodes) switch (n) { 327 | case MnText(s): r += s; 328 | case MnSpaces: r += " "; 329 | case MnWhitespace: r += "\n"; 330 | case MnLN: r += "\n"; 331 | case MnSet(_): r += next(); 332 | case MnNot: r += "not "; 333 | case MnRelative: if (m.relative) r += "relative "; 334 | case MnWith: 335 | var m_with = m.with; 336 | if (m_with == "other") r += "for other object: "; 337 | else if (m_with != null) r += 'for all $m_with: '; 338 | case MnExpr, MnCode, MnExprUntil: 339 | var codeList:Array = next(); 340 | for (codeNode in codeList) r += Code.print(codeNode, mode); 341 | case MnColor: r += next(); 342 | case MnResource: r += next(); 343 | case MnEOL, MnStringUntil, MnMultiline: r += next(); 344 | } 345 | }; // default 346 | } // switch (mode) 347 | return r; 348 | } // function print 349 | } 350 | -------------------------------------------------------------------------------- /src/matcher/MatchNode.hx: -------------------------------------------------------------------------------- 1 | package matcher; 2 | 3 | /** 4 | * @author YellowAfterlife 5 | */ 6 | 7 | enum MatchNode { 8 | /// Plain text snippet 9 | MnText(text:String); 10 | /// "@[a|b|c]": Any of options in the set. 11 | MnSet(list:Array); 12 | /// "@L": String lasting until the end of the line. 13 | MnEOL; 14 | /// "@{su}": "Cautious" string 15 | MnStringUntil; 16 | /// "@{mu}": "Cautious" multi-line string 17 | MnMultiline; 18 | /// "\n": Linebreak 19 | MnLN; 20 | /// "@e": An inline GML expression. 21 | MnExpr; 22 | /// "@{eu}": "Cautious" expression 23 | MnExprUntil; 24 | /// "@]": Soaks up extra spaces after expressions 25 | MnSpaces; 26 | /// "@s": " \t\r\n" 27 | MnWhitespace; 28 | /// "@{code}": Mutli-line GML code (spans until the invalid expression) 29 | MnCode; 30 | /// "@r": Optional "relative ". 31 | MnRelative; 32 | /// "@w": Optional "with"-prefix. 33 | MnWith; 34 | /// "@N": Optional "not ". 35 | MnNot; 36 | /// "@i": Resource index. 37 | MnResource; 38 | /// "@c": BGR color integer. 39 | MnColor; 40 | } 41 | -------------------------------------------------------------------------------- /src/matcher/MatchResult.hx: -------------------------------------------------------------------------------- 1 | package matcher; 2 | 3 | /** 4 | * Represents a result of Match.read - presence of values depends on type alone. 5 | * @author YellowAfterlife 6 | */ 7 | typedef MatchResult = { 8 | /// matched values, in order. 9 | ?values:Array, 10 | /// action context. null if not set. 11 | ?with:String, 12 | /// whether `relative` flag is set (some actions) 13 | ?relative:Bool, 14 | /// whether `not` flag is set (conditions only) 15 | ?not:Bool, 16 | } 17 | -------------------------------------------------------------------------------- /src/types/NodeAction.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | import data.BBStyle; 3 | import matcher.*; 4 | /** 5 | * ... 6 | * @author YellowAfterlife 7 | */ 8 | class NodeAction extends NodeType { 9 | public static var actions:Map = new Map(); 10 | public static var iconMap:Map = new Map(); 11 | public static var gmlCounter:Int = -1; 12 | public var iconId:Int; 13 | public var iconCol:Int; 14 | public var iconRow:Int; 15 | public var iconOffsetCSS:String; 16 | public var iconIdURL:String; 17 | public var gmlFunc:MatchResult->String; 18 | public function new(name:String, code:String, icon:Int) { 19 | super(code); 20 | var s:String = name, i:Int = 1; 21 | if (actions.exists(s)) { 22 | while (i < 100) { 23 | s = name + i; 24 | if (!actions.exists(s)) break; 25 | i++; 26 | } 27 | } 28 | actions.set(s, this); 29 | iconMap.set(icon, this); 30 | this.name = name; 31 | iconId = icon; 32 | iconCol = icon % 100; 33 | iconRow = Std.int(icon / 100); 34 | } 35 | public function printIcon(v:Node, mode:OutputMode):String { 36 | var r:String, s:String; 37 | switch (mode) { 38 | case OutputMode.OmHTML: { 39 | if (Conf.htmlModern && Conf.htmlIcon == Conf.htmlIconSpan) { 40 | r = '' 70 | //+ '[' + name + '] ' 71 | + ' '; 72 | else '' + name + '';*/ 75 | }; 76 | case OutputMode.OmBB: { 77 | if (Conf.bbGMC) { 78 | s = data.GMCIcons.action(iconId); 79 | if (s != null) return s + " "; 80 | } 81 | if ((s = iconIdURL) == null) { 82 | iconIdURL = s = StringTools.lpad("" + iconId, "0", 3); 83 | } 84 | return BBStyle.img(Conf.getIconURL(Conf.miniIcons ? 'm$s' : s)) + " "; 85 | }; 86 | default: return ""; 87 | } 88 | } 89 | private static var rxApplyToOther = ~/other\/\* apply to \*\/\./g; 90 | public function printText(v:Node, mode:OutputMode):String { 91 | switch (mode) { 92 | case OutputMode.OmGML: { 93 | if (gmlFunc != null) { 94 | var r = v.match; 95 | var s = gmlFunc(r); 96 | var r_with = r.with; 97 | if (r_with != null && s != "") { 98 | if (r_with == "other" && s.indexOf("other/* apply to */.") >= 0) { 99 | s = rxApplyToOther.replace(s, "other."); 100 | } else { 101 | if (v.type.isIndent) { 102 | s = 'var ifwith; ifwith = false;' 103 | + '\nwith ($r_with) $s { ifwith = true; break; }' 104 | + '\nif (ifwith)'; 105 | } else { 106 | if (s.indexOf("\n") >= 0) { 107 | s = StringTools.replace(s, "\n", "\n\t"); 108 | s = 'with ($r_with) {\n\t$s\n}'; 109 | } else if (s.indexOf(";") >= 0) { 110 | s = 'with ($r_with) { $s }'; 111 | } else s = 'with ($r_with) $s'; 112 | } 113 | } 114 | } 115 | if (gmlCounter >= 0) gmlCounter += s.split("\n").length + 1; 116 | s = StringTools.replace(s, "\t", Conf.gmlIndentString); 117 | return s; 118 | } else { 119 | return "todo: /* " + Match.print(nodes, v.match, mode) + " */"; 120 | } 121 | }; 122 | default: return Match.print(nodes, v.match, mode); 123 | } 124 | } 125 | override public function print(v:Node, mode:OutputMode):String { 126 | var r = printIcon(v, mode) + printText(v, mode); 127 | switch (mode) { 128 | case OutputMode.OmHTML: 129 | return '
  • $r
  • '; 130 | default: return r; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/types/NodeBracket.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeBracket extends NodeAction { 8 | 9 | } -------------------------------------------------------------------------------- /src/types/NodeClose.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeClose extends NodeBracket { 8 | public static var inst:NodeClose; 9 | override public function print(v:Node, mode:OutputMode):String { 10 | var r = super.print(v, mode); 11 | switch (mode) { 12 | case OutputMode.OmHTML: 13 | return r + ''; 14 | case OmBB: 15 | if (Conf.bbIndentMode == Conf.bbIndentModeList) r = '$r\n[/list]'; 16 | return r; 17 | default: return r; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/types/NodeComment.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * Comment action (special printing rule) 5 | * @author YellowAfterlife 6 | */ 7 | class NodeComment extends NodeAction { 8 | override public function printText(v:Node, mode:OutputMode):String { 9 | switch (mode) { 10 | case OmHTML: 11 | return '' 12 | + 'COMMENT: ' 13 | + StringTools.htmlEscape(v.match.values[0]) 14 | + ''; 15 | case OmBB: return data.BBStyle.get("comment", 16 | data.BBStyle.get("comment prefix", "COMMENT: ") + v.match.values[0]); 17 | default: return super.printText(v, mode); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/types/NodeEvent.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | import data.BBStyle; 3 | 4 | /** 5 | * ... 6 | * @author YellowAfterlife 7 | */ 8 | class NodeEvent extends NodeType { 9 | public static var eventTypes:Array; 10 | public var icon:Int; 11 | private var iconCssOffset:String; 12 | public function new(code:String, icon:Int) { 13 | super(code); 14 | this.icon = icon; 15 | } 16 | public function printText(v:Node, mode:OutputMode):String { 17 | return printNodes(v, mode); 18 | } 19 | override public function print(v:Node, mode:OutputMode):String { 20 | var d:String = printText(v, mode), r:String, s:String; 21 | switch (mode) { 22 | case OutputMode.OmHTML: { 23 | if (Conf.htmlModern && Conf.htmlIcon == Conf.htmlIconSpan) { 24 | r = '$r'; 17 | case OutputMode.OmBB: 18 | return data.BBStyle.get("h2", r); 19 | default: return r; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/types/NodeOpen.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * "start of a block" action 5 | * @author YellowAfterlife 6 | */ 7 | class NodeOpen extends NodeBracket { 8 | public static var inst:NodeOpen; 9 | override public function print(v:Node, mode:OutputMode):String { 10 | var r = super.print(v, mode); 11 | switch (mode) { 12 | case OutputMode.OmHTML: 13 | return '
      ' + r; 14 | case OmBB: 15 | if (Conf.bbIndentMode == Conf.bbIndentModeList) r = '[list]\n$r'; 16 | return r; 17 | default: return r; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/types/NodeSeparator.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeSeparator extends NodeType { 8 | public static var inst:NodeSeparator; 9 | public function new() { 10 | super("______________________________________________________"); 11 | } 12 | override public function print(v:Node, mode:OutputMode):String { 13 | return ""; 14 | } 15 | } -------------------------------------------------------------------------------- /src/types/NodeText.hx: -------------------------------------------------------------------------------- 1 | package types; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeText extends NodeType { 8 | override public function print(v:Node, mode:OutputMode):String { 9 | var r = super.print(v, mode); 10 | switch (mode) { 11 | case OutputMode.OmGML: 12 | return 'todo: /* $r */'; 13 | default: return r; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/types/code/NodeCode.hx: -------------------------------------------------------------------------------- 1 | package types.code; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeCode extends NodeAction { 8 | public function printCode(nodes:Array, v:Node, mode:OutputMode):String { 9 | var b:StringBuf = new StringBuf(); 10 | switch (mode) { 11 | case OmHTML: 12 | for (n in nodes) b.add(Code.print(n, mode, true)); 13 | return b.toString(); 14 | case OmBB: 15 | for (n in nodes) b.add(Code.print(n, mode, true)); 16 | var code = b.toString(); 17 | if (v.indent > 0) { 18 | var lines = b.toString().split("\n"); 19 | var indent = Conf.bbGetIndent(v.indent); 20 | b = new StringBuf(); 21 | for (i in 0 ... lines.length) { 22 | if (i > 0) b.addChar("\n".code); 23 | b.add(indent); 24 | b.add(data.BBStyle.get("code mono", lines[i])); 25 | } 26 | return b.toString(); 27 | } else return data.BBStyle.get("code mono", b.toString()); 28 | default: return super.printText(v, mode); 29 | } 30 | } 31 | override public function printText(v:Node, mode:OutputMode):String { 32 | var r:String = printCode(v.match.values[0], v, mode); 33 | return switch (mode) { 34 | case OmHTML: r != "" ? '
      \n$r\n
      ' : ""; 35 | default: r; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/types/code/NodeCodeBlock.hx: -------------------------------------------------------------------------------- 1 | package types.code; 2 | import data.BBStyle; 3 | 4 | /** 5 | * ... 6 | * @author YellowAfterlife 7 | */ 8 | class NodeCodeBlock extends NodeCode { 9 | override public function printText(v:Node, mode:OutputMode):String { 10 | var r:String = super.printText(v, mode); 11 | switch (mode) { 12 | case OmHTML: 13 | return "execute code:" + r; 14 | case OmBB: 15 | var t = "execute code:"; 16 | if (r != "") { 17 | return t + "\n" + Conf.bbGetIndent(v.indent) + r; 18 | } else return t; 19 | default: return r; 20 | } 21 | } 22 | #if (dnd_to_gml) 23 | override public function print(v:Node, mode:OutputMode):String { 24 | switch (mode) { 25 | case OmHTML: return super.printText(v, mode); 26 | default: return super.print(v, mode); 27 | } 28 | } 29 | #end 30 | } 31 | -------------------------------------------------------------------------------- /src/types/code/NodeCodeRaw.hx: -------------------------------------------------------------------------------- 1 | package types.code; 2 | import types.code.NodeCode; 3 | 4 | /** 5 | * ... 6 | * @author YellowAfterlife 7 | */ 8 | class NodeCodeRaw extends NodeCode { 9 | override public function print(v:Node, mode:OutputMode):String { 10 | var r = printText(v, mode); 11 | return switch (mode) { 12 | case OutputMode.OmHTML: r; 13 | default: r; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/types/code/NodeCodeScript.hx: -------------------------------------------------------------------------------- 1 | package types.code; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeCodeScript extends NodeCode { 8 | override public function printText(v:Node, mode:OutputMode):String { 9 | var r:String = printCode(v.match.values[1], v, mode); 10 | var name:String = v.match.values[0]; 11 | switch (mode) { 12 | case OmHTML: 13 | return '
      #define $name'
      14 | 				+ '\n$r
      '; 15 | case OmBB: 16 | var t = data.BBStyle.get("code pp", '#define $name'); 17 | if (r != "") { 18 | return t + "\n" + Conf.bbGetIndent(v.indent) + r; 19 | } else return t; 20 | default: return r; 21 | } 22 | } 23 | override public function print(v:Node, mode:OutputMode):String { 24 | return printText(v, mode); 25 | } 26 | } -------------------------------------------------------------------------------- /src/types/gmx/NodeGmxAction.hx: -------------------------------------------------------------------------------- 1 | package types.gmx; 2 | import matcher.MatchResult; 3 | import types.NodeAction; 4 | import Code; 5 | using StringTools; 6 | 7 | /** 8 | * ... 9 | * @author YellowAfterlife 10 | */ 11 | class NodeGmxAction extends NodeType { 12 | public var action:NodeAction; 13 | public var arguments:String; 14 | public static var dndCounter:Int = 0; 15 | public function new(code:String, node:NodeAction, args:String) { 16 | super(code); 17 | action = node; 18 | arguments = args; 19 | } 20 | override public function read(s:StringReader):Node { 21 | var r0 = super.read(s); 22 | if (r0 == null) return null; 23 | var xml:String = r0.match.values[0]; 24 | var m:MatchResult = { }; 25 | var pos:Int, end:Int, len:Int; 26 | var seek:String; 27 | if (xml.indexOf("-1") >= 0) m.relative = true; 28 | if (xml.indexOf("-1") >= 0) m.not = true; 29 | seek = ""; 30 | pos = xml.indexOf(seek); 31 | if (pos >= 0) { 32 | pos += seek.length; 33 | end = xml.indexOf("", pos); 34 | var with = xml.substring(pos, end); 35 | if (with != "self") m.with = with; 36 | } 37 | var meta = arguments; 38 | if (meta != "0E") dndCounter++; 39 | seek = ""; 40 | pos = xml.indexOf(seek); 41 | if (meta != null && pos >= 0) { 42 | pos += seek.length; 43 | end = xml.indexOf(""); 44 | var xmlArgs = xml.substring(pos, end); 45 | // read arguments: 46 | var args:Array = []; 47 | seek = ""; 48 | len = seek.length; 49 | pos = xmlArgs.indexOf(""); 50 | while (pos != -1) { 51 | pos = xmlArgs.indexOf("", pos + 6); 52 | pos = xmlArgs.indexOf(">", pos + 7) + 1; 53 | end = xmlArgs.indexOf("<", pos); 54 | args.push(xmlArgs.substring(pos, end)); 55 | pos = xmlArgs.indexOf("", pos); 56 | } 57 | // parse arguments: 58 | var values:Array = []; 59 | pos = 0; 60 | len = meta.length; 61 | while (pos < len) { 62 | var id = meta.fastCodeAt(pos++) - "0".code; 63 | var data = args[id]; 64 | data = data != null ? data.htmlUnescape() : ""; 65 | var value:Dynamic; 66 | switch (meta.fastCodeAt(pos++)) { 67 | case "e".code: 68 | var list = []; 69 | var dr = new StringReader(data); 70 | Code.readExpr(dr, list); 71 | if (dr.pos < dr.len) list.push(CoElse(data.substring(dr.pos))); 72 | value = list; 73 | case "E".code: 74 | var list = []; 75 | var _ml = Code.multiline; 76 | Code.multiline = true; 77 | var dr = new StringReader(data); 78 | Code.readLines(dr, list); 79 | if (dr.pos < dr.len) list.push(CoElse(data.substring(dr.pos))); 80 | value = list; 81 | Code.multiline = _ml; 82 | case "[".code: 83 | end = meta.indexOf("]", pos); 84 | var options = meta.substring(pos, end).split("|"); 85 | pos = end + 1; 86 | value = options[Std.parseInt(data)]; 87 | if (value == null) trace('Cannot get $data from $options'); 88 | default: 89 | value = data; 90 | } 91 | values.push(value); 92 | } 93 | m.values = values; 94 | } 95 | return new Node(action, m); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/types/gmx/NodeGmxComment.hx: -------------------------------------------------------------------------------- 1 | package types.gmx; 2 | 3 | /** 4 | * ... 5 | * @author YellowAfterlife 6 | */ 7 | class NodeGmxComment extends NodeType { 8 | public function new() { 9 | super(""); 10 | } 11 | override public function print(v:Node, mode:OutputMode):String { 12 | switch (mode) { 13 | case OutputMode.OmGmxGml: { 14 | return super.print(v, mode); 15 | }; 16 | default: return ""; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/types/gmx/NodeGmxEvent.hx: -------------------------------------------------------------------------------- 1 | package types.gmx; 2 | 3 | import matcher.MatchResult; 4 | import types.NodeEvent; 5 | 6 | /** 7 | * ... 8 | * @author YellowAfterlife 9 | */ 10 | class NodeGmxEvent extends NodeEvent { 11 | public var text:String; 12 | public function new(code:String, icon:Int, name:String) { 13 | super(code, icon); 14 | text = name + ":"; 15 | } 16 | override public function read(s:StringReader):Node { 17 | var node = super.read(s); 18 | if (node == null) return null; 19 | var mt = node.match; 20 | var values = mt.values; 21 | var xml = values[values.length - 1]; 22 | var info = new Info(); 23 | info.optIndent = false; 24 | info.readString(xml); 25 | node.extra = mt; 26 | node.nodes = info.nodes; 27 | //node.match = { }; 28 | return node; 29 | } 30 | override public function printText(v:Node, mode:OutputMode):String { 31 | return text; 32 | } 33 | override public function print(v:Node, mode:OutputMode):String { 34 | switch (mode) { 35 | case OutputMode.OmGmxGml: { 36 | var vals = v.match.values; 37 | var last = vals.length - 1; 38 | var prev = vals[last]; 39 | var _gmx = Info.isGMX; 40 | Info.isGMX = true; 41 | var gml = Info.printNodes(v.nodes, OutputMode.OmGML, 0); 42 | Info.isGMX = _gmx; 43 | vals[last] = '' 44 | + '\n ' 45 | + '\n 1' 46 | + '\n 603' 47 | + '\n 7' 48 | + '\n 0' 49 | + '\n 0' 50 | + '\n -1' 51 | + '\n 2' 52 | + '\n ' 53 | + '\n ' 54 | + '\n self' 55 | + '\n 0' 56 | + '\n 0' 57 | + '\n ' 58 | + '\n ' 59 | + '\n 1' 60 | + '\n ' + StringTools.htmlEscape(gml) + '' 61 | + '\n ' 62 | + '\n ' 63 | + '\n ' 64 | + '\n '; 65 | var r = super.printText(v, mode); 66 | vals[last] = prev; 67 | return r; 68 | }; 69 | default: return super.print(v, mode); 70 | } 71 | } 72 | } 73 | 74 | class NodeGmxCollisionEvent extends NodeGmxEvent { 75 | override public function printText(v:Node, mode:OutputMode):String { 76 | var mt:MatchResult = v.extra; 77 | return "Collision Event with object " + mt.values[0] + ":"; 78 | } 79 | } 80 | 81 | class NodeGmxEventAny extends NodeGmxEvent { 82 | override public function read(s:StringReader):Node { 83 | var p = s.pos; 84 | var r = super.read(s); 85 | if (r != null) { 86 | s.pos = p; 87 | super.read(s); 88 | } 89 | return r; 90 | } 91 | override public function printText(v:Node, mode:OutputMode):String { 92 | var mt:MatchResult = v.extra; 93 | var values = mt.values; 94 | return "Unknown Event (" + values[0] + ":" + values[1] + "):"; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/types/gmx/NodeGmxObject.hx: -------------------------------------------------------------------------------- 1 | package types.gmx; 2 | 3 | import matcher.MatchResult; 4 | 5 | /** 6 | * ... 7 | * @author YellowAfterlife 8 | */ 9 | class NodeGmxObject extends NodeType { 10 | private var eventsParam:Int; 11 | public function new(code:String, eventsParam:Int) { 12 | super(code); 13 | this.eventsParam = eventsParam; 14 | } 15 | override public function print(v:Node, mode:OutputMode):String { 16 | var vals = v.match.values; 17 | var events = vals[eventsParam]; 18 | var r:String = ""; 19 | if (events != null) { 20 | var info = new Info(); 21 | info.optPostFix = mode != OmGML; 22 | info.optIndent = false; 23 | info.readString(events); 24 | r += Info.printNodes(info.nodes, mode, 1); 25 | } 26 | if (mode == OutputMode.OmGmxGml) { 27 | if (events != null) { 28 | r = "\n " + r + "\n "; 29 | vals[eventsParam] = r; 30 | } 31 | r = super.print(v, mode); 32 | if (events != null) vals[eventsParam] = events; 33 | } 34 | return r; 35 | } 36 | } 37 | --------------------------------------------------------------------------------