-
Notifications
You must be signed in to change notification settings - Fork 4
Complex UI (part 2)
Prev: Complex UI (part 1)
After part one we have nice looking item slots, but do you remember about not repeat yourself? What are you thinking about five lines of <ItemSlot />
? I found it not great and think we're ready to use <Loop />
tag to itterate collection of items.
To show any amount of item slots with some data let's make another custom component <ItemShelf />
where magic will live. Starts from skeleton of component:
<?xml version="1.0" encoding="utf-8" ?>
<Root Name="Shelf">
<OnProps>
-- state setup code here
</OnProps>
<Loop Component="ItemSlot">
<Collection>
-- return collection of data to itterate
return {}
</Collection>
<Itteration>
-- invokes for each item in collection
return {}
</Itteration>
</Loop>
</Root>
Here is few unknown tags: <Loop />
, <Collection />
and <Itteration />
. Let's look at them:
-
Loop says to ReUI about starts itteration section of element passed by
Component
attribute (ItemSlot
in our case) - Collection says to ReUI about take from it lua code to obtain proper collection of data (we will set up it later)
- Itteration is a function what will be invoked with two arguments: item (instance of current ItemSlot) and index (id key of collection). It will invoke N-times equal length of collection.
Imagine we're already passed as a props to ItemShelf
some data and ready to set up state:
<Root Name="Shelf">
<OnProps>
-- set items collection to state
state.items = props.items or {}
</OnProps>
<Loop Component="ItemSlot">
<Collection>
return state.items
</Collection>
<Itteration>
item:setAnchor('TopCenter')
item:setPivot('TopRight')
item:setPosition(0, -48 * (index - 1))
item:setSize(42, 42)
return state.items[index]
</Itteration>
</Loop>
</Root>
It's not ready, but it should work. Here is huge room of imrovements, but we will test it right now. Go to InGame.xml
and call it with some collection:
<?xml version="1.0" encoding="utf-8" ?>
<Root Name="In Game UI">
<ItemShelf Anchor="TopRight"
Position="-9,-53"
Name="Armory Shelf">
return {
items = {
{
name = "Plate helm",
icon = "icons/upg_helmet",
properties = {
{ key = 'Exceptional', color = '#FFFF00' }
}
},
{ }, -- no pauldron item
{
name = "Plate chest",
icon = "icons/armor",
properties = {
{ key = 'Block Chance', value = '10%' }
}
},
{ }, -- no legs item
{ } -- no boots item
}
}
</ItemShelf>
</Root>
Yay! It's work as expected. But what about reusability? How about more that one col or row? This is improvments what I told about.
As a topic says.. I will just write simple grid code and show result. Anyway if you're not familiar with Lua and want to use ReUI, you should spend 15 minutes to understand Lua: Take a quick course made by Tyler Neylon.
<?xml version="1.0" encoding="utf-8" ?>
<Root Name="Shelf">
<OnProps>
-- set items collection to state
state.items = props.items or {}
state.cols = props.cols or 5
state.rows = props.rows or 5
state.size = tonumber(props.size) or 42
state.offset = tonumber(props.offset) or 6
state.pivot = props.pivot or 'MiddleCenter'
state.anchor = props.anchor or 'TopLeft'
</OnProps>
<Loop Component="ItemSlot">
<Collection>
-- ugly range function... :D
local max = state.rows * state.cols
log(max)
local collection = {}
for i = 1, max, 1 do
collection[i] = i
end
return collection
</Collection>
<Itteration>
local s = state.size
local o = state.offset
local c = state.cols
local r = state.rows
-- substract one because lua index start from 1 (have no idea why..)
local i = index - 1
local ir = math.floor(i / c)
local ic = i - (ir * c)
local is = s + o
local x = is * ic
local y = is * -ir
item:setAnchor(state.anchor)
item:setPivot(state.pivot)
item:setPosition(x, y)
item:setSize(s, s)
return state.items[index] or {}
</Itteration>
</Loop>
</Root>
Example of usage and final result
<ItemShelf Anchor="TopLeft"
Position="9,-53"
Name="Bag Shelf">
return {
cols = 3,
rows = 2,
size = 42,
offset = 6,
pivot = 'TopLeft';
items = {
-- items collection
}
}
</ItemShelf>