PDA

View Full Version : Detecting and deleting empty windowlists



phantomwhale
September 12th, 2011, 12:44
Have hit a bit of a wall today with windowlists containing windowlists.

More specific, I have a windowlist which contains window instances with a couple of string fields, and another windowlist. When the inner windowlist is empty, I want to delete the whole window instance.

The only way I know how to delete windowlist elements is to delete the database node which represents them. This is how I delete elements of the inner list (on the class itself, I call getDatabaseNode().delete()).

But when I do this on one of the instances within the outer list, FGII hangs and crashes; presumably as I am deleting a whole window class whilst code is still executing.

So I looked to catch a "when the list is empty" event in the outer windowlist, but there are no "on list size change" events I can really catch.

In the end I've opted to "close" the outer windowlist instances, and when I close the overall windowlist, I quickly parse through the underlying database nodes, and delete any instances which have empty lists, otherwise the "empty" lists reappear again when I reopen the main windowlist.

Hope that all made some sense - is there a clever trick here ? Would post code samples, but it's a LOT of code making up this stuff, and it's late, so instead I'm going to apologise for the wooly question and burn a bit of good karma looking for a patient respondee ;)

drahkar
September 12th, 2011, 14:03
I handled this by nesting the DBNodes for the windowlist that is in the windowlist under the outer Windowlist's nodes within the DB Structure. Course this assumes that the sub-windowlist exists for each Primary one specifically. That way when you delete the highest level node, it removes all of them below as well.

Moon Wizard
September 12th, 2011, 19:59
Given that this is exactly how the CT works for 3.5E and 4E, with nested windowlists for effects, attacks, targeting, etc. There should not be any issues with nested windowlists in general.

However, I know that I have found that deleting objects during certain event handlers can cause crashes.

* Which object and event handler are you using to trigger the delete?

Cheers,
JPG

phantomwhale
September 13th, 2011, 00:04
I tried onClose and onListRearranged from the window element itself and the inner windowlist respectively,

Moon Wizard
September 25th, 2011, 00:33
I finally got a chance to think through this one.

onClose is definitely off limits. After the onClose call, the FG code calls the code to finish the deletion of the window and it's controls. Since you would have already deleted through a function call, you get an FG crash. There's no easy way for me to detect this, so the best I could do would be to block window close and database deletion during onClose events which doesn't help you.

onListRearranged seems even more problematic for close/deletion during the event, since it is triggered so often.

Have you thought about adding an onChildUpdate handler to the list database node, then checking the number of children and deleting?

Regards,
JPG

phantomwhale
November 10th, 2012, 03:21
Arghh... it's back ! (in the latest Test version of 2.9.2, that is)

I had this problem fixed for SWEX v3.2, and now it seems to be back with the latest version of FGII.

The code causing this is when I delete a combatant in the combat tracker (when there are no grouped enemies). At this point, FGII crashes :(

Under the hood, the combat tracker is a windowlist of "combatant_groups" where each combatant_group has a few settings and it's own list of "combatants". When a combatant is deleted, it triggers the onChildUpdate() handler for the combatants windowlist. This handler calls onCombatantUpdate() (called onActorUpdate() in v3.3) on the combatant_group object, which looks as follows:



function onActorUpdate()
if actors.getDatabaseNode().getChildCount() == 0 then
getDatabaseNode().delete()
end
end


So this used to delete the database node underpinning the combatant_group windowclass, ensuring it was deleted when the last combatant of that group is deleted.

It seems that this approach no longer works and is causing some deadlock with FGII does not recover from.

Any ideas how I might go about doing this now ?

Have tried moving the handler, or just calling close() - which is no good, as I need to have that entry in the windowlist deleted. It's almost like I need an "afterDelete" handler that is well clear of any locks ? Without knowing the details under the hood, it's very hard to guess.

Cheers,
Ben

Moon Wizard
November 10th, 2012, 09:24
Let me take a look at what might have changed. The node deletion code has always been convoluted.

Here's my workaround when I want to delete a child:
* Call a windowlist script function with the databasenode to delete
* Remember the parent node
* Delete the target node
* Check the parent child count
* Then act
See the deleteEffect function in the manager_effect.lua script in the 3.5E/4E rulesets.

Regards,
JPG

Moon Wizard
November 10th, 2012, 18:52
I think I tracked it down. It's an interaction with the new DB.addHandler/removeHandler code. If you delete the node in the onChildUpdate call, then it crashes when the new update handlers are checked because the node no longer exists.

The code was always a bit convoluted around the script calls from the original developers, and it never handled node deletion within the script files well. I'm going to restructure all the internal database script calls to use the path to check for node existence before script calls, instead of passing node pointers like it has done so far. I'm going to do this for v2.9.2, and push a new update in the next day or two.

Regards,
JPG

Moon Wizard
November 10th, 2012, 19:59
Updated in v2.9.2 beta.
JPG

phantomwhale
November 11th, 2012, 02:30
Ha - I only got your first update via email and then set about trying to recreate it... and couldn't ! It was only as I came to the forums to say "everything seems OK now ?!?!" that I saw your follow on posts.

Awesome work JPG - saved me a day of potentially ugly workarounds and patches :)