Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AGulev committed Apr 13, 2018
1 parent 21cb39b commit 043a63d
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 13 deletions.
47 changes: 47 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
std = "max"
files['.luacheckrc'].global = false
unused_args = false

globals = {
"sys",
"go",
"gui",
"label",
"render",
"crash",
"sprite",
"sound",
"tilemap",
"spine",
"particlefx",
"physics",
"factory",
"collectionfactory",
"iac",
"msg",
"vmath",
"url",
"http",
"image",
"json",
"zlib",
"iap",
"push",
"facebook",
"hash",
"hash_to_hex",
"pprint",
"init",
"final",
"update",
"on_input",
"on_message",
"on_reload",
"window",
"unityads",
"socket",
"defreview",
"resource",
"buffer",
"drawpixels"
}
1 change: 1 addition & 0 deletions drawpixels/ext.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: "DrawPixels"
232 changes: 232 additions & 0 deletions drawpixels/src/drawpixels.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
// Extension lib defines
#define LIB_NAME "DrawPixels"
#define MODULE_NAME "drawpixels"

#define DLIB_LOG_DOMAIN LIB_NAME

#include <dmsdk/sdk.h>
#include <math.h>

struct BufferInfo
{
dmBuffer::HBuffer buffer;
int width;
int height;
int colors_count;
};

BufferInfo buffer_info;

static int xytoi(int x, int y, int w, int h, int bpp) {
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= w) x = w - 1;
if (y >= h) y = h - 1;
return (y * w * bpp) + (x * bpp);
}

static int lenght(int x1, int y1, int x2, int y2){
int a = x1-x2;
int b = y1-y2;
return sqrt(a*a + b*b);
}

static void read_and_validate_buffer_info(lua_State* L, int index) {
luaL_checktype(L, index, LUA_TTABLE);
lua_getfield(L, index, "buffer");
lua_getfield(L, index, "width");
lua_getfield(L, index, "height");
lua_getfield(L, index, "colors_count");
dmScript::LuaHBuffer *lua_buffer = dmScript::CheckBuffer(L, -4);
buffer_info.buffer = lua_buffer->m_Buffer;

if (!dmBuffer::IsBufferValid(buffer_info.buffer)) {
luaL_error(L, "Buffer is invalid");
}

buffer_info.width = lua_tointeger(L, -3);
if (buffer_info.width == 0) {
luaL_error(L, "'width' of the buffer should be an integer and > 0");
}

buffer_info.height = lua_tointeger(L, -2);
if (buffer_info.height == 0) {
luaL_error(L, "'height' of the buffer should be an integer and > 0");
}

buffer_info.colors_count = lua_tointeger(L, -1);
if (buffer_info.colors_count == 0) {
luaL_error(L, "'colors_count' of the buffer should be an integer and > 0");
}
}

static int draw_circle(lua_State* L) {
int top = lua_gettop(L) + 4;

read_and_validate_buffer_info(L, 1);
uint32_t posx = luaL_checknumber(L, 2);
uint32_t posy = luaL_checknumber(L, 3);
uint32_t size = luaL_checknumber(L, 4);
uint32_t r = luaL_checknumber(L, 5);
uint32_t g = luaL_checknumber(L, 6);
uint32_t b = luaL_checknumber(L, 7);
uint32_t a = 0;
if (lua_isnumber(L, 5) == 1)
{
a = luaL_checknumber(L, 5);
}

uint8_t* bytes = 0;
uint32_t src_size = 0;

dmBuffer::Result result = dmBuffer::GetBytes(buffer_info.buffer, (void**)&bytes, &src_size);
if (result != dmBuffer::RESULT_OK) {
dmLogError("Unable to get bytes from source buffer");
return 0;
}
int newposx = 0;
int newposy = 0;
int half_size = size/2;
for(int x = -half_size; x < half_size; x++) {
for(int y = -half_size; y < half_size; y++) {
newposx = x + posx;
newposy = y + posy;
if (lenght(newposx, newposy, posx, posy) < half_size) {
int i = xytoi(newposx, newposy, buffer_info.width, buffer_info.height, buffer_info.colors_count);
bytes[i] = r;
bytes[i + 1] = g;
bytes[i + 2] = b;
if (buffer_info.colors_count == 4) {
bytes[i + 3] = a;
}
}
}
}

assert(top == lua_gettop(L));
return 0;
}

static int fill_texture(lua_State* L) {
int top = lua_gettop(L) + 4;

read_and_validate_buffer_info(L, 1);
uint32_t r = luaL_checknumber(L, 2);
uint32_t g = luaL_checknumber(L, 3);
uint32_t b = luaL_checknumber(L, 4);
uint32_t a = 0;
if (lua_isnumber(L, 5) == 1)
{
a = luaL_checknumber(L, 5);
}

uint8_t* bytes = 0;
uint32_t src_size = 0;

dmBuffer::Result result = dmBuffer::GetBytes(buffer_info.buffer, (void**)&bytes, &src_size);
if (result != dmBuffer::RESULT_OK) {
dmLogError("Unable to get bytes from source buffer");
return 0;
}
for(int i = 0; i < src_size; i += buffer_info.colors_count) {
bytes[i] = r;
bytes[i + 1] = g;
bytes[i + 2] = b;
if (buffer_info.colors_count == 4) {
bytes[i + 3] = a;
}
}

assert(top == lua_gettop(L));
return 0;
}

