push
This commit is contained in:
@@ -226,7 +226,7 @@ action.on_input = function(action_id, evt)
|
||||
var matched_actions = []
|
||||
arrfor(array(this.action_map), mapped_action => {
|
||||
if (find(this.action_map[mapped_action], action_id) != null) {
|
||||
matched_actions.push(mapped_action)
|
||||
push(matched_actions, mapped_action)
|
||||
|
||||
if (evt.pressed)
|
||||
this.down[mapped_action] = true
|
||||
@@ -256,14 +256,14 @@ action.rebind_action = function(action_name, new_key) {
|
||||
arrfor(array(this.action_map), act => {
|
||||
var idx = find(this.action_map[act], new_key)
|
||||
if (idx != null)
|
||||
this.action_map[act].splice(idx, 1)
|
||||
this.action_map[act] = array(array(this.action_map[act], 0, idx), array(this.action_map[act], idx+1))
|
||||
})
|
||||
|
||||
// Clear existing bindings for the current device from the target action
|
||||
var target_bindings = this.action_map[action_name]
|
||||
for (var i = length(target_bindings) - 1; i >= 0; i--) {
|
||||
if (detect_device(target_bindings[i]) == this.current_device)
|
||||
target_bindings.splice(i, 1)
|
||||
this.action_map[action_name] = array(array(this.action_map[action_name], 0, i), array(this.action_map[action_name], i+1))
|
||||
}
|
||||
|
||||
// Only insert into the target if it's the right device
|
||||
|
||||
16
clay.cm
16
clay.cm
@@ -130,7 +130,7 @@ function build_drawables(node, root_height, parent_abs_x, parent_abs_y, parent_s
|
||||
// Background
|
||||
if (node.config.background_image) {
|
||||
if (node.config.slice) {
|
||||
drawables.push({
|
||||
push(drawables, {
|
||||
type: 'sprite',
|
||||
image: node.config.background_image,
|
||||
pos: {x: vis_x, y: vis_y},
|
||||
@@ -142,7 +142,7 @@ function build_drawables(node, root_height, parent_abs_x, parent_abs_y, parent_s
|
||||
scissor: current_scissor
|
||||
})
|
||||
} else {
|
||||
drawables.push({
|
||||
push(drawables, {
|
||||
type: 'sprite',
|
||||
image: node.config.background_image,
|
||||
pos: {x: vis_x, y: vis_y},
|
||||
@@ -154,7 +154,7 @@ function build_drawables(node, root_height, parent_abs_x, parent_abs_y, parent_s
|
||||
})
|
||||
}
|
||||
} else if (node.config.background_color) {
|
||||
drawables.push({
|
||||
push(drawables, {
|
||||
type: 'rect',
|
||||
pos: {x: vis_x, y: vis_y},
|
||||
width: rect.width,
|
||||
@@ -167,7 +167,7 @@ function build_drawables(node, root_height, parent_abs_x, parent_abs_y, parent_s
|
||||
|
||||
// Content (Image/Text)
|
||||
if (node.config.image) {
|
||||
drawables.push({
|
||||
push(drawables, {
|
||||
type: 'sprite',
|
||||
image: node.config.image,
|
||||
pos: {x: vis_x, y: vis_y},
|
||||
@@ -180,7 +180,7 @@ function build_drawables(node, root_height, parent_abs_x, parent_abs_y, parent_s
|
||||
}
|
||||
|
||||
if (node.config.text) {
|
||||
drawables.push({
|
||||
push(drawables, {
|
||||
type: 'text',
|
||||
text: node.config.text,
|
||||
font: node.config.font_path,
|
||||
@@ -249,15 +249,15 @@ function push_node(configs, contain_mode) {
|
||||
|
||||
// Add to parent
|
||||
var parent = tree_stack[length(tree_stack)-1]
|
||||
parent.children.push(node)
|
||||
push(parent.children, node)
|
||||
lay_ctx.insert(parent.id, item)
|
||||
|
||||
tree_stack.push(node)
|
||||
push(tree_stack, node)
|
||||
return node
|
||||
}
|
||||
|
||||
function pop_node() {
|
||||
tree_stack.pop()
|
||||
pop(tree_stack)
|
||||
}
|
||||
|
||||
// Generic container
|
||||
|
||||
@@ -74,7 +74,7 @@ clay_input.click = function click(tree_root, mousepos, button = 'left') {
|
||||
clay_input.get_actionable = function get_actionable(tree_root) {
|
||||
var actionable = []
|
||||
function walk(node) {
|
||||
if (node.config.action) actionable.push(node)
|
||||
if (node.config.action) push(actionable, node)
|
||||
if (node[clay.CHILDREN])
|
||||
arrfor(node[clay.CHILDREN], walk)
|
||||
}
|
||||
@@ -85,7 +85,7 @@ clay_input.get_actionable = function get_actionable(tree_root) {
|
||||
clay_input.filter = function filter(tree_root, predicate) {
|
||||
var results = []
|
||||
function rec(node) {
|
||||
if (predicate(node)) results.push(node)
|
||||
if (predicate(node)) push(results, node)
|
||||
if (node[clay.CHILDREN])
|
||||
arrfor(node[clay.CHILDREN], rec)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ compositor.compile = function(config) {
|
||||
|
||||
// Clear screen
|
||||
if (config.clear)
|
||||
ctx.passes.push({type: 'clear', target: 'screen', color: config.clear})
|
||||
push(ctx.passes, {type: 'clear', target: 'screen', color: config.clear})
|
||||
|
||||
// Process each plane (supports both 'planes' and legacy 'layers' key)
|
||||
var planes = config.planes || config.layers || []
|
||||
@@ -41,7 +41,7 @@ compositor.compile = function(config) {
|
||||
}
|
||||
|
||||
function compile_imgui_layer(layer, ctx) {
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'imgui',
|
||||
target: 'screen',
|
||||
draw: layer.draw
|
||||
@@ -70,7 +70,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
// Add manual drawables
|
||||
if (plane_config.drawables) {
|
||||
for (var i = 0; i < length(plane_config.drawables); i++)
|
||||
all_sprites.push(plane_config.drawables[i])
|
||||
push(all_sprites, plane_config.drawables[i])
|
||||
}
|
||||
|
||||
// Find which sprites belong to groups with effects
|
||||
@@ -98,14 +98,14 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
if (group_effects[gname]) {
|
||||
if (!effect_groups[gname])
|
||||
effect_groups[gname] = {sprites: [], effects: group_effects[gname].effects}
|
||||
effect_groups[gname].sprites.push(s)
|
||||
push(effect_groups[gname].sprites, s)
|
||||
assigned = true
|
||||
break // Only assign to first matching effect group
|
||||
}
|
||||
}
|
||||
|
||||
// Add to base sprites if not assigned to effect group and not mask-only
|
||||
if (!assigned && !is_mask_only) base_sprites.push(s)
|
||||
if (!assigned && !is_mask_only) push(base_sprites, s)
|
||||
}
|
||||
|
||||
// Allocate plane target
|
||||
@@ -113,7 +113,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
|
||||
// Clear plane
|
||||
if (plane_config.clear)
|
||||
ctx.passes.push({type: 'clear', target: plane_target, color: plane_config.clear})
|
||||
push(ctx.passes, {type: 'clear', target: plane_target, color: plane_config.clear})
|
||||
|
||||
// Render each effect group to temp target, apply effects, composite back
|
||||
arrfor(array(effect_groups), gname => {
|
||||
@@ -123,7 +123,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
var group_target = ctx.alloc(res.width, res.height, gname + '_content')
|
||||
|
||||
// Render group content
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'render',
|
||||
renderer: 'film2d',
|
||||
drawables: eg.sprites,
|
||||
@@ -142,7 +142,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
}
|
||||
|
||||
// Composite result to plane
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'composite',
|
||||
source: current,
|
||||
dest: plane_target,
|
||||
@@ -154,7 +154,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
|
||||
// Render base sprites (no effects)
|
||||
if (length(base_sprites) > 0) {
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'render',
|
||||
renderer: 'film2d',
|
||||
drawables: base_sprites,
|
||||
@@ -167,7 +167,7 @@ function compile_plane(plane_config, ctx, group_effects) {
|
||||
}
|
||||
|
||||
// Composite plane to screen
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'blit_to_screen',
|
||||
source: plane_target,
|
||||
source_size: res,
|
||||
@@ -185,7 +185,7 @@ function apply_effect(ctx, effect, input, size, camera, hint, current_plane, gro
|
||||
var blur2 = ctx.alloc(size.width, size.height, hint + '_blur2')
|
||||
|
||||
// Threshold
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'shader_pass',
|
||||
shader: 'threshold',
|
||||
input: input,
|
||||
@@ -197,13 +197,13 @@ function apply_effect(ctx, effect, input, size, camera, hint, current_plane, gro
|
||||
var blur_passes = effect.blur_passes || 2
|
||||
var blur_in = bright
|
||||
for (var p = 0; p < blur_passes; p++) {
|
||||
ctx.passes.push({type: 'shader_pass', shader: 'blur', input: blur_in, output: blur1, uniforms: {direction: {x: 1, y: 0}, texel_size: {x: 1/size.width, y: 1/size.height}}})
|
||||
ctx.passes.push({type: 'shader_pass', shader: 'blur', input: blur1, output: blur2, uniforms: {direction: {x: 0, y: 1}, texel_size: {x: 1/size.width, y: 1/size.height}}})
|
||||
push(ctx.passes, {type: 'shader_pass', shader: 'blur', input: blur_in, output: blur1, uniforms: {direction: {x: 1, y: 0}, texel_size: {x: 1/size.width, y: 1/size.height}}})
|
||||
push(ctx.passes, {type: 'shader_pass', shader: 'blur', input: blur1, output: blur2, uniforms: {direction: {x: 0, y: 1}, texel_size: {x: 1/size.width, y: 1/size.height}}})
|
||||
blur_in = blur2
|
||||
}
|
||||
|
||||
// Composite bloom
|
||||
ctx.passes.push({type: 'composite_textures', base: input, overlay: blur2, output: output, mode: 'add'})
|
||||
push(ctx.passes, {type: 'composite_textures', base: input, overlay: blur2, output: output, mode: 'add'})
|
||||
|
||||
} else if (effect.type == 'mask') {
|
||||
var mask_group = effect.mask_group
|
||||
@@ -214,7 +214,7 @@ function apply_effect(ctx, effect, input, size, camera, hint, current_plane, gro
|
||||
var mask_target = ctx.alloc(size.width, size.height, hint + '_mask')
|
||||
|
||||
// Render mask
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'render',
|
||||
renderer: 'film2d',
|
||||
drawables: mask_sprites,
|
||||
@@ -225,7 +225,7 @@ function apply_effect(ctx, effect, input, size, camera, hint, current_plane, gro
|
||||
})
|
||||
|
||||
// Apply mask
|
||||
ctx.passes.push({
|
||||
push(ctx.passes, {
|
||||
type: 'apply_mask',
|
||||
content: input,
|
||||
mask: mask_target,
|
||||
@@ -235,11 +235,11 @@ function apply_effect(ctx, effect, input, size, camera, hint, current_plane, gro
|
||||
})
|
||||
} else {
|
||||
// No mask sprites, pass through
|
||||
ctx.passes.push({type: 'blit', source: input, dest: output})
|
||||
push(ctx.passes, {type: 'blit', source: input, dest: output})
|
||||
}
|
||||
} else {
|
||||
// Unknown effect, pass through
|
||||
ctx.passes.push({type: 'blit', source: input, dest: output})
|
||||
push(ctx.passes, {type: 'blit', source: input, dest: output})
|
||||
}
|
||||
|
||||
return output
|
||||
@@ -267,8 +267,8 @@ compositor.execute = function(plan) {
|
||||
|
||||
if (pass.type == 'clear') {
|
||||
var target = resolve(pass.target)
|
||||
commands.push({cmd: 'begin_render', target: target, clear: pass.color})
|
||||
commands.push({cmd: 'end_render'})
|
||||
push(commands, {cmd: 'begin_render', target: target, clear: pass.color})
|
||||
push(commands, {cmd: 'end_render'})
|
||||
|
||||
} else if (pass.type == 'render') {
|
||||
var result = film2d.render({
|
||||
@@ -280,10 +280,10 @@ compositor.execute = function(plan) {
|
||||
clear: pass.clear
|
||||
}, backend)
|
||||
for (var c = 0; c < length(result.commands); c++)
|
||||
commands.push(result.commands[c])
|
||||
push(commands, result.commands[c])
|
||||
|
||||
} else if (pass.type == 'shader_pass') {
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'shader_pass',
|
||||
shader: pass.shader,
|
||||
input: resolve(pass.input),
|
||||
@@ -292,7 +292,7 @@ compositor.execute = function(plan) {
|
||||
})
|
||||
|
||||
} else if (pass.type == 'composite_textures') {
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'composite_textures',
|
||||
base: resolve(pass.base),
|
||||
overlay: resolve(pass.overlay),
|
||||
@@ -301,7 +301,7 @@ compositor.execute = function(plan) {
|
||||
})
|
||||
|
||||
} else if (pass.type == 'apply_mask') {
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'apply_mask',
|
||||
content_texture: resolve(pass.content),
|
||||
mask_texture: resolve(pass.mask),
|
||||
@@ -311,7 +311,7 @@ compositor.execute = function(plan) {
|
||||
})
|
||||
|
||||
} else if (pass.type == 'composite') {
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'blit',
|
||||
texture: resolve(pass.source),
|
||||
target: resolve(pass.dest),
|
||||
@@ -320,7 +320,7 @@ compositor.execute = function(plan) {
|
||||
|
||||
} else if (pass.type == 'blit_to_screen') {
|
||||
var rect = _calc_presentation(pass.source_size, pass.dest_size, pass.presentation)
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'blit',
|
||||
texture: resolve(pass.source),
|
||||
target: 'screen',
|
||||
@@ -330,14 +330,14 @@ compositor.execute = function(plan) {
|
||||
} else if (pass.type == 'blit') {
|
||||
var src = resolve(pass.source)
|
||||
var dst = resolve(pass.dest)
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'blit',
|
||||
texture: src,
|
||||
target: dst,
|
||||
dst_rect: {x: 0, y: 0, width: dst.width, height: dst.height}
|
||||
})
|
||||
} else if (pass.type == 'imgui') {
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'imgui',
|
||||
target: resolve(pass.target),
|
||||
draw: pass.draw
|
||||
|
||||
40
core.cm
40
core.cm
@@ -78,7 +78,29 @@ core.backend = function() {
|
||||
}
|
||||
// FPS tracking
|
||||
var _fps_samples = []
|
||||
var _fps_sample_count = 60
|
||||
var _fps_sample_count = 120
|
||||
var _fps_sample_sum = 0
|
||||
var _fps_sample_pos = 0
|
||||
|
||||
function fps_add_sample(sample) {
|
||||
var n = length(_fps_samples)
|
||||
if (n < _fps_sample_count) {
|
||||
push(_fps_samples, sample)
|
||||
_fps_sample_sum += sample
|
||||
} else {
|
||||
var old = _fps_samples[_fps_sample_pos]
|
||||
_fps_samples[_fps_sample_pos] = sample
|
||||
_fps_sample_sum += sample - old
|
||||
_fps_sample_pos++
|
||||
if (_fps_sample_pos >= _fps_sample_count) _fps_sample_pos = 0
|
||||
}
|
||||
}
|
||||
|
||||
function fps_get_avg() {
|
||||
var n = length(_fps_samples)
|
||||
return n ? _fps_sample_sum / n : 0
|
||||
}
|
||||
|
||||
var _current_fps = 0
|
||||
var _frame_time_ms = 0
|
||||
|
||||
@@ -162,7 +184,7 @@ function _main_loop() {
|
||||
// Handle both compositor result ({commands: [...]}) and fx_graph (graph object)
|
||||
if (render_result.commands) {
|
||||
if (_config.imgui || _config.editor) {
|
||||
render_result.commands.push({
|
||||
push(render_result.commands, {
|
||||
cmd: 'imgui',
|
||||
draw: function(ui) {
|
||||
if (_config.imgui) _config.imgui(ui)
|
||||
@@ -188,19 +210,15 @@ function _main_loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// Measure actual frame work time (excluding delay)
|
||||
var frame_end = time_mod.number()
|
||||
var actual_frame_time = frame_end - frame_start
|
||||
|
||||
// Track FPS based on actual work time
|
||||
|
||||
_frame_time_ms = actual_frame_time * 1000
|
||||
_fps_samples.push(actual_frame_time)
|
||||
if (length(_fps_samples) > _fps_sample_count) {
|
||||
_fps_samples.shift()
|
||||
}
|
||||
var avg_frame_time = reduce(_fps_samples, function(a,b) { return a+b }) / length(_fps_samples)
|
||||
fps_add_sample(actual_frame_time)
|
||||
|
||||
var avg_frame_time = fps_get_avg()
|
||||
_current_fps = avg_frame_time > 0 ? 1 / avg_frame_time : 0
|
||||
|
||||
|
||||
// Schedule next frame
|
||||
var frame_time = 1 / _framerate
|
||||
var elapsed = frame_end - frame_start
|
||||
|
||||
@@ -143,29 +143,29 @@ function _render_node_summary(imgui, node) {
|
||||
var info = []
|
||||
|
||||
if (node.pos) {
|
||||
info.push("pos:(" + text(round(node.pos.x)) + "," + text(round(node.pos.y)) + ")")
|
||||
push(info, "pos:(" + text(round(node.pos.x)) + "," + text(round(node.pos.y)) + ")")
|
||||
}
|
||||
|
||||
if (node.width && node.height) {
|
||||
info.push("size:" + text(node.width) + "x" + text(node.height))
|
||||
push(info, "size:" + text(node.width) + "x" + text(node.height))
|
||||
}
|
||||
|
||||
if (node.image) {
|
||||
info.push("img:" + node.image)
|
||||
push(info, "img:" + node.image)
|
||||
}
|
||||
|
||||
if (node.text) {
|
||||
var t = node.text
|
||||
if (length(t) > 20) t = text(t, 0, 17) + "..."
|
||||
info.push("\"" + t + "\"")
|
||||
push(info, "\"" + t + "\"")
|
||||
}
|
||||
|
||||
if (node.effects && length(node.effects) > 0) {
|
||||
var fx = []
|
||||
for (var i = 0; i < length(node.effects); i++) {
|
||||
fx.push(node.effects[i].type)
|
||||
push(fx, node.effects[i].type)
|
||||
}
|
||||
info.push("fx:[" + text(fx, ",") + "]")
|
||||
push(info, "fx:[" + text(fx, ",") + "]")
|
||||
}
|
||||
|
||||
if (length(info) > 0) {
|
||||
|
||||
18
effects.cm
18
effects.cm
@@ -36,7 +36,7 @@ effects.register('bloom', {
|
||||
|
||||
// Threshold extraction
|
||||
var thresh_target = ctx.alloc_target(size.width, size.height, 'bloom_thresh')
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'threshold',
|
||||
input: input,
|
||||
@@ -55,14 +55,14 @@ effects.register('bloom', {
|
||||
var blur_count = params.blur_passes != null ? params.blur_passes : 3
|
||||
|
||||
for (var i = 0; i < blur_count; i++) {
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'blur',
|
||||
input: blur_src,
|
||||
output: blur_a,
|
||||
uniforms: {direction: {x: 2, y: 0}, texel_size: texel}
|
||||
})
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'blur',
|
||||
input: blur_a,
|
||||
@@ -73,7 +73,7 @@ effects.register('bloom', {
|
||||
}
|
||||
|
||||
// Additive composite
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'composite',
|
||||
base: input,
|
||||
overlay: blur_src,
|
||||
@@ -124,7 +124,7 @@ effects.register('mask', {
|
||||
|
||||
// Render mask source to target
|
||||
var mask_target = ctx.alloc_target(size.width, size.height, 'mask_src')
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'render_subtree',
|
||||
root: mask_source,
|
||||
output: mask_target,
|
||||
@@ -133,7 +133,7 @@ effects.register('mask', {
|
||||
})
|
||||
|
||||
// Apply mask shader
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'mask',
|
||||
inputs: [input, mask_target],
|
||||
@@ -190,14 +190,14 @@ effects.register('blur', {
|
||||
var blur_count = params.passes != null ? params.passes : 2
|
||||
|
||||
for (var i = 0; i < blur_count; i++) {
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'blur',
|
||||
input: src,
|
||||
output: blur_a,
|
||||
uniforms: {direction: {x: 2, y: 0}, texel_size: texel}
|
||||
})
|
||||
passes.push({
|
||||
push(passes, {
|
||||
type: 'shader',
|
||||
shader: 'blur',
|
||||
input: blur_a,
|
||||
@@ -208,7 +208,7 @@ effects.register('blur', {
|
||||
}
|
||||
|
||||
// Final blit to output
|
||||
passes.push({type: 'blit', source: src, dest: output})
|
||||
push(passes, {type: 'blit', source: src, dest: output})
|
||||
return passes
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ var bunnies = []
|
||||
|
||||
// Start with some initial bunnies:
|
||||
for (var i = 0; i < 100; i++) {
|
||||
bunnies.push({
|
||||
push(bunnies, {
|
||||
x: random.random() * config.width,
|
||||
y: random.random() * config.height,
|
||||
vx: (random.random() * 300) - 150,
|
||||
@@ -22,22 +22,12 @@ for (var i = 0; i < 100; i++) {
|
||||
})
|
||||
}
|
||||
|
||||
var fpsSamples = []
|
||||
var fpsAvg = 0
|
||||
|
||||
this.update = function(dt) {
|
||||
// Compute FPS average over the last 60 frames:
|
||||
var currentFPS = 1 / dt
|
||||
fpsSamples.push(currentFPS)
|
||||
if (length(fpsSamples) > 60) fpsSamples.shift()
|
||||
var sum = reduce(fpsSamples, function(a,b) { return a + b })
|
||||
fpsAvg = sum / length(fpsSamples)
|
||||
|
||||
// If left mouse is down, spawn some more bunnies:
|
||||
var mouse = input.mousestate()
|
||||
if (mouse.left)
|
||||
for (var i = 0; i < 50; i++) {
|
||||
bunnies.push({
|
||||
push(bunnies, {
|
||||
x: mouse.x,
|
||||
y: mouse.y,
|
||||
vx: (random.random() * 300) - 150,
|
||||
@@ -63,7 +53,4 @@ this.update = function(dt) {
|
||||
|
||||
this.hud = function() {
|
||||
draw.images(bunnyTex, bunnies)
|
||||
|
||||
var msg = 'FPS: ' + fpsAvg.toFixed(2) + ' Bunnies: ' + length(bunnies)
|
||||
draw.text(msg, {x:0, y:0, width:config.width, height:40}, null, 0, color.white, 0)
|
||||
}
|
||||
|
||||
@@ -26,15 +26,13 @@ var grid_prototype = {
|
||||
|
||||
// add an entity into a cell
|
||||
add(entity, pos) {
|
||||
this.cell(pos.x, pos.y).push(entity);
|
||||
push(this.cell(pos.x, pos.y), entity);
|
||||
entity.coord = array(pos);
|
||||
},
|
||||
|
||||
// remove an entity from a cell
|
||||
remove(entity, pos) {
|
||||
def c = this.cell(pos.x, pos.y);
|
||||
def i = search(c, entity);
|
||||
if (i != null) c.splice(i, 1);
|
||||
this.cells[pos.y][pos.x] = filter(this.cells[pos.y][pos.x], x => x != entity)
|
||||
},
|
||||
|
||||
// bounds check
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
/* pieces.js – simple data holders + starting layout */
|
||||
function Piece(kind, colour) {
|
||||
this.kind = kind; // "pawn" etc.
|
||||
this.colour = colour; // "white"/"black"
|
||||
this.sprite = colour + '_' + kind; // for draw2d.image
|
||||
this.captured = false;
|
||||
this.coord = [0,0];
|
||||
var newpiece = { kind, colour}
|
||||
|
||||
newpiece.sprite = colour + '_' + kind; // for draw2d.image
|
||||
newpiece.captured = false;
|
||||
newpiece.coord = [0,0];
|
||||
|
||||
return newpiece
|
||||
}
|
||||
Piece.prototype.toString = function () {
|
||||
return character(this.colour) + upper(character(this.kind));
|
||||
};
|
||||
|
||||
function startingPosition(grid) {
|
||||
var W = 'white', B = 'black', x;
|
||||
|
||||
// pawns
|
||||
for (x = 0; x < 8; x++) {
|
||||
grid.add(new Piece('pawn', W), [x, 6]);
|
||||
grid.add(new Piece('pawn', B), [x, 1]);
|
||||
grid.add(Piece('pawn', W), [x, 6]);
|
||||
grid.add(Piece('pawn', B), [x, 1]);
|
||||
}
|
||||
// major pieces
|
||||
var back = ['rook','knight','bishop','queen','king','bishop','knight','rook'];
|
||||
for (x = 0; x < 8; x++) {
|
||||
grid.add(new Piece(back[x], W), [x, 7]);
|
||||
grid.add(new Piece(back[x], B), [x, 0]);
|
||||
grid.add(Piece(back[x], W), [x, 7]);
|
||||
grid.add(Piece(back[x], B), [x, 0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ this.update = function(dt) {
|
||||
|
||||
// Eat apple?
|
||||
if (head.x == apple.x && head.y == apple.y) spawnApple()
|
||||
else snake.pop()
|
||||
else pop(snake)
|
||||
}
|
||||
|
||||
this.hud = function() {
|
||||
|
||||
@@ -58,8 +58,8 @@ function initBoard() {
|
||||
board = []
|
||||
for (var r=0; r<ROWS; r++) {
|
||||
var row = []
|
||||
for (var c=0; c<COLS; c++) row.push(0)
|
||||
board.push(row)
|
||||
for (var c=0; c<COLS; c++) push(row, 0)
|
||||
push(board, row)
|
||||
}
|
||||
}
|
||||
initBoard()
|
||||
@@ -119,10 +119,10 @@ function clearLines() {
|
||||
if (every(board[r], cell => cell)) {
|
||||
lines++
|
||||
// remove row
|
||||
board.splice(r,1)
|
||||
board = array(array(board, 0, r), array(board, r+1))
|
||||
// add empty row on top
|
||||
var newRow = []
|
||||
for (var c=0; c<COLS; c++) newRow.push(0)
|
||||
for (var c=0; c<COLS; c++) push(newRow, 0)
|
||||
board.unshift(newRow)
|
||||
} else {
|
||||
r--
|
||||
|
||||
71
film2d.cm
71
film2d.cm
@@ -118,14 +118,14 @@ film2d.register = function(drawable) {
|
||||
// Index by plane
|
||||
var plane = drawable.plane || 'default'
|
||||
if (!plane_index[plane]) plane_index[plane] = []
|
||||
plane_index[plane].push(id)
|
||||
push(plane_index[plane], id)
|
||||
|
||||
// Index by groups (effect routing only)
|
||||
var groups = drawable.groups || []
|
||||
for (var i = 0; i < length(groups); i++) {
|
||||
var g = groups[i]
|
||||
if (!group_index[g]) group_index[g] = []
|
||||
group_index[g].push(id)
|
||||
push(group_index[g], id)
|
||||
}
|
||||
|
||||
return id
|
||||
@@ -140,7 +140,8 @@ film2d.unregister = function(id) {
|
||||
var plane = drawable.plane || 'default'
|
||||
if (plane_index[plane]) {
|
||||
var idx = find(plane_index[plane], id_str)
|
||||
if (idx != null) plane_index[plane].splice(idx, 1)
|
||||
if (idx != null)
|
||||
plane_index[plane] = array(array(plane_index[plane], 0, idx), array(plane_index[plane], idx+1))
|
||||
}
|
||||
|
||||
// Remove from group indices
|
||||
@@ -149,7 +150,8 @@ film2d.unregister = function(id) {
|
||||
var g = groups[i]
|
||||
if (group_index[g]) {
|
||||
var idx = find(group_index[g], id_str)
|
||||
if (idx != null) group_index[g].splice(idx, 1)
|
||||
if (idx != null)
|
||||
group_index[g] = array(array(group_index[g], 0, idx), array(group_index[g], idx+1))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,13 +161,14 @@ film2d.unregister = function(id) {
|
||||
film2d.index_group = function(id, group) {
|
||||
if (!group_index[group]) group_index[group] = []
|
||||
if (search(group_index[group], text(id)) == null)
|
||||
group_index[group].push(text(id))
|
||||
push(group_index[group], text(id))
|
||||
}
|
||||
|
||||
film2d.unindex_group = function(id, group) {
|
||||
if (!group_index[group]) return
|
||||
var idx = search(group_index[group], text(id))
|
||||
if (idx != null) group_index[group].splice(idx, 1)
|
||||
if (idx != null)
|
||||
group_index[group] = array(array(group_index[group], 0, idx), array(group_index[group], idx+1))
|
||||
}
|
||||
|
||||
film2d.reindex = function(id, old_groups, new_groups) {
|
||||
@@ -192,9 +195,9 @@ film2d.query = function(selector) {
|
||||
// If also filtering by group, check membership
|
||||
if (selector.group) {
|
||||
var groups = d.groups || []
|
||||
if (search(groups, selector.group) != null) result.push(d)
|
||||
if (search(groups, selector.group) != null) push(result, d)
|
||||
} else {
|
||||
result.push(d)
|
||||
push(result, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +209,7 @@ film2d.query = function(selector) {
|
||||
var ids = group_index[selector.group] || []
|
||||
for (var i = 0; i < length(ids); i++) {
|
||||
var d = registry[ids[i]]
|
||||
if (d && d.visible != false) result.push(d)
|
||||
if (d && d.visible != false) push(result, d)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -219,7 +222,7 @@ film2d.query = function(selector) {
|
||||
if (!seen[ids[i]]) {
|
||||
seen[ids[i]] = true
|
||||
var d = registry[ids[i]]
|
||||
if (d && d.visible != false) result.push(d)
|
||||
if (d && d.visible != false) push(result, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,7 +245,7 @@ film2d.get_groups = function(id) {
|
||||
film2d.all_groups = function() {
|
||||
var groups = []
|
||||
arrfor(array(group_index), g => {
|
||||
if (length(group_index[g]) > 0) groups.push(g)
|
||||
if (length(group_index[g]) > 0) push(groups, g)
|
||||
})
|
||||
return groups
|
||||
}
|
||||
@@ -282,7 +285,7 @@ film2d.render = function(params, render_backend) {
|
||||
b = []
|
||||
buckets[layer_key] = b
|
||||
}
|
||||
b.push(d)
|
||||
push(b, d)
|
||||
}
|
||||
|
||||
// Sort layers numerically (keys are text)
|
||||
@@ -305,32 +308,32 @@ film2d.render = function(params, render_backend) {
|
||||
if (!y_down) b = reverse(b) // y_up => smaller y draws later => reverse
|
||||
}
|
||||
|
||||
for (var j = 0; j < length(b); j++) sorted_drawables.push(b[j])
|
||||
for (var j = 0; j < length(b); j++) push(sorted_drawables, b[j])
|
||||
}
|
||||
|
||||
drawables = sorted_drawables
|
||||
|
||||
var commands = []
|
||||
commands.push({ cmd: "begin_render", target: target, clear: clear_color, target_size: target_size })
|
||||
commands.push({ cmd: "set_camera", camera: camera })
|
||||
push(commands, { cmd: "begin_render", target: target, clear: clear_color, target_size: target_size })
|
||||
push(commands, { cmd: "set_camera", camera: camera })
|
||||
|
||||
var batches = _batch_drawables(drawables)
|
||||
|
||||
for (var i = 0; i < length(batches); i++) {
|
||||
var batch = batches[i]
|
||||
if (batch.type == "sprite_batch")
|
||||
commands.push({ cmd: "draw_batch", batch_type: "sprites", geometry: { sprites: batch.sprites }, texture: batch.texture, material: batch.material })
|
||||
push(commands, { cmd: "draw_batch", batch_type: "sprites", geometry: { sprites: batch.sprites }, texture: batch.texture, material: batch.material })
|
||||
else if (batch.type == "mesh2d_batch")
|
||||
commands.push({ cmd: "draw_mesh2d", meshes: batch.meshes, texture: batch.texture, material: batch.material })
|
||||
push(commands, { cmd: "draw_mesh2d", meshes: batch.meshes, texture: batch.texture, material: batch.material })
|
||||
else if (batch.type == "text")
|
||||
commands.push({ cmd: "draw_text", drawable: batch.drawable })
|
||||
push(commands, { cmd: "draw_text", drawable: batch.drawable })
|
||||
else if (batch.type == "texture_ref")
|
||||
commands.push({ cmd: "draw_texture_ref", drawable: batch.drawable })
|
||||
push(commands, { cmd: "draw_texture_ref", drawable: batch.drawable })
|
||||
else if (batch.type == "shape")
|
||||
commands.push({ cmd: "draw_shape", drawable: batch.drawable })
|
||||
push(commands, { cmd: "draw_shape", drawable: batch.drawable })
|
||||
}
|
||||
|
||||
commands.push({ cmd: "end_render" })
|
||||
push(commands, { cmd: "end_render" })
|
||||
return { commands: commands }
|
||||
}
|
||||
|
||||
@@ -350,9 +353,9 @@ function _batch_drawables(drawables) {
|
||||
var mat = d.material || {blend: 'alpha', sampler: d.filter || 'nearest'}
|
||||
|
||||
if (current && current.type == 'sprite_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
|
||||
current.sprites.push(d)
|
||||
push(current.sprites, d)
|
||||
} else {
|
||||
if (current) batches.push(current)
|
||||
if (current) push(batches, current)
|
||||
current = {type: 'sprite_batch', texture: tex, material: mat, sprites: [d]}
|
||||
}
|
||||
} else if (d.type == 'particles') {
|
||||
@@ -379,9 +382,9 @@ function _batch_drawables(drawables) {
|
||||
}
|
||||
|
||||
if (current && current.type == 'sprite_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
|
||||
current.sprites.push(sprite)
|
||||
push(current.sprites, sprite)
|
||||
} else {
|
||||
if (current) batches.push(current)
|
||||
if (current) push(batches, current)
|
||||
current = {type: 'sprite_batch', texture: tex, material: mat, sprites: [sprite]}
|
||||
}
|
||||
}
|
||||
@@ -422,9 +425,9 @@ function _batch_drawables(drawables) {
|
||||
var tex = img
|
||||
var mat = default_mat
|
||||
if (current && current.type == 'sprite_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
|
||||
current.sprites.push(sprite)
|
||||
push(current.sprites, sprite)
|
||||
} else {
|
||||
if (current) batches.push(current)
|
||||
if (current) push(batches, current)
|
||||
current = {type: 'sprite_batch', texture: tex, material: mat, sprites: [sprite]}
|
||||
}
|
||||
}
|
||||
@@ -435,28 +438,28 @@ function _batch_drawables(drawables) {
|
||||
var mat = d.material || {blend: d.blend || 'alpha', sampler: d.filter || 'linear'}
|
||||
|
||||
if (current && current.type == 'mesh2d_batch' && current.texture == tex && _mat_eq(current.material, mat)) {
|
||||
current.meshes.push(d)
|
||||
push(current.meshes, d)
|
||||
} else {
|
||||
if (current) batches.push(current)
|
||||
if (current) push(batches, current)
|
||||
current = {type: 'mesh2d_batch', texture: tex, material: mat, meshes: [d]}
|
||||
}
|
||||
} else if (d.type == 'shape') {
|
||||
// Shapes are rendered individually (each has unique SDF params)
|
||||
if (current) {
|
||||
batches.push(current)
|
||||
push(batches, current)
|
||||
current = null
|
||||
}
|
||||
batches.push({type: 'shape', drawable: d})
|
||||
push(batches, {type: 'shape', drawable: d})
|
||||
} else {
|
||||
if (current) {
|
||||
batches.push(current)
|
||||
push(batches, current)
|
||||
current = null
|
||||
}
|
||||
batches.push({type: d.type, drawable: d})
|
||||
push(batches, {type: d.type, drawable: d})
|
||||
}
|
||||
}
|
||||
|
||||
if (current) batches.push(current)
|
||||
if (current) push(batches, current)
|
||||
return batches
|
||||
}
|
||||
|
||||
|
||||
16
fx_graph.cm
16
fx_graph.cm
@@ -67,7 +67,7 @@ fx_graph.add_node = function(type, params) {
|
||||
params: params,
|
||||
output: {node_id: this.next_id - 1, slot: 'output'}
|
||||
}
|
||||
this.nodes.push(node)
|
||||
push(this.nodes, node)
|
||||
return node
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ NODE_EXECUTORS.composite = function(params, backend) {
|
||||
|
||||
// Emit composite_textures command (handled outside render pass)
|
||||
var commands = []
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'composite_textures',
|
||||
base: base.target,
|
||||
overlay: overlay.target,
|
||||
@@ -233,7 +233,7 @@ NODE_EXECUTORS.mask = function(params, backend) {
|
||||
|
||||
// Emit apply_mask command (handled via shader pass outside render pass)
|
||||
var commands = []
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'apply_mask',
|
||||
content_texture: content.target,
|
||||
mask_texture: mask.target,
|
||||
@@ -264,12 +264,12 @@ NODE_EXECUTORS.clip_rect = function(params, backend) {
|
||||
}
|
||||
}
|
||||
|
||||
commands.splice(insert_idx, 0, {cmd: 'scissor', rect: rect})
|
||||
commands = array(array(array(commands, 0, insert_idx), [{cmd: 'scissor', rect: rect}]), array(commands, insert_idx))
|
||||
|
||||
// Add scissor reset before end_render
|
||||
for (var i = length(commands) - 1; i >= 0; i--) {
|
||||
if (commands[i].cmd == 'end_render') {
|
||||
commands.splice(i, 0, {cmd: 'scissor', rect: null})
|
||||
commands = array(array(array(commands, 0, i), [{cmd: 'scissor', rect:null}]) ,array(commands, i+1))
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -305,7 +305,7 @@ NODE_EXECUTORS.blit = function(params, backend) {
|
||||
}
|
||||
|
||||
var commands = []
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'blit',
|
||||
texture: src_target,
|
||||
target: target,
|
||||
@@ -321,7 +321,7 @@ NODE_EXECUTORS.present = function(params, backend) {
|
||||
var input = params.input
|
||||
|
||||
var commands = []
|
||||
commands.push({cmd: 'present'})
|
||||
push(commands, {cmd: 'present'})
|
||||
|
||||
return {commands: commands}
|
||||
}
|
||||
@@ -350,7 +350,7 @@ NODE_EXECUTORS.shader_pass = function(params, backend) {
|
||||
}
|
||||
|
||||
var commands = []
|
||||
commands.push({
|
||||
push(commands, {
|
||||
cmd: 'shader_pass',
|
||||
shader: shader,
|
||||
input: src,
|
||||
|
||||
@@ -41,7 +41,7 @@ gesture.on_input = function(action_id, action) {
|
||||
} else if (touchCount == 2) {
|
||||
// Two touches - potential pinch
|
||||
this.gestureState = 'multi'
|
||||
var fingers = object.values(this.touches)
|
||||
var fingers = array(array(this.touches), k => this.touches[k])
|
||||
this.startDist = this.dist(fingers[0], fingers[1])
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ gesture.on_input = function(action_id, action) {
|
||||
|
||||
if (touchCount == 2 && this.gestureState == 'multi') {
|
||||
// Check for pinch gesture
|
||||
var fingers = object.values(this.touches)
|
||||
var fingers = array(array(this.touches), k => this.touches[k])
|
||||
var currentDist = this.dist(fingers[0], fingers[1])
|
||||
var d = currentDist - this.startDist
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ function create_image(path){
|
||||
try{
|
||||
def bytes = io.slurp(path);
|
||||
|
||||
var ext = array(path, '.').pop()
|
||||
var ext = pop(array(path, '.'))
|
||||
var raw = decode_image(bytes, ext);
|
||||
|
||||
/* ── Case A: single surface (from make_texture) ────────────── */
|
||||
@@ -357,7 +357,7 @@ graphics.texture = function texture(path) {
|
||||
}
|
||||
|
||||
graphics.tex_hotreload = function tex_hotreload(file) {
|
||||
var basename = array(array(file, '/').pop(), '.')[0]
|
||||
var basename = array(pop(array(file, '/')), '.')[0]
|
||||
|
||||
// Check if this basename exists in our cache
|
||||
if (!(basename in cache)) return
|
||||
|
||||
8
input.cm
8
input.cm
@@ -93,13 +93,13 @@ function create_user(index, config) {
|
||||
|
||||
// Push entity onto control stack
|
||||
push: function(entity) {
|
||||
this.control_stack.push(entity)
|
||||
push(this.control_stack, entity)
|
||||
},
|
||||
|
||||
// Pop from control stack
|
||||
pop: function() {
|
||||
if (length(this.control_stack) > 1) {
|
||||
return this.control_stack.pop()
|
||||
return pop(this.control_stack)
|
||||
}
|
||||
return null
|
||||
},
|
||||
@@ -166,7 +166,7 @@ function pick_user(canon) {
|
||||
|
||||
user.active_device = canon.device_id
|
||||
if (find(user.paired_devices, canon.device_id) == null) {
|
||||
user.paired_devices.push(canon.device_id)
|
||||
push(user.paired_devices, canon.device_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +207,7 @@ function configure(opts) {
|
||||
// Create users
|
||||
_users = []
|
||||
for (var i = 0; i < _config.max_users; i++) {
|
||||
_users.push(create_user(i, _config))
|
||||
push(_users, create_user(i, _config))
|
||||
}
|
||||
|
||||
_initialized = true
|
||||
|
||||
@@ -135,7 +135,8 @@ function make(defaults, display_names) {
|
||||
// Remove from other actions
|
||||
arrfor(array(this.action_map), act => {
|
||||
var idx = search(this.action_map[act], new_control)
|
||||
if (idx >= 0) this.action_map[act].splice(idx, 1)
|
||||
if (idx >= 0)
|
||||
this.action_map[act] = array(array(this.action_map[act], 0, idx), array(this.action_map[act], idx+1))
|
||||
})
|
||||
|
||||
// Clear existing bindings for this device kind
|
||||
@@ -143,9 +144,8 @@ function make(defaults, display_names) {
|
||||
for (var i = length(target) - 1; i >= 0; i--) {
|
||||
var existing_kind = starts_with(target[i], 'gamepad_') ? 'gamepad' :
|
||||
starts_with(target[i], 'swipe_') ? 'touch' : 'keyboard'
|
||||
if (existing_kind == device_kind) {
|
||||
target.splice(i, 1)
|
||||
}
|
||||
if (existing_kind == device_kind)
|
||||
this.action_map[action] = array(array(this.action_map[action], 0, i), array(this.action_map[action], i+1))
|
||||
}
|
||||
|
||||
// Add new binding
|
||||
|
||||
@@ -40,7 +40,7 @@ function gesture_stage(config) {
|
||||
|
||||
// Only process gamepad touchpad events
|
||||
if (ev.control != 'gamepad_touchpad') {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ function gesture_stage(config) {
|
||||
var d = currentDist - start_dist
|
||||
|
||||
if (Math.abs(d) >= pinch_th / 100) {
|
||||
output.push({
|
||||
push(output, {
|
||||
kind: 'gesture',
|
||||
device_id: ev.device_id,
|
||||
control: d > 0 ? 'pinch_out' : 'pinch_in',
|
||||
@@ -103,7 +103,7 @@ function gesture_stage(config) {
|
||||
? (dx > 0 ? 'swipe_right' : 'swipe_left')
|
||||
: (dy > 0 ? 'swipe_down' : 'swipe_up')
|
||||
|
||||
output.push({
|
||||
push(output, {
|
||||
kind: 'gesture',
|
||||
device_id: ev.device_id,
|
||||
control: dir,
|
||||
@@ -139,18 +139,18 @@ function emacs_stage() {
|
||||
|
||||
// Only process keyboard button events
|
||||
if (ev.device_id != 'kbm' || ev.kind != 'button' || !ev.pressed) {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
if (find(valid_emacs_keys, ev.control) == null) {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
// Only process if we have modifiers OR waiting for chord
|
||||
if (!ev.mods?.ctrl && !ev.mods?.alt && !prefix) {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ function emacs_stage() {
|
||||
if (prefix) {
|
||||
var chord = prefix + " " + notation
|
||||
prefix = null
|
||||
output.push({
|
||||
push(output, {
|
||||
kind: 'chord',
|
||||
device_id: ev.device_id,
|
||||
control: chord,
|
||||
@@ -183,7 +183,7 @@ function emacs_stage() {
|
||||
time: ev.time
|
||||
})
|
||||
} else {
|
||||
output.push({
|
||||
push(output, {
|
||||
kind: 'chord',
|
||||
device_id: ev.device_id,
|
||||
control: notation,
|
||||
@@ -213,14 +213,14 @@ function action_stage(bindings) {
|
||||
|
||||
// Pass through non-button events
|
||||
if (ev.kind != 'button' && ev.kind != 'chord' && ev.kind != 'gesture') {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
var actions = bindings.get_actions(ev.control)
|
||||
|
||||
if (length(actions) == 0) {
|
||||
output.push(ev)
|
||||
push(output, ev)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ function action_stage(bindings) {
|
||||
if (ev.pressed) down[action] = true
|
||||
else if (ev.released) down[action] = false
|
||||
|
||||
output.push({
|
||||
push(output, {
|
||||
kind: 'action',
|
||||
device_id: ev.device_id,
|
||||
control: action,
|
||||
@@ -277,16 +277,16 @@ function make(user, config) {
|
||||
var action = null
|
||||
|
||||
if (config.gestures != false) {
|
||||
stages.push(gesture_stage(config))
|
||||
push(stages, gesture_stage(config))
|
||||
}
|
||||
|
||||
if (config.emacs != false) {
|
||||
stages.push(emacs_stage())
|
||||
push(stages, emacs_stage())
|
||||
}
|
||||
|
||||
action = action_stage(user.bindings)
|
||||
stages.push(action)
|
||||
stages.push(delivery_stage(user))
|
||||
push(stages, action)
|
||||
push(stages, delivery_stage(user))
|
||||
|
||||
return {
|
||||
stages: stages,
|
||||
|
||||
66
line2d.cm
66
line2d.cm
@@ -81,9 +81,9 @@ function build_polyline_mesh(line) {
|
||||
for (var i = 0; i < length(points); i++) {
|
||||
var p = points[i]
|
||||
if (points_space == 'local') {
|
||||
pts.push({x: p.x + pos.x, y: p.y + pos.y})
|
||||
push(pts, {x: p.x + pos.x, y: p.y + pos.y})
|
||||
} else {
|
||||
pts.push({x: p.x, y: p.y})
|
||||
push(pts, {x: p.x, y: p.y})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ function build_polyline_mesh(line) {
|
||||
for (var i = 1; i < length(pts); i++) {
|
||||
var dx = pts[i].x - pts[i-1].x
|
||||
var dy = pts[i].y - pts[i-1].y
|
||||
cumulative.push(cumulative[i-1] + math.sqrt(dx*dx + dy*dy))
|
||||
push(cumulative, cumulative[i-1] + math.sqrt(dx*dx + dy*dy))
|
||||
}
|
||||
var total_length = cumulative[length(cumulative) - 1]
|
||||
|
||||
@@ -179,7 +179,7 @@ function build_polyline_mesh(line) {
|
||||
n.y = dx
|
||||
}
|
||||
|
||||
normals.push(n)
|
||||
push(normals, n)
|
||||
}
|
||||
|
||||
// Generate vertices (2 per point - left and right of line)
|
||||
@@ -190,7 +190,7 @@ function build_polyline_mesh(line) {
|
||||
var u = get_u(i)
|
||||
|
||||
// Left vertex (v=0)
|
||||
verts.push({
|
||||
push(verts, {
|
||||
x: p.x + n.x * w,
|
||||
y: p.y + n.y * w,
|
||||
u: u,
|
||||
@@ -199,7 +199,7 @@ function build_polyline_mesh(line) {
|
||||
})
|
||||
|
||||
// Right vertex (v=1)
|
||||
verts.push({
|
||||
push(verts, {
|
||||
x: p.x - n.x * w,
|
||||
y: p.y - n.y * w,
|
||||
u: u,
|
||||
@@ -212,24 +212,24 @@ function build_polyline_mesh(line) {
|
||||
for (var i = 0; i < length(pts) - 1; i++) {
|
||||
var base = i * 2
|
||||
// First triangle
|
||||
indices.push(base + 0)
|
||||
indices.push(base + 1)
|
||||
indices.push(base + 2)
|
||||
push(indices, base + 0)
|
||||
push(indices, base + 1)
|
||||
push(indices, base + 2)
|
||||
// Second triangle
|
||||
indices.push(base + 1)
|
||||
indices.push(base + 3)
|
||||
indices.push(base + 2)
|
||||
push(indices, base + 1)
|
||||
push(indices, base + 3)
|
||||
push(indices, base + 2)
|
||||
}
|
||||
|
||||
// Handle closed path
|
||||
if (closed && length(pts) > 2) {
|
||||
var last = (length(pts) - 1) * 2
|
||||
indices.push(last + 0)
|
||||
indices.push(last + 1)
|
||||
indices.push(0)
|
||||
indices.push(last + 1)
|
||||
indices.push(1)
|
||||
indices.push(0)
|
||||
push(indices, last + 0)
|
||||
push(indices, last + 1)
|
||||
push(indices, 0)
|
||||
push(indices, last + 1)
|
||||
push(indices, 1)
|
||||
push(indices, 0)
|
||||
}
|
||||
|
||||
// Add round caps if requested
|
||||
@@ -259,7 +259,7 @@ function add_round_cap(verts, indices, p, n, width, u, v_offset, v_scale, is_sta
|
||||
var dy = is_start ? n.x : -n.x
|
||||
|
||||
// Center vertex
|
||||
verts.push({
|
||||
push(verts, {
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
u: u,
|
||||
@@ -274,7 +274,7 @@ function add_round_cap(verts, indices, p, n, width, u, v_offset, v_scale, is_sta
|
||||
var cx = math.cosine(angle)
|
||||
var cy = math.sine(angle)
|
||||
|
||||
verts.push({
|
||||
push(verts, {
|
||||
x: p.x + cx * w,
|
||||
y: p.y + cy * w,
|
||||
u: u,
|
||||
@@ -285,9 +285,9 @@ function add_round_cap(verts, indices, p, n, width, u, v_offset, v_scale, is_sta
|
||||
|
||||
// Fan triangles
|
||||
for (var i = 0; i < segments; i++) {
|
||||
indices.push(base_idx)
|
||||
indices.push(base_idx + 1 + i)
|
||||
indices.push(base_idx + 2 + i)
|
||||
push(indices, base_idx)
|
||||
push(indices, base_idx + 1 + i)
|
||||
push(indices, base_idx + 2 + i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,17 +307,17 @@ function add_square_cap(verts, indices, p, n, width, u, v_offset, v_scale, is_st
|
||||
var ey = p.y + dy * ext
|
||||
|
||||
// Four corners of the cap
|
||||
verts.push({x: p.x + n.x * w, y: p.y + n.y * w, u: u, v: v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
verts.push({x: p.x - n.x * w, y: p.y - n.y * w, u: u, v: v_scale + v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
verts.push({x: ex + n.x * w, y: ey + n.y * w, u: u, v: v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
verts.push({x: ex - n.x * w, y: ey - n.y * w, u: u, v: v_scale + v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
push(verts, {x: p.x + n.x * w, y: p.y + n.y * w, u: u, v: v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
push(verts, {x: p.x - n.x * w, y: p.y - n.y * w, u: u, v: v_scale + v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
push(verts, {x: ex + n.x * w, y: ey + n.y * w, u: u, v: v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
push(verts, {x: ex - n.x * w, y: ey - n.y * w, u: u, v: v_scale + v_offset, r: 1, g: 1, b: 1, a: 1})
|
||||
|
||||
indices.push(base_idx + 0)
|
||||
indices.push(base_idx + 1)
|
||||
indices.push(base_idx + 2)
|
||||
indices.push(base_idx + 1)
|
||||
indices.push(base_idx + 3)
|
||||
indices.push(base_idx + 2)
|
||||
push(indices, base_idx + 0)
|
||||
push(indices, base_idx + 1)
|
||||
push(indices, base_idx + 2)
|
||||
push(indices, base_idx + 1)
|
||||
push(indices, base_idx + 3)
|
||||
push(indices, base_idx + 2)
|
||||
}
|
||||
|
||||
var defaults = {
|
||||
|
||||
@@ -18,7 +18,7 @@ var particles2d_proto = {
|
||||
var emitters = {
|
||||
// Spawn a particle for an emitter
|
||||
spawn: function(emitter) {
|
||||
emitter.particles.push({
|
||||
push(emitter.particles, {
|
||||
pos: {
|
||||
x: emitter.pos.x + (random() - 0.5) * emitter.spawn_area.width,
|
||||
y: emitter.pos.y + (random() - 0.5) * emitter.spawn_area.height
|
||||
@@ -76,17 +76,13 @@ var emitters = {
|
||||
alpha = 1 - (p.time - p.life * 0.7) / (p.life * 0.3)
|
||||
}
|
||||
p.color.a = alpha
|
||||
|
||||
// Remove dead particles
|
||||
if (p.time >= p.life) {
|
||||
emitter.particles.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
emitter.particles = filter(emitter.particles, p => p.time < p.life)
|
||||
|
||||
// Sync to film2d if handle provided
|
||||
if (emitter.handle) {
|
||||
if (emitter.handle)
|
||||
emitter.handle.particles = emitter.particles
|
||||
}
|
||||
},
|
||||
|
||||
// Create an emitter config
|
||||
|
||||
@@ -56,7 +56,7 @@ PlaydateBackend.prototype.get_or_create_target = function(width, height, key) {
|
||||
key: key
|
||||
}
|
||||
|
||||
this.target_pool[pool_key].push(target)
|
||||
push(this.target_pool[pool_key], target)
|
||||
return target
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ rasterize.ellipse = function ellipse(pos, radii, opt) {
|
||||
within_wedge(dx+1, dy, start, end, full_circle)
|
||||
|
||||
if (last || !next_in_ring) {
|
||||
strips.push({
|
||||
push(strips, {
|
||||
x: run_start,
|
||||
y: y_screen,
|
||||
width: (cx + dx) - run_start + 1,
|
||||
@@ -176,7 +176,7 @@ rasterize.round_rect = function round_rect(rect, radius, thickness) {
|
||||
var w = dx_out - dx_in
|
||||
if (w <= 0) continue
|
||||
|
||||
strips.push(
|
||||
push(strips,
|
||||
{ x:cx_l - dx_out, y:cy_t - dy, width:w, height:1 },
|
||||
{ x:cx_r + dx_in + 1, y:cy_t - dy, width:w, height:1 },
|
||||
{ x:cx_l - dx_out, y:cy_b + dy, width:w, height:1 },
|
||||
@@ -209,7 +209,7 @@ rasterize.fill_round_rect = function fill_round_rect(rect, radius) {
|
||||
var dx = floor(math.sqrt(radius * radius - dy * dy))
|
||||
var w = (dx << 1) + 1
|
||||
|
||||
caps.push(
|
||||
push(caps,
|
||||
{ x:cx_l - dx, y:cy_t - dy, width:w, height:1 },
|
||||
{ x:cx_r - dx, y:cy_t - dy, width:w, height:1 },
|
||||
{ x:cx_l - dx, y:cy_b + dy, width:w, height:1 },
|
||||
|
||||
@@ -100,7 +100,7 @@ function read_ignore(dir) {
|
||||
arrfor(lines, function(line) {
|
||||
line = trim(line)
|
||||
if (!line || starts_with(line, '#')) return
|
||||
patterns.push(line)
|
||||
push(patterns, line)
|
||||
})
|
||||
}
|
||||
return patterns
|
||||
@@ -120,7 +120,7 @@ Resources.getAllFiles = function(dir = "") {
|
||||
if (!st.filesize) return
|
||||
var ext = getExtension(f)
|
||||
if (!isRecognizedExtension(ext)) return
|
||||
results.push(fullPath)
|
||||
push(results, fullPath)
|
||||
} catch(e) {}
|
||||
})
|
||||
return results
|
||||
|
||||
16
sdl_gpu.cm
16
sdl_gpu.cm
@@ -700,7 +700,7 @@ function _load_image_file(path) {
|
||||
var decoded
|
||||
if (!bytes) return null
|
||||
|
||||
var ext = lower(array(path, '.').pop())
|
||||
var ext = lower(pop(array(path, '.')))
|
||||
var surface = null
|
||||
|
||||
switch (ext) {
|
||||
@@ -822,7 +822,7 @@ sdl_gpu.get_or_create_target = function(width, height, key) {
|
||||
key: key
|
||||
}
|
||||
|
||||
_target_pool[pool_key].push(target)
|
||||
push(_target_pool[pool_key], target)
|
||||
return target
|
||||
}
|
||||
|
||||
@@ -1202,23 +1202,23 @@ function _execute_commands(commands, window_size) {
|
||||
break
|
||||
|
||||
case 'draw_batch':
|
||||
pending_draws.push(cmd)
|
||||
push(pending_draws, cmd)
|
||||
break
|
||||
|
||||
case 'draw_text':
|
||||
pending_draws.push(cmd)
|
||||
push(pending_draws, cmd)
|
||||
break
|
||||
|
||||
case 'draw_texture_ref':
|
||||
pending_draws.push(cmd)
|
||||
push(pending_draws, cmd)
|
||||
break
|
||||
|
||||
case 'draw_shape':
|
||||
pending_draws.push(cmd)
|
||||
push(pending_draws, cmd)
|
||||
break
|
||||
|
||||
case 'draw_mesh2d':
|
||||
pending_draws.push(cmd)
|
||||
push(pending_draws, cmd)
|
||||
break
|
||||
|
||||
case 'blit':
|
||||
@@ -2219,7 +2219,7 @@ function _do_shader_pass(cmd_buffer, cmd, get_swapchain_tex) {
|
||||
var samplers = [{texture: input.texture, sampler: _sampler_linear}]
|
||||
if (cmd.extra_inputs) {
|
||||
arrfor(cmd.extra_inputs, function(extra) {
|
||||
samplers.push({texture: extra.texture, sampler: _sampler_linear})
|
||||
push(samplers, {texture: extra.texture, sampler: _sampler_linear})
|
||||
})
|
||||
}
|
||||
pass.bind_fragment_samplers(0, samplers)
|
||||
|
||||
@@ -87,16 +87,6 @@ function loop()
|
||||
render.present()
|
||||
dt = os.now() - now
|
||||
|
||||
fps_samples.push(dt)
|
||||
if (length(fps_samples) > fps_window) fps_samples.shift()
|
||||
|
||||
if (now - last_fps_update >= fps_update_period) {
|
||||
var sum = 0
|
||||
arrfor(fps_samples, x => sum += x)
|
||||
prosperon.window.title = `Bunnymark [fps: ${(length(fps_samples)/sum).toFixed(1)}]`;
|
||||
last_fps_update = now
|
||||
}
|
||||
|
||||
var delay = (1/60) - dt
|
||||
$delay(loop, delay)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ for (var i = 0; i < length(formats); i++) {
|
||||
if (!colorspaces[fmt.colorspace]) {
|
||||
colorspaces[fmt.colorspace] = [];
|
||||
}
|
||||
colorspaces[fmt.colorspace].push(fmt);
|
||||
push(colorspaces[fmt.colorspace], fmt);
|
||||
}
|
||||
|
||||
log.console("\nFound colorspaces:");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var Surface = use('sdl3/surface');
|
||||
|
||||
// Test creating a surface
|
||||
var surf = new Surface({width: 100, height: 100});
|
||||
var surf = Surface({width: 100, height: 100});
|
||||
log.console("Created surface:", surf.width, "x", surf.height);
|
||||
|
||||
log.console(surf)
|
||||
@@ -26,12 +26,12 @@ var pixels = surf.pixels();
|
||||
log.console("Got pixels array buffer, length:", pixels.byteLength);
|
||||
|
||||
// Test creating surface with custom format
|
||||
var surf4 = new Surface({width: 64, height: 64, format: "rgb24"});
|
||||
var surf4 = Surface({width: 64, height: 64, format: "rgb24"});
|
||||
log.console("Created RGB24 surface:", surf4.width, "x", surf4.height, "format:", surf4.format);
|
||||
|
||||
// Test creating surface from pixels
|
||||
var pixelData = new ArrayBuffer(32 * 32 * 4); // 32x32 RGBA
|
||||
var surf5 = new Surface({width: 32, height: 32, pixels: pixelData});
|
||||
var pixelData = ArrayBuffer(32 * 32 * 4); // 32x32 RGBA
|
||||
var surf5 = Surface({width: 32, height: 32, pixels: pixelData});
|
||||
log.console("Created surface from pixels:", surf5.width, "x", surf5.height);
|
||||
|
||||
log.console("Surface module test passed!");
|
||||
@@ -19,10 +19,10 @@ var tilemap = {
|
||||
var y = pos.y - this.offset_y
|
||||
|
||||
while (length(this.tiles) <= x)
|
||||
this.tiles.push([])
|
||||
push(this.tiles, [])
|
||||
|
||||
while (length(this.tiles[x]) <= y)
|
||||
this.tiles[x].push(null)
|
||||
push(this.tiles[x], null)
|
||||
|
||||
this.tiles[x][y] = image
|
||||
},
|
||||
|
||||
4
tween.cm
4
tween.cm
@@ -8,7 +8,7 @@ function make_engine(default_clock) {
|
||||
tweens: [],
|
||||
default_clock: default_clock || null,
|
||||
add(tween) {
|
||||
this.tweens.push(tween)
|
||||
push(this.tweens, tween)
|
||||
},
|
||||
remove(tween) {
|
||||
this.tweens = filter(this.tweens, t => t != tween)
|
||||
@@ -160,7 +160,7 @@ var TimelineProto = {
|
||||
engine: null,
|
||||
|
||||
add_event: function(time_value, fn) {
|
||||
this.events.push({ time: time_value, fn, fired: false })
|
||||
push(this.events, { time: time_value, fn, fired: false })
|
||||
},
|
||||
|
||||
add_tween: function(obj, props, duration, start_time) {
|
||||
|
||||
Reference in New Issue
Block a user