├── .gitignore
├── .vscode
└── tasks.json
├── GmlCppExtFuncs.hxproj
├── GmlCppExtFuncsJS.hxproj
├── GmlCppExtFuncsNET.hxproj
├── Package.bat
├── README.md
├── Run.bat
├── bin
├── index.html
└── test.cpp
├── build.hxml
├── export
├── interop_test.dmd
├── interop_test.html
├── pack-legacy.bat
├── thumb.svg
└── thumbs.bat
├── extraParams.hxml
├── haxelib.json
├── interop_test.gmx
├── Configs
│ └── Default.config.gmx
├── extensions
│ ├── interop_test.extension.gmx
│ └── interop_test
│ │ ├── autogen.gml
│ │ └── interop_test.gml
├── fonts
│ ├── fnt_test.font.gmx
│ └── fnt_test.png
├── interop_test.project.gmx
├── objects
│ └── obj_test.object.gmx
├── rooms
│ └── rm_test.room.gmx
└── scripts
│ └── trace.gml
├── interop_test.sln
├── interop_test
├── README.md
├── YYRunnerInterface.h
├── autogen.cpp
├── dllmain.cpp
├── gml_ext.h
├── gml_extm.h
├── interop_test.APS
├── interop_test.h
├── interop_test.rc
├── interop_test.vcxproj
├── interop_test.vcxproj.filters
├── interop_test.vcxproj.user
├── postBuild.bat
├── preBuild.bat
├── resource1.h
├── stdafx.cpp
├── stdafx.h
├── targetver.h
├── test_basics.cpp
├── test_buffer.cpp
├── test_gml_id.cpp
├── test_gml_ptr.cpp
├── test_inout.cpp
├── test_struct.cpp
├── test_tuple.cpp
├── test_vector.cpp
└── test_yyri.cpp
├── interop_test_23
├── #config
│ └── properties.json
├── extensions
│ └── interop_test
│ │ ├── autogen.gml
│ │ ├── interop_test.gml
│ │ └── interop_test.yy
├── fonts
│ └── fnt_test
│ │ ├── fnt_test.png
│ │ └── fnt_test.yy
├── interop_test_23.yyp
├── objects
│ └── obj_test
│ │ ├── Create_0.gml
│ │ ├── Draw_0.gml
│ │ ├── Step_0.gml
│ │ └── obj_test.yy
├── options
│ ├── amazonfire
│ │ └── options_amazonfire.yy
│ ├── android
│ │ └── options_android.yy
│ ├── extensions
│ │ └── interop_test.json
│ ├── html5
│ │ └── options_html5.yy
│ ├── ios
│ │ └── options_ios.yy
│ ├── linux
│ │ └── options_linux.yy
│ ├── mac
│ │ └── options_mac.yy
│ ├── main
│ │ ├── inherited
│ │ │ └── options_main.inherited.yy
│ │ └── options_main.yy
│ ├── operagx
│ │ └── options_operagx.yy
│ ├── tvos
│ │ └── options_tvos.yy
│ └── windows
│ │ └── options_windows.yy
├── rooms
│ └── rm_test
│ │ └── rm_test.yy
└── scripts
│ ├── assert
│ ├── assert.gml
│ └── assert.yy
│ ├── interop_test_23
│ ├── interop_test_23.gml
│ └── interop_test_23.yy
│ ├── is_equal
│ ├── is_equal.gml
│ └── is_equal.yy
│ ├── scr_test
│ ├── scr_test.gml
│ └── scr_test.yy
│ ├── scr_test_basics
│ ├── scr_test_basics.gml
│ └── scr_test_basics.yy
│ ├── scr_test_buffer
│ ├── scr_test_buffer.gml
│ └── scr_test_buffer.yy
│ ├── scr_test_gml_id
│ ├── scr_test_gml_id.gml
│ └── scr_test_gml_id.yy
│ ├── scr_test_gml_ptr
│ ├── scr_test_gml_ptr.gml
│ └── scr_test_gml_ptr.yy
│ ├── scr_test_inout
│ ├── scr_test_inout.gml
│ └── scr_test_inout.yy
│ ├── scr_test_struct
│ ├── scr_test_struct.gml
│ └── scr_test_struct.yy
│ ├── scr_test_tuple
│ ├── scr_test_tuple.gml
│ └── scr_test_tuple.yy
│ ├── scr_test_vector
│ ├── scr_test_vector.gml
│ └── scr_test_vector.yy
│ ├── scr_test_yyri
│ ├── scr_test_yyri.gml
│ └── scr_test_yyri.yy
│ ├── sfmt
│ ├── sfmt.gml
│ └── sfmt.yy
│ └── trace
│ ├── trace.gml
│ └── trace.yy
├── interop_test_yy
├── extensions
│ └── interop_test
│ │ ├── autogen.gml
│ │ ├── interop_test.gml
│ │ └── interop_test.yy
├── fonts
│ └── fnt_test
│ │ ├── fnt_test.gms1.png
│ │ ├── fnt_test.gms1.yy
│ │ ├── fnt_test.png
│ │ └── fnt_test.yy
├── interop_test.yyp
├── objects
│ └── obj_test
│ │ ├── Create_0.gml
│ │ ├── Draw_0.gml
│ │ ├── Step_0.gml
│ │ └── obj_test.yy
├── options
│ ├── amazonfire
│ │ └── options_amazonfire.yy
│ ├── android
│ │ └── options_android.yy
│ ├── html5
│ │ └── options_html5.yy
│ ├── ios
│ │ └── options_ios.yy
│ ├── linux
│ │ └── options_linux.yy
│ ├── mac
│ │ └── options_mac.yy
│ ├── main
│ │ └── inherited
│ │ │ └── options_main.inherited.yy
│ ├── switch
│ │ └── options_switch.yy
│ ├── tvos
│ │ └── options_tvos.yy
│ └── windows
│ │ └── options_windows.yy
├── rooms
│ └── rm_test
│ │ └── rm_test.yy
├── scripts
│ └── trace
│ │ ├── trace.gml
│ │ └── trace.yy
└── views
│ ├── 1a1012ca-9702-4cd0-870a-3101ca12fddb.yy
│ ├── 4f96784b-1ebd-4fc6-8c5b-10ee426a2840.yy
│ ├── 504c1931-39ad-4f48-b783-4eb537b963d6.yy
│ ├── 690caa00-bb5f-4c7f-b921-6fd3330a6bc3.yy
│ ├── 6e9a4a1b-fa39-4f06-94c9-1a7f8822216a.yy
│ ├── 81be6123-f045-42c2-ad8f-dd97676ed387.yy
│ ├── 8c638ff8-1abe-4e11-bc32-7ef6af8b7b4f.yy
│ ├── 9878a9d0-ce0a-4455-91a7-89de6e4976a2.yy
│ ├── 9fdcc299-adf8-4729-b2f3-076ababf81ed.yy
│ ├── c583b9bc-76c2-490f-a077-1eeafac7f5ec.yy
│ ├── c9dcc6e5-46f1-4578-8543-9af4f6a4f7de.yy
│ ├── e5b1e8fe-f417-43e8-b65f-8a518d723aea.yy
│ ├── e5bc0382-83e6-4bfa-b68f-c702a7545129.yy
│ ├── f2ec9b0e-c3fe-4297-a78d-fa6f418fd827.yy
│ ├── f664cd6f-a19b-470a-8b94-844b0367b313.yy
│ └── f8edfe34-8789-4236-b7e4-741b59e181b8.yy
└── src
├── CppConfig.hx
├── CppGen.hx
├── CppGenParser.hx
├── CppType.hx
├── CppTypeHelper.hx
├── CppTypeMacroHelper.hx
├── GmlExtMacro.hx
├── func
├── CppFunc.hx
├── CppFuncArg.hx
├── CppFuncGmlDoc.hx
├── CppFuncMangled.hx
└── CppFuncReader.hx
├── misc
└── GmlConstructor.hx
├── proc
├── CppTypeProc.hx
├── CppTypeProcAssetIndexOf.hx
├── CppTypeProcCond.hx
├── CppTypeProcCustom.hx
├── CppTypeProcEnum.hx
├── CppTypeProcError.hx
├── CppTypeProcGameHwnd.hx
├── CppTypeProcGmlBuffer.hx
├── CppTypeProcGmlInOut.hx
├── CppTypeProcGmlInOutVector.hx
├── CppTypeProcGmlPointer.hx
├── CppTypeProcOptional.hx
├── CppTypeProcSimple.hx
├── CppTypeProcString.hx
├── CppTypeProcStruct.hx
├── CppTypeProcTuple.hx
└── CppTypeProcVector.hx
├── struct
├── CppStruct.hx
├── CppStructField.hx
├── CppStructIO.hx
└── GmlStructIO.hx
└── tools
├── CharCode.hx
├── CppBuf.hx
├── CppReader.hx
├── GmkGen.hx
└── GmlConditionalComments.hx
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | */#backups/*
3 | */Configs/*/*
4 |
5 | */extensions/*/*.cpp
6 | */extensions/*/*.dll
7 | */datafiles/interop_test.html
8 |
9 | */Debug/
10 | */Release/
11 | Debug/
12 | Release/
13 | bin/
14 | export/*.gmz
15 | export/*.gmez
16 | export/*.yymp
17 | export/*.yymps
18 | export/*.png
19 | export/*.zip
20 | *.sdf
21 | help.rtf
22 | /bin/GmlCppExtFuncs.n
23 | /bin/GmlCppExtFuncs.exe
24 | /bin/GmlCppExtFuncs.zip
25 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "Rebuild Haxe",
6 | "command": "haxe",
7 | "args": [
8 | "build.hxml"
9 | ],
10 | "problemMatcher": [
11 | "$haxe"
12 | ]
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/GmlCppExtFuncs.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 |
--------------------------------------------------------------------------------
/GmlCppExtFuncsJS.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 |
--------------------------------------------------------------------------------
/GmlCppExtFuncsNET.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 | DEBUG: cmd /C copy bin\cs\bin\CppGen-Debug.exe bin\GmlCppExtFuncs.exe
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Package.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd bin
3 | echo Creating standalone command line executable...
4 | nekotools boot GmlCppExtFuncs.n
5 | cmd /C 7z a GmlCppExtFuncs.zip GmlCppExtFuncs.n GmlCppExtFuncs.exe
6 | pause
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # GmlCppExtFuncs (working title)
3 | By default, GameMaker's extension interop has some limitations - since you can only pass around reals (64-bit floating point values) and pointers (to strings or binary buffers), many things are a bother to do - for example, if you want a function that computes a sum of int64 values in an array, you have to do
4 | ```cpp
5 | dllexport double get_sum_raw(int64_t* values, double count) {
6 | int64_t sum = 0;
7 | for (int i = 0; i < count; i++) sum += values[i];
8 | values[0] = sum;
9 | return 1;
10 | }
11 | ```
12 | and then a wrapper GML script:
13 | ```gml
14 | #define get_sum
15 | /// get_sum(values:array)->int
16 | var b = global.reusable_grow_buffer;
17 | buffer_seek(b, buffer_seek_start, 0);
18 | var arr = argument0;
19 | var len = array_length(arr);
20 | for (var i = 0; i < len; i++) buffer_write(b, buffer_u64, arr[i]);
21 | if (get_sum_raw(buffer_get_address(b), len)) {
22 | return buffer_peek(b, 0, buffer_u64);
23 | } else {
24 | // extension failed to load
25 | }
26 | ```
27 | With help of this tool, however, you can write just
28 | ```cpp
29 | dllg int64_t get_sum(vector values) {
30 | int64_t sum = 0;
31 | for each (auto val in arr) sum += val;
32 | return sum;
33 | }
34 | ```
35 | and the tool will generate the rest (a wrapper C++ function and a GML script that'll call it).
36 |
37 | Combined with [GmxGen](https://github.com/YAL-GameMaker-Tools/GmxGen), this means that you can write your C++ functions like normal and have them become available in GM automatically.
38 |
39 | ## Compiling
40 | ```bat
41 | haxe -cp src -neko GmlCppExtFuncs.n -main CppGen
42 | nekotools boot GmlCppExtFuncs.n
43 | ```
44 |
45 | ## Setting up
46 |
47 | * Add a new .cpp file to your C++ project
48 | * Add [gml_ext.h](https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs/blob/master/interop_test/gml_ext.h) to your C++ project
49 | * Add a blank GML file to your GameMaker extension (using GM IDE)
50 | * Add [interop_test.gml](https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs/blob/master/interop_test_23/extensions/interop_test/interop_test.gml) to your GameMaker extension
51 | * Prepend your C++ functions of interest with the macro (default: `dllg`)
52 |
53 | ## Using
54 |
55 | The general syntax is as following:
56 | ```
57 | GmlCppExtFuncs --cpp autogenerated_file.cpp --gml autogenerated_file.gml ...files [...options]
58 | ```
59 |
60 | For a practical example, suppose you wanted to do this for the project in this repository.
61 |
62 | You could do so by calling
63 | ```
64 | GmlCppExtFuncs -cpp interop_test/autogen.cpp -gml interop_test_23/extensions/interop_test/autogen.gml --prefix itr_test interop_test/interop_test.cpp
65 | ```
66 |
67 | When using Visual Studio, you can use Build Events -> Pre-Build Event to automatically run the command before you compile.
68 |
69 | ## Further reading
70 |
71 | * [Command-line arguments](https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs/wiki/Command-line-arguments)
72 | * [Supported types](https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs/wiki/Supported-types)
73 | * [Documentation tags](https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs/wiki/Documentation-tags)
74 |
75 | ## TODOs
76 |
77 | * Generate inline "serialization" code on C++ side as well so that data types can be nested arbitrarily
78 | * Support returning pointers
79 |
80 | ## Limitations
81 | * Since the tool relies on parsing C++ code, it may fail on code that looks deceptively (e.g. because it's full of C++ macros) - feel free to preprocess your files (via `-E` in GCC or `/P` in MSVC) before feeding the files to the tool if you rely heavily on generating functions through macros.
82 |
--------------------------------------------------------------------------------
/Run.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | neko bin/GmlCppExtFuncs.n^
3 | --prefix itr_test^
4 | --cpp interop_test/autogen.cpp^
5 | --gml interop_test_23/extensions/interop_test/autogen.gml^
6 | interop_test/interop_test.cpp^
7 | interop_test/interop_test_m.cpp
8 | pause
9 |
--------------------------------------------------------------------------------
/bin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/bin/test.cpp:
--------------------------------------------------------------------------------
1 |
2 | struct Test {
3 | int a0;
4 | int a1[2];
5 | int a2[3][2];
6 | }
7 |
8 | struct Inner {
9 | int a;
10 | }
11 | struct Outer {
12 | Inner a;
13 | int b;
14 | }
15 |
16 | dllw Test getTest(Test q) {
17 | Test t;
18 | t.a = q.a + 1;
19 | t.b = 1;
20 | return t;
21 | }
22 |
23 | dllw void testLayered(Outer a) {
24 |
25 | }
26 |
27 | /*
28 | dllw void no_ret(int64 i, int k) {
29 |
30 | }
31 |
32 | dllw int int64_to_int(int64 i) {
33 | return (int)i;
34 | }
35 |
36 | dllw int64 int64_to_int64(int64 i) {
37 | return i;
38 | }
39 |
40 | dllw int64 test(int64 i) {
41 | return i + 1;
42 | }
43 |
44 | dllw int64 test2(int64 i, int64 k = 0) {
45 | return i + k;
46 | }
47 |
48 | dllw int64 test2(int64 i, int64 k = 0, int64 j = 1) {
49 | return i + k;
50 | }
51 |
52 | dllw Test getTest() {
53 | Test t;
54 | t.a = 4;
55 | t.b = "hi!";
56 | return t;
57 | }
--------------------------------------------------------------------------------
/build.hxml:
--------------------------------------------------------------------------------
1 | -cp src
2 | -neko bin/GmlCppExtFuncs.n
3 | -main CppGen
4 | --cmd cmd /C interop_test\preBuild.bat dll .\ interop_test\ x64 default
--------------------------------------------------------------------------------
/export/interop_test.dmd:
--------------------------------------------------------------------------------
1 | ```set template default.html```
2 | ```set title interop_test cheat sheet```
3 | ```set autoapi ext```
4 | ```set intro
5 | This is a "cheat sheet" for "interop_test" extension by YellowAfterlife.
6 | The extension can be found on [itch.io](https://yellowafterlife.itch.io/gamemaker-interop_test).
7 | ```
--------------------------------------------------------------------------------
/export/interop_test.html:
--------------------------------------------------------------------------------
1 | .vs/
2 | */#backups/*
3 | */Configs/*/*
4 | */extensions/*/*.cpp
5 | */extensions/*/*.dll
6 | */Release/
7 | Release/
8 | export/*.gmez
9 | export/*.png
10 | export/*.gmz
11 | *.sdf
12 | help.rtf
--------------------------------------------------------------------------------
/export/pack-legacy.bat:
--------------------------------------------------------------------------------
1 | cd legacy
2 | cmd /C 7z a "../interop_test-for-GM8.1-or-older.zip" *
3 | pause
--------------------------------------------------------------------------------
/export/thumb.svg:
--------------------------------------------------------------------------------
1 |
2 |
128 |
--------------------------------------------------------------------------------
/export/thumbs.bat:
--------------------------------------------------------------------------------
1 | magick thumb.png -background #889ec5 -gravity center -extent 315x250 thumb-itch.png
2 | magick thumb.png -background #889ec5 -gravity center -extent 560x240 thumb-twitter.png
3 | magick thumb.png -background #889ec5 -gravity center -extent 540x240 thumb-tumblr.png
--------------------------------------------------------------------------------
/extraParams.hxml:
--------------------------------------------------------------------------------
1 | --macro GmlExtMacro.macroMain()
--------------------------------------------------------------------------------
/haxelib.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "GmlCppExtFuncs",
3 | "url": "https://github.com/YAL-GameMaker-Tools/GmlCppExtFuncs",
4 | "license": "MIT",
5 | "classPath": "src/",
6 | "tags": [
7 | "cpp", "gamemaker"
8 | ],
9 | "description": "",
10 | "contributors": ["YellowAfterlife"],
11 | "releasenote": "",
12 | "version": "1.0.0",
13 | "dependencies": { }
14 | }
15 |
--------------------------------------------------------------------------------
/interop_test.gmx/extensions/interop_test/interop_test.gml:
--------------------------------------------------------------------------------
1 | #define itr_test_init
2 | global.__iq_use_structs = false;
3 | global.__ptrt_iq_thing = ["iq_thing"];
4 |
5 | #define itr_test_prepare_buffer
6 | /// (size:int)->buffer~
7 | var _size = argument0;
8 | gml_pragma("global", "global.__itr_test_buffer = undefined");
9 | var _buf = global.__itr_test_buffer;
10 | if (_buf == undefined) {
11 | _buf = buffer_create(_size, buffer_grow, 1);
12 | global.__itr_test_buffer = _buf;
13 | } else if (buffer_get_size(_buf) < _size) {
14 | buffer_resize(_buf, _size);
15 | }
16 | buffer_seek(_buf, buffer_seek_start, 0);
17 | return _buf;
18 |
19 | #define itr_test_read_chars
20 | /// (buffer:buffer, len:int)->string~
21 | var _buf = argument0, _len = argument1;
22 | gml_pragma("global", "global.__itr_test_string_buffer = undefined");
23 | var _tmp = global.__itr_test_string_buffer;
24 | if (_tmp == undefined) {
25 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
26 | global.__itr_test_string_buffer = _tmp;
27 | } else if (buffer_get_size(_tmp) <= _len) {
28 | buffer_resize(_tmp, _len + 1);
29 | }
30 | buffer_copy(_buf, buffer_tell(_buf), _len, _tmp, 0);
31 | buffer_seek(_buf, buffer_seek_relative, _len);
32 | buffer_poke(_tmp, _len, buffer_u8, 0);
33 | buffer_seek(_tmp, buffer_seek_start, 0);
34 | return buffer_read(_tmp, buffer_string);
35 |
36 | #define itr_test_write_chars
37 | /// (buffer:buffer, str:string, len:int)~
38 | var _buf = argument0, _str = argument1, _len = argument2;
39 | var _tmp = global.__itr_test_string_buffer;
40 | if (_tmp == undefined) {
41 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
42 | global.__itr_test_string_buffer = _tmp;
43 | }
44 | buffer_seek(_tmp, buffer_seek_start, 0);
45 | buffer_write(_tmp, buffer_text, _str);
46 | var _pos = buffer_tell(_tmp);
47 | if (_pos < _len) buffer_fill(_tmp, _pos, buffer_u8, 0, _len - _pos);
48 | buffer_copy(_tmp, 0, _len, _buf, buffer_tell(_buf));
49 | buffer_seek(_buf, buffer_seek_relative, _len);
--------------------------------------------------------------------------------
/interop_test.gmx/fonts/fnt_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test.gmx/fonts/fnt_test.png
--------------------------------------------------------------------------------
/interop_test.gmx/interop_test.project.gmx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Configs\Default
5 |
6 |
7 |
8 | extensions\interop_test
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | fonts\fnt_test
19 |
20 |
21 |
22 |
23 |
24 | rooms\rm_test
25 |
26 |
27 | help.rtf
28 |
29 |
30 | 0
31 |
32 | 0
33 |
34 |
35 |
--------------------------------------------------------------------------------
/interop_test.gmx/objects/obj_test.object.gmx:
--------------------------------------------------------------------------------
1 |
2 |
93 |
--------------------------------------------------------------------------------
/interop_test.gmx/rooms/rm_test.room.gmx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 480
5 | 272
6 | 32
7 | 32
8 | 0
9 | 30
10 | 0
11 | 12951176
12 | -1
13 |
14 | 0
15 | -1
16 | -1
17 |
18 | -1
19 | 1024
20 | 600
21 | -1
22 | -1
23 | -1
24 | -1
25 | -1
26 | 0
27 | 0
28 | -1
29 | 4
30 | 0
31 | 0
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | 0
58 | 0
59 | 0
60 | 1024
61 | 768
62 | 0
63 | 10
64 | 0.100000001490116
65 |
66 |
--------------------------------------------------------------------------------
/interop_test.gmx/scripts/trace.gml:
--------------------------------------------------------------------------------
1 | /// trace(...)
2 | var r = string(argument[0]);
3 | for (var i = 1; i < argument_count; i++) {
4 | r += " " + string(argument[i]);
5 | }
6 | show_debug_message(r);
7 |
--------------------------------------------------------------------------------
/interop_test.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29424.173
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "interop_test", "interop_test\interop_test.vcxproj", "{C09F7563-35EB-439B-ABF2-0E72F829A515}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Debug|x64.ActiveCfg = Debug|x64
17 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Debug|x64.Build.0 = Debug|x64
18 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Debug|x86.ActiveCfg = Debug|Win32
19 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Debug|x86.Build.0 = Debug|Win32
20 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Release|x64.ActiveCfg = Release|x64
21 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Release|x64.Build.0 = Release|x64
22 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Release|x86.ActiveCfg = Release|Win32
23 | {C09F7563-35EB-439B-ABF2-0E72F829A515}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {964197C3-1C90-46BA-B404-E8C40EA7C1F4}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/interop_test/README.md:
--------------------------------------------------------------------------------
1 | # interop_test
2 |
3 |
4 |
5 | ## Installing
6 |
7 |
12 | - **GameMaker: Studio:**
13 | Import the GMEZ by right-clicking Extensions folder in resource tree and picking "Import extension"
14 | - **GameMaker Studio 2**
15 | Import the YYMP by drag and dropping it onto your workspace or picking menu:Tools➜Import Local Package
16 |
17 | ## Meta
18 |
19 | **Author:** [YellowAfterlife](https://github.com/YellowAfterlife)
20 | **License:** MIT
--------------------------------------------------------------------------------
/interop_test/dllmain.cpp:
--------------------------------------------------------------------------------
1 | // dllmain.cpp : Defines the entry point for the DLL application.
2 | #include "stdafx.h"
3 |
4 | BOOL APIENTRY DllMain( HMODULE hModule,
5 | DWORD ul_reason_for_call,
6 | LPVOID lpReserved
7 | )
8 | {
9 | switch (ul_reason_for_call)
10 | {
11 | case DLL_PROCESS_ATTACH:
12 | case DLL_THREAD_ATTACH:
13 | case DLL_THREAD_DETACH:
14 | case DLL_PROCESS_DETACH:
15 | break;
16 | }
17 | return TRUE;
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/interop_test/gml_ext.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
4 | #include
5 | #endif
6 | #include
7 | #include
8 | #include
9 |
10 | #define dllg /* tag */
11 | #define dllgm /* tag;mangled */
12 |
13 | #if defined(_WINDOWS)
14 | #define dllx extern "C" __declspec(dllexport)
15 | #define dllm __declspec(dllexport)
16 | #elif defined(GNUC)
17 | #define dllx extern "C" __attribute__ ((visibility("default")))
18 | #define dllm __attribute__ ((visibility("default")))
19 | #else
20 | #define dllx extern "C"
21 | #define dllm /* */
22 | #endif
23 |
24 | #ifdef _WINDEF_
25 | /// auto-generates a window_handle() on GML side
26 | typedef HWND GAME_HWND;
27 | #endif
28 |
29 | /// auto-generates an asset_get_index("argument_name") on GML side
30 | typedef int gml_asset_index_of;
31 | /// Wraps a C++ pointer for GML.
32 | template using gml_ptr = T*;
33 | /// Passes a modified struct back to GML
34 | template using gml_inout = T&;
35 | /// Modifies an array of values that GML passed in
36 | template using gml_inout_vector = std::vector&;
37 |
38 | /// Same as gml_ptr, but replaces the GML-side pointer by a nullptr after passing it to C++
39 | template using gml_ptr_destroy = T*;
40 | /// Wraps any ID (or anything that casts to int64, really) for GML.
41 | template using gml_id = T;
42 | /// Same as gml_id, but replaces the GML-side ID by a 0 after passing it to C++
43 | template using gml_id_destroy = T;
44 |
45 | class gml_buffer {
46 | private:
47 | uint8_t* _data;
48 | int32_t _size;
49 | int32_t _tell;
50 | public:
51 | gml_buffer() : _data(nullptr), _tell(0), _size(0) {}
52 | gml_buffer(uint8_t* data, int32_t size, int32_t tell) : _data(data), _size(size), _tell(tell) {}
53 |
54 | inline uint8_t* data() { return _data; }
55 | inline int32_t tell() { return _tell; }
56 | inline int32_t size() { return _size; }
57 | };
58 |
59 | class gml_istream {
60 | uint8_t* pos;
61 | uint8_t* start;
62 | public:
63 | gml_istream(void* origin) : pos((uint8_t*)origin), start((uint8_t*)origin) {}
64 |
65 | template T read() {
66 | static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read");
67 | T result{};
68 | std::memcpy(&result, pos, sizeof(T));
69 | pos += sizeof(T);
70 | return result;
71 | }
72 |
73 | char* read_string() {
74 | char* r = (char*)pos;
75 | while (*pos != 0) pos++;
76 | pos++;
77 | return r;
78 | }
79 |
80 | gml_buffer read_gml_buffer() {
81 | auto _data = (uint8_t*)read();
82 | auto _size = read();
83 | auto _tell = read();
84 | return gml_buffer(_data, _size, _tell);
85 | }
86 | };
87 |
88 | class gml_ostream {
89 | uint8_t* pos;
90 | uint8_t* start;
91 | public:
92 | gml_ostream(void* origin) : pos((uint8_t*)origin), start((uint8_t*)origin) {}
93 |
94 | template void write(T val) {
95 | static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write");
96 | memcpy(pos, &val, sizeof(T));
97 | pos += sizeof(T);
98 | }
99 |
100 | void write_string(const char* s) {
101 | for (int i = 0; s[i] != 0; i++) write(s[i]);
102 | write(0);
103 | }
104 | };
105 |
106 | class gmk_buffer {
107 | uint8_t* buf = 0;
108 | int pos = 0;
109 | int len = 0;
110 | public:
111 | gmk_buffer() {}
112 | uint8_t* prepare(int size) {
113 | if (len < size) {
114 | auto nb = (uint8_t*)realloc(buf, size);
115 | if (nb == nullptr) {
116 | show_error("Failed to reallocate %u bytes in gmk_buffer::prepare", size);
117 | return nullptr;
118 | }
119 | len = size;
120 | buf = nb;
121 | }
122 | pos = 0;
123 | return buf;
124 | }
125 | void init() {
126 | buf = 0;
127 | pos = 0;
128 | len = 0;
129 | }
130 | void rewind() { pos = 0; }
131 | inline uint8_t* data() { return buf; }
132 | //
133 | template void write(T val) {
134 | static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be write");
135 | int next = pos + sizeof(T);
136 | if (next > len) {
137 | auto nl = len;
138 | while (nl < next) nl *= 2;
139 | auto nb = (uint8_t*)realloc(buf, nl);
140 | if (nb == nullptr) {
141 | show_error("Failed to reallocate %u bytes in gmk_buffer::write", nl);
142 | return;
143 | }
144 | len = nl;
145 | buf = nb;
146 | }
147 | memcpy(buf + pos, &val, sizeof(T));
148 | pos = next;
149 | }
150 | template T read() {
151 | static_assert(std::is_trivially_copyable_v, "T must be trivially copyable to be read");
152 | int next = pos + sizeof(T);
153 | T result{};
154 | if (next > len) return result;
155 | memcpy(&result, buf + pos, sizeof(T));
156 | pos = next;
157 | return result;
158 | }
159 | };
160 |
--------------------------------------------------------------------------------
/interop_test/interop_test.APS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test/interop_test.APS
--------------------------------------------------------------------------------
/interop_test/interop_test.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | using iq_id = int;
3 |
--------------------------------------------------------------------------------
/interop_test/interop_test.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test/interop_test.rc
--------------------------------------------------------------------------------
/interop_test/interop_test.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {01f53200-1d0b-4f7a-845b-8bc07fccd020}
18 |
19 |
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 |
44 |
45 | Source Files
46 |
47 |
48 | Source Files
49 |
50 |
51 | Source Files
52 |
53 |
54 | Source Files
55 |
56 |
57 | Source Files
58 |
59 |
60 | Source Files
61 |
62 |
63 | Source Files
64 |
65 |
66 | Source Files
67 |
68 |
69 | Source Files
70 |
71 |
72 | Source Files
73 |
74 |
75 | Source Files
76 |
77 |
78 | Source Files
79 |
80 |
81 |
82 |
83 | Resource Files
84 |
85 |
86 |
87 |
88 | Build scripts
89 |
90 |
91 | Build scripts
92 |
93 |
94 |
--------------------------------------------------------------------------------
/interop_test/interop_test.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Default
5 |
6 |
--------------------------------------------------------------------------------
/interop_test/postBuild.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set dllPath=%~1
3 | set solutionDir=%~2
4 | set projectDir=%~3
5 | set arch=%~4
6 | set config=%~5
7 |
8 | echo Running post-build for %config%
9 |
10 | set extName=interop_test
11 | set dllName=interop_test
12 | set gmlDir14=%solutionDir%interop_test.gmx
13 | set gmlDir22=%solutionDir%interop_test_yy
14 | set gmlDir23=%solutionDir%interop_test_23
15 | set ext14=%gmlDir14%\extensions\%extName%
16 | set ext22=%gmlDir22%\extensions\%extName%
17 | set ext23=%gmlDir23%\extensions\%extName%
18 | set dllRel=%dllName%.dll
19 | set cppRel=%dllName%.cpp
20 | set cppPath=%ext23%\%cppRel%
21 | set gmlPath=%ext23%\*.gml
22 | set docName=%extName%.html
23 | set docPath=%solutionDir%export\%docName%
24 |
25 | echo Copying documentation...
26 | copy /Y %docPath% %gmlDir23%\datafiles\%docName%
27 | copy /Y %docPath% %gmlDir22%\datafiles\%docName%
28 | copy /Y %docPath% %gmlDir14%\datafiles\%docName%
29 |
30 | where /q gmxgen
31 | if %ERRORLEVEL% EQU 0 (
32 |
33 | echo Combining the source files...
34 | type "%projectDir%*.h" "%projectDir%*.cpp" >"%cppPath%" 2>nul
35 |
36 | echo Running GmxGen...
37 |
38 | gmxgen "%ext23%\%extName%.yy" ^
39 | --copy "%dllPath%" "%dllRel%:%arch%"
40 |
41 | gmxgen "%ext22%\%extName%.yy" ^
42 | --copy "%dllPath%" "%dllRel%:%arch%" ^
43 | --copy "%cppPath%" "%cppRel%" ^
44 | --copy "%gmlPath%" "*.gml"
45 |
46 | gmxgen "%ext14%.extension.gmx" ^
47 | --copy "%dllPath%" "%dllRel%:%arch%" ^
48 | --copy "%cppPath%" "%cppRel%" ^
49 | --copy "%gmlPath%" "*.gml"
50 |
51 | ) else (
52 |
53 | echo Copying DLLs...
54 | if "%arch%" EQU "x64" (
55 | copy /Y "%dllPath%" "%ext23%\%dllName%_x64.dll"
56 | ) else (
57 | copy /Y "%dllPath%" "%ext22%\%dllRel%"
58 | copy /Y "%dllPath%" "%ext23%\%dllRel%"
59 | copy /Y "%dllPath%" "%ext14%\%dllRel%"
60 | )
61 |
62 | echo Copying GML files...
63 | robocopy %ext23% %ext22% *.gml /L >nul
64 | robocopy %ext23% %ext14% *.gml /L >nul
65 |
66 | echo postBuild.bat: Warning N/A: Could not find GmxGen - extensions will not be updated automatically. See https://github.com/YAL-GameMaker-Tools/GmxGen for setup.
67 | )
--------------------------------------------------------------------------------
/interop_test/preBuild.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set dllPath=%~1
3 | set solutionDir=%~2
4 | set projectDir=%~3
5 | set arch=%~4
6 | set config=%~5
7 |
8 | echo Running pre-build for %config%
9 |
10 | where /q GmlCppExtFuncs
11 | if %ERRORLEVEL% EQU 0 (
12 | echo Running GmlCppExtFuncs...
13 |
14 | GmlCppExtFuncs ^
15 | --prefix itr_test^
16 | --cpp "%projectDir%autogen.cpp"^
17 | --gml "%solutionDir%interop_test_23/extensions/interop_test/autogen.gml"^
18 | --include interop_test.h^
19 | --struct iq_use_structs^
20 | %projectDir%test*.cpp
21 | )
--------------------------------------------------------------------------------
/interop_test/resource1.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by interop_test.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/interop_test/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // interop_test.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/interop_test/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #ifdef _WINDOWS
9 | #include "targetver.h"
10 |
11 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
12 | #include
13 | #endif
14 |
15 | #define trace(...) { printf("[interop_test] "); printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
16 |
17 | // TODO: reference additional headers your program requires here
18 | #include "interop_test.h"
19 | #include "gml_ext.h"
20 |
--------------------------------------------------------------------------------
/interop_test/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/interop_test/test_basics.cpp:
--------------------------------------------------------------------------------
1 | /// @author YellowAfterlife
2 |
3 | #include "stdafx.h"
4 |
5 | // @dllg:cond 0
6 | dllg void iq_never() {}
7 | // @dllg:cond
8 |
9 | dllg int iq_get_int() {
10 | return 1;
11 | }
12 | dllg int64_t iq_get_int64() {
13 | return 0x123456789ABCDEFi64;
14 | }
15 | dllg const char* iq_get_string() {
16 | return "hi!";
17 | }
18 |
19 | dllg int64_t iq_add_int64(int64_t a, int64_t b = 0) {
20 | return a + b;
21 | }
22 |
23 | dllg std::optional iq_inc_opt_int(std::optional i) {
24 | if (i.has_value()) {
25 | return i.value() + 1;
26 | } else return {};
27 | }
28 |
29 | // @dllg:defValue -3
30 | dllg int iq_def_ret_int() {
31 | return 3;
32 | }
33 |
34 | // @dllg:defValue "DLL is not loaded"
35 | dllg const char* iq_def_ret_string() {
36 | return "OK!";
37 | }
38 |
39 | dllg int iq_add_strlens(const char* a, const char* b, const char* c, const char* d) {
40 | return strlen(a) + strlen(b) + strlen(c) + strlen(d);
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/interop_test/test_buffer.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | dllg int iq_get_buffer_sum(gml_buffer buf) {
4 | int sum = 0;
5 | int till = buf.tell();
6 | auto data = buf.data();
7 | for (int i = 0; i < till; i++) {
8 | sum += data[i];
9 | }
10 | return sum;
11 | }
--------------------------------------------------------------------------------
/interop_test/test_gml_id.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | int _next_id = 0;
4 | dllg gml_id iq_id_create() {
5 | return ++_next_id;
6 | }
7 | dllg int iq_id_value(gml_id id) {
8 | return id;
9 | }
10 | dllg void iq_id_destroy(gml_id_destroy id) {
11 | //
12 | }
--------------------------------------------------------------------------------
/interop_test/test_gml_ptr.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | struct iq_thing {
4 | int count;
5 | };
6 | dllg gml_ptr iq_thing_create(int count) {
7 | auto thing = new iq_thing();
8 | thing->count = count;
9 | return thing;
10 | }
11 | dllg void iq_thing_destroy(gml_ptr_destroy thing) {
12 | delete thing;
13 | }
14 | dllg int iq_thing_get_count(gml_ptr thing) {
15 | return thing->count;
16 | }
17 | dllg void iq_thing_set_count(gml_ptr thing, int count) {
18 | thing->count = count;
19 | }
20 |
--------------------------------------------------------------------------------
/interop_test/test_inout.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | dllg void iq_test_inout_box(gml_inout q) {
4 | q += 1;
5 | }
6 | struct iq_inoutish {
7 | int a, b;
8 | char text[32];
9 | };
10 | dllg void iq_test_inout_struct(gml_inout q) {
11 | q.a += 1;
12 | strncpy(q.text, "Yeah!", std::size(q.text));
13 | }
14 | dllg void iq_test_inout_int_vector(gml_inout_vector v) {
15 | for (auto i = 0u; i < v.size(); i++) {
16 | v[i] += 1;
17 | }
18 | }
19 | dllg void iq_test_inout_struct_vector(gml_inout_vector v) {
20 | for (auto i = 0u; i < v.size(); i++) {
21 | v[i].a += 1;
22 | }
23 | }
--------------------------------------------------------------------------------
/interop_test/test_struct.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | struct _iq_get_struct_vec {
4 | int ind;
5 | char name[4];
6 | };
7 | dllg std::vector<_iq_get_struct_vec> iq_get_struct_vec() {
8 | std::vector<_iq_get_struct_vec> vec;
9 | vec.push_back({ 1, "one" });
10 | _iq_get_struct_vec two = { 2, "two" };
11 | two.name[3] = '-'; // non-NUL-terminated
12 | vec.push_back(two);
13 | vec.push_back({ 3, "tri" });
14 | return vec;
15 | }
16 |
17 | struct mixed_sub {
18 | int a, b;
19 | };
20 | struct mixed {
21 | int num;
22 | const char* str;
23 | uint8_t grid[3][3];
24 | mixed_sub sub[2];
25 | };
26 |
27 | dllg mixed iq_mixed(mixed q) {
28 | return q;
29 | }
--------------------------------------------------------------------------------
/interop_test/test_tuple.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | dllg std::tuple iq_get_int64_pair() {
4 | return { 1i64, 2i64 };
5 | }
6 |
7 | dllg int64_t iq_int64_pair_sum(std::tuple pair) {
8 | return std::get<0>(pair) + std::get<1>(pair);
9 | }
10 |
11 | dllg std::tuple iq_int64_pair_swap(std::tuple pair) {
12 | return { std::get<1>(pair), std::get<0>(pair) };
13 | }
14 |
15 | dllg std::tuple iq_get_int64_pair_vec_sum(std::vector> arr) {
16 | int64_t sum1 = 0, sum2 = 0;
17 | for each (auto val in arr) {
18 | sum1 += std::get<0>(val);
19 | sum2 += std::get<1>(val);
20 | }
21 | return { sum1, sum2 };
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/interop_test/test_vector.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 |
3 | dllg std::vector iq_get_vec() {
4 | std::vector vec{};
5 | for (int i = 1; i <= 3; i++) vec.push_back(i);
6 | return vec;
7 | }
8 |
9 | dllg std::optional> iq_get_opt_vec(bool ret) {
10 | std::vector vec{};
11 | for (int i = 1; i <= 3; i++) vec.push_back(i);
12 | if (!ret) return {};
13 | return vec;
14 | }
15 |
16 | dllg int64_t iq_get_int64_vec_sum(std::vector arr) {
17 | int64_t sum = 0;
18 | for each (auto val in arr) {
19 | sum += val;
20 | }
21 | return sum;
22 | }
23 |
24 | dllg int iq_get_length_of_strings(std::vector strings) {
25 | int sum = 0;
26 | for each (auto str in strings) {
27 | sum += (int)strlen(str);
28 | }
29 | return sum;
30 | }
--------------------------------------------------------------------------------
/interop_test/test_yyri.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "gml_ext.h"
3 | #include "gml_extm.h"
4 |
5 | #define trace(...) { printf("[interop_test:%d] ", __LINE__); printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
6 |
7 | static YYRunnerInterface g_YYRunnerInterface{};
8 | YYRunnerInterface* g_pYYRunnerInterface;
9 | dllm void YYExtensionInitialise(const struct YYRunnerInterface* _struct, size_t _size) {
10 | if (_size < sizeof(YYRunnerInterface)) {
11 | memcpy(&g_YYRunnerInterface, _struct, _size);
12 | } else {
13 | memcpy(&g_YYRunnerInterface, _struct, sizeof(YYRunnerInterface));
14 | }
15 | g_pYYRunnerInterface = &g_YYRunnerInterface;
16 | }
17 |
18 | dllgm int im_get_int() {
19 | return 1;
20 | }
21 | dllgm const char* im_get_string() {
22 | return "wow";
23 | }
24 | dllgm void im_get_result(YYResult& result) {
25 | YYCreateString(&result, "result");
26 | }
27 |
28 | dllgm int im_add_ints(int a, int b) {
29 | return a + b;
30 | }
31 | dllgm int im_add_rest(YYRest values) {
32 | auto result = 0;
33 | for (int i = 0; i < values.length; i++) {
34 | int v; if (values[i].tryGetInt(v)) result += v;
35 | }
36 | return result;
37 | }
38 |
39 | dllgm int64_t im_ptr_to_int64(void* ptr) {
40 | return (int64_t)ptr;
41 | }
42 |
43 | dllgm int im_string_length(const char* str) {
44 | return (int)strlen(str);
45 | }
46 |
47 | dllgm const char* im_typeof(RValue* val) {
48 | return KIND_NAME_RValue(val);
49 | }
--------------------------------------------------------------------------------
/interop_test_23/#config/properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "linterPrefs": {
3 |
4 | },
5 | "templateStringScript": "sfmt"
6 | }
--------------------------------------------------------------------------------
/interop_test_23/extensions/interop_test/interop_test.gml:
--------------------------------------------------------------------------------
1 | #define itr_test_init
2 | global.__iq_use_structs = false;
3 | global.__ptrt_iq_thing = ["iq_thing"];
4 |
5 | #define itr_test_prepare_buffer
6 | /// (size:int)->buffer~
7 | var _size = argument0;
8 | gml_pragma("global", "global.__itr_test_buffer = undefined");
9 | var _buf = global.__itr_test_buffer;
10 | if (_buf == undefined) {
11 | _buf = buffer_create(_size, buffer_grow, 1);
12 | global.__itr_test_buffer = _buf;
13 | } else if (buffer_get_size(_buf) < _size) {
14 | buffer_resize(_buf, _size);
15 | }
16 | buffer_seek(_buf, buffer_seek_start, 0);
17 | return _buf;
18 |
19 | #define itr_test_read_chars
20 | /// (buffer:buffer, len:int)->string~
21 | var _buf = argument0, _len = argument1;
22 | gml_pragma("global", "global.__itr_test_string_buffer = undefined");
23 | var _tmp = global.__itr_test_string_buffer;
24 | if (_tmp == undefined) {
25 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
26 | global.__itr_test_string_buffer = _tmp;
27 | } else if (buffer_get_size(_tmp) <= _len) {
28 | buffer_resize(_tmp, _len + 1);
29 | }
30 | buffer_copy(_buf, buffer_tell(_buf), _len, _tmp, 0);
31 | buffer_seek(_buf, buffer_seek_relative, _len);
32 | buffer_poke(_tmp, _len, buffer_u8, 0);
33 | buffer_seek(_tmp, buffer_seek_start, 0);
34 | return buffer_read(_tmp, buffer_string);
35 |
36 | #define itr_test_write_chars
37 | /// (buffer:buffer, str:string, len:int)~
38 | var _buf = argument0, _str = argument1, _len = argument2;
39 | var _tmp = global.__itr_test_string_buffer;
40 | if (_tmp == undefined) {
41 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
42 | global.__itr_test_string_buffer = _tmp;
43 | } else if (buffer_get_size(_tmp) <= _len) {
44 | buffer_resize(_tmp, _len + 1);
45 | }
46 | buffer_seek(_tmp, buffer_seek_start, 0);
47 | buffer_write(_tmp, buffer_text, _str);
48 | var _pos = buffer_tell(_tmp);
49 | if (_pos < _len) buffer_fill(_tmp, _pos, buffer_u8, 0, _len - _pos);
50 | buffer_copy(_tmp, 0, _len, _buf, buffer_tell(_buf));
51 | buffer_seek(_buf, buffer_seek_relative, _len);
--------------------------------------------------------------------------------
/interop_test_23/fonts/fnt_test/fnt_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test_23/fonts/fnt_test/fnt_test.png
--------------------------------------------------------------------------------
/interop_test_23/interop_test_23.yyp:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMProject",
3 | "resourceVersion": "1.6",
4 | "name": "interop_test_23",
5 | "resources": [
6 | {"id":{"name":"trace","path":"scripts/trace/trace.yy",},"order":1,},
7 | {"id":{"name":"fnt_test","path":"fonts/fnt_test/fnt_test.yy",},"order":1,},
8 | {"id":{"name":"obj_test","path":"objects/obj_test/obj_test.yy",},"order":1,},
9 | {"id":{"name":"rm_test","path":"rooms/rm_test/rm_test.yy",},"order":1,},
10 | {"id":{"name":"interop_test","path":"extensions/interop_test/interop_test.yy",},"order":1,},
11 | {"id":{"name":"scr_test_buffer","path":"scripts/scr_test_buffer/scr_test_buffer.yy",},"order":5,},
12 | {"id":{"name":"scr_test_struct","path":"scripts/scr_test_struct/scr_test_struct.yy",},"order":8,},
13 | {"id":{"name":"scr_test_vector","path":"scripts/scr_test_vector/scr_test_vector.yy",},"order":3,},
14 | {"id":{"name":"scr_test","path":"scripts/scr_test/scr_test.yy",},"order":0,},
15 | {"id":{"name":"assert","path":"scripts/assert/assert.yy",},"order":3,},
16 | {"id":{"name":"sfmt","path":"scripts/sfmt/sfmt.yy",},"order":1,},
17 | {"id":{"name":"scr_test_basics","path":"scripts/scr_test_basics/scr_test_basics.yy",},"order":1,},
18 | {"id":{"name":"scr_test_gml_id","path":"scripts/scr_test_gml_id/scr_test_gml_id.yy",},"order":7,},
19 | {"id":{"name":"is_equal","path":"scripts/is_equal/is_equal.yy",},"order":2,},
20 | {"id":{"name":"scr_test_inout","path":"scripts/scr_test_inout/scr_test_inout.yy",},"order":9,},
21 | {"id":{"name":"interop_test_23","path":"scripts/interop_test_23/interop_test_23.yy",},"order":1,},
22 | {"id":{"name":"scr_test_tuple","path":"scripts/scr_test_tuple/scr_test_tuple.yy",},"order":4,},
23 | {"id":{"name":"scr_test_gml_ptr","path":"scripts/scr_test_gml_ptr/scr_test_gml_ptr.yy",},"order":6,},
24 | {"id":{"name":"scr_test_yyri","path":"scripts/scr_test_yyri/scr_test_yyri.yy",},"order":2,},
25 | ],
26 | "Options": [
27 | {"name":"Amazon Fire","path":"options/amazonfire/options_amazonfire.yy",},
28 | {"name":"Android","path":"options/android/options_android.yy",},
29 | {"name":"HTML5","path":"options/html5/options_html5.yy",},
30 | {"name":"iOS","path":"options/ios/options_ios.yy",},
31 | {"name":"Linux","path":"options/linux/options_linux.yy",},
32 | {"name":"macOS","path":"options/mac/options_mac.yy",},
33 | {"name":"tvOS","path":"options/tvos/options_tvos.yy",},
34 | {"name":"Windows","path":"options/windows/options_windows.yy",},
35 | {"name":"operagx","path":"options/operagx/options_operagx.yy",},
36 | {"name":"Main","path":"options/main/options_main.yy",},
37 | ],
38 | "defaultScriptType": 1,
39 | "isEcma": false,
40 | "configs": {
41 | "name": "Default",
42 | "children": [],
43 | },
44 | "RoomOrderNodes": [
45 | {"roomId":{"name":"rm_test","path":"rooms/rm_test/rm_test.yy",},},
46 | ],
47 | "Folders": [
48 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Animation Curves","folderPath":"folders/Animation Curves.yy","order":1,},
49 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Extensions","folderPath":"folders/Extensions.yy","order":23,},
50 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Fonts","folderPath":"folders/Fonts.yy","order":13,},
51 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Notes","folderPath":"folders/Notes.yy","order":21,},
52 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Objects","folderPath":"folders/Objects.yy","order":17,},
53 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Paths","folderPath":"folders/Paths.yy","order":7,},
54 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Rooms","folderPath":"folders/Rooms.yy","order":19,},
55 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Scripts","folderPath":"folders/Scripts.yy","order":9,},
56 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sequences","folderPath":"folders/Sequences.yy","order":1,},
57 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Shaders","folderPath":"folders/Shaders.yy","order":11,},
58 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sounds","folderPath":"folders/Sounds.yy","order":5,},
59 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Sprites","folderPath":"folders/Sprites.yy","order":1,},
60 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Tile Sets","folderPath":"folders/Tile Sets.yy","order":3,},
61 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"Timelines","folderPath":"folders/Timelines.yy","order":15,},
62 | {"resourceType":"GMFolder","resourceVersion":"1.0","name":"tests","folderPath":"folders/Scripts/tests.yy","order":4,"tags":[],},
63 | ],
64 | "AudioGroups": [
65 | {"resourceType":"GMAudioGroup","resourceVersion":"1.3","name":"audiogroup_default","targets":-1,},
66 | ],
67 | "TextureGroups": [
68 | {"resourceType":"GMTextureGroup","resourceVersion":"1.3","name":"Default","isScaled":true,"compressFormat":"bz2","loadType":"default","directory":"","autocrop":true,"border":2,"mipsToGenerate":0,"groupParent":null,"targets":-1,},
69 | ],
70 | "IncludedFiles": [
71 | {"resourceType":"GMIncludedFile","resourceVersion":"1.0","name":"interop_test.html","CopyToMask":-1,"filePath":"datafiles",},
72 | ],
73 | "MetaData": {
74 | "IDEVersion": "2022.11.1.56",
75 | },
76 | }
--------------------------------------------------------------------------------
/interop_test_23/objects/obj_test/Create_0.gml:
--------------------------------------------------------------------------------
1 | //show_message("!");
2 | scr_test(false);
3 | scr_test(true);
4 | scr_test_yyri();
5 |
--------------------------------------------------------------------------------
/interop_test_23/objects/obj_test/Draw_0.gml:
--------------------------------------------------------------------------------
1 | draw_set_font(fnt_test);
2 | draw_set_color(c_white);
3 |
4 |
--------------------------------------------------------------------------------
/interop_test_23/objects/obj_test/Step_0.gml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/interop_test_23/objects/obj_test/obj_test.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMObject",
3 | "resourceVersion": "1.0",
4 | "name": "obj_test",
5 | "spriteId": null,
6 | "solid": false,
7 | "visible": true,
8 | "managed": true,
9 | "spriteMaskId": null,
10 | "persistent": false,
11 | "parentObjectId": null,
12 | "physicsObject": false,
13 | "physicsSensor": false,
14 | "physicsShape": 0,
15 | "physicsGroup": 0,
16 | "physicsDensity": 0.5,
17 | "physicsRestitution": 0.1,
18 | "physicsLinearDamping": 0.1,
19 | "physicsAngularDamping": 0.1,
20 | "physicsFriction": 0.2,
21 | "physicsStartAwake": true,
22 | "physicsKinematic": false,
23 | "physicsShapePoints": [],
24 | "eventList": [
25 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,},
26 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","isDnD":false,"eventNum":0,"eventType":3,"collisionObjectId":null,},
27 | {"resourceType":"GMEvent","resourceVersion":"1.0","name":"","isDnD":false,"eventNum":0,"eventType":8,"collisionObjectId":null,},
28 | ],
29 | "properties": [],
30 | "overriddenProperties": [],
31 | "parent": {
32 | "name": "Objects",
33 | "path": "folders/Objects.yy",
34 | },
35 | }
--------------------------------------------------------------------------------
/interop_test_23/options/amazonfire/options_amazonfire.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_amazonfire_sync_android": false,
3 | "option_amazonfire_display_name": "Created with GameMaker Studio 2",
4 | "option_amazonfire_version": "1.0.0.0",
5 | "option_amazonfire_tools_from_version": false,
6 | "option_amazonfire_build_tools": "",
7 | "option_amazonfire_support_lib": "",
8 | "option_amazonfire_target_sdk": "",
9 | "option_amazonfire_minimum_sdk": "",
10 | "option_amazonfire_compile_sdk": "",
11 | "option_amazonfire_package_domain": "com",
12 | "option_amazonfire_package_company": "company",
13 | "option_amazonfire_package_product": "game",
14 | "option_amazonfire_orient_portrait": true,
15 | "option_amazonfire_orient_portrait_flipped": true,
16 | "option_amazonfire_orient_landscape": true,
17 | "option_amazonfire_orient_landscape_flipped": true,
18 | "option_amazonfire_gamepad_support": true,
19 | "option_amazonfire_lint": false,
20 | "option_amazonfire_install_location": 0,
21 | "option_amazonfire_sleep_margin": 4,
22 | "option_amazonfire_splash_screens_landscape": "${base_options_dir}/amazonfire/splash/landscape.png",
23 | "option_amazonfire_splash_screens_portrait": "${base_options_dir}/amazonfire/splash/portrait.png",
24 | "option_amazonfire_splash_time": 0,
25 | "option_amazonfire_launchscreen_fill": 0,
26 | "option_amazonfire_splashscreen_background_colour": 255,
27 | "option_amazonfire_tv_banner": "${base_options_dir}/amazonfire/tv_banner.png",
28 | "option_amazonfire_interpolate_pixels": false,
29 | "option_amazonfire_screen_depth": 0,
30 | "option_amazonfire_scale": 0,
31 | "option_amazonfire_texture_page": "2048x2048",
32 | "option_amazonfire_icon_ldpi": "${base_options_dir}/android/icons/ldpi.png",
33 | "option_amazonfire_icon_mdpi": "${base_options_dir}/android/icons/mdpi.png",
34 | "option_amazonfire_icon_hdpi": "${base_options_dir}/android/icons/hdpi.png",
35 | "option_amazonfire_icon_xhdpi": "${base_options_dir}/android/icons/xhdpi.png",
36 | "option_amazonfire_icon_xxhdpi": "${base_options_dir}/android/icons/xxhdpi.png",
37 | "option_amazonfire_icon_xxxhdpi": "${base_options_dir}/android/icons/xxxhdpi.png",
38 | "option_amazonfire_permission_write_external_storage": false,
39 | "option_amazonfire_permission_read_phone_state": false,
40 | "option_amazonfire_permission_network_state": false,
41 | "option_amazonfire_permission_internet": true,
42 | "option_amazonfire_permission_bluetooth": true,
43 | "option_amazonfire_permission_record_audio": false,
44 | "option_amazonfire_application_tag_inject": "",
45 | "resourceVersion": "1.0",
46 | "name": "Amazon Fire",
47 | "tags": [],
48 | "resourceType": "GMAmazonFireOptions",
49 | }
--------------------------------------------------------------------------------
/interop_test_23/options/android/options_android.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_android_sync_amazon": false,
3 | "option_android_display_name": "Made in GameMaker Studio 2",
4 | "option_android_version": "1.0.0.0",
5 | "option_android_tools_from_version": false,
6 | "option_android_build_tools": "",
7 | "option_android_support_lib": "",
8 | "option_android_target_sdk": "",
9 | "option_android_minimum_sdk": "",
10 | "option_android_compile_sdk": "",
11 | "option_android_package_domain": "com",
12 | "option_android_package_company": "company",
13 | "option_android_package_product": "game",
14 | "option_android_arch_armv7": true,
15 | "option_android_arch_x86": false,
16 | "option_android_arch_arm64": false,
17 | "option_android_arch_x86_64": false,
18 | "option_android_orient_portrait": true,
19 | "option_android_orient_portrait_flipped": true,
20 | "option_android_orient_landscape": true,
21 | "option_android_orient_landscape_flipped": true,
22 | "option_android_gamepad_support": true,
23 | "option_android_lint": false,
24 | "option_android_install_location": 0,
25 | "option_android_sleep_margin": 4,
26 | "option_android_splash_screens_landscape": "${base_options_dir}/android/splash/landscape.png",
27 | "option_android_splash_screens_portrait": "${base_options_dir}/android/splash/portrait.png",
28 | "option_android_splash_time": 0,
29 | "option_android_launchscreen_fill": 0,
30 | "option_android_splashscreen_background_colour": 4294967295,
31 | "option_android_tv_banner": "${base_options_dir}/android/tv_banner.png",
32 | "option_android_interpolate_pixels": false,
33 | "option_android_screen_depth": 0,
34 | "option_android_device_support": 0,
35 | "option_android_scale": 0,
36 | "option_android_texture_page": "2048x2048",
37 | "option_android_icon_ldpi": "${base_options_dir}/android/icons/ldpi.png",
38 | "option_android_icon_mdpi": "${base_options_dir}/android/icons/mdpi.png",
39 | "option_android_icon_hdpi": "${base_options_dir}/android/icons/hdpi.png",
40 | "option_android_icon_xhdpi": "${base_options_dir}/android/icons/xhdpi.png",
41 | "option_android_icon_xxhdpi": "${base_options_dir}/android/icons/xxhdpi.png",
42 | "option_android_icon_xxxhdpi": "${base_options_dir}/android/icons/xxxhdpi.png",
43 | "option_android_icon_adaptive_generate": false,
44 | "option_android_icon_adaptive_ldpi": "${base_options_dir}/android/icons_adaptive/ldpi.png",
45 | "option_android_icon_adaptive_mdpi": "${base_options_dir}/android/icons_adaptive/mdpi.png",
46 | "option_android_icon_adaptive_hdpi": "${base_options_dir}/android/icons_adaptive/hdpi.png",
47 | "option_android_icon_adaptive_xhdpi": "${base_options_dir}/android/icons_adaptive/xhdpi.png",
48 | "option_android_icon_adaptive_xxhdpi": "${base_options_dir}/android/icons_adaptive/xxhdpi.png",
49 | "option_android_icon_adaptive_xxxhdpi": "${base_options_dir}/android/icons_adaptive/xxxhdpi.png",
50 | "option_android_icon_adaptivebg_ldpi": "${base_options_dir}/android/icons_adaptivebg/ldpi.png",
51 | "option_android_icon_adaptivebg_mdpi": "${base_options_dir}/android/icons_adaptivebg/mdpi.png",
52 | "option_android_icon_adaptivebg_hdpi": "${base_options_dir}/android/icons_adaptivebg/hdpi.png",
53 | "option_android_icon_adaptivebg_xhdpi": "${base_options_dir}/android/icons_adaptivebg/xhdpi.png",
54 | "option_android_icon_adaptivebg_xxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxhdpi.png",
55 | "option_android_icon_adaptivebg_xxxhdpi": "${base_options_dir}/android/icons_adaptivebg/xxxhdpi.png",
56 | "option_android_use_facebook": false,
57 | "option_android_facebook_id": "",
58 | "option_android_facebook_app_display_name": "",
59 | "option_android_google_cloud_saving": false,
60 | "option_android_google_services_app_id": "",
61 | "option_android_permission_write_external_storage": false,
62 | "option_android_permission_read_phone_state": false,
63 | "option_android_permission_network_state": false,
64 | "option_android_permission_internet": true,
65 | "option_android_permission_bluetooth": false,
66 | "option_android_permission_record_audio": false,
67 | "option_android_application_tag_inject": null,
68 | "option_android_google_apk_expansion": false,
69 | "option_android_google_dynamic_asset_delivery": false,
70 | "option_android_google_licensing_public_key": "",
71 | "option_android_tv_isgame": true,
72 | "resourceVersion": "1.0",
73 | "name": "Android",
74 | "tags": [],
75 | "resourceType": "GMAndroidOptions",
76 | }
--------------------------------------------------------------------------------
/interop_test_23/options/extensions/interop_test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extensionId": null,
3 | "resourceVersion": "1.0",
4 | "resourceType": "GMExtensionConfigSet",
5 | "configurables": null
6 | }
--------------------------------------------------------------------------------
/interop_test_23/options/html5/options_html5.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_html5_browser_title": "Made in GameMaker Studio 2",
3 | "option_html5_version": "1.0.0.0",
4 | "option_html5_foldername": "html5game",
5 | "option_html5_outputname": "index.html",
6 | "option_html5_splash_png": "${base_options_dir}/html5/splash.png",
7 | "option_html5_usesplash": false,
8 | "option_html5_outputdebugtoconsole": true,
9 | "option_html5_display_cursor": true,
10 | "option_html5_localrunalert": true,
11 | "option_html5_index": "",
12 | "option_html5_loadingbar": "",
13 | "option_html5_jsprepend": "",
14 | "option_html5_icon": "${base_options_dir}/html5/fav.ico",
15 | "option_html5_allow_fullscreen": true,
16 | "option_html5_interpolate_pixels": false,
17 | "option_html5_centregame": false,
18 | "option_html5_usebuiltinparticles": true,
19 | "option_html5_usebuiltinfont": true,
20 | "option_html5_webgl": 2,
21 | "option_html5_scale": 0,
22 | "option_html5_texture_page": "2048x2048",
23 | "option_html5_use_facebook": false,
24 | "option_html5_facebook_id": "",
25 | "option_html5_facebook_app_display_name": "",
26 | "option_html5_flurry_enable": false,
27 | "option_html5_flurry_id": "",
28 | "option_html5_google_analytics_enable": false,
29 | "option_html5_google_tracking_id": "",
30 | "resourceVersion": "1.0",
31 | "name": "HTML5",
32 | "tags": [],
33 | "resourceType": "GMHtml5Options",
34 | }
--------------------------------------------------------------------------------
/interop_test_23/options/ios/options_ios.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_ios_display_name": "Made in GameMaker Studio 2",
3 | "option_ios_bundle_name": "com.company.game",
4 | "option_ios_version": "1.0.0.0",
5 | "option_ios_output_dir": "~/GameMakerStudio2/iOS",
6 | "option_ios_team_id": "",
7 | "option_ios_orientation_portrait": true,
8 | "option_ios_orientation_portrait_flipped": true,
9 | "option_ios_orientation_landscape": true,
10 | "option_ios_orientation_landscape_flipped": true,
11 | "option_ios_devices": 2,
12 | "option_ios_defer_home_indicator": false,
13 | "option_ios_icon_iphone_app_120": "${base_options_dir}/ios/icons/app/iphone_120.png",
14 | "option_ios_icon_iphone_app_180": "${base_options_dir}/ios/icons/app/iphone_180.png",
15 | "option_ios_icon_ipad_app_76": "${base_options_dir}/ios/icons/app/ipad_76.png",
16 | "option_ios_icon_ipad_app_152": "${base_options_dir}/ios/icons/app/ipad_152.png",
17 | "option_ios_icon_ipad_pro_app_167": "${base_options_dir}/ios/icons/app/ipad_pro_167.png",
18 | "option_ios_icon_iphone_notification_40": "${base_options_dir}/ios/icons/notification/iphone_40.png",
19 | "option_ios_icon_iphone_notification_60": "${base_options_dir}/ios/icons/notification/iphone_60.png",
20 | "option_ios_icon_ipad_notification_20": "${base_options_dir}/ios/icons/notification/ipad_20.png",
21 | "option_ios_icon_ipad_notification_40": "${base_options_dir}/ios/icons/notification/ipad_40.png",
22 | "option_ios_icon_iphone_spotlight_80": "${base_options_dir}/ios/icons/spotlight/iphone_80.png",
23 | "option_ios_icon_iphone_spotlight_120": "${base_options_dir}/ios/icons/spotlight/iphone_120.png",
24 | "option_ios_icon_ipad_spotlight_40": "${base_options_dir}/ios/icons/spotlight/ipad_40.png",
25 | "option_ios_icon_ipad_spotlight_80": "${base_options_dir}/ios/icons/spotlight/ipad_80.png",
26 | "option_ios_icon_iphone_settings_58": "${base_options_dir}/ios/icons/settings/iphone_58.png",
27 | "option_ios_icon_iphone_settings_87": "${base_options_dir}/ios/icons/settings/iphone_87.png",
28 | "option_ios_icon_ipad_settings_29": "${base_options_dir}/ios/icons/settings/ipad_29.png",
29 | "option_ios_icon_ipad_settings_58": "${base_options_dir}/ios/icons/settings/ipad_58.png",
30 | "option_ios_icon_itunes_artwork_1024": "${base_options_dir}/ios/icons/itunes/itunes_1024.png",
31 | "option_ios_splashscreen_background_colour": 4294967295,
32 | "option_ios_launchscreen_image": "${base_options_dir}/ios/splash/launchscreen.png",
33 | "option_ios_launchscreen_image_landscape": "${base_options_dir}/ios/splash/launchscreen-landscape.png",
34 | "option_ios_launchscreen_fill": 0,
35 | "option_ios_interpolate_pixels": false,
36 | "option_ios_half_ipad1_textures": false,
37 | "option_ios_scale": 0,
38 | "option_ios_texture_page": "2048x2048",
39 | "option_ios_use_facebook": false,
40 | "option_ios_facebook_id": "",
41 | "option_ios_facebook_app_display_name": "",
42 | "option_ios_push_notifications": false,
43 | "option_ios_apple_sign_in": false,
44 | "option_ios_podfile_path": "${options_dir}/ios/Podfile",
45 | "option_ios_podfile_lock_path": "${options_dir}/ios/Podfile.lock",
46 | "resourceVersion": "1.3",
47 | "name": "iOS",
48 | "tags": [],
49 | "resourceType": "GMiOSOptions",
50 | }
--------------------------------------------------------------------------------
/interop_test_23/options/linux/options_linux.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_linux_display_name": "Made in GameMaker Studio 2",
3 | "option_linux_version": "1.0.0.0",
4 | "option_linux_maintainer_email": "",
5 | "option_linux_homepage": "http://www.yoyogames.com",
6 | "option_linux_short_desc": "",
7 | "option_linux_long_desc": "",
8 | "option_linux_splash_screen": "${base_options_dir}/linux/splash/splash.png",
9 | "option_linux_display_splash": false,
10 | "option_linux_icon": "${base_options_dir}/linux/icons/64.png",
11 | "option_linux_start_fullscreen": false,
12 | "option_linux_allow_fullscreen": false,
13 | "option_linux_interpolate_pixels": false,
14 | "option_linux_display_cursor": true,
15 | "option_linux_sync": false,
16 | "option_linux_resize_window": false,
17 | "option_linux_scale": 0,
18 | "option_linux_texture_page": "2048x2048",
19 | "option_linux_enable_steam": false,
20 | "option_linux_disable_sandbox": false,
21 | "resourceVersion": "1.0",
22 | "name": "Linux",
23 | "tags": [],
24 | "resourceType": "GMLinuxOptions",
25 | }
--------------------------------------------------------------------------------
/interop_test_23/options/mac/options_mac.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_mac_display_name": "Made in GameMaker Studio 2",
3 | "option_mac_app_id": "com.company.game",
4 | "option_mac_version": "1.0.0.0",
5 | "option_mac_output_dir": "~/GameMakerStudio2/Mac",
6 | "option_mac_team_id": null,
7 | "option_mac_signing_identity": "Developer ID Application:",
8 | "option_mac_copyright": "(c) 2018 CompanyName",
9 | "option_mac_splash_png": "${base_options_dir}/mac/splash/splash.png",
10 | "option_mac_icon_png": "${base_options_dir}/mac/icons/1024.png",
11 | "option_mac_menu_dock": false,
12 | "option_mac_display_cursor": true,
13 | "option_mac_start_fullscreen": false,
14 | "option_mac_allow_fullscreen": false,
15 | "option_mac_interpolate_pixels": false,
16 | "option_mac_vsync": false,
17 | "option_mac_resize_window": false,
18 | "option_mac_enable_retina": false,
19 | "option_mac_scale": 0,
20 | "option_mac_texture_page": "2048x2048",
21 | "option_mac_build_app_store": false,
22 | "option_mac_allow_incoming_network": false,
23 | "option_mac_allow_outgoing_network": false,
24 | "option_mac_app_category": "Games",
25 | "option_mac_enable_steam": false,
26 | "option_mac_disable_sandbox": false,
27 | "option_mac_apple_sign_in": false,
28 | "resourceVersion": "1.0",
29 | "name": "macOS",
30 | "tags": [],
31 | "resourceType": "GMMacOptions",
32 | }
--------------------------------------------------------------------------------
/interop_test_23/options/main/inherited/options_main.inherited.yy:
--------------------------------------------------------------------------------
1 | 1.0.0←ed6a955d-5826-4f98-a450-10b414266c27←ed6a955d-5826-4f98-a450-10b414266c27|{
2 | "option_game_speed": 30,
3 | "option_gameguid": "caab8cc1-112a-417f-aa89-bf8f42e48583"
4 | }←1225f6b0-ac20-43bd-a82e-be73fa0b6f4f|{
5 | "targets": 461609314234257646
6 | }←7b2c4976-1e09-44e5-8256-c527145e03bb|{
7 | "targets": 461609314234257646
8 | }
--------------------------------------------------------------------------------
/interop_test_23/options/main/options_main.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMMainOptions",
3 | "resourceVersion": "1.4",
4 | "name": "Main",
5 | "option_gameguid": "caab8cc1-112a-417f-aa89-bf8f42e48583",
6 | "option_gameid": "0",
7 | "option_game_speed": 30,
8 | "option_mips_for_3d_textures": false,
9 | "option_draw_colour": 4294967295,
10 | "option_window_colour": 255,
11 | "option_steam_app_id": "0",
12 | "option_sci_usesci": false,
13 | "option_author": "",
14 | "option_collision_compatibility": true,
15 | "option_copy_on_write_enabled": true,
16 | "option_spine_licence": false,
17 | "option_template_image": "${base_options_dir}/main/template_image.png",
18 | "option_template_icon": "${base_options_dir}/main/template_icon.png",
19 | "option_template_description": null,
20 | }
--------------------------------------------------------------------------------
/interop_test_23/options/operagx/options_operagx.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMOperaGXOptions",
3 | "resourceVersion": "1.0",
4 | "name": "operagx",
5 | "option_operagx_version": "1.0.0.0",
6 | "option_operagx_next_version": "1.0.0.0",
7 | "option_operagx_game_name": "${project_name}",
8 | "option_operagx_interpolate_pixels": true,
9 | "option_operagx_scale": 0,
10 | "option_operagx_texture_page": "2048x2048",
11 | "option_operagx_display_cursor": true,
12 | "option_operagx_guid": "",
13 | "option_operagx_team_name": "",
14 | "option_operagx_team_id": "",
15 | "option_operagx_editUrl": "",
16 | "option_operagx_internalShareUrl": "",
17 | "option_operagx_publicShareUrl": "",
18 | }
--------------------------------------------------------------------------------
/interop_test_23/options/tvos/options_tvos.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_tvos_display_name": "Made in GameMaker Studio 2",
3 | "option_tvos_bundle_name": "com.company.game",
4 | "option_tvos_version": "1.0.0.0",
5 | "option_tvos_output_dir": "~/GameMakerStudio2/tvOS",
6 | "option_tvos_team_id": "",
7 | "option_tvos_icon_400": "${base_options_dir}/tvos/icons/400.png",
8 | "option_tvos_icon_400_2x": "${base_options_dir}/tvos/icons/400_2x.png",
9 | "option_tvos_icon_1280": "${base_options_dir}/tvos/icons/1280.png",
10 | "option_tvos_topshelf": "${base_options_dir}/tvos/topshelf/topshelf.png",
11 | "option_tvos_topshelf_2x": "${base_options_dir}/tvos/topshelf/topshelf_2x.png",
12 | "option_tvos_topshelf_wide": "${base_options_dir}/tvos/topshelf/topshelf_wide.png",
13 | "option_tvos_topshelf_wide_2x": "${base_options_dir}/tvos/topshelf/topshelf_wide_2x.png",
14 | "option_tvos_splashscreen": "${base_options_dir}/tvos/splash/splash.png",
15 | "option_tvos_splashscreen_2x": "${base_options_dir}/tvos/splash/splash_2x.png",
16 | "option_tvos_splash_time": 10,
17 | "option_tvos_interpolate_pixels": true,
18 | "option_tvos_scale": 0,
19 | "option_tvos_texture_page": "2048x2048",
20 | "option_tvos_display_cursor": false,
21 | "option_tvos_push_notifications": false,
22 | "option_tvos_apple_sign_in": false,
23 | "option_tvos_podfile_path": "${options_dir}\\tvos\\Podfile",
24 | "option_tvos_podfile_lock_path": "${options_dir}\\tvos\\Podfile.lock",
25 | "resourceVersion": "1.3",
26 | "name": "tvOS",
27 | "tags": [],
28 | "resourceType": "GMtvOSOptions",
29 | }
--------------------------------------------------------------------------------
/interop_test_23/options/windows/options_windows.yy:
--------------------------------------------------------------------------------
1 | {
2 | "option_windows_display_name": "interop_test by YellowAfterlife",
3 | "option_windows_executable_name": "${project_name}",
4 | "option_windows_version": "1.0.0.0",
5 | "option_windows_company_info": "",
6 | "option_windows_product_info": "interop_test",
7 | "option_windows_copyright_info": "(c) YellowAfterlife",
8 | "option_windows_description_info": "",
9 | "option_windows_display_cursor": true,
10 | "option_windows_icon": "${base_options_dir}/windows/icons/icon.ico",
11 | "option_windows_save_location": 0,
12 | "option_windows_splash_screen": "${base_options_dir}/windows/splash/splash.png",
13 | "option_windows_use_splash": false,
14 | "option_windows_start_fullscreen": false,
15 | "option_windows_allow_fullscreen_switching": false,
16 | "option_windows_interpolate_pixels": false,
17 | "option_windows_vsync": false,
18 | "option_windows_resize_window": false,
19 | "option_windows_borderless": false,
20 | "option_windows_scale": 0,
21 | "option_windows_copy_exe_to_dest": false,
22 | "option_windows_sleep_margin": 10,
23 | "option_windows_texture_page": "2048x2048",
24 | "option_windows_installer_finished": "${base_options_dir}/windows/installer/finished.bmp",
25 | "option_windows_installer_header": "${base_options_dir}/windows/installer/header.bmp",
26 | "option_windows_license": "${base_options_dir}/windows/installer/license.txt",
27 | "option_windows_nsis_file": "${base_options_dir}/windows/installer/nsis_script.nsi",
28 | "option_windows_enable_steam": false,
29 | "option_windows_disable_sandbox": false,
30 | "option_windows_steam_use_alternative_launcher": true,
31 | "option_windows_use_x64": false,
32 | "resourceVersion": "1.1",
33 | "name": "Windows",
34 | "tags": [],
35 | "resourceType": "GMWindowsOptions",
36 | }
--------------------------------------------------------------------------------
/interop_test_23/rooms/rm_test/rm_test.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnd": false,
3 | "volume": 1.0,
4 | "parentRoom": null,
5 | "views": [
6 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
7 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
8 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
9 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
10 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
11 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
12 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
13 | {"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1024,"hview":768,"xport":0,"yport":0,"wport":1024,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
14 | ],
15 | "layers": [
16 | {"instances":[
17 | {"properties":[],"isDnd":false,"objectId":{"name":"obj_test","path":"objects/obj_test/obj_test.yy",},"inheritCode":false,"hasCreationCode":false,"colour":4294967295,"rotation":0.0,"scaleX":1.0,"scaleY":1.0,"imageIndex":0,"imageSpeed":1.0,"inheritedItemId":null,"frozen":false,"ignore":false,"inheritItemSettings":false,"x":0.0,"y":0.0,"resourceVersion":"1.0","name":"inst_F55A924E","tags":[],"resourceType":"GMRInstance",},
18 | ],"visible":true,"depth":0,"userdefinedDepth":true,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Compatibility_Instances_Depth_0","tags":[],"resourceType":"GMRInstanceLayer",},
19 | {"spriteId":null,"colour":4291141256,"x":0,"y":0,"htiled":false,"vtiled":false,"hspeed":0.0,"vspeed":0.0,"stretch":false,"animationFPS":15.0,"animationSpeedType":0,"userdefinedAnimFPS":false,"visible":true,"depth":2147483600,"userdefinedDepth":true,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Compatibility_Colour","tags":[],"resourceType":"GMRBackgroundLayer",},
20 | ],
21 | "inheritLayers": false,
22 | "creationCodeFile": "",
23 | "inheritCode": false,
24 | "instanceCreationOrder": [
25 | {"name":"inst_F55A924E","path":"rooms/rm_test/rm_test.yy",},
26 | ],
27 | "inheritCreationOrder": false,
28 | "sequenceId": null,
29 | "roomSettings": {
30 | "inheritRoomSettings": false,
31 | "Width": 480,
32 | "Height": 272,
33 | "persistent": false,
34 | },
35 | "viewSettings": {
36 | "inheritViewSettings": false,
37 | "enableViews": false,
38 | "clearViewBackground": true,
39 | "clearDisplayBuffer": true,
40 | },
41 | "physicsSettings": {
42 | "inheritPhysicsSettings": false,
43 | "PhysicsWorld": false,
44 | "PhysicsWorldGravityX": 0.0,
45 | "PhysicsWorldGravityY": 10.0,
46 | "PhysicsWorldPixToMetres": 0.1,
47 | },
48 | "parent": {
49 | "name": "Rooms",
50 | "path": "folders/Rooms.yy",
51 | },
52 | "resourceVersion": "1.0",
53 | "name": "rm_test",
54 | "tags": [],
55 | "resourceType": "GMRoom",
56 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/assert/assert.gml:
--------------------------------------------------------------------------------
1 | /// @param value
2 | /// @param want
3 | /// @param ?label
4 | function assert(_val, _want, _label) {
5 | if (_label == undefined) _label = "unnamed";
6 | if (!is_equal(_val, _want)) {
7 | show_error(
8 | "Want " + string(_want) + "\n" +
9 | "Have " + string(_val) + "\n" +
10 | "for " + string(_label)
11 | , 1)
12 | }
13 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/assert/assert.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "Scripts",
6 | "path": "folders/Scripts.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "assert",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/interop_test_23/interop_test_23.gml:
--------------------------------------------------------------------------------
1 | global.__ptrt_iq_thing = ["iq_thing"]
2 | function iq_thing(_ptr) constructor {
3 | __ptr__ = _ptr;
4 | static toString = function() /*=>*/ {return "iq_thing(0x" + string(__ptr__) + ")"};
5 | }
6 |
7 | global.__ptrt_iq_id = ["iq_id"]
8 | function iq_id(_id) constructor {
9 | __id__ = _id;
10 | static toString = function() /*=>*/ {return "iq_id(" + string(__id__) + ")"};
11 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/interop_test_23/interop_test_23.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "Extensions",
6 | "path": "folders/Extensions.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "interop_test_23",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/is_equal/is_equal.gml:
--------------------------------------------------------------------------------
1 | function is_equal(a, b, _depth = 0) {
2 | _depth += 1;
3 | if (is_array(a) && is_array(b)) {
4 | var n = array_length(a);
5 | if (n != array_length(b)) return false;
6 | for (var i = 0; i < n; i++) {
7 | if (!is_equal(a[i], b[i], _depth)) return false;
8 | }
9 | return true;
10 | }
11 | if (is_struct(a) && is_struct(b)) {
12 | var keys = variable_struct_get_names(a);
13 | var n = array_length(keys);
14 | if (n != array_length(variable_struct_get_names(b))) return false;
15 | for (var i = 0; i < n; i++) {
16 | var key = keys[i];
17 | if (!variable_struct_exists(b, key)) return false;
18 | if (!is_equal(a[$ key], b[$ key], _depth)) return false;
19 | }
20 | return true;
21 | }
22 | return a == b;
23 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/is_equal/is_equal.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "Scripts",
6 | "path": "folders/Scripts.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "is_equal",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test/scr_test.gml:
--------------------------------------------------------------------------------
1 | globalvar iq_use_structs;
2 | function scr_test(_use_structs) {
3 | iq_use_structs = _use_structs;
4 | scr_test_basics();
5 | scr_test_vector();
6 | scr_test_tuple();
7 | scr_test_buffer();
8 | scr_test_gml_ptr();
9 | scr_test_gml_id();
10 | scr_test_struct();
11 | scr_test_inout();
12 |
13 | trace(sfmt("Test OK! (use_structs=%)",_use_structs));
14 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test/scr_test.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "tests",
6 | "path": "folders/Scripts/tests.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "scr_test",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_basics/scr_test_basics.gml:
--------------------------------------------------------------------------------
1 | function scr_test_basics() {
2 | assert(iq_get_int(), 1);
3 |
4 | assert(iq_get_int64(), 0x123456789ABCDEF);
5 |
6 | assert(iq_get_string(), "hi!");
7 |
8 | var a = 0x123456789;
9 | var b = 0x987654321;
10 | assert(iq_add_int64(a, b), a + b);
11 |
12 | assert(iq_inc_opt_int(3), 4);
13 | assert(iq_inc_opt_int(undefined), undefined);
14 |
15 | assert(iq_def_ret_int(), 3);
16 |
17 | assert(iq_def_ret_string(), "OK!");
18 |
19 | assert(iq_add_strlens("a", "bb", "ccc", "dddd"), 10);
20 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_basics/scr_test_basics.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_basics",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_buffer/scr_test_buffer.gml:
--------------------------------------------------------------------------------
1 | function scr_test_buffer() {
2 | var buf = buffer_create(16, buffer_fixed, 1);
3 | buffer_fill(buf, 0, buffer_u8, 0xFF, 16);
4 | for (var i = 1; i <= 4; i++) buffer_write(buf, buffer_u8, i);
5 | assert(iq_get_buffer_sum(buf), 10);
6 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_buffer/scr_test_buffer.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_buffer",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_gml_id/scr_test_gml_id.gml:
--------------------------------------------------------------------------------
1 | function scr_test_gml_id() {
2 | var _id = iq_id_create();
3 | assert(_id != undefined, true);
4 | assert(iq_id_value(_id) != 0, true);
5 | iq_id_destroy(_id);
6 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_gml_id/scr_test_gml_id.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_gml_id",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_gml_ptr/scr_test_gml_ptr.gml:
--------------------------------------------------------------------------------
1 | function scr_test_gml_ptr() {
2 | var th = iq_thing_create(3);
3 | assert(iq_thing_get_count(th), 3);
4 | iq_thing_set_count(th, 5);
5 | assert(iq_thing_get_count(th), 5);
6 | iq_thing_destroy(th);
7 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_gml_ptr/scr_test_gml_ptr.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_gml_ptr",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_inout/scr_test_inout.gml:
--------------------------------------------------------------------------------
1 | function scr_test_inout() {
2 | var box = [3];
3 | iq_test_inout_box(box);
4 | assert(box[0], 4);
5 | //
6 | if (iq_use_structs) {
7 | var one = {
8 | a: 1, b: 3,
9 | text: "Hello!"
10 | }
11 | iq_test_inout_struct(one);
12 | assert(one.a, 2);
13 | assert(one.text, "Yeah!");
14 | } else {
15 | var one = [
16 | 1, 3,
17 | "Hello!"
18 | ];
19 | iq_test_inout_struct(one);
20 | assert(one[0], 2);
21 | assert(one[2], "Yeah!");
22 | }
23 | //
24 | var arr = [1, 2, 3];
25 | iq_test_inout_int_vector(arr);
26 | assert(arr, [2, 3, 4]);
27 | //
28 | if (iq_use_structs) {
29 | var arr = [
30 | { a: 1, b: 3, text: "A" },
31 | { a: 2, b: 4, text: "B" },
32 | ];
33 | iq_test_inout_struct_vector(arr);
34 | }
35 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_inout/scr_test_inout.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_inout",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_struct/scr_test_struct.gml:
--------------------------------------------------------------------------------
1 | function scr_test_struct() {
2 | if (iq_use_structs) {
3 | assert(iq_get_struct_vec(), [
4 | { ind: 1, name: "one" },
5 | { ind: 2, name: "two-" },
6 | { ind: 3, name: "tri" },
7 | ]);
8 | } else {
9 | assert(iq_get_struct_vec(), [
10 | [1, "one"],
11 | [2, "two-"],
12 | [3, "tri"],
13 | ]);
14 | }
15 |
16 | if (iq_use_structs) {
17 | var m1 = {
18 | num: 3,
19 | str: "hi!",
20 | grid: [
21 | [1, 2, 3],
22 | [4, 5, 6],
23 | [7, 8, 9],
24 | ],
25 | sub: [
26 | { a: 1, b: 2 },
27 | { a: 3, b: 4 },
28 | ]
29 | }
30 | var m2 = iq_mixed(m1);
31 | assert(m2, m1, "mixed");
32 | }
33 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_struct/scr_test_struct.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_struct",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_tuple/scr_test_tuple.gml:
--------------------------------------------------------------------------------
1 | function scr_test_tuple() {
2 | assert(iq_get_int64_pair(), [1, 2]);
3 |
4 | assert(iq_int64_pair_sum([2, 3]), 5);
5 |
6 | assert(iq_int64_pair_swap([3, 4]), [4, 3]);
7 |
8 | assert(iq_get_int64_pair_vec_sum([
9 | [1, 2],
10 | [3, 4],
11 | ]), [4, 6]);
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_tuple/scr_test_tuple.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_tuple",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_vector/scr_test_vector.gml:
--------------------------------------------------------------------------------
1 | function scr_test_vector() {
2 | assert(iq_get_vec(), [1, 2, 3]);
3 |
4 | assert(iq_get_opt_vec(true), [1, 2, 3]);
5 | assert(iq_get_opt_vec(false), undefined);
6 |
7 | assert(iq_get_int64_vec_sum([1, 2, 3]), 6);
8 |
9 | assert(iq_get_length_of_strings(["A", "B", "CD"]), 4);
10 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_vector/scr_test_vector.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_vector",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_yyri/scr_test_yyri.gml:
--------------------------------------------------------------------------------
1 | function scr_test_yyri() {
2 | assert(im_get_int(), 1);
3 | assert(im_get_string(), "wow");
4 | assert(im_get_result(), "result");
5 | assert(im_add_ints(1, 4), 5);
6 | assert(im_add_rest(1, 2, 3), 6);
7 | assert(im_string_length("hello"), 5);
8 | assert(im_typeof(""), "string");
9 |
10 | trace(sfmt("Mangled test OK!"));
11 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/scr_test_yyri/scr_test_yyri.yy:
--------------------------------------------------------------------------------
1 | {
2 | "resourceType": "GMScript",
3 | "resourceVersion": "1.0",
4 | "name": "scr_test_yyri",
5 | "isDnD": false,
6 | "isCompatibility": false,
7 | "parent": {
8 | "name": "tests",
9 | "path": "folders/Scripts/tests.yy",
10 | },
11 | "tags": [],
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/sfmt/sfmt.gml:
--------------------------------------------------------------------------------
1 | global.sfmt_buf = buffer_create(1024, buffer_grow, 1);
2 | global.sfmt_map = ds_map_create();
3 | global.sfmt_warn = ds_map_create();
4 |
5 | /// @description sfmt(format, ...values)
6 | /// @param format
7 | /// @param ...values
8 | function sfmt() {
9 | // sfmt("%/% hp", 1, 2) -> "1/2 hp"
10 | var f = argument[0];
11 | var w = global.sfmt_map[?f], i, n;
12 | if (w == undefined) {
13 | w[0] = "";
14 | global.sfmt_map[?f] = w;
15 | i = string_pos("%", f);
16 | n = 0;
17 | while (i) {
18 | w[n++] = string_copy(f, 1, i - 1);
19 | f = string_delete(f, 1, i);
20 | i = string_pos("%", f);
21 | }
22 | w[n++] = f;
23 | } else n = array_length_1d(w);
24 | //
25 | var b = global.sfmt_buf;
26 | buffer_seek(b, buffer_seek_start, 0);
27 | buffer_write(b, buffer_text, w[0]);
28 | var m = argument_count;
29 | for (i = 1; i < n; i++) {
30 | if (i < m) {
31 | f = string(argument[i]);
32 | if (f != "") buffer_write(b, buffer_text, f);
33 | }
34 | f = w[i];
35 | if (f != "") buffer_write(b, buffer_text, f);
36 | }
37 | buffer_write(b, buffer_u8, 0);
38 | buffer_seek(b, buffer_seek_start, 0);
39 | return buffer_read(b, buffer_string);
40 | }
41 |
--------------------------------------------------------------------------------
/interop_test_23/scripts/sfmt/sfmt.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "Scripts",
6 | "path": "folders/Scripts.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "sfmt",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_23/scripts/trace/trace.gml:
--------------------------------------------------------------------------------
1 | /// @description trace(...)
2 | /// @param ...
3 | function trace() {
4 | var r = string(argument[0]);
5 | for (var i = 1; i < argument_count; i++) {
6 | r += " " + string(argument[i]);
7 | }
8 | show_debug_message(r);
9 |
10 |
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/interop_test_23/scripts/trace/trace.yy:
--------------------------------------------------------------------------------
1 | {
2 | "isDnD": false,
3 | "isCompatibility": false,
4 | "parent": {
5 | "name": "Scripts",
6 | "path": "folders/Scripts.yy",
7 | },
8 | "resourceVersion": "1.0",
9 | "name": "trace",
10 | "tags": [],
11 | "resourceType": "GMScript",
12 | }
--------------------------------------------------------------------------------
/interop_test_yy/extensions/interop_test/interop_test.gml:
--------------------------------------------------------------------------------
1 | #define itr_test_init
2 | global.__iq_use_structs = false;
3 | global.__ptrt_iq_thing = ["iq_thing"];
4 |
5 | #define itr_test_prepare_buffer
6 | /// (size:int)->buffer~
7 | var _size = argument0;
8 | gml_pragma("global", "global.__itr_test_buffer = undefined");
9 | var _buf = global.__itr_test_buffer;
10 | if (_buf == undefined) {
11 | _buf = buffer_create(_size, buffer_grow, 1);
12 | global.__itr_test_buffer = _buf;
13 | } else if (buffer_get_size(_buf) < _size) {
14 | buffer_resize(_buf, _size);
15 | }
16 | buffer_seek(_buf, buffer_seek_start, 0);
17 | return _buf;
18 |
19 | #define itr_test_read_chars
20 | /// (buffer:buffer, len:int)->string~
21 | var _buf = argument0, _len = argument1;
22 | gml_pragma("global", "global.__itr_test_string_buffer = undefined");
23 | var _tmp = global.__itr_test_string_buffer;
24 | if (_tmp == undefined) {
25 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
26 | global.__itr_test_string_buffer = _tmp;
27 | } else if (buffer_get_size(_tmp) <= _len) {
28 | buffer_resize(_tmp, _len + 1);
29 | }
30 | buffer_copy(_buf, buffer_tell(_buf), _len, _tmp, 0);
31 | buffer_seek(_buf, buffer_seek_relative, _len);
32 | buffer_poke(_tmp, _len, buffer_u8, 0);
33 | buffer_seek(_tmp, buffer_seek_start, 0);
34 | return buffer_read(_tmp, buffer_string);
35 |
36 | #define itr_test_write_chars
37 | /// (buffer:buffer, str:string, len:int)~
38 | var _buf = argument0, _str = argument1, _len = argument2;
39 | var _tmp = global.__itr_test_string_buffer;
40 | if (_tmp == undefined) {
41 | _tmp = buffer_create(_len + 1, buffer_grow, 1);
42 | global.__itr_test_string_buffer = _tmp;
43 | }
44 | buffer_seek(_tmp, buffer_seek_start, 0);
45 | buffer_write(_tmp, buffer_text, _str);
46 | var _pos = buffer_tell(_tmp);
47 | if (_pos < _len) buffer_fill(_tmp, _pos, buffer_u8, 0, _len - _pos);
48 | buffer_copy(_tmp, 0, _len, _buf, buffer_tell(_buf));
49 | buffer_seek(_buf, buffer_seek_relative, _len);
--------------------------------------------------------------------------------
/interop_test_yy/fonts/fnt_test/fnt_test.gms1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test_yy/fonts/fnt_test/fnt_test.gms1.png
--------------------------------------------------------------------------------
/interop_test_yy/fonts/fnt_test/fnt_test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YAL-GameMaker-Tools/GmlCppExtFuncs/5293a574efac244853219eecb3f745ca4e062c86/interop_test_yy/fonts/fnt_test/fnt_test.png
--------------------------------------------------------------------------------
/interop_test_yy/objects/obj_test/Create_0.gml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/interop_test_yy/objects/obj_test/Draw_0.gml:
--------------------------------------------------------------------------------
1 | draw_set_font(fnt_test);
2 | draw_set_color(c_white);
3 |
4 |
--------------------------------------------------------------------------------
/interop_test_yy/objects/obj_test/Step_0.gml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/interop_test_yy/objects/obj_test/obj_test.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "9a74872b-1d34-4b7c-8038-1116e4426c86",
3 | "modelName": "GMObject",
4 | "mvc": "1.0",
5 | "name": "obj_test",
6 | "eventList": [
7 | {
8 | "id": "f93557ac-a01c-475b-a656-4fbd2ebcf2fb",
9 | "modelName": "GMEvent",
10 | "mvc": "1.0",
11 | "IsDnD": false,
12 | "collisionObjectId": "00000000-0000-0000-0000-000000000000",
13 | "enumb": 0,
14 | "eventtype": 0,
15 | "m_owner": "9a74872b-1d34-4b7c-8038-1116e4426c86"
16 | },
17 | {
18 | "id": "9f151821-c696-4aef-b011-948071008f29",
19 | "modelName": "GMEvent",
20 | "mvc": "1.0",
21 | "IsDnD": false,
22 | "collisionObjectId": "00000000-0000-0000-0000-000000000000",
23 | "enumb": 0,
24 | "eventtype": 3,
25 | "m_owner": "9a74872b-1d34-4b7c-8038-1116e4426c86"
26 | },
27 | {
28 | "id": "6ef8ae5e-f16b-4a4b-8d63-5453f3f747bb",
29 | "modelName": "GMEvent",
30 | "mvc": "1.0",
31 | "IsDnD": false,
32 | "collisionObjectId": "00000000-0000-0000-0000-000000000000",
33 | "enumb": 0,
34 | "eventtype": 8,
35 | "m_owner": "9a74872b-1d34-4b7c-8038-1116e4426c86"
36 | }
37 | ],
38 | "maskSpriteId": "00000000-0000-0000-0000-000000000000",
39 | "overriddenProperties": null,
40 | "parentObjectId": "00000000-0000-0000-0000-000000000000",
41 | "persistent": false,
42 | "physicsAngularDamping": 0.1,
43 | "physicsDensity": 0.5,
44 | "physicsFriction": 0.2,
45 | "physicsGroup": 0,
46 | "physicsKinematic": false,
47 | "physicsLinearDamping": 0.1,
48 | "physicsObject": false,
49 | "physicsRestitution": 0.1,
50 | "physicsSensor": false,
51 | "physicsShape": 0,
52 | "physicsShapePoints": [
53 |
54 | ],
55 | "physicsStartAwake": true,
56 | "properties": null,
57 | "solid": false,
58 | "spriteId": "00000000-0000-0000-0000-000000000000",
59 | "visible": true
60 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/amazonfire/options_amazonfire.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "a128950b-5063-4876-b4a6-b99dbd2ea6d1",
3 | "modelName": "GMAmazonFireOptions",
4 | "mvc": "1.0",
5 | "name": "Amazon Fire",
6 | "option_amazonfire_application_tag_inject": null,
7 | "option_amazonfire_build_tools": "",
8 | "option_amazonfire_compile_sdk": "",
9 | "option_amazonfire_display_name": "Made in GameMaker Studio 2",
10 | "option_amazonfire_gamepad_support": true,
11 | "option_amazonfire_icon_hdpi": "${base_options_dir}\\amazonfire\\icons\\hdpi.png",
12 | "option_amazonfire_icon_ldpi": "${base_options_dir}\\amazonfire\\icons\\ldpi.png",
13 | "option_amazonfire_icon_mdpi": "${base_options_dir}\\amazonfire\\icons\\mdpi.png",
14 | "option_amazonfire_icon_xhdpi": "${base_options_dir}\\amazonfire\\icons\\xhdpi.png",
15 | "option_amazonfire_icon_xxhdpi": "${base_options_dir}\\amazonfire\\icons\\xxhdpi.png",
16 | "option_amazonfire_icon_xxxhdpi": "${base_options_dir}\\amazonfire\\icons\\xxxhdpi.png",
17 | "option_amazonfire_install_location": 0,
18 | "option_amazonfire_interpolate_pixels": false,
19 | "option_amazonfire_lint": false,
20 | "option_amazonfire_minimum_sdk": "",
21 | "option_amazonfire_orient_landscape": true,
22 | "option_amazonfire_orient_landscape_flipped": true,
23 | "option_amazonfire_orient_portrait": true,
24 | "option_amazonfire_orient_portrait_flipped": true,
25 | "option_amazonfire_package_company": "company",
26 | "option_amazonfire_package_domain": "com",
27 | "option_amazonfire_package_product": "game",
28 | "option_amazonfire_permission_bluetooth": false,
29 | "option_amazonfire_permission_internet": true,
30 | "option_amazonfire_permission_network_state": false,
31 | "option_amazonfire_permission_read_phone_state": false,
32 | "option_amazonfire_permission_record_audio": false,
33 | "option_amazonfire_permission_write_external_storage": false,
34 | "option_amazonfire_scale": 0,
35 | "option_amazonfire_screen_depth": 0,
36 | "option_amazonfire_sleep_margin": 4,
37 | "option_amazonfire_splash_screens_landscape": "${base_options_dir}\\amazonfire\\splash\\landscape.png",
38 | "option_amazonfire_splash_screens_portrait": "${base_options_dir}\\amazonfire\\splash\\portrait.png",
39 | "option_amazonfire_splash_time": 0,
40 | "option_amazonfire_support_lib": "",
41 | "option_amazonfire_sync_android": false,
42 | "option_amazonfire_target_sdk": "",
43 | "option_amazonfire_texture_page": "2048x2048",
44 | "option_amazonfire_tools_from_version": false,
45 | "option_amazonfire_tv_banner": "${base_options_dir}\\amazonfire\\tv_banner.png",
46 | "option_amazonfire_version": {
47 | "build": 0,
48 | "major": 1,
49 | "minor": 0,
50 | "revision": 0
51 | }
52 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/android/options_android.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "e42bf5cc-3f46-4d67-a6d0-a4885a11ac3f",
3 | "modelName": "GMAndroidOptions",
4 | "mvc": "1.0",
5 | "name": "Android",
6 | "option_android_application_tag_inject": null,
7 | "option_android_arch_arm64": false,
8 | "option_android_arch_armv7": true,
9 | "option_android_arch_x86": false,
10 | "option_android_arch_x86_64": false,
11 | "option_android_build_tools": "",
12 | "option_android_compile_sdk": "",
13 | "option_android_device_support": 0,
14 | "option_android_display_name": "Made in GameMaker Studio 2",
15 | "option_android_facebook_app_display_name": "",
16 | "option_android_facebook_id": "",
17 | "option_android_gamepad_support": true,
18 | "option_android_google_apk_expansion": false,
19 | "option_android_google_cloud_saving": false,
20 | "option_android_google_licensing_public_key": "",
21 | "option_android_google_services_app_id": "",
22 | "option_android_icon_adaptive_generate": false,
23 | "option_android_icon_adaptive_hdpi": "${base_options_dir}\/android\/icons_adaptive\/hdpi.png",
24 | "option_android_icon_adaptive_ldpi": "${base_options_dir}\/android\/icons_adaptive\/ldpi.png",
25 | "option_android_icon_adaptive_mdpi": "${base_options_dir}\/android\/icons_adaptive\/mdpi.png",
26 | "option_android_icon_adaptive_xhdpi": "${base_options_dir}\/android\/icons_adaptive\/xhdpi.png",
27 | "option_android_icon_adaptive_xxhdpi": "${base_options_dir}\/android\/icons_adaptive\/xxhdpi.png",
28 | "option_android_icon_adaptive_xxxhdpi": "${base_options_dir}\/android\/icons_adaptive\/xxxhdpi.png",
29 | "option_android_icon_adaptivebg_hdpi": "${base_options_dir}\/android\/icons_adaptivebg\/hdpi.png",
30 | "option_android_icon_adaptivebg_ldpi": "${base_options_dir}\/android\/icons_adaptivebg\/ldpi.png",
31 | "option_android_icon_adaptivebg_mdpi": "${base_options_dir}\/android\/icons_adaptivebg\/mdpi.png",
32 | "option_android_icon_adaptivebg_xhdpi": "${base_options_dir}\/android\/icons_adaptivebg\/xhdpi.png",
33 | "option_android_icon_adaptivebg_xxhdpi": "${base_options_dir}\/android\/icons_adaptivebg\/xxhdpi.png",
34 | "option_android_icon_adaptivebg_xxxhdpi": "${base_options_dir}\/android\/icons_adaptivebg\/xxxhdpi.png",
35 | "option_android_icon_hdpi": "${base_options_dir}\/android\/icons\/hdpi.png",
36 | "option_android_icon_ldpi": "${base_options_dir}\/android\/icons\/ldpi.png",
37 | "option_android_icon_mdpi": "${base_options_dir}\/android\/icons\/mdpi.png",
38 | "option_android_icon_xhdpi": "${base_options_dir}\/android\/icons\/xhdpi.png",
39 | "option_android_icon_xxhdpi": "${base_options_dir}\/android\/icons\/xxhdpi.png",
40 | "option_android_icon_xxxhdpi": "${base_options_dir}\/android\/icons\/xxxhdpi.png",
41 | "option_android_install_location": 0,
42 | "option_android_interpolate_pixels": false,
43 | "option_android_lint": false,
44 | "option_android_minimum_sdk": "",
45 | "option_android_orient_landscape": true,
46 | "option_android_orient_landscape_flipped": true,
47 | "option_android_orient_portrait": true,
48 | "option_android_orient_portrait_flipped": true,
49 | "option_android_package_company": "company",
50 | "option_android_package_domain": "com",
51 | "option_android_package_product": "game",
52 | "option_android_permission_bluetooth": false,
53 | "option_android_permission_internet": true,
54 | "option_android_permission_network_state": false,
55 | "option_android_permission_read_phone_state": false,
56 | "option_android_permission_record_audio": false,
57 | "option_android_permission_write_external_storage": false,
58 | "option_android_scale": 0,
59 | "option_android_screen_depth": 0,
60 | "option_android_sleep_margin": 4,
61 | "option_android_splash_screens_landscape": "${base_options_dir}\/android\/splash\/landscape.png",
62 | "option_android_splash_screens_portrait": "${base_options_dir}\/android\/splash\/portrait.png",
63 | "option_android_splash_time": 0,
64 | "option_android_support_lib": "",
65 | "option_android_sync_amazon": false,
66 | "option_android_target_sdk": "",
67 | "option_android_texture_page": "2048x2048",
68 | "option_android_tools_from_version": false,
69 | "option_android_tv_banner": "${base_options_dir}\\android\\tv_banner.png",
70 | "option_android_tv_isgame": true,
71 | "option_android_use_facebook": false,
72 | "option_android_version": {
73 | "build": 0,
74 | "major": 1,
75 | "minor": 0,
76 | "revision": 0
77 | }
78 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/html5/options_html5.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "75ac291e-7061-4bcb-8e8a-3b3545332d41",
3 | "modelName": "GMHtml5Options",
4 | "mvc": "1.0",
5 | "name": "HTML5",
6 | "option_html5_allow_fullscreen": true,
7 | "option_html5_browser_title": "Made in GameMaker Studio 2",
8 | "option_html5_centregame": false,
9 | "option_html5_display_cursor": true,
10 | "option_html5_facebook_app_display_name": "",
11 | "option_html5_facebook_id": "",
12 | "option_html5_flurry_enable": false,
13 | "option_html5_flurry_id": "",
14 | "option_html5_foldername": "html5game",
15 | "option_html5_google_analytics_enable": false,
16 | "option_html5_google_tracking_id": "",
17 | "option_html5_icon": "${base_options_dir}\/html5\/fav.ico",
18 | "option_html5_index": "",
19 | "option_html5_interpolate_pixels": false,
20 | "option_html5_jsprepend": "",
21 | "option_html5_loadingbar": "",
22 | "option_html5_localrunalert": true,
23 | "option_html5_outputdebugtoconsole": true,
24 | "option_html5_outputname": "index.html",
25 | "option_html5_scale": 0,
26 | "option_html5_splash_png": "${base_options_dir}\/html5\/splash.png",
27 | "option_html5_texture_page": "2048x2048",
28 | "option_html5_use_facebook": false,
29 | "option_html5_usebuiltinfont": true,
30 | "option_html5_usebuiltinparticles": true,
31 | "option_html5_usesplash": false,
32 | "option_html5_version": {
33 | "build": 0,
34 | "major": 1,
35 | "minor": 0,
36 | "revision": 0
37 | },
38 | "option_html5_webgl": 2
39 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/linux/options_linux.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "a9188620-a624-4a5a-83ae-a1b53faf038b",
3 | "modelName": "GMLinuxOptions",
4 | "mvc": "1.0",
5 | "name": "Linux",
6 | "option_linux_allow_fullscreen": false,
7 | "option_linux_disable_sandbox": false,
8 | "option_linux_display_cursor": true,
9 | "option_linux_display_name": "Made in GameMaker Studio 2",
10 | "option_linux_display_splash": false,
11 | "option_linux_enable_steam": false,
12 | "option_linux_homepage": "http:\/\/www.yoyogames.com",
13 | "option_linux_icon": "${base_options_dir}\/linux\/icons\/64.png",
14 | "option_linux_interpolate_pixels": false,
15 | "option_linux_long_desc": "",
16 | "option_linux_maintainer_email": "",
17 | "option_linux_resize_window": false,
18 | "option_linux_scale": 0,
19 | "option_linux_short_desc": "",
20 | "option_linux_splash_screen": "${base_options_dir}\/linux\/splash\/splash.png",
21 | "option_linux_start_fullscreen": false,
22 | "option_linux_sync": false,
23 | "option_linux_texture_page": "2048x2048",
24 | "option_linux_version": {
25 | "build": 0,
26 | "major": 1,
27 | "minor": 0,
28 | "revision": 0
29 | }
30 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/mac/options_mac.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f418569b-3bdd-4706-a0e4-364317f54032",
3 | "modelName": "GMMacOptions",
4 | "mvc": "1.0",
5 | "name": "macOS",
6 | "option_mac_allow_fullscreen": false,
7 | "option_mac_allow_incoming_network": false,
8 | "option_mac_allow_outgoing_network": false,
9 | "option_mac_app_category": "Games",
10 | "option_mac_app_id": "com.company.game",
11 | "option_mac_apple_sign_in": false,
12 | "option_mac_build_app_store": false,
13 | "option_mac_copyright": "(c) 2018 CompanyName",
14 | "option_mac_disable_sandbox": false,
15 | "option_mac_display_cursor": true,
16 | "option_mac_display_name": "Made in GameMaker Studio 2",
17 | "option_mac_enable_retina": false,
18 | "option_mac_enable_steam": false,
19 | "option_mac_icon_png": "${base_options_dir}\/mac\/icons\/1024.png",
20 | "option_mac_interpolate_pixels": false,
21 | "option_mac_menu_dock": false,
22 | "option_mac_output_dir": "~\/GameMakerStudio2\/Mac",
23 | "option_mac_resize_window": false,
24 | "option_mac_scale": 0,
25 | "option_mac_signing_identity": "Developer ID Application:",
26 | "option_mac_splash_png": "${base_options_dir}\/mac\/splash\/splash.png",
27 | "option_mac_start_fullscreen": false,
28 | "option_mac_team_id": null,
29 | "option_mac_texture_page": "2048x2048",
30 | "option_mac_version": {
31 | "build": 0,
32 | "major": 1,
33 | "minor": 0,
34 | "revision": 0
35 | },
36 | "option_mac_vsync": false
37 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/main/inherited/options_main.inherited.yy:
--------------------------------------------------------------------------------
1 | 1.0.0←ed6a955d-5826-4f98-a450-10b414266c27←ed6a955d-5826-4f98-a450-10b414266c27|{
2 | "option_game_speed": 30,
3 | "option_gameguid": "caab8cc1-112a-417f-aa89-bf8f42e48583"
4 | }←1225f6b0-ac20-43bd-a82e-be73fa0b6f4f|{
5 | "targets": 461609314234257646
6 | }←7b2c4976-1e09-44e5-8256-c527145e03bb|{
7 | "targets": 461609314234257646
8 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/switch/options_switch.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "3a5af38c-757d-41ae-98c0-5d4b09e14e6a",
3 | "modelName": "GMSwitchOptions",
4 | "mvc": "1.0",
5 | "name": "Switch",
6 | "option_switch_allow_debug_output": false,
7 | "option_switch_check_nsp_publish_errors": true,
8 | "option_switch_enable_fileaccess_checking": true,
9 | "option_switch_enable_nex_libraries": false,
10 | "option_switch_interpolate_pixels": true,
11 | "option_switch_project_nmeta": "${options_dir}\/switch\/application.nmeta",
12 | "option_switch_scale": 0,
13 | "option_switch_splash_screen": "${options_dir}\\switch\\splash.png",
14 | "option_switch_texture_page": "2048x2048",
15 | "option_switch_use_splash": true
16 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/tvos/options_tvos.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "93566aad-c3b3-48a9-8fa7-9c5ee19f74ac",
3 | "modelName": "GMtvOSOptions",
4 | "mvc": "1.0",
5 | "name": "tvOS",
6 | "option_tvos_apple_sign_in": false,
7 | "option_tvos_bundle_name": "com.company.game",
8 | "option_tvos_display_cursor": false,
9 | "option_tvos_display_name": "Made in GameMaker Studio 2",
10 | "option_tvos_icon_1280": "${base_options_dir}\\tvos\\icons\\1280.png",
11 | "option_tvos_icon_400": "${base_options_dir}\\tvos\\icons\\400.png",
12 | "option_tvos_icon_400_2x": "${base_options_dir}\\tvos\\icons\\400_2x.png",
13 | "option_tvos_interpolate_pixels": true,
14 | "option_tvos_output_dir": "~\/GameMakerStudio2\/tvOS",
15 | "option_tvos_push_notifications": false,
16 | "option_tvos_scale": 0,
17 | "option_tvos_splash_time": 10,
18 | "option_tvos_splashscreen": "${base_options_dir}\\tvos\\splash\\splash.png",
19 | "option_tvos_splashscreen_2x": "${base_options_dir}\\tvos\\splash\\splash_2x.png",
20 | "option_tvos_team_id": "",
21 | "option_tvos_texture_page": "2048x2048",
22 | "option_tvos_topshelf": "${base_options_dir}\\tvos\\topshelf\\topshelf.png",
23 | "option_tvos_topshelf_2x": "${base_options_dir}\\tvos\\topshelf\\topshelf_2x.png",
24 | "option_tvos_topshelf_wide": "${base_options_dir}\\tvos\\topshelf\\topshelf_wide.png",
25 | "option_tvos_topshelf_wide_2x": "${base_options_dir}\\tvos\\topshelf\\topshelf_wide_2x.png",
26 | "option_tvos_version": {
27 | "build": 0,
28 | "major": 1,
29 | "minor": 0,
30 | "revision": 0
31 | }
32 | }
--------------------------------------------------------------------------------
/interop_test_yy/options/windows/options_windows.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "cc98d028-7bdd-4680-85f3-c87a7baa481e",
3 | "modelName": "GMWindowsOptions",
4 | "mvc": "1.0",
5 | "name": "Windows",
6 | "option_windows_allow_fullscreen_switching": false,
7 | "option_windows_borderless": false,
8 | "option_windows_company_info": "",
9 | "option_windows_copy_exe_to_dest": false,
10 | "option_windows_copyright_info": "(c) YellowAfterlife",
11 | "option_windows_description_info": "",
12 | "option_windows_disable_sandbox": false,
13 | "option_windows_display_cursor": true,
14 | "option_windows_display_name": "interop_test by YellowAfterlife",
15 | "option_windows_enable_steam": false,
16 | "option_windows_executable_name": "${project_name}",
17 | "option_windows_icon": "${base_options_dir}\\windows\\icons\\icon.ico",
18 | "option_windows_installer_finished": "${base_options_dir}\\windows\\installer\\finished.bmp",
19 | "option_windows_installer_header": "${base_options_dir}\\windows\\installer\\header.bmp",
20 | "option_windows_interpolate_pixels": false,
21 | "option_windows_license": "${base_options_dir}\\windows\\installer\\license.txt",
22 | "option_windows_nsis_file": "${base_options_dir}\\windows\\installer\\nsis_script.nsi",
23 | "option_windows_product_info": "interop_test",
24 | "option_windows_resize_window": false,
25 | "option_windows_save_location": 0,
26 | "option_windows_scale": 0,
27 | "option_windows_sleep_margin": 10,
28 | "option_windows_splash_screen": "${base_options_dir}\\windows\\splash\\splash.png",
29 | "option_windows_start_fullscreen": false,
30 | "option_windows_steam_use_alternative_launcher": true,
31 | "option_windows_texture_page": "2048x2048",
32 | "option_windows_use_splash": false,
33 | "option_windows_version": {
34 | "build": 0,
35 | "major": 1,
36 | "minor": 0,
37 | "revision": 0
38 | },
39 | "option_windows_vsync": false
40 | }
--------------------------------------------------------------------------------
/interop_test_yy/scripts/trace/trace.gml:
--------------------------------------------------------------------------------
1 | /// @description trace(...)
2 | /// @param ...
3 | var r = string(argument[0]);
4 | for (var i = 1; i < argument_count; i++) {
5 | r += " " + string(argument[i]);
6 | }
7 | show_debug_message(r);
8 |
--------------------------------------------------------------------------------
/interop_test_yy/scripts/trace/trace.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "b0dd5a43-c44b-402e-b40f-a394287a9e3e",
3 | "modelName": "GMScript",
4 | "mvc": "1.0",
5 | "name": "trace",
6 | "IsCompatibility": false,
7 | "IsDnD": false
8 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/1a1012ca-9702-4cd0-870a-3101ca12fddb.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1a1012ca-9702-4cd0-870a-3101ca12fddb",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "1a1012ca-9702-4cd0-870a-3101ca12fddb",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMSprite",
10 | "folderName": "sprites",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Sprites"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/4f96784b-1ebd-4fc6-8c5b-10ee426a2840.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "4f96784b-1ebd-4fc6-8c5b-10ee426a2840",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "4f96784b-1ebd-4fc6-8c5b-10ee426a2840",
6 | "children": [
7 | "1a1012ca-9702-4cd0-870a-3101ca12fddb",
8 | "9fdcc299-adf8-4729-b2f3-076ababf81ed",
9 | "9878a9d0-ce0a-4455-91a7-89de6e4976a2",
10 | "e5b1e8fe-f417-43e8-b65f-8a518d723aea",
11 | "c9dcc6e5-46f1-4578-8543-9af4f6a4f7de",
12 | "f664cd6f-a19b-470a-8b94-844b0367b313",
13 | "f2ec9b0e-c3fe-4297-a78d-fa6f418fd827",
14 | "c583b9bc-76c2-490f-a077-1eeafac7f5ec",
15 | "e5bc0382-83e6-4bfa-b68f-c702a7545129",
16 | "504c1931-39ad-4f48-b783-4eb537b963d6",
17 | "f8edfe34-8789-4236-b7e4-741b59e181b8",
18 | "690caa00-bb5f-4c7f-b921-6fd3330a6bc3",
19 | "6e9a4a1b-fa39-4f06-94c9-1a7f8822216a",
20 | "8c638ff8-1abe-4e11-bc32-7ef6af8b7b4f",
21 | "81be6123-f045-42c2-ad8f-dd97676ed387"
22 | ],
23 | "filterType": "root",
24 | "folderName": "Default",
25 | "isDefaultView": true,
26 | "localisedFolderName": ""
27 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/504c1931-39ad-4f48-b783-4eb537b963d6.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "504c1931-39ad-4f48-b783-4eb537b963d6",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "504c1931-39ad-4f48-b783-4eb537b963d6",
6 | "children": [
7 | "ce213238-b114-4f2b-bed8-b066f6e9de72"
8 | ],
9 | "filterType": "GMRoom",
10 | "folderName": "rooms",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Rooms"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/690caa00-bb5f-4c7f-b921-6fd3330a6bc3.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "690caa00-bb5f-4c7f-b921-6fd3330a6bc3",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "690caa00-bb5f-4c7f-b921-6fd3330a6bc3",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMIncludedFile",
10 | "folderName": "datafiles",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_IncludedFiles"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/6e9a4a1b-fa39-4f06-94c9-1a7f8822216a.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "6e9a4a1b-fa39-4f06-94c9-1a7f8822216a",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "6e9a4a1b-fa39-4f06-94c9-1a7f8822216a",
6 | "children": [
7 | "9fa1a0e1-7fc5-429a-b8c2-75333f34fd29"
8 | ],
9 | "filterType": "GMExtension",
10 | "folderName": "extensions",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Extensions"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/81be6123-f045-42c2-ad8f-dd97676ed387.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "81be6123-f045-42c2-ad8f-dd97676ed387",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "81be6123-f045-42c2-ad8f-dd97676ed387",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMConfig",
10 | "folderName": "configs",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Configs"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/8c638ff8-1abe-4e11-bc32-7ef6af8b7b4f.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "8c638ff8-1abe-4e11-bc32-7ef6af8b7b4f",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "8c638ff8-1abe-4e11-bc32-7ef6af8b7b4f",
6 | "children": [
7 | "ed6a955d-5826-4f98-a450-10b414266c27",
8 | "f418569b-3bdd-4706-a0e4-364317f54032",
9 | "a9188620-a624-4a5a-83ae-a1b53faf038b",
10 | "cc98d028-7bdd-4680-85f3-c87a7baa481e",
11 | "3a5af38c-757d-41ae-98c0-5d4b09e14e6a"
12 | ],
13 | "filterType": "GMOptions",
14 | "folderName": "options",
15 | "isDefaultView": false,
16 | "localisedFolderName": "ResourceTree_Options"
17 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/9878a9d0-ce0a-4455-91a7-89de6e4976a2.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "9878a9d0-ce0a-4455-91a7-89de6e4976a2",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "9878a9d0-ce0a-4455-91a7-89de6e4976a2",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMSound",
10 | "folderName": "sounds",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Sounds"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/9fdcc299-adf8-4729-b2f3-076ababf81ed.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "9fdcc299-adf8-4729-b2f3-076ababf81ed",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "9fdcc299-adf8-4729-b2f3-076ababf81ed",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMTileSet",
10 | "folderName": "tilesets",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Tilesets"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/c583b9bc-76c2-490f-a077-1eeafac7f5ec.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "c583b9bc-76c2-490f-a077-1eeafac7f5ec",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "c583b9bc-76c2-490f-a077-1eeafac7f5ec",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMTimeline",
10 | "folderName": "timelines",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Timelines"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/c9dcc6e5-46f1-4578-8543-9af4f6a4f7de.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "c9dcc6e5-46f1-4578-8543-9af4f6a4f7de",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "c9dcc6e5-46f1-4578-8543-9af4f6a4f7de",
6 | "children": [
7 | "b0dd5a43-c44b-402e-b40f-a394287a9e3e"
8 | ],
9 | "filterType": "GMScript",
10 | "folderName": "scripts",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Scripts"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/e5b1e8fe-f417-43e8-b65f-8a518d723aea.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "e5b1e8fe-f417-43e8-b65f-8a518d723aea",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "e5b1e8fe-f417-43e8-b65f-8a518d723aea",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMPath",
10 | "folderName": "paths",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Paths"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/e5bc0382-83e6-4bfa-b68f-c702a7545129.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "e5bc0382-83e6-4bfa-b68f-c702a7545129",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "e5bc0382-83e6-4bfa-b68f-c702a7545129",
6 | "children": [
7 | "9a74872b-1d34-4b7c-8038-1116e4426c86"
8 | ],
9 | "filterType": "GMObject",
10 | "folderName": "objects",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Objects"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/f2ec9b0e-c3fe-4297-a78d-fa6f418fd827.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f2ec9b0e-c3fe-4297-a78d-fa6f418fd827",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "f2ec9b0e-c3fe-4297-a78d-fa6f418fd827",
6 | "children": [
7 | "7a21cc3d-d166-41e9-b51a-ecd396e706aa"
8 | ],
9 | "filterType": "GMFont",
10 | "folderName": "fonts",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Fonts"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/f664cd6f-a19b-470a-8b94-844b0367b313.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f664cd6f-a19b-470a-8b94-844b0367b313",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "f664cd6f-a19b-470a-8b94-844b0367b313",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMShader",
10 | "folderName": "shaders",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Shaders"
13 | }
--------------------------------------------------------------------------------
/interop_test_yy/views/f8edfe34-8789-4236-b7e4-741b59e181b8.yy:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f8edfe34-8789-4236-b7e4-741b59e181b8",
3 | "modelName": "GMFolder",
4 | "mvc": "1.1",
5 | "name": "f8edfe34-8789-4236-b7e4-741b59e181b8",
6 | "children": [
7 |
8 | ],
9 | "filterType": "GMNotes",
10 | "folderName": "notes",
11 | "isDefaultView": false,
12 | "localisedFolderName": "ResourceTree_Notes"
13 | }
--------------------------------------------------------------------------------
/src/CppGen.hx:
--------------------------------------------------------------------------------
1 | package ;
2 | import misc.GmlConstructor;
3 | import tools.GmkGen;
4 | import func.CppFunc;
5 | import func.CppFuncMangled;
6 | import haxe.io.Path;
7 | #if sys
8 | import sys.io.File;
9 | import sys.FileSystem;
10 | #end
11 | import struct.CppStruct;
12 | import tools.CppReader;
13 | import tools.CppBuf;
14 | using StringTools;
15 |
16 | /**
17 | * ...
18 | * @author YellowAfterlife
19 | */
20 | class CppGen {
21 | public static var config:CppConfig = new CppConfig();
22 |
23 | public static var outCppPath:String = null;
24 | public static var outGmlPath:String = null;
25 | public static var outGmlExtrasPath:String = null;
26 | public static var outGmkPath:String = null;
27 | public static var hasGmkPath(get, never):Bool;
28 | static function get_hasGmkPath(){
29 | return outGmkPath != null;
30 | }
31 |
32 | public static inline function procFile(path:String, cpp:String, indexStructs:Bool) {
33 | CppGenParser.procFile(path, cpp, indexStructs);
34 | }
35 |
36 | public static function warn(text:String) {
37 | #if js
38 | js.Browser.console.warn(text);
39 | #else
40 | Sys.println("GmlCppExtFuncs: warning #: " + text);
41 | #end
42 | }
43 |
44 | static function writeIfNotSame(path:String, text:String) {
45 | #if sys
46 | if (!FileSystem.exists(path)) {
47 | File.saveContent(path, text);
48 | } else {
49 | var curr = try {
50 | File.getContent(path);
51 | } catch (x:Dynamic) null;
52 | if (curr != text) File.saveContent(path, text);
53 | }
54 | #else
55 | trace(path);
56 | trace(text);
57 | #end
58 | }
59 |
60 | public static function finish() {
61 | var gml = new CppBuf();
62 | var cpp = new CppBuf();
63 |
64 | for (line in config.prepend) {
65 | cpp.addFormat("%s%|", line);
66 | }
67 | for (fn in CppFunc.list) if (fn.isMangled) {
68 | config.includes.insert(1, "gml_extm.h");
69 | break;
70 | }
71 | for (inc in config.includes) {
72 | cpp.addFormat('#include "%s"%|', inc);
73 | }
74 |
75 | if (outGmkPath != null) {
76 | cpp.addFormat("gmk_buffer %s;%|", GmkGen.argBuffer);
77 | }
78 |
79 | if (CppStruct.list.length > 0) {
80 | var prefix = false;
81 | for (struct in CppStruct.list) if (struct.shouldForwardDeclare) {
82 | var byval = CppType.useMap[struct.name];
83 | if (byval == null) continue;
84 | if (!prefix) {
85 | prefix = true;
86 | cpp.addFormat("// Struct forward declarations:%|");
87 | }
88 | cpp.addFormat("// from %s:%|", struct.origin);
89 | if (byval > 0) {
90 | cpp.addFormat("%s;%|", struct.impl);
91 | } else cpp.addFormat("struct %s;%|", struct.name);
92 | }
93 | }
94 |
95 | var fnCond = "";
96 | for (fn in func.CppFunc.list) {
97 | #if !sys
98 | trace(fn);
99 | #end
100 | if (fnCond != fn.condition) {
101 | if (fnCond != "") cpp.addFormat("#endif // %s%|%|", fnCond);
102 | fnCond = fn.condition;
103 | if (fnCond != "") cpp.addFormat("#if %s%|%|", fnCond);
104 | }
105 | fn.print(gml, cpp);
106 | }
107 | if (fnCond != "") cpp.addFormat("#endif // %s%|", fnCond);
108 |
109 | for (line in config.append) cpp.addFormat("%|%s", line);
110 |
111 | var gmlCode = gml.toString();
112 | var cppCode = cpp.toString();
113 | if (outGmkPath != null) {
114 | cppCode = tools.GmkGen.run(gmlCode, cppCode);
115 | }
116 | writeIfNotSame(outGmlPath, gmlCode);
117 | writeIfNotSame(outCppPath, cppCode);
118 | //
119 | var extras = new CppBuf();
120 | GmlConstructor.print(extras);
121 | if (extras.length == 0) {
122 | // OK!
123 | } else if (outGmlExtrasPath == null) {
124 | CppGen.warn('Constructors are used but no --gml-extras path is set');
125 | } else {
126 | writeIfNotSame(outGmlExtrasPath, extras.toString());
127 | }
128 | }
129 | #if sys
130 | public static function procArg(full:String, indexStructs:Bool) {
131 | var rel = Path.withoutDirectory(full);
132 | if (rel.indexOf("*") >= 0) {
133 | var rs = new EReg("([.*+?^${}()|[\\]\\/\\\\])", "g").replace(rel, "\\$1");
134 | rs = StringTools.replace(rs, "\\*", ".*?");
135 | var rx = try {
136 | new EReg("^" + rs + "$", "");
137 | } catch (x:Dynamic) {
138 | Sys.println("Couldn't make a regex for " + rel);
139 | return;
140 | }
141 | var dir = Path.normalize(Path.directory(full));
142 | var normCpp = Path.normalize(outCppPath);
143 | for (relx in FileSystem.readDirectory(dir)) {
144 | if (rx.match(relx)) {
145 | var fullx = dir + "/" + relx;
146 | if (fullx == normCpp) continue;
147 | procFile(fullx, File.getContent(fullx), indexStructs);
148 | }
149 | }
150 | } else procFile(full, File.getContent(full), indexStructs);
151 | }
152 | #end
153 | static function main() {
154 | #if sys
155 | var args = Sys.args();
156 | if (args.length == 0
157 | || args.length == 1 && (args[0] == "--help" || args[0] == "/?")
158 | ) {
159 | config.showHelp(false);
160 | return;
161 | }
162 | //Sys.println("cwd: " + Sys.getCwd());
163 | config.handleArgs(args);
164 | var trouble = null;
165 | if (args.length == 0) {
166 | trouble = "No paths provided!";
167 | } else if (outGmlPath == null) {
168 | trouble = "No output GML path provided!";
169 | } else if (outCppPath == null) {
170 | trouble = "No output C++ path provided!";
171 | }
172 | if (trouble != null) {
173 | Sys.println(trouble);
174 | Sys.stdin().readLine();
175 | return;
176 | }
177 | for (full in args) {
178 | procArg(full, true);
179 | }
180 | finish();
181 | #else
182 | var h = new haxe.Http("test.cpp?v=" + Date.now().getTime());
183 | h.onData = function(cpp) {
184 | procFile("test.cpp", cpp, true);
185 | finish();
186 | }
187 | h.request();
188 | #end
189 | }
190 | }
--------------------------------------------------------------------------------
/src/CppTypeHelper.hx:
--------------------------------------------------------------------------------
1 | package ;
2 | import proc.*;
3 | import proc.CppTypeProcSimple;
4 | import proc.CppTypeProcVector;
5 | import proc.CppTypeProcOptional;
6 |
7 | /**
8 | * ...
9 | * @author YellowAfterlife
10 | */
11 | class CppTypeHelper {
12 | public static var map:Map = (function() {
13 | inline function simple(name:String, docName:String, size:Int) {
14 | return new CppTypeProcSimple(name, docName, size);
15 | }
16 | var bool = simple("buffer_bool", "bool", 1);
17 | var s8 = new CppTypeProcSimpleChar("buffer_s8", "int", 1);
18 | var u8 = simple("buffer_u8", "int", 1);
19 | var s16 = simple("buffer_s16", "int", 2);
20 | var u16 = simple("buffer_u16", "int", 2);
21 | var s32 = simple("buffer_s32", "int", 4);
22 | var u32 = simple("buffer_u32", "int", 4);
23 | var s64 = simple("buffer_u64", "int", 8);
24 | var u64 = simple("buffer_u64", "int", 8);
25 | var f32 = simple("buffer_f32", "number", 4);
26 | var f64 = simple("buffer_f64", "number", 8);
27 | var str = new CppTypeProcString();
28 | var intPtr = new CppTypeProcSimpleIntPtr();
29 | var gmlPtr = new CppTypeProcGmlPointer(false);
30 | var gmlID = new CppTypeProcGmlPointer(true);
31 |
32 | return [
33 | // 1-byte:
34 | "bool" => (bool:CppTypeProc),
35 | "char" => s8, "unsigned char" => u8,
36 | "int8" => s8, "int8_t" => s8,
37 | "uint8" => u8, "uint8_t" => u8,
38 | // 2-byte:
39 | "short" => s16, "unsigned short" => u16,
40 | "int16" => s16, "int16_t" => s16,
41 | "uint16" => u16, "uint16_t" => u16,
42 | // 4-byte:
43 | "int" => s32, "unsigned int" => u32,
44 | "int32" => s32, "int32_t" => s32,
45 | "uint32" => u32, "uint32_t" => u32,
46 | "long" => s32, "unsigned long" => u32,
47 | // 8-byte:
48 | "long long" => s64,
49 | "int64" => s64, "int64_t" => s64,
50 | "uint64" => u64, "uint64_t" => u64,
51 | // floating-point:
52 | "float" => f32, "double" => f64,
53 | // pointerish:
54 | "intptr_t" => intPtr, "uintptr_t" => intPtr,
55 | // special cases:
56 | "char*" => str,
57 | "gml_ptr" => gmlPtr,
58 | "gml_ptr_destroy" => gmlPtr,
59 | "gml_id" => gmlID,
60 | "gml_id_destroy" => gmlID,
61 | "vector" => new CppTypeProcVector(),
62 | "tiny_array" => new CppTypeProcTinyArray(),
63 | "tiny_const_array" => new CppTypeProcTinyConstArray(),
64 | "tuple" => new CppTypeProcTuple(),
65 | "optional" => new CppTypeProcOptional(),
66 | "tiny_optional" => new CppTypeProcTinyOptional(),
67 | "gml_buffer" => new CppTypeProcGmlBuffer(),
68 | "GAME_HWND" => new CppTypeProcGameHwnd(),
69 | "gml_asset_index_of" => new CppTypeProcAssetIndexOf(),
70 | "gml_inout" => new CppTypeProcGmlInOut(),
71 | "gml_inout_vector" => new CppTypeProcGmlInOutVector(),
72 | ];
73 | })();
74 |
75 | public static function find(t:CppType):CppTypeProc {
76 | var tp = map[t.toKey()];
77 | if (tp != null) return tp;
78 | tp = map[t.name];
79 | if (tp != null) return tp;
80 | CppGen.warn('Couldn\'t find type ${t.toString()}'
81 | //+ haxe.CallStack.toString(haxe.CallStack.callStack())
82 | );
83 | return new CppTypeProcError(t.toString());
84 | }
85 | public static function isSugar(t:CppType):Bool {
86 | var p = find(t);
87 | return (p is CppTypeProcGmlPointer);
88 | }
89 | }
--------------------------------------------------------------------------------
/src/CppTypeMacroHelper.hx:
--------------------------------------------------------------------------------
1 | package ;
2 | import haxe.macro.Expr;
3 | import haxe.macro.Type;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppTypeMacroHelper {
10 | public static function fromComplexType(t:ComplexType):CppType {
11 | if (t == null) return null;
12 | var r:CppType;
13 | switch (t) {
14 | case TPath(p):
15 | if (p.pack.length == 0) {
16 | switch (p.name) {
17 | case "Int": return new CppType("int");
18 | case "Float": return new CppType("double");
19 | case "Void": return new CppType("void");
20 | case "String":
21 | r = new CppType("char");
22 | r.isConst = true;
23 | r.ptrCount = 1;
24 | return r;
25 | }
26 | }
27 | switch (p.name) {
28 | case "Int8": return new CppType("int8_t");
29 | case "Int16": return new CppType("int16_t");
30 | case "Int32": return new CppType("int32_t");
31 | case "Int64": return new CppType("int64_t");
32 | case "UInt8": return new CppType("uint8_t");
33 | case "UInt16": return new CppType("uint16_t");
34 | case "UInt32": return new CppType("uint32_t");
35 | case "UInt64": return new CppType("uint64_t");
36 | case "Pointer":
37 | r = switch (p.params[0]) {
38 | case TPType(_ct): fromComplexType(_ct);
39 | default: return null;
40 | }
41 | r.ptrCount++;
42 | return r;
43 | }
44 | default:
45 | }
46 | trace(t);
47 | return null;
48 | }
49 | }
--------------------------------------------------------------------------------
/src/GmlExtMacro.hx:
--------------------------------------------------------------------------------
1 | package ;
2 | import func.CppFunc;
3 | import func.CppFuncArg;
4 | import haxe.macro.Compiler;
5 | import haxe.macro.ComplexTypeTools;
6 | import haxe.macro.Context;
7 | import haxe.macro.Expr;
8 | import haxe.macro.Type;
9 | import sys.FileSystem;
10 | import sys.io.File;
11 | import tools.CppBuf;
12 |
13 | /**
14 | * ...
15 | * @author YellowAfterlife
16 | */
17 | class GmlExtMacro {
18 | static var isFirstClass:Bool = false;
19 | static var initFunc:String;
20 | static var gmlAutogen:CppBuf;
21 | static var cppAutogen:CppBuf;
22 | public static function build():Array {
23 | var localClass:ClassType = {
24 | var r_class = Context.getLocalClass();
25 | if (r_class == null) {
26 | Context.error("Should be applied to a class", Context.currentPos());
27 | return null;
28 | }
29 | r_class.get();
30 | }
31 |
32 | var cppAutogen = new CppBuf();
33 |
34 | var fields = Context.getBuildFields();
35 | for (field in fields) {
36 | if (field.meta == null) continue;
37 |
38 | var dllExport = field.meta.filter(m -> m.name == ":dllExport")[0];
39 | if (dllExport == null) continue;
40 |
41 | var mf = switch (field.kind) {
42 | case FFun(f): f;
43 | default:
44 | Context.error("@:dllExport should be applied to a function.", field.pos);
45 | continue;
46 | }
47 |
48 | var fname = field.name;
49 | var exportName = fname;
50 | if (dllExport.params != null) switch (dllExport.params[0]) {
51 | case null:
52 | case { expr: EConst(CString(_name)) }: exportName = _name;
53 | default:
54 | }
55 |
56 | var cf = new CppFunc(exportName);
57 | cf.cppFuncName = localClass.pack.concat([localClass.name + "_obj", fname]).join("::");
58 | cf.retType = CppTypeMacroHelper.fromComplexType(mf.ret);
59 | cf.generateFuncExtern = false;
60 | if (cf.retType == null) {
61 | Context.error("Couldn't convert return type for " + field.name
62 | + " (" + ComplexTypeTools.toString(mf.ret) + ")", field.pos);
63 | continue;
64 | }
65 | for (arg in mf.args) {
66 | var cargType = CppTypeMacroHelper.fromComplexType(arg.type);
67 | if (cargType == null) {
68 | Context.error("Couldn't convert type for " + field.name
69 | + " argument " + arg.name
70 | + " (" + ComplexTypeTools.toString(arg.type) + ")", field.pos);
71 | continue;
72 | }
73 | var carg = new CppFuncArg(cargType, arg.name);
74 | cf.args.push(carg);
75 | }
76 | cf.print(gmlAutogen, cppAutogen);
77 | }
78 |
79 | var cppFileCodeStr = cppAutogen.toString();
80 | if (isFirstClass) {
81 | isFirstClass = false;
82 | cppFileCodeStr = [
83 | 'extern "C" const char *hxRunLibrary();',
84 | 'extern "C" void hxcpp_set_top_of_stack();',
85 | 'dllx const char* $initFunc() {',
86 | '\t' + 'hxcpp_set_top_of_stack();',
87 | '\t' + 'const char* result = hxRunLibrary();',
88 | '\t' + 'return result ? result : "OK!";',
89 | '}',
90 | cppFileCodeStr
91 | ].join("\n");
92 | }
93 | GmlExtMacro.cppAutogen.add(cppFileCodeStr);
94 |
95 | cppFileCodeStr = '#include \n' + cppFileCodeStr;
96 | var cppFileCodeMeta = localClass.meta.extract(":cppFileCode")[0];
97 | if (cppFileCodeMeta != null) {
98 | if (cppFileCodeMeta.params != null) {
99 | switch (cppFileCodeMeta.params[0]) {
100 | case null:
101 | case { expr: EConst(CString(_code)) }:
102 | cppFileCodeStr = _code + "\n" + cppFileCodeStr;
103 | default:
104 | }
105 | }
106 | localClass.meta.remove(":cppFileCode");
107 | }
108 | localClass.meta.add(":cppFileCode", [macro $v{cppFileCodeStr}], localClass.pos);
109 |
110 | return fields;
111 | }
112 | public static function macroMain() {
113 | var outdir = Compiler.getOutput();
114 | var incdir = outdir + "/include";
115 | try {
116 | if (!FileSystem.exists(outdir)) FileSystem.createDirectory(outdir);
117 | if (!FileSystem.exists(incdir)) FileSystem.createDirectory(incdir);
118 | } catch (x:Dynamic) {
119 | trace("Error validating directories: ", x);
120 | }
121 | var gml_ext = Context.resolvePath("include/gml_ext.h");
122 | if (gml_ext != null) File.copy(gml_ext, incdir + "/gml_ext.h");
123 |
124 | var name = Context.definedValue("HAXE_OUTPUT_FILE");
125 | if (name == null) {
126 | name = Context.definedValue("autogen_main");
127 | if (name == null) name = "Main";
128 | }
129 | CppGen.config.helperPrefix = name;
130 |
131 | isFirstClass = true;
132 | initFunc = Context.definedValue("autogen_init");
133 | if (initFunc == null) {
134 | initFunc = name + "_init_raw";
135 | }
136 |
137 | gmlAutogen = new CppBuf();
138 | cppAutogen = new CppBuf();
139 | cppAutogen.add("#include \n");
140 | var gmlAutogenPath = Context.definedValue("autogen_gml");
141 | var cppAutogenPath = Context.definedValue("autogen_cpp");
142 | Context.onAfterGenerate(function() {
143 | File.saveContent(gmlAutogenPath, gmlAutogen.toString());
144 | File.saveContent(cppAutogenPath, cppAutogen.toString());
145 |
146 | if (Sys.systemName() == "Windows") {
147 | var dllPath = Compiler.getOutput() + "\\" + name;
148 | #if debug
149 | dllPath += "-debug";
150 | #end
151 | dllPath += ".dll";
152 |
153 | var projectDir = Sys.getCwd();
154 | projectDir = StringTools.replace(projectDir, "/", "\\");
155 |
156 | var arch = "x86";
157 | #if HXCPP_M64
158 | arch = "x64";
159 | #end
160 |
161 | var config = "Release";
162 | #if debug
163 | config = "Debug";
164 | #end
165 |
166 | Sys.command("cmd", [
167 | "/C", "postBuild.bat",
168 | dllPath,
169 | projectDir + "..\\",
170 | projectDir,
171 | arch,
172 | config,
173 | ]);
174 | }
175 | });
176 | //trace("hi!", autogenPath);
177 | }
178 | }
--------------------------------------------------------------------------------
/src/func/CppFuncArg.hx:
--------------------------------------------------------------------------------
1 | package func ;
2 |
3 | /**
4 | * ...
5 | * @author YellowAfterlife
6 | */
7 | class CppFuncArg {
8 | public var index:Int;
9 | public var type:CppType;
10 | public var name:String;
11 | /** default value (if omitted) **/
12 | public var value:String = null;
13 | /** like `double` or `const char*`. If it's null, it goes in the buffer **/
14 | public var exportType:String;
15 | /** but also we'll put things in the buffer if we're out of argument space **/
16 | public var putInBuffer = true;
17 | public var isSelf = false;
18 | public var gmlArgument:String = null;
19 | public var gmlUnpacked:String = null;
20 | public var gmlUnpackedPerVersion:Map = new Map();
21 | public static var current:CppFuncArg = null;
22 | public function new(index:Int, type:CppType, name:String) {
23 | this.index = index;
24 | this.type = type;
25 | this.name = name;
26 | }
27 | public function isOut() {
28 | return type.proc.isOut();
29 | }
30 | }
--------------------------------------------------------------------------------
/src/func/CppFuncGmlDoc.hx:
--------------------------------------------------------------------------------
1 | package func;
2 |
3 | import proc.CppTypeProc;
4 | import tools.CppBuf;
5 | using StringTools;
6 |
7 | class CppFuncGmlDoc {
8 | public static function print(fn:CppFunc, gml:CppBuf, hasReturn:Bool, retTypeProc:CppTypeProc, jsDoc:Bool) {
9 | var metaComment = fn.metaComment;
10 | if (metaComment != null && metaComment.startsWith("(")) {
11 | // function is preceded by `/// (...args)->`
12 | gml.addFormat("%|/// %s%s%|", fn.name, fn.metaComment);
13 | return;
14 | }
15 | if (!jsDoc) gml.addFormat("%|/// %s(", fn.name);
16 | var sep = false;
17 | for (arg in fn.args) {
18 | if (!arg.type.proc.useGmlArgument()) continue;
19 | if (jsDoc && !fn.gmlStatic && !sep) {
20 | // first arg is self
21 | sep = true;
22 | continue;
23 | }
24 | CppFuncArg.current = arg;
25 | if (!jsDoc) {
26 | if (sep) gml.add(", "); else sep = true;
27 | }
28 | //
29 | var argValue = arg.value;
30 | var isOpt = argValue == "{}";
31 | //
32 | if (jsDoc) {
33 | gml.addFormat("/// @param");
34 | if (arg.type != null) {
35 | var docType = arg.type.proc.getGmlDocTypeEx(arg.type);
36 | gml.addFormat(" {%s}", docType);
37 | }
38 | gml.addFormat(" %s%s", argValue != null ? "?" : "", arg.name);
39 | gml.addLine();
40 | } else {
41 | if (isOpt) {
42 | gml.addString("?");
43 | argValue = null;
44 | }
45 | gml.addFormat("%s", arg.name);
46 | if (arg.type != null) {
47 | var docType = arg.type.proc.getGmlDocTypeEx(arg.type);
48 | if (docType != null) gml.addFormat(":%s", docType);
49 | }
50 | if (argValue != null) gml.addFormat(" = %s", argValue.trim());
51 | }
52 | }
53 | if (jsDoc) {
54 | if (hasReturn && retTypeProc != null) {
55 | var docType = retTypeProc.getGmlDocTypeEx(fn.retType);
56 | if (docType != null) gml.addFormat("/// @returns {%s}%|", docType);
57 | }
58 | } else {
59 | gml.add(")");
60 | if (metaComment != null && metaComment.startsWith("->")) {
61 | gml.addFormat("%s%|", metaComment);
62 | return;
63 | }
64 | if (hasReturn && retTypeProc != null) {
65 | gml.add("->");
66 | var docType = retTypeProc.getGmlDocTypeEx(fn.retType);
67 | if (docType != null) gml.addString(docType);
68 | }
69 | if (metaComment != null) gml.addFormat(" %s", metaComment);
70 | gml.addLine();
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/src/func/CppFuncMangled.hx:
--------------------------------------------------------------------------------
1 | package func;
2 | import tools.CppBuf;
3 | using StringTools;
4 |
5 | /**
6 | * ...
7 | * @author
8 | */
9 | class CppFuncMangled {
10 | public static var isUsed = false;
11 | public static function print(fn:CppFunc, cpp:CppBuf) {
12 | isUsed = true;
13 | var retCppType = fn.retType.toCppType();
14 | var retVoid = retCppType == "void";
15 | fn.printExtern(cpp, retCppType, false);
16 | var config = CppGen.config;
17 |
18 | var argDoc:CppBuf = new CppBuf();
19 | var argDecl:CppBuf = new CppBuf(); argDecl.indent = cpp.indent + 1;
20 | var argCall:CppBuf = new CppBuf();
21 | var argi = 0;
22 | var hasResult = false, hasRest = false;
23 | var minArgs = -1;
24 | var sep = false;
25 | for (arg in fn.args) {
26 | var t = arg.type;
27 | if (retVoid && t.name == "YYResult" && ((t.ptrCount == 1) /*xor*/!= (t.isRef))) {
28 | hasResult = true;
29 | if (argCall.length > 0) argCall.addString(", ");
30 | if (t.isRef) {
31 | argCall.addString("result");
32 | } else argCall.addString("&result");
33 | continue;
34 | }
35 | if (t.name == "YYSelf" || t.name == "YYOther") {
36 | var isSelf = t.name == "YYSelf";
37 | if (argCall.length > 0) argCall.addString(", ");
38 | argCall.addString(isSelf ? "self" : "other");
39 | continue;
40 | }
41 |
42 | var isOpt = arg.value != null;
43 | if (argDoc.length > 0) argDoc.addString(", ");
44 | if (t.name == "YYRest") {
45 | hasRest = true;
46 | argDoc.addString("...");
47 | } else if (isOpt) argDoc.addString("?");
48 |
49 | argDoc.addString(arg.name);
50 | var varName = "_arg_" + arg.name;
51 | argDecl.addFormat("%s %s;", t.toCppType(), varName);
52 | if (isOpt) {
53 | if (minArgs < 0) minArgs = argi;
54 | argDecl.addFormat("%|if (argc > %d) {%+", argi);
55 | } else argDecl.addString(" ");
56 | argDecl.addFormat('__YYArg_%s("%s", %s, %d);',
57 | t.toCppMacroType(), arg.name, varName, argi);
58 | if (isOpt) {
59 | argDecl.addFormat("%-} else %s = %s;", varName, arg.value);
60 | }
61 | argDecl.addLine();
62 |
63 | if (argCall.length > 0) argCall.addString(", ");
64 | argCall.addString(varName);
65 |
66 | if (hasRest) break;
67 | argi += 1;
68 | }
69 |
70 | cpp.addFormat("/// %s(%b)%s\n", fn.name, argDoc, retVoid && !hasResult ? "" : "->");
71 | var cppName = config.cppNameMangled.replace("$", fn.name);
72 | cpp.addFormat("%s ", config.exportPrefixM);
73 | cpp.addFormat("void %s", cppName);
74 | cpp.addString("(RValue& result, CInstance* self, CInstance* other, int argc, RValue* arg)");
75 | cpp.addFormat(" {%+");
76 | cpp.addFormat('#define __YYFUNCNAME__ "%s"%|', fn.name);
77 | var maxArgs = argi;
78 | if (minArgs < 0) minArgs = maxArgs;
79 | if (hasRest && minArgs == 0) {
80 | cpp.addFormat("__YYArgCheck_any;");
81 | } else if (hasRest) {
82 | cpp.addFormat("__YYArgCheck_rest(%d);", minArgs);
83 | } else if (minArgs != maxArgs) {
84 | cpp.addFormat("__YYArgCheck_range(%d, %d);", minArgs, maxArgs);
85 | } else {
86 | cpp.addFormat("__YYArgCheck(%d);", minArgs);
87 | }
88 | cpp.addLine();
89 | cpp.addBuffer(argDecl);
90 | if (!retVoid) {
91 | cpp.addFormat("%s _result = ", retCppType);
92 | }
93 | cpp.addFormat("%s(%b);%|", fn.name, argCall);
94 | if (!retVoid) {
95 | cpp.addFormat("__YYResult_%s(%s);%|", fn.retType.toCppMacroType(), "_result");
96 | }
97 | cpp.addFormat('#undef __YYFUNCNAME__');
98 | cpp.addFormat("%-}%|%|");
99 | }
100 | }
--------------------------------------------------------------------------------
/src/func/CppFuncReader.hx:
--------------------------------------------------------------------------------
1 | package func;
2 | import tools.CppReader;
3 | using StringTools;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppFuncReader {
10 | public static function read(q:CppReader):CppFunc {
11 | var fnStart = q.pos;
12 | //
13 | var retType = CppType.read(q);
14 | var fnName = q.readSpIdent();
15 | q.skipSpaces();
16 | if (!q.skipIfEqu("(".code)) return null;
17 | //
18 | var fn = new CppFunc(fnName);
19 | fn.retType = retType;
20 | CppFunc.list.push(fn);
21 | //
22 | var readArg = true;
23 | var depth = 1;
24 | var args = [];
25 | while (q.loop) {
26 | var c = q.read();
27 | switch (c) {
28 | case "(".code: depth++;
29 | case ")".code: if (--depth <= 0) break;
30 | case ",".code if (depth == 1):
31 | readArg = true;
32 | case _ if (c.isIdent0()):
33 | var w = q.readIdent(true);
34 | if (readArg) {
35 | readArg = false;
36 | var argType = CppType.read(q, w);
37 | var argName = q.readSpIdent();
38 | if (argName == "") continue;
39 | var arg = new func.CppFuncArg(fn.args.length, argType, argName);
40 | fn.args.push(arg);
41 | q.skipSpaces();
42 | if (q.skipIfEqu("=".code)) {
43 | q.skipSpaces();
44 | var valStart = q.pos;
45 | var comma = false;
46 | while (q.loop) {
47 | c = q.read();
48 | switch (c) {
49 | case "(".code: depth++;
50 | case ")".code: if (--depth <= 1) break;
51 | case ",".code:
52 | if (depth <= 1) {
53 | comma = true;
54 | break;
55 | }
56 | }
57 | }
58 | arg.value = q.substring(valStart, q.pos - 1).ltrim();
59 | if (comma) q.back();
60 | if (depth <= 0) break;
61 | }
62 | }
63 | }
64 | }
65 | //
66 | var lineStart = q.str.lastIndexOf("\n", fnStart);
67 | if (lineStart >= 0) {
68 | var prevLineStart = q.str.lastIndexOf("\n", lineStart - 1);
69 | if (prevLineStart < 0) prevLineStart = 0;
70 | var prevLine = q.str.substring(prevLineStart, lineStart);
71 | var prevLineCmtStart = prevLine.lastIndexOf("///");
72 | if (prevLineCmtStart >= 0) {
73 | fn.metaComment = prevLine.substring(prevLineCmtStart + 3).trim();
74 | }
75 | }
76 | //
77 | return fn;
78 | }
79 | }
--------------------------------------------------------------------------------
/src/misc/GmlConstructor.hx:
--------------------------------------------------------------------------------
1 | package misc;
2 | import tools.CppBuf;
3 | using StringTools;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class GmlConstructor {
10 | public static var map:Map = new Map();
11 | public static var list:Array = [];
12 | //
13 | public var name:String;
14 | public var cppType:String = null;
15 | public var isID:Null = null;
16 | public var bufMethods:CppBuf = new CppBuf();
17 | public var bufStatics:CppBuf = new CppBuf();
18 | public var templateStart:String = null;
19 | public var templateEnd:String = null;
20 | public function new(name:String) {
21 | this.name = name;
22 | bufMethods.indent = 1;
23 | bufStatics.indent = 1;
24 | }
25 | public function setTemplate(tpl:String) {
26 | static var rxCode = ~/\$code\b/;
27 | if (templateStart != null) {
28 | CppGen.warn('Constructor $name already has a template!');
29 | }
30 | if (rxCode.match(tpl)) {
31 | templateStart = rxCode.matchedLeft().rtrim();
32 | templateEnd = rxCode.matchedRight();
33 | } else {
34 | templateStart = tpl;
35 | }
36 | }
37 | public static function find(name:String) {
38 | var ctr = map[name];
39 | if (ctr == null) {
40 | ctr = new GmlConstructor(name);
41 | list.push(ctr);
42 | map[name] = ctr;
43 | }
44 | return ctr;
45 | }
46 | public static function print(out:CppBuf) {
47 | if (list.length == 0) return;
48 | out.addFormat("// auto-generated!");
49 | for (ctr in list) {
50 | out.addFormat("%|%|");
51 | var param = ctr.isID ? "_id" : "_ptr";
52 | if (ctr.templateStart != null) {
53 | out.addString(ctr.templateStart);
54 | } else {
55 | out.addFormat("function %s(%s) constructor %{", ctr.name, param);
56 | out.addFormat("%|%s = %s;", ctr.isID ? "__id__" : "__ptr__", param);
57 | }
58 | out.addBuffer(ctr.bufStatics);
59 | out.addBuffer(ctr.bufMethods);
60 | if (ctr.templateEnd != null) {
61 | out.addString(ctr.templateEnd);
62 | } else {
63 | out.addFormat("%-}");
64 | }
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProc.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import tools.CppBuf;
3 |
4 | /**
5 | * ...
6 | * @author YellowAfterlife
7 | */
8 | class CppTypeProc {
9 | public function new() {
10 |
11 | }
12 |
13 | /**
14 | Should return a snip of GML code to read a value (that was written by C++) from `_buf`.
15 |
16 | GML code can be appended into `gml` if additional logic is necessary.
17 |
18 | When doing so, each line should be followed by a linebreak (or addFormat("...%|"))
19 |
20 | @param gml (code buffer)
21 | @param type Value type
22 | @param depth (for generating non-conflicting local variable names)
23 | @return GML code for use as a final value
24 | **/
25 | public function gmlRead(gml:CppBuf, type:CppType, depth:Int):String {
26 | throw "todo";
27 | }
28 |
29 | public function gmlReadOut(gml:CppBuf, type:CppType, depth:Int, out:String) {
30 | var val = gmlRead(gml, type, depth);
31 | gml.addFormat("%|%s = %s;", out, val);
32 | }
33 |
34 | /**
35 | * Should append GML code to write a value for use by C++ to `_buf`.
36 | * @param gml (code buffer)
37 | * @param type Value type
38 | * @param depth (for generating non-conflicting local variable names)
39 | * @param val Value as a GML expression string
40 | */
41 | public function gmlWrite(gml:CppBuf, type:CppType, depth:Int, val:String):Void {
42 | throw "todo";
43 | }
44 |
45 | /**
46 | If this is a struct/array with something that we're going to pass as-is,
47 | this should unpack the value and return it.
48 | **/
49 | public function gmlUnpack(gml:CppBuf, type:CppType, depth:Int, val:String):String {
50 | return val;
51 | }
52 |
53 | public function gmlCleanup(gml:CppBuf, type:CppType, depth:Int, val:String):Void {
54 |
55 | }
56 |
57 | /**
58 | * Should append C++ code to read a value written by GML from `_in`.
59 | * @param cpp (code buffer)
60 | * @param type Value type
61 | * @return C++ code to use as a final value
62 | */
63 | public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
64 | var ts = type.toCppType_mutable();
65 | return '_in.read<$ts>()';
66 | }
67 |
68 | /**
69 | * Should append C++ code to write a value for use by GML to `_out`.
70 | * @param cpp (code buffer)
71 | * @param type Value type
72 | * @param val Value as a C++ expression string
73 | */
74 | public function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String):Void {
75 | cpp.addFormat('%|_out.write<%s>(%s);', type.toCppType(), val);
76 | }
77 |
78 | /**
79 | * Should return the size of a value for the given type(+parameters).
80 | * This is used to ensure that a GML buffer is large enough for function arguments/return value
81 | * to be written to it without going out-of-bounds.
82 | *
83 | * Vectors are an exception from this behaviour due to their size depending on value.
84 | * @param type
85 | * @return
86 | */
87 | public function getSize(type:CppType):Int {
88 | return 8;
89 | }
90 |
91 | static function hasDynSize_seeker(t:CppType) {
92 | return t.proc.hasDynSize(t);
93 | }
94 | public function hasDynSize(type:CppType) {
95 | return seekRec(type, hasDynSize_seeker);
96 | }
97 |
98 | /**
99 | Can do `cpp.addFormat("%s += ...", result);` and return non-dynamic size for this type
100 | **/
101 | public function cppDynSize(cpp:CppBuf, type:CppType, prefix:String, val:String, result:String):Int {
102 | return getSize(type);
103 | }
104 |
105 | /**
106 | Should iterate sub-types, run fn() on them, and return whether
107 | **/
108 | public function seekRec(type:CppType, fn:(CppType) -> Bool):Bool {
109 | return false;
110 | }
111 |
112 | public function getGmlDocType(type:CppType):String {
113 | return null;
114 | }
115 | public function getGmlDocTypeEx(type:CppType):String {
116 | var t = CppType.docNames[type.docKey];
117 | if (t == null) t = CppType.docNames[type.docKeyFull];
118 | return t != null ? t : getGmlDocType(type);
119 | }
120 | public function toGmlJSDocType(type:CppType):String {
121 | var t = getGmlDocTypeEx(type);
122 | return switch (t) {
123 | case "int", "number": "real";
124 | default: t;
125 | }
126 | }
127 |
128 | /** Does this use structs? (and might need a conditional block) */
129 | public function usesStructs(type:CppType):Bool {
130 | return seekRec(type, usesStructs_seeker);
131 | }
132 | static function usesStructs_seeker(t:CppType) return t.proc.usesStructs(t);
133 |
134 | /** Does this use GM<=8.1 logic? (and might need another conditional block) */
135 | public function usesGmkSpec(type:CppType):Bool {
136 | return seekRec(type, usesGmkSpec_seeker);
137 | }
138 | static function usesGmkSpec_seeker(t:CppType) return t.proc.usesGmkSpec(t);
139 |
140 | public function isOut() {
141 | return false;
142 | }
143 |
144 | /** Some things (such as GameHwnd) are passed to C++, but are not passed to the GML wrapper **/
145 | public function useGmlArgument():Bool {
146 | return true;
147 | }
148 | public function keepGmlArgVar(type:CppType):Bool {
149 | return false;
150 | }
151 | public function isMap(type:CppType) {
152 | return false;
153 | }
154 | public function isList(type:CppType) {
155 | return false;
156 | }
157 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcAssetIndexOf.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import tools.CppBuf;
3 | import func.CppFuncArg;
4 | import proc.CppTypeProc;
5 |
6 | /**
7 | * Looks up an asset ID based on argument name
8 | * @author YellowAfterlife
9 | */
10 | class CppTypeProcAssetIndexOf extends CppTypeProc {
11 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
12 | var name = CppFuncArg.current.name;
13 | gml.addFormat('%|%bw;', "s32", 'asset_get_index("$name")');
14 | }
15 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
16 | var ts = type.toCppType();
17 | return '($ts)_in.read()';
18 | }
19 | override public function useGmlArgument():Bool {
20 | return false;
21 | }
22 | override public function getSize(type:CppType):Int {
23 | return 4;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcCond.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import CppConfig;
3 | import tools.CppBuf;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppTypeProcCond {
10 | public static function run(
11 | gml:CppBuf,
12 | func:Void->Void,
13 | useStructs:Void->Bool,
14 | useGmkSpec:Void->Bool,
15 | ) {
16 | var config = CppGen.config;
17 | var structMode = config.structMode;
18 | var structModeVal = config.structModeVal;
19 | var structModeCond = structMode != "auto";
20 | var gmkSpec = CppGen.hasGmkPath && useGmkSpec();
21 | var gmkBox = GmlBoxMode.BmGrid;
22 | inline function addElseGmk(elseif:Bool) {
23 | if (elseif) {
24 | gml.addFormat("%|//*/");
25 | gml.addFormat("%|/* GMS < 1:");
26 | } else gml.addFormat("%|/*/");
27 | }
28 | //
29 | function proc(ver:Int, sm:GmlStorageMode, bm:GmlBoxMode, vm:GmlVectorMode, gmk = false) {
30 | var _gmlVersion = config.gmlVersion;
31 | var _storageMode = config.storageMode;
32 | var _vectorMode = config.vectorMode;
33 | var _boxMode = config.boxMode;
34 | var _isGMK = config.isGMK;
35 | //
36 | config.gmlVersion = ver;
37 | config.storageMode = sm;
38 | config.vectorMode = vm;
39 | config.boxMode = bm;
40 | config.isGMK = gmk;
41 | //
42 | func();
43 | //
44 | config.gmlVersion = _gmlVersion;
45 | config.storageMode = _storageMode;
46 | config.vectorMode = _vectorMode;
47 | config.boxMode = _boxMode;
48 | config.isGMK = _isGMK;
49 | }
50 | inline function procGMS23() {
51 | proc(23, SmStruct, BmStruct, VmArray);
52 | }
53 | inline function procGMS1() {
54 | if (config.preferDS) {
55 | proc(14, SmMap, BmArray, VmList);
56 | } else {
57 | proc(14, SmArray, BmArray, VmArray);
58 | }
59 | }
60 |
61 | if (structModeVal != null) {
62 | // e.g. forced array mode for GMS 2.3
63 | if (gmkSpec) gml.addFormat("%|// GMS >= 1:");
64 |
65 | if (structModeVal) {
66 | procGMS23();
67 | } else procGMS1();
68 |
69 | if (gmkSpec) {
70 | addElseGmk(false);
71 | proc(8, structModeVal ? SmMap : SmList, gmkBox, VmList, true);
72 | gml.addFormat("%|//*/");
73 | }
74 | return;
75 | }
76 |
77 | if (!useStructs()) {
78 | // no structs, but don't get too excited
79 | if (gmkSpec) gml.addFormat("%|// GMS >= 1:");
80 | procGMS1();
81 | if (gmkSpec) {
82 | addElseGmk(false);
83 | proc(8, SmList, gmkBox, VmList, true);
84 | gml.addFormat("%|//*/");
85 | }
86 | return;
87 | }
88 |
89 | gml.addFormat("%|// GMS >= 2.3:");
90 | if (structModeCond) {
91 | gml.addFormat("%|if (%s) %{", structMode);
92 | }
93 |
94 | procGMS23();
95 |
96 | if (structModeCond) {
97 | gml.addFormat("%-} else //*/");
98 | gml.addFormat("%|%{");
99 | if (gmkSpec) {
100 | gml.addFormat("%|// GMS >= 1:");
101 | }
102 | } else if (!gmkSpec) {
103 | // >=2.3 / else
104 | gml.addFormat("%|/*/");
105 | } else {
106 | // >=2.3 / >=1 / gmk
107 | gml.addFormat("%|//*/");
108 | gml.addFormat("%|/* GMS >= 1 && GMS < 2.3:");
109 | }
110 |
111 | procGMS1();
112 |
113 | if (gmkSpec) {
114 | addElseGmk(true);
115 | if (structModeCond) {
116 | // a condition to select which of two workarounds you'd prefer?
117 | gml.addFormat("%|if (%s) %{", structMode);
118 | proc(8, SmMap, gmkBox, VmList, true);
119 | gml.addFormat("%-} else %{");
120 | proc(7, SmList, gmkBox, VmList, true); // so that it doesn't clash with above
121 | gml.addFormat("%-}");
122 | } else {
123 | // if you're going to have to free it anyway, might as well
124 | // make it something with readable keys, you know?
125 | proc(8, SmMap, gmkBox, VmList, true);
126 | }
127 | }
128 |
129 | if (structModeCond) {
130 | gml.addFormat("%-}");
131 | } else {
132 | gml.addFormat("%|//*/");
133 | }
134 | }
135 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcCustom.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 |
3 | import tools.CppBuf;
4 | using StringTools;
5 |
6 | class CppTypeProcCustom extends CppTypeProc {
7 | public var custom = new CppTypeProcCustomValues();
8 | public static var rxValue = ~/\$value\b/g;
9 | public static var rxDepth = ~/\$depth\b/g;
10 | public static var rxReturn = ~/^return\b\s*(.+?);?$/;
11 |
12 | static function patch(buf:CppBuf, snip:String, ?depth:Int, ?val:String) {
13 | if (snip == null) return null;
14 | if (val != null) snip = rxValue.replace(snip, val);
15 | if (depth != null) snip = rxDepth.replace(snip, "" + depth);
16 |
17 | if (buf != null) {
18 | var lines = snip.split("\n");
19 | var expr = lines.pop().trim();
20 | if (rxReturn.match(expr)) {
21 | expr = rxReturn.matched(1);
22 | }
23 | for (line in lines) buf.addFormat("%|%s", line);
24 | return expr;
25 | } else return snip;
26 | }
27 |
28 | override function gmlRead(gml:CppBuf, type:CppType, depth:Int):String {
29 | return patch(gml, custom.gmlRead, depth);
30 | }
31 | override function gmlWrite(gml:CppBuf, type:CppType, depth:Int, val:String) {
32 | if (custom.gmlWrite != null) {
33 | gml.addFormat("%|%s", patch(gml, custom.gmlWrite, depth, val));
34 | }
35 | }
36 | override function gmlCleanup(gml:CppBuf, type:CppType, depth:Int, val:String) {
37 | if (custom.gmlCleanup == null) return;
38 | gml.addFormat("%|%s", patch(gml, custom.gmlCleanup, depth, val));
39 | }
40 |
41 | override function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
42 | if (custom.cppRead != null) {
43 | return patch(cpp, custom.cppRead, null);
44 | } else {
45 | return super.cppRead(cpp, type, null);
46 | }
47 | }
48 | override function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String) {
49 | if (custom.cppWrite != null) {
50 | cpp.addFormat("%|%s", patch(cpp, custom.cppWrite, null, val));
51 | } else {
52 | super.cppWrite(cpp, type, null, val);
53 | }
54 | }
55 |
56 | override function getSize(type:CppType):Int {
57 | if (custom.size != null) return custom.size;
58 | return super.getSize(type);
59 | }
60 | override function hasDynSize(type:CppType):Bool {
61 | return custom.dynSize != null;
62 | }
63 | override function cppDynSize(cpp:CppBuf, type:CppType, prefix:String, val:String, result:String):Int {
64 | if (custom.dynSize != null) {
65 | cpp.addFormat("%|%s", patch(null, custom.dynSize, null, val));
66 | }
67 | return getSize(type);
68 | }
69 | override function usesStructs(type:CppType):Bool {
70 | return custom.usesStructs;
71 | }
72 |
73 | override function useGmlArgument():Bool {
74 | return custom.useGmlArgument;
75 | }
76 | override function keepGmlArgVar(type):Bool {
77 | return custom.keepGmlArgVar;
78 | }
79 |
80 | public static function parse(snip:String) {
81 | static var rxStart = ~/^(\w+)[ \t]*\n(\s*)([\s\S]+)/;
82 | //trace('"' + snip + '"');
83 | if (!rxStart.match(snip)) {
84 | CppGen.warn("@dllg:type should start with typename");
85 | return;
86 | }
87 | var typename = rxStart.matched(1);
88 | var indent = rxStart.matched(2);
89 | snip = rxStart.matched(3);
90 |
91 | static var rxMeta = ~/^\s*@(\w+)\s*(.+)?/;
92 | var tp = new CppTypeProcCustom();
93 | var tc = tp.custom;
94 | var metaName:String = null;
95 | var metaLines = [];
96 | function flush() {
97 | if (metaName == null) return;
98 | var metaText = metaLines.join("\n");
99 | switch (metaName.toLowerCase()) {
100 | case "gmlread": tc.gmlRead = metaText;
101 | case "gmlwrite": tc.gmlWrite = metaText;
102 | case "gmlcleanup": tc.gmlCleanup = metaText;
103 | case "cppread": tc.cppRead = metaText;
104 | case "cppwrite": tc.cppWrite = metaText;
105 | //
106 | case "size": tc.size = Std.parseInt(metaText);
107 | case "dynsize": tc.dynSize = metaText;
108 | //
109 | case "struct": tc.usesStructs = true;
110 | case "gmlargvar": tc.keepGmlArgVar = true;
111 | //
112 | default: CppGen.warn('Unknown meta @${metaName} in type ${typename}');
113 | }
114 | }
115 | for (line in snip.split("\n")) {
116 | if (line.startsWith(indent)) line = line.substr(indent.length);
117 |
118 | if (rxMeta.match(line)) {
119 | flush();
120 | metaName = rxMeta.matched(1);
121 | metaLines = [];
122 | var first = rxMeta.matched(2);
123 | if (first != null) metaLines.push(first);
124 | } else metaLines.push(line);
125 | }
126 | flush();
127 | CppType.typedefs.remove(typename);
128 | CppTypeHelper.map[typename] = tp;
129 | }
130 | }
131 | class CppTypeProcCustomValues {
132 | public var gmlRead:String = null;
133 | public var gmlWrite:String = null;
134 | public var gmlCleanup:String = null;
135 | //
136 | public var cppRead:String = null;
137 | public var cppWrite:String = null;
138 | //
139 | public var size:Null = null;
140 | public var dynSize:String = null;
141 | public var usesStructs = false;
142 | public var useGmlArgument = true;
143 | public var keepGmlArgVar = false;
144 | //
145 | public function new() {}
146 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcEnum.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 |
3 | import tools.CppBuf;
4 |
5 | class CppTypeProcEnum extends CppTypeProcSimple {
6 | public var ename:String;
7 | public var baseType = "int";
8 | public function new(ename:String) {
9 | this.ename = ename;
10 | super("buffer_s32", baseType, 4);
11 | }
12 | override function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
13 | return '($ename)_in.read<$baseType>()';
14 | }
15 | override function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String) {
16 | cpp.addFormat('%|_out.write<%s>(%s);', baseType, '($baseType)' + val);
17 | }
18 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcError.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import proc.CppTypeProc;
3 | import tools.CppBuf;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppTypeProcError extends CppTypeProc {
10 | private var name:String;
11 | public function new(name:String) {
12 | super();
13 | this.name = name;
14 | }
15 | override public function gmlRead(gml:CppBuf, type:CppType, z:Int):String {
16 | return 'show_error("Unsupported type $name", true)';
17 | }
18 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
19 | gml.addFormat('%|show_error("Unsupported type %s", true)', name);
20 | }
21 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
22 | return 'void/* Unsupported type $name */';
23 | }
24 | override public function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String):Void {
25 | cpp.addFormat("%|#error Unsupported type %s", name);
26 | }
27 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcGameHwnd.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import tools.CppBuf;
3 |
4 | /**
5 | * ...
6 | * @author YellowAfterlife
7 | */
8 | class CppTypeProcGameHwnd extends CppTypeProc {
9 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
10 | var x = CppGen.config.gmlWindowHandle;
11 | if (CppGen.config.isGMK) {
12 | gml.addFormat('%|%bw;', 'ptr', x);
13 | } else {
14 | gml.addFormat('%|%bw;', 'u64', 'int64($x)');
15 | }
16 | }
17 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
18 | var ts = type.toCppType();
19 | return '($ts)_in.read()';
20 | }
21 | override public function useGmlArgument():Bool {
22 | return false;
23 | }
24 | override public function getSize(type:CppType):Int {
25 | return 8;
26 | }
27 | override public function usesGmkSpec(type:CppType):Bool {
28 | return true;
29 | }
30 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcGmlBuffer.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import func.CppFuncArg;
3 | import tools.CppBuf;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppTypeProcGmlBuffer extends CppTypeProc {
10 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
11 | return '_in.read_gml_buffer()';
12 | }
13 | override public function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String):Void {
14 | cpp.addFormat("%|#error You may not return GML buffers at this time");
15 | }
16 |
17 | static var rxInOut:EReg = ~/^_*([iI]n_*)?([oO]ut)?[_A-Z]/i;
18 | function getArgUses() {
19 | var name = CppFuncArg.current.name;
20 | var _in = true, _out = false;
21 | if (rxInOut.match(name)) {
22 | _in = rxInOut.matched(1) != null;
23 | _out = rxInOut.matched(2) != null;
24 | if (_out == false) _in = true;
25 | }
26 | return { isInput: _in, isOutput: _out };
27 | }
28 |
29 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
30 | var v = '_val_$z';
31 | var wasm = CppGen.config.useWASM;
32 | var vwb = '_wb_$z';
33 | gml.addFormat("%|var %s = %s;", v, val);
34 | if (wasm) gml.addFormat("%|var %s;", vwb);
35 | gml.addFormat("%|if (buffer_exists(%s)) %{", v);
36 | if (wasm) {
37 | var pfx = CppGen.config.helperPrefix;
38 | var vlen = '_len_$z';
39 | gml.addFormat("%|if (%(s)_is_js) %{", pfx);
40 | gml.addFormat("%|var %s = buffer_get_size(%s);", vlen, v);
41 | gml.addFormat("%|%s = %(s)_wasm_alloc(%s", vwb, pfx, vlen);
42 | if (getArgUses().isInput) gml.addFormat(", buffer_get_address(%s)", v);
43 | gml.addString(");");
44 | gml.addFormat('%|%bw;', 'u64', vwb);
45 | gml.addFormat('%|%bw;', 's32', vlen);
46 | gml.addFormat('%|%bw;', 's32', 'buffer_tell($v)');
47 | gml.addFormat("%-} else %{");
48 | }
49 |
50 | // native:
51 | gml.addFormat('%|%bw;', 'u64', 'int64(buffer_get_address($v))');
52 | gml.addFormat('%|%bw;', 's32', 'buffer_get_size($v)');
53 | gml.addFormat('%|%bw;', 's32', 'buffer_tell($v)');
54 | if (wasm) gml.addFormat("%-}"); // closes if-js-else
55 |
56 | // no buffer:
57 | gml.addFormat("%-} else %{");
58 | if (wasm) gml.addFormat("%|%s = undefined;", vwb);
59 | gml.addFormat('%|%bw;', 'u64', '0');
60 | gml.addFormat('%|%bw;', 's32', '0');
61 | gml.addFormat('%|%bw;', 's32', '0');
62 | gml.addFormat("%-}");
63 | }
64 | override public function gmlCleanup(gml:CppBuf, type:CppType, z:Int, val:String):Void {
65 | if (CppGen.config.useWASM) {
66 | var pfx = CppGen.config.helperPrefix;
67 | // todo: this wouldn't work right for vector of buffers/etc.
68 | gml.addFormat("%|if (%(s)_is_js) ", pfx);
69 | gml.addFormat("%(s)_wasm_free(%s", pfx, '_wb_$z');
70 | if (getArgUses().isOutput) {
71 | var v = '_val_$z';
72 | gml.addFormat(", buffer_get_address(%s), buffer_get_size(%s)", v, v);
73 | }
74 | gml.addString(");");
75 | }
76 | }
77 | override public function gmlRead(gml:CppBuf, type:CppType, z:Int):String {
78 | return 'show_error("Unsupported type gml_buffer", true)';
79 | }
80 | override public function getGmlDocType(type:CppType):String {
81 | return "buffer";
82 | }
83 | override public function getSize(type:CppType):Int {
84 | return 16;
85 | }
86 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcGmlInOut.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 |
3 | import struct.CppStructIO;
4 | import struct.GmlStructIO;
5 | import tools.CppBuf;
6 |
7 | class CppTypeProcGmlInOut extends CppTypeProc {
8 | static function unpack(type:CppType) {
9 | var t = type.params[0];
10 | if (t == null) throw "gml_inout requires a type param";
11 | var sp:CppTypeProcStruct;
12 | sp = (t.proc is CppTypeProcStruct) ? cast t.proc : null;
13 | return {
14 | type: t,
15 | proc: t.proc,
16 | sp: sp,
17 | };
18 | }
19 | override function gmlRead(gml:CppBuf, type:CppType, depth:Int):String {
20 | return unpack(type).type.gmlRead(gml, depth);
21 | }
22 | override function gmlWrite(gml:CppBuf, type:CppType, depth:Int, val:String) {
23 | var p = unpack(type);
24 | var vp = (p.sp != null ? '_struct_' : '_box_') + depth;
25 | var isGMK = CppGen.config.isGMK;
26 | gml.addFormat("%|%vdp = %s;", vp, val);
27 | gml.addFormat("%|if (");
28 | if (p.sp == null) {
29 | if (isGMK) {
30 | gml.addFormat("!ds_list_empty(%s)", vp);
31 | } else {
32 | gml.addFormat("array_length_1d(%s)", vp);
33 | }
34 | } else switch (CppGen.config.storageMode) {
35 | case SmStruct: gml.addFormat('variable_struct_names_count(%s) != 0', vp);
36 | case SmArray: gml.addFormat('array_length_1d(%s) != 0', vp);
37 | case SmMap: gml.addFormat('!ds_map_empty(%s)', vp);
38 | case SmList: gml.addFormat('!ds_list_empty(%s)', vp);
39 | }
40 | gml.addFormat(") %{");
41 | gml.addFormat("%|buffer_write(_buf, buffer_bool, true);");
42 | if (p.sp == null) {
43 | var item = isGMK ? 'ds_list_find_value($vp)' : '$vp[0]';
44 | p.type.gmlWrite(gml, depth, item);
45 | } else {
46 | var struct = p.sp.struct;
47 | GmlStructIO.writeFields(struct, gml, depth, vp);
48 | }
49 | gml.addFormat("%-} else buffer_write(_buf, buffer_bool, false);");
50 | }
51 | override function cppRead(cpp:CppBuf, type:CppType, vp:String):String {
52 | var p = unpack(type);
53 | cpp.addFormat("%|%s %s;", p.type.toCppType_mutable(), vp);
54 | cpp.addFormat("%|if (_in.read()) %{");
55 | if (p.sp != null) {
56 | CppStructIO.readFields(p.sp.struct, cpp, vp);
57 | } else {
58 | cpp.addFormat("%|%s = %s;", vp, p.type.cppRead(cpp, vp + "_val"));
59 | }
60 | cpp.addFormat("%-} else %s = {};", vp);
61 | return vp;
62 | }
63 | override function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String) {
64 | unpack(type).type.cppWrite(cpp, prefix, val);
65 | }
66 | override function getSize(type:CppType):Int {
67 | var p = unpack(type);
68 | return 1 + p.type.getSize();
69 | }
70 | override function cppDynSize(cpp:CppBuf, type:CppType, prefix:String, val:String, result:String):Int {
71 | var p = unpack(type);
72 | return 1 + p.proc.cppDynSize(cpp, p.type, prefix, val, result);
73 | }
74 | override function gmlReadOut(gml:CppBuf, type:CppType, depth:Int, out:String) {
75 | var p = unpack(type);
76 | if (p.sp != null) {
77 | var vp = "_struct_" + depth;
78 | gml.addFormat("%|%vdp = %s;", vp, out);
79 | switch (CppGen.config.storageMode) {
80 | case SmStruct, SmArray: {}; // OK!
81 | case SmMap: gml.addFormat("%|ds_map_clear(%s);", vp);
82 | case SmList: gml.addFormat("%|ds_list_clear(%s);", vp);
83 | }
84 | GmlStructIO.readFields(p.sp.struct, gml, depth, vp, true);
85 | } else {
86 | var vp = "_box_" + depth;
87 | var vp_val = "_val_" + depth;
88 | gml.addFormat("%|%vdp = %s;", vp, out);
89 | gml.addFormat("%|var %s;", vp_val);
90 | p.type.gmlReadOut(gml, depth + 1, vp);
91 | var isGMK = CppGen.config.isGMK;
92 | if (isGMK) {
93 | gml.addFormat("%|if (ds_list_empty(%s)) %{", vp);
94 | gml.addFormat("%|ds_list_add(%s, %s);", vp, vp_val);
95 | gml.addFormat("%-} else %{");
96 | gml.addFormat("%|ds_list_replace(%s, 0, %s);", vp, vp_val);
97 | gml.addFormat("%-}");
98 | } else {
99 | gml.addFormat("%|%s[@0] = %s;", vp, vp_val);
100 | }
101 | }
102 | }
103 | override function isOut():Bool {
104 | return true;
105 | }
106 | override function seekRec(type:CppType, fn:CppType -> Bool):Bool {
107 | return fn(unpack(type).type);
108 | }
109 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcOptional.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import proc.CppTypeProcTuple;
3 | import tools.CppBuf;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppTypeProcOptional extends CppTypeProc {
10 | public static inline function unpack(type:CppType):CppType {
11 | return type.params[0];
12 | }
13 |
14 | public static inline var zeroString = "(0)";
15 | static function getDefValue_1(type:CppType, gmk:Bool){
16 | var tp = type.proc;
17 | var ds = CppGen.config.preferDS;
18 | if (tp is CppTypeProcOptional) {
19 | return getDefValue_1(unpack(type), gmk);
20 | }
21 | if ((tp is CppTypeProcStruct) || (tp is CppTypeProcVector)) {
22 | return gmk || ds ? "-1" : null;
23 | }
24 | if (tp is CppTypeProcGmlPointer) return gmk ? "-1" : null;
25 | if (tp is CppTypeProcString) return gmk ? zeroString : null;
26 | if (tp is CppTypeProcSimple) return gmk ? '""' : null;
27 | return gmk ? "chr(0)" : null;
28 | }
29 | public static function getDefValue(type:CppType, ?struct:Bool, ?gmk:Bool) {
30 | if (struct == null) struct = CppGen.config.boxMode == BmStruct;
31 |
32 | if (gmk == null) gmk = CppGen.config.isGMK;
33 | if (struct) return "undefined";
34 |
35 | var v = getDefValue_1(type, gmk);
36 | if (v == null) v = "undefined";
37 |
38 | return v;
39 | }
40 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
41 | var v = '_val_$z';
42 | var f = '_flag_$z';
43 | var t = unpack(type);
44 | var u = getDefValue(t);
45 | gml.addFormat("%|%vdp = %s;", v, val);
46 | gml.addFormat("%|%vdp = ", f);
47 | if (u == '""') {
48 | gml.addFormat("is_real(%s);", v);
49 | } else if (u == "0") {
50 | gml.addFormat("is_string(%s);", v);
51 | } else {
52 | gml.addFormat("%s != %s;", v, u);
53 | }
54 | gml.addFormat('%|%bw;', 'bool', f);
55 | gml.addFormat("%|if (%s) %{", f);
56 | t.proc.gmlWrite(gml, t, z + 1, v);
57 | gml.addFormat("%-}");
58 | }
59 | override public function gmlRead(gml:CppBuf, type:CppType, z:Int):String {
60 | var v = '_val_$z';
61 | gml.addFormat("%|var %s;", v);
62 | gml.addFormat("%|if (buffer_read(_buf, buffer_bool)) %{");
63 | var t = unpack(type);
64 | var val = t.proc.gmlRead(gml, t, z + 1);
65 | gml.addFormat("%|%s = %s;", v, val);
66 | var u = getDefValue(type);
67 | gml.addFormat("%-} else %s = %s;", v, u);
68 | return v;
69 | }
70 |
71 | override public function cppRead(cpp:CppBuf, type:CppType, vp:String):String {
72 | cpp.addFormat("%|%s %s;", type.toCppType(), vp);
73 | cpp.addFormat("%|if (_in.read()) %{");
74 | var ot = unpack(type);
75 | var val = ot.proc.cppRead(cpp, ot, vp + '_v');
76 | cpp.addFormat("%|%s = %s;", vp, val);
77 | cpp.addFormat("%-} else %s = {};", vp);
78 | return vp;
79 | }
80 | override public function cppWrite(cpp:CppBuf, type:CppType, vp:String, val:String):Void {
81 | cpp.addFormat('%|auto& %s = %s;', vp, val);
82 | cpp.addFormat('%|if (%s.has_value()) %{', vp);
83 | cpp.addFormat('%|_out.write(true);');
84 | var t = unpack(type);
85 | t.proc.cppWrite(cpp, t, vp + '_v', vp + '.value()');
86 | cpp.addFormat('%-} else _out.write(false);');
87 | }
88 |
89 | override public function getGmlDocType(type:CppType):String {
90 | var t = unpack(type);
91 | var s = t.proc.getGmlDocTypeEx(t);
92 | return s != null ? s + "?" : null;
93 | }
94 |
95 | override public function getSize(type:CppType):Int {
96 | return unpack(type).getSize() + 1;
97 | }
98 | override function cppDynSize(cpp:CppBuf, type:CppType, vp:String, val:String, out:String):Int {
99 | cpp.addFormat("%|auto& %s = %s;", vp, val);
100 | cpp.addFormat("%|if (%s.has_value()) %{", vp);
101 | var fixed = unpack(type).cppDynSize(cpp, vp + "_v", val + ".value()", out);
102 | if (fixed > 0) cpp.addFormat("%|%s += %d;", out, fixed);
103 | cpp.addFormat("%-}");
104 | return 1;
105 | }
106 | override function seekRec(type:CppType, fn:CppType -> Bool):Bool {
107 | var t = unpack(type);
108 | return t != null && fn(t);
109 | }
110 | override function usesGmkSpec(type:CppType):Bool {
111 | return true;
112 | }
113 | }
114 | class CppTypeProcTinyOptional extends CppTypeProcOptional {
115 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
116 | var ts = CppTypeProcOptional.unpack(type).toCppType();
117 | return '_in.read_tiny_optional<$ts>()';
118 | }
119 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcSimple.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import proc.CppTypeProc;
3 | import tools.CppBuf;
4 | using StringTools;
5 |
6 | /**
7 | * ...
8 | * @author YellowAfterlife
9 | */
10 | class CppTypeProcSimple extends CppTypeProc {
11 | public var bufType:String;
12 | public var shortBufType:String;
13 | public var docType:String;
14 | public var size:Int;
15 | public function new(bufType:String, docType:String, size:Int) {
16 | super();
17 | this.bufType = bufType;
18 | if (bufType.startsWith('buffer_')) {
19 | shortBufType = bufType.substring('buffer_'.length);
20 | } else throw 'Unexpected buffer type "$bufType"';
21 | this.docType = docType;
22 | this.size = size;
23 | }
24 | override public function gmlRead(gml:CppBuf, type:CppType, depth:Int):String {
25 | return 'buffer_read(_buf, $bufType)';
26 | }
27 | override public function gmlWrite(gml:CppBuf, type:CppType, depth:Int, val:String):Void {
28 | gml.addFormat('%|%bw;', shortBufType, val);
29 | }
30 | override public function getSize(type:CppType):Int {
31 | return size;
32 | }
33 | override public function getGmlDocType(type:CppType):String {
34 | // TODO: JSDoc types
35 | return docType;
36 | }
37 | }
38 | class CppTypeProcSimpleChar extends CppTypeProcSimple {
39 | override public function getGmlDocType(type:CppType):String {
40 | if (type.ptrCount == 1) return "string";
41 | return super.getGmlDocType(type);
42 | }
43 | }
44 | class CppTypeProcSimpleIntPtr extends CppTypeProcSimple {
45 | public function new(){
46 | super("buffer_u64", "int", 8);
47 | }
48 | override public function gmlRead(gml:CppBuf, type:CppType, depth:Int):String {
49 | if (CppGen.config.isGMK) {
50 | return 'buffer_read(_buf, buffer_s32)';
51 | } else return "ptr(" + super.gmlRead(gml, type, depth) + ")";
52 | }
53 | override public function gmlWrite(gml:CppBuf, type:CppType, depth:Int, val:String):Void {
54 | if (CppGen.config.isGMK) {
55 | gml.addFormat('%|%bw;', "s32", val);
56 | } else {
57 | super.gmlWrite(gml, type, depth, val);
58 | }
59 | }
60 | override public function usesGmkSpec(type:CppType):Bool {
61 | return true;
62 | }
63 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcString.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import tools.CppBuf;
3 |
4 | /**
5 | * ...
6 | * @author
7 | */
8 | class CppTypeProcString extends CppTypeProcSimple {
9 | public function new() {
10 | super("buffer_string", "string", 8);
11 | }
12 | override function hasDynSize(type:CppType):Bool {
13 | return true;
14 | }
15 | override function cppDynSize(cpp:CppBuf, type:CppType, prefix:String, val:String, result:String):Int {
16 | cpp.addFormat("%|%s += strlen(%s);", result, val);
17 | return 1;
18 | }
19 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
20 | return '_in.read_string()';
21 | }
22 | override public function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String):Void {
23 | cpp.addFormat('%|_out.write_string(%s);', val);
24 | }
25 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcStruct.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import haxe.ds.Vector;
3 | import proc.CppTypeProc;
4 | import struct.CppStruct;
5 | import struct.CppStructField;
6 | import struct.*;
7 | import tools.CppBuf;
8 |
9 | /**
10 | * ...
11 | * @author YellowAfterlife
12 | */
13 | class CppTypeProcStruct extends CppTypeProc {
14 | public var struct:CppStruct;
15 | public function new(struct:CppStruct) {
16 | super();
17 | this.struct = struct;
18 | }
19 | //
20 | override public function gmlRead(gml:CppBuf, type:CppType, z:Int):String {
21 | var structVar = "_struct_" + z;
22 | gml.addFormat("%|%vdp = ", structVar);
23 | GmlStructIO.createTail(struct, gml);
24 | GmlStructIO.readFields(struct, gml, z, structVar, false);
25 | return structVar;
26 | }
27 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
28 | var structVar = "_struct_" + z;
29 | gml.addFormat("%|%vdp = %s;", structVar, val);
30 | GmlStructIO.writeFields(struct, gml, z, structVar);
31 | }
32 | //
33 | override function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
34 | cpp.addFormat('%|%s %s;', type.toCppType_mutable(), prefix);
35 | CppStructIO.readFields(struct, cpp, prefix);
36 | return prefix;
37 | }
38 | override function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String) {
39 | cpp.addFormat('%|auto& %s = %s;', prefix, val);
40 | CppStructIO.writeFields(struct, cpp, prefix);
41 | }
42 | //
43 | override public function getSize(type:CppType):Int {
44 | var size = 0;
45 | for (fd in struct.fields) size += fd.getSize();
46 | return size;
47 | }
48 | override function cppDynSize(cpp:CppBuf, type:CppType, prefix:String, val:String, result:String):Int {
49 | var fixed = 0;
50 | var tmp = cpp.fork();
51 | for (fd in struct.fields) {
52 | // TODO: what if we have a `dynSizeType x[32]`
53 | fixed += fd.type.proc.cppDynSize(tmp, fd.type,
54 | prefix + '_f_' + fd.name,
55 | prefix + "." + fd.name,
56 | result
57 | ) * fd.getQuantity();
58 | }
59 | if (tmp.hasText) {
60 | cpp.addFormat("%|auto& %s = %s;", prefix, val);
61 | cpp.addBuffer(tmp);
62 | }
63 | return fixed;
64 | }
65 |
66 | override function seekRec(type:CppType, fn:CppType -> Bool):Bool {
67 | for (fd in struct.fields) {
68 | if (fn(fd.type)) return true;
69 | }
70 | return false;
71 | }
72 | override public function usesStructs(type:CppType):Bool {
73 | return true;
74 | }
75 | override public function usesGmkSpec(type:CppType):Bool {
76 | return true;
77 | }
78 | override function isMap(type:CppType):Bool {
79 | return CppGen.config.storageMode == SmMap;
80 | }
81 | override function isList(type:CppType):Bool {
82 | return CppGen.config.storageMode == SmList;
83 | }
84 | }
--------------------------------------------------------------------------------
/src/proc/CppTypeProcTuple.hx:
--------------------------------------------------------------------------------
1 | package proc;
2 | import tools.CppBuf;
3 |
4 | /**
5 | * ...
6 | * @author YellowAfterlife
7 | */
8 | class CppTypeProcTuple extends CppTypeProc {
9 | override public function gmlRead(gml:CppBuf, type:CppType, z:Int):String {
10 | var _tup = '_tup_$z';
11 | gml.addFormat("var %s = array_create(%d);%|", _tup, type.params.length);
12 | for (i => tupType in type.params) {
13 | var val = tupType.proc.gmlRead(gml, tupType, z + 1);
14 | gml.addFormat("%s[%d] = %s;%|", _tup, i, val);
15 | }
16 | return _tup;
17 | }
18 | override public function gmlWrite(gml:CppBuf, type:CppType, z:Int, val:String):Void {
19 | var _tup = '_tup_$z';
20 | gml.addFormat("%|var %s = %s;", _tup, val);
21 | for (i => tupType in type.params) {
22 | var val = _tup + "[" + i + "]";
23 | tupType.proc.gmlWrite(gml, tupType, z + 1, val);
24 | }
25 | }
26 |
27 | static inline function getPrefix(prefix:String, ind:Int) {
28 | return prefix + "_t" + ind;
29 | }
30 |
31 | override public function cppRead(cpp:CppBuf, type:CppType, prefix:String):String {
32 | cpp.addFormat("%|%s %s; %{", type.toCppType(), prefix);
33 | var vb = new CppBuf();
34 | for (i => tupType in type.params) {
35 | var tupVar = prefix + "_t" + i;
36 | cpp.addFormat("%|%s %s = %s;",
37 | tupType.toCppType(),
38 | tupVar,
39 | tupType.proc.cppRead(cpp, tupType, getPrefix(prefix, i))
40 | );
41 | if (i > 0) vb.add(", ");
42 | vb.add(tupVar);
43 | }
44 | cpp.addFormat("%|%s = { %b };", prefix, vb);
45 | cpp.addFormat("%-}");
46 | return prefix;
47 | }
48 | override public function cppWrite(cpp:CppBuf, type:CppType, prefix:String, val:String):Void {
49 | var v = prefix;
50 | //cpp.addFormat('%|%{');
51 | cpp.addFormat('%|auto& %s = %s;', v, val);
52 | for (i => t in type.params) {
53 | t.proc.cppWrite(cpp, t, getPrefix(prefix, i), 'std::get<$i>($v)');
54 | }
55 | //cpp.addFormat('%-}');
56 | }
57 |
58 | override function getSize(type:CppType):Int {
59 | var n = 0;
60 | for (t in type.params) n += t.getSize();
61 | return n;
62 | }
63 | override function hasDynSize(type:CppType):Bool {
64 | for (t in type.params) {
65 | if (t.hasDynSize()) return true;
66 | }
67 | return false;
68 | }
69 | override function cppDynSize(cpp:CppBuf, type:CppType, vp:String, val:String, result:String):Int {
70 | var n = 0;
71 | cpp.addFormat("%|auto& %s = %s;", vp, val);
72 | for (i => t in type.params) {
73 | n += t.cppDynSize(cpp, getPrefix(vp, i), 'std::get<$i>($vp)', result);
74 | }
75 | return n;
76 | }
77 |
78 | override function seekRec(type:CppType, fn:(CppType) -> Bool):Bool {
79 | for (t in type.params) if (fn(t)) return true;
80 | return false;
81 | }
82 |
83 | override public function usesStructs(type:CppType):Bool {
84 | for (t in type.params) if (t.proc.usesStructs(t)) return true;
85 | return false;
86 | }
87 | override public function usesGmkSpec(type:CppType):Bool {
88 | for (t in type.params) if (t.proc.usesGmkSpec(t)) return true;
89 | return false;
90 | }
91 | override function isList(type:CppType):Bool {
92 | return CppGen.config.isGMK;
93 | }
94 | }
--------------------------------------------------------------------------------
/src/struct/CppStruct.hx:
--------------------------------------------------------------------------------
1 | package struct ;
2 | import proc.CppTypeProcStruct;
3 | import tools.CppReader;
4 | using StringTools;
5 |
6 | /**
7 | * ...
8 | * @author YellowAfterlife
9 | */
10 | class CppStruct {
11 | public static var list:Array = [];
12 | public static var map:Map = new Map();
13 | public var name:String;
14 | public var parent:String;
15 | /** "file.cpp:line" */
16 | public var origin:String;
17 | public var fields:Array = [];
18 | public var proc:CppTypeProcStruct;
19 | /** C++ implementation */
20 | public var impl:String;
21 | /**
22 | Whether the struct body can/should be copied for forward declaration
23 | (read: it was defined in a source file instead of a header)
24 | **/
25 | public var shouldForwardDeclare:Bool = true;
26 | public function new(name:String) {
27 | this.name = name;
28 | proc = new CppTypeProcStruct(this);
29 | }
30 |
31 | public static function readStructField(q:tools.CppReader, struct:CppStruct, firstIdent:String) {
32 | var fdType = CppType.read(q, firstIdent);
33 | if (fdType == null) return;
34 | while (q.loop) {
35 | q.skipSpaces();
36 | var fdName = q.readIdent();
37 | if (fdName == "") break;
38 | q.skipSpaces();
39 | if (q.peek() == "(".code) break; // retType funcName()
40 | var fd = new CppStructField(fdType, fdName);
41 | while (q.skipIfEqu("[".code)) {
42 | q.skipSpaces();
43 | var n = Std.parseInt(q.readIdent());
44 | q.skipSpaces();
45 | q.skipIfEqu("]".code);
46 | q.skipSpaces();
47 | if (n == null) break;
48 | fd.size.push(n);
49 | }
50 | //
51 | struct.fields.push(fd);
52 | q.skipSpaces();
53 | if (q.skipIfEqu("=".code)) {
54 | q.skipSpaces();
55 | var depth = 0;
56 | while (q.loop) {
57 | var c = q.read();
58 | switch (c) {
59 | case '"'.code, "'".code: q.skipCString(c);
60 | case "/".code: {
61 | switch (q.peek()) {
62 | case "/".code: q.skipUntil("\n".code);
63 | case "*".code: q.pos++; q.skipUntilStr("*/");
64 | }
65 | }
66 | case "{".code, "(".code: depth++;
67 | case "}".code, ")".code: depth--;
68 | case ",".code if (depth == 0): q.back(); break;
69 | case ";".code if (depth == 0): q.back(); break;
70 | }
71 | }
72 | }
73 | //
74 | q.skipSpaces();
75 | switch (q.peek()) {
76 | case ",".code: q.skip();
77 | case ";".code: q.skip(); break;
78 | }
79 | }
80 | }
81 |
82 | public static function read(q:tools.CppReader, shouldForwardDeclare) {
83 | var structStart = q.pos - "struct".length;
84 | q.skipSpaces();
85 | var structName = q.readIdent();
86 | var struct = new CppStruct(structName);
87 | struct.shouldForwardDeclare = shouldForwardDeclare;
88 | struct.origin = q.name + ":" + q.getRow(structStart);
89 | @:privateAccess CppTypeHelper.map[structName] = struct.proc;
90 | list.push(struct);
91 | map[structName] = struct;
92 | q.skipSpaces();
93 | if (q.skipIfEqu(":".code)) {
94 | q.skipSpaces();
95 | struct.parent = q.readIdent();
96 | }
97 | var depth = 0;
98 | while (q.loop) {
99 | var c = q.read();
100 | switch (c) {
101 | case '"'.code, "'".code: q.skipCString(c);
102 | case "/".code: {
103 | switch (q.peek()) {
104 | case "/".code: q.skipUntil("\n".code);
105 | case "*".code: q.pos++; q.skipUntilStr("*/");
106 | }
107 | }
108 | case "{".code, "(".code: depth++;
109 | case "}".code, ")".code: if (--depth <= 0) break;
110 | case _ if (c.isIdent0() && depth == 1): {
111 | var w = q.readIdent(true);
112 | switch (w) {
113 | case "public", "private": {};
114 | case _ if (w == structName): {};
115 | default:
116 | readStructField(q, struct, w);
117 | }
118 | }
119 | default:
120 | }
121 | } // can continue
122 | struct.impl = q.substring(structStart, q.pos);
123 | //trace(q.name, structName, structStart, q.len, q.substring(0, structStart) + "<<" + struct.impl + ">>" + q.substring(q.pos, q.len));
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/struct/CppStructField.hx:
--------------------------------------------------------------------------------
1 | package struct ;
2 | import proc.CppTypeProc;
3 |
4 | /**
5 | * ...
6 | * @author YellowAfterlife
7 | */
8 | class CppStructField {
9 | public var type:CppType;
10 |
11 | public var name:String;
12 | public var size:Array = [];
13 |
14 | public function getSize() {
15 | var n = type.getSize();
16 | for (m in size) n *= m;
17 | return n;
18 | }
19 | public function getQuantity() {
20 | var n = 1;
21 | for (m in size) n *= m;
22 | return n;
23 | }
24 | public function new(type:CppType, name:String) {
25 | this.type = type;
26 | this.name = name;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/struct/CppStructIO.hx:
--------------------------------------------------------------------------------
1 | package struct;
2 |
3 | import proc.CppTypeProc;
4 | import tools.CppBuf;
5 |
6 | class CppStructIO {
7 | public static function readFields(struct:CppStruct, cpp:CppBuf, vp:String) {
8 | for (i => fd in struct.fields) {
9 | for (i => n in fd.size) {
10 | cpp.addFormat("%|for (auto %s = 0u; %0 < %d; %0++) %{", vp + '_i' + i, n);
11 | }
12 | var val = fd.type.proc.cppRead(cpp, fd.type, vp + '_f_' + fd.name);
13 | cpp.addFormat('%|%s.%s', vp, fd.name);
14 | for (i in 0 ... fd.size.length) {
15 | cpp.addFormat('[%s]', vp + '_i' + i);
16 | }
17 | cpp.addFormat(' = %s;', val);
18 | for (_ in 0 ... fd.size.length) {
19 | cpp.addFormat("%-}");
20 | }
21 | }
22 | }
23 | public static function writeFields(struct:CppStruct, cpp:CppBuf, vp:String) {
24 | for (i => fd in struct.fields) {
25 | for (i => n in fd.size) {
26 | cpp.addFormat("%|for (auto %s = 0u; %0 < %d; %0++) %{", vp + '_i' + i, n);
27 | }
28 | //
29 | var val = vp + "." + fd.name;
30 | for (i in 0 ... fd.size.length) {
31 | val += "[" + vp + '_i' + i + "]";
32 | }
33 | //
34 | fd.type.proc.cppWrite(cpp, fd.type, vp + '_f_' + fd.name, val);
35 | //
36 | for (_ in 0 ... fd.size.length) {
37 | cpp.addFormat("%-}");
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/struct/GmlStructIO.hx:
--------------------------------------------------------------------------------
1 | package struct;
2 |
3 | import proc.CppTypeProc;
4 | import tools.CppBuf;
5 |
6 | class GmlStructIO {
7 | public static function createTail(struct:CppStruct, gml:CppBuf) {
8 | switch (CppGen.config.storageMode) {
9 | case SmStruct:
10 | gml.addFormat("{}; // %s", struct.name);
11 | case SmArray:
12 | gml.addFormat("array_create(%d); // %s", struct.fields.length, struct.name);
13 | case SmMap:
14 | gml.addFormat("ds_map_create(); // %s", struct.name);
15 | case SmList:
16 | gml.addFormat("ds_list_create(); // %s", struct.name);
17 | }
18 | }
19 |
20 | public static function readFields(struct:CppStruct, gml:CppBuf, z:Int, structVar:String, isOut:Bool) {
21 | var mode = CppGen.config.storageMode;
22 | var useArrays = mode == SmStruct || mode == SmArray;
23 | var acc = isOut ? "@" : "";
24 |
25 | // this gets called recursively to handle reading fixed-size arrays like `type field[d1][d2]`
26 | function proc(gml:CppBuf, type:CppType, tp:CppTypeProc, z:Int, size:Array, size_ind:Int) {
27 | if (size_ind >= size.length) {
28 | return tp.gmlRead(gml, type, z + 1);
29 | }
30 | if (size_ind == size.length - 1 && type.name == "char") {
31 | // the last char[n] segment becomes a string
32 | var fn = CppGen.config.helperPrefix + "_read_chars";
33 | return '$fn(_buf, ${size[size_ind]})';
34 | }
35 | var _arr = '_arr_$z';
36 | var _ind = '_ind_$z';
37 | var _len = size[size_ind];
38 |
39 | // declaration:
40 | gml.addFormat("%|%vdp = ", _arr);
41 | if (useArrays) {
42 | gml.addFormat("array_create(%d);", _len);
43 | } else {
44 | gml.addFormat("ds_list_create();");
45 | }
46 |
47 | // array itself
48 | gml.addFormat('%|for (%vdb; %0 < %d; %0 += 1) %{', _ind, "0", _len);
49 | var val = proc(gml, type, tp, z + 1, size, size_ind + 1);
50 | if (useArrays) {
51 | gml.addFormat("%|%s[%s%s] = %s;", _arr, acc, _ind, val);
52 | } else {
53 | gml.addFormat("%|ds_list_add(%s, %s", _arr, val);
54 | if (type.proc.isMap(type)) {
55 | gml.addFormat("%|ds_list_mark_as_map(%s, %s);", _arr, _ind);
56 | } else if (type.proc.isMap(type)) {
57 | gml.addFormat("%|ds_list_mark_as_list(%s, %s);", _arr, _ind);
58 | }
59 | }
60 | gml.addFormat("%-}");
61 |
62 | return _arr;
63 | } // proc
64 |
65 | for (i => fd in struct.fields) {
66 | var tp = fd.type.proc;
67 | var val = proc(gml, fd.type, tp, z + 1, fd.size, 0);
68 | switch (mode) {
69 | case SmStruct:
70 | gml.addFormat("%|%s.%s = %s;", structVar, fd.name, val);
71 | case SmArray:
72 | gml.addFormat("%|%s[%s%d] = %s; // %s", structVar, acc, i, val, fd.name);
73 | case SmMap:
74 | if (tp.isMap(fd.type)) {
75 | gml.addFormat('%|ds_map_add_map(%s, "%s", %s);', structVar, fd.name, val);
76 | } else if (tp.isList(fd.type)) {
77 | gml.addFormat('%|ds_map_add_list(%s, "%s", %s);', structVar, fd.name, val);
78 | } else {
79 | gml.addFormat('%|ds_map_add(%s, "%s", %s);', structVar, fd.name, val);
80 | }
81 | case SmList:
82 | gml.addFormat('%|ds_list_add(%s, %s); // %s', structVar, val, fd.name);
83 | }
84 | }
85 | }
86 |
87 | public static function writeFields(struct:CppStruct, gml:CppBuf, z:Int, structVar:String) {
88 | var mode = CppGen.config.storageMode;
89 | var useArrays = mode == SmStruct || mode == SmArray;
90 |
91 | function proc(gml:CppBuf, type:CppType, tp:CppTypeProc, z:Int, size:Array, size_ind:Int, val:String) {
92 | if (size_ind >= size.length) {
93 | tp.gmlWrite(gml, type, z + 1, val);
94 | return;
95 | }
96 | if (size_ind == size.length - 1 && type.name == "char") {
97 | // same char[n] -> string conversion
98 | var fn = CppGen.config.helperPrefix + "_write_chars";
99 | gml.addFormat('%|%s(_buf, %s, %d)', fn, val, size[size_ind]);
100 | return;
101 | }
102 | var _arr = '_arr_$z';
103 | var _ind = '_ind_$z';
104 | var _len = size[size_ind];
105 | gml.addFormat("%|%vdp = %s;", _arr, val);
106 | gml.addFormat('%|for (%vdb; %0 < %d; %0 += 1) %{', _ind, 0, _len);
107 | var val = useArrays ? '$_arr[$_ind]' : 'ds_list_find_value($_arr, $_ind)';
108 | proc(gml, type, tp, z + 1, size, size_ind + 1, val);
109 | gml.addFormat("%-}");
110 | } // proc
111 |
112 | for (i => fd in struct.fields) {
113 | var note = false;
114 | var val = structVar;
115 | switch (mode) {
116 | case SmStruct:
117 | val += "." + fd.name;
118 | case SmArray:
119 | note = true;
120 | val += '[$i]';
121 | case SmMap:
122 | val = 'ds_map_find_value($val, "${fd.name}")';
123 | case SmList:
124 | note = true;
125 | val = 'ds_list_find_value($val, ${i})';
126 | }
127 |
128 | proc(gml, fd.type, fd.type.proc, z + 1, fd.size, 0, val);
129 | if (note) gml.addFormat(" // %s", fd.name);
130 | }
131 | }
132 | }
--------------------------------------------------------------------------------
/src/tools/CharCode.hx:
--------------------------------------------------------------------------------
1 | package tools;
2 |
3 | /**
4 | * ...
5 | * @author YellowAfterlife
6 | */
7 | abstract CharCode(Int) from Int to Int {
8 | public function isSpace():Bool {
9 | var c = this;
10 | return c == " ".code || c == "\t".code || c == "\r".code || c == "\n".code;
11 | }
12 | public function isLineSpace():Bool {
13 | var c = this;
14 | return c == " ".code || c == "\t".code;
15 | }
16 | public function isIdent0():Bool {
17 | var c = this;
18 | return (c == "_".code
19 | || c >= "a".code && c <= "z".code
20 | || c >= "A".code && c <= "Z".code
21 | );
22 | }
23 | public function isIdent1():Bool {
24 | var c = this;
25 | return (c == "_".code
26 | || c >= "a".code && c <= "z".code
27 | || c >= "A".code && c <= "Z".code
28 | || c >= "0".code && c <= "9".code
29 | );
30 | }
31 | public function isDigit():Bool {
32 | var c = this;
33 | return (c >= "0".code && c <= "9".code);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/tools/CppReader.hx:
--------------------------------------------------------------------------------
1 | package tools ;
2 | import tools.CharCode;
3 | using StringTools;
4 |
5 | /**
6 | * ...
7 | * @author YellowAfterlife
8 | */
9 | class CppReader {
10 | public var name:String;
11 | public var str:String;
12 | public var pos:Int = 0;
13 | public var len:Int;
14 | public function new(s:String, name:String) {
15 | this.name = name;
16 | str = s;
17 | len = s.length;
18 | }
19 |
20 | public var loop(get, never):Bool;
21 | private inline function get_loop():Bool {
22 | return pos < len;
23 | }
24 |
25 | public function read():tools.CharCode {
26 | return str.unsafeCodeAt(pos++);
27 | }
28 |
29 | public inline function peek():tools.CharCode {
30 | return str.unsafeCodeAt(pos);
31 | }
32 | public inline function peekAt(ofs:Int):tools.CharCode {
33 | return str.unsafeCodeAt(pos + ofs);
34 | }
35 |
36 | public function peekn(n:Int):String {
37 | return str.substr(pos, n);
38 | }
39 | public function peeknAt(ofs:Int, n:Int):String {
40 | return str.substr(pos + ofs, n);
41 | }
42 |
43 | public function substr(pos:Int, len:Int):String {
44 | return str.substr(pos, len);
45 | }
46 |
47 | public function substring(start:Int, end:Int):String {
48 | return str.substring(start, end);
49 | }
50 |
51 | public inline function skip(n:Int = 1):Void {
52 | pos += n;
53 | }
54 | public inline function back(n:Int = 1):Void {
55 | pos -= n;
56 | }
57 |
58 | public function skipIfEqu(c:tools.CharCode):Bool {
59 | if (peek() == c) {
60 | skip(1);
61 | return true;
62 | } else return false;
63 | }
64 |
65 | public function readIdent(?pastFirst:Bool):String {
66 | var start = pastFirst ? pos - 1 : pos;
67 | while (loop) {
68 | var c = peek();
69 | if (c.isIdent1()) pos++; else break;
70 | }
71 | return substring(start, pos);
72 | }
73 |
74 | public function readSpIdent():String {
75 | inline this.skipSpaces();
76 | return inline this.readIdent();
77 | }
78 |
79 | public function readLspIdent():String {
80 | inline this.skipLineSpaces();
81 | return inline this.readIdent();
82 | }
83 |
84 | public function readLine():String {
85 | var start = pos;
86 | while (loop) {
87 | var c = peek();
88 | if (c == "\n".code) {
89 | return substring(start, pos++);
90 | } else skip();
91 | }
92 | return substring(start, pos);
93 | }
94 |
95 | public function readLineNonSpace():String {
96 | var start = pos;
97 | while (loop) {
98 | var c = peek();
99 | if (c == "\n".code) break;
100 | if (!c.isLineSpace()) skip(); else break;
101 | }
102 | return substring(start, pos);
103 | }
104 |
105 | public function skipUntil(c:tools.CharCode) {
106 | while (loop) {
107 | if (read() == c) break;
108 | }
109 | }
110 |
111 | public function skipSpaces() {
112 | while (loop) {
113 | var c = peek();
114 | if (c.isSpace()) skip(); else break;
115 | }
116 | }
117 |
118 | public function skipLineSpaces() {
119 | while (loop) {
120 | var c = peek();
121 | if (c.isLineSpace()) skip(); else break;
122 | }
123 | }
124 |
125 | public function skipUntilStr(s:String):Bool {
126 | var n = s.length;
127 | while (loop) {
128 | if (substr(pos, n) == s) {
129 | pos += n;
130 | return true;
131 | } else pos++;
132 | }
133 | return false;
134 | }
135 |
136 | public function skipCString(c1:tools.CharCode) {
137 | while (loop) {
138 | var c = read();
139 | if (c == c1) break;
140 | if (c == "\\".code) {
141 | pos++;
142 | }
143 | }
144 | }
145 |
146 | public function getRow(pos:Int):Int {
147 | var row = 0;
148 | while (pos > 0) {
149 | row += 1;
150 | pos = str.lastIndexOf("\n", pos - 1);
151 | }
152 | return row;
153 | }
154 | }
--------------------------------------------------------------------------------