separate input and events; pull camera out of render
This commit is contained in:
@@ -5,7 +5,12 @@ With Javascript's C-like syntax, it makes it easy to make classic style games li
|
|||||||
# API usage
|
# API usage
|
||||||
A lot of the API usage is informed from 'duck typing'. If something "looks" like a camera - it can be used like one! If something "looks" like a sprite, it can be used like one! There are fast paths on nearly everything for well defined objects
|
A lot of the API usage is informed from 'duck typing'. If something "looks" like a camera - it can be used like one! If something "looks" like a sprite, it can be used like one! There are fast paths on nearly everything for well defined objects
|
||||||
|
|
||||||
Uniformity is prioritized.
|
Uniformity is prioritized. Javascript allows for a powerful abstraction - the object - which Prosperon makes much use of. It allows for another - the arraybuffer - which makes it simple to plug different parts of the engine into each other.
|
||||||
|
|
||||||
|
The object is the lingua franca of the API. For example, json.encode and json.decode converts objects to and fromt json strings; nota.encode and nota.decode converts objects to and from nota bytes, represented as a javascript arraybuffer. To convert a json string to a nota buffer, one would do:
|
||||||
|
nota.encode(json.decode(str))
|
||||||
|
|
||||||
|
Most functions take objects just like this, increasing flexibility for what you can send into functions.
|
||||||
|
|
||||||
# Gradual performance
|
# Gradual performance
|
||||||
Prosperon makes it easy to make something quickly, and if it runs well, you're golden! But if it's slow, there are a plethora of options to make it faster. Plus, with native C plugins, there is nothing that can't be figured out.
|
Prosperon makes it easy to make something quickly, and if it runs well, you're golden! But if it's slow, there are a plethora of options to make it faster. Plus, with native C plugins, there is nothing that can't be figured out.
|
||||||
@@ -14,42 +19,64 @@ Prosperon makes it easy to make something quickly, and if it runs well, you're g
|
|||||||
~~prosperon master
|
~~prosperon master
|
||||||
Here are the modules that can be included via 'use'.
|
Here are the modules that can be included via 'use'.
|
||||||
|
|
||||||
|
// extensions
|
||||||
|
Object.id - get a unique id for the given javascript object
|
||||||
|
|
||||||
// global syntax level things
|
// global syntax level things
|
||||||
|
Globals have been kept to a minimum to ensure game objects are as flexible as possible in what they can call their state. The vast majority of access to prosperon is done through the 'use' statement.
|
||||||
|
use - import a module
|
||||||
|
on actors: /* look to web windows for a comparison */
|
||||||
|
- spawn: create a new actor
|
||||||
|
- delay: execute a function after seconds
|
||||||
|
-
|
||||||
|
|
||||||
|
prosperon global object; information about the engine; process related (ie, if there are multiple threads running, prosperon will be different in each, os will be the same)
|
||||||
|
- version: 0.6.1
|
||||||
|
- revision: git revision
|
||||||
|
- argv: the string of arguments passed to the process
|
||||||
|
- semver: functions to compare use
|
||||||
|
|
||||||
// core
|
os - sys calls; information about the underlying hardware
|
||||||
prosperon
|
js - information about the scripting language; gc functions; etc
|
||||||
input
|
|
||||||
json
|
// mixed in
|
||||||
layout
|
base
|
||||||
resources
|
|
||||||
sound
|
|
||||||
std
|
std
|
||||||
time
|
|
||||||
search
|
// core use fns
|
||||||
color
|
input - user input settings
|
||||||
tween
|
json - json encoding and decoding
|
||||||
util
|
resources - access resources
|
||||||
io
|
sound - play sounds
|
||||||
os
|
time - time access
|
||||||
|
actor - actor helpers
|
||||||
|
color - color constants
|
||||||
|
tween - helper to tween
|
||||||
|
util - random helpers
|
||||||
|
io - file system access, mounting, unmounting
|
||||||
|
event - system events
|
||||||
|
|
||||||
|
math - math help
|
||||||
|
geometry - geometry help
|
||||||
|
|
||||||
// rendering
|
// rendering
|
||||||
draw2d
|
draw2d - immediate mode draw 2d stuff functions
|
||||||
render
|
render - render configuration and use; shaders, pipelines, render state.
|
||||||
graphics
|
graphics - create graphics objects (textures, fonts, etc); memory usage of fonts, textures, etc.
|
||||||
|
|
||||||
// game components
|
|
||||||
emitter
|
|
||||||
sprite
|
|
||||||
transform
|
|
||||||
|
|
||||||
// math
|
|
||||||
pmath
|
|
||||||
vector
|
|
||||||
geometry
|
|
||||||
|
|
||||||
|
// game component modules
|
||||||
|
emitter - particle drawing helper
|
||||||
|
sprite - sprite drawing helper
|
||||||
|
transform - helper to turn programs into transforms
|
||||||
|
layout - a gui layout helper
|
||||||
|
imgui - add for imgui calls
|
||||||
|
controller - higher level controller based on events
|
||||||
|
|
||||||
~~prosperon dev
|
~~prosperon dev
|
||||||
|
nota
|
||||||
|
dmon
|
||||||
|
enet
|
||||||
|
|
||||||
convert
|
convert
|
||||||
debug
|
debug
|
||||||
diff
|
diff
|
||||||
@@ -69,4 +96,5 @@ yaml
|
|||||||
spline
|
spline
|
||||||
profile
|
profile
|
||||||
sim
|
sim
|
||||||
dmon
|
|
||||||
|
noise // using stb perlin
|
||||||
@@ -110,7 +110,7 @@ if get_option('enet')
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','yugine.c', 'wildmatch.c', 'sprite.c', 'quadtree.c', 'aabb.c', 'rtree.c']
|
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'quadtree.c', 'aabb.c', 'rtree.c']
|
||||||
|
|
||||||
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp', 'imgui_impl_sdlrenderer3.cpp', 'imgui_impl_sdl3.cpp', 'imgui_impl_sdlgpu3.cpp']
|
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp', 'imgui_impl_sdlrenderer3.cpp', 'imgui_impl_sdl3.cpp', 'imgui_impl_sdlgpu3.cpp']
|
||||||
|
|
||||||
|
|||||||
@@ -338,10 +338,8 @@ Cmdline.register_order(
|
|||||||
"Display Prosperon info.",
|
"Display Prosperon info.",
|
||||||
);
|
);
|
||||||
|
|
||||||
function cmd_args(cmdargs) {
|
function cmd_args(cmds) {
|
||||||
var play = false;
|
var play = false;
|
||||||
var cmds = cmdargs.split(/\s+/).slice(1);
|
|
||||||
|
|
||||||
if (cmds.length === 0) cmds[0] = "play";
|
if (cmds.length === 0) cmds[0] = "play";
|
||||||
else if (!Cmdline.orders[cmds[0]]) {
|
else if (!Cmdline.orders[cmds[0]]) {
|
||||||
console.warn(`Command ${cmds[0]} not found. Playing instead.`);
|
console.warn(`Command ${cmds[0]} not found. Playing instead.`);
|
||||||
@@ -420,4 +418,4 @@ function convertYAMLtoJSON(yamlString) {
|
|||||||
return jsonObj;
|
return jsonObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {cmd_args}
|
return cmd_args;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
var render = use('render')
|
var render = use('render')
|
||||||
var graphics = use('graphics')
|
var graphics = use('graphics')
|
||||||
var math = use('math')
|
var math = use('math')
|
||||||
|
var util = use('util')
|
||||||
|
|
||||||
var base_pipeline = {
|
var base_pipeline = {
|
||||||
vertex: "sprite.vert",
|
vertex: "sprite.vert",
|
||||||
@@ -54,7 +55,6 @@ var base_pipeline = {
|
|||||||
target: {}
|
target: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var sprite_pipeline = Object.create(base_pipeline);
|
var sprite_pipeline = Object.create(base_pipeline);
|
||||||
sprite_pipeline.blend = {
|
sprite_pipeline.blend = {
|
||||||
enabled:true,
|
enabled:true,
|
||||||
@@ -88,7 +88,7 @@ draw.point = function (pos, size, color = Color.blue) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
draw.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) {
|
draw.line = function render_line(points, color = Color.white, thickness = 1, pipeline = rect_pipeline) {
|
||||||
var mesh = os.make_line_prim(points,thickness, 0,0,color);
|
var mesh = graphics.make_line_prim(points,thickness, 0,0,color);
|
||||||
render.queue({
|
render.queue({
|
||||||
type: 'geometry',
|
type: 'geometry',
|
||||||
mesh,
|
mesh,
|
||||||
@@ -157,7 +157,7 @@ draw.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.whit
|
|||||||
if (typeof image === "string")
|
if (typeof image === "string")
|
||||||
image = graphics.texture(image);
|
image = graphics.texture(image);
|
||||||
|
|
||||||
var mesh = render._main.slice9(image.texture, rect, gizmo.normalizeSpacing(slice), info);
|
var mesh = render._main.slice9(image.texture, rect, util.normalizeSpacing(slice), info);
|
||||||
render.queue({
|
render.queue({
|
||||||
type: 'geometry',
|
type: 'geometry',
|
||||||
mesh,
|
mesh,
|
||||||
@@ -188,7 +188,7 @@ draw.image = function image(image, rect = [0,0], rotation = 0, color, pipeline)
|
|||||||
if (color) cmd.color = color;
|
if (color) cmd.color = color;
|
||||||
render.queue(cmd)
|
render.queue(cmd)
|
||||||
|
|
||||||
var sprite = os.make_sprite();
|
var sprite = graphics.make_sprite();
|
||||||
sprite.set_image(image);
|
sprite.set_image(image);
|
||||||
sprite.set_rect(rect);
|
sprite.set_rect(rect);
|
||||||
return sprite;
|
return sprite;
|
||||||
@@ -207,14 +207,14 @@ draw.images = function images(image, rects, config)
|
|||||||
for (var rect of rects) {
|
for (var rect of rects) {
|
||||||
// get sprite from sprite_buf, or make a new one
|
// get sprite from sprite_buf, or make a new one
|
||||||
rect.__proto__ = bb;
|
rect.__proto__ = bb;
|
||||||
var sprite = os.make_sprite();
|
var sprite = graphics.make_sprite();
|
||||||
sprite.set_rect(rect);
|
sprite.set_rect(rect);
|
||||||
sprite.set_image(image);
|
sprite.set_image(image);
|
||||||
sprites.push(sprite)
|
sprites.push(sprite)
|
||||||
}
|
}
|
||||||
|
|
||||||
// var sprites = os.rects_to_sprites(image,rects);
|
// var sprites = graphics.rects_to_sprites(image,rects);
|
||||||
var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, sprite_pipeline)
|
var cmds = graphics.make_sprite_queue(sprites, prosperon.camera, sprite_pipeline)
|
||||||
for (var i = 0; i < cmds.length; i++)
|
for (var i = 0; i < cmds.length; i++)
|
||||||
render.queue(cmds[i])
|
render.queue(cmds[i])
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ draw.images = function images(image, rects, config)
|
|||||||
|
|
||||||
draw.sprites = function(sprites, sort = 0, pipeline = sprite_pipeline)
|
draw.sprites = function(sprites, sort = 0, pipeline = sprite_pipeline)
|
||||||
{
|
{
|
||||||
var cmds = render._main.make_sprite_queue(sprites, prosperon.camera, pipeline, sort);
|
var cmds = graphics.make_sprite_queue(sprites, prosperon.camera, pipeline, sort);
|
||||||
for (var i = 0; i < cmds.length; i++)
|
for (var i = 0; i < cmds.length; i++)
|
||||||
render.queue(cmds[i]);
|
render.queue(cmds[i]);
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ var sysfont = graphics.get_font('fonts/c64.ttf', 8);
|
|||||||
draw.text = function text(text, rect, font = sysfont, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) {
|
draw.text = function text(text, rect, font = sysfont, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) {
|
||||||
if (typeof font === 'string')
|
if (typeof font === 'string')
|
||||||
font = graphics.get_font(font)
|
font = graphics.get_font(font)
|
||||||
var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font);
|
var mesh = graphics.make_text_buffer(text, rect, 0, color, wrap, font);
|
||||||
|
|
||||||
render.queue({
|
render.queue({
|
||||||
type: 'geometry',
|
type: 'geometry',
|
||||||
@@ -250,4 +250,6 @@ draw.text = function text(text, rect, font = sysfont, size = 0, color = Color.wh
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
draw.sprite_pipeline = sprite_pipeline;
|
||||||
|
|
||||||
return draw
|
return draw
|
||||||
|
|||||||
@@ -1,10 +1,42 @@
|
|||||||
globalThis.prosperon = {}
|
// set up events on prosperon
|
||||||
var os = use_embed('os')
|
var listeners = new Map()
|
||||||
|
prosperon.on = function(type, callback)
|
||||||
|
{
|
||||||
|
if (!listeners.has(type)) listeners.set(type, [])
|
||||||
|
listeners.get(type).push(callback)
|
||||||
|
|
||||||
prosperon.SIGINT = function() {
|
return function() {
|
||||||
os.exit();
|
var arr = listeners.get(type)
|
||||||
|
if (!arr) return
|
||||||
|
var idx = arr.indexOf(callback)
|
||||||
|
if (idx >= 0) arr.splice(idx,1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prosperon.dispatch = function(type, data)
|
||||||
|
{
|
||||||
|
var arr = listeners.get(type)
|
||||||
|
if (!arr) return
|
||||||
|
for (var callback of arr) callback(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
var os = use_embed('os')
|
||||||
|
var js = use_embed('js')
|
||||||
|
|
||||||
|
prosperon.on('SIGINT', function() {
|
||||||
|
os.exit();
|
||||||
|
})
|
||||||
|
|
||||||
|
prosperon.on('SIGABRT', function() {
|
||||||
|
console.error(new Error('SIGABRT'));
|
||||||
|
os.exit(1);
|
||||||
|
})
|
||||||
|
|
||||||
|
prosperon.on('SIGSEGV', function() {
|
||||||
|
console.error(new Error('SIGSEGV'));
|
||||||
|
os.exit(1);
|
||||||
|
})
|
||||||
|
|
||||||
var use_cache = {}
|
var use_cache = {}
|
||||||
|
|
||||||
Object.defineProperty(Function.prototype, "hashify", {
|
Object.defineProperty(Function.prototype, "hashify", {
|
||||||
@@ -28,11 +60,10 @@ io.mount("core")
|
|||||||
|
|
||||||
var canonical = io.realdir('resources.js') + 'resources.js'
|
var canonical = io.realdir('resources.js') + 'resources.js'
|
||||||
var content = io.slurp('resources.js')
|
var content = io.slurp('resources.js')
|
||||||
var resources = os.eval('resources.js', `(function setup_resources(){${content}})`).call({})
|
var resources = js.eval('resources.js', `(function setup_resources(){${content}})`).call({})
|
||||||
console.print(resources.canonical('resources.js'))
|
console.print(resources.canonical('resources.js'))
|
||||||
use_cache[resources.canonical('resources.js')] = resources
|
use_cache[resources.canonical('resources.js')] = resources
|
||||||
|
|
||||||
|
|
||||||
function print_api(obj) {
|
function print_api(obj) {
|
||||||
for (var prop in obj) {
|
for (var prop in obj) {
|
||||||
if (!obj.hasOwnProperty(prop)) continue
|
if (!obj.hasOwnProperty(prop)) continue
|
||||||
@@ -65,7 +96,7 @@ var script_fn = function script_fn(path) {
|
|||||||
|
|
||||||
if (parsed.module) {
|
if (parsed.module) {
|
||||||
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports: exports}; var define = undefined; ${parsed.module}})`;
|
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports: exports}; var define = undefined; ${parsed.module}})`;
|
||||||
var module_fn = os.eval(file, mod_script);
|
var module_fn = js.eval(file, mod_script);
|
||||||
parsed.module_ret = module_fn.call(parsed.module_ret);
|
parsed.module_ret = module_fn.call(parsed.module_ret);
|
||||||
if (parsed.module_ret === undefined || parsed.module_ret === null)
|
if (parsed.module_ret === undefined || parsed.module_ret === null)
|
||||||
throw new Error(`Module ${module_name} must return a value`);
|
throw new Error(`Module ${module_name} must return a value`);
|
||||||
@@ -76,7 +107,7 @@ var script_fn = function script_fn(path) {
|
|||||||
|
|
||||||
if (parsed.program) {
|
if (parsed.program) {
|
||||||
var prog_script = `(function use_${module_name}() { var self = this; var $ = this.__proto__; ${parsed.program}})`;
|
var prog_script = `(function use_${module_name}() { var self = this; var $ = this.__proto__; ${parsed.program}})`;
|
||||||
parsed.prog_fn = os.eval(file, prog_script);
|
parsed.prog_fn = js.eval(file, prog_script);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
@@ -183,19 +214,7 @@ console.doc = {
|
|||||||
var script = io.slurp("core/scripts/base.js")
|
var script = io.slurp("core/scripts/base.js")
|
||||||
var fnname = "base"
|
var fnname = "base"
|
||||||
script = `(function ${fnname}() { ${script}; })`
|
script = `(function ${fnname}() { ${script}; })`
|
||||||
os.eval('core/scripts/base.js', script)()
|
js.eval('core/scripts/base.js', script)()
|
||||||
|
|
||||||
prosperon.SIGABRT = function()
|
|
||||||
{
|
|
||||||
console.error(new Error('SIGABRT'));
|
|
||||||
os.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
prosperon.SIGSEGV = function()
|
|
||||||
{
|
|
||||||
console.error(new Error('SIGSEGV'));
|
|
||||||
os.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_timer(obj, fn, seconds)
|
function add_timer(obj, fn, seconds)
|
||||||
{
|
{
|
||||||
@@ -240,7 +259,7 @@ var OVERLING = Symbol()
|
|||||||
var actor = {};
|
var actor = {};
|
||||||
|
|
||||||
var so_ext;
|
var so_ext;
|
||||||
switch(os.sys()) {
|
switch(os.platform()) {
|
||||||
case 'Windows':
|
case 'Windows':
|
||||||
so_ext = '.dll';
|
so_ext = '.dll';
|
||||||
break;
|
break;
|
||||||
@@ -471,7 +490,7 @@ try{
|
|||||||
|
|
||||||
this[UNDERLINGS].add(underling);
|
this[UNDERLINGS].add(underling);
|
||||||
if (underling.tag)
|
if (underling.tag)
|
||||||
search.tag_add(underling.tag, underling)
|
act.tag_add(underling.tag, underling)
|
||||||
|
|
||||||
underling[GARBAGE] = underling.garbage
|
underling[GARBAGE] = underling.garbage
|
||||||
return underling;
|
return underling;
|
||||||
@@ -501,7 +520,7 @@ actor.kill = function kill() {
|
|||||||
if (typeof this.garbage === "function") this.garbage();
|
if (typeof this.garbage === "function") this.garbage();
|
||||||
if (typeof this.then === "function") this.then();
|
if (typeof this.then === "function") this.then();
|
||||||
|
|
||||||
search.tag_clear_guid(this)
|
act.tag_clear_guid(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
actor.kill.doc = `Remove this actor and all its underlings from existence.`;
|
actor.kill.doc = `Remove this actor and all its underlings from existence.`;
|
||||||
@@ -509,9 +528,11 @@ actor.kill.doc = `Remove this actor and all its underlings from existence.`;
|
|||||||
actor.delay = function (fn, seconds) { add_timer(this, fn, seconds) }
|
actor.delay = function (fn, seconds) { add_timer(this, fn, seconds) }
|
||||||
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
||||||
|
|
||||||
var search = use('search')
|
var act = use('actor')
|
||||||
|
|
||||||
actor[UNDERLINGS] = new Set()
|
actor[UNDERLINGS] = new Set()
|
||||||
|
|
||||||
globalThis.mixin("color");
|
globalThis.mixin("color");
|
||||||
globalThis.mixin("std")
|
|
||||||
|
use('cmd')(prosperon.argv)
|
||||||
|
|
||||||
|
|||||||
5
scripts/event.js
Normal file
5
scripts/event.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
var event = this
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return event
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
var graphics = {}
|
var graphics = this
|
||||||
var os = use('os')
|
|
||||||
var io = use('io')
|
var io = use('io')
|
||||||
var res = use('resources')
|
var res = use('resources')
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ function create_image(path)
|
|||||||
var newimg;
|
var newimg;
|
||||||
switch(path.ext()) {
|
switch(path.ext()) {
|
||||||
case 'gif':
|
case 'gif':
|
||||||
newimg = os.make_gif(data);
|
newimg = graphics.make_gif(data);
|
||||||
if (newimg.surface)
|
if (newimg.surface)
|
||||||
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
||||||
else
|
else
|
||||||
@@ -24,7 +23,7 @@ function create_image(path)
|
|||||||
break;
|
break;
|
||||||
case 'ase':
|
case 'ase':
|
||||||
case 'aseprite':
|
case 'aseprite':
|
||||||
newimg = os.make_aseprite(data);
|
newimg = graphics.make_aseprite(data);
|
||||||
if (newimg.surface)
|
if (newimg.surface)
|
||||||
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
||||||
else {
|
else {
|
||||||
@@ -37,7 +36,7 @@ function create_image(path)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
newimg = {
|
newimg = {
|
||||||
surface: os.make_texture(data)
|
surface: graphics.make_texture(data)
|
||||||
};
|
};
|
||||||
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
newimg.texture = prosperon.gpu.load_texture(newimg.surface);
|
||||||
break;
|
break;
|
||||||
@@ -62,14 +61,14 @@ function pack_into_sheet(images)
|
|||||||
if (images[0].texture.width > 300 && images[0].texture.height > 300) return;
|
if (images[0].texture.width > 300 && images[0].texture.height > 300) return;
|
||||||
sheet_frames = sheet_frames.concat(images);
|
sheet_frames = sheet_frames.concat(images);
|
||||||
var sizes = sheet_frames.map(x => [x.rect.width*x.texture.width, x.rect.height*x.texture.height]);
|
var sizes = sheet_frames.map(x => [x.rect.width*x.texture.width, x.rect.height*x.texture.height]);
|
||||||
var pos = os.rectpack(sheetsize, sheetsize, sizes);
|
var pos = graphics.rectpack(sheetsize, sheetsize, sizes);
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
console.error(`did not make spritesheet properly from images ${images}`);
|
console.error(`did not make spritesheet properly from images ${images}`);
|
||||||
console.info(sizes);
|
console.info(sizes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newsheet = os.make_tex_data(sheetsize,sheetsize);
|
var newsheet = graphics.make_tex_data(sheetsize,sheetsize);
|
||||||
|
|
||||||
for (var i = 0; i < pos.length; i++) {
|
for (var i = 0; i < pos.length; i++) {
|
||||||
// Copy the texture to the new sheet
|
// Copy the texture to the new sheet
|
||||||
@@ -147,10 +146,10 @@ function make_spritesheet(paths, width, height)
|
|||||||
return
|
return
|
||||||
var textures = paths.map(path => graphics.texture(path));
|
var textures = paths.map(path => graphics.texture(path));
|
||||||
var sizes = textures.map(tex => [tex.width, tex.height]);
|
var sizes = textures.map(tex => [tex.width, tex.height]);
|
||||||
var pos = os.rectpack(width, height, sizes);
|
var pos = graphics.rectpack(width, height, sizes);
|
||||||
if (!pos) return;
|
if (!pos) return;
|
||||||
|
|
||||||
var sheet = os.make_tex_data(width,height);
|
var sheet = graphics.make_tex_data(width,height);
|
||||||
|
|
||||||
var st = profile.now();
|
var st = profile.now();
|
||||||
for (var i = 0; i < pos.length; i++)
|
for (var i = 0; i < pos.length; i++)
|
||||||
@@ -177,52 +176,23 @@ graphics.get_font = function get_font(path,size)
|
|||||||
if (fontcache[fontstr]) return fontcache[fontstr];
|
if (fontcache[fontstr]) return fontcache[fontstr];
|
||||||
|
|
||||||
var data = io.slurpbytes(fullpath);
|
var data = io.slurpbytes(fullpath);
|
||||||
fontcache[fontstr] = os.make_font(data,size);
|
fontcache[fontstr] = graphics.make_font(data,size);
|
||||||
fontcache[fontstr].texture = prosperon.gpu.load_texture(fontcache[fontstr].surface);
|
fontcache[fontstr].texture = prosperon.gpu.load_texture(fontcache[fontstr].surface);
|
||||||
return fontcache[fontstr];
|
return fontcache[fontstr];
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics.semver = {};
|
graphics.queue_sprite_mesh = function(queue)
|
||||||
graphics.semver.valid = function (v, range) {
|
{
|
||||||
v = v.split(".");
|
var sprites = queue.filter(x => x.type === 'sprite');
|
||||||
range = range.split(".");
|
if (sprites.length === 0) return [];
|
||||||
if (v.length !== 3) return undefined;
|
var mesh = graphics.make_sprite_mesh(sprites);
|
||||||
if (range.length !== 3) return undefined;
|
for (var i = 0; i < sprites.length; i++) {
|
||||||
|
sprites[i].mesh = mesh;
|
||||||
if (range[0][0] === "^") {
|
sprites[i].first_index = i*6;
|
||||||
range[0] = range[0].slice(1);
|
sprites[i].num_indices = 6;
|
||||||
if (parseInt(v[0]) >= parseInt(range[0])) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (range[0] === "~") {
|
return [mesh.pos,mesh.uv,mesh.color,mesh.indices]
|
||||||
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 graphics.semver.cmp(v.join("."), range.join(".")) === 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
graphics.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;
|
|
||||||
};
|
|
||||||
|
|
||||||
graphics.semver.cmp.doc = "Compare two semantic version numbers, given like X.X.X.";
|
|
||||||
graphics.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.`;
|
|
||||||
|
|
||||||
return graphics
|
return graphics
|
||||||
|
|||||||
102
scripts/modules/camera.js
Normal file
102
scripts/modules/camera.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
var cam = {}
|
||||||
|
|
||||||
|
var os = use('os')
|
||||||
|
|
||||||
|
var basecam = {}
|
||||||
|
basecam.draw_rect = function(size)
|
||||||
|
{
|
||||||
|
var mode = this.presentation || "letterbox"
|
||||||
|
var vp = {
|
||||||
|
x:this.viewport.x,
|
||||||
|
y:1-this.viewport.y-this.viewport.height,
|
||||||
|
width:this.viewport.width,
|
||||||
|
height:this.viewport.height
|
||||||
|
}
|
||||||
|
var src_rect = {x:0,y:0,width:this.size.x,height:this.size.y}
|
||||||
|
var dst_rect = {x:vp.x*size.x,y:vp.y*size.y,width:vp.width*size.x,height:vp.height*size.y};
|
||||||
|
return mode_rect(src_rect,dst_rect,mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
basecam.screen2camera = function(pos)
|
||||||
|
{
|
||||||
|
var draw_rect = this.draw_rect(prosperon.window.size);
|
||||||
|
var ret = [pos.x-draw_rect.x, pos.y - draw_rect.y];
|
||||||
|
ret.x /= draw_rect.width;
|
||||||
|
ret.y /= draw_rect.height;
|
||||||
|
ret.y = 1 - ret.y;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
basecam.screen2hud = function(pos)
|
||||||
|
{
|
||||||
|
var cam = this.screen2camera(pos);
|
||||||
|
cam.x *= this.size.x;
|
||||||
|
cam.y *= this.size.y;
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
basecam.screen2world = function(pos)
|
||||||
|
{
|
||||||
|
var hud = this.screen2hud(pos);
|
||||||
|
hud.x += this.transform.pos.x - this.size.x/2;
|
||||||
|
hud.y += this.transform.pos.y - this.size.y/2;
|
||||||
|
return hud;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mode_rect(src,dst,mode = "stretch")
|
||||||
|
{
|
||||||
|
var aspect_src = src.width/src.height;
|
||||||
|
var aspect_dst = dst.width/dst.height;
|
||||||
|
var out = {
|
||||||
|
x:dst.x,
|
||||||
|
y:dst.y,
|
||||||
|
width:dst.width,
|
||||||
|
height:dst.height
|
||||||
|
};
|
||||||
|
if (mode == "stretch") return out;
|
||||||
|
|
||||||
|
if (mode == "letterbox") {
|
||||||
|
if (aspect_src > aspect_dst) {
|
||||||
|
var scaled_h = out.width/aspect_src;
|
||||||
|
var off = (out.height - scaled_h) * 0.5;
|
||||||
|
out.y += off;
|
||||||
|
out.height = scaled_h;
|
||||||
|
} else {
|
||||||
|
var scaled_w =out.height * aspect_src;
|
||||||
|
var off = (out.width - scaled_w) * 0.5;
|
||||||
|
out.x += off;
|
||||||
|
out.width = scaled_w;
|
||||||
|
}
|
||||||
|
} else if (mode == "overscan"){
|
||||||
|
if (aspect_src > aspect_dst) {
|
||||||
|
var scaled_w = out.height * aspect_src;
|
||||||
|
var off = (out.width - scaled_w) * 0.5;
|
||||||
|
out.x += off;
|
||||||
|
out.width = scaled_w;
|
||||||
|
} else {
|
||||||
|
var scaled_h = out.width / aspect_src;
|
||||||
|
var off = (out.height - scaled_h) * 0.5;
|
||||||
|
out.y += off;
|
||||||
|
out.height = scaled_h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If camera viewport is defined, will draw to the screen
|
||||||
|
// If target is defined, will render to a target, too
|
||||||
|
cam.make = function()
|
||||||
|
{
|
||||||
|
var c = Object.create(basecam)
|
||||||
|
c.transform = os.make_transform()
|
||||||
|
c.zoom = 1
|
||||||
|
c.size = [640,360]
|
||||||
|
c.mode = 'keep'
|
||||||
|
c.viewport = {x:0,y:0,width:1,height:1}
|
||||||
|
c.fov = 45
|
||||||
|
c.type = 'ortho'
|
||||||
|
c.aspect = 16/9
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
return cam
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
var input = this
|
var input = use('input')
|
||||||
|
|
||||||
var util = use('util')
|
var util = use('util')
|
||||||
|
|
||||||
var downkeys = {};
|
var downkeys = {};
|
||||||
@@ -18,54 +17,52 @@ function modstr(mod = input.keymod()) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
prosperon.key_down = function key_down(e) {
|
prosperon.on('key_down', function key_down(e) {
|
||||||
downkeys[e.key] = true;
|
downkeys[e.key] = true;
|
||||||
var emacs = modstr(e.mod) + keyname(e.key);
|
var emacs = modstr(e.mod) + keyname(e.key);
|
||||||
if (e.repeat) player[0].raw_input(emacs, "rep");
|
if (e.repeat) player[0].raw_input(emacs, "rep");
|
||||||
else player[0].raw_input(emacs, "pressed");
|
else player[0].raw_input(emacs, "pressed");
|
||||||
};
|
})
|
||||||
|
|
||||||
prosperon.quit = function()
|
prosperon.on('quit', function() {
|
||||||
{
|
|
||||||
os.exit(0);
|
os.exit(0);
|
||||||
}
|
})
|
||||||
|
|
||||||
prosperon.key_up = function key_up(e) {
|
prosperon.on('key_up', function key_up(e) {
|
||||||
delete downkeys[e.key];
|
delete downkeys[e.key];
|
||||||
var emacs = modstr(e.mod) + keyname(e.key);
|
var emacs = modstr(e.mod) + keyname(e.key);
|
||||||
player[0].raw_input(emacs, "released");
|
player[0].raw_input(emacs, "released");
|
||||||
};
|
})
|
||||||
|
|
||||||
prosperon.drop_file = function (path) {
|
prosperon.on('drop_file', function (path) {
|
||||||
player[0].raw_input("drop", "pressed", path);
|
player[0].raw_input("drop", "pressed", path);
|
||||||
};
|
})
|
||||||
|
|
||||||
var mousepos = [0, 0];
|
var mousepos = [0, 0];
|
||||||
|
|
||||||
prosperon.text_input = function (e) {
|
prosperon.on('text_input', function (e) {
|
||||||
player[0].raw_input("char", "pressed", e.text);
|
player[0].raw_input("char", "pressed", e.text);
|
||||||
};
|
})
|
||||||
|
|
||||||
prosperon.mouse_motion = function (e)
|
prosperon.on('mouse_motion', function (e)
|
||||||
{
|
{
|
||||||
mousepos = e.pos;
|
mousepos = e.pos;
|
||||||
player[0].mouse_input("move", e.pos, e.d_pos);
|
player[0].mouse_input("move", e.pos, e.d_pos);
|
||||||
};
|
})
|
||||||
prosperon.mouse_wheel = function mousescroll(e) {
|
|
||||||
player[0].mouse_input(modstr() + "scroll", e.scroll);
|
|
||||||
};
|
|
||||||
|
|
||||||
prosperon.mouse_button_down = function(e)
|
prosperon.on('mouse_wheel', function mousescroll(e) {
|
||||||
{
|
player[0].mouse_input(modstr() + "scroll", e.scroll);
|
||||||
|
})
|
||||||
|
|
||||||
|
prosperon.on('mouse_button_down', function(e) {
|
||||||
player[0].mouse_input(modstr() + e.button, "pressed");
|
player[0].mouse_input(modstr() + e.button, "pressed");
|
||||||
input.mouse.buttons[e.button] = true
|
input.mouse.buttons[e.button] = true
|
||||||
}
|
})
|
||||||
|
|
||||||
prosperon.mouse_button_up = function(e)
|
prosperon.on('mouse_button_up', function(e) {
|
||||||
{
|
|
||||||
player[0].mouse_input(modstr() + e.button, "released");
|
player[0].mouse_input(modstr() + e.button, "released");
|
||||||
input.mouse.buttons[e.button] = false
|
input.mouse.buttons[e.button] = false
|
||||||
}
|
})
|
||||||
|
|
||||||
input.mouse = {};
|
input.mouse = {};
|
||||||
input.mouse.screenpos = function mouse_screenpos() {
|
input.mouse.screenpos = function mouse_screenpos() {
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
var Color = use('color')
|
var Color = use('color')
|
||||||
var os = use('os')
|
var os = use('os')
|
||||||
|
var graphics = use('graphics')
|
||||||
|
//var render = use('render')
|
||||||
|
|
||||||
var ex = {}
|
var ex = {}
|
||||||
|
|
||||||
@@ -104,6 +106,24 @@ ex.spawn_timer = 0
|
|||||||
ex.pps = 0
|
ex.pps = 0
|
||||||
ex.color = Color.white
|
ex.color = Color.white
|
||||||
|
|
||||||
|
ex.draw = function()
|
||||||
|
{
|
||||||
|
/* var diff = graphics.texture(this.diffuse)
|
||||||
|
if (!diff) throw new Error("emitter does not have a proper diffuse texture")
|
||||||
|
|
||||||
|
var mesh = render._main.make_sprite_mesh(this.particles)
|
||||||
|
if (mesh.num_indices === 0) return
|
||||||
|
render.queue({
|
||||||
|
type:'geometry',
|
||||||
|
mesh,
|
||||||
|
image:diff,
|
||||||
|
pipeline,
|
||||||
|
first_index:0,
|
||||||
|
num_indices:mesh.num_indices
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
return ex
|
return ex
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -113,5 +133,4 @@ this.dead = []
|
|||||||
|
|
||||||
this.transform = this.overling.transform
|
this.transform = this.overling.transform
|
||||||
|
|
||||||
|
|
||||||
$.emitters.add(this)
|
$.emitters.add(this)
|
||||||
|
|||||||
@@ -1,5 +1,69 @@
|
|||||||
var graphics = use('graphics')
|
var graphics = use('graphics')
|
||||||
|
|
||||||
|
var base_pipeline = {
|
||||||
|
vertex: "sprite.vert",
|
||||||
|
fragment: "sprite.frag",
|
||||||
|
primitive: "triangle", // point, line, linestrip, triangle, trianglestrip
|
||||||
|
fill: true, // false for lines
|
||||||
|
depth: {
|
||||||
|
compare: "greater_equal", // never/less/equal/less_equal/greater/not_equal/greater_equal/always
|
||||||
|
test: false,
|
||||||
|
write: false,
|
||||||
|
bias: 0,
|
||||||
|
bias_slope_scale: 0,
|
||||||
|
bias_clamp: 0
|
||||||
|
},
|
||||||
|
stencil: {
|
||||||
|
enabled: true,
|
||||||
|
front: {
|
||||||
|
compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always
|
||||||
|
fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap
|
||||||
|
depth_fail: "keep",
|
||||||
|
pass: "keep"
|
||||||
|
},
|
||||||
|
back: {
|
||||||
|
compare: "equal", // never/less/equal/less_equal/greater/neq/greq/always
|
||||||
|
fail: "keep", // keep/zero/replace/incr_clamp/decr_clamp/invert/incr_wrap/decr_wrap
|
||||||
|
depth_fail: "keep",
|
||||||
|
pass: "keep"
|
||||||
|
},
|
||||||
|
test: true,
|
||||||
|
compare_mask: 0,
|
||||||
|
write_mask: 0
|
||||||
|
},
|
||||||
|
blend: {
|
||||||
|
enabled: false,
|
||||||
|
src_rgb: "zero", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate
|
||||||
|
dst_rgb: "zero",
|
||||||
|
op_rgb: "add", // add/sub/rev_sub/min/max
|
||||||
|
src_alpha: "one",
|
||||||
|
dst_alpha: "zero",
|
||||||
|
op_alpha: "add"
|
||||||
|
},
|
||||||
|
cull: "none", // none/front/back
|
||||||
|
face: "cw", // cw/ccw
|
||||||
|
alpha_to_coverage: false,
|
||||||
|
multisample: {
|
||||||
|
count: 1, // number of multisamples
|
||||||
|
mask: 0xFFFFFFFF,
|
||||||
|
domask: false
|
||||||
|
},
|
||||||
|
label: "scripted pipeline",
|
||||||
|
target: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sprite_pipeline = Object.create(base_pipeline);
|
||||||
|
sprite_pipeline.blend = {
|
||||||
|
enabled:true,
|
||||||
|
src_rgb: "src_alpha", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate
|
||||||
|
dst_rgb: "one_minus_src_alpha",
|
||||||
|
op_rgb: "add", // add/sub/rev_sub/min/max
|
||||||
|
src_alpha: "one",
|
||||||
|
dst_alpha: "zero",
|
||||||
|
op_alpha: "add"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
var sprite = {
|
var sprite = {
|
||||||
image: undefined,
|
image: undefined,
|
||||||
set color(x) { this._sprite.color = x; },
|
set color(x) { this._sprite.color = x; },
|
||||||
@@ -184,7 +248,7 @@ sprite.inputs.kp1 = function () {
|
|||||||
this.setanchor("ul");
|
this.setanchor("ul");
|
||||||
};
|
};
|
||||||
|
|
||||||
var tree = os.make_rtree()
|
var tree = graphics.make_rtree()
|
||||||
sprite.tree = tree;
|
sprite.tree = tree;
|
||||||
|
|
||||||
sprite.t_hook = function() {
|
sprite.t_hook = function() {
|
||||||
@@ -199,19 +263,36 @@ sprite.t_hook = function() {
|
|||||||
|
|
||||||
Object.mixin(sprite,use("transform"))
|
Object.mixin(sprite,use("transform"))
|
||||||
|
|
||||||
|
sprite.to_queue = function(ysort = false)
|
||||||
|
{
|
||||||
|
var pos = prosperon.camera.transform.pos;
|
||||||
|
var size = prosperon.camera.size;
|
||||||
|
var camrect = {
|
||||||
|
x:pos.x-size.x/2,
|
||||||
|
y:pos.y-size.y/2,
|
||||||
|
width:size.x,
|
||||||
|
height:size.y
|
||||||
|
};
|
||||||
|
var culled = sprite.tree.query(camrect)
|
||||||
|
if (culled.length == 0) return [];
|
||||||
|
var cmd = graphics.make_sprite_queue(culled, prosperon.camera, sprite_pipeline, 1);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
return sprite;
|
return sprite;
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
var Color = use('color')
|
var Color = use('color')
|
||||||
var os = use('os')
|
var os = use('os')
|
||||||
|
var graphics = use('graphics')
|
||||||
|
|
||||||
this.transform = os.make_transform();
|
this.transform = os.make_transform();
|
||||||
if (this.overling.transform)
|
if (this.overling.transform)
|
||||||
this.transform.parent = this.overling.transform;
|
this.transform.parent = this.overling.transform;
|
||||||
|
|
||||||
this.transform.change_hook = $.t_hook;
|
this.transform.change_hook = $.t_hook;
|
||||||
var msp = os.make_sprite();
|
var msp = graphics.make_sprite();
|
||||||
this._sprite = msp;
|
this._sprite = msp;
|
||||||
msp.color = Color.white;
|
msp.color = Color.white;
|
||||||
this.transform.sprite = this
|
this.transform.sprite = this
|
||||||
|
|||||||
@@ -5,23 +5,26 @@ var io = use('io')
|
|||||||
var os = use('os')
|
var os = use('os')
|
||||||
var util = use('util')
|
var util = use('util')
|
||||||
var emitter = use('emitter')
|
var emitter = use('emitter')
|
||||||
var input = use('input')
|
var controller = use('controller')
|
||||||
|
var event = use('event')
|
||||||
|
|
||||||
var sprite = use('sprite')
|
var sprite = use('sprite')
|
||||||
|
var graphics = use('graphics')
|
||||||
|
|
||||||
var appy = {};
|
var appy = {};
|
||||||
appy.inputs = {};
|
appy.inputs = {};
|
||||||
if (os.sys() === "macos") {
|
if (os.platform() === "macos") {
|
||||||
appy.inputs["S-q"] = os.exit;
|
appy.inputs["S-q"] = os.exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
appy.inputs["M-f4"] = os.exit;
|
appy.inputs["M-f4"] = os.exit;
|
||||||
|
|
||||||
input.player[0].control(appy);
|
controller.player[0].control(appy);
|
||||||
|
|
||||||
prosperon.window = os.engine_start(config);
|
prosperon.window = prosperon.engine_start(config);
|
||||||
|
|
||||||
var driver = "vulkan"
|
var driver = "vulkan"
|
||||||
switch(os.sys()) {
|
switch(os.platform()) {
|
||||||
case "Linux":
|
case "Linux":
|
||||||
driver = "vulkan"
|
driver = "vulkan"
|
||||||
break
|
break
|
||||||
@@ -40,8 +43,6 @@ render._main.window = prosperon.window
|
|||||||
render._main.claim_window(prosperon.window)
|
render._main.claim_window(prosperon.window)
|
||||||
render._main.set_swapchain('sdr', 'vsync')
|
render._main.set_swapchain('sdr', 'vsync')
|
||||||
|
|
||||||
var graphics = use('graphics')
|
|
||||||
|
|
||||||
var unit_transform = os.make_transform();
|
var unit_transform = os.make_transform();
|
||||||
|
|
||||||
var cur = {};
|
var cur = {};
|
||||||
@@ -56,19 +57,6 @@ function full_upload(buffers)
|
|||||||
cmds.submit();
|
cmds.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function queue_sprite_mesh(queue)
|
|
||||||
{
|
|
||||||
var sprites = queue.filter(x => x.type === 'sprite');
|
|
||||||
if (sprites.length === 0) return [];
|
|
||||||
var mesh = render._main.make_sprite_mesh(sprites);
|
|
||||||
for (var i = 0; i < sprites.length; i++) {
|
|
||||||
sprites[i].mesh = mesh;
|
|
||||||
sprites[i].first_index = i*6;
|
|
||||||
sprites[i].num_indices = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [mesh.pos,mesh.uv,mesh.color,mesh.indices]
|
|
||||||
}
|
|
||||||
function bind_pipeline(pass, pipeline)
|
function bind_pipeline(pass, pipeline)
|
||||||
{
|
{
|
||||||
make_pipeline(pipeline)
|
make_pipeline(pipeline)
|
||||||
@@ -431,12 +419,12 @@ var pass;
|
|||||||
}
|
}
|
||||||
|
|
||||||
var buffers = [];
|
var buffers = [];
|
||||||
buffers = buffers.concat(queue_sprite_mesh(render_queue));
|
buffers = buffers.concat(graphics.queue_sprite_mesh(render_queue));
|
||||||
var unique_meshes = [...new Set(render_queue.map(x => x.mesh))];
|
var unique_meshes = [...new Set(render_queue.map(x => x.mesh))];
|
||||||
for (var q of unique_meshes)
|
for (var q of unique_meshes)
|
||||||
buffers = buffers.concat([q.pos, q.color,q.uv,q.indices]);
|
buffers = buffers.concat([q.pos, q.color,q.uv,q.indices]);
|
||||||
|
|
||||||
buffers = buffers.concat(queue_sprite_mesh(hud_queue));
|
buffers = buffers.concat(graphics.queue_sprite_mesh(hud_queue));
|
||||||
for (var q of hud_queue)
|
for (var q of hud_queue)
|
||||||
if (q.type === 'geometry') buffers = buffers.concat([q.mesh.pos, q.mesh.color,q.mesh.uv,q.mesh.indices]);
|
if (q.type === 'geometry') buffers = buffers.concat([q.mesh.pos, q.mesh.color,q.mesh.uv,q.mesh.indices]);
|
||||||
|
|
||||||
@@ -521,102 +509,8 @@ var pass;
|
|||||||
hud_queue = [];
|
hud_queue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function mode_rect(src,dst,mode = "stretch")
|
|
||||||
{
|
|
||||||
var aspect_src = src.width/src.height;
|
|
||||||
var aspect_dst = dst.width/dst.height;
|
|
||||||
var out = {
|
|
||||||
x:dst.x,
|
|
||||||
y:dst.y,
|
|
||||||
width:dst.width,
|
|
||||||
height:dst.height
|
|
||||||
};
|
|
||||||
if (mode == "stretch") return out;
|
|
||||||
|
|
||||||
if (mode == "letterbox") {
|
|
||||||
if (aspect_src > aspect_dst) {
|
|
||||||
var scaled_h = out.width/aspect_src;
|
|
||||||
var off = (out.height - scaled_h) * 0.5;
|
|
||||||
out.y += off;
|
|
||||||
out.height = scaled_h;
|
|
||||||
} else {
|
|
||||||
var scaled_w =out.height * aspect_src;
|
|
||||||
var off = (out.width - scaled_w) * 0.5;
|
|
||||||
out.x += off;
|
|
||||||
out.width = scaled_w;
|
|
||||||
}
|
|
||||||
} else if (mode == "overscan"){
|
|
||||||
if (aspect_src > aspect_dst) {
|
|
||||||
var scaled_w = out.height * aspect_src;
|
|
||||||
var off = (out.width - scaled_w) * 0.5;
|
|
||||||
out.x += off;
|
|
||||||
out.width = scaled_w;
|
|
||||||
} else {
|
|
||||||
var scaled_h = out.width / aspect_src;
|
|
||||||
var off = (out.height - scaled_h) * 0.5;
|
|
||||||
out.y += off;
|
|
||||||
out.height = scaled_h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
prosperon.camera = {};
|
prosperon.camera = use('camera').make()
|
||||||
// If camera viewport is defined, will draw to the screen
|
|
||||||
// If target is defined, will render to a target, too
|
|
||||||
|
|
||||||
prosperon.camera.transform = os.make_transform();
|
|
||||||
prosperon.camera.transform.unit();
|
|
||||||
prosperon.camera.zoom = 1;
|
|
||||||
prosperon.camera.size = [640,360];
|
|
||||||
prosperon.camera.mode = 'keep';
|
|
||||||
prosperon.camera.viewport = {x:0,y:0,width:1,height:1}
|
|
||||||
prosperon.camera.fov = 45;
|
|
||||||
prosperon.camera.type = 'ortho';
|
|
||||||
prosperon.camera.ortho = true
|
|
||||||
prosperon.camera.aspect = 16/9;
|
|
||||||
delete prosperon.camera.target;
|
|
||||||
|
|
||||||
prosperon.camera.draw_rect = function(size)
|
|
||||||
{
|
|
||||||
var mode = this.presentation || "letterbox"
|
|
||||||
var vp = {
|
|
||||||
x:this.viewport.x,
|
|
||||||
y:1-this.viewport.y-this.viewport.height,
|
|
||||||
width:this.viewport.width,
|
|
||||||
height:this.viewport.height
|
|
||||||
}
|
|
||||||
var src_rect = {x:0,y:0,width:this.size.x,height:this.size.y}
|
|
||||||
var dst_rect = {x:vp.x*size.x,y:vp.y*size.y,width:vp.width*size.x,height:vp.height*size.y};
|
|
||||||
return mode_rect(src_rect,dst_rect,mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Camera coordinates are [0,0]
|
|
||||||
prosperon.camera.screen2camera = function(pos)
|
|
||||||
{
|
|
||||||
var draw_rect = this.draw_rect(prosperon.window.size);
|
|
||||||
var ret = [pos.x-draw_rect.x, pos.y - draw_rect.y];
|
|
||||||
ret.x /= draw_rect.width;
|
|
||||||
ret.y /= draw_rect.height;
|
|
||||||
ret.y = 1 - ret.y;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
prosperon.camera.screen2hud = function(pos)
|
|
||||||
{
|
|
||||||
var cam = this.screen2camera(pos);
|
|
||||||
cam.x *= this.size.x;
|
|
||||||
cam.y *= this.size.y;
|
|
||||||
return cam;
|
|
||||||
}
|
|
||||||
|
|
||||||
prosperon.camera.screen2world = function(pos)
|
|
||||||
{
|
|
||||||
var hud = this.screen2hud(pos);
|
|
||||||
hud.x += this.transform.pos.x - this.size.x/2;
|
|
||||||
hud.y += this.transform.pos.y - this.size.y/2;
|
|
||||||
return hud;
|
|
||||||
}
|
|
||||||
|
|
||||||
var swaps = [];
|
var swaps = [];
|
||||||
function gpupresent()
|
function gpupresent()
|
||||||
@@ -624,7 +518,7 @@ function gpupresent()
|
|||||||
os.clean_transforms();
|
os.clean_transforms();
|
||||||
prosperon.prerender();
|
prosperon.prerender();
|
||||||
var cmds = render._main.acquire_cmd_buffer();
|
var cmds = render._main.acquire_cmd_buffer();
|
||||||
render_queue = sprites_to_queue().concat(render_queue);
|
render_queue = sprite.to_queue().concat(render_queue);
|
||||||
render_camera(cmds, prosperon.camera);
|
render_camera(cmds, prosperon.camera);
|
||||||
var swapchain_tex = cmds.acquire_swapchain();
|
var swapchain_tex = cmds.acquire_swapchain();
|
||||||
if (!swapchain_tex)
|
if (!swapchain_tex)
|
||||||
@@ -660,39 +554,6 @@ render.toggles = {
|
|||||||
draw_gui:true
|
draw_gui:true
|
||||||
}
|
}
|
||||||
|
|
||||||
function sprites_to_queue(ysort = false)
|
|
||||||
{
|
|
||||||
var pos = prosperon.camera.transform.pos;
|
|
||||||
var size = prosperon.camera.size;
|
|
||||||
var camrect = {
|
|
||||||
x:pos.x-size.x/2,
|
|
||||||
y:pos.y-size.y/2,
|
|
||||||
width:size.x,
|
|
||||||
height:size.y
|
|
||||||
};
|
|
||||||
var culled = sprite.tree.query(camrect)
|
|
||||||
if (culled.length == 0) return [];
|
|
||||||
var cmd = render._main.make_sprite_queue(culled, prosperon.camera, sprite_pipeline, 1);
|
|
||||||
return cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
render.particles = function render_particles(emitter, pipeline = sprite_pipeline)
|
|
||||||
{
|
|
||||||
var diff = graphics.texture(emitter.diffuse)
|
|
||||||
if (!diff) throw new Error("emitter does not have a proper diffuse");
|
|
||||||
|
|
||||||
var mesh = render._main.make_sprite_mesh(emitter.particles);
|
|
||||||
if (mesh.num_indices === 0) return;
|
|
||||||
current_queue.push({
|
|
||||||
type:'geometry',
|
|
||||||
mesh,
|
|
||||||
image:diff,
|
|
||||||
pipeline,
|
|
||||||
first_index:0,
|
|
||||||
num_indices:mesh.num_indices
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var stencil_write = {
|
var stencil_write = {
|
||||||
compare: "always",
|
compare: "always",
|
||||||
fail_op: "replace",
|
fail_op: "replace",
|
||||||
@@ -766,65 +627,7 @@ render.scissor = function(rect)
|
|||||||
{
|
{
|
||||||
render.viewport(rect)
|
render.viewport(rect)
|
||||||
}
|
}
|
||||||
|
//////////////////////////////////////////////////
|
||||||
function camscreen2world(pos) {
|
|
||||||
var view = this.screen2cam(pos);
|
|
||||||
var viewport = render._main.get_viewport();
|
|
||||||
view.x *= viewport.width;
|
|
||||||
view.y *= viewport.height;
|
|
||||||
view = view.add(this.pos.xy);
|
|
||||||
view = view.sub([viewport.width,viewport.height].scale(0.5))
|
|
||||||
// view = view.scale(this.transform.scale);
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
// world coordinates, the "actual" view relative to the game's universe
|
|
||||||
// camera coordinates, normalized from 0 to 1 inside of a camera's viewport, bottom left is 0,0, top right is 1,1
|
|
||||||
// screen coordinates, pixels, 0,0 at the top left of the window and [w,h] at the bottom right of the window
|
|
||||||
// hud coordinates, same as screen coordinates but the top left is 0,0
|
|
||||||
|
|
||||||
camscreen2world.doc = "Convert a view position for a camera to world.";
|
|
||||||
|
|
||||||
// return camera coordinates given a screen position
|
|
||||||
function screen2cam(pos) {
|
|
||||||
var tpos = render._main.coords(pos);
|
|
||||||
var viewport = render._main.get_viewport();
|
|
||||||
var viewpos = tpos.div([viewport.width,viewport.height]);
|
|
||||||
viewpos.y *= -1;
|
|
||||||
viewpos.y += 1;
|
|
||||||
return viewpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen2cam.doc = "Convert a screen space position in pixels to a normalized viewport position in a camera.";
|
|
||||||
|
|
||||||
function screen2hud(pos)
|
|
||||||
{
|
|
||||||
var campos = this.screen2cam(pos);
|
|
||||||
var viewport = render._main.get_viewport();
|
|
||||||
campos = campos.scale([viewport.width,viewport.height]);
|
|
||||||
return campos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cameras
|
|
||||||
* Cameras have a position and rotation. They are not affected by scale.
|
|
||||||
*/
|
|
||||||
|
|
||||||
prosperon.make_camera = function (make_camera) {
|
|
||||||
return;
|
|
||||||
/* var cam = world.spawn();
|
|
||||||
cam.near = 1;
|
|
||||||
cam.far = -1000;
|
|
||||||
cam.ortho = true; // True if this is a 2d camera
|
|
||||||
cam.size = prosperon.size.slice() // The render size of this camera in pixels
|
|
||||||
// In ortho mode, this determines how many pixels it will see
|
|
||||||
cam.mode = "stretch";
|
|
||||||
cam.screen2world = camscreen2world;
|
|
||||||
cam.screen2cam = screen2cam;
|
|
||||||
cam.screen2hud = screen2hud;
|
|
||||||
cam.zoom = 1; // the "scale factor" this camera demonstrates
|
|
||||||
return cam;*/
|
|
||||||
};
|
|
||||||
|
|
||||||
var screencolor;
|
var screencolor;
|
||||||
|
|
||||||
globalThis.imtoggle = function (name, obj, field) {
|
globalThis.imtoggle = function (name, obj, field) {
|
||||||
@@ -941,8 +744,8 @@ render.process = function process() {
|
|||||||
var dt = last_frame_time - frame_t;
|
var dt = last_frame_time - frame_t;
|
||||||
frame_t = last_frame_time;
|
frame_t = last_frame_time;
|
||||||
|
|
||||||
os.engine_input(e => {
|
event.engine_input(e => {
|
||||||
prosperon[e.type]?.(e);
|
prosperon.dispatch(e.type, e);
|
||||||
});
|
});
|
||||||
|
|
||||||
layout.newframe();
|
layout.newframe();
|
||||||
@@ -956,7 +759,6 @@ render.process = function process() {
|
|||||||
|
|
||||||
current_queue = render_queue;
|
current_queue = render_queue;
|
||||||
prosperon.draw()
|
prosperon.draw()
|
||||||
emitter.emitters.forEach(e => render.particles(e))
|
|
||||||
current_queue = hud_queue;
|
current_queue = hud_queue;
|
||||||
prosperon.hud()
|
prosperon.hud()
|
||||||
imgui_fn()
|
imgui_fn()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var Resources = {}
|
var Resources = {}
|
||||||
|
|
||||||
var so_ext;
|
var so_ext;
|
||||||
switch(os.sys()) {
|
switch(os.platform()) {
|
||||||
case 'Windows':
|
case 'Windows':
|
||||||
so_ext = '.dll';
|
so_ext = '.dll';
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
var util = {}
|
var util = this
|
||||||
|
|
||||||
util.deepfreeze = function (obj) {
|
util.deepfreeze = function (obj) {
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
|
|||||||
813
source/jsffi.c
813
source/jsffi.c
@@ -9,7 +9,6 @@
|
|||||||
#include "stb_dxt.h"
|
#include "stb_dxt.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "spline.h"
|
#include "spline.h"
|
||||||
#include "yugine.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -29,13 +28,22 @@
|
|||||||
#include "cgltf.h"
|
#include "cgltf.h"
|
||||||
#include "physfs.h"
|
#include "physfs.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "wildmatch.h"
|
#include "wildmatch.h"
|
||||||
|
|
||||||
#include "freelist.h"
|
#include "freelist.h"
|
||||||
|
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
|
||||||
#include "quadtree.h"
|
|
||||||
#include "rtree.h"
|
#include "rtree.h"
|
||||||
|
|
||||||
typedef struct rtree rtree;
|
typedef struct rtree rtree;
|
||||||
@@ -45,6 +53,7 @@ typedef struct rtree rtree;
|
|||||||
#include <SDL3/SDL_error.h>
|
#include <SDL3/SDL_error.h>
|
||||||
#include <SDL3/SDL_properties.h>
|
#include <SDL3/SDL_properties.h>
|
||||||
#include <SDL3/SDL_loadso.h>
|
#include <SDL3/SDL_loadso.h>
|
||||||
|
#include <SDL3/SDL_cpuinfo.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -410,8 +419,6 @@ static BufferCheckResult get_or_extend_buffer(
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "stb_perlin.h"
|
|
||||||
|
|
||||||
#if (defined(_WIN32) || defined(__WIN32__))
|
#if (defined(_WIN32) || defined(__WIN32__))
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#define mkdir(x,y) _mkdir(x)
|
#define mkdir(x,y) _mkdir(x)
|
||||||
@@ -1105,10 +1112,6 @@ char *js2strdup(JSContext *js, JSValue v) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skin_free(JSRuntime *rt,skin *sk) {
|
|
||||||
arrfree(sk->invbind);
|
|
||||||
free(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "qjs_macros.h"
|
#include "qjs_macros.h"
|
||||||
|
|
||||||
@@ -1194,7 +1197,6 @@ static void js_timer_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_fun
|
|||||||
}
|
}
|
||||||
QJSCLASSMARK(timer)
|
QJSCLASSMARK(timer)
|
||||||
|
|
||||||
QJSCLASS(skin)
|
|
||||||
QJSCLASS(SDL_Window)
|
QJSCLASS(SDL_Window)
|
||||||
QJSCLASS(SDL_Renderer)
|
QJSCLASS(SDL_Renderer)
|
||||||
QJSCLASS(SDL_Camera)
|
QJSCLASS(SDL_Camera)
|
||||||
@@ -1241,13 +1243,6 @@ static void PHYSFS_File_free(JSRuntime *rt, PHYSFS_File *f)
|
|||||||
|
|
||||||
QJSCLASS(PHYSFS_File)
|
QJSCLASS(PHYSFS_File)
|
||||||
|
|
||||||
void qtree_free(JSRuntime *rt, qtree *tree)
|
|
||||||
{
|
|
||||||
qtree_destroy(*tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
QJSCLASS(qtree)
|
|
||||||
|
|
||||||
void rtree_free(JSRuntime *rt, rtree *tree)
|
void rtree_free(JSRuntime *rt, rtree *tree)
|
||||||
{
|
{
|
||||||
rtree_destroy(tree);
|
rtree_destroy(tree);
|
||||||
@@ -2869,20 +2864,6 @@ static JSValue event2js(JSContext *js, SDL_Event event)
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui_input(SDL_Event *e);
|
|
||||||
// Polls and handles all input events
|
|
||||||
JSC_CCALL(os_engine_input,
|
|
||||||
SDL_Event event;
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
#ifndef NEDITOR
|
|
||||||
gui_input(&event);
|
|
||||||
#endif
|
|
||||||
JSValue e = event2js(js,event);
|
|
||||||
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
|
|
||||||
uncaught_exception(js,ret);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(camera_list,
|
JSC_CCALL(camera_list,
|
||||||
int num;
|
int num;
|
||||||
SDL_CameraID *ids = SDL_GetCameras(&num);
|
SDL_CameraID *ids = SDL_GetCameras(&num);
|
||||||
@@ -5061,8 +5042,6 @@ static const JSCFunctionListEntry js_SDL_GPUDevice_funcs[] = {
|
|||||||
MIST_FUNC_DEF(gpu, make_sampler,1),
|
MIST_FUNC_DEF(gpu, make_sampler,1),
|
||||||
MIST_FUNC_DEF(gpu, load_texture, 2),
|
MIST_FUNC_DEF(gpu, load_texture, 2),
|
||||||
MIST_FUNC_DEF(gpu, texture, 1),
|
MIST_FUNC_DEF(gpu, texture, 1),
|
||||||
MIST_FUNC_DEF(gpu, make_sprite_mesh, 2),
|
|
||||||
MIST_FUNC_DEF(gpu, make_sprite_queue, 4),
|
|
||||||
MIST_FUNC_DEF(gpu, make_quad, 0),
|
MIST_FUNC_DEF(gpu, make_quad, 0),
|
||||||
MIST_FUNC_DEF(gpu, driver, 0),
|
MIST_FUNC_DEF(gpu, driver, 0),
|
||||||
MIST_FUNC_DEF(gpu, make_shader, 1),
|
MIST_FUNC_DEF(gpu, make_shader, 1),
|
||||||
@@ -5704,18 +5683,6 @@ JSC_SCALL(os_openurl,
|
|||||||
ret = JS_ThrowReferenceError(js, "unable to open url %s: %s\n", str, SDL_GetError());
|
ret = JS_ThrowReferenceError(js, "unable to open url %s: %s\n", str, SDL_GetError());
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_push_event,
|
|
||||||
SDL_UserEvent e;
|
|
||||||
SDL_zero(e);
|
|
||||||
e.type = SDL_EVENT_USER;
|
|
||||||
e.timestamp = SDL_GetTicksNS();
|
|
||||||
e.code = 0;
|
|
||||||
JSValue fn = JS_DupValue(js,argv[0]);
|
|
||||||
e.data1 = malloc(sizeof(JSValue));
|
|
||||||
*(JSValue*)e.data1 = fn;
|
|
||||||
SDL_PushEvent(&e);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(time_now,
|
JSC_CCALL(time_now,
|
||||||
struct timeval ct;
|
struct timeval ct;
|
||||||
gettimeofday(&ct, NULL);
|
gettimeofday(&ct, NULL);
|
||||||
@@ -6401,18 +6368,6 @@ static const JSCFunctionListEntry js_geometry_funcs[] = {
|
|||||||
MIST_FUNC_DEF(geometry, rect_move, 2),
|
MIST_FUNC_DEF(geometry, rect_move, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSValue js_os_cwd(JSContext *js, JSValue self, int argc, JSValue *argv)
|
|
||||||
{
|
|
||||||
char cwd[PATH_MAX];
|
|
||||||
#ifndef __EMSCRIPTEN__
|
|
||||||
getcwd(cwd, sizeof(cwd));
|
|
||||||
#else
|
|
||||||
cwd[0] = '.';
|
|
||||||
cwd[1] = 0;
|
|
||||||
#endif
|
|
||||||
return JS_NewString(js,cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSC_SCALL(os_env,
|
JSC_SCALL(os_env,
|
||||||
char *env = getenv(str);
|
char *env = getenv(str);
|
||||||
if (env) ret = JS_NewString(js,env);
|
if (env) ret = JS_NewString(js,env);
|
||||||
@@ -6556,7 +6511,7 @@ JSC_CCALL(os_dump_mem,
|
|||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_value_id,
|
JSC_CCALL(os_value_id,
|
||||||
return number2js(js,(intptr_t)JS_VALUE_GET_PTR(argv[0]));
|
return number2js(js,(intptr_t)JS_VALUE_GET_PTR(self));
|
||||||
)
|
)
|
||||||
|
|
||||||
static double gc_t = 0;
|
static double gc_t = 0;
|
||||||
@@ -6750,271 +6705,6 @@ JSC_CCALL(os_make_sprite, return sprite2js(js,make_sprite()))
|
|||||||
|
|
||||||
JSC_SCALL(os_system, ret = number2js(js,system(str)); )
|
JSC_SCALL(os_system, ret = number2js(js,system(str)); )
|
||||||
|
|
||||||
JSC_SCALL(os_model_buffer,
|
|
||||||
/*
|
|
||||||
int mesh_idx = 0;
|
|
||||||
|
|
||||||
// Configure cgltf
|
|
||||||
cgltf_options options;
|
|
||||||
memset(&options, 0, sizeof(options));
|
|
||||||
|
|
||||||
// Parse the file
|
|
||||||
cgltf_data* data = NULL;
|
|
||||||
cgltf_result result = cgltf_parse_file(&options, str, &data);
|
|
||||||
if (result != cgltf_result_success) {
|
|
||||||
JS_ThrowInternalError(js, "Failed to load glTF model: parse error");
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load any external buffers (bin files, images)
|
|
||||||
result = cgltf_load_buffers(&options, data, str);
|
|
||||||
if (result != cgltf_result_success) {
|
|
||||||
cgltf_free(data);
|
|
||||||
JS_ThrowInternalError(js, "Failed to load glTF model: buffer load error");
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only check for mesh_idx vs. the count of cgltf_data->meshes
|
|
||||||
// (though note that glTF organizes data in scenes, nodes, etc.,
|
|
||||||
// so you might want to handle multiple nodes or node->mesh references)
|
|
||||||
if (mesh_idx < 0 || mesh_idx >= (int)data->meshes_count) {
|
|
||||||
cgltf_free(data);
|
|
||||||
JS_ThrowInternalError(js, "Invalid mesh index");
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue materials[data->materials_count];
|
|
||||||
for (int i = 0; i < (int)data->materials_count; i++) {
|
|
||||||
JSValue mat = JS_NewObject(js);
|
|
||||||
materials[i] = mat;
|
|
||||||
cgltf_material *cgmat = &data->materials[i];
|
|
||||||
|
|
||||||
// Grab the base color texture if it exists
|
|
||||||
cgltf_texture_view *bc_view = &cgmat->pbr_metallic_roughness.base_color_texture;
|
|
||||||
if (bc_view->texture && bc_view->texture->image) {
|
|
||||||
cgltf_image *img = bc_view->texture->image;
|
|
||||||
// If the image is an external URI
|
|
||||||
if (img->uri) {
|
|
||||||
// For glTF 2.0, this often points to a .png/.jpg
|
|
||||||
JS_SetPropertyStr(js, mat, "diffuse", JS_NewString(js, img->uri));
|
|
||||||
}
|
|
||||||
// If it's an embedded buffer view (e.g., "data:" or bufferView-based image)
|
|
||||||
else if (img->buffer_view) {
|
|
||||||
size_t size = img->buffer_view->size;
|
|
||||||
uint8_t *ptr = (uint8_t*)img->buffer_view->buffer->data + img->buffer_view->offset;
|
|
||||||
JS_SetPropertyStr(js, mat, "diffuse", JS_NewArrayBufferCopy(js, ptr, size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an array to hold all the "model" objects
|
|
||||||
JSValue ret_arr = JS_NewArray(js);
|
|
||||||
|
|
||||||
for (int m = 0; m < (int)data->meshes_count; m++) {
|
|
||||||
cgltf_mesh *cgmesh = &data->meshes[m];
|
|
||||||
// Go through each primitive in this mesh
|
|
||||||
for (int p = 0; p < (int)cgmesh->primitives_count; p++) {
|
|
||||||
cgltf_primitive *prim = &cgmesh->primitives[p];
|
|
||||||
if (!prim->attributes) {
|
|
||||||
// No attributes => no geometry
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll collect attribute data in arrays, just like with Assimp
|
|
||||||
float *posdata = NULL, *normdata = NULL, *uvdata = NULL, *colordata = NULL;
|
|
||||||
Uint16 *indicesdata = NULL;
|
|
||||||
size_t num_verts = 0;
|
|
||||||
size_t index_count = 0;
|
|
||||||
|
|
||||||
// Helper function to find an accessor by "POSITION", "NORMAL", "TEXCOORD_0", etc.
|
|
||||||
// We'll parse it below in parseAttributeFloat.
|
|
||||||
cgltf_accessor* findAccessor(cgltf_primitive* prim, const char* semantic) {
|
|
||||||
for (int a = 0; a < (int)prim->attributes_count; a++) {
|
|
||||||
if (prim->attributes[a].name && strcmp(prim->attributes[a].name, semantic) == 0)
|
|
||||||
return prim->attributes[a].data;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseAttributeFloat:
|
|
||||||
// read floats from a cgltf_accessor into outBuffer
|
|
||||||
// The 'stride' is how many floats we read per element (e.g. 3 for POSITION)
|
|
||||||
// Returns the number of elements read
|
|
||||||
size_t parseAttributeFloat(JSContext* js, cgltf_accessor* acc, float** outBuffer, int stride, float defaultVal) {
|
|
||||||
if (!acc) {
|
|
||||||
// If the attribute doesn't exist, fill default
|
|
||||||
size_t count = 0;
|
|
||||||
*outBuffer = NULL;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
size_t count = acc->count;
|
|
||||||
size_t total_floats = count * stride;
|
|
||||||
*outBuffer = malloc(total_floats * sizeof(float));
|
|
||||||
if (!(*outBuffer)) return 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
float tmp[4] = { defaultVal, defaultVal, defaultVal, defaultVal };
|
|
||||||
cgltf_accessor_read_float(acc, i, tmp, 4);
|
|
||||||
// copy only 'stride' components
|
|
||||||
for (int c = 0; c < stride; c++)
|
|
||||||
(*outBuffer)[i*stride + c] = tmp[c];
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1) POSITION
|
|
||||||
cgltf_accessor *accPos = findAccessor(prim, "POSITION");
|
|
||||||
num_verts = parseAttributeFloat(js, accPos, &posdata, 3, 0.0f);
|
|
||||||
|
|
||||||
// 2) NORMAL
|
|
||||||
cgltf_accessor *accNorm = findAccessor(prim, "NORMAL");
|
|
||||||
// If missing normals, default them to (0,0,1)
|
|
||||||
parseAttributeFloat(js, accNorm, &normdata, 3, 0.0f);
|
|
||||||
if (!normdata && num_verts > 0) {
|
|
||||||
normdata = malloc(num_verts*3*sizeof(float));
|
|
||||||
for (size_t i = 0; i < num_verts; i++) {
|
|
||||||
normdata[i*3+0] = 0.0f;
|
|
||||||
normdata[i*3+1] = 0.0f;
|
|
||||||
normdata[i*3+2] = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) TEXCOORD_0
|
|
||||||
cgltf_accessor *accUV = findAccessor(prim, "TEXCOORD_0");
|
|
||||||
parseAttributeFloat(js, accUV, &uvdata, 2, 0.0f);
|
|
||||||
if (!uvdata && num_verts > 0) {
|
|
||||||
uvdata = malloc(num_verts*2*sizeof(float));
|
|
||||||
for (size_t i = 0; i < num_verts; i++) {
|
|
||||||
uvdata[i*2+0] = 0.0f;
|
|
||||||
uvdata[i*2+1] = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4) COLOR_0
|
|
||||||
cgltf_accessor *accColor = findAccessor(prim, "COLOR_0");
|
|
||||||
parseAttributeFloat(js, accColor, &colordata, 4, 1.0f);
|
|
||||||
if (!colordata && num_verts > 0) {
|
|
||||||
colordata = malloc(num_verts*4*sizeof(float));
|
|
||||||
for (size_t i = 0; i < num_verts; i++) {
|
|
||||||
colordata[i*4+0] = 1.0f;
|
|
||||||
colordata[i*4+1] = 1.0f;
|
|
||||||
colordata[i*4+2] = 1.0f;
|
|
||||||
colordata[i*4+3] = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5) Indices (if present)
|
|
||||||
if (prim->indices) {
|
|
||||||
cgltf_accessor *idxAcc = prim->indices;
|
|
||||||
index_count = idxAcc->count;
|
|
||||||
indicesdata = malloc(index_count*sizeof(Uint16));
|
|
||||||
if (indicesdata) {
|
|
||||||
for (size_t i = 0; i < index_count; i++) {
|
|
||||||
// cgltf_accessor_read_index can read the index as uint32_t
|
|
||||||
uint32_t val = 0;
|
|
||||||
val = cgltf_accessor_read_index(idxAcc, i);
|
|
||||||
// NOTE: if val > 65535, you'll need 32-bit index buffers
|
|
||||||
indicesdata[i] = (Uint16)val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build a JS object for the mesh data
|
|
||||||
JSValue js_mesh = JS_NewObject(js);
|
|
||||||
|
|
||||||
// Positions
|
|
||||||
if (posdata && num_verts > 0)
|
|
||||||
JS_SetProperty(js, js_mesh, pos_atom,
|
|
||||||
make_gpu_buffer(js, posdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
|
||||||
|
|
||||||
// UV
|
|
||||||
if (uvdata && num_verts > 0)
|
|
||||||
JS_SetProperty(js, js_mesh, uv_atom,
|
|
||||||
make_gpu_buffer(js, uvdata, sizeof(float)*2*num_verts, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0));
|
|
||||||
|
|
||||||
// Color
|
|
||||||
if (colordata && num_verts > 0)
|
|
||||||
JS_SetProperty(js, js_mesh, color_atom,
|
|
||||||
make_gpu_buffer(js, colordata, sizeof(float)*4*num_verts, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0));
|
|
||||||
|
|
||||||
// Normal
|
|
||||||
if (normdata && num_verts > 0)
|
|
||||||
JS_SetProperty(js, js_mesh, norm_atom,
|
|
||||||
make_gpu_buffer(js, normdata, sizeof(float)*3*num_verts, JS_TYPED_ARRAY_FLOAT32, 3, 1, 0));
|
|
||||||
|
|
||||||
// Indices
|
|
||||||
if (indicesdata && index_count > 0)
|
|
||||||
JS_SetProperty(js, js_mesh, indices_atom,
|
|
||||||
make_gpu_buffer(js, indicesdata, sizeof(Uint16)*index_count, JS_TYPED_ARRAY_UINT16, 0, 1, 1));
|
|
||||||
|
|
||||||
// Metadata
|
|
||||||
JS_SetProperty(js, js_mesh, vertices_atom, number2js(js, (double)num_verts));
|
|
||||||
JS_SetProperty(js, js_mesh, count_atom, number2js(js, (double)index_count));
|
|
||||||
|
|
||||||
// Build final "model" object with mesh + material
|
|
||||||
JSValue model_obj = JS_NewObject(js);
|
|
||||||
JS_SetPropertyStr(js, model_obj, "mesh", js_mesh);
|
|
||||||
|
|
||||||
// Figure out the index of the material in data->materials. If prim->material is non-null,
|
|
||||||
// its index is `prim->material - data->materials`.
|
|
||||||
int mat_index = -1;
|
|
||||||
if (prim->material) mat_index = (int)(prim->material - data->materials);
|
|
||||||
if (mat_index >= 0 && mat_index < (int)data->materials_count)
|
|
||||||
JS_SetPropertyStr(js, model_obj, "material", JS_DupValue(js, materials[mat_index]));
|
|
||||||
else
|
|
||||||
JS_SetPropertyStr(js, model_obj, "material", JS_NewObject(js));
|
|
||||||
|
|
||||||
// Place this "model" object into our return array
|
|
||||||
uint32_t idx_in_array = js_arrlen(js,ret_arr);
|
|
||||||
JS_SetPropertyUint32(js, ret_arr, idx_in_array, model_obj);
|
|
||||||
|
|
||||||
// Cleanup (per-primitive)
|
|
||||||
if (posdata) free(posdata);
|
|
||||||
if (normdata) free(normdata);
|
|
||||||
if (uvdata) free(uvdata);
|
|
||||||
if (colordata) free(colordata);
|
|
||||||
if (indicesdata) free(indicesdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cgltf_free(data);
|
|
||||||
|
|
||||||
ret = ret_arr;
|
|
||||||
*/
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_SCALL(os_gltf_buffer,
|
|
||||||
// int buffer_idx = js2number(js,argv[1]);
|
|
||||||
// int type = js2number(js,argv[2]);
|
|
||||||
// cgltf_options options = {0};
|
|
||||||
// cgltf_data *data = NULL;
|
|
||||||
// cgltf_result result = cgltf_parse_file(&options, str, &data);
|
|
||||||
// result = cgltf_load_buffers(&options, data, str);
|
|
||||||
|
|
||||||
// SDL_GPUBuffer *b = SDL_CreateGPUBuffer(NULL,NULL);
|
|
||||||
// *b = accessor2buffer(&data->accessors[buffer_idx], type);
|
|
||||||
// cgltf_free(data);
|
|
||||||
|
|
||||||
// ret = sg_buffer2js(js,b);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_SCALL(os_gltf_skin,
|
|
||||||
cgltf_options options = {0};
|
|
||||||
cgltf_data *data = NULL;
|
|
||||||
cgltf_parse_file(&options,str,&data);
|
|
||||||
cgltf_load_buffers(&options,data,str);
|
|
||||||
|
|
||||||
if (data->skins_count <= 0) {
|
|
||||||
ret = (JS_UNDEFINED);
|
|
||||||
goto CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = skin2js(js,make_gltf_skin(data->skins+0, data));
|
|
||||||
|
|
||||||
CLEANUP:
|
|
||||||
cgltf_free(data);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSValue make_color_buffer(JSContext *js, colorf c, int verts)
|
JSValue make_color_buffer(JSContext *js, colorf c, int verts)
|
||||||
{
|
{
|
||||||
HMM_Vec4 *colordata = malloc(sizeof(*colordata)*verts);
|
HMM_Vec4 *colordata = malloc(sizeof(*colordata)*verts);
|
||||||
@@ -7065,79 +6755,6 @@ JSC_CCALL(os_make_line_prim,
|
|||||||
return prim;
|
return prim;
|
||||||
)
|
)
|
||||||
|
|
||||||
JSValue parmesh2js(JSContext *js,par_shapes_mesh *m)
|
|
||||||
{
|
|
||||||
return JS_UNDEFINED;
|
|
||||||
/* JSValue obj = JS_NewObject(js);
|
|
||||||
sg_buffer *pos = malloc(sizeof(*pos));
|
|
||||||
*pos = float_buffer(m->points, 3*m->npoints);
|
|
||||||
JS_SetPropertyStr(js, obj, "pos", sg_buffer2js(js,pos));
|
|
||||||
|
|
||||||
if (m->tcoords) {
|
|
||||||
sg_buffer *uv = malloc(sizeof(*uv));
|
|
||||||
*uv = texcoord_floats(m->tcoords, 2*m->npoints);
|
|
||||||
JS_SetPropertyStr(js, obj, "uv", sg_buffer2js(js,uv));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m->normals) {
|
|
||||||
sg_buffer *norm = malloc(sizeof(*norm));
|
|
||||||
*norm = normal_floats(m->normals, 3*m->npoints);
|
|
||||||
JS_SetPropertyStr(js, obj, "norm", sg_buffer2js(js,norm));
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_buffer *index = malloc(sizeof(*index));
|
|
||||||
*index = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data = {
|
|
||||||
.ptr = m->triangles,
|
|
||||||
.size = sizeof(*m->triangles)*3*m->ntriangles
|
|
||||||
},
|
|
||||||
.type = SG_BUFFERTYPE_INDEXBUFFER
|
|
||||||
});
|
|
||||||
JS_SetPropertyStr(js, obj, "index", sg_buffer2js(js,index));
|
|
||||||
|
|
||||||
JS_SetPropertyStr(js, obj, "count", number2js(js,3*m->ntriangles));
|
|
||||||
|
|
||||||
par_shapes_free_mesh(m);
|
|
||||||
return obj;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_cylinder,
|
|
||||||
return parmesh2js(js,par_shapes_create_cylinder(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_cone,
|
|
||||||
return parmesh2js(js,par_shapes_create_cone(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_disk,
|
|
||||||
return parmesh2js(js,par_shapes_create_parametric_disk(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_torus,
|
|
||||||
return parmesh2js(js,par_shapes_create_torus(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_sphere,
|
|
||||||
return parmesh2js(js,par_shapes_create_parametric_sphere(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_klein_bottle,
|
|
||||||
return parmesh2js(js,par_shapes_create_klein_bottle(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_trefoil_knot,
|
|
||||||
return parmesh2js(js,par_shapes_create_trefoil_knot(js2number(js,argv[0]), js2number(js,argv[1]), js2number(js,argv[2])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_hemisphere,
|
|
||||||
return parmesh2js(js,par_shapes_create_hemisphere(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_plane,
|
|
||||||
return parmesh2js(js,par_shapes_create_plane(js2number(js,argv[0]), js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
|
static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) {
|
||||||
if (JS_IsUndefined(ds->callback)) return;
|
if (JS_IsUndefined(ds->callback)) return;
|
||||||
uint8_t *rgb = malloc(frame->height*frame->width*4);
|
uint8_t *rgb = malloc(frame->height*frame->width*4);
|
||||||
@@ -7164,11 +6781,6 @@ JSC_CCALL(os_make_video,
|
|||||||
return datastream2js(js,ds);
|
return datastream2js(js,ds);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_skin_calculate,
|
|
||||||
skin *sk = js2skin(js,argv[0]);
|
|
||||||
skin_calculate(sk);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_rectpack,
|
JSC_CCALL(os_rectpack,
|
||||||
int width = js2number(js,argv[0]);
|
int width = js2number(js,argv[0]);
|
||||||
int height = js2number(js,argv[1]);
|
int height = js2number(js,argv[1]);
|
||||||
@@ -7200,27 +6812,6 @@ JSC_CCALL(os_rectpack,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_perlin,
|
|
||||||
HMM_Vec3 coord = js2vec3(js,argv[0]);
|
|
||||||
HMM_Vec3 wrap = js2vec3(js,argv[2]);
|
|
||||||
return number2js(js,stb_perlin_noise3_seed(coord.x, coord.y, coord.z, wrap.x, wrap.y, wrap.z, js2number(js,argv[1])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_ridge,
|
|
||||||
HMM_Vec3 c = js2vec3(js,argv[0]);
|
|
||||||
return number2js(js,stb_perlin_ridge_noise3(c.x, c.y, c.z, js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3]), js2number(js,argv[4])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_fbm,
|
|
||||||
HMM_Vec3 c = js2vec3(js,argv[0]);
|
|
||||||
return number2js(js,stb_perlin_fbm_noise3(c.x, c.y, c.z, js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_turbulence,
|
|
||||||
HMM_Vec3 c = js2vec3(js,argv[0]);
|
|
||||||
return number2js(js,stb_perlin_turbulence_noise3(c.x, c.y, c.z, js2number(js,argv[1]), js2number(js,argv[2]), js2number(js,argv[3])));
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_SCALL(os_kill,
|
JSC_SCALL(os_kill,
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
if (!strcmp(str, "SIGABRT")) sig = SIGABRT;
|
if (!strcmp(str, "SIGABRT")) sig = SIGABRT;
|
||||||
@@ -7232,16 +6823,8 @@ JSC_SCALL(os_kill,
|
|||||||
|
|
||||||
if (!sig) return JS_ThrowReferenceError(js, "string %s is not a valid signal", str);
|
if (!sig) return JS_ThrowReferenceError(js, "string %s is not a valid signal", str);
|
||||||
raise(sig);
|
raise(sig);
|
||||||
return JS_UNDEFINED;
|
|
||||||
)
|
)
|
||||||
int detectImageInWebcam(SDL_Surface *a, SDL_Surface *b);
|
|
||||||
/*JSC_CCALL(os_match_img,
|
|
||||||
SDL_Surface *img1 = js2SDL_Surface(js,argv[0]);
|
|
||||||
SDL_Surface *img2 = js2SDL_Surface(js,argv[1]);
|
|
||||||
int n = detectImageInWebcam(img1,img2);
|
|
||||||
return number2js(js,n);
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
JSC_CCALL(os_sleep,
|
JSC_CCALL(os_sleep,
|
||||||
double time = js2number(js,argv[0]);
|
double time = js2number(js,argv[0]);
|
||||||
time *= 1000000000.;
|
time *= 1000000000.;
|
||||||
@@ -7341,36 +6924,6 @@ JSC_CCALL(os_cull_sprites,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
struct qtree_sprite {
|
|
||||||
rect rect;
|
|
||||||
JSValue value;
|
|
||||||
};
|
|
||||||
|
|
||||||
int js_qtree_cmp(struct qtree_sprite *v, aabb *range)
|
|
||||||
{
|
|
||||||
rect ab = {
|
|
||||||
.x = range->center.x-range->dims.w,
|
|
||||||
.y = range->center.y-range->dims.h,
|
|
||||||
.w = range->dims.w*2.0,
|
|
||||||
.h = range->dims.h*2.0
|
|
||||||
};
|
|
||||||
return SDL_HasRectIntersectionFloat(&v->rect, &ab);
|
|
||||||
}
|
|
||||||
|
|
||||||
int js_qtree_rm(struct qtree_sprite *val, struct qtree_sprite *cmp)
|
|
||||||
{
|
|
||||||
int same = JS_SameValue(global_js, val->value, cmp->value);
|
|
||||||
if (same)
|
|
||||||
JS_FreeValue(global_js, val->value);
|
|
||||||
return same;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_quadtree,
|
|
||||||
rect area = js2rect(js,argv[0]);
|
|
||||||
qtree tree = qtree_new(area.x,area.y,area.w,area.h, js_qtree_cmp, js_qtree_rm);
|
|
||||||
return qtree2js(js,tree);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_rtree,
|
JSC_CCALL(os_make_rtree,
|
||||||
struct rtree *tree = rtree_new();
|
struct rtree *tree = rtree_new();
|
||||||
if (!tree) return JS_ThrowOutOfMemory(js);
|
if (!tree) return JS_ThrowOutOfMemory(js);
|
||||||
@@ -7421,106 +6974,216 @@ typedef struct {
|
|||||||
size_t fn_count;
|
size_t fn_count;
|
||||||
} ModuleEntry;
|
} ModuleEntry;
|
||||||
|
|
||||||
JSC_SSCALL(os_trimchr,
|
JSC_CCALL(os_totalmem, return number2js(js, SDL_GetSystemRAM()))
|
||||||
int len;
|
JSC_CCALL(os_platform, return JS_NewString(js,SDL_GetPlatform()))
|
||||||
JS_GETPROP(js,len,argv[0],length,number)
|
JSC_CCALL(os_hostname,
|
||||||
const char *start = str;
|
char buf[256];
|
||||||
|
if (gethostname(buf,sizeof(buf)) == 0) return JS_NewString(js,buf);
|
||||||
while (*start == *str2)
|
return JS_NewString(js,"");
|
||||||
start++;
|
)
|
||||||
|
|
||||||
const char *end = str + len-1;
|
JSC_CCALL(os_freemem,
|
||||||
while(*end == *str2)
|
#ifdef _WIN32
|
||||||
end--;
|
MEMORYSTATUSEX statex;
|
||||||
|
statex.dwLength = sizeof(statex);
|
||||||
ret = JS_NewStringLen(js, start, end-start+1);
|
if (!GlobalMemoryStatusEx(&statex)) return JS_ThrowInternalError(js,"GlobalMemoryStatusEx failed");
|
||||||
|
return JS_NewInt64(js,(int64_t)statex.ullAvailPhys);
|
||||||
|
#elif defined(__linux__)
|
||||||
|
struct sysinfo info;
|
||||||
|
if (sysinfo(&info) == 0)
|
||||||
|
return JS_NewInt64(js,(int64_t)info.freeram * info.mem_unit);
|
||||||
|
return JS_NewInt64(js,0);
|
||||||
|
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
|
// A very rough fallback using the same sysconf approach
|
||||||
|
// (macOS or *BSD typically need specialized APIs to get free mem accurately)
|
||||||
|
// This is often only "unused" pages, ignoring caches, etc.
|
||||||
|
long pages = sysconf(_SC_AVPHYS_PAGES);
|
||||||
|
long page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
|
if (pages < 0 || page_size < 0) return JS_NewInt64(js,0);
|
||||||
|
return JS_NewInt64(js,(int64_t)pages * (int64_t)page_size);
|
||||||
|
#else
|
||||||
|
// Fallback: unknown
|
||||||
|
return JS_NewInt64(js,0);
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_arch,
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64)
|
||||||
|
return JS_NewString(js,"x64");
|
||||||
|
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
return JS_NewString(js,"arm64");
|
||||||
|
#elif defined(__arm__) || defined(_M_ARM)
|
||||||
|
return JS_NewString(js,"arm");
|
||||||
|
#elif defined(__i386__) || defined(_M_IX86)
|
||||||
|
return JS_NewString(js,"ia32");
|
||||||
|
#elif defined(__loongarch__) || defined(__loongarch32) || defined(__loongarch64)
|
||||||
|
return JS_NewString(js,"loong64");
|
||||||
|
#elif defined(__mips__) || defined(__mips) || defined(_M_MIPS)
|
||||||
|
// You might want to distinguish mips vs mipsel
|
||||||
|
return JS_NewString(js,"mips");
|
||||||
|
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_M_PPC)
|
||||||
|
// You might want to distinguish ppc vs ppc64, big-endian vs little-endian
|
||||||
|
return JS_NewString(js,"ppc64");
|
||||||
|
#elif defined(__riscv) && __riscv_xlen == 64
|
||||||
|
return JS_NewString(js,"riscv64");
|
||||||
|
#elif defined(__s390x__)
|
||||||
|
return JS_NewString(js,"s390x");
|
||||||
|
#else
|
||||||
|
return JS_NewString(js,"unknown");
|
||||||
|
#endif
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_version,
|
JSC_CCALL(os_version,
|
||||||
return JS_NewString(js,PROSPERON_VERSION);
|
#ifdef _WIN32
|
||||||
)
|
typedef LONG (WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||||
|
HMODULE h = GetModuleHandleA("ntdll.dll");
|
||||||
JSC_CCALL(os_commit,
|
if (h) {
|
||||||
return JS_NewString(js,PROSPERON_COMMIT);
|
RtlGetVersionPtr fx = (RtlGetVersionPtr)GetProcAddress(h, "RtlGetVersion");
|
||||||
|
if (fx) {
|
||||||
|
RTL_OSVERSIONINFOW ver;
|
||||||
|
memset(&ver, 0, sizeof(ver));
|
||||||
|
ver.dwOSVersionInfoSize = sizeof(ver);
|
||||||
|
if (!fx(&ver)) {
|
||||||
|
char buf[128];
|
||||||
|
sprintf(buf, "%u.%u.%u",
|
||||||
|
(unsigned)ver.dwMajorVersion,
|
||||||
|
(unsigned)ver.dwMinorVersion,
|
||||||
|
(unsigned)ver.dwBuildNumber
|
||||||
|
);
|
||||||
|
return JS_NewString(js, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OSVERSIONINFOW wver;
|
||||||
|
memset(&wver, 0, sizeof(wver));
|
||||||
|
wver.dwOSVersionInfoSize = sizeof(wver);
|
||||||
|
if (GetVersionExW(&wver)) {
|
||||||
|
char buf[128];
|
||||||
|
sprintf(buf, "%u.%u.%u",
|
||||||
|
(unsigned)wver.dwMajorVersion,
|
||||||
|
(unsigned)wver.dwMinorVersion,
|
||||||
|
(unsigned)wver.dwBuildNumber
|
||||||
|
);
|
||||||
|
return JS_NewString(js, buf);
|
||||||
|
}
|
||||||
|
return JS_NewString(js, "Windows_Unknown");
|
||||||
|
#else
|
||||||
|
struct utsname info;
|
||||||
|
if (!uname(&info)) return JS_NewString(js, info.release);
|
||||||
|
return JS_NewString(js, "");
|
||||||
|
#endif
|
||||||
)
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, version, 0),
|
|
||||||
MIST_FUNC_DEF(os, commit, 0),
|
|
||||||
MIST_FUNC_DEF(os, engine_start, 1),
|
|
||||||
MIST_FUNC_DEF(os, engine_input, 1),
|
|
||||||
MIST_FUNC_DEF(os, turbulence, 4),
|
|
||||||
MIST_FUNC_DEF(os, model_buffer, 1),
|
|
||||||
MIST_FUNC_DEF(os, clean_transforms, 0),
|
|
||||||
MIST_FUNC_DEF(os, fbm, 4),
|
|
||||||
MIST_FUNC_DEF(os, ridge, 5),
|
|
||||||
MIST_FUNC_DEF(os, perlin, 3),
|
|
||||||
MIST_FUNC_DEF(os, rectpack, 3),
|
|
||||||
MIST_FUNC_DEF(os, cwd, 0),
|
|
||||||
MIST_FUNC_DEF(os, rusage, 0),
|
|
||||||
MIST_FUNC_DEF(os, mallinfo, 0),
|
|
||||||
MIST_FUNC_DEF(os, env, 1),
|
|
||||||
MIST_FUNC_DEF(os, sys, 0),
|
|
||||||
MIST_FUNC_DEF(os, system, 1),
|
|
||||||
MIST_FUNC_DEF(os, exit, 1),
|
|
||||||
MIST_FUNC_DEF(os, gc, 0),
|
|
||||||
MIST_FUNC_DEF(os, now, 0),
|
|
||||||
MIST_FUNC_DEF(os, guid, 0),
|
|
||||||
MIST_FUNC_DEF(os, openurl, 1),
|
|
||||||
MIST_FUNC_DEF(os, push_event, 1),
|
|
||||||
MIST_FUNC_DEF(os, eval, 2),
|
|
||||||
MIST_FUNC_DEF(os, make_quadtree, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_rtree, 0),
|
|
||||||
MIST_FUNC_DEF(os, make_texture, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_gif, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_aseprite, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_surface, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_cursor, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_font, 2),
|
|
||||||
MIST_FUNC_DEF(os, make_transform, 0),
|
MIST_FUNC_DEF(os, make_transform, 0),
|
||||||
MIST_FUNC_DEF(os, make_sprite, 0),
|
MIST_FUNC_DEF(os, clean_transforms, 0),
|
||||||
MIST_FUNC_DEF(os, make_line_prim, 5),
|
|
||||||
MIST_FUNC_DEF(os, make_cylinder, 2),
|
MIST_FUNC_DEF(os, platform, 0),
|
||||||
MIST_FUNC_DEF(os, make_cone, 2),
|
MIST_FUNC_DEF(os, arch, 0),
|
||||||
MIST_FUNC_DEF(os, make_disk, 2),
|
MIST_FUNC_DEF(os, totalmem, 0),
|
||||||
MIST_FUNC_DEF(os, make_torus, 3),
|
MIST_FUNC_DEF(os, freemem, 0),
|
||||||
MIST_FUNC_DEF(os, make_sphere, 2),
|
MIST_FUNC_DEF(os, hostname, 0),
|
||||||
MIST_FUNC_DEF(os, make_klein_bottle, 2),
|
MIST_FUNC_DEF(os, version, 0),
|
||||||
MIST_FUNC_DEF(os, make_trefoil_knot, 3),
|
|
||||||
MIST_FUNC_DEF(os, make_hemisphere, 2),
|
MIST_FUNC_DEF(os, kill, 1),
|
||||||
MIST_FUNC_DEF(os, make_plane, 2),
|
MIST_FUNC_DEF(os, exit, 1),
|
||||||
MIST_FUNC_DEF(os, make_video, 1),
|
|
||||||
|
MIST_FUNC_DEF(os, now, 0),
|
||||||
|
|
||||||
|
MIST_FUNC_DEF(os, openurl, 1),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MIST_FUNC_DEF(os, make_timer, 1),
|
MIST_FUNC_DEF(os, make_timer, 1),
|
||||||
MIST_FUNC_DEF(os, make_text_buffer, 6),
|
|
||||||
MIST_FUNC_DEF(os, update_timers, 1),
|
MIST_FUNC_DEF(os, update_timers, 1),
|
||||||
MIST_FUNC_DEF(os, mem, 1),
|
|
||||||
MIST_FUNC_DEF(os, mem_limit, 1),
|
|
||||||
MIST_FUNC_DEF(os, gc_threshold, 1),
|
|
||||||
MIST_FUNC_DEF(os, max_stacksize, 1),
|
|
||||||
MIST_FUNC_DEF(os, rt_info, 0),
|
|
||||||
MIST_FUNC_DEF(os, dump_mem, 0),
|
|
||||||
MIST_FUNC_DEF(os, dump_shapes, 0),
|
|
||||||
MIST_FUNC_DEF(os, dump_atoms,0),
|
|
||||||
MIST_FUNC_DEF(os, calc_mem, 1),
|
|
||||||
MIST_FUNC_DEF(os, memstate, 0),
|
|
||||||
MIST_FUNC_DEF(os, value_id, 1),
|
|
||||||
MIST_FUNC_DEF(os, gltf_buffer, 3),
|
|
||||||
MIST_FUNC_DEF(os, gltf_skin, 1),
|
|
||||||
MIST_FUNC_DEF(os, skin_calculate, 1),
|
|
||||||
MIST_FUNC_DEF(os, kill, 1),
|
|
||||||
// MIST_FUNC_DEF(os, match_img, 2),
|
|
||||||
MIST_FUNC_DEF(os, sleep, 1),
|
MIST_FUNC_DEF(os, sleep, 1),
|
||||||
MIST_FUNC_DEF(os, battery_pct, 0),
|
MIST_FUNC_DEF(os, battery_pct, 0),
|
||||||
MIST_FUNC_DEF(os, battery_voltage, 0),
|
MIST_FUNC_DEF(os, battery_voltage, 0),
|
||||||
MIST_FUNC_DEF(os, battery_seconds, 0),
|
MIST_FUNC_DEF(os, battery_seconds, 0),
|
||||||
MIST_FUNC_DEF(os, power_state, 0),
|
MIST_FUNC_DEF(os, power_state, 0),
|
||||||
MIST_FUNC_DEF(os, insertion_sort, 2),
|
|
||||||
|
MIST_FUNC_DEF(os, on, 2),
|
||||||
|
|
||||||
|
MIST_FUNC_DEF(os, rt_info, 0),
|
||||||
|
MIST_FUNC_DEF(os, rusage, 0),
|
||||||
|
MIST_FUNC_DEF(os, mallinfo, 0),
|
||||||
|
|
||||||
|
// dangerous ones that need disabled for shipping
|
||||||
|
MIST_FUNC_DEF(os, env, 1),
|
||||||
|
MIST_FUNC_DEF(os, system, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_js_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(os, dump_mem, 0),
|
||||||
|
MIST_FUNC_DEF(os, dump_shapes, 0),
|
||||||
|
MIST_FUNC_DEF(os, dump_atoms,0),
|
||||||
|
MIST_FUNC_DEF(os, calc_mem, 1),
|
||||||
|
MIST_FUNC_DEF(os, mem, 1),
|
||||||
|
MIST_FUNC_DEF(os, mem_limit, 1),
|
||||||
|
MIST_FUNC_DEF(os, gc_threshold, 1),
|
||||||
|
MIST_FUNC_DEF(os, max_stacksize, 1),
|
||||||
|
MIST_FUNC_DEF(os, memstate, 0),
|
||||||
|
MIST_FUNC_DEF(os, gc, 0),
|
||||||
|
MIST_FUNC_DEF(os, eval, 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_util_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(os, guid, 0),
|
||||||
|
MIST_FUNC_DEF(os, insertion_sort, 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_graphics_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(gpu, make_sprite_mesh, 2),
|
||||||
|
MIST_FUNC_DEF(gpu, make_sprite_queue, 4),
|
||||||
|
MIST_FUNC_DEF(os, make_text_buffer, 6),
|
||||||
|
MIST_FUNC_DEF(os, rectpack, 3),
|
||||||
|
MIST_FUNC_DEF(os, make_rtree, 0),
|
||||||
|
MIST_FUNC_DEF(os, make_texture, 1),
|
||||||
|
MIST_FUNC_DEF(os, make_gif, 1),
|
||||||
|
MIST_FUNC_DEF(os, make_aseprite, 1),
|
||||||
MIST_FUNC_DEF(os, cull_sprites, 2),
|
MIST_FUNC_DEF(os, cull_sprites, 2),
|
||||||
MIST_FUNC_DEF(os, rects_to_sprites,2),
|
MIST_FUNC_DEF(os, rects_to_sprites,2),
|
||||||
MIST_FUNC_DEF(os, on, 2),
|
MIST_FUNC_DEF(os, make_surface, 1),
|
||||||
MIST_FUNC_DEF(os, trimchr, 2),
|
MIST_FUNC_DEF(os, make_cursor, 1),
|
||||||
|
MIST_FUNC_DEF(os, make_font, 2),
|
||||||
|
MIST_FUNC_DEF(os, make_sprite, 0),
|
||||||
|
MIST_FUNC_DEF(os, make_line_prim, 5),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_video_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(os, make_video, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
void gui_input(SDL_Event *e);
|
||||||
|
// Polls and handles all input events
|
||||||
|
JSC_CCALL(os_engine_input,
|
||||||
|
SDL_Event event;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
#ifndef NEDITOR
|
||||||
|
gui_input(&event);
|
||||||
|
#endif
|
||||||
|
JSValue e = event2js(js,event);
|
||||||
|
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
|
||||||
|
uncaught_exception(js,ret);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(os_push_event,
|
||||||
|
SDL_UserEvent e;
|
||||||
|
SDL_zero(e);
|
||||||
|
e.type = SDL_EVENT_USER;
|
||||||
|
e.timestamp = SDL_GetTicksNS();
|
||||||
|
e.code = 0;
|
||||||
|
JSValue fn = JS_DupValue(js,argv[0]);
|
||||||
|
e.data1 = malloc(sizeof(JSValue));
|
||||||
|
*(JSValue*)e.data1 = fn;
|
||||||
|
SDL_PushEvent(&e);
|
||||||
|
)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_event_funcs[] = {
|
||||||
|
MIST_FUNC_DEF(os, push_event, 1),
|
||||||
|
MIST_FUNC_DEF(os, engine_input, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
|
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
|
||||||
@@ -7533,6 +7196,11 @@ static ModuleEntry module_registry[] = {
|
|||||||
MISTLINE(math),
|
MISTLINE(math),
|
||||||
MISTLINE(spline),
|
MISTLINE(spline),
|
||||||
MISTLINE(geometry),
|
MISTLINE(geometry),
|
||||||
|
MISTLINE(graphics),
|
||||||
|
MISTLINE(js),
|
||||||
|
MISTLINE(util),
|
||||||
|
MISTLINE(video),
|
||||||
|
MISTLINE(event),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_SCALL(os_use_embed,
|
JSC_SCALL(os_use_embed,
|
||||||
@@ -7565,41 +7233,6 @@ JSC_SCALL(os_use_dyn,
|
|||||||
SDL_UnloadObject(ptr);
|
SDL_UnloadObject(ptr);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(qtree_insert,
|
|
||||||
qtree tree = js2qtree(js,self);
|
|
||||||
JSValue v = argv[0];
|
|
||||||
struct qtree_sprite *item = malloc(sizeof(*item));
|
|
||||||
item->value = JS_DupValue(js,v);
|
|
||||||
JS_GETATOM(js,item->rect,v,rect_atom,rect)
|
|
||||||
qtree_insert(tree, item);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(qtree_remove,
|
|
||||||
struct qtree_sprite tmp;
|
|
||||||
tmp.value = argv[0];
|
|
||||||
qtree tree = js2qtree(js,self);
|
|
||||||
qtree_remove(tree, &tmp);
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(qtree_query,
|
|
||||||
qtree tree = js2qtree(js,self);
|
|
||||||
rect area = js2rect(js,argv[0]);
|
|
||||||
uint32_t n;
|
|
||||||
struct qtree_sprite **items = qtree_findInArea(tree, area.x, area.y, area.w, area.h, &n);
|
|
||||||
|
|
||||||
ret = JS_NewArray(js);
|
|
||||||
for (int i = 0; i < n; i++)
|
|
||||||
JS_SetPropertyUint32(js,ret,i, JS_DupValue(js,items[i]->value));
|
|
||||||
|
|
||||||
free(items);
|
|
||||||
)
|
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_qtree_funcs[] = {
|
|
||||||
MIST_FUNC_DEF(qtree, insert, 1),
|
|
||||||
MIST_FUNC_DEF(qtree, remove, 1),
|
|
||||||
MIST_FUNC_DEF(qtree, query, 2),
|
|
||||||
};
|
|
||||||
|
|
||||||
JSC_CCALL(rtree_add,
|
JSC_CCALL(rtree_add,
|
||||||
rtree *tree = js2rtree(js,self);
|
rtree *tree = js2rtree(js,self);
|
||||||
JSValue v = argv[0];
|
JSValue v = argv[0];
|
||||||
@@ -7832,19 +7465,18 @@ static void signal_handler(int sig) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!str) return;
|
if (!str) return;
|
||||||
script_evalf("prosperon.%s?.();", str);
|
script_evalf("prosperon.dispatch('%s')", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit_handler()
|
static void exit_handler()
|
||||||
{
|
{
|
||||||
script_evalf("prosperon.exit?.();");
|
script_evalf("prosperon.dispatch('exit')");
|
||||||
script_stop();
|
script_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffi_load(JSContext *js) {
|
void ffi_load(JSContext *js, int argc, char **argv) {
|
||||||
JSValue globalThis = JS_GetGlobalObject(js);
|
JSValue globalThis = JS_GetGlobalObject(js);
|
||||||
|
|
||||||
QJSCLASSPREP_FUNCS(qtree)
|
|
||||||
QJSCLASSPREP_FUNCS(rtree)
|
QJSCLASSPREP_FUNCS(rtree)
|
||||||
QJSCLASSPREP_FUNCS(SDL_Window)
|
QJSCLASSPREP_FUNCS(SDL_Window)
|
||||||
QJSCLASSPREP_FUNCS(SDL_Surface)
|
QJSCLASSPREP_FUNCS(SDL_Surface)
|
||||||
@@ -7883,6 +7515,10 @@ void ffi_load(JSContext *js) {
|
|||||||
QJSGLOBALCLASS(os);
|
QJSGLOBALCLASS(os);
|
||||||
QJSGLOBALCLASS(console);
|
QJSGLOBALCLASS(console);
|
||||||
|
|
||||||
|
JSValue jsobject = JS_GetPropertyStr(js,globalThis, "Object");
|
||||||
|
JS_SetPropertyStr(js, jsobject, "id", JS_NewCFunction(js, js_os_value_id, "id", 1));
|
||||||
|
JS_FreeValue(js,jsobject);
|
||||||
|
|
||||||
JSValue jsarray = JS_GetPropertyStr(js,globalThis, "Array");
|
JSValue jsarray = JS_GetPropertyStr(js,globalThis, "Array");
|
||||||
JSValue array_proto = JS_GetPropertyStr(js,jsarray, "prototype");
|
JSValue array_proto = JS_GetPropertyStr(js,jsarray, "prototype");
|
||||||
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, countof(js_array_funcs));
|
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, countof(js_array_funcs));
|
||||||
@@ -8008,5 +7644,18 @@ void ffi_load(JSContext *js) {
|
|||||||
|
|
||||||
m_seedRand(&mrand, time(NULL));
|
m_seedRand(&mrand, time(NULL));
|
||||||
|
|
||||||
|
JSValue prosp = JS_NewObject(js);
|
||||||
|
|
||||||
|
JSValue args = JS_NewArray(js);
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
JS_SetPropertyUint32(js,args, i, JS_NewString(js,argv[i]));
|
||||||
|
|
||||||
|
JS_SetPropertyStr(js,prosp,"argv", args);
|
||||||
|
JS_SetPropertyStr(js,prosp, "version", JS_NewString(js,PROSPERON_VERSION));
|
||||||
|
JS_SetPropertyStr(js,prosp,"revision",JS_NewString(js,PROSPERON_COMMIT));
|
||||||
|
JS_SetPropertyStr(js,prosp,"engine_start", JS_NewCFunction(js,js_os_engine_start, "engine_start", 1));
|
||||||
|
|
||||||
|
JS_SetPropertyStr(js,globalThis,"prosperon", prosp);
|
||||||
|
|
||||||
JS_FreeValue(js,globalThis);
|
JS_FreeValue(js,globalThis);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef FFI_H
|
#ifndef FFI_H
|
||||||
#define FFI_H
|
#define FFI_H
|
||||||
#include <quickjs.h>
|
#include <quickjs.h>
|
||||||
void ffi_load(JSContext *js);
|
void ffi_load(JSContext *js, int argc, char **argv);
|
||||||
int js_print_exception(JSContext *js, JSValue v);
|
int js_print_exception(JSContext *js, JSValue v);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "yugine.h"
|
|
||||||
|
|
||||||
#include "jsffi.h"
|
#include "jsffi.h"
|
||||||
|
|
||||||
|
|||||||
12
source/prosperon.c
Normal file
12
source/prosperon.c
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "script.h"
|
||||||
|
#include "physfs.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
PHYSFS_init(argv[0]);
|
||||||
|
char *base = PHYSFS_getBaseDir();
|
||||||
|
PHYSFS_setWriteDir(base);
|
||||||
|
PHYSFS_mount(base,NULL,0);
|
||||||
|
PHYSFS_mount(base,"/",0);
|
||||||
|
script_startup(argc, argv); // runs engine.js
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -61,7 +61,7 @@ int js_interrupt(JSRuntime *rt, void *data)
|
|||||||
// printf("INTERRUPT\n");
|
// printf("INTERRUPT\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_startup() {
|
void script_startup(int argc, char **argv) {
|
||||||
rt = JS_NewRuntime();
|
rt = JS_NewRuntime();
|
||||||
js = JS_NewContextRaw(rt);
|
js = JS_NewContextRaw(rt);
|
||||||
JS_AddIntrinsicBaseObjects(js);
|
JS_AddIntrinsicBaseObjects(js);
|
||||||
@@ -77,7 +77,7 @@ void script_startup() {
|
|||||||
JS_AddIntrinsicBigDecimal(js);
|
JS_AddIntrinsicBigDecimal(js);
|
||||||
JS_AddIntrinsicOperators(js);
|
JS_AddIntrinsicOperators(js);
|
||||||
|
|
||||||
ffi_load(js);
|
ffi_load(js, argc, argv);
|
||||||
|
|
||||||
char *eng = read_file("core/scripts/engine.js");
|
char *eng = read_file("core/scripts/engine.js");
|
||||||
JSValue v = script_eval(js, "core/scripts/engine.js", eng);
|
JSValue v = script_eval(js, "core/scripts/engine.js", eng);
|
||||||
@@ -87,11 +87,12 @@ void script_startup() {
|
|||||||
|
|
||||||
void script_stop()
|
void script_stop()
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
JS_FreeContext(js);
|
JS_FreeContext(js);
|
||||||
js = NULL;
|
|
||||||
JS_FreeRuntime(rt);
|
JS_FreeRuntime(rt);
|
||||||
|
JS_FreeValue(js,on_exception);
|
||||||
|
|
||||||
rt = NULL;
|
rt = NULL;
|
||||||
|
js = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uncaught_exception(JSContext *js, JSValue v)
|
void uncaught_exception(JSContext *js, JSValue v)
|
||||||
@@ -118,10 +119,6 @@ void uncaught_exception(JSContext *js, JSValue v)
|
|||||||
JS_FreeValue(js,v);
|
JS_FreeValue(js,v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_mem_limit(size_t limit) { JS_SetMemoryLimit(rt, limit); }
|
|
||||||
void script_gc_threshold(size_t threshold) { JS_SetGCThreshold(rt, threshold); }
|
|
||||||
void script_max_stacksize(size_t size) { JS_SetMaxStackSize(rt, size); }
|
|
||||||
|
|
||||||
void script_evalf(const char *format, ...)
|
void script_evalf(const char *format, ...)
|
||||||
{
|
{
|
||||||
JSValue obj;
|
JSValue obj;
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
#include "yugine.h"
|
|
||||||
#include "script.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
PHYSFS_init(argv[0]);
|
|
||||||
char *base = PHYSFS_getBaseDir();
|
|
||||||
PHYSFS_setWriteDir(base);
|
|
||||||
PHYSFS_mount(base,NULL,0);
|
|
||||||
PHYSFS_mount(base,"/",0);
|
|
||||||
script_startup(); // runs engine.js
|
|
||||||
|
|
||||||
int argsize = 0;
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
argsize += strlen(argv[i]);
|
|
||||||
if (argc > i+1) argsize++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char cmdstr[argsize+1];
|
|
||||||
cmdstr[0] = '\0';
|
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
|
||||||
strcat(cmdstr, argv[i]);
|
|
||||||
if (argc > i+1) strcat(cmdstr, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
script_evalf("cmd_args('%s');", cmdstr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef YUGINE_H
|
|
||||||
#define YUGINE_H
|
|
||||||
|
|
||||||
#include "script.h"
|
|
||||||
|
|
||||||
void engine_start(JSContext *js, JSValue start_fn, JSValue proc_fn, float x, float y); /* fn runs after the engine starts */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user