ID:2962148
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
It'd be super nice if vis_contents could be indexed with string keys.

How I picture this working, is all atoms that can be in the vis-locs of another object would have a property called "vis_tag". This property can be set to a string EXCLUDING the character ".".

When indexing vis_contents via a string, it would break the supplied string by "."s and perform an upward search through the vis_contents:

for each tag node:
* find the first element in vis_contents with a matching vis_tag. If not found, return null.
* if there are remaining nodes, deepen the search to the found element's vis_contents
* repeat until we have reached a dead end (returning null), or we have exhausted the tag nodes.

I currently do this in uilib:

        //allows accessing nested hud components by path string EG "child" or "child.variable" or "child_hud.grandchild.variable"
operator[](idx)
var/path = idx
var/list/nodes = splittext(path,".")
var/list/registry = vis_registry
var/hud/component/child, hud/hud, len = nodes.len
for(idx in 1 to len)
child = registry[nodes[idx]]
if(child)
if(istype(child,/hud))
hud = child
registry = hud.vis_registry
else
registry = child.vars
else if(idx < len)
throw EXCEPTION("Invalid HUD element: [path]")

return child

//allows assigning nested hud elements by path string, and modifying variables of children.
operator[]=(idx,B)
var/path = idx
var/list/nodes = splittext(path,".")
var/list/registry = vis_registry, id, len = nodes.len - 1
var/hud/component/child, hud/hud
var/is_registry = 1

for(idx in 1 to len)
id = nodes[idx]
child = registry[id]
if(child)
if(istype(child,/hud))
hud = child
registry = hud.vis_registry
is_registry = 1
else
registry = child.vars
is_registry = 0
else if(idx < len)
throw EXCEPTION("Invalid HUD element: [path]")

id = nodes[len+1]
if(is_registry)
if(istype(B,/obj))
B:vis_id = id
hud += B
else
throw EXCEPTION("Invalid type for vis_registry: [B]")
else
registry[id] = B



The reason I do this is so I can construct complex, multi-object HUD elements extremely efficiently, without needing to define a whole boatload of boilerplate structure.

When I create a widget, I just fork New():

New()
..()
src.menu_item = src["menu"]
src.stat_page = src["stats"]


It really cuts down on the labor of boilerplate initializations, when you can just newlist() vis_contents to add what you need to the element at declaration.


For such an approach "downward" searching isn't necessary. Because vis_contents can be in multiple vis_locs, figuring out downward traversal really needs to be left up to the user, so doing things like "parent.herp.derp" is really unnecessary and overcomplicated for this approach.