From acd244b6a3b3bc31b78ff94604125c53741f6035 Mon Sep 17 00:00:00 2001 From: Bruce Pascoe Date: Sun, 6 May 2018 00:42:18 -0400 Subject: [PATCH] Backport `Shape.drawImmediate` from 5.2 This is another function that should have gone in from the start. Now that it's backported I'll be able to lower its API level to 1. --- CHANGELOG.md | 2 + assets/system/game_modules/prim.mjs | 88 ++++++++++++----------------- src/minisphere/pegasus.c | 76 ++++++++++++++++++++++++- 3 files changed, 113 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 642ff159e..fbf9cb38d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ miniSphere Changelog v5.0.2 - TBD ------------ +* Adds `Shape.drawImmediate()` function which avoids the overhead of creating + VertexList and Shape objects for immediate-mode drawing. * Adds `index.mjs` to the list of filenames recognized by the module loader. * Adds `print()` as an alias for `SSj.log()`. * Adds support for passing command-line arguments to a game's `main()`. diff --git a/assets/system/game_modules/prim.mjs b/assets/system/game_modules/prim.mjs index e49efba1d..116a9d594 100644 --- a/assets/system/game_modules/prim.mjs +++ b/assets/system/game_modules/prim.mjs @@ -55,14 +55,12 @@ class Prim var v1 = 1.0 - sy / texture.height; var u2 = (sx + width) / texture.width; var v2 = 1.0 - (sy + height) / texture.height; - var shape = new Shape(ShapeType.TriStrip, texture, - new VertexList([ - { x: x1, y: y1, u: u1, v: v1, color: mask }, - { x: x2, y: y1, u: u2, v: v1, color: mask }, - { x: x1, y: y2, u: u1, v: v2, color: mask }, - { x: x2, y: y2, u: u2, v: v2, color: mask }, - ])); - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.TriStrip, texture, [ + { x: x1, y: y1, u: u1, v: v1, color: mask }, + { x: x2, y: y1, u: u2, v: v1, color: mask }, + { x: x1, y: y2, u: u1, v: v2, color: mask }, + { x: x2, y: y2, u: u2, v: v2, color: mask }, + ]); } static drawCircle(surface, x, y, radius, color) @@ -87,9 +85,7 @@ class Prim color: color }); } - var vList = new VertexList(vertices); - var shape = new Shape(ShapeType.LineLoop, vList) - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.LineLoop, vertices); } static drawSolidCircle(surface, x, y, radius, color, color2) @@ -122,9 +118,7 @@ class Prim color: color2 }; - var vList = new VertexList(vertices); - var shape = new Shape(ShapeType.Fan, vList); - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.Fan, vertices); } static drawSolidRectangle(surface, x, y, width, height, color_ul, color_ur, color_lr, color_ll) @@ -133,14 +127,12 @@ class Prim color_lr = color_lr || color_ul; color_ll = color_ll || color_ul; - var shape = new Shape(ShapeType.TriStrip, - new VertexList([ - { x: x, y: y, color: color_ul }, - { x: x + width, y: y, color: color_ur }, - { x: x, y: y + height, color: color_ll }, - { x: x + width, y: y + height, color: color_lr }, - ])); - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.TriStrip, [ + { x: x, y: y, color: color_ul }, + { x: x + width, y: y, color: color_ur }, + { x: x, y: y + height, color: color_ll }, + { x: x + width, y: y + height, color: color_lr }, + ]); } static drawSolidTriangle(surface, x1, y1, x2, y2, x3, y3, color1, color2, color3) @@ -148,19 +140,17 @@ class Prim color2 = color2 || color1; color3 = color3 || color1; - var shape = new Shape(ShapeType.Triangles, - new VertexList([ - { x: x1, y: y1, color: color1 }, - { x: x2, y: y2, color: color2 }, - { x: x3, y: y3, color: color3 }, - ])); + Shape.drawImmediate(surface, ShapeType.Triangles, [ + { x: x1, y: y1, color: color1 }, + { x: x2, y: y2, color: color2 }, + { x: x3, y: y3, color: color3 }, + ]); } static drawLine(surface, x1, y1, x2, y2, thickness, color1, color2) { color2 = color2 || color1; - var shape; var xSize = x2 - x1; var ySize = y2 - y1; var length = Math.sqrt(xSize*xSize + ySize*ySize); @@ -168,14 +158,12 @@ class Prim return; var tx = 0.5 * thickness * (y2 - y1) / length; var ty = 0.5 * thickness * -(x2 - x1) / length; - shape = new Shape(ShapeType.Fan, - new VertexList([ - { x: x1 + tx, y: y1 + ty, color: color1 }, - { x: x1 - tx, y: y1 - ty, color: color1 }, - { x: x2 - tx, y: y2 - ty, color: color2 }, - { x: x2 + tx, y: y2 + ty, color: color2 }, - ])); - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.Fan, [ + { x: x1 + tx, y: y1 + ty, color: color1 }, + { x: x1 - tx, y: y1 - ty, color: color1 }, + { x: x2 - tx, y: y2 - ty, color: color2 }, + { x: x2 + tx, y: y2 + ty, color: color2 }, + ]); } static drawPoint(surface, x, y, color) @@ -190,20 +178,18 @@ class Prim var y1 = y + t; var x2 = x1 + width - thickness; var y2 = y1 + height - thickness; - var shape = new Shape(ShapeType.TriStrip, - new VertexList([ - { x: x1 - t, y: y1 - t, color: color }, - { x: x1 + t, y: y1 + t, color: color }, - { x: x2 + t, y: y1 - t, color: color }, - { x: x2 - t, y: y1 + t, color: color }, - { x: x2 + t, y: y2 + t, color: color }, - { x: x2 - t, y: y2 - t, color: color }, - { x: x1 - t, y: y2 + t, color: color }, - { x: x1 + t, y: y2 - t, color: color }, - { x: x1 - t, y: y1 - t, color: color }, - { x: x1 + t, y: y1 + t, color: color }, - ])); - shape.draw(surface); + Shape.drawImmediate(surface, ShapeType.TriStrip, [ + { x: x1 - t, y: y1 - t, color: color }, + { x: x1 + t, y: y1 + t, color: color }, + { x: x2 + t, y: y1 - t, color: color }, + { x: x2 - t, y: y1 + t, color: color }, + { x: x2 + t, y: y2 + t, color: color }, + { x: x2 - t, y: y2 - t, color: color }, + { x: x1 - t, y: y2 + t, color: color }, + { x: x1 + t, y: y2 - t, color: color }, + { x: x1 - t, y: y1 - t, color: color }, + { x: x1 + t, y: y1 + t, color: color }, + ]); } static fill(surface, color) diff --git a/src/minisphere/pegasus.c b/src/minisphere/pegasus.c index 71d01d5a6..500b634b3 100644 --- a/src/minisphere/pegasus.c +++ b/src/minisphere/pegasus.c @@ -184,8 +184,6 @@ COLORS[] = { "Plum", 221, 160, 221, 255 }, { "PowderBlue", 176, 224, 230, 255 }, { "Purple", 128, 0, 128, 255 }, - { "PurwaBlue", 155, 225, 255, 255 }, - { "RebeccaPurple", 102, 51, 153, 255 }, { "Red", 255, 0, 0, 255 }, { "RosyBrown", 188, 143, 143, 255 }, { "RoyalBlue", 65, 105, 225, 255 }, @@ -352,6 +350,7 @@ static bool js_Shader_setInt (int num_args, bool is_ctor, int ma static bool js_Shader_setIntArray (int num_args, bool is_ctor, int magic); static bool js_Shader_setIntVector (int num_args, bool is_ctor, int magic); static bool js_Shader_setMatrix (int num_args, bool is_ctor, int magic); +static bool js_Shape_drawImmediate (int num_args, bool is_ctor, int magic); static bool js_new_Shape (int num_args, bool is_ctor, int magic); static bool js_Shape_get_indexList (int num_args, bool is_ctor, int magic); static bool js_Shape_get_texture (int num_args, bool is_ctor, int magic); @@ -638,6 +637,7 @@ pegasus_init(void) api_define_method("Shader", "setIntVector", js_Shader_setIntVector, 0); api_define_method("Shader", "setMatrix", js_Shader_setMatrix, 0); api_define_class("Shape", PEGASUS_SHAPE, js_new_Shape, js_Shape_finalize); + api_define_function("Shape", "drawImmediate", js_Shape_drawImmediate, 0); api_define_property("Shape", "indexList", false, js_Shape_get_indexList, js_Shape_set_indexList); api_define_property("Shape", "texture", false, js_Shape_get_texture, js_Shape_set_texture); api_define_property("Shape", "vertexList", false, js_Shape_get_vertexList, js_Shape_set_vertexList); @@ -3570,6 +3570,78 @@ js_Shader_finalize(void* host_ptr) shader_unref(host_ptr); } +static bool +js_Shape_drawImmediate(int num_args, bool is_ctor, int magic) +{ + int array_idx; + ALLEGRO_BITMAP* bitmap = NULL; + int draw_mode; + int item_idx; + int num_entries; + image_t* surface; + image_t* texture = NULL; + shape_type_t type; + ALLEGRO_VERTEX* vertices; + + int i; + + if ((jsal_is_class_obj(0, PEGASUS_SURFACE))) { + surface = jsal_require_class_obj(0, PEGASUS_SURFACE); + type = jsal_require_int(1); + array_idx = 2; + if (num_args >= 4) { + if (!jsal_is_null(2) && !jsal_is_undefined(2)) + texture = jsal_require_class_obj(2, PEGASUS_TEXTURE); + array_idx = 3; + } + } + else { + surface = screen_backbuffer(g_screen); + type = jsal_require_int(0); + array_idx = 1; + if (num_args >= 3) { + if (!jsal_is_null(1) && !jsal_is_undefined(1)) + texture = jsal_require_class_obj(2, PEGASUS_TEXTURE); + array_idx = 2; + } + } + jsal_require_array(array_idx); + + num_entries = jsal_get_length(array_idx); + if (num_entries == 0) + jsal_error(JS_RANGE_ERROR, "Empty list is not allowed"); + + vertices = alloca(num_entries * sizeof(ALLEGRO_VERTEX)); + for (i = 0; i < num_entries; ++i) { + jsal_get_prop_index(array_idx, i); + jsal_require_object_coercible(-1); + item_idx = jsal_normalize_index(-1); + vertices[i].x = jsal_get_prop_key(item_idx, s_key_x) ? jsal_require_number(-1) : 0.0f; + vertices[i].y = jsal_get_prop_key(item_idx, s_key_y) ? jsal_require_number(-1) : 0.0f; + vertices[i].z = jsal_get_prop_key(item_idx, s_key_z) ? jsal_require_number(-1) : 0.0f; + vertices[i].u = jsal_get_prop_key(item_idx, s_key_u) ? jsal_require_number(-1) : 0.0f; + vertices[i].v = jsal_get_prop_key(item_idx, s_key_v) ? jsal_require_number(-1) : 0.0f; + vertices[i].color = jsal_get_prop_key(item_idx, s_key_color) + ? nativecolor(jsal_pegasus_require_color(-1)) + : al_map_rgba_f(1.0f, 1.0f, 1.0f, 1.0f); + jsal_pop(7); + } + + draw_mode = type == SHAPE_LINES ? ALLEGRO_PRIM_LINE_LIST + : type == SHAPE_LINE_LOOP ? ALLEGRO_PRIM_LINE_LOOP + : type == SHAPE_LINE_STRIP ? ALLEGRO_PRIM_LINE_STRIP + : type == SHAPE_TRIANGLES ? ALLEGRO_PRIM_TRIANGLE_LIST + : type == SHAPE_TRI_STRIP ? ALLEGRO_PRIM_TRIANGLE_STRIP + : type == SHAPE_TRI_FAN ? ALLEGRO_PRIM_TRIANGLE_FAN + : ALLEGRO_PRIM_POINT_LIST; + if (texture != NULL) + bitmap = image_bitmap(texture); + image_render_to(surface, NULL); + shader_use(galileo_shader(), false); + al_draw_prim(vertices, NULL, bitmap, 0, num_entries, draw_mode); + return false; +} + static bool js_new_Shape(int num_args, bool is_ctor, int magic) {