Hard Light Productions Forums

Modding, Mission Design, and Coding => The Scripting Workshop => Topic started by: Parias on July 11, 2014, 11:36:57 am

Title: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 11, 2014, 11:36:57 am
I've got a couple of things I'd like to try for a campaign I'm working on, and for various plot purposes would like to be able to trigger playback of a full-color ANIs (pre-existing ones from the base game for now) directly to the player's viewport. I've had little prior experience with LUA scripting though, so I'm taking this as a learning opportunity to try and figure things out as I go.

To assess if what I want to do is even possible, I've pieced together the following basic script as a quick test:

Code: [Select]
#Global Hooks

$HUD:

[

tex = gr.loadTexture('cb_sm1-01_d',true)

gr.drawImage(tex)

]

#End

This works in the sense that it loads one of the command briefing ANIs from the main campaign and throws it into the top left of the player's viewport. However, only the first frame is shown - the ANI doesn't animate.  Is what I'm trying to do even supported - is there a better way of doing this?

I've been considering trying to create some kind of flat object in the 3D gameworld and attaching that right in front of the player instead, then applying a texture to it (if I can even figure out how) - but I thought this might be a more straightforward way of doing it.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: jr2 on July 11, 2014, 12:08:51 pm
Post a debug log?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: The E on July 11, 2014, 12:18:23 pm
Animations will not play themselves when loaded through the lua API. You basically have to switch frames yourself; you can access all frames in an animation by using the [] operator on a texture handle. In order to find out how many frames an animation has, you can use the "#" operator, and in order to find out how fast you have to switch through frames, you can use texture::getFPS().

You do have used the -output_scripting parameter from FSO to generate scripting.html, have you? That's basically your one-stop reference to all commands in the lua API.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 11, 2014, 12:22:49 pm
Post a debug log?

Certainly. Here you are: http://pastebin.com/raw.php?i=4maPsWuU

Looks to me like it's definitely recognizing the ANI, of course:

Code: [Select]
Got event GS_EVENT_ENTER_GAME (2) in state GS_STATE_BRIEFING (10)
Entering game at time = 129.508
ANI cb_sm1-01_d with size 440x200 (21.9% wasted)
ANI cb_sm1-01_d.ani with size 440x200 (21.9% wasted)
Frame  1 too long!!: frametime = 0.837 (0.837)
Got event GS_EVENT_END_GAME (4) in state GS_STATE_GAME_PLAY (2)
Unloading in mission messages


Also, I found this obscure post with some interesting information from WMCoolmon: http://www.hard-light.net/forums/index.php?topic=51493.msg1042099#msg1042099

Quote
Yes, animated interface art is possible, and AFAIK alpha channel support is enabled. You will have to show the correct frames of the animation manually, by using gr.loadTexture() and indexing the texture handle (with []) using the FPS, number of frames left, and ba.getFrametime() (which tells you how many seconds have passed). It's not that hard to do.

So it sounds like what I might want to do instead is something like gr.drawImage(tex[1]). gr.drawImage(tex[2]), etc - basically have it increment through each frame of animation?

If this is what I need, WMCoolmon's post fundamentally makes sense to me, but I'm unclear how I'd set up my script to just automatically increment / loop through all of the available frames of animation. I'm going to play around and look at some other examples of this. I actually just had some success - if I set gr.drawImage(tex[30]) for example, the single-frame image I saw was much further into the animation. I just need a way to run through / loop it automatically then.

Edit: Sorry The E, didn't see your post. That's perfect then, it sounds like I'm on the right track.

And yup, I did generate my own scripting.html file and have been parsing through it as well as the basic scripting tutorials on the Wiki - it's how I got this far :) From the data in there though (and given how new I am to scripting / coding in general), it wasn't clear to me that I could actually call individual frames of an animation from a texture handle and how to do it. I think I'm moving in the right direction now though!
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: zookeeper on July 11, 2014, 12:29:16 pm
If it's a looping animation, then it should be easy: in your drawing hook, just use mn.getMissionTime(), the number of frames and modulo to determine which frame should be drawn right now.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 11, 2014, 08:23:00 pm
Holy hell - she works!


Code: [Select]
#Global Hooks

$HUD:

[

tex = gr.loadTexture('cb_sm1-01_d',true)
totalframes = tex:getFramesLeft()
animfps = tex:getFPS()
missiontime = mn.getMissionTime()
i = (missiontime * animfps) % totalframes
gr.drawImage(tex[i])

]

#End

Now to go forth and turn this into something glorious. Thanks for your help - I promise to use this newfound power mostly for good, instead of evil. Mostly.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Cyborg17 on July 12, 2014, 11:24:34 am
Would this work with .EFF?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: The E on July 12, 2014, 11:34:08 am
Yes. At the level at which lua interacts with the engine, there is no difference between effs and anis.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on July 12, 2014, 12:03:45 pm
You should also cache the loaded texture as every time you call gr.loadTexture('cb_sm1-01_d',true) the whole animation is reloaded (it isn't completely reloaded, the engine is smart enough to know that it already loaded that animation and gives you that handle instead).
A simple fix would be something like this:
Code: [Select]
#Global Hooks

$HUD:
[
if tex == nil then
    tex = gr.loadTexture('cb_sm1-01_d',true)
end

totalframes = tex:getFramesLeft()
animfps = tex:getFPS()
missiontime = mn.getMissionTime()
i = (missiontime * animfps) % totalframes
gr.drawImage(tex[i])
]

#End
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 12, 2014, 12:11:07 pm
totalframes and animfps can probably also be set just once.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: zookeeper on July 12, 2014, 01:18:47 pm
And if you're doing that route, you might as well load the anim in an $On Game Init hook, so you don't get a delay from loading when the HUD is drawn for the first time.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 18, 2014, 08:29:31 pm
Hi all - I've made some decent progress but I'm having a weird blocker. Here's my current process:

* I've set up a script that reads a pre-determined file - cbanims.txt. Each line in this file has a string (i.e. "cb_sm1-01_d") which is indexed into a variable (if I'm saying that correctly).
* My script has a function ("readfile.showcbanim()") which uses this index to figure out which animation to play.
* From FRED, my intention is then to call my scripted function with the desired index number as an argument to dynamically play different animations based on in-mission triggers - i.e. invoke script-eval with readfile.showcbanim(2) will read the second line in my text file, and then play the anim file it references. The whole purpose of this is to get around the script-eval character limit in FRED of course.

