ID:2949140
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
One common task in creating UIs is laying out on-screen elements in an evenly spaced grid.

It would be really cool if we could enhance the power of vis_contents without having to constantly churn appearances. The client already knows how to lay out turfs in a grid when they are in vis_contents, but it doesn't know how to do anything with arbitrary objects.

The problem is always syntax, though.

I'm suggesting the addition of an atom property that is similar to filters, in that you send the client an arbitrary data structure that gives rules for rendering. Instead of post-processing effects, this one applies to the entire vis_contents list of an atom.

vis_layout would come packaged with the following layouts:

Grid layout

Parameters:
x,y - starting point to draw the 1st element in vis_contents from the bottom-left of the atom

skip - how many items to skip before starting the grid; Items skipped will not be drawn at all.

cols - how many items go on one row before moving to the next row.

width,height - the size of each cell. Each element will be drawn at the bottom-left of its corner, however, each atom's pixel offsets and transform will still apply.

Screen layout

Parameters:
x,y - the position to draw the screen relative to the bottom-left corner of the atom.
width,height - the width of the screen. Anything outside of these coordinates will be cropped.
icon_size - the "tile" size to use for this screen layout. See notes below.
background - null would be transparent, but a color or an icon could be supplied to use as a background image. The background image would be repeated every tile_width/height pixels.

This particular layout would hijack the fact that screen_locs don't mean anything in vis_contents. vis_contents with screen_locs inside of a screen layout would be able to treat the parent atom as though it were an in-screen map element. Much like a screen object, pixel offsets would not contribute to the final position, but transforms would.

This layout would cause the vis children to be drawn to an off-screen surface first, and then over the appearance of the parent object.


Flexible rows layout
x,y - the position to draw this layout relative to the parent
width,height - the width and height of the layout. Elements beginning outside of the layout would simply not render.
row_padding, col_padding - extra width and height added to the flow position of the cursor.
flow=EAST|WEST - What direction rows should flow in.
order=FORWARD|REVERSE - Whether to begin from the back or front of the vis children
align = NORTH|CENTER|SOUTH

Flexible column layout
flow = NORTH|SOUTH
align = EAST|CENTER|WEST

This is like the flexible rows layout, but instead of operating in rows, it operates in columns.


The flexible layouts would use the visual bounds of the child appearance to flow controls left to right, or top-to-bottom. Elements would still use their pixel offsets and transforms to affect their final visual position.



like filters, some layout variables should be animatable. Notably:

x,y
width,height
row_padding,col_padding


Finally, a few new vis_flags would make sense:

VIS_IGNORE_LAYOUT - vis children that ignore layouts won't even be considered in the counts of layouts. This will allow you to nest children inside of a layout that aren't actually part of it in order to achieve visual effects.

VIS_SCREEN_LAYOUT - vis children that have this flag will be treated as though they are screen objects, with the area of the layout being treated as though it were a screen. pixel offsets would be ignored for vis children with this flag set. For grid layouts, the tile-size of the screen is considered to be the width,height of the layout. This has no effect with vis screen layouts. For flexible rows/columns, the tile position would be relative to the position of the Xth element on the Yth row.
use cases:

inventory grid:

/inventory_grid
parent_type = /obj
vis_layout = vis_layout(type="grid",x=0,y=288,width=32,height=32,cols=8,rows=10)
operator+=(B)
if(B.loc)
if(B.loc==src) return
B.loc -= B
vis_contents += B
B.loc = src
return B

operator-=(B)
vis_contents -= B
B.loc = src

mob
var
inventory/inventory = new()
proc
GetItem(item)
inventory += item
Dropitem(item)
inventory -= item

Login to reply.