fix syntax
This commit is contained in:
178
playdate.cm
178
playdate.cm
@@ -82,46 +82,36 @@ PlaydateBackend.prototype.execute = function(commands) {
|
||||
}
|
||||
|
||||
PlaydateBackend.prototype.execute_command = function(cmd) {
|
||||
switch (cmd.cmd) {
|
||||
case 'begin_render':
|
||||
this.cmd_begin_render(cmd)
|
||||
break
|
||||
case 'end_render':
|
||||
this.cmd_end_render()
|
||||
break
|
||||
case 'set_camera':
|
||||
this.cmd_set_camera(cmd)
|
||||
break
|
||||
case 'draw_batch':
|
||||
this.cmd_draw_batch(cmd)
|
||||
break
|
||||
case 'shader_pass':
|
||||
this.cmd_shader_pass(cmd) // DEGRADES
|
||||
break
|
||||
case 'apply_mask':
|
||||
this.cmd_apply_mask(cmd) // NATIVE!
|
||||
break
|
||||
case 'composite':
|
||||
this.cmd_composite(cmd)
|
||||
break
|
||||
case 'blit':
|
||||
this.cmd_blit(cmd)
|
||||
break
|
||||
case 'clear':
|
||||
this.cmd_clear(cmd)
|
||||
break
|
||||
case 'present':
|
||||
// Nothing to do, display updates automatically
|
||||
break
|
||||
default:
|
||||
console.error(`Unknown command: ${cmd.cmd}`)
|
||||
if (cmd.cmd == 'begin_render') {
|
||||
this.cmd_begin_render(cmd)
|
||||
} else if (cmd.cmd == 'end_render') {
|
||||
this.cmd_end_render()
|
||||
} else if (cmd.cmd == 'set_camera') {
|
||||
this.cmd_set_camera(cmd)
|
||||
} else if (cmd.cmd == 'draw_batch') {
|
||||
this.cmd_draw_batch(cmd)
|
||||
} else if (cmd.cmd == 'shader_pass') {
|
||||
this.cmd_shader_pass(cmd) // DEGRADES
|
||||
} else if (cmd.cmd == 'apply_mask') {
|
||||
this.cmd_apply_mask(cmd) // NATIVE!
|
||||
} else if (cmd.cmd == 'composite') {
|
||||
this.cmd_composite(cmd)
|
||||
} else if (cmd.cmd == 'blit') {
|
||||
this.cmd_blit(cmd)
|
||||
} else if (cmd.cmd == 'clear') {
|
||||
this.cmd_clear(cmd)
|
||||
} else if (cmd.cmd == 'present') {
|
||||
// Nothing to do, display updates automatically
|
||||
} else {
|
||||
log.console(`Unknown command: ${cmd.cmd}`)
|
||||
}
|
||||
}
|
||||
|
||||
PlaydateBackend.prototype.cmd_begin_render = function(cmd) {
|
||||
var target = cmd.target
|
||||
var clear = cmd.clear
|
||||
|
||||
var pattern = null
|
||||
|
||||
if (target == 'screen') {
|
||||
// Render to screen framebuffer
|
||||
this.current_target = 'screen'
|
||||
@@ -130,10 +120,10 @@ PlaydateBackend.prototype.cmd_begin_render = function(cmd) {
|
||||
// Render to bitmap
|
||||
this.current_target = target
|
||||
this.pd.graphics.pushContext(target.bitmap)
|
||||
|
||||
|
||||
if (clear) {
|
||||
// Clear with color (Playdate is 1-bit, so color becomes pattern/dither)
|
||||
var pattern = this.color_to_dither_pattern(clear)
|
||||
pattern = this.color_to_dither_pattern(clear)
|
||||
this.pd.graphics.setDitherPattern(pattern)
|
||||
this.pd.graphics.fillRect(0, 0, target.width, target.height)
|
||||
}
|
||||
@@ -156,44 +146,54 @@ PlaydateBackend.prototype.cmd_set_camera = function(cmd) {
|
||||
PlaydateBackend.prototype.cmd_draw_batch = function(cmd) {
|
||||
var geometry = cmd.geometry
|
||||
var material = cmd.material || {}
|
||||
|
||||
|
||||
// Get image (Playdate uses LCDBitmap for textures)
|
||||
var image = this.get_image(material.texture || 'white')
|
||||
if (!image) return
|
||||
|
||||
|
||||
// Set draw mode based on material
|
||||
var draw_mode = this.material_to_draw_mode(material)
|
||||
this.pd.graphics.setImageDrawMode(draw_mode)
|
||||
|
||||
|
||||
// Draw each sprite in the batch
|
||||
for (var i = 0; i < length(geometry.indices); i += 6) {
|
||||
var i = 0
|
||||
var vert_idx = 0
|
||||
var v = null
|
||||
var screen_pos = null
|
||||
var v2 = null
|
||||
var width = 0
|
||||
var height = 0
|
||||
var scale = 0
|
||||
var alpha_pattern = null
|
||||
var scaled = null
|
||||
for (i = 0; i < length(geometry.indices); i += 6) {
|
||||
// Each sprite is 2 triangles = 6 indices = 4 vertices
|
||||
var vert_idx = geometry.indices[i]
|
||||
var v = geometry.vertices[vert_idx]
|
||||
|
||||
vert_idx = geometry.indices[i]
|
||||
v = geometry.vertices[vert_idx]
|
||||
|
||||
// Transform by camera
|
||||
var screen_pos = this.world_to_screen(v.pos, this.current_camera)
|
||||
|
||||
screen_pos = this.world_to_screen(v.pos, this.current_camera)
|
||||
|
||||
// Get sprite size from vertices
|
||||
var v2 = geometry.vertices[vert_idx + 2]
|
||||
var width = v2.pos[0] - v.pos[0]
|
||||
var height = v2.pos[1] - v.pos[1]
|
||||
|
||||
v2 = geometry.vertices[vert_idx + 2]
|
||||
width = v2.pos[0] - v.pos[0]
|
||||
height = v2.pos[1] - v.pos[1]
|
||||
|
||||
// Transform size by camera zoom
|
||||
var scale = this.get_camera_scale(this.current_camera)
|
||||
scale = this.get_camera_scale(this.current_camera)
|
||||
width *= scale
|
||||
height *= scale
|
||||
|
||||
|
||||
// Apply vertex color as dither pattern (best we can do on 1-bit)
|
||||
if (v.color.a < 1.0) {
|
||||
var alpha_pattern = this.alpha_to_dither_pattern(v.color.a)
|
||||
alpha_pattern = this.alpha_to_dither_pattern(v.color.a)
|
||||
this.pd.graphics.setDitherPattern(alpha_pattern)
|
||||
}
|
||||
|
||||
|
||||
// Draw image
|
||||
if (width != image.width || height != image.height) {
|
||||
// Need scaling
|
||||
var scaled = image.scaledImage(width / image.width, height / image.height)
|
||||
scaled = image.scaledImage(width / image.width, height / image.height)
|
||||
this.pd.graphics.drawBitmap(scaled, screen_pos[0], screen_pos[1])
|
||||
} else {
|
||||
this.pd.graphics.drawBitmap(image, screen_pos[0], screen_pos[1])
|
||||
@@ -204,35 +204,35 @@ PlaydateBackend.prototype.cmd_draw_batch = function(cmd) {
|
||||
PlaydateBackend.prototype.cmd_shader_pass = function(cmd) {
|
||||
// NO SHADERS ON PLAYDATE
|
||||
// Degrade gracefully based on shader type
|
||||
|
||||
|
||||
var shader = cmd.shader
|
||||
var input = cmd.input
|
||||
var params = cmd.params
|
||||
|
||||
|
||||
if (shader == 'threshold') {
|
||||
// Threshold: Just copy input (or could dither based on threshold)
|
||||
console.warn('Threshold shader not supported on Playdate, copying')
|
||||
log.console('Threshold shader not supported on Playdate, copying')
|
||||
this.copy_bitmap(input.bitmap, this.current_target.bitmap)
|
||||
}
|
||||
else if (shader == 'gaussian_blur') {
|
||||
// Blur: Box blur in CPU (slow but possible)
|
||||
console.warn('Blur shader using CPU fallback')
|
||||
log.console('Blur shader using CPU fallback')
|
||||
this.cpu_box_blur(input.bitmap, this.current_target.bitmap, params.radius || 5)
|
||||
}
|
||||
else if (shader == 'add_textures') {
|
||||
// Additive blend: Use XOR draw mode (not perfect but interesting)
|
||||
console.warn('Additive blend approximated with XOR')
|
||||
log.console('Additive blend approximated with XOR')
|
||||
this.pd.graphics.setImageDrawMode(this.pd.graphics.kDrawModeXOR)
|
||||
this.pd.graphics.drawBitmap(input.bitmap, 0, 0)
|
||||
}
|
||||
else if (shader == 'crt_filter') {
|
||||
// CRT: Not possible, just copy
|
||||
console.warn('CRT filter not supported on Playdate, copying')
|
||||
log.console('CRT filter not supported on Playdate, copying')
|
||||
this.copy_bitmap(input.bitmap, this.current_target.bitmap)
|
||||
}
|
||||
else {
|
||||
// Unknown shader: copy
|
||||
console.warn(`Shader ${shader} not supported on Playdate, copying`)
|
||||
log.console(`Shader ${shader} not supported on Playdate, copying`)
|
||||
this.copy_bitmap(input.bitmap, this.current_target.bitmap)
|
||||
}
|
||||
}
|
||||
@@ -242,23 +242,24 @@ PlaydateBackend.prototype.cmd_apply_mask = function(cmd) {
|
||||
var content = cmd.content_texture.bitmap
|
||||
var mask = cmd.mask_texture.bitmap
|
||||
var invert = cmd.invert
|
||||
|
||||
var inverted = null
|
||||
|
||||
if (invert) {
|
||||
// Invert mask first
|
||||
var inverted = this.pd.graphics.newBitmap(mask.width, mask.height)
|
||||
inverted = this.pd.graphics.newBitmap(mask.width, mask.height)
|
||||
this.pd.graphics.pushContext(inverted)
|
||||
this.pd.graphics.setImageDrawMode(this.pd.graphics.kDrawModeInverted)
|
||||
this.pd.graphics.drawBitmap(mask, 0, 0)
|
||||
this.pd.graphics.popContext()
|
||||
mask = inverted
|
||||
}
|
||||
|
||||
|
||||
// Set mask on content bitmap
|
||||
content.setMask(mask)
|
||||
|
||||
|
||||
// Draw masked content to current target
|
||||
this.pd.graphics.drawBitmap(content, 0, 0)
|
||||
|
||||
|
||||
// Clear mask (don't leave it set)
|
||||
content.setMask(null)
|
||||
}
|
||||
@@ -284,14 +285,15 @@ PlaydateBackend.prototype.cmd_blit = function(cmd) {
|
||||
var bitmap = cmd.texture.bitmap
|
||||
var dst_rect = cmd.dst_rect
|
||||
var filter = cmd.filter
|
||||
|
||||
|
||||
// Scale bitmap to fit dst_rect
|
||||
var scale_x = dst_rect.width / bitmap.width
|
||||
var scale_y = dst_rect.height / bitmap.height
|
||||
|
||||
var scaled = null
|
||||
|
||||
if (scale_x != 1.0 || scale_y != 1.0) {
|
||||
// Playdate only supports nearest-neighbor scaling
|
||||
var scaled = bitmap.scaledImage(scale_x, scale_y)
|
||||
scaled = bitmap.scaledImage(scale_x, scale_y)
|
||||
this.pd.graphics.drawBitmap(scaled, dst_rect.x, dst_rect.y)
|
||||
} else {
|
||||
this.pd.graphics.drawBitmap(bitmap, dst_rect.x, dst_rect.y)
|
||||
@@ -400,36 +402,44 @@ PlaydateBackend.prototype.get_image = function(name) {
|
||||
PlaydateBackend.prototype.cpu_box_blur = function(src, dst, radius) {
|
||||
// Simple box blur implementation in CPU
|
||||
// This is SLOW but correct
|
||||
|
||||
|
||||
var width = src.width
|
||||
var height = src.height
|
||||
|
||||
|
||||
// Get pixel data (Playdate API for accessing bitmap pixels)
|
||||
var src_data = src.getData()
|
||||
var dst_data = dst.getData()
|
||||
|
||||
for (var y = 0; y < height; y++) {
|
||||
for (var x = 0; x < width; x++) {
|
||||
var sum = 0
|
||||
var count = 0
|
||||
|
||||
var y = 0
|
||||
var x = 0
|
||||
var sum = 0
|
||||
var count = 0
|
||||
var dy = 0
|
||||
var dx = 0
|
||||
var sx = 0
|
||||
var sy = 0
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
sum = 0
|
||||
count = 0
|
||||
|
||||
// Sample neighborhood
|
||||
for (var dy = -radius; dy <= radius; dy++) {
|
||||
for (var dx = -radius; dx <= radius; dx++) {
|
||||
var sx = x + dx
|
||||
var sy = y + dy
|
||||
|
||||
for (dy = -radius; dy <= radius; dy++) {
|
||||
for (dx = -radius; dx <= radius; dx++) {
|
||||
sx = x + dx
|
||||
sy = y + dy
|
||||
|
||||
if (sx >= 0 && sx < width && sy >= 0 && sy < height) {
|
||||
sum += src_data[sy * width + sx]
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dst_data[y * width + x] = sum / count
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dst.setData(dst_data)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user