Seems simple enough, right? I have this all laid out and functional. If I write "readfile.showcbanim(some number)" at the very end of my script with an "On HUD Draw" hook, this works perfectly - I can change the number in the script and the associated string with an anim filename that it finds will load and play.

However, if I call the script through FRED via script-eval, this doesn't work at all - or more specifically, the gr.drawImage component doesn't work. I stuck a ba.warning into my function so I'd get a pop-up alert upon execution, and even though this alert DOES trigger (and does show the expected variable data), the animation itself never actually plays. The image / texture area itself actually never even appears - it's like gr.drawImage just gets arbitrarily passed over if FRED is involved.

I've experimented with gr.drawString and I'm getting a similar effect - I just can't seem to invoke either of these if I'm using a function called from FRED for some reason. If I call the function from the end of the script itself however, they work fine.

Here's my horrible mess of code - does anybody have any idea what I'm doing wrong?

Code: [Select]
#Conditional Hooks

$Application: FS2_Open

$On HUD Draw:

[

readfile = {} --Sets up our table and gets it ready to store strings.
readfile.strings = {}
readfile.filename = "cbanims.txt" --We're going to be pulling our strings from "cbanims.txt"

if cf.fileExists(readfile.filename, "data/scripts",true) then --Confirms the existence of, then opens cbanims.txt in the data\scripts sub-folder.
local file = cf.openFile(readfile.filename,"r","data/scripts")
local i = 1
while true do
local entry = file:read("*l")
if entry == nil then break end
readfile.strings[i] = entry --Store indexed lines from cbanims.txt in readfile.strings
i=i+1
--ba.warning("Doing the things!")
end
file:close()
end

readfile.showcbanim = function(line) --Function called from FRED for showing our anim - uses the line number in cbanim.txt as an argument
local t = readfile.strings[line]
if t then
local f = loadstring(t)
if t then
ba.warning("Attempting to render " ..t.. " ")   --Blast a debug notice confirming what file we're loading (confirm data is being read correctly)
cbanim = gr.loadTexture(""..t.."",true) --Pull what anim resource to use from cbanims.txt and store it in cbanim

totalframes = cbanim:getFramesLeft() --Magic 3 lines to make the animation animate
animfps = cbanim:getFPS()
missiontime = mn.getMissionTime()

screenx = gr.getScreenWidth()
screeny = gr.getScreenHeight()
i = (missiontime * animfps) % totalframes
x = (screenx - cbanim:getWidth()) / 2
y = (screeny - cbanim:getHeight()) / 2 + 250
gr.drawImage(cbanim[i],x, y) --Play our animation
else
ba.warning("'"..t.."' loaded from line "..line.." of "..t.." and called from readfile.showcbanim() is not valid.") --Give a debug warning if string loaded isn't valid
end
else
ba.warning("readfile.showcbanim() has just attempted to load line "..line.." from "..readfile.filename.." and failed. Most likely this line or the file does not exist.") --Give a debug warning if the table entry is empty
end
end



]

#End

(You might see some similarities to FelixJim's RunFromFile script (http://www.hard-light.net/forums/index.php?topic=84819) here, so credit where credit is due as I've been using it to help learn how to get things working. I also appreciate the earlier suggestions on optimizing things and will be rolling those in once I'm past the "just get it working" phase)

Here's the debug warning I get from the ba.warning call in readfile.showcbanim() confirming that execution 'should' be working when I try to invoke this from FRED (the "Attempting to render (string)" bit - this accurately changes if I pass different line numbers from FRED, so it's definitely getting far enough to read my strings and start processing them)

Code: [Select]
---------------------------
Warning!
---------------------------
Attempting to render cb_sm1-01_d
ntdll.dll! ZwWaitForSingleObject + 21 bytes
kernel32.dll! WaitForSingleObjectEx + 67 bytes
kernel32.dll! WaitForSingleObject + 18 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! SCP_DumpStack + 354 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! Warning + 416 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! l_Base_warning_f + 72 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! luaD_precall + 785 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! luaV_execute + 5766 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! luaD_call + 161 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! f_call + 58 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! luaD_rawrunprotected + 86 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! luaD_pcall + 100 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! lua_pcall + 134 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! script_state::EvalString + 460 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! sexp_script_eval + 643 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! eval_sexp + 11499 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! eval_when_do_one_exp + 417 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! eval_when + 792 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! eval_sexp + 3659 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! mission_process_event + 547 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! mission_eval_goals + 517 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! game_simulation_frame + 1153 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! game_frame + 497 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! game_do_frame + 239 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! game_do_state + 379 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! gameseq_process_events + 237 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! game_main + 782 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! WinMain + 330 bytes
fs2_open_3_7_2_RC3-DEBUG.exe! __tmainCRTStartup + 358 bytes
[...]
[ This info is in the clipboard so you can paste it somewhere now ]


Use Yes to break into Debugger, No to continue.
and Cancel to Quit

---------------------------
Yes   No   Cancel   
---------------------------


So.. I'm completely stumped.  Is $On HUD Draw an inappropriate hook to use if you intend to call something from FRED, and if so, what should I be using instead? Why does this work fine when I call the function from inside the script, but not when I call it using script-eval in FRED?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: DahBlount on July 18, 2014, 08:39:03 pm
I'm fairly sure you should make the file "cbanims.cfg" in data\config and use references like $FileName:, then create a parse scheme to grab the file from the .cfg file. As it stands FSO can't read .txt files in data\scripts, so it's pretty much only possible to use a config file.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 18, 2014, 08:51:26 pm
Are you sure? Sorry, as I know I'm the noob here, but that seems contradictory to the information I'm seeing...

* The .txt file I have in data\scripts DOES get read - in fact, my LUA script works perfectly fine so long as I call my function at the end of it (instead of from FRED). Because I'm hooking into On HUD Draw, the .txt file is read and the corresponding anim effect is loaded and played constantly as soon as I start the mission. FSO seems to read it just fine. My goal is just to be able to trigger this dynamically from the mission instead of it being a constant, and it's only when I call the function from FRED (where a path and filename doesn't even enter the equation - it's just "run this function with this numerical argument" and the exact same LUA script that worked previously takes over from there) that a small component of it (gr.drawImage) doesn't seem to work. The rest of the script definitely does seem to work when called from FRED though as you can see the right string from my .txt file gets pulled when I put a ba.warning debug line in front of the execution.

