├── .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 |
97 |
102 | |
103 |
104 | by YellowAfterlife
105 |
106 | Save output
107 | ·
108 | Offline/multi-file version
109 | ·
110 | Donate
111 | |
112 |
113 |
114 |
115 | |
116 |
117 | |
118 |
119 |
120 |
121 |
122 | Visualization of converted object will be displayed here.
123 |
124 |
125 | |
126 | |
127 |
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 |
149 |
150 | Program by YellowAfterlife (
Twitter ·
Tumblr ·
VK). GameMaker © YoYo Games.
151 | Licenced

152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/dnd-to-gml-web.hxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/dnd-to-gml.hxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/gmvisualizer.hxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
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("", -1));
182 | list.push(new NodeGmxObject("", 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 = '';
47 | if (Conf.htmlIconText) r += '[$name] ';
48 | r += '';
49 | return r;
50 | } else {
51 | if (Conf.htmlModern) {
52 | r = '
';
60 | return r;
61 | } else {
62 | r = '
'
70 | //+ '[' + name + '] '
71 | + ' ';
72 | else '
';*/
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 '';
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 = '';
30 | return r + d;
31 | } else {
32 | if (Conf.htmlModern) {
33 | r = '
';
38 | return r + d;
39 | } else {
40 |
41 | }
42 | return d;
43 | }
44 | };
45 | case OmBB: {
46 | s = null;
47 | if (Conf.bbGMC) s = data.GMCIcons.event(icon);
48 | if (s == null) s = BBStyle.img(Conf.getIconURL("t" + icon));
49 | return s + " " + d;
50 | };
51 | default: return d;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/types/NodeHeader.hx:
--------------------------------------------------------------------------------
1 | package types;
2 |
3 | /**
4 | * "Information about object: " header
5 | * @author YellowAfterlife
6 | */
7 | class NodeHeader extends NodeType {
8 | public static var inst:NodeHeader;
9 | public function new() {
10 | super("Information about object: @i");
11 | }
12 | override public function print(v:Node, mode:OutputMode):String {
13 | var r = matcher.Match.print(nodes, v.match, mode);
14 | switch (mode) {
15 | case OutputMode.OmHTML:
16 | return '$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 '