static int draw_rect(lua_State* L) {
int top = lua_gettop(L) + 4;

read_and_validate_buffer_info(L, 1);
uint32_t posx = luaL_checknumber(L, 2);
uint32_t posy = luaL_checknumber(L, 3);
uint32_t sizex = luaL_checknumber(L, 4);
uint32_t sizey = luaL_checknumber(L, 5);
uint32_t r = luaL_checknumber(L, 6);
uint32_t g = luaL_checknumber(L, 7);
uint32_t b = luaL_checknumber(L, 8);
uint32_t a = 0;
if (lua_isnumber(L, 5) == 1)
{
a = luaL_checknumber(L, 5);
}

uint8_t* bytes = 0;
uint32_t src_size = 0;

dmBuffer::Result result = dmBuffer::GetBytes(buffer_info.buffer, (void**)&bytes, &src_size);
if (result != dmBuffer::RESULT_OK) {
dmLogError("Unable to get bytes from source buffer");
return 0;
}

int half_size_x = sizex/2;
int half_size_y = sizey/2;
int newposx = 0;
int newposy = 0;
for(int x = -half_size_x; x < half_size_x; x++) {
for(int y = -half_size_y; y < half_size_y; y++) {
newposx = x + posx;
newposy = y + posy;
int i = xytoi(newposx, newposy, buffer_info.width, buffer_info.height, buffer_info.colors_count);
bytes[i] = r;
bytes[i + 1] = g;
bytes[i + 2] = b;
if (buffer_info.colors_count == 4) {
bytes[i + 3] = a;
}
}
}

assert(top == lua_gettop(L));
return 0;
}

// Functions exposed to Lua
static const luaL_reg Module_methods[] = {
{"circle", draw_circle},
{"fill", fill_texture},
{"rect", draw_rect},
{0, 0}
};

static void LuaInit(lua_State* L) {
int top = lua_gettop(L);
// Register lua names
luaL_register(L, MODULE_NAME, Module_methods);
lua_pop(L, 1);
assert(top == lua_gettop(L));
}

dmExtension::Result AppInitializeImpExtension(dmExtension::AppParams* params) {
return dmExtension::RESULT_OK;
}

dmExtension::Result InitializeImpExtension(dmExtension::Params* params) {
// Init Lua
LuaInit(params->m_L);
printf("Registered %s Extension\n", MODULE_NAME);
return dmExtension::RESULT_OK;
}

dmExtension::Result AppFinalizeImpExtension(dmExtension::AppParams* params) {
return dmExtension::RESULT_OK;
}

dmExtension::Result FinalizeImpExtension(dmExtension::Params* params) {
return dmExtension::RESULT_OK;
}


// Defold SDK uses a macro for setting up extension entry points:
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)

DM_DECLARE_EXTENSION(DrawPixels, LIB_NAME, AppInitializeImpExtension, AppFinalizeImpExtension, InitializeImpExtension, 0, 0, FinalizeImpExtension)
78 changes: 78 additions & 0 deletions example/canvas.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
function init(self)
msg.post(".", "acquire_input_focus")

-- size of texture when scaled to nearest power of two
local width = 512
local height = 1024

local our_buffer = buffer.create(width * height, {{name = hash("rgba"), type = buffer.VALUE_TYPE_UINT8, count = 4}})

self.buffer_info = {
buffer = our_buffer,
width = width,
height = height,
colors_count = 4 --- 3 for rgb, 4 for rgba
}

drawpixels.fill(self.buffer_info, 128, 128, 128)
self.dirty = true

-- drawing params
self.prev_pos = vmath.vector3()
self.resource_path = go.get("#sprite", "texture0")
self.header = {
width = width,
height = height,
type = resource.TEXTURE_TYPE_2D,
format = resource.TEXTURE_FORMAT_RGBA,
num_mip_maps = 1
}
end

function update(self, dt)
-- update texture if it's dirty (ie we've drawn to it)
if self.dirty then
resource.set_texture(self.resource_path, self.header, self.buffer_info.buffer)
self.dirty = false
end
end

function on_input(self, action_id, action)
if action_id == hash("touch") then
local pos = vmath.vector3(action.x, action.y, 0)
if action.pressed then
self.drawing = true
self.touch_pos = pos
elseif action.released then
self.drawing = false
end
if self.drawing then
-- calculate the length and direction from the previous touch
-- position to the current position
local length = math.ceil(vmath.length(self.touch_pos - pos))
local dir = vmath.normalize(self.touch_pos - pos)
if length == 0 then
length = 1
dir = vmath.vector3(0)
end
if self.prev_pos == pos then
return false
end
self.prev_pos = self.touch_pos
-- use current tool from the previous touch position to
-- the current touch position0
while length > 0 do
drawpixels.rect(self.buffer_info, self.touch_pos.x, self.touch_pos.y, 40, 40, 255, 255, 255, 255)
-- drawpixels.circle(self.buffer_info, self.touch_pos.x, self.touch_pos.y, 120, 255, 255, 255, 255)
self.dirty = true
self.touch_pos = self.touch_pos - dir
length = length - 1
end
end
end
end

function on_reload(self)
-- Add reload-handling code here
-- Remove this function if not needed
end
Loading

0 comments on commit 043a63d

Please sign in to comment.