* FelixJim's RFF script that I'm borrowing from (http://www.hard-light.net/forums/index.php?topic=84819) also relies on the same logic - his sample uses "runfromfile.txt" in data/scripts to read function calls in a similar way to what I'm doing (which is why I actually used this as a baseline example). Of course his post is also a year old, so I'm not sure if perhaps something changed engine-wise between then and now.

(Sorry if I'm being vague in explaining any of this though - I've been beating my head against it for the last two days and I'm about burned out)
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 18, 2014, 08:52:07 pm
The problem is that "On HUD Draw" will call that function once every frame, while script-eval is (presumably) only doing it once. What you should do instead is have your showcbanim() function load the animation and set it up so that gr.drawImage() then gets called every frame (until the animation is done, presumably).
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 18, 2014, 09:28:05 pm
So what you're saying is that my drawImage call probably is working when called via script-eval -- but it only happens for a single frame, and so basically goes by so fast I never see it?

Oh god, that.. actually makes perfect sense (and I could probably further verify if I set something up to report if drawImage was actually successful or not). In any case, I'm admittedly fuzzy on how to implement what you're describing but I think I conceptually get it. I'm going to play with this a bit and will report back if I need further guidance.

Thanks!
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 19, 2014, 01:37:22 am
Alright, sorry - I've been toying with this for the last little while and still haven't had any success.  I added a ba.warning bit at the end of my execution to report on the value of "i" (i.e. the current anim frame it should be on) out of the totalframes value (max number of frames in the anim):

Code: [Select]
gr.drawImage(cbanim[i],x, y) --Play our animation
ba.warning("i is " ..i.. ", totalframes is " ..totalframes.. "")

If I execute readfile.showcbanim from within my script, I'll get back "i is 3.75, totalframes is 180", "i is 7.5, totalframes is 180", etc every time I hit "no" to the debug warning window and step forward - I can see the animation rendering to the game screen and properly advancing in tandem.

If I use script-eval to call it from FRED, I'll actually see the same thing (albeit with more decimal places) - i.e. i is 15.149917602539, totalframes is 180. The message only appears once which sounds in sync with the "your FRED mission is only parsing script-eval once" theory. The interesting bit is if I change my script-eval event to use an "every-time" conditional instead of "when" (in both cases I'm using has-time-elapsed 1 as the trigger) I can see the "i" value - i.e. supposed current frame - increasing, so I'll get "i is 18.899917602539", "i is 22.649917602539", etc. The value which drives the current animation frame is clearly incrementing - the animation itself just doesn't appear.

I also just tried statically declaring a particular frame in my drawImage call (i.e. gr.drawImage(cbanim[15],x, y) ) which I was half-way hoping would leave at least a static image on the screen, but it didn't. Even if I stick this (and the associated loadTexture call) at the very highest point in my function, I still get nothing rendered if I call it from FRED.

I'm probably steering a bit off-course here and missing the obvious - you're probably right in that I still need a way to force the image to properly appear every frame, but from the results I'm getting (especially switching my script-eval call to an every-time conditional that's pretty much always true) leave me baffled on exactly what the difference is between calling this directly from my script, and from FRED, especially when I can't even get a static image to appear. What am I doing wrong - could you provide some tips on how I would get gr.drawImage to call every frame?

Edit: I've tried randomly switching over to different hooks too just for kicks - $On Hud Draw, $On Game Init, $On Frame, etc, but none of these seem to work any differently as far as the symptoms I'm seeing are concerned.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 19, 2014, 02:00:35 am
I would probably do something along these lines (with the caveat that I don't actually know Lua):
Code: [Select]
#Conditional Hooks

$Application: FS2_Open

$On Game Init:

[

readfile = {} --Sets up our table and gets it ready to store strings.
readfile.strings = {}
readfile.filename = "cbanims.txt" --We're going to be pulling our strings from "cbanims.txt"

if cf.fileExists(readfile.filename, "data/scripts",true) then --Confirms the existence of, then opens cbanims.txt in the data\scripts sub-folder.
local file = cf.openFile(readfile.filename,"r","data/scripts")
local i = 1
while true do
local entry = file:read("*l")
if entry == nil then break end
readfile.strings[i] = entry --Store indexed lines from cbanims.txt in readfile.strings
i=i+1
--ba.warning("Doing the things!")
end
file:close()
end

readfile.showcbanim = function(line) --Function called from FRED for showing our anim - uses the line number in cbanim.txt as an argument
local t = readfile.strings[line]
if t then
--ba.warning("Attempting to render " ..t.. " ")   --Blast a debug notice confirming what file we're loading (confirm data is being read correctly)
cbanim = gr.loadTexture(""..t.."",true) --Pull what anim resource to use from cbanims.txt and store it in cbanim

totalframes = cbanim:getFramesLeft() --Magic 3 lines to make the animation animate
animfps = cbanim:getFPS()
starttime = mn.getMissionTime()

screenx = gr.getScreenWidth()
screeny = gr.getScreenHeight()
else
ba.warning("readfile.showcbanim() has just attempted to load line "..line.." from "..readfile.filename.." and failed. Most likely this line or the file does not exist.") --Give a debug warning if the table entry is empty
end
end

]

$On HUD Draw:

[

if cbanim != nil then
local animtime = mn.getMissionTime() - starttime
local i = animtime * animfps
if i >= totalframes then
cbanim = nil
else
local x = (screenx - cbanim:getWidth()) / 2
local y = (screeny - cbanim:getHeight()) / 2 + 250
gr.drawImage(cbanim[i],x, y) --Play our animation
end
end


]

#End
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 19, 2014, 02:35:55 am
Wow, thanks! I was contemplating trying something like that...

Dropped it in and it loaded OK (only LUA-specific variance I think was I had to change "if cbanim != nil" to use ~=)..... at least in the sense that the game processed it without hemmoraging errors and all of the functions triggered when they should have (I stuck extra ba.warnings everywhere just to make sure - it definitely runs through readfile.showcbanim() which then successfully triggers the "if cbanim" bit in the seperate HUD Draw hook).

But sadly, nothing still gets rendered from gr.drawImage when I call readfile.showcbanim() from FRED via script-eval. And if I call showcbanim "locally" from within the script instead, the anim will appear and play the first few frames, but then disappear and not come back. That might just have to do with the slightly different way the anim is being looped though and I'm not worried about that right now  - the point is, an image still gets rendered by gr.drawImage if I call the associated function in the script locally, but not from script-eval in FRED.

I was admittedly working from the fsport mod for some of this, so I just shifted the script over to my base Freespace 2 folder and tried running the game with no mods at all just to see if maybe something silly was happening there. No change either.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on July 19, 2014, 02:40:26 am
Have you checked the coordinates where the script draws the animation?
This part seems a bit suspicious:
Code: [Select]
  screenx = gr.getScreenWidth()
  screeny = gr.getScreenHeight()
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 19, 2014, 03:56:11 am
the point is, an image still gets rendered by gr.drawImage if I call the associated function in the script locally, but not from script-eval in FRED.
:wtf: With the code I gave you, gr.drawImage() should always be being called with the same timing, regardless of if readfile.showcbanim() is called from script-eval or not. Did you make any other changes aside from "!=" -> "~=" and sprinkling some warnings?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 19, 2014, 08:53:11 am
the point is, an image still gets rendered by gr.drawImage if I call the associated function in the script locally, but not from script-eval in FRED.
:wtf: With the code I gave you, gr.drawImage() should always be being called with the same timing, regardless of if readfile.showcbanim() is called from script-eval or not. Did you make any other changes aside from "!=" -> "~=" and sprinkling some warnings?

Oh, duh! I'm sorry, I just realized it was actually my leftover script-eval from the near-blank FRED mission I'm using to test this that was causing the anim to disappear so fast - when it triggered (one second into the mission), the image vanished.

I just re-pasted the script in to test, with my only changes being the "if not nil" bit and adding "readfile.showcbanim(some line number)" to execute the script locally at the bottom of $On Game Init.  I then removed the event from FRED and the anim now automatically loads and plays all the way when the function is called locally..... but it only does it once and doesn't loop, which is OK since I probably want to use FRED to ultimately control the looping anyways (when I figure out why the FRED call won't load the image in the first place).

