Command line overhaul
This commit is contained in:
parent
11b369b368
commit
9c8fe27ce4
10
Makefile
10
Makefile
|
@ -19,6 +19,7 @@ CC := $(notdir $(CC))
|
||||||
|
|
||||||
DBG ?= 1
|
DBG ?= 1
|
||||||
OPT ?= 0
|
OPT ?= 0
|
||||||
|
LEAK ?= 0
|
||||||
|
|
||||||
INFO :=
|
INFO :=
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
|
@ -64,6 +65,8 @@ ifeq ($(LEAK),1)
|
||||||
CPPFLAGS += -fsanitize=address
|
CPPFLAGS += -fsanitize=address
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
CPPFLAGS += -DLEAK=$(LEAK)
|
||||||
|
|
||||||
ifeq ($(OPT),small)
|
ifeq ($(OPT),small)
|
||||||
CPPFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables
|
CPPFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables
|
||||||
LDFLAGS += -flto
|
LDFLAGS += -flto
|
||||||
|
@ -82,7 +85,7 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(VER)\" -DINFO=\"$(INFO)\" #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t
|
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(VER)\" -DCOM=\"$(COM)\" -DINFO=\"$(INFO)\" #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t
|
||||||
|
|
||||||
# ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER
|
# ENABLE_SINC_[BEST|FAST|MEDIUM]_CONVERTER
|
||||||
# default, fast and medium available in game at runtime; best available in editor
|
# default, fast and medium available in game at runtime; best available in editor
|
||||||
|
@ -177,7 +180,7 @@ WARNING_FLAGS = -Wno-incompatible-function-pointer-types
|
||||||
NAME = primum$(EXT)
|
NAME = primum$(EXT)
|
||||||
SEM = 0.0.1
|
SEM = 0.0.1
|
||||||
COM != fossil describe
|
COM != fossil describe
|
||||||
VER = $(SEM)-$(COM)
|
VER = $(SEM)
|
||||||
|
|
||||||
LDLIBS := $(addprefix -l, $(LDLIBS))
|
LDLIBS := $(addprefix -l, $(LDLIBS))
|
||||||
LDPATHS := $(addprefix -L, $(LDPATHS))
|
LDPATHS := $(addprefix -L, $(LDPATHS))
|
||||||
|
@ -236,6 +239,7 @@ api.md: $(DOCMD)
|
||||||
@rm $^
|
@rm $^
|
||||||
|
|
||||||
INPUT = editor DebugControls component.sprite component.polygon2d component.edge2d component.circle2d
|
INPUT = editor DebugControls component.sprite component.polygon2d component.edge2d component.circle2d
|
||||||
|
|
||||||
INPUTMD := $(addsuffix .input.md, $(INPUT))
|
INPUTMD := $(addsuffix .input.md, $(INPUT))
|
||||||
input.md: $(INPUTMD)
|
input.md: $(INPUTMD)
|
||||||
@(echo "# Input"; cat $^) > $@
|
@(echo "# Input"; cat $^) > $@
|
||||||
|
@ -251,7 +255,7 @@ input.md: $(INPUTMD)
|
||||||
|
|
||||||
$(BIN)/libquickjs.a: $(QUICKJS_O)
|
$(BIN)/libquickjs.a: $(QUICKJS_O)
|
||||||
make -C quickjs clean
|
make -C quickjs clean
|
||||||
make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) AR=$(AR) OS=$(OS) libquickjs.a libquickjs.lto.a HOST_CC=$(CC)
|
make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) AR=$(AR) OS=$(OS) libquickjs.a libquickjs.lto.a HOST_CC=$(CC) LEAK=$(LEAK)
|
||||||
@mkdir -p $(BIN)
|
@mkdir -p $(BIN)
|
||||||
cp -rf quickjs/libquickjs.* $(BIN)
|
cp -rf quickjs/libquickjs.* $(BIN)
|
||||||
|
|
||||||
|
|
|
@ -77,12 +77,18 @@ The fundamental tool for building in Prosperon is the actor system. Actors run i
|
||||||
|
|
||||||
The most masterful actor is the *Empyrean*. The first actor you create will have the Empyrean as its master. Subsequent actors can use any other actor as its master.
|
The most masterful actor is the *Empyrean*. The first actor you create will have the Empyrean as its master. Subsequent actors can use any other actor as its master.
|
||||||
|
|
||||||
|
| fn | description |
|
||||||
|
|--------------------+----------------------------------------------------------|
|
||||||
|
| delay(fn, seconds) | Calls 'fn' after 'seconds' with the context of the actor |
|
||||||
|
|
||||||
*** Actor Lifetime
|
*** Actor Lifetime
|
||||||
When an actor dies, all of the actors that have it as their master[fn::What a mouthful!] will die as well.
|
When an actor dies, all of the actors that have it as their master[fn::What a mouthful!] will die as well.
|
||||||
|
|
||||||
*** Turns
|
*** Turns
|
||||||
Actors get fragments of time called a *turn*. Actors which belong to different systems can have different lengths of turns.
|
Actors get fragments of time called a *turn*. Actors which belong to different systems can have different lengths of turns.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*** Actor files
|
*** Actor files
|
||||||
Actor files end with the extension *.jso*[fn::"Javascript object".]. They list a series of functions to call on a newly formed actor. Actors have a number of useful functions which are called as defined.
|
Actor files end with the extension *.jso*[fn::"Javascript object".]. They list a series of functions to call on a newly formed actor. Actors have a number of useful functions which are called as defined.
|
||||||
|
|
||||||
|
@ -100,8 +106,8 @@ Create a new actor, then kill it.
|
||||||
var act_die_call = function() {
|
var act_die_call = function() {
|
||||||
console.log(`Actor ${this.id} has died.`);
|
console.log(`Actor ${this.id} has died.`);
|
||||||
}
|
}
|
||||||
var act1 = Empyrean.new();
|
var act1 = Empyrean.spawn();
|
||||||
var act2 = actor1.new();
|
var act2 = actor1.spawn();
|
||||||
act1.stop = act_die_call;
|
act1.stop = act_die_call;
|
||||||
act2.stop = act_die_call;
|
act2.stop = act_die_call;
|
||||||
Empyrean.kill(); /* Error: The Empyrean cannot be killed */
|
Empyrean.kill(); /* Error: The Empyrean cannot be killed */
|
||||||
|
@ -119,8 +125,8 @@ this.stop = function() {
|
||||||
#+end_src
|
#+end_src
|
||||||
Now spawn two actors using it.
|
Now spawn two actors using it.
|
||||||
#+begin_src
|
#+begin_src
|
||||||
var act1 = Empyrean.new("hello.jso");
|
var act1 = Empyrean.spawn("hello.jso");
|
||||||
var act2 = act1.new("hello.jso");
|
var act2 = act1.spawn("hello.jso");
|
||||||
#+end_src
|
#+end_src
|
||||||
#+end_scholium
|
#+end_scholium
|
||||||
|
|
||||||
|
@ -153,7 +159,7 @@ Entities can have *components*. Components are essentially javascript wrappers o
|
||||||
#+begin_scholium
|
#+begin_scholium
|
||||||
For example, to render an image, set up a *sprite* component on an entity and point its path to an image on your harddrive.
|
For example, to render an image, set up a *sprite* component on an entity and point its path to an image on your harddrive.
|
||||||
#+begin_src
|
#+begin_src
|
||||||
var ent = Empyrean.new();
|
var ent = Empyrean.spawn();
|
||||||
var spr = ent.add_component(component.sprite);
|
var spr = ent.add_component(component.sprite);
|
||||||
spr.path = "image.png";
|
spr.path = "image.png";
|
||||||
#+end_src
|
#+end_src
|
||||||
|
@ -249,11 +255,13 @@ Caution! Because the path is resolved during object load, you will need to fresh
|
||||||
**** Links
|
**** Links
|
||||||
Links can be specified using the "#" sign. These are shortcuts you can specify for large projects. Specify them in the array ~Resources.links~.
|
Links can be specified using the "#" sign. These are shortcuts you can specify for large projects. Specify them in the array ~Resources.links~.
|
||||||
|
|
||||||
An example is of the form ~trees:/world/assets/nature/trees~. Links are called with ~#~, so you can now make a "fern" with ~Primum.new("#trees/fern.jso")~.
|
An example is of the form ~trees:/world/assets/nature/trees~. Links are called with ~#~, so you can now make a "fern" with ~Primum.spawn("#trees/fern.jso")~.
|
||||||
|
|
||||||
*** Ur auto creation
|
*** Ur auto creation
|
||||||
Instead of coding all the ur type creation by hand, Prosperon can automatically search your project's folder and create the ur types for you. Any /[name].jso/ file is converted into an ur with the name. Any /[name].json/ file is then applied over it, should it exist. If there is a /.json/ file without a corresponding /.jso/, it can still be turned into an ur, if it is a valid ur format.
|
Instead of coding all the ur type creation by hand, Prosperon can automatically search your project's folder and create the ur types for you. Any /[name].jso/ file is converted into an ur with the name. Any /[name].json/ file is then applied over it, should it exist. If there is a /.json/ file without a corresponding /.jso/, it can still be turned into an ur, if it is a valid ur format.
|
||||||
|
|
||||||
|
Folders and files beginning with a '.' (hidden) or a '_' will be ignored for ur creation.
|
||||||
|
|
||||||
The folder hierarchy of your file system determines the ur prototype chain. /.jso/ files inside of a folder will be subtyped off the folder ur name.
|
The folder hierarchy of your file system determines the ur prototype chain. /.jso/ files inside of a folder will be subtyped off the folder ur name.
|
||||||
|
|
||||||
Only one ur of any name can be created.
|
Only one ur of any name can be created.
|
||||||
|
@ -333,6 +341,9 @@ The GUI system which ships with Prosperon is called *MUM*. MUM is a declarative,
|
||||||
|
|
||||||
All GUI objects derive from MUM. MUM has a list of properties, used for rendering. Mum also has functions which cause drawing to appear on the screen.
|
All GUI objects derive from MUM. MUM has a list of properties, used for rendering. Mum also has functions which cause drawing to appear on the screen.
|
||||||
|
|
||||||
|
** Physics
|
||||||
|
Prospeorn comes with the [[https://chipmunk-physics.net][Chipmunk]] physics engine built in. It is a fast, stable physics solution. All entities are assumed to be physics based objects, and components can be added to them to enable more physics features.
|
||||||
|
|
||||||
* Editor Tour
|
* Editor Tour
|
||||||
Prosperon's visual editor is an assistant for the creation and editing of your game entities and actors. In the editor, all ur types are loaded, and assets are constantly monitored for changes for hot reloading.
|
Prosperon's visual editor is an assistant for the creation and editing of your game entities and actors. In the editor, all ur types are loaded, and assets are constantly monitored for changes for hot reloading.
|
||||||
|
|
||||||
|
|
|
@ -91,14 +91,16 @@
|
||||||
*/
|
*/
|
||||||
//#define DUMP_BYTECODE (1)
|
//#define DUMP_BYTECODE (1)
|
||||||
/* dump the occurence of the automatic GC */
|
/* dump the occurence of the automatic GC */
|
||||||
#define DUMP_GC
|
//#define DUMP_GC
|
||||||
/* dump objects freed by the garbage collector */
|
/* dump objects freed by the garbage collector */
|
||||||
//#define DUMP_GC_FREE
|
//#define DUMP_GC_FREE
|
||||||
/* dump objects leaking when freeing the runtime */
|
/* dump objects leaking when freeing the runtime */
|
||||||
|
#ifdef LEAK
|
||||||
#define DUMP_LEAKS 1
|
#define DUMP_LEAKS 1
|
||||||
|
#endif
|
||||||
/* dump memory usage before running the garbage collector */
|
/* dump memory usage before running the garbage collector */
|
||||||
#define DUMP_MEM
|
//#define DUMP_MEM
|
||||||
#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
|
//#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
|
||||||
//#define DUMP_ATOMS /* dump atoms in JS_FreeContext */
|
//#define DUMP_ATOMS /* dump atoms in JS_FreeContext */
|
||||||
//#define DUMP_SHAPES /* dump shapes in JS_FreeContext */
|
//#define DUMP_SHAPES /* dump shapes in JS_FreeContext */
|
||||||
//#define DUMP_MODULE_RESOLVE
|
//#define DUMP_MODULE_RESOLVE
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Prosperon Engine
|
# Prosperon Engine
|
||||||
A developer minded, 2D-first game engine.
|
The easily extendable, developer minded, 2D-first game engine.
|
||||||
|
|
||||||
See the documentation [here](https://prosperon.dev/doc).
|
See the documentation [here](https://prosperon.dev/doc).
|
||||||
|
|
116
scripts/debug.js
116
scripts/debug.js
|
@ -1,15 +1,22 @@
|
||||||
/* All draw in screen space */
|
/* All draw in screen space */
|
||||||
var Shape = {
|
var Shape = {
|
||||||
circle(pos, radius, color) { cmd(115, pos, radius, color); },
|
|
||||||
|
|
||||||
point(pos,size,color) {
|
point(pos,size,color) {
|
||||||
color ??= Color.blue;
|
color ??= Color.blue;
|
||||||
Shape.circle(pos,size,color);
|
Shape.circle(pos,size,color);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
line(points, color, thickness) {
|
||||||
|
thickness ??= 1;
|
||||||
|
color ??= Color.white;
|
||||||
|
cmd(83, points, color, thickness);
|
||||||
|
},
|
||||||
|
|
||||||
|
poly(points, color) { cmd_points(0,points,color); },
|
||||||
|
|
||||||
|
circle(pos, radius, color) { cmd(115, pos, radius, color); },
|
||||||
|
|
||||||
/* size here is arm length - size of 2 is 4 height total */
|
/* size here is arm length - size of 2 is 4 height total */
|
||||||
cross(pos, size, color, angle) {
|
cross(pos, size, color) {
|
||||||
angle ??= 0;
|
|
||||||
color ??= Color.red;
|
color ??= Color.red;
|
||||||
var a = [
|
var a = [
|
||||||
pos.add([0,size]),
|
pos.add([0,size]),
|
||||||
|
@ -43,8 +50,6 @@ var Shape = {
|
||||||
Shape.line(wing2,color);
|
Shape.line(wing2,color);
|
||||||
},
|
},
|
||||||
|
|
||||||
poly(points, color) { cmd_points(0,points,color); },
|
|
||||||
|
|
||||||
rectangle(lowerleft, upperright, color) {
|
rectangle(lowerleft, upperright, color) {
|
||||||
var pos = lowerleft.add(upperright).map(x=>x/2);
|
var pos = lowerleft.add(upperright).map(x=>x/2);
|
||||||
var wh = [upperright.x-lowerleft.x,upperright.y-lowerleft.y];
|
var wh = [upperright.x-lowerleft.x,upperright.y-lowerleft.y];
|
||||||
|
@ -56,18 +61,17 @@ var Shape = {
|
||||||
cmd(53, pos, wh, color);
|
cmd(53, pos, wh, color);
|
||||||
},
|
},
|
||||||
|
|
||||||
line(points, color, type, thickness) {
|
|
||||||
thickness ??= 1;
|
|
||||||
type ??= 0;
|
|
||||||
color ??= Color.white;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 0:
|
|
||||||
cmd(83, points, color, thickness);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Shape.doc = "Draw shapes in screen space.";
|
||||||
|
Shape.circle.doc = "Draw a circle at pos, with a given radius and color.";
|
||||||
|
Shape.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
||||||
|
Shape.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
||||||
|
Shape.poly.doc = "Draw a concave polygon from a set of points.";
|
||||||
|
Shape.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
|
||||||
|
Shape.box.doc = "Draw a box centered at pos, with width and height in the tuple wh.";
|
||||||
|
Shape.line.doc = "Draw a line from a set of points, and a given thickness.";
|
||||||
|
|
||||||
var Debug = {
|
var Debug = {
|
||||||
fn_break(fn, obj) {
|
fn_break(fn, obj) {
|
||||||
if (typeof fn !== 'function') return;
|
if (typeof fn !== 'function') return;
|
||||||
|
@ -352,11 +356,36 @@ console.clear = function()
|
||||||
cmd(146);
|
cmd(146);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.assert = function(assertion, msg, objs)
|
||||||
|
{
|
||||||
|
if (!assertion) {
|
||||||
|
console.error(msg);
|
||||||
|
console.stack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var say = function(msg) {
|
||||||
|
console.say(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
say.doc = "Print to std out with an appended newline.";
|
||||||
|
|
||||||
|
var gist = function(o)
|
||||||
|
{
|
||||||
|
if (typeof o === 'object') return json.encode(o,null,1);
|
||||||
|
if (typeof o === 'string') return o;
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
gist.doc = "Return the best string gist of an object.";
|
||||||
|
|
||||||
var API = {};
|
var API = {};
|
||||||
API.doc_entry = function(obj, key)
|
API.doc_entry = function(obj, key)
|
||||||
{
|
{
|
||||||
var d = obj.doc;
|
if (typeof key !== 'string') {
|
||||||
var doc = "";
|
console.warn("Cannot print a key that isn't a string.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
var title = key;
|
var title = key;
|
||||||
|
|
||||||
var o = obj[key];
|
var o = obj[key];
|
||||||
|
@ -364,23 +393,23 @@ API.doc_entry = function(obj, key)
|
||||||
o = obj.impl[key];
|
o = obj.impl[key];
|
||||||
|
|
||||||
var t = typeof o;
|
var t = typeof o;
|
||||||
if (t === 'object' && Array.isArray(o)) t = 'array';
|
if (Array.isArray(o)) t = "array";
|
||||||
|
else if (t === 'function') {
|
||||||
if (t === 'function') {
|
|
||||||
title = o.toString().tofirst(')') + ")";
|
title = o.toString().tofirst(')') + ")";
|
||||||
|
title = title.fromfirst('(');
|
||||||
|
title = key + "(" + title;
|
||||||
if (o.doc) doc = o.doc;
|
if (o.doc) doc = o.doc;
|
||||||
t = "";
|
t = "";
|
||||||
}
|
} else if (t === 'undefined') t = "";
|
||||||
if (t === 'undefined') t = "";
|
|
||||||
|
|
||||||
if (t) t = "**" + t + "**";
|
if (t) t = "**" + t + "**\n";
|
||||||
|
|
||||||
if (!doc) {
|
var doc = "";
|
||||||
if (d && d[key]) doc = d[key];
|
if (o.doc) doc = o.doc;
|
||||||
else return "";
|
else if (obj.doc && obj.doc[key]) doc = obj.doc[key];
|
||||||
}
|
else if (Array.isArray(o)) doc = json.encode(o);
|
||||||
|
|
||||||
return `### \`${title}\`
|
return `## ${title}
|
||||||
${t}
|
${t}
|
||||||
${doc}
|
${doc}
|
||||||
`;
|
`;
|
||||||
|
@ -388,19 +417,38 @@ ${doc}
|
||||||
|
|
||||||
API.print_doc = function(name)
|
API.print_doc = function(name)
|
||||||
{
|
{
|
||||||
var obj = eval(name);
|
var obj = name;
|
||||||
if (!obj.doc) {
|
if (typeof name === 'string') {
|
||||||
Log.warn(`Object has no doc sidecar.`);
|
obj = eval(name);
|
||||||
|
if (!obj) {
|
||||||
|
console.warn(`Cannot print the API of '${name}', as it was not found.`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = globalThis[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = eval(name);
|
||||||
|
|
||||||
|
if (!Object.isObject(obj)) {
|
||||||
|
console.warn("Cannot print the API of something that isn't an object.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj) {
|
||||||
|
console.warn(`Object '${name}' does not exist.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mdoc = "# " + name + " API #\n";
|
var mdoc = "# " + name + "\n";
|
||||||
if (obj.doc?.doc) mdoc += obj.doc.doc + "\n";
|
if (obj.doc?.doc) mdoc += obj.doc.doc + "\n";
|
||||||
else if (typeof obj.doc === 'string') mdoc += obj.doc + "\n";
|
else if (typeof obj.doc === 'string') mdoc += obj.doc + "\n";
|
||||||
|
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
if (key === 'doc') continue;
|
if (key === 'doc') continue;
|
||||||
if (key === 'toString') continue;
|
if (key === 'toString') continue;
|
||||||
mdoc += API.doc_entry(obj, key);
|
|
||||||
|
mdoc += API.doc_entry(obj, key) + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return mdoc;
|
return mdoc;
|
||||||
|
|
|
@ -876,6 +876,7 @@ editor.inputs['M-t'] = function() { editor.edit_level.objects.forEach(function(x
|
||||||
editor.inputs['M-t'].doc = "Unlock all objects in current level.";
|
editor.inputs['M-t'].doc = "Unlock all objects in current level.";
|
||||||
|
|
||||||
editor.inputs['C-n'] = function() {
|
editor.inputs['C-n'] = function() {
|
||||||
|
console.warn(`Spawning a new object on ${editor.edit_level.toString()}`);
|
||||||
editor.edit_level.spawn();
|
editor.edit_level.spawn();
|
||||||
};
|
};
|
||||||
editor.inputs['C-n'].doc = "Create an empty object.";
|
editor.inputs['C-n'].doc = "Create an empty object.";
|
||||||
|
|
|
@ -5,11 +5,19 @@ function load(file) {
|
||||||
files[file] = modtime;
|
files[file] = modtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmd_args = function(cc)
|
||||||
|
{
|
||||||
|
console.warn(cc);
|
||||||
|
}
|
||||||
|
|
||||||
load("scripts/base.js");
|
load("scripts/base.js");
|
||||||
load("scripts/std.js");
|
load("scripts/std.js");
|
||||||
//load("scripts/lunr.js");
|
//load("scripts/lunr.js");
|
||||||
var lunrtxt = load("scripts/lunr.js");
|
//var lunrtxt = load("scripts/lunr.js");
|
||||||
eval(lunrtxt);
|
//eval(lunrtxt);
|
||||||
|
|
||||||
|
/* The global namespace file */
|
||||||
|
var prosp = {};
|
||||||
|
|
||||||
function run(file)
|
function run(file)
|
||||||
{
|
{
|
||||||
|
@ -23,12 +31,17 @@ function run(file)
|
||||||
return cmd(117, file);
|
return cmd(117, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run.doc = `Load a given script file.`;
|
||||||
|
load.doc = `Load a given script file.`;
|
||||||
|
|
||||||
function run_env(file, env)
|
function run_env(file, env)
|
||||||
{
|
{
|
||||||
var script = IO.slurp(file);
|
var script = IO.slurp(file);
|
||||||
return function(){return eval(script);}.call(env);
|
return function(){return eval(script);}.call(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_env.doc = `Load a given script file, evaluating it in the context of the object 'env'.`;
|
||||||
|
|
||||||
load("scripts/diff.js");
|
load("scripts/diff.js");
|
||||||
Log.level = 1;
|
Log.level = 1;
|
||||||
|
|
||||||
|
@ -72,6 +85,62 @@ var Device = {
|
||||||
gamegear: [160,144,3.2],
|
gamegear: [160,144,3.2],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Device.doc = `Device resolutions given as [x,y,inches diagonal].`;
|
||||||
|
|
||||||
|
var prosperon = {};
|
||||||
|
prosperon.version = cmd(255);
|
||||||
|
prosperon.revision = cmd(256);
|
||||||
|
|
||||||
|
prosperon.semver = {};
|
||||||
|
prosperon.semver.valid = function(v, range)
|
||||||
|
{
|
||||||
|
v = v.split('.');
|
||||||
|
range = range.split('.');
|
||||||
|
if (v.length !== 3) return undefined;
|
||||||
|
if (range.length !== 3) return undefined;
|
||||||
|
|
||||||
|
if (range[0][0] === '^') {
|
||||||
|
range[0] = range[0].slice(1);
|
||||||
|
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range[0] === '~') {
|
||||||
|
range[0] = range[0].slice(1);
|
||||||
|
for (var i = 0; i < 2; i++)
|
||||||
|
if (parseInt(v[i]) < parseInt(range[i])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prosperon.semver.cmp(v.join('.'), range.join('.')) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prosperon.semver.cmp = function(v1, v2)
|
||||||
|
{
|
||||||
|
var ver1 = v1.split('.');
|
||||||
|
var ver2 = v2.split('.');
|
||||||
|
|
||||||
|
for (var i = 0; i < 3; i++) {
|
||||||
|
var n1 = parseInt(ver1[i]);
|
||||||
|
var n2 = parseInt(ver2[i]);
|
||||||
|
if (n1 > n2)
|
||||||
|
return 1;
|
||||||
|
else if (n1 < n2)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prosperon.semver.doc = "Functions for semantic versioning numbers. Semantic versioning is given as a triple digit number, as MAJOR.MINOR.PATCH.";
|
||||||
|
prosperon.semver.cmp.doc = "Compare two semantic version numbers, given like X.X.X.";
|
||||||
|
prosperon.semver.valid.doc = `Test if semantic version v is valid, given a range.
|
||||||
|
Range is given by a semantic versioning number, prefixed with nothing, a ~, or a ^.
|
||||||
|
~ means that MAJOR and MINOR must match exactly, but any PATCH greater or equal is valid.
|
||||||
|
^ means that MAJOR must match exactly, but any MINOR and PATCH greater or equal is valid.`;
|
||||||
|
|
||||||
|
|
||||||
load("scripts/gui.js");
|
load("scripts/gui.js");
|
||||||
|
|
||||||
var timer = {
|
var timer = {
|
||||||
|
@ -253,8 +322,6 @@ var Event = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Event.observe('quit', undefined, function() { Primum.kill(); });
|
|
||||||
|
|
||||||
var Window = {
|
var Window = {
|
||||||
fullscreen(f) { cmd(145, f); },
|
fullscreen(f) { cmd(145, f); },
|
||||||
set width(w) { cmd(125, w); },
|
set width(w) { cmd(125, w); },
|
||||||
|
@ -411,22 +478,14 @@ Spline.bezier_is_handle = function(points, i) { return !Spline.bezier_is_node(po
|
||||||
load("scripts/components.js");
|
load("scripts/components.js");
|
||||||
|
|
||||||
var Game = {
|
var Game = {
|
||||||
init() {
|
engine_start(fn) {
|
||||||
if (!Game.edit) {
|
cmd(257, fn);
|
||||||
load("config.js");
|
Sound.bus.master = cmd(180);
|
||||||
load("game.js");
|
Sound.master = Sound.bus.master;
|
||||||
}
|
|
||||||
else {
|
|
||||||
load("scripts/editor.js");
|
|
||||||
load("editorconfig.js");
|
|
||||||
editor.enter_editor();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
native: Device.pc,
|
native: Device.pc,
|
||||||
|
|
||||||
edit: true,
|
|
||||||
|
|
||||||
object_count() {
|
object_count() {
|
||||||
return cmd(214);
|
return cmd(214);
|
||||||
},
|
},
|
||||||
|
@ -476,6 +535,9 @@ var Game = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Game.gc = function() { cmd(259); }
|
||||||
|
Game.gc.doc = "Force the garbage collector to run.";
|
||||||
|
|
||||||
Game.doc = {};
|
Game.doc = {};
|
||||||
Game.doc.object = "Returns the entity belonging to a given id.";
|
Game.doc.object = "Returns the entity belonging to a given id.";
|
||||||
Game.doc.quit = "Immediately quit the game.";
|
Game.doc.quit = "Immediately quit the game.";
|
||||||
|
@ -511,7 +573,11 @@ function world_start() {
|
||||||
Primum.ur = "Primum";
|
Primum.ur = "Primum";
|
||||||
Primum.kill = function() { this.clear(); };
|
Primum.kill = function() { this.clear(); };
|
||||||
Primum.phys = 2;
|
Primum.phys = 2;
|
||||||
|
|
||||||
gameobject.level = Primum;
|
gameobject.level = Primum;
|
||||||
|
gameobject.body = make_gameobject();
|
||||||
|
cmd(113,gameobject.body, gameobject);
|
||||||
|
Object.hide(gameobject, 'timescale');
|
||||||
}
|
}
|
||||||
|
|
||||||
load("scripts/physics.js");
|
load("scripts/physics.js");
|
||||||
|
@ -525,8 +591,3 @@ Game.view_camera = function(cam)
|
||||||
Window.name = "Prosperon (V0.1)";
|
Window.name = "Prosperon (V0.1)";
|
||||||
Window.width = 1280;
|
Window.width = 1280;
|
||||||
Window.height = 720;
|
Window.height = 720;
|
||||||
|
|
||||||
var Asset = {};
|
|
||||||
Asset.doc = {
|
|
||||||
doc: "Functions to manage the loading and unloading of assets, like sounds and images."
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
function obj_unique_name(name, obj)
|
prosp.obj_unique_name = function(name, obj)
|
||||||
{
|
{
|
||||||
name = name.replaceAll('.', '_');
|
name = name.replaceAll('.', '_');
|
||||||
if (!(name in obj)) return name;
|
if (!(name in obj)) return name;
|
||||||
|
@ -27,9 +27,13 @@ actor.spawn = function(script, config){
|
||||||
this.padawans.push(padawan);
|
this.padawans.push(padawan);
|
||||||
return padawan;
|
return padawan;
|
||||||
};
|
};
|
||||||
actor.die = function(actor){
|
|
||||||
|
|
||||||
|
actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`;
|
||||||
|
|
||||||
|
actor.die = function(e){
|
||||||
|
e.kill();
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.timers = [];
|
actor.timers = [];
|
||||||
actor.kill = function(){
|
actor.kill = function(){
|
||||||
this.timers.forEach(t => t.kill());
|
this.timers.forEach(t => t.kill());
|
||||||
|
@ -38,6 +42,8 @@ actor.kill = function(){
|
||||||
this.__dead__ = true;
|
this.__dead__ = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
actor.kill.doc = `Remove this actor and all its padawans from existence.`;
|
||||||
|
|
||||||
actor.delay = function(fn, seconds) {
|
actor.delay = function(fn, seconds) {
|
||||||
var t = Object.create(timer);
|
var t = Object.create(timer);
|
||||||
t.remain = seconds;
|
t.remain = seconds;
|
||||||
|
@ -55,6 +61,8 @@ actor.delay = function(fn, seconds) {
|
||||||
return function() { t.kill(); };
|
return function() { t.kill(); };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
||||||
|
|
||||||
actor.master = undefined;
|
actor.master = undefined;
|
||||||
|
|
||||||
actor.padawans = [];
|
actor.padawans = [];
|
||||||
|
@ -682,7 +690,7 @@ var gameobject = {
|
||||||
add_component(comp, data) {
|
add_component(comp, data) {
|
||||||
data ??= undefined;
|
data ??= undefined;
|
||||||
if (typeof comp.make !== 'function') return;
|
if (typeof comp.make !== 'function') return;
|
||||||
var name = obj_unique_name(comp.toString(), this);
|
var name = prosp.obj_unique_name(comp.toString(), this);
|
||||||
this[name] = comp.make(this);
|
this[name] = comp.make(this);
|
||||||
this[name].comp = comp.toString();
|
this[name].comp = comp.toString();
|
||||||
this.components[name] = this[name];
|
this.components[name] = this[name];
|
||||||
|
@ -699,10 +707,6 @@ var gameobject = {
|
||||||
}
|
}
|
||||||
Object.mixin(gameobject,gameobject_impl);
|
Object.mixin(gameobject,gameobject_impl);
|
||||||
|
|
||||||
gameobject.body = make_gameobject();
|
|
||||||
cmd(113,gameobject.body, gameobject);
|
|
||||||
Object.hide(gameobject, 'timescale');
|
|
||||||
|
|
||||||
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
||||||
|
|
||||||
gameobject.doc = {
|
gameobject.doc = {
|
||||||
|
@ -865,14 +869,10 @@ prototypes.file2ur = function(file)
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns an ur, or makes it, for any given type of path
|
|
||||||
could be a file on a disk like ball/big.js
|
|
||||||
could be an ur path like ball.big
|
|
||||||
*/
|
|
||||||
prototypes.get_ur = function(name)
|
prototypes.get_ur = function(name)
|
||||||
{
|
{
|
||||||
if (!name) {
|
if (!name) {
|
||||||
Log.warn(`Can't get ur from an undefined.`);
|
console.error(`Can't get ur from an undefined.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var urpath = name;
|
var urpath = name;
|
||||||
|
@ -884,13 +884,17 @@ prototypes.get_ur = function(name)
|
||||||
if (ur)
|
if (ur)
|
||||||
return ur;
|
return ur;
|
||||||
else {
|
else {
|
||||||
Log.warn(`Could not find prototype using name ${name}.`);
|
console.warn(`Could not find prototype using name ${name}.`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
return prototypes.ur[urpath];
|
return prototypes.ur[urpath];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prototypes.get_ur.doc = `Returns an ur, or makes it, for any given type of path
|
||||||
|
could be a file on a disk like ball/big.js
|
||||||
|
could be an ur path like ball.big`;
|
||||||
|
|
||||||
prototypes.get_ur_file = function(path, ext)
|
prototypes.get_ur_file = function(path, ext)
|
||||||
{
|
{
|
||||||
var urpath = prototypes.ur2file(path);
|
var urpath = prototypes.ur2file(path);
|
||||||
|
@ -908,6 +912,8 @@ prototypes.generate_ur = function(path)
|
||||||
|
|
||||||
ob = ob.map(function(path) { return path.set_ext(""); });
|
ob = ob.map(function(path) { return path.set_ext(""); });
|
||||||
ob = ob.map(function(path) { return path[0] !== '.' ? path : undefined; });
|
ob = ob.map(function(path) { return path[0] !== '.' ? path : undefined; });
|
||||||
|
ob = ob.map(function(path) { return path[0] !== '_' ? path : undefined; });
|
||||||
|
ob = ob.filter(x => x !== undefined);
|
||||||
ob.forEach(function(name) { prototypes.get_ur(name); });
|
ob.forEach(function(name) { prototypes.get_ur(name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,6 @@ var DSP = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Sound.bus.master = cmd(180);
|
|
||||||
Sound.master = Sound.bus.master;
|
|
||||||
|
|
||||||
Sound.play.doc = "Play the given file once.";
|
Sound.play.doc = "Play the given file once.";
|
||||||
Sound.doc = {};
|
Sound.doc = {};
|
||||||
|
|
228
scripts/std.js
228
scripts/std.js
|
@ -15,6 +15,8 @@ function buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||||
var OS = {};
|
var OS = {};
|
||||||
OS.cwd = function() { return cmd(144); }
|
OS.cwd = function() { return cmd(144); }
|
||||||
OS.exec = function(s) { cmd(143, s); }
|
OS.exec = function(s) { cmd(143, s); }
|
||||||
|
OS.cwd.doc = "Get the absolute path of the current working directory.";
|
||||||
|
OS.exec.doc = "Run a command line instruction, and return when it finishes.";
|
||||||
|
|
||||||
var Resources = {};
|
var Resources = {};
|
||||||
Resources.images = ["png", "jpg", "jpeg", "gif"];
|
Resources.images = ["png", "jpg", "jpeg", "gif"];
|
||||||
|
@ -24,6 +26,7 @@ Resources.is_image = function(path) {
|
||||||
var ext = path.ext();
|
var ext = path.ext();
|
||||||
return Resources.images.any(x => x === ext);
|
return Resources.images.any(x => x === ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources.is_sound = function(path) {
|
Resources.is_sound = function(path) {
|
||||||
var ext = path.ext();
|
var ext = path.ext();
|
||||||
return Resources.sounds.any(x => x === ext);
|
return Resources.sounds.any(x => x === ext);
|
||||||
|
@ -91,13 +94,8 @@ var Log = {
|
||||||
cmd(91,msg);
|
cmd(91,msg);
|
||||||
},
|
},
|
||||||
|
|
||||||
say(msg) {
|
say(msg) { Log.write(msg + '\n'); },
|
||||||
Log.write(msg + '\n');
|
repl(msg) { cmd(142, msg + '\n'); },
|
||||||
},
|
|
||||||
|
|
||||||
repl(msg) {
|
|
||||||
cmd(142, msg + '\n');
|
|
||||||
},
|
|
||||||
|
|
||||||
stack(skip = 0) {
|
stack(skip = 0) {
|
||||||
var err = new Error();
|
var err = new Error();
|
||||||
|
@ -160,6 +158,12 @@ var IO = {
|
||||||
paths = paths.filter(function(str) { return str.ext() === ext; });
|
paths = paths.filter(function(str) { return str.ext() === ext; });
|
||||||
return paths;
|
return paths;
|
||||||
},
|
},
|
||||||
|
compile(script) {
|
||||||
|
return cmd(260, script);
|
||||||
|
},
|
||||||
|
run_bytecode(byte_file) {
|
||||||
|
return cmd(261, byte_file);
|
||||||
|
},
|
||||||
ls() { return cmd(66); },
|
ls() { return cmd(66); },
|
||||||
/* Only works on text files currently */
|
/* Only works on text files currently */
|
||||||
cp(f1, f2) {
|
cp(f1, f2) {
|
||||||
|
@ -171,6 +175,9 @@ var IO = {
|
||||||
rm(f) {
|
rm(f) {
|
||||||
return cmd(f);
|
return cmd(f);
|
||||||
},
|
},
|
||||||
|
mkdir(dir) {
|
||||||
|
cmd(258, dir);
|
||||||
|
},
|
||||||
glob(pat) {
|
glob(pat) {
|
||||||
var paths = IO.ls();
|
var paths = IO.ls();
|
||||||
pat = pat.replaceAll(/([\[\]\(\)\^\$\.\|\+])/g, "\\$1");
|
pat = pat.replaceAll(/([\[\]\(\)\^\$\.\|\+])/g, "\\$1");
|
||||||
|
@ -187,7 +194,12 @@ IO.doc = {
|
||||||
doc: "Functions for filesystem input/output commands.",
|
doc: "Functions for filesystem input/output commands.",
|
||||||
exists: "Returns true if a file exists.",
|
exists: "Returns true if a file exists.",
|
||||||
slurp: "Returns the contents of given file as a string.",
|
slurp: "Returns the contents of given file as a string.",
|
||||||
|
slurpbytes: "Return the contents of a file as a byte array.",
|
||||||
slurpwrite: "Write a given string to a given file.",
|
slurpwrite: "Write a given string to a given file.",
|
||||||
|
cp: "Copy file f1 to f2.",
|
||||||
|
mv: "Rename file f1 to f2.",
|
||||||
|
rm: "Remove file f.",
|
||||||
|
mkdir: "Make dir.",
|
||||||
ls: "List contents of the game directory.",
|
ls: "List contents of the game directory.",
|
||||||
glob: "Glob files in game directory.",
|
glob: "Glob files in game directory.",
|
||||||
};
|
};
|
||||||
|
@ -214,6 +226,7 @@ Parser.replstrs = function(path)
|
||||||
var Cmdline = {};
|
var Cmdline = {};
|
||||||
|
|
||||||
Cmdline.cmds = [];
|
Cmdline.cmds = [];
|
||||||
|
Cmdline.orders = {};
|
||||||
Cmdline.register_cmd = function(flag, fn, doc) {
|
Cmdline.register_cmd = function(flag, fn, doc) {
|
||||||
Cmdline.cmds.push({
|
Cmdline.cmds.push({
|
||||||
flag: flag,
|
flag: flag,
|
||||||
|
@ -222,10 +235,160 @@ Cmdline.register_cmd = function(flag, fn, doc) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Cmdline.register_order = function(order, fn, doc, usage) {
|
||||||
|
Cmdline.orders[order] = fn;
|
||||||
|
fn.doc = doc;
|
||||||
|
usage ??= "";
|
||||||
|
fn.usage = `${order} ${usage}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cmdline.register_order("edit", function() {
|
||||||
|
if (!IO.exists(".prosperon")) {
|
||||||
|
IO.mkdir(".prosperon");
|
||||||
|
var project = {};
|
||||||
|
project.version = prosperon.version;
|
||||||
|
project.revision = prosperon.revision;
|
||||||
|
IO.slurpwrite(".prosperon/project", json.encode(project));
|
||||||
|
}
|
||||||
|
Game.engine_start(function() {
|
||||||
|
load("scripts/editor.js");
|
||||||
|
load("editorconfig.js");
|
||||||
|
editor.enter_editor();
|
||||||
|
});
|
||||||
|
}, "Edit the project in this folder. Give it the name of an UR to edit that specific object.", "?UR?");
|
||||||
|
|
||||||
|
Cmdline.register_order("play", function() {
|
||||||
|
if (!IO.exists(".prosperon")) {
|
||||||
|
IO.mkdir(".prosperon");
|
||||||
|
var project = {};
|
||||||
|
project.version = prosperon.version;
|
||||||
|
project.revision = prosperon.revision;
|
||||||
|
IO.slurpwrite(".prosperon/project", json.encode(project));
|
||||||
|
}
|
||||||
|
Game.engine_start(function() {
|
||||||
|
load("config.js");
|
||||||
|
load("game.js");
|
||||||
|
});
|
||||||
|
}, "Play the game present in this folder.");
|
||||||
|
|
||||||
|
Cmdline.register_order("pack", function(str) {
|
||||||
|
var packname;
|
||||||
|
if (str.length === 0)
|
||||||
|
packname = "test.cdb";
|
||||||
|
else if (str.length > 1) {
|
||||||
|
Log.warn("Give me a single filename for the pack.");
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
packname = str[0];
|
||||||
|
|
||||||
|
say(`Packing into ${packname}`);
|
||||||
|
|
||||||
|
cmd(124, packname);
|
||||||
|
}, "Pack the game into the given name.", "NAME");
|
||||||
|
|
||||||
|
Cmdline.register_order("unpack", function() {
|
||||||
|
say("Unpacking not implemented.");
|
||||||
|
}, "Unpack this binary's contents into this folder for editing.");
|
||||||
|
|
||||||
|
Cmdline.register_order("build", function() {
|
||||||
|
say("Building not implemented.");
|
||||||
|
}, "Build static assets for this project.");
|
||||||
|
|
||||||
|
Cmdline.register_order("api", function(obj) {
|
||||||
|
if (!obj[0])
|
||||||
|
Cmdline.print_order("api");
|
||||||
|
|
||||||
|
load("scripts/editor.js");
|
||||||
|
var api = API.print_doc(obj[0]);
|
||||||
|
if (!api)
|
||||||
|
return;
|
||||||
|
|
||||||
|
say(api);
|
||||||
|
}, "Print the API for an object as markdown. Give it a file to save the output to.", "OBJECT");
|
||||||
|
|
||||||
|
Cmdline.register_order("compile", function(argv) {
|
||||||
|
for (var file of argv) {
|
||||||
|
var comp = IO.compile(file);
|
||||||
|
IO.slurpwrite(file + ".byte", comp);
|
||||||
|
}
|
||||||
|
}, "Compile one or more provided files into bytecode.", "FILE ...");
|
||||||
|
|
||||||
|
Cmdline.register_order("input", function(pawn) {
|
||||||
|
load("scripts/editor.js");
|
||||||
|
say(`## Input for ${pawn}`);
|
||||||
|
eval(`say(Input.print_md_kbm(${pawn}));`);
|
||||||
|
}, "Print input documentation for a given object as markdown. Give it a file to save the output to", "OBJECT ?FILE?");
|
||||||
|
|
||||||
|
Cmdline.register_order("run", function(script) {
|
||||||
|
script = script.join(" ");
|
||||||
|
if (!script) {
|
||||||
|
say("Need something to run.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IO.exists(script))
|
||||||
|
try {
|
||||||
|
if (script.endswith(".byte"))
|
||||||
|
cmd(261, script);
|
||||||
|
else
|
||||||
|
run(script);
|
||||||
|
} catch(e) { }
|
||||||
|
else {
|
||||||
|
var ret = eval(script);
|
||||||
|
if (ret) say(ret);
|
||||||
|
}
|
||||||
|
}, "Run a given script. SCRIPT can be the script itself, or a file containing the script", "SCRIPT");
|
||||||
|
|
||||||
|
Cmdline.print_order = function(fn)
|
||||||
|
{
|
||||||
|
if (typeof fn === 'string')
|
||||||
|
fn = Cmdline.orders[fn];
|
||||||
|
|
||||||
|
if (!fn) return;
|
||||||
|
say(`Usage: prosperon ${fn.usage}`);
|
||||||
|
say(fn.doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cmdline.register_order("help", function(order) {
|
||||||
|
|
||||||
|
if (!Object.empty(order)) {
|
||||||
|
var orfn = Cmdline.orders[order];
|
||||||
|
|
||||||
|
if (!orfn) {
|
||||||
|
console.warn(`No command named ${order}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cmdline.print_order(orfn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cmdline.print_order("help");
|
||||||
|
|
||||||
|
for (var cmd of Object.keys(Cmdline.orders).sort())
|
||||||
|
say(cmd);
|
||||||
|
|
||||||
|
Cmdline.orders.version();
|
||||||
|
}, "Give help with a specific command.", "TOPIC");
|
||||||
|
|
||||||
|
Cmdline.register_order("version", function() {
|
||||||
|
say(`Prosperon version ${prosperon.version} [${prosperon.revision}]`);
|
||||||
|
}, "Display Prosperon info.");
|
||||||
|
|
||||||
function cmd_args(cmdargs)
|
function cmd_args(cmdargs)
|
||||||
{
|
{
|
||||||
var play = false;
|
var play = false;
|
||||||
var cmds = cmdargs.split(" ");
|
var cmds = cmdargs.split(/\s+/).slice(1);
|
||||||
|
|
||||||
|
if (cmds.length === 0)
|
||||||
|
cmds[0] = "play";
|
||||||
|
else if (!Cmdline.orders[cmds[0]]) {
|
||||||
|
console.warn(`Command ${cmds[0]} not found.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cmdline.orders[cmds[0]](cmds.slice(1));
|
||||||
|
return;
|
||||||
|
|
||||||
for (var i = 1; i < cmds.length; i++) {
|
for (var i = 1; i < cmds.length; i++) {
|
||||||
if (cmds[i][0] !== '-') {
|
if (cmds[i][0] !== '-') {
|
||||||
|
@ -256,51 +419,10 @@ STD.exit = function(status)
|
||||||
{
|
{
|
||||||
cmd(147,status);
|
cmd(147,status);
|
||||||
}
|
}
|
||||||
Cmdline.register_cmd("p", function() { Game.edit = false; }, "Launch engine in play mode.");
|
|
||||||
Cmdline.register_cmd("v", function() { Log.say(cmd(120)); STD.exit(0);}, "Display engine info.");
|
|
||||||
Cmdline.register_cmd("l", function(n) {
|
Cmdline.register_cmd("l", function(n) {
|
||||||
Log.level = n;
|
Log.level = n;
|
||||||
}, "Set log level.");
|
}, "Set log level.");
|
||||||
Cmdline.register_cmd("h", function(str) {
|
|
||||||
for (var cmd of Cmdline.cmds) {
|
|
||||||
Log.say(`-${cmd.flag}: ${cmd.doc}`);
|
|
||||||
}
|
|
||||||
STD.exit(0);
|
|
||||||
},
|
|
||||||
"Help.");
|
|
||||||
Cmdline.register_cmd("b", function(str) {
|
|
||||||
var packname;
|
|
||||||
if (str.length === 0)
|
|
||||||
packname = "test.cdb";
|
|
||||||
else if (str.length > 1) {
|
|
||||||
Log.warn("Give me a single filename for the pack.");
|
|
||||||
Game.quit();
|
|
||||||
} else
|
|
||||||
packname = str[0];
|
|
||||||
|
|
||||||
Log.warn(`Packing into ${packname}`);
|
|
||||||
|
|
||||||
cmd(124, packname);
|
|
||||||
STD.exit(0);
|
|
||||||
}, "Pack the game into the given name.");
|
|
||||||
|
|
||||||
Cmdline.register_cmd("e", function(pawn) {
|
|
||||||
load("scripts/editor.js");
|
|
||||||
Log.write(`## Input for ${pawn}\n`);
|
|
||||||
eval(`Log.write(Input.print_md_kbm(${pawn}));`);
|
|
||||||
STD.exit(0);
|
|
||||||
}, "Print input documentation for a given object in a markdown table." );
|
|
||||||
|
|
||||||
Cmdline.register_cmd("t", function() {
|
|
||||||
Log.warn("Testing not implemented yet.");
|
|
||||||
STD.exit(0);
|
|
||||||
}, "Test suite.");
|
|
||||||
|
|
||||||
Cmdline.register_cmd("d", function(obj) {
|
|
||||||
load("scripts/editor.js");
|
|
||||||
Log.say(API.print_doc(obj[0]));
|
|
||||||
STD.exit(0);
|
|
||||||
}, "Print documentation for an object.");
|
|
||||||
|
|
||||||
Cmdline.register_cmd("cjson", function(json) {
|
Cmdline.register_cmd("cjson", function(json) {
|
||||||
var f = json[0];
|
var f = json[0];
|
||||||
|
@ -329,9 +451,3 @@ Cmdline.register_cmd("cjson", function(json) {
|
||||||
|
|
||||||
STD.exit(0);
|
STD.exit(0);
|
||||||
}, "Clean up a jso file.");
|
}, "Clean up a jso file.");
|
||||||
|
|
||||||
Cmdline.register_cmd("r", function(script) {
|
|
||||||
try { run(script); } catch(e) { STD.exit(0); }
|
|
||||||
|
|
||||||
STD.exit(0);
|
|
||||||
}, "Run a script.");
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef CIRCBUF_H
|
#ifndef CIRCBUF_H
|
||||||
#define CIRCBUF_H
|
#define CIRCBUF_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
static inline unsigned int powof2(unsigned int x)
|
static inline unsigned int powof2(unsigned int x)
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include <sokol/sokol_time.h>
|
#include <sokol/sokol_time.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "nota.h"
|
#include "nota.h"
|
||||||
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
@ -1081,9 +1084,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
ret = JS_NewInt64(js, file_mod_secs(str));
|
ret = JS_NewInt64(js, file_mod_secs(str));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 120:
|
|
||||||
ret = str2js(engine_info());
|
|
||||||
break;
|
|
||||||
case 121:
|
case 121:
|
||||||
ret = number2js(get_timescale());
|
ret = number2js(get_timescale());
|
||||||
break;
|
break;
|
||||||
|
@ -1194,7 +1194,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 147:
|
case 147:
|
||||||
YughWarn("EXITING");
|
|
||||||
exit(js2int(argv[1]));
|
exit(js2int(argv[1]));
|
||||||
break;
|
break;
|
||||||
case 148:
|
case 148:
|
||||||
|
@ -1435,6 +1434,34 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
case 254:
|
case 254:
|
||||||
ret = warp_damp2js(warp_damp_make());
|
ret = warp_damp2js(warp_damp_make());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 255:
|
||||||
|
ret = str2js(VER);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 256:
|
||||||
|
ret = str2js(COM);
|
||||||
|
break;
|
||||||
|
case 257:
|
||||||
|
engine_start(argv[1]);
|
||||||
|
break;
|
||||||
|
case 258:
|
||||||
|
str = js2str(argv[1]);
|
||||||
|
ret = int2js(mkdir(str, 0777));
|
||||||
|
break;
|
||||||
|
case 259:
|
||||||
|
script_gc();
|
||||||
|
break;
|
||||||
|
case 260:
|
||||||
|
str = js2str(argv[1]);
|
||||||
|
d1 = script_compile(str, &plen);
|
||||||
|
ret = JS_NewArrayBufferCopy(js, d1, plen);
|
||||||
|
break;
|
||||||
|
case 261:
|
||||||
|
str = js2str(argv[1]);
|
||||||
|
d1 = slurp_file(str, &plen);
|
||||||
|
return script_run_bytecode(d1, plen);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str) JS_FreeCString(js, str);
|
if (str) JS_FreeCString(js, str);
|
||||||
|
@ -1816,7 +1843,6 @@ GETSET_PAIR(warp_gravity, planar_force, vec3)
|
||||||
|
|
||||||
#define MIST_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
|
#define MIST_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
|
||||||
|
|
||||||
|
|
||||||
#define CGETSET_ADD(ID, ENTRY) MIST_CGETSET_DEF(#ENTRY, ID##_get_##ENTRY, ID##_set_##ENTRY)
|
#define CGETSET_ADD(ID, ENTRY) MIST_CGETSET_DEF(#ENTRY, ID##_get_##ENTRY, ID##_set_##ENTRY)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_warp_gravity_funcs [] = {
|
static const JSCFunctionListEntry js_warp_gravity_funcs [] = {
|
||||||
|
@ -1873,6 +1899,10 @@ JSValue js_emitter_emit(JSContext *js, JSValueConst this, int argc, JSValue *arg
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_global_funcs[] = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_emitter_funcs[] = {
|
static const JSCFunctionListEntry js_emitter_funcs[] = {
|
||||||
CGETSET_ADD(emitter, life),
|
CGETSET_ADD(emitter, life),
|
||||||
CGETSET_ADD(emitter, life_var),
|
CGETSET_ADD(emitter, life_var),
|
||||||
|
|
|
@ -26,7 +26,7 @@ JSRuntime *rt = NULL;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT
|
||||||
#else
|
#else
|
||||||
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT// | JS_EVAL_FLAG_STRIP
|
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -76,8 +76,11 @@ void script_stop()
|
||||||
ffi_stop();
|
ffi_stop();
|
||||||
for (int i = 0; i < shlen(jsstrs); i++)
|
for (int i = 0; i < shlen(jsstrs); i++)
|
||||||
JS_FreeValue(js,jsstrs[i].value);
|
JS_FreeValue(js,jsstrs[i].value);
|
||||||
|
|
||||||
|
#if LEAK
|
||||||
JS_FreeContext(js);
|
JS_FreeContext(js);
|
||||||
JS_FreeRuntime(rt);
|
JS_FreeRuntime(rt);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_gc()
|
void script_gc()
|
||||||
|
@ -134,16 +137,25 @@ void script_evalf(const char *format, ...)
|
||||||
JS_FreeValue(js,obj);
|
JS_FreeValue(js,obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *compile_script(const char *file, size_t *len) {
|
uint8_t *script_compile(const char *file, size_t *len) {
|
||||||
char *script = slurp_text(file, len);
|
size_t file_len;
|
||||||
JSValue obj = JS_Eval(js, script, *len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS);
|
char *script = slurp_text(file, &file_len);
|
||||||
|
JSValue obj = JS_Eval(js, script, file_len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS);
|
||||||
free(script);
|
free(script);
|
||||||
size_t out_len;
|
uint8_t *out = JS_WriteObject(js, len, obj, JS_WRITE_OBJ_BYTECODE);
|
||||||
uint8_t *out = JS_WriteObject(js, &out_len, obj, JS_WRITE_OBJ_BYTECODE);
|
|
||||||
JS_FreeValue(js,obj);
|
JS_FreeValue(js,obj);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue script_run_bytecode(uint8_t *code, size_t len)
|
||||||
|
{
|
||||||
|
JSValue b = JS_ReadObject(js, code, len, JS_READ_OBJ_BYTECODE);
|
||||||
|
JSValue ret = JS_EvalFunction(js, b);
|
||||||
|
js_print_exception(ret);
|
||||||
|
JS_FreeValue(js,b);
|
||||||
|
JS_FreeValue(js,ret);
|
||||||
|
}
|
||||||
|
|
||||||
struct callee stacktrace_callee;
|
struct callee stacktrace_callee;
|
||||||
|
|
||||||
time_t file_mod_secs(const char *file) {
|
time_t file_mod_secs(const char *file) {
|
||||||
|
@ -265,7 +277,7 @@ void script_call_fn_arg(JSValue fn, JSValue arg)
|
||||||
|
|
||||||
void out_memusage(const char *file)
|
void out_memusage(const char *file)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(file, "w");
|
FILE *f = fopen_mkdir(file, "w");
|
||||||
JSMemoryUsage jsmem;
|
JSMemoryUsage jsmem;
|
||||||
JS_ComputeMemoryUsage(rt, &jsmem);
|
JS_ComputeMemoryUsage(rt, &jsmem);
|
||||||
JS_DumpMemoryUsage(f, &jsmem, rt);
|
JS_DumpMemoryUsage(f, &jsmem, rt);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#define SCRIPT_H
|
#define SCRIPT_H
|
||||||
|
|
||||||
#include "quickjs/quickjs.h"
|
#include "quickjs/quickjs.h"
|
||||||
#include <chipmunk/chipmunk.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
extern JSContext *js;
|
extern JSContext *js;
|
||||||
|
@ -67,12 +66,15 @@ void call_nk_gui();
|
||||||
void unregister_obj(JSValue obj);
|
void unregister_obj(JSValue obj);
|
||||||
|
|
||||||
void send_signal(const char *signal, int argc, JSValue *argv);
|
void send_signal(const char *signal, int argc, JSValue *argv);
|
||||||
|
void script_gc();
|
||||||
|
|
||||||
void register_physics(struct callee c);
|
void register_physics(struct callee c);
|
||||||
void call_physics(double dt);
|
void call_physics(double dt);
|
||||||
|
|
||||||
void register_draw(struct callee c);
|
void register_draw(struct callee c);
|
||||||
void call_draw();
|
void call_draw();
|
||||||
uint8_t *compile_script(const char *file, size_t *len);
|
|
||||||
|
JSValue script_run_bytecode(uint8_t *code, size_t len);
|
||||||
|
uint8_t *script_compile(const char *file, size_t *len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,15 @@ warp_damp *warp_damp_make()
|
||||||
}
|
}
|
||||||
|
|
||||||
void warp_damp_free(warp_damp *d) { free(d); }
|
void warp_damp_free(warp_damp *d) { free(d); }
|
||||||
void warp_gravity_free(warp_gravity *n) { free(n); }
|
void warp_gravity_free(warp_gravity *n) {
|
||||||
|
for (int i = 0; i < arrlen(warps); i++) {
|
||||||
|
if (warps[i] == n) {
|
||||||
|
arrdelswap(warps, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(n);
|
||||||
|
}
|
||||||
|
|
||||||
HMM_Vec3 warp_damp_force(warp_damp *d, HMM_Vec3 pos, HMM_Vec3 vel)
|
HMM_Vec3 warp_damp_force(warp_damp *d, HMM_Vec3 pos, HMM_Vec3 vel)
|
||||||
{
|
{
|
||||||
|
|
|
@ -81,10 +81,6 @@ static int sim_play = SIM_PLAY;
|
||||||
|
|
||||||
int editor_mode = 0;
|
int editor_mode = 0;
|
||||||
|
|
||||||
#define ENGINEINFO "Yugine version " VER ", " INFO " build.\nCopyright 2022-2024."
|
|
||||||
|
|
||||||
const char *engine_info() { return ENGINEINFO; }
|
|
||||||
|
|
||||||
static int argc;
|
static int argc;
|
||||||
static char **args;
|
static char **args;
|
||||||
|
|
||||||
|
@ -94,17 +90,18 @@ void seghandle()
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void c_init() {
|
static JSValue c_init_fn;
|
||||||
|
|
||||||
|
void c_init() {
|
||||||
input_init();
|
input_init();
|
||||||
script_evalf("world_start();");
|
script_evalf("world_start();");
|
||||||
|
|
||||||
render_init();
|
render_init();
|
||||||
window_set_icon("icons/moon.gif");
|
window_set_icon("icons/moon.gif");
|
||||||
window_resize(sapp_width(), sapp_height());
|
window_resize(sapp_width(), sapp_height());
|
||||||
script_evalf("Game.init();");
|
|
||||||
|
|
||||||
particle_init();
|
particle_init();
|
||||||
|
|
||||||
|
if (!JS_IsUndefined(c_init_fn))
|
||||||
|
script_call_sym(c_init_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int frame_fps() { return 1.0/sapp_frame_duration(); }
|
int frame_fps() { return 1.0/sapp_frame_duration(); }
|
||||||
|
@ -158,7 +155,7 @@ void c_frame()
|
||||||
|
|
||||||
void c_clean() {
|
void c_clean() {
|
||||||
gif_rec_end("out.gif");
|
gif_rec_end("out.gif");
|
||||||
out_memusage("jsmem.txt");
|
out_memusage(".prosperon/jsmem.txt");
|
||||||
script_stop();
|
script_stop();
|
||||||
saudio_shutdown();
|
saudio_shutdown();
|
||||||
sg_shutdown();
|
sg_shutdown();
|
||||||
|
@ -250,7 +247,7 @@ static sapp_desc start_desc = {
|
||||||
.high_dpi = 0,
|
.high_dpi = 0,
|
||||||
.sample_count = 1,
|
.sample_count = 1,
|
||||||
.fullscreen = 1,
|
.fullscreen = 1,
|
||||||
.window_title = "Primum Machinam",
|
.window_title = "Prosperon",
|
||||||
.enable_clipboard = false,
|
.enable_clipboard = false,
|
||||||
.clipboard_size = 0,
|
.clipboard_size = 0,
|
||||||
.enable_dragndrop = true,
|
.enable_dragndrop = true,
|
||||||
|
@ -303,12 +300,8 @@ sprintf(da.details, "COMPetitive");
|
||||||
dam->update_activity(dam, &da, NULL, NULL);
|
dam->update_activity(dam, &da, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stm_setup(); /* time */
|
|
||||||
start_t = frame_t = stm_now();
|
|
||||||
physlast = updatelast = start_t;
|
|
||||||
sound_init();
|
|
||||||
resources_init();
|
resources_init();
|
||||||
phys2d_init();
|
|
||||||
script_startup();
|
script_startup();
|
||||||
|
|
||||||
int argsize = 0;
|
int argsize = 0;
|
||||||
|
@ -324,15 +317,27 @@ dam->update_activity(dam, &da, NULL, NULL);
|
||||||
strcat(cmdstr, argv[i]);
|
strcat(cmdstr, argv[i]);
|
||||||
if (argc > i+1) strcat(cmdstr, " ");
|
if (argc > i+1) strcat(cmdstr, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
script_evalf("cmd_args('%s');", cmdstr);
|
script_evalf("cmd_args('%s');", cmdstr);
|
||||||
|
|
||||||
|
out_memusage(".prosperon/jsmem.txt");
|
||||||
|
script_stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void engine_start(JSValue fn)
|
||||||
|
{
|
||||||
|
c_init_fn = fn;
|
||||||
|
stm_setup(); /* time */
|
||||||
|
start_t = frame_t = stm_now();
|
||||||
|
physlast = updatelast = start_t;
|
||||||
|
sound_init();
|
||||||
|
phys2d_init();
|
||||||
|
|
||||||
start_desc.width = mainwin.width;
|
start_desc.width = mainwin.width;
|
||||||
start_desc.height = mainwin.height;
|
start_desc.height = mainwin.height;
|
||||||
start_desc.fullscreen = 0;
|
start_desc.fullscreen = 0;
|
||||||
sapp_run(&start_desc);
|
sapp_run(&start_desc);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double apptime() { return stm_sec(stm_diff(stm_now(), start_t)); }
|
double apptime() { return stm_sec(stm_diff(stm_now(), start_t)); }
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef YUGINE_H
|
#ifndef YUGINE_H
|
||||||
#define YUGINE_H
|
#define YUGINE_H
|
||||||
|
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
int sim_playing();
|
int sim_playing();
|
||||||
int sim_paused();
|
int sim_paused();
|
||||||
void sim_start();
|
void sim_start();
|
||||||
|
@ -10,9 +12,8 @@ void sim_step();
|
||||||
int phys_stepping();
|
int phys_stepping();
|
||||||
void set_timescale(float val);
|
void set_timescale(float val);
|
||||||
void print_stacktrace();
|
void print_stacktrace();
|
||||||
void yugine_init();
|
void engine_start(JSValue fn); /* fn runs after the engine starts */
|
||||||
|
|
||||||
const char *engine_info();
|
|
||||||
void app_name(const char *name);
|
void app_name(const char *name);
|
||||||
|
|
||||||
int frame_fps();
|
int frame_fps();
|
||||||
|
|
Loading…
Reference in a new issue