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