Skip to content

Commit

Permalink
A few tweaks: arguments for snippet_execute_string, added snippet_cal…
Browse files Browse the repository at this point in the history
…l_ext, fixed key event name parsing, now works when working directory != program directory
  • Loading branch information
YellowAfterlife committed Jun 23, 2024
1 parent 74119ea commit cc57403
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 26 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ The DLL does code preprocessing and other operations that were deemed too slow t
The scripts use `object_event_add` + `event_perform_object` to store and call the final code without parsing penalties that would occur with `execute_string`.

## Intended use cases
<center>
<p align="center">

![shrug](./misc/shrug.png)\
~~What use cases?~~

</center>
</p>

You could use it for dynamic content loading if you are making a game in GM8.1.

Expand All @@ -52,8 +52,6 @@ If you compile a [GMEdit](https://github.com/YellowAfterlife/GMEdit/) version fr
- Wildcard support in listfiles?\
(`folder/*.gml`)
- Arguments for `snippet_execute_string`?\
(needs an "argument count waterfall")
## Meta
Expand Down
11 changes: 10 additions & 1 deletion docs/index.dmd
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The extension can be found
```
and a `snippet_function_add` for each script in the project.
}
#[snippet_execute_string(gml_code)->]() {
#[snippet_execute_string(gml_code, ...arguments)->]() {
Like regular `execute_string`, but uses the snippet preprocessor
(e.g. can call snippets using `func()`).
}
Expand Down Expand Up @@ -115,6 +115,11 @@ The extension can be found
#[snippet_call(name, ...arguments)->]() {
Calls a snippet with the given name and returns the result, not unlike `script_execute`.
}
#[snippet_call_ext(name, argument_list, offset=0, ?count)->]() {
Like [snippet_call], but takes arguments from a ds_list instead.

If `count` is not specified, it's assumed to be `ds_list_size(argument_list) - offset`.
}
}
#[Objects](objects) {
#[snippet_define_object(name, gml_code)->]() {
Expand Down Expand Up @@ -295,6 +300,10 @@ The extension can be found
}
#[Other stuff](other) {
File functions:
#[sniptools_file_exists(path)->]() {
Returns whether the extension/C++ thinks that the file exists,
which doesn't necessarily match with when GameMaker thinks that a file exists.
}
#[sniptools_file_get_contents(path)->]() {
Returns the contents of a file as a string (`""` if a file is missing).
}
Expand Down
11 changes: 9 additions & 2 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@
<a class="sf" href="#snippet_parse_event_file">snippet_parse_event_file</a><span class="op">(</span><span class="st">"events.gml"</span><span class="op">)</span><span class="op">;</span>
</pre><p>
and a <code>snippet_function_add</code> for each script in the project.
</p></article></section><section><header id="snippet_execute_string"><a href="#snippet_execute_string" title="(permalink)">snippet_execute_string(gml_code)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
</p></article></section><section><header id="snippet_execute_string"><a href="#snippet_execute_string" title="(permalink)">snippet_execute_string(gml_code, ...arguments)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Like regular <code>execute_string</code>, but uses the snippet preprocessor
(e.g. can call snippets using <code>func()</code>).
</p></article></section></article></section><section><header id="snippets"><a href="#snippets" title="(permalink)">Snippets</a></header><article><a class="sticky-side" href="#snippets" title="Snippets"><span>Snippets</span></a><section><header id="snippet_define"><a href="#snippet_define" title="(permalink)">snippet_define(name, gml_code)</a></header><article><p>
Expand Down Expand Up @@ -515,6 +515,10 @@
Calls:
</p><section><header id="snippet_call"><a href="#snippet_call" title="(permalink)">snippet_call(name, ...arguments)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Calls a snippet with the given name and returns the result, not unlike <code>script_execute</code>.
</p></article></section><section><header id="snippet_call_ext"><a href="#snippet_call_ext" title="(permalink)">snippet_call_ext(name, argument_list, offset=0, ?count)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Like <a href="#snippet_call">snippet_call</a>, but takes arguments from a ds_list instead.
</p><p>
If <code>count</code> is not specified, it's assumed to be <code>ds_list_size(argument_list) - offset</code>.
</p></article></section></article></section><section><header id="objects"><a href="#objects" title="(permalink)">Objects</a></header><article><a class="sticky-side" href="#objects" title="Objects"><span>Objects</span></a><section><header id="snippet_define_object"><a href="#snippet_define_object" title="(permalink)">snippet_define_object(name, gml_code)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Creates/overwrites an object.
</p><p>
Expand Down Expand Up @@ -662,7 +666,10 @@
Calls to it in subsequently compiled snippet will be the <a href="#preproc.call">preprocessor</a>.
</p></article></section></article></section><section><header id="other"><a href="#other" title="(permalink)">Other stuff</a></header><article><a class="sticky-side" href="#other" title="Other stuff"><span>Other stuff</span></a><p>
File functions:
</p><section><header id="sniptools_file_get_contents"><a href="#sniptools_file_get_contents" title="(permalink)">sniptools_file_get_contents(path)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
</p><section><header id="sniptools_file_exists"><a href="#sniptools_file_exists" title="(permalink)">sniptools_file_exists(path)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Returns whether the extension/C++ thinks that the file exists,
which doesn't necessarily match with when GameMaker thinks that a file exists.
</p></article></section><section><header id="sniptools_file_get_contents"><a href="#sniptools_file_get_contents" title="(permalink)">sniptools_file_get_contents(path)&#8203;<span class="ret-arrow">&#10140;</span></a></header><article><p>
Returns the contents of a file as a string (<code>""</code> if a file is missing).
</p></article></section><p>
String functions:
Expand Down
2 changes: 1 addition & 1 deletion snippets/named_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ dllx double snippet_event_get_number(const char* name) {
case gml_event_type_arg::key: {
auto key = str.substr(pos + 1);
auto kp = gml_keycodes.find(key);
if (kp != gml_keycodes.end()) kp->second;
if (kp != gml_keycodes.end()) return kp->second;

int numb = 0;
if (std::sscanf(key.c_str(), "%d", &numb)) {
Expand Down
Binary file modified snippets/snippets.aps
Binary file not shown.
5 changes: 5 additions & 0 deletions snippets/sniptools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
#include <queue>
#include "CharTools.h"

///
dllx double sniptools_file_exists(const char* path) {
std::ifstream fs(path);
return fs.good();
}
///
dllx const char* sniptools_file_get_contents(const char* path) {
std::ifstream fs(path);
Expand Down
154 changes: 144 additions & 10 deletions snippets_gml/snippets.gml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#define snippet_init_dll
/// snippet_init_dll()
/// snippet_init_dll(?path_prefix)
var _path, _dir;
if (argument_count > 0) {
_dir = argument[0];
} else _dir = "";

_dir = "";
_path = _dir + "snippets.dll";
global.f_snippet_event_get_type = external_define(_path, "snippet_event_get_type", dll_cdecl, ty_real, 1, ty_string);
global.f_snippet_event_get_number = external_define(_path, "snippet_event_get_number", dll_cdecl, ty_real, 1, ty_string);
Expand All @@ -14,6 +16,7 @@ global.f_snippet_function_add = external_define(_path, "snippet_function_add", d
global.f_snippet_function_remove = external_define(_path, "snippet_function_remove", dll_cdecl, ty_real, 1, ty_string);
global.f_snippet_parse_api_entry = external_define(_path, "snippet_parse_api_entry", dll_cdecl, ty_real, 1, ty_string);
global.f_snippet_parse_api_file = external_define(_path, "snippet_parse_api_file", dll_cdecl, ty_real, 1, ty_string);
global.f_sniptools_file_exists = external_define(_path, "sniptools_file_exists", dll_cdecl, ty_real, 1, ty_string);
global.f_sniptools_file_get_contents = external_define(_path, "sniptools_file_get_contents", dll_cdecl, ty_string, 1, ty_string);
global.f_sniptools_string_trim = external_define(_path, "sniptools_string_trim", dll_cdecl, ty_string, 1, ty_string);
global.f_sniptools_string_trim_start = external_define(_path, "sniptools_string_trim_start", dll_cdecl, ty_string, 1, ty_string);
Expand All @@ -28,7 +31,14 @@ global.f_snippet_preproc_concat_names = external_define(_path, "snippet_preproc_


#define snippet_init
/// ()
/// (?path_prefix)
var _dir, _dir_auto;
_dir_auto = argument_count == 0;
if (_dir_auto) {
_dir = "";
} else {
_dir = argument[0];
}
snippet_init_dll();
var i; i = 0;
global.__snippet__argument[0] = 0;
Expand All @@ -52,8 +62,15 @@ for (i = 0; i < global.__snippet__blank_object; i += 1) if (object_exists(i)) {
// contains things like "create\nstep" in case we need to delete events later
global.__snippet__object_events = ds_map_create();

snippet_parse_api_file("fnames");
snippet_parse_event_file("events.gml");
if (_dir == "" || filename_drive(_dir) == "") { // relative path?
if (sniptools_file_exists(program_directory + _dir + "\fnames")) {
_dir = program_directory + _dir + "\";
} else if (sniptools_file_exists(working_directory + _dir + "\fnames")) {
_dir = working_directory + _dir + "\";
}
}
snippet_parse_api_file(_dir + "fnames");
snippet_parse_event_file(_dir + "events.gml");
// collect scripts:
var _max_gap; _max_gap = 1024;
Expand All @@ -77,14 +94,58 @@ while (_gap < _max_gap || !_seen_snippet_init) {
);*/
#define snippet_execute_string
/// (gml_code)
var n; n = external_call(global.f_snippet_preproc_run, "", argument0, "define");
/// (gml_code, ...arguments)
var n; n = external_call(global.f_snippet_preproc_run, "", argument[0], "define");
// NB! Store-restore mirrors across snippet_execute_string, snippet_call, snippet_call_ext
// store old arguments:
var _old_argc; _old_argc = global.__snippet__argument_count;
var _old_args; _old_args = global.__snippet__argument;
var i; i = 1;
repeat (_old_argc - 1) {
_old_args[i] = global.__snippet__argument[i];
i += 1;
}
// copy new arguments:
var _argc; _argc = argument_count - 1;
global.__snippet__argument_count = _argc;
i = 0;
repeat (_argc) {
global.__snippet__argument[i] = argument[i + 1];
i += 1;
}
// clear "extra" arguments:
repeat (_old_argc - _argc) {
global.__snippet__argument[i] = 0;
i += 1;
}
// run the snippet(s):
var _result; _result = 0;
repeat (n) {
var _name; _name = external_call(global.f_snippet_preproc_pop_name);
var _code; _code = external_call(global.f_snippet_preproc_pop_code);
_result = execute_string(_code);
global.__snippet__result = 0;
execute_string(_code);
_result = global.__snippet__result;
}
// restore previous arguments:
global.__snippet__argument_count = _old_argc;
i = 0;
repeat (_old_argc) {
global.__snippet__argument[i] = _old_args[i];
i += 1;
}
// clear the extra arguments (the other way around!):
repeat (_argc - _old_argc) {
global.__snippet__argument[i] = 0;
i += 1;
}
return _result;
#define snippet_define
Expand Down Expand Up @@ -142,9 +203,10 @@ if (ds_map_exists(global.__snippet__code_map, argument0)) {
} else return "";
#define snippet_call
/// (name, ...args)
var _name; _name = argument0;
/// (name, ...arguments)
var _name; _name = argument[0];
// NB! Store-restore mirrors across snippet_execute_string, snippet_call, snippet_call_ext
// store old arguments:
var _old_argc; _old_argc = global.__snippet__argument_count;
var _old_args; _old_args = global.__snippet__argument;
Expand All @@ -170,6 +232,74 @@ repeat (_old_argc - _argc) {
}
if (ds_map_exists(global.__snippet__map, _name)) {
global.__snippet__result = 0;
// one snippet per event:
var _enumb; _enumb = ds_map_find_value(global.__snippet__map, _name);
event_perform_object(obj_snippets, ev_alarm, _enumb);
//*/
/* one snippet per object:
var _obj; _obj = ds_map_find_value(global.__snippet__map, _name);
event_perform_object(_obj, ev_other, 257);
//*/
} else {
show_error('Snippet "' + _name + '" does not exist!', true);
}
// restore previous arguments:
global.__snippet__argument_count = _old_argc;
i = 0;
repeat (_old_argc) {
global.__snippet__argument[i] = _old_args[i];
i += 1;
}
// clear the extra arguments (the other way around!):
repeat (_argc - _old_argc) {
global.__snippet__argument[i] = 0;
i += 1;
}
return global.__snippet__result;
#define snippet_call_ext
/// (name, argument_list, offset=0, ?count)
var _name; _name = argument[0];
var _args; _args = argument[1];
var _argi, _argc;
if (argument_count > 2) {
_argi = argument[2];
} else _argi = 0;
if (argument_count > 3) {
_argc = argument[3];
} else _argc = ds_list_size(_args) - _argi;
// NB! Store-restore mirrors across snippet_execute_string, snippet_call, snippet_call_ext
// store old arguments:
var _old_argc; _old_argc = global.__snippet__argument_count;
var _old_args; _old_args = global.__snippet__argument;
var i; i = 1;
repeat (_old_argc - 1) {
_old_args[i] = global.__snippet__argument[i];
i += 1;
}
// copy new arguments:
global.__snippet__argument_count = _argc;
i = 0;
repeat (_argc) {
global.__snippet__argument[i] = ds_list_find_value(_args, _argi + i);
i += 1;
}
// clear "extra" arguments:
repeat (_old_argc - _argc) {
global.__snippet__argument[i] = 0;
i += 1;
}
if (ds_map_exists(global.__snippet__map, _name)) {
global.__snippet__result = 0;
// one snippet per event:
var _enumb; _enumb = ds_map_find_value(global.__snippet__map, _name);
event_perform_object(obj_snippets, ev_alarm, _enumb);
Expand Down Expand Up @@ -489,6 +619,10 @@ return external_call(global.f_snippet_parse_api_entry, argument0);
/// snippet_parse_api_file(path)
return external_call(global.f_snippet_parse_api_file, argument0);
#define sniptools_file_exists
/// sniptools_file_exists(path)
return external_call(global.f_sniptools_file_exists, argument0);
#define sniptools_file_get_contents
/// sniptools_file_get_contents(path)
return external_call(global.f_sniptools_file_get_contents, argument0);
Expand Down
Loading

0 comments on commit cc57403

Please sign in to comment.