mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +00:00
Lunatic: retire per-sprite tsprite access for per-tile animation callback reg.
Don't yet make this official API though, since there are unresolved issues with newly created tsprites potentially being fed back to the animation loop. Add xmath.angvec(), xmath.bangvec(), tspr:set_sectnum(), tspr:setpos(). git-svn-id: https://svn.eduke32.com/eduke32@3937 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
c243bab0e7
commit
7f2175fcec
10 changed files with 133 additions and 47 deletions
|
@ -7051,6 +7051,7 @@ static void G_DoEventAnimSprites(int32_t j)
|
|||
if ((unsigned)ow < MAXSPRITES && spriteext[ow].flags & SPREXT_TSPRACCESS)
|
||||
{
|
||||
spriteext[ow].tspr = &tsprite[j];
|
||||
// XXX: wouldn't screenpeek be more meaningful as current player?
|
||||
VM_OnEvent(EVENT_ANIMATESPRITES, ow, myconnectindex, -1, 0);
|
||||
spriteext[ow].tspr = NULL;
|
||||
}
|
||||
|
@ -7884,6 +7885,11 @@ skip:
|
|||
for (j = spritesortcnt-1; j>=0; j--)
|
||||
G_DoEventAnimSprites(j);
|
||||
}
|
||||
|
||||
#ifdef LUNATIC
|
||||
if (G_HaveEvent(EVENT_ANIMATEALLSPRITES))
|
||||
VM_OnEvent(EVENT_ANIMATEALLSPRITES, -1, -1, -1, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -694,7 +694,10 @@ const char *EventNames[MAXEVENTS] =
|
|||
"EVENT_LOADGAME",
|
||||
"EVENT_SAVEGAME",
|
||||
"EVENT_PREGAME",
|
||||
"EVENT_CHANGEMENU"
|
||||
"EVENT_CHANGEMENU",
|
||||
#ifdef LUNATIC
|
||||
"EVENT_ANIMATEALLSPRITES",
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined LUNATIC
|
||||
|
|
|
@ -125,6 +125,9 @@ enum GameEvent_t {
|
|||
EVENT_SAVEGAME,
|
||||
EVENT_PREGAME,
|
||||
EVENT_CHANGEMENU,
|
||||
#ifdef LUNATIC
|
||||
EVENT_ANIMATEALLSPRITES, // 95
|
||||
#endif
|
||||
MAXEVENTS
|
||||
};
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ EVENT = {
|
|||
EVENT_SAVEGAME = 92,
|
||||
EVENT_PREGAME = 93,
|
||||
EVENT_CHANGEMENU = 94,
|
||||
-- EVENT_ANIMATEALLSPRITES = 95, -- internal
|
||||
}
|
||||
|
||||
-- NOTE: negated values are not exported to the ffi.C namespace or CON.
|
||||
|
@ -331,7 +332,7 @@ wdata_members =
|
|||
|
||||
|
||||
local SP = function(memb) return "sprite[%s]"..memb end
|
||||
local ATSP = function(memb) return "atsprite[%s]"..memb end
|
||||
local ATSP = function(memb) return "_atsprite[%s]"..memb end
|
||||
local AC = function(memb) return "actor[%s]"..memb end
|
||||
local SX = function(memb) return "spriteext[%s]"..memb end
|
||||
|
||||
|
|
|
@ -1928,8 +1928,31 @@ local g_firstRun = (ffiC.g_elCONSize == 0)
|
|||
|
||||
-- Actor functions, saved for actor chaining
|
||||
local actor_funcs = {}
|
||||
-- Event functions, saved for event chaining
|
||||
local event_funcs = {}
|
||||
|
||||
-- Per-actor sprite animation callbacks
|
||||
local animsprite_funcs = {}
|
||||
|
||||
local gameactor_internal = gameactor_internal -- included in lunatic.c
|
||||
local gameevent_internal = gameevent_internal -- included in lunatic.c
|
||||
|
||||
local function animate_all_sprites()
|
||||
for i=0,ffiC.spritesortcnt-1 do
|
||||
local tspr = ffiC.tsprite[i]
|
||||
|
||||
if (tspr.owner < ffiC.MAXSPRITES+0ULL) then
|
||||
local spr = tspr:getspr()
|
||||
local animfunc = animsprite_funcs[spr.picnum]
|
||||
|
||||
if (animfunc) then
|
||||
animfunc(tspr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- gameactor{tilenum [, flags [, strength [, action [, move [, movflags]]]]], func}
|
||||
-- Every arg may be positional OR key=val (with the name indicated above as key),
|
||||
-- but not both.
|
||||
|
@ -2018,6 +2041,24 @@ local function our_gameactor(args)
|
|||
end
|
||||
end
|
||||
|
||||
-- Register a potentially passed drawn sprite animation callback function.
|
||||
-- TODO: allow registering without main actor execution callback.
|
||||
local animfunc = args.animate
|
||||
if (animfunc ~= nil) then
|
||||
if (type(animfunc) ~= "function") then
|
||||
error("invalid 'animate' argument to gameactor: must be a function", 2)
|
||||
end
|
||||
|
||||
animsprite_funcs[tilenum] = replacep and func
|
||||
or (chainflags==AF.chain_beg) and chain_func3(animfunc, animsprite_funcs[tilenum])
|
||||
or (chainflags==AF.chain_end) and chain_func3(animsprite_funcs[tilenum], animfunc)
|
||||
or assert(false)
|
||||
|
||||
-- Register our EVENT_ANIMATEALLSPRITES only now so that it is not
|
||||
-- called if there are no 'animate' definitions.
|
||||
gameevent_internal(95, animate_all_sprites) -- EVENT_ANIMATEALLSPRITES
|
||||
end
|
||||
|
||||
-- All good, set the tile bits in initial run and register the actor!
|
||||
-- XXX: Need to see if some other state living on the C side is clobbered
|
||||
-- by Lua state recreation.
|
||||
|
@ -2040,10 +2081,7 @@ local function our_gameactor(args)
|
|||
actor_funcs[tilenum] = newfunc
|
||||
end
|
||||
|
||||
-- Event functions, saved for event chaining
|
||||
local event_funcs = {}
|
||||
|
||||
local gameevent_internal = gameevent_internal -- included in lunatic.c
|
||||
-- gameevent{<event idx or string> [, flags], <event function>}
|
||||
local function our_gameevent(args)
|
||||
bcheck.top_level("gameevent")
|
||||
|
@ -2313,7 +2351,6 @@ gv = setmtonce(gv_, tmpmt)
|
|||
-- This will create 'sprite', 'wall', etc. HERE, i.e. in the environment of this chunk
|
||||
defs_c.create_globals(_G)
|
||||
|
||||
|
||||
-- REMOVE this for release
|
||||
DBG_ = {}
|
||||
DBG_.debug = require("debug")
|
||||
|
|
|
@ -155,6 +155,7 @@ string.format([[
|
|||
|
||||
local SPRITE_STRUCT = [[
|
||||
struct {
|
||||
// TODO: transparent union with vec3_t pos?
|
||||
int32_t x, y, z;
|
||||
]]..bitint_member("UBit16", "cstat")..[[
|
||||
const int16_t picnum;
|
||||
|
@ -597,6 +598,7 @@ ffi.metatype("walltype", walltype_mt)
|
|||
local spriteext_mt = {
|
||||
__index = {
|
||||
-- Enable EVENT_ANIMATESPRITES for this sprite.
|
||||
-- XXX: unused?
|
||||
make_animated = function(sx)
|
||||
sx.flags = bor(sx.flags, 16)
|
||||
end,
|
||||
|
@ -669,22 +671,40 @@ local function get_sprite_idx(spr)
|
|||
return i
|
||||
end
|
||||
|
||||
-- Methods that are specific to sprites
|
||||
---=== Methods that are specific to sprites ===---
|
||||
|
||||
function spritetype_mt.__index.setpos(spr, pos) -- setsprite() clone
|
||||
spr.x, spr.y, spr.z = pos.x, pos.y, pos.z
|
||||
|
||||
local newsect = updatesector(spr, spr.sectnum)
|
||||
if (newsect < 0) then
|
||||
return -1
|
||||
end
|
||||
|
||||
if (spr.sectnum ~= newsect) then
|
||||
if (newsect >= 0 and spr.sectnum ~= newsect) then
|
||||
ffiC.changespritesect(get_sprite_idx(spr), newsect)
|
||||
end
|
||||
|
||||
return newsect
|
||||
end
|
||||
|
||||
|
||||
---=== Methods that are specific to tsprites ===---
|
||||
|
||||
function tspritetype_mt.__index.set_sectnum(tspr, sectnum)
|
||||
check_sector_idx(sectnum)
|
||||
ffi.cast(spritetype_ptr_ct, tspr).sectnum = sectnum
|
||||
end
|
||||
|
||||
-- TODO: flags (the same as sprite.UPDATE_FLAGS + "provide own sectnum",
|
||||
-- e.g. for example because it's already there from "hitscan").
|
||||
function tspritetype_mt.__index.setpos(tspr, pos)
|
||||
tspr.x, tspr.y, tspr.z = pos.x, pos.y, pos.z
|
||||
local newsect = updatesector(tspr, tspr.sectnum)
|
||||
|
||||
if (newsect >= 0 and tspr.sectnum ~= newsect) then
|
||||
tspr:set_sectnum(newsect)
|
||||
end
|
||||
|
||||
return newsect
|
||||
end
|
||||
|
||||
-- Methods that are specific to tsprites
|
||||
function tspritetype_mt.__index.dup(tspr)
|
||||
if (ffiC.spritesortcnt >= ffiC.MAXSPRITESONSCREEN+0ULL) then
|
||||
return nil
|
||||
|
@ -698,9 +718,11 @@ function tspritetype_mt.__index.dup(tspr)
|
|||
end
|
||||
|
||||
function tspritetype_mt.__index.getspr(tspr)
|
||||
return sprite[tspr.owner]
|
||||
check_sprite_idx(tspr.owner)
|
||||
return ffiC.sprite[tspr.owner]
|
||||
end
|
||||
|
||||
---======---
|
||||
|
||||
-- The user of this module can insert additional "spritetype" index
|
||||
-- methods and register them with "ffi.metatype".
|
||||
|
@ -923,7 +945,7 @@ sector = setmtonce({}, sector_mt)
|
|||
wall = setmtonce({}, wall_mt)
|
||||
sprite = setmtonce({}, sprite_mt)
|
||||
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[]')
|
||||
atsprite = setmtonce({}, atsprite_mt)
|
||||
_atsprite = setmtonce({}, atsprite_mt)
|
||||
|
||||
local function iter_wallsofsec(endwall, w)
|
||||
w = w+1
|
||||
|
@ -1039,7 +1061,7 @@ end
|
|||
|
||||
-- returns a hitdata_ct
|
||||
-- TODO: make v[xyz] be passed as one aggregate, too?
|
||||
-- Additionally, permit different coordinates? (ang&horiz, ...)
|
||||
-- TODO: make cliptype optional? What should be the default?
|
||||
function hitscan(pos, sectnum, vx,vy,vz, cliptype)
|
||||
check_sector_idx(sectnum)
|
||||
local vec = vec3_ct(pos.x, pos.y, pos.z)
|
||||
|
|
|
@ -182,7 +182,7 @@ local function new_initial_codetab()
|
|||
"local _xmath = require'xmath'",
|
||||
|
||||
-- Cache globals into locals.
|
||||
"local sector, sprite, wall, spriteext, atsprite = sector, sprite, wall, spriteext, atsprite",
|
||||
"local sector, sprite, wall, spriteext, _atsprite = sector, sprite, wall, spriteext, _atsprite",
|
||||
"local actor, player, projectile, g_tile = actor, player, projectile, g_tile",
|
||||
"local gameactor, gameevent, _gv = gameactor, gameevent, gv",
|
||||
"local updatesector, updatesectorz, cansee = updatesector, updatesectorz, cansee",
|
||||
|
|
|
@ -418,10 +418,8 @@ gameactor
|
|||
action = AC.TROOPSTAND,
|
||||
|
||||
func = function(i, playeri, dist)
|
||||
spriteext[i]:make_animated()
|
||||
|
||||
sprite[i].pal = math.random(32)
|
||||
-- sprite[i].ang = bit.band(sprite[i].ang-20, 2047)
|
||||
-- sprite[i].ang = bit.band(sprite[i].ang-20, 2047)
|
||||
|
||||
local spr = sprite[i]
|
||||
|
||||
|
@ -459,7 +457,36 @@ gameactor
|
|||
actr.movflagsbits:flip(actor.MOVFLAGS.spin)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
-- NOTE: the animate callback is not yet documented and thus not official API!
|
||||
animate = function(tspr)
|
||||
local tspr2 = tspr:dup()
|
||||
if (tspr2) then
|
||||
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60)
|
||||
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60)
|
||||
tspr2.cstatbits:set(CS.TRANS_BITMASK)
|
||||
end
|
||||
|
||||
-- XXX: inserted tsprites have floor shadow in classic! (r_shadow)
|
||||
-- G_DoSpriteAnimations() is passed as callback to the engine on occasion,
|
||||
-- in other words, created tsprites may be fed back to G_DoSpriteAnimations()!
|
||||
-- classic: shows shadow for both "ghost" liztroop and aim "reticle"
|
||||
-- Polymost: only for "ghost"
|
||||
-- Polymer: none
|
||||
local aimv = 256*xmath.bangvec(tspr.ang)
|
||||
local hit = hitscan(tspr^(16*256), tspr.sectnum, aimv.x, aimv.y, 0, gv.CLIPMASK1)
|
||||
|
||||
if (hit.wall >= 0) then
|
||||
local aimtspr = tspr:dup()
|
||||
if (aimtspr) then
|
||||
aimtspr.pal = 2
|
||||
aimtspr:set_picnum(555)
|
||||
aimtspr:setpos(hit.pos)
|
||||
aimtspr:set_sectnum(hit.sect)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
gameactor
|
||||
|
@ -539,24 +566,6 @@ gameactor
|
|||
end
|
||||
}
|
||||
|
||||
|
||||
gameevent
|
||||
{
|
||||
"ANIMATESPRITES",
|
||||
|
||||
function(aci)
|
||||
local tspr = atsprite[aci]
|
||||
if (tspr:getspr().picnum==D.LIZTROOP) then
|
||||
local tspr2 = tspr:dup()
|
||||
if (tspr2) then
|
||||
tspr2.x = tspr2.x + 512*math.cos(gv.totalclock/60)
|
||||
tspr2.y = tspr2.y + 512*math.sin(gv.totalclock/60)
|
||||
tspr2.cstatbits:set(CS.TRANS_BITMASK)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local function testbit(num, b)
|
||||
return bit.band(num,b)~=0 and 1 or 0
|
||||
end
|
||||
|
|
|
@ -31,14 +31,8 @@ local starPal = con.actorvar(0)
|
|||
require("end_gamevars")
|
||||
|
||||
|
||||
local function bangvec(bang)
|
||||
bang = math.floor(bang)
|
||||
return xmath.vec3(xmath.cosb(bang), xmath.sinb(bang))
|
||||
end
|
||||
|
||||
local function angvec(ang)
|
||||
return xmath.vec3(math.cos(ang), math.sin(ang))
|
||||
end
|
||||
local bangvec = xmath.bangvec
|
||||
local angvec = xmath.angvec
|
||||
|
||||
|
||||
local D = require("CON.DEFS")
|
||||
|
|
|
@ -285,6 +285,17 @@ end
|
|||
|
||||
---=== MISCELLANEOUS MATH ===---
|
||||
|
||||
local intarg = ffi.new("int32_t [1]")
|
||||
function bangvec(bang)
|
||||
intarg[0] = bang -- round towards zero
|
||||
return vec3(cosb(intarg[0]), sinb(intarg[0]))
|
||||
end
|
||||
|
||||
function angvec(ang)
|
||||
return vec3(cos(ang), sin(ang))
|
||||
end
|
||||
|
||||
|
||||
local zerovec = vec3()
|
||||
-- Point rotation. Note the different order of arguments from engine function.
|
||||
-- XXX: passing mixed vec2/vec3 is problematic. Get rid of vec2?
|
||||
|
|
Loading…
Reference in a new issue