So I guess we're at roughly the same symptoms - the image definitely will load with your version of the script and play through, but only does it once (whereas mine loops indefinitely). And in either case it still doesn't draw anything if I try and invoke the function from FRED.


Have you checked the coordinates where the script draws the animation?
This part seems a bit suspicious:
Code: [Select]
  screenx = gr.getScreenWidth()
  screeny = gr.getScreenHeight()

Admittedly I haven't paid much attention to this just because the image DOES render fine if I call the script locally - it's only when I'm using script-eval in FRED to call it that it doesn't appear at all. Would this cause some kind of strange variance in the coordinates used?

Just to be sure, I tried statically setting the gr.drawImage xy arguments to 200, 200, but this made no change in my symptoms (still works fine from the script and appears where expected, but doesn't appear when triggered from script-eval)

Here's the basic event tree I'm using when trying to call the event from my mission, if it matters:

Code: [Select]
#Events ;! 1 total

$Formula: ( every-time
   ( has-time-elapsed 1 )
   ( script-eval
      "readfile.showcbanim(2)"
   )
)

(Note: I've tried both "every-time" and just "when" as conditionals)

This 'should' load cb_sm1-01_d as per what I have in cbanims.txt and play it as per the function. And it does - my ba.warning hooks throw alerts indicating it's processing the image file and advancing the associated frameindex, and I can even see it expressly loading the .ani asset (cb-sm1-01_d.ani in this case) in fs2open.log:

Code: [Select]
Got event GS_EVENT_ENTER_GAME (2) in state GS_STATE_BRIEFING (10)
Entering game at time =  70.523
ANI cb_sm1-01_d with size 440x200 (21.9% wasted)
ANI cb_sm1-01_d.ani with size 440x200 (21.9% wasted)
WARNING: "i is 15.149917602539, totalframes is 171" at lua.cpp:12105
Frame 46 too long!!: frametime = 4.433 (4.433)
WARNING: "i is 18.899917602539, totalframes is 171" at lua.cpp:12105
Frame 47 too long!!: frametime = 1.084 (1.084)
WARNING: "i is 22.649917602539, totalframes is 171" at lua.cpp:12105

But nothing actually appears on the screen if I do it this way.

You can try all this yourself if you want as well - this should work with an unmodded base game (or any other mod really). After deploying the script, create data\scripts\cbanims.txt and throw a line in with the desired animation (i.e. cb_sm1-01_d ). Then either execute the function in the script locally (i.e. from $On Game Init or whatever), or call it via script-eval and compare the difference. I'd actually be genuinely curious if anyone else can reproduce this, because I'm starting to wonder if I just have something really, really strange with my environment and that this really "should" be working. I'm almost tempted to try a clean install.

I guess to be clear, I should also mention I'm running all this on 3.7.2 RC3.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on July 19, 2014, 09:33:06 am
I just tested your script and it works perfectly. I tried starting it from a script and from FRED and it worked both times.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 19, 2014, 10:11:44 am
Arrrrgh, it must be something on my end then. OK, I'm going to go for a clean slate and try to see what's wrong specific to my installation. Thanks for checking.

Just for comparison, can you show me what FRED events you used and what build you're running?

Edit: Well this is embarrassing.. it was me all along. I cleaned out my tables folder a bit (which just had a scripting.tbl and an old scripting.bak file in it - I removed the .bak), cleaned out a couple of random .patch files from the root of my FS2 folder that had no godly reason to be there, and wiped / created a whole new blank mission to start from in FRED.

I can now do script-eval after has-time-elapsed (whatever) in FRED and the anim actually will appear and trigger as expected when the mission plays. Hooray!

I have no godly idea what exactly changed that was previously preventing script-eval from giving the expected results (vs calling the function from the script itself), but it seems like it's working now. God, 2 days wasted on this problem..

Thanks for helping me look into this. I may still have some more questions, but at least I've gotten past this silly blocker -- and learned a lot of valuable stuff along the way.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 19, 2014, 12:58:36 pm
cleaned out a couple of random .patch files from the root of my FS2 folder that had no godly reason to be there
A loose .patch file will never cause any altered behavior, but I'm glad you solved the problem.

but it only does it once and doesn't loop
Sorry, I assumed your end goal was to play an animation once, not loop indefinitely. All you have to do is restore the modulo operation and remove the ">= totalframes" check to make it loop until another animation plays (or cbanim gets set to nil).
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 20, 2014, 02:55:13 pm
cleaned out a couple of random .patch files from the root of my FS2 folder that had no godly reason to be there
A loose .patch file will never cause any altered behavior, but I'm glad you solved the problem.

but it only does it once and doesn't loop
Sorry, I assumed your end goal was to play an animation once, not loop indefinitely. All you have to do is restore the modulo operation and remove the ">= totalframes" check to make it loop until another animation plays (or cbanim gets set to nil).

I totally agree - I honestly couldn't find much in my FS2 environment that seemed like it would have caused the issue, and even now I'm still baffled as to what exactly was causing the very specific symptoms I was seeing. You're likely correct in that it had nothing to do with the .patch file - if anything, I'm thinking maybe my FRED mission had gotten screwed up somehow and making a totally fresh one somehow helped fix it. Again totally lost on why, as I had a really simple setup and there wasn't really much room for error... I'm content to leave it a mystery for now though.

And that's OK - I've been pretty vague about my intentions with this script anyways. I've put the modulo bit in and also added a second function to set cbanim to nil. So far this seems to be working exactly as I need; I can start the anim and have it loop indefinitely, then stop it on-demand with a second function, all from FRED. This is perfect!

Thanks again everyone for all your help!
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 12:40:30 am
Sorry, one more question (and from past SEXP experience this one's probably a doozy): Is it possible to get this sort of script working properly in multiplayer?

While this all works great for the multiplayer host, client systems don't seem to process the script at all when script-eval is called.

On a whim, I tried throwing out script-eval completely from my mission events, and switched to a variable-based approach instead with the following event / variable tree:

Code: [Select]
$Formula: ( when
   ( has-time-elapsed 3 )
   ( modify-variable @playanim[0] 3 )

(...)

$Variables:
(
0 "playanim" "0" "number" "network-variable"
)

I then added this code to the $On HUD Draw hook in my script:

Code: [Select]
if (mn.SEXPVariables['playanim']:isValid()) then
if (mn.SEXPVariables['playanim'].Value) > 0 then
ba.warning("Trying to process your variable dood")
readfile.showcbanim(mn.SEXPVariables['playanim'].Value)
mn.SEXPVariables['playanim'].Value = 0
end
end

This listens constantly for the state of the 'playanim' network variable in my mission. If it changes to something more than 0 (i.e. a usable index from my cbanims.txt list of animation filenames to play), it'll run the function to actually play the anim in question. It then sets the variable value back to 0 because if I don't, I think the function gets stuck being called over and over again from scratch each frame and doesn't have time to actually play the anim (nothing appears); I just want to trigger it once per variable-change. There's also of course a debug catch at the top just to help further confirm it's being triggered.

This again works awesome on the host - because I'm using a "network-variable" type I thought it would work on the client as well, but nothing happens. If I run both the host and client in debug mode, only the host gets the "Trying to process your variable dood" debug message and renders the anim. If I move the debug message up a level (so just checking if if (mn.SEXPVariables['playanim']:isValid())) then both the client and host systems will spew the debug message (still no anim play client-side of course), but I can't seem to get the client system to recognize at all that the network-variable has switched to a valid range.

Am I doing about this the wrong way? What I'm ultimately trying to do is hack together my own functional command-briefing anims for multiplayer co-op (since they apparently aren't possible normally), but maybe I'm being too ambitious here :) What I have so far works surprisingly well though:

Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 21, 2014, 12:53:45 am
What I'm ultimately trying to do is hack together my own functional command-briefing anims for multiplayer co-op (since they apparently aren't possible normally), but maybe I'm being too ambitious here :)
...A bit of an ambitious goal, yes. That is quite the impressive hackjob, though.

I vaguely remember someone intending to eventually add multiplayer support for command briefings, although that was some time ago; I personally haven't even tried to look into multiplayer code yet.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 01:14:23 am
Geez - do you ever sleep AdmiralRalwood? ;)

Yeah, I actually asked about this a few years back (http://www.hard-light.net/forums/index.php?topic=66813) and was advised it basically wasn't simple to do. With all the advances in LUA support, I decided it was finally time to try a creative workaround.

I do also know karajorma's put a ton of effort towards making sure a lot of the newer SEXP's work correctly in multiplayer (here, (http://www.hard-light.net/forums/index.php?topic=77775) for example), but I have no idea if script-eval is one of them.

That's why I figured if nothing else, a network-variable would do the trick (since... I guess it's supposed to work properly over network sessions? I'm actually unclear on the technicalities of it), but in my case it doesn't seem to be working at all.

I'm so close to having a basically-functional solution for this... just need to clear this final hurdle.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 21, 2014, 01:44:22 am
Geez - do you ever sleep AdmiralRalwood? ;)
Pacific coastie, here; it's not even midnight yet.

I figured if nothing else, a network-variable would do the trick (since... I guess it's supposed to work properly over network sessions? I'm actually unclear on the technicalities of it), but in my case it doesn't seem to be working at all.
That was, indeed, my impression of what network-variables were supposed to do, but if your code is showing that the variable is valid but staying as 0 on clients... a quick look at the code says that modify-variable is supposed to update network variables with clients, yet it sounds like that's not happening for some reason.

EDIT: Looks like the Lua interface calls sexp_modify_variable() when you set the value of a SEXP Variable from within a Lua script. If the two are happening in the same frame, the clients are probably getting both updates at the same time, and therefore have no time to start the animation.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 01:56:52 am
EDIT: Looks like the Lua interface calls sexp_modify_variable() when you set the value of a SEXP Variable from within a Lua script. If the two are happening in the same frame, the clients are probably getting both updates at the same time, and therefore have no time to start the animation.

Thanks for checking the code. That almost makes sense, but at the least shouldn't I be seeing the debug pop-up on the client (which should happen earlier in the execution, just before the function is called and the SEXP variable is reset to 0)? I don't even get that, leading me to believe the client never even realizes the variable is set to 3. I see it happen on the host system at exactly the same time, so I know the code-flow is working (and yes, I've been keeping my script / table folders synchronized between client and host, and they are both running debug builds)

Semi-related, but woa - I just found this (http://diaspora.fs2downloads.com/FREDDocs/multiplayer_walkthrough.html) and it sounds like exactly what I need!

Quote
Many of your missions for Diaspora will require you to start with a tube launch from a battlestar. This is a significant problem in singleplayer but is even more difficult to achieve in multiplayer since you need to consider what to do if the player respawns. In Diaspora R1, tube launches were handled mainly using SEXPs. This approach is rather cumbersome and as a result Diaspora R1.5 introduces a brand new script based system which can be used in both multiplayer and singleplayer missions. For multiplayer missions, you can't use script-eval because it only evaluates on the server. Instead you need to use the multi-eval SEXP which allows you do say which computers evaluate the script.

This sounds Diaspora-only though - how do I get ahold of this for normal Freespace / SCP use?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on July 21, 2014, 02:30:28 am
I remember seeing that SEXP in code review somewhere but it doesn't look like it is in trunk yet.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 21, 2014, 02:41:56 am
at the least shouldn't I be seeing the debug pop-up on the client[...]?
No, because the client is getting the update that the variable was set to 0 at the same time that it was getting the update that the variable was set to 3, so the client never has a chance to execute the code while the variable is non-zero.

Semi-related, but woa - I just found this (http://diaspora.fs2downloads.com/FREDDocs/multiplayer_walkthrough.html) and it sounds like exactly what I need!
[...]
This sounds Diaspora-only though - how do I get ahold of this for normal Freespace / SCP use?
Actually, looks it's not even in Diaspora, or at least not in 1.1.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: niffiwan on July 21, 2014, 03:12:50 am
Here's the code (http://www.hard-light.net/forums/index.php?topic=86422.0), based on r10253 so it'll probably need a bit of tweaking to apply to trunk.  If you want to give it a spin some one will need to compile a custom test build for you.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 12:02:17 pm
No, because the client is getting the update that the variable was set to 0 at the same time that it was getting the update that the variable was set to 3, so the client never has a chance to execute the code while the variable is non-zero.

Ah, that makes sense - your logic is sound then. I guess I could tell for sure if I set something up to just throw a message if the client sees the variable change without all the extra functionality around it.

And thanks Niffiwan - I just dusted off my Visual Studio installation, figured out how to get and compile the current source from SVN, and managed to hack together the changes from the patch into the relevant source files (you're right, a fair amount of manual work was needed here just due to the offset placement of just about everything).  I don't really have any idea what I'm doing, but so far it looks like I've been successful in getting the new "multi-eval" SEXP to work great on the host side. I'll do a proper client-side test later today when I have access to the necessary resources.

If I get it working, I guess I'll submit a formal request to get it into the main branch (particularly since I now know first-hand it won't take a lot of work to do aside from the requisite labor around the code review)  and work with what I have for the mean time. I'll advise how this goes.

(BTW, should new SEXPs appear in FRED automatically, or do you need to recompile FRED for that to happen? I didn't see multi-eval appear in my list of available items and had to add it to the mission file by hand instead)
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: AdmiralRalwood on July 21, 2014, 12:46:44 pm
No, because the client is getting the update that the variable was set to 0 at the same time that it was getting the update that the variable was set to 3, so the client never has a chance to execute the code while the variable is non-zero.

Ah, that makes sense - your logic is sound then. I guess I could tell for sure if I set something up to just throw a message if the client sees the variable change without all the extra functionality around it.
What you could have done is just made it so that instead of setting the variable to zero, it set a Lua variable to the current value of the network variable and only called the function if the two values differed (and special-cased 0 to stop the animation, for instance). Then you wouldn't have to screw around with custom builds. ;)

BTW, should new SEXPs appear in FRED automatically, or do you need to recompile FRED for that to happen?
You need to recompile FRED.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 02:03:39 pm
True! But then I wouldn't have a flimsy excuse for mucking around in the source code. :P

In all seriousness though that might actually be a good option to go with. I'm going to try multi-eval for now anyways just because I find it a bit more straight-forward to leverage (and having it available may provide wider-scale uses down the road), but if I don't get any traction with getting it into the main build, I might just do this instead. Above all else I don't want to have to fart around with my own custom branches of the codebase that will quickly fall out of date this just to make it work.

And I just recompiled FRED and see the new SEXP available now - thanks!

In other news, the problems never end... I fix one issue and run square into another:

(http://i.imgur.com/7AsyHJW.png)

Technically off-topic at this point, but arrrrgh.

This happens right as the mission starts (and the briefing stuff is supposed to appear) only on the client end, not the host (I've separately tried w/ both a dedicated server and client / host in-game setup). Line 21120 is multi_sexp_show_subtitle_text() -- I think I'm throwing too much at the show-subtitle SEXP. To work around the character limit, I'm triggering multiple show-subtitle events (each with associated messages less than 255 characters in length) when I make the briefing texts appear... if I had to guess, I'd suspect that this must be overloading the function that sends this stuff across the network.  I thought splitting this into separate SEXP calls that just happen to occur at the same time (one immediately after the other in the same event) would work, but maybe it's still batching it all together and firing too much text across at once. 

I'm going to try splitting them up w/ 1-second delays and see if that helps.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: niffiwan on July 21, 2014, 04:58:51 pm
That kinda looks like memory corruption and a code bug.  Can you grab a stacktrace using the debugger?  Or maybe post the relevant mission and the steps to reproduce the crash?
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 05:40:33 pm
Yeah, I was doing a bit more reading and thinking it seemed pretty similar to this report (http://scp.indiegames.us/mantis/view.php?id=3050), or at least might contribute to the note at the end about there potentially being other limits elsewhere in the code potentially impacting things. This also might be sort of a different issue (since in this case we're supposed to have a limit of 255 characters per-subtitle event, vs the 31 character limit referenced there), but one way or another I'd be super-happy if this kind of problem could be fixed so that I didn't have to try and work around it.

I'll collect some more details and then fire this into Mantis as a separate thread to avoid confusion with this topic.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on July 21, 2014, 11:37:17 pm
Looks like I wasn't quite correct - from what I'm reproducing, the crash actually seems to happen for clients when show-subtitle-text is triggered with a message that has more than 32 characters. The SEXP is actually supposed to support 255 AFAIK, and it does for the host system, but clients just shoot themselves in the head with that much text.

I actually dug fairly deep into this and I think I've not only found the cause, but compiled a fix for myself as well to get past this issue (although with a request for a better solution if one is needed for the main branch). My full report is here (http://scp.indiegames.us/mantis/view.php?id=3077). Is this the right way to do a bug report? ;)

With this fix put in place and multi-eval enabled, this is looking good! Host and client systems alike can play the cbriefing fairly consistently (some text-formatting issues aside) and transition into the rest of the campaign. I still have a lot of work to do (resolution scaling in particular), but things are rapidly approaching a 'playable' state. I'm going to test the heck out of multi-eval, and if I can't find any problems I'll probably formally request it get added to the main build; I'd really like to see it in there if possible
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on August 05, 2014, 01:36:32 am
Ack! OK... I've run into a really weird problem that I'm utterly stumped how to resolve (or even troubleshoot further), and was hoping for some more input. I've nearly got my glorious upgrade of a co-operative-friendly-FSPort-campaign ready to roll, but this issue is turning into a huge blocker.

Basically, after about 15 animations play, I suddenly start getting nil values returned from my variables. Here's an example error that's thrown:

Code: [Select]
---------------------------
Error!
---------------------------
LUA ERROR: [string "scripting.tbl - On HUD Draw"]:15: attempt to perform arithmetic on global 'totalframes' (a nil value)

------------------------------------------------------------------
ADE Debug:

------------------------------------------------------------------
Name: (null)

Name of:

Function type: main

Defined on: 0

Upvalues: 0



Source: scripting.tbl - On HUD Draw

Short source: [string "scripting.tbl - On HUD Draw"]

Current line: 13

- Function line: 0

------------------------------------------------------------------




------------------------------------------------------------------


stack traceback:
[C]: ?
[string "scripting.tbl - On HUD Draw"]:15: in main chunk

------------------------------------------------------------------


------------------------------------------------------------------


[ This info is in the clipboard so you can paste it somewhere now ]





Use Yes to break into Debugger, No to continue.

and Cancel to Quit
---------------------------
Yes   No   Cancel   
---------------------------

"totalframes" is a variable in my script that gets populated with the number of frames in the animation I'm loading. Errors involving a nil value can occur if I pass it an invalid file to process... except I'm not.  I've thrown debug notices just ahead of the execution and can confirm it's getting a valid file to process. Everything just BEFORE that step in the execution gets lined up fine, but when it hits "totalframes", suddenly it thinks the data is nil / invalid.

And this suddenly only happens after the same animation script has already been called several times and has worked fine (in a particular test case that I'll attach, it's the 16th execution that causes this).

What's up - am I tripping on some kind of obscure garbage cleanup routine? Is there some kind of weird overflow happening with my data? Am I stuffing one of my variables or arrays with too much data to process?

I don't have any command briefings in my co-op campaign which in themselves involve sixteen stages - but over the course of a continuous gameplay session and multiple command briefing segments, you'll eventually hit this limit and break the script. The only way to fix it is to restart the game - no new animations called from the script will properly appear until you do this.

I've back-ported all of my work into a small sample that can be easily dropped and tested into a base FSOpen install just in case you want to see this for yourselves - this includes an exaggerated mission that will load 16 cbanims, in sequence. Here it is:

http://illuminatihq.net/mp-cbanim.rar

To repro: Stick Blank.fs2 into your data\missions folder, cbanims.txt into your data\scripts folder, and scripting.tbl (which of course is the actual script in question) into your data\tables folder. Load FSOpen (i.e. fs2_open_3_7_2_RC3-DEBUG), start a new multiplayer co-op session, and load the "CrashTestDummy" single mission.

Step through the command briefings (hit "T" to advance the stage, as per on-screen instructions) - as each loads, you should get a pop-up window confirming which anim file is about to be loaded. When it hits the 16th, you'll see it tries to load it, then throws the error about "totalframes" being nil and it'll refuse to render any further anims. You can bomb out of the mission and retry it to get the same result (all previously-loaded animations will play until it again hits the 16th). If you want to confirm that the file being loaded *is* valid, feel free to open cbanims.txt and switch the order of the files around; no matter what file it is, it'll throw the same error when you hit the 16th stage and break.

In short: Zah?

Just for a quick at-a-glance reference, here's a copy of the latest version of the script I'm using (same as in the linked sample download, minus a couple of pages of "howto" comments)

Code: [Select]
#Conditional Hooks

$Application: FS2_Open

$On Game Init:

[
readfile = {} --Sets up our table and gets it ready to store strings.
readfile.strings = {}
readfile.filename = "cbanims.txt" --We're going to be pulling our strings from "cbanims.txt"

screenx = gr.getScreenWidth()
screeny = gr.getScreenHeight() --Get our current screen resolution. Used for image scaling and placement purposes.

if cf.fileExists(readfile.filename, "data/scripts",true) then --Confirms the existence of, then opens cbanims.txt in the data\scripts sub-folder.
local file = cf.openFile(readfile.filename,"r","data/scripts")
local i = 1
while true do
local entry = file:read("*l")
if entry == nil then break end
readfile.strings[i] = entry --Store indexed lines from cbanims.txt in readfile.strings
i=i+1
end
file:close()
end

readfile.showcbanim = function(line) --Function called from FRED for showing our anim - uses the line number in cbanims.txt as an argument
local t = readfile.strings[line]
if t then
ba.warning("Attempting to render " ..t.. " ")   --Blast a debug notice confirming what file we're loading (confirm data is being read correctly)
cbanim = gr.loadTexture(""..t.."",true) --Pull what anim resource to use from cbanims.txt and store it in  cbanim

totalframes = cbanim:getFramesLeft() --Magic 3 lines to make the animation animate
animfps = cbanim:getFPS()
starttime = mn.getMissionTime()
else
ba.warning("readfile.showcbanim() has just attempted to load line "..line.." from "..readfile.filename.." and failed. Most likely this line or the file does not exist.") --Give a debug warning if the table entry is empty
end
end

readfile.showcboverlay = function(line) --Function called from FRED for showing our command-briefing overlay - uses the line number in cbanims.txt as an argument
local t = readfile.strings[line]
if t then
--ba.warning("Attempting to render " ..t.. " ")   --Blast a debug notice confirming what file we're loading (confirm data is being read correctly)
cboverlay = gr.loadTexture(""..t.."",true) --Pull what anim resource to use from cbanims.txt and store it in cbanim

else
ba.warning("readfile.showcboverlay() has just attempted to load line "..line.." from "..readfile.filename.." and failed. Most likely this line or the file does not exist.") --Give a debug warning if the table entry is empty
end
end

]

$On HUD Draw:

[

if cboverlay ~= nil then --If readfile.showcboverlay has been called and has populated the "cboverlay" variable, display the command-briefing overlay.
local x = (screenx - cboverlay:getWidth())
local y = (screeny - cboverlay:getHeight()) --Stretch it across the entire screen
gr.drawImage(cboverlay, 0, 0, screenx, screeny) --Play our animation
end

stopcboverlay = function() --FRED-called function to stop drawing the command-briefing overlay. REMEMBER TO CALL THIS BEFORE ENDING YOUR BRIEFING MISSION.
cboverlay:unload()
cboverlay = nil
end

if cbanim ~= nil then --If readfile.showcbanim has been called and has populated the "cbanim" variable, display the command-briefing animation.
local animtime = mn.getMissionTime() - starttime
--local i = animtime * animfps
local i = (animtime * animfps) % totalframes
if i >= totalframes then
cbanim = nil
else
local x = (screenx - cbanim:getWidth()) / 2 - 120             
local y = (screeny - cbanim:getHeight()) / 2 + 200 --Make this appear in the appropriate box towards lower-left-ish corner of the screen. TODO: Adjust for proper resolution scaling!
gr.drawImage(cbanim[i],x, y) --Play our animation
end
end

stopcbanim = function() --FRED-called function to stop drawing the command-briefing animation. REMEMBER TO CALL THIS BEFORE ENDING YOUR BRIEFING MISSION.
cbanim:unload()
cbanim = nil
end

if (mn.SEXPVariables['playanim']:isValid()) then --Ignore all these, chaos happened here. TODO: Clean up the chaos
if (mn.SEXPVariables['playanim'].Value) > 0 then
ba.warning("Trying to process your variable dood")
readfile.showcbanim(mn.SEXPVariables['playanim'].Value)
mn.SEXPVariables['playanim'].Value = 0
end
end


]

#End

Any ideas? Hope I'm not missing something obvious :)

Going to experiment a bit more with some of the unloading functions - I already tried invoking the "unload" function for cbanim (and setting it to nil) for the first step of every stage of the briefing, and while this fixes a potential long-term memory usage problem (and is something I should do for the final product), it doesn't seem to make any difference as far as this issue goes.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on August 05, 2014, 01:43:09 am
Do you unload the cbanims once you don't need them anymore?
It shouldn't be a problem but it's something that you should do to keep the code clean.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: ngld on August 05, 2014, 05:16:28 am
EDIT: You have to manually unload *all* animations you have loaded. You should replace this line
Code: [Select]
cbanim = gr.loadTexture(""..t.."",true)
with this:
Code: [Select]
if cbanim ~= nil then
  cbanim:unload()
end
cbanim = gr.loadTexture(""..t.."",true)
It still won't work because of an engine bug (http://scp.indiegames.us/mantis/view.php?id=3084). cbanim:unload() will unload the bitmap but not release it.

Whenever totalframes is nil, cbanim:getFramesLeft() returned nil because cbanim wasn't a valid handle.

If you're running a debug build, you can press Shift+Enter to open the debug console and type bm_frag to show the bitmap memory. Most blocks should be grey AKA free. When you advance to the 10th stage and look at the bitmap memory again you'll notice that many (if not most) grey blocks have turned into blue blocks (AKA reserved for animations). At some point bm_load_animation() (called by loadTexture()) will fail because it ran out of memory.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on August 05, 2014, 11:38:24 am
Do you unload the cbanims once you don't need them anymore?
It shouldn't be a problem but it's something that you should do to keep the code clean.

Totally agree. Right now at the end of each command briefing "mission" (but only at the very end, i.e. after several animations have loaded), I call stopcbanim() and stopcboverlay() before I trigger the end-mission SEXP to unload those components and set their values to nil. However watching the VRAM memory usage in debug mode, I could see this perpetually climbing with each briefing stage - more aggressive unloading is definitely prudent here.

Which brings me on to...

EDIT: You have to manually unload *all* animations you have loaded. You should replace this line
Code: [Select]
cbanim = gr.loadTexture(""..t.."",true)
with this:
Code: [Select]
if cbanim ~= nil then
  cbanim:unload()
end
cbanim = gr.loadTexture(""..t.."",true)
It still won't work because of an engine bug (http://scp.indiegames.us/mantis/view.php?id=3084). cbanim:unload() will unload the bitmap but not release it.

Whenever totalframes is nil, cbanim:getFramesLeft() returned nil because cbanim wasn't a valid handle.

If you're running a debug build, you can press Shift+Enter to open the debug console and type bm_frag to show the bitmap memory. Most blocks should be grey AKA free. When you advance to the 10th stage and look at the bitmap memory again you'll notice that many (if not most) grey blocks have turned into blue blocks (AKA reserved for animations). At some point bm_load_animation() (called by loadTexture()) will fail because it ran out of memory.

Aha! Engine bug :D This was it - and thank you for detailing this in the Mantis report. I recompiled my build with the adjustments you suggested. I added your suggested script adjustment, and updated all of my command briefing "missions" in FRED to call ( multi-eval/script-eval "stopcbanim()" ) as the very first step of every briefing stage (before calling the next anim).

The combination of these steps seems to have done the trick! I think the lua.cpp change was the catalyst though, as I had played with more aggressive unloading earlier with no apparent impact on the overall problem. If it's OK, I'm going to add a note to your ticket referencing back to this thread as another reason for the fix being needed. I'm also working under the assumption of course that the suggested changes aren't going to discreetly break something somewhere else...

Unfortunately this means I now have three disparate reasons for needing to run my own separate fork of the code for my co-op mod to work:

--Availability of multi-eval (arguable as I could probably use properly-set network-variables to accomplish similar triggers, but multi-eval is a bit easier to work with in this case and may give me a few more options) (Mantis 3079 (http://scp.indiegames.us/mantis/view.php?id=3079))
--Multiplayer clients crash when subtitle string larger than 32 characters is triggered (Mantis 3077 (http://scp.indiegames.us/mantis/view.php?id=3077))
--Bitmaps loaded with gr.loadTexture() are never released (Mantis 3084 (http://scp.indiegames.us/mantis/view.php?id=3084))

But this is all part of the process :) All of these have associated Mantis tickets open, and I know they'll be subjected to the appropriate code review for integration when it comes time to add more features, so it's all good. Let's see if I can find any more bugs with this project!
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: m!m on August 05, 2014, 11:44:29 am
Can you upload your patch for Mantis 3084?

I'll see what I can do about 3079, the patch was reviewed before and if karajorma is fine with adding it with a warning I'll commit it ASAP.

EDIT: 3079 and 3084 are now fixed in trunk.
Title: Re: Animated texture / ANIs not working with gr.DrawImage ?
Post by: Parias on August 05, 2014, 11:52:17 am
Sure, my pleasure.  .patch has been submitted. And thanks for taking a look at 3079!

Any idea on when 3077 will get a closer look as well? It sounds like this would lie in karajorma's camp and I don't know if the change I made is at all the proper way of resolving this, but so long as that problem exists, I'm stuck with a much more arduous way of presenting briefing text (being limited to ~31 characters per-message is a huge pain).