Skip to content
Snippets Groups Projects
Commit 4ea0bac4 authored by dg's avatar dg
Browse files

Particles can be attached to any entities, not just actors

Particles attached to an entity now display on the same z-order as the entity


git-svn-id: http://svn.net-core.org/repos/t-engine4@3120 51575b47-30f0-44d4-a5cc-537603b46e54
parent 7ed76fd1
No related branches found
No related tags found
No related merge requests found
......@@ -71,27 +71,6 @@ function _M:setupMinimapInfo(mo, map)
end
end
--- Adds a particles emitter following the actor
function _M:addParticles(ps)
self.__particles[ps] = true
if self.x and self.y and game.level and game.level.map then
ps.x = self.x
ps.y = self.y
game.level.map:addParticleEmitter(ps)
end
return ps
end
--- Removes a particles emitter following the actor
function _M:removeParticles(ps)
self.__particles[ps] = nil
if self.x and self.y and game.level and game.level.map then
ps.x = nil
ps.y = nil
game.level.map:removeParticleEmitter(ps)
end
end
--- Set the current emote
function _M:setEmote(e)
-- Remove previous
......@@ -106,6 +85,28 @@ function _M:setEmote(e)
end
end
--- Attach or remove a display callback
-- Defines particles to display
function _M:defineDisplayCallback()
if not self._mo then return end
local ps = {}
for e, _ in pairs(self.__particles) do
ps[#ps+1] = e
end
self._mo:displayCallback(function(x, y, w, h)
local e
for i = 1, #ps do
e = ps[i]
if e.ps:isAlive() then e.ps:toScreen(x + w / 2, y + h / 2, true)
else self:removeParticles(e)
end
end
return true
end)
end
--- Moves an actor on the map
-- *WARNING*: changing x and y properties manually is *WRONG* and will blow up in your face. Use this method. Always.
-- @param map the map to move onto
......@@ -136,20 +137,6 @@ function _M:move(x, y, force)
self.x, self.y = x, y
map(x, y, Map.ACTOR, self)
-- Update particle emitters attached to that actor
local del = {}
for e, _ in pairs(self.__particles) do
if e.dead then del[#del+1] = e
else
e.x = x
e.y = y
map.particles[e] = true
-- Give it our main _mo for display coords
e._mo = self._mo
end
end
for i = 1, #del do self.__particles[del[i]] = nil end
-- Move emote
if self.__emote then
if self.__emote.dead then self.__emote = nil
......@@ -309,11 +296,6 @@ end
function _M:deleteFromMap(map)
if self.x and self.y and map then
map:remove(self.x, self.y, engine.Map.ACTOR)
for e, _ in pairs(self.__particles) do
e.x = nil
e.y = nil
map:removeParticleEmitter(e)
end
end
end
......
......@@ -161,6 +161,51 @@ end
function _M:setupMinimapInfo(mo, map)
end
--- Adds a particles emitter following the entity
function _M:addParticles(ps)
self.__particles[ps] = true
if self.x and self.y and game.level and game.level.map then
ps.x = self.x
ps.y = self.y
self:defineDisplayCallback()
end
return ps
end
--- Removes a particles emitter following the entity
function _M:removeParticles(ps)
self.__particles[ps] = nil
if self.x and self.y and game.level and game.level.map then
ps.x = nil
ps.y = nil
self:defineDisplayCallback()
end
end
--- Attach or remove a display callback
-- Defines particles to display
function _M:defineDisplayCallback()
if not self._mo then return end
if not next(self.__particles) then self._mo:displayCallback(nil) return end
local ps = {}
for e, _ in pairs(self.__particles) do
ps[#ps+1] = e
end
self._mo:displayCallback(function(x, y, w, h)
local e
for i = 1, #ps do
e = ps[i]
if e.ps:isAlive() then e.ps:toScreen(x + w / 2, y + h / 2, true)
else
end
end
return true
end)
end
--- Create the "map object" representing this entity
-- Do not touch unless you *KNOW* what you are doing.<br/>
-- You do *NOT* need this, this is used by the engine.Map class automatically.<br/>
......@@ -188,6 +233,8 @@ function _M:makeMapObject(tiles, idx)
)
_M.__mo_repo[self._mo] = true
self:defineDisplayCallback()
-- Setup tint
self._mo:tint(self.tint_r, self.tint_g, self.tint_b)
......
......@@ -51,6 +51,8 @@ static int map_object_new(lua_State *L)
obj->move_max = 0;
obj->cb_ref = LUA_NOREF;
obj->mm_r = -1;
obj->mm_g = -1;
obj->mm_b = -1;
......@@ -94,10 +96,31 @@ static int map_object_free(lua_State *L)
obj->next = NULL;
}
if (obj->cb_ref != LUA_NOREF)
{
luaL_unref(L, LUA_REGISTRYINDEX, obj->cb_ref);
obj->cb_ref = LUA_NOREF;
}
lua_pushnumber(L, 1);
return 1;
}
static int map_object_cb(lua_State *L)
{
map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
if (lua_isfunction(L, 2))
{
obj->cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
else
{
if (obj->cb_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, obj->cb_ref);
obj->cb_ref = LUA_NOREF;
}
return 0;
}
static int map_object_chain(lua_State *L)
{
map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
......@@ -951,7 +974,7 @@ static int map_get_scroll(lua_State *L)
}
#define DO_QUAD(dx, dy, dw, dh, zoom, r, g, b, a, force) {\
#define DO_QUAD(dm, dx, dy, dw, dh, zoom, r, g, b, a, force) {\
vertices[(*vert_idx)] = (dx); vertices[(*vert_idx)+1] = (dy); \
vertices[(*vert_idx)+2] = map->tile_w * (dw) * (zoom) + (dx); vertices[(*vert_idx)+3] = (dy); \
vertices[(*vert_idx)+4] = map->tile_w * (dw) * (zoom) + (dx); vertices[(*vert_idx)+5] = map->tile_h * (dh) * (zoom) + (dy); \
......@@ -969,11 +992,31 @@ static int map_get_scroll(lua_State *L)
\
(*vert_idx) += 8; \
(*col_idx) += 16; \
if ((*vert_idx) >= 8*QUADS_PER_BATCH || force) {\
if ((*vert_idx) >= 8*QUADS_PER_BATCH || force || dm->cb_ref != LUA_NOREF) {\
glDrawArrays(GL_QUADS, 0, (*vert_idx) / 2); \
(*vert_idx) = 0; \
(*col_idx) = 0; \
} \
\
if (dm->cb_ref != LUA_NOREF) \
{\
lua_rawgeti(L, LUA_REGISTRYINDEX, dm->cb_ref); \
lua_pushnumber(L, dx); \
lua_pushnumber(L, dy); \
lua_pushnumber(L, map->tile_w * (dw) * (zoom)); \
lua_pushnumber(L, map->tile_h * (dh) * (zoom)); \
if (lua_pcall(L, 4, 1, 0)) \
{ \
printf("Display callback error: UID %ld: %s\n", dm->uid, lua_tostring(L, -1)); \
lua_pop(L, 1); \
} \
if (lua_isboolean(L, -1)) { \
glTexCoordPointer(2, GL_FLOAT, 0, texcoords); \
glVertexPointer(2, GL_FLOAT, 0, vertices); \
glColorPointer(4, GL_FLOAT, 0, colors); \
} \
lua_pop(L, 1); \
} \
}
inline void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, float seen, int nb_keyframes, bool always_show) ALWAYS_INLINE;
......@@ -1087,7 +1130,7 @@ void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *ma
while (dm)
{
tglBindTexture(GL_TEXTURE_2D, dm->textures[0]);
DO_QUAD(dx + dm->dx * map->tile_w + animdx, dy + dm->dy * map->tile_h + animdy, dm->dw, dm->dh, dm->scale, r, g, b, a * 2 / (3 + z), m->next);
DO_QUAD(dm, dx + dm->dx * map->tile_w + animdx, dy + dm->dy * map->tile_h + animdy, dm->dw, dm->dh, dm->scale, r, g, b, a * 2 / (3 + z), m->next);
dm = dm->next;
}
}
......@@ -1107,7 +1150,7 @@ void display_map_quad(GLuint *cur_tex, int *vert_idx, int *col_idx, map_type *ma
while (dm)
{
tglBindTexture(GL_TEXTURE_2D, dm->textures[0]);
DO_QUAD(dx + dm->dx * map->tile_w + animdx, dy + dm->dy * map->tile_h + animdy, dm->dw, dm->dh, dm->scale, r, g, b, a, m->next);
DO_QUAD(dm, dx + dm->dx * map->tile_w + animdx, dy + dm->dy * map->tile_h + animdy, dm->dw, dm->dh, dm->scale, r, g, b, a, m->next);
dm = dm->next;
}
......@@ -1341,6 +1384,7 @@ static const struct luaL_reg map_object_reg[] =
{
{"__gc", map_object_free},
{"texture", map_object_texture},
{"displayCallback", map_object_cb},
{"chain", map_object_chain},
{"tint", map_object_tint},
{"shader", map_object_shader},
......
......@@ -47,6 +47,8 @@ struct s_map_object {
enum {DL_NONE, DL_TRUE_LAST, DL_TRUE} display_last;
long uid;
int cb_ref;
struct s_map_object *next;
int next_ref;
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment