James Paige wrote:
On Thu, Oct 02, 2008 at 12:58:22PM -0400, Mike Caron wrote:
James Paige wrote:
On Thu, Oct 02, 2008 at 12:37:04PM -0400, Mike Caron wrote:
James Paige wrote:
On Thu, Oct 02, 2008 at 12:04:47PM -0400, Mike Caron wrote:
James Paige wrote:
So I am going to start work on the rectangle interface...

SUDDEN VOCABULARY CHANGE!

Actually, I think I will start using the term "slice" as S'orlok coined for the FMF. I am not sure that my plan is exactly analogous to his slices, but I think it is pretty darn close, and it is less ambigious than "rectangle interfaces"

So anyway, I need to maintain a tree of slices. FreeBasic is sadly missing a good data type for trees. Now I could hack together a tree of pointers, but you know how that makes me weep. Besides, I really want to make FreeBasic do my memory allocation with REDIM I don't want to do it myself.

So I am thinking I will have a one dimentional array of slices. Each slice will have a property which indicates its parent, and a property which indicates how many children it has. This is a little bit like how the menu items are stored, with the difference that this will be a depeer tree than just one level.

So I will sort this tree when elements are inserted or deleted. That does mean a lot of work-- but really this sorting will have to happen at some point no matter what, since we have to get z-order correct for drawing. So I think it is better to sort the tree when slices are added, removed, or moved, which will happen far less often than the drawing cycle.

So the first element in this array will always be the root slice. It will have (by default) five child slices, map slice, scriptsprite slice, textbox slice, menu slice, scriptstring slice in that order.

The camera code would be updated to move the x,y position of the map slice relative to the root slice

The map slice will have six child slices, the map layer 0 slice, map layer 1 slice, npc&hero slice, map layer 2 slice, overhead backcompat slice, and the harm tile flash slice.

The map layer slices will have a "type" property which indicates that they draw map tile layers

The npc&hero slice will have two child slices, the npc slice and the hero slice, and their order will depend on the general map bitset that controls hero-vs-npc layering.

To begin with, these slices can simply be of a type that instructs the slice drawing code to draw all the NPCs or heroes using pretty much exactly the same NPC and hero drawing code that exists now.

In the future, these npc and hero slices could be changed to have child slices which would be generic sprite slices representing each NPC and hero. For example, The npc layer will have 300 child slices, one for each NPC reference. These slices will replace the .x and .y members of the current array of NPCInst, and all the current code to move NPCs would just reference these slices instead (to do this efficiently, the slice tree sorting code would have to notice and save the index of the NPC slice, so the child NPC sprite slices could be found quickly without needing a search each time)

Anyway, everything that has an x/y position would be moved into the slice tree. Drawing of all layers would be unified, and easy to extend and manipulate. We could have generic plotscripting functions that re-order or re-parent slices. Existing commands, like the ones to move plot strings, or the ones to move custom menus, or the ones mike just implemented for scriptsprites would all remain the same to plotscripters, but internally their implementations would be moving slices relative to their natural parents.

The slice tree sorter would update a table of indexes into the slice array that mark various important standard slices, so that other code can find these slices quickly without having to search the slice tree.

Comments?
This seems like a pretty good plan. However, there is one thing that I need to ask:

Let's say I add sprite A, and get a handle to it. Since I put it on the hero and NPC slice, it's somewhere in the middle of the pile. Now, let's say I add another sprite, sprite B, which is on Layer 0. The resort then puts sprite B before sprite A, and since numbers have the irritating property of being consecutive, sprite A is no longer at the same ordinal as it was before, giving it a new handle, and rendering my old handle invalid.

Or, am I missing something?
No, that is a very valid point. The sorted-tree-in-a-linear-array approach has the disadvantage that you have to have a sceme to update your handles. That table of magical slices that gets updated when the tree storage re-sorts is basically a table of handles, they just happen to be handles used by the engine internally rather than handles used by plotscripts.

However, I think that problem can be solved by indirecting plotscript slice handles through a similar table which will also be updated at sort time.

If all this slice handle updating sounds daunting, fear not. There will be good ways to optimize the sort. For example, when a slice moves, only the parent slice needs to be re-sorted, which will be pretty easy to do since the tree is always sorted already. And after a sub-tree has changed size through the addition or deletion of a child, the rest of the handles can be updated by +1 or -1 to anything > the end of the slice that just got sorted.

But honestly, this is all complicated. Would it be more complicated than a tree built from *shiver* pointers?

I'm not sure. I guess I need to give some more thought to a pointer tree, so I can fairly compare the two options.
Well, the main point against pointers is that you want to avoid passing pointers to plotscripts, since that's just inviting trouble. However, a way around it would be to store the pointers in a table, and pass the index, much like existing solutions (the plotsprites, for example, are a good example)

One large problem we have to keep in mind, though, is that we'll be going both up and down the tree: Drawing will be bottom up, while manipulation is top down. So, for maximum efficiency, we should keep references to both parents and (I can hear the gasp coming...) children.

To do so is complex, yes, but it would make everything so much easier, and not require sorting. How I would do it is like this:

Type Slice
 Parent as Slice Ptr
 Children as Slice Ptr Ptr
 NumChildren as Integer
 'whatever else
End Type

So, by default, .Children is null, indicating that there's no children. .Parent works as expected, pointing at the parent. For the root node, this will be null.

When we need to add a child to a slice, we do something like this:

Function AddChildSlice(parent as Slice ptr) as slice ptr
 'check parent for null and validity
 dim found as integer
 for i as integer = 0 to parent->NumChildren - 1
   if parent->Children[i] = 0 then
     found = YES
     exit for
   end if
 next

 if not found then
   GrowChildren(parent) 'add error checking here, in case of mem error
 end if

 dim child as Slice ptr = new Slice
 parent->Children[i] = child
 child->Parent = parent
 'whatever else we need to do

 return child
end function

The GrowChildren function, as it says on the tin, grows the number of children a slice can have.

So, to draw this tree, we recurse from the root node, and follow children. To move a slice, we remove the child from the parent, change the parent to a new parent, and add the child to the new parent. Easier done than said, really.
Wow. that above code makes me shiver.

Granted it will be bad either way, and no matter what implementation we choose, we will need to work hard to wrap the uglyness into functions so that some bright day when FreeBasic implements a real tree-suitable container datatype like other languages have we will be able to easily retrofit this mess to use the new simpler data type.

Type Slice
 Parent as Slice Ptr
 Children as Slice Ptr Ptr
 NumChildren as Integer
 'whatever else
End Type
About this part. Wouldn't it be easier to do:

Type Slice
 Parent as Slice Ptr
 FirstChild as Slice Ptr
 NextSibling as Slice Ptr
 PrevSibling as Slice Ptr
 NumChildren as Integer
 'whatever else
End Type

I think that would eliminate the need for GrowChildren()
That would work too, at the expense of slightly more complex code. Actually, in this case, you likely wouldn't need NumChildren any more, since to append a new child, you navigate to the first child, and then navigate to the end of the linked list. Or, hell, append it in the front for all it matters.

keeping NumChildren could just be an optimization so that if you wanted to know the count, the work could be done at add/remove time rather than at request-time

I was thinking about that... But, truthfully, 95% of the time I would want to know how many children there are, I simply want to enumerate over them anyway. But, I suppose it doesn't hurt.

It occurs to me that we're duplicating work ;) http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core

infinity cool-points for the first person to re-implement the OHRRPGCE in javascript.

infinity+1 cool-points for the first person to implement a W3C compliant web browser in HamsterSpeak

Let me check in my Networking module for HamsterSpeak then!

... Actually, that would be kickass, if a bit impractical.
_______________________________________________
Ohrrpgce mailing list
ohrrpgce@lists.motherhamster.org
http://lists.motherhamster.org/listinfo.cgi/ohrrpgce-motherhamster.org

Reply via email to