Refining the "Arcane" Tab (Savage): Difference between revisions
New page: {{context|Authoring Examples|Savage Worlds Walk-Through}} ===Overview=== The "Arcane" tab is currently very minimalist in nature. None of the special fields of powers are shown for selec... |
|||
(5 intermediate revisions by the same user not shown) | |||
Line 17: | Line 17: | ||
showtemplate="apPower" | showtemplate="apPower" | ||
choosetemplate="SimpleItem" | choosetemplate="SimpleItem" | ||
addpick="resPowers" | |||
descwidth="350"> | descwidth="350"> | ||
<titlebar><![CDATA[ | <titlebar><![CDATA[ | ||
@text = "Add an Arcane Power - " & hero.child[resPowers].field[resSummary].text | @text = "Add an Arcane Power - " & hero.child[resPowers].field[resSummary].text | ||
]]></titlebar> | ]]></titlebar> | ||
<description | <description/> | ||
<headertitle><![CDATA[ | <headertitle><![CDATA[ | ||
@text = "Arcane Powers - " & hero.child[resPowers].field[resSummary].text | @text = "Arcane Powers - " & hero.child[resPowers].field[resSummary].text | ||
Line 50: | Line 45: | ||
marginhorz="3" | marginhorz="3" | ||
marginvert="2"> | marginvert="2"> | ||
<portal | <portal | ||
id="name" | id="name" | ||
Line 58: | Line 54: | ||
</label> | </label> | ||
</portal> | </portal> | ||
<portal | <portal | ||
id="info" | id="info" | ||
Line 64: | Line 61: | ||
action="info"> | action="info"> | ||
</action> | </action> | ||
<mouseinfo mousepos="middle+above" | <mouseinfo mousepos="middle+above"/> | ||
</portal> | </portal> | ||
<portal | <portal | ||
id="delete" | id="delete" | ||
Line 78: | Line 72: | ||
</action> | </action> | ||
</portal> | </portal> | ||
<position><![CDATA[ | <position><![CDATA[ | ||
~set up our height based on our tallest portal | ~set up our height based on our tallest portal | ||
height = portal[info].height | height = portal[info].height | ||
~if this is a "sizing" calculation, we're done | ~if this is a "sizing" calculation, we're done | ||
if (issizing <> 0) then | if (issizing <> 0) then | ||
done | done | ||
endif | endif | ||
~position our tallest portal at the top | ~position our tallest portal at the top | ||
portal[info].top = 0 | portal[info].top = 0 | ||
~position the other portals vertically | ~position the other portals vertically | ||
perform portal[name].centervert | perform portal[name].centervert | ||
perform portal[delete].centervert | perform portal[delete].centervert | ||
~position the delete portal on the far right | ~position the delete portal on the far right | ||
perform portal[delete].alignedge[right,0] | perform portal[delete].alignedge[right,0] | ||
~position the info portal to the left of the delete button | ~position the info portal to the left of the delete button | ||
perform portal[info].alignrel[rtol,delete,-8] | perform portal[info].alignrel[rtol,delete,-8] | ||
~position the name on the left and use all availble space | ~position the name on the left and use all availble space | ||
portal[name].left = 0 | portal[name].left = 0 | ||
Line 111: | Line 112: | ||
<labeltext><![CDATA[ | <labeltext><![CDATA[ | ||
@text = "{/b}Points:{b} " & field[powPoints].text | @text = "{/b}Points:{b} " & field[powPoints].text | ||
@text &= " | @text &= "{br}{/b}Range:{b} " & field[powRange].text | ||
@text &= " | @text &= "{br}{/b}Duration:{b} " & field[powLength].text | ||
if (field[powMaint].isempty = 0) then | if (field[powMaint].isempty = 0) then | ||
@text &= " (" & field[powMaint].text & ")" | @text &= " (" & field[powMaint].text & ")" | ||
Line 121: | Line 122: | ||
</pre> | </pre> | ||
Note that we could have strung all of the fields together on a single line, but then we wouldn't always have room for them all. So we instead string them together with a newline ( | Note that we could have strung all of the fields together on a single line, but then we wouldn't always have room for them all. So we instead string them together with a newline ("{br}") between each, which makes sure that everything is visible. Since this is a multi-line label, we need to make sure to designate it as such so that HL handles it properly for auto-sizing purposes. | ||
Before we revise the template Position script to re-position the portals properly, let's also address the ability for users to specify the trappings for each power. The description of the trappings for a power may be somewhat lengthy, so our first inclination is to use a wide edit portal for the purpose, or perhaps even a multi-line edit portal. However, trappings are not something that the user will likely want to see all the time, so dedicating a large area of screen real estate to trappings is probably not a good idea. A better approach is to do something similar to the way details are handled for Journal entries: an "edit" button allows the user to edit the contents via a dedicated form. | Before we revise the template Position script to re-position the portals properly, let's also address the ability for users to specify the trappings for each power. The description of the trappings for a power may be somewhat lengthy, so our first inclination is to use a wide edit portal for the purpose, or perhaps even a multi-line edit portal. However, trappings are not something that the user will likely want to see all the time, so dedicating a large area of screen real estate to trappings is probably not a good idea. A better approach is to do something similar to the way details are handled for Journal entries: an "edit" button allows the user to edit the contents via a dedicated form. | ||
Line 134: | Line 135: | ||
<action | <action | ||
action="notes" | action="notes" | ||
field="powTraps | field="powTraps"> | ||
</action> | </action> | ||
</portal> | </portal> | ||
Line 148: | Line 148: | ||
~Consequently, we can't use "textheight" here and must use "fontheight" instead. | ~Consequently, we can't use "textheight" here and must use "fontheight" instead. | ||
height = portal[details].fontheight * 3 | height = portal[details].fontheight * 3 | ||
~if this is a "sizing" calculation, we're done | ~if this is a "sizing" calculation, we're done | ||
if (issizing <> 0) then | if (issizing <> 0) then | ||
done | done | ||
endif | endif | ||
~position our tallest portal at the top | ~position our tallest portal at the top | ||
portal[details].top = 0 | portal[details].top = 0 | ||
~center the name vertically | ~center the name vertically | ||
perform portal[name].centervert | perform portal[name].centervert | ||
~center the info and delete portals within the upper half of the template | ~center the info and delete portals within the upper half of the template | ||
var half as number | var half as number | ||
Line 161: | Line 165: | ||
portal[info].top = (half - portal[info].height) / 2 | portal[info].top = (half - portal[info].height) / 2 | ||
portal[delete].top = (half - portal[delete].height) / 2 | portal[delete].top = (half - portal[delete].height) / 2 | ||
~center the trappings portal within the lower half of the template | ~center the trappings portal within the lower half of the template | ||
~Note: The info portal is big, so shift it down a little extra for better spacing. | ~Note: The info portal is big, so shift it down a little extra for better spacing. | ||
portal[trappings].top = half + (half - portal[trappings].height) / 2 + 1 | portal[trappings].top = half + (half - portal[trappings].height) / 2 + 1 | ||
~position the delete portal on the far right | ~position the delete portal on the far right | ||
perform portal[delete].alignedge[right,0] | perform portal[delete].alignedge[right,0] | ||
~position the info portal to the left of the delete button | ~position the info portal to the left of the delete button | ||
perform portal[info].alignrel[rtol,delete,-6] | perform portal[info].alignrel[rtol,delete,-6] | ||
~center the trappings portal between the info and delete buttons | ~center the trappings portal between the info and delete buttons | ||
var span as number | var span as number | ||
span = portal[delete].right - portal[info].left | span = portal[delete].right - portal[info].left | ||
portal[trappings].left = portal[info].left + (span - portal[trappings].width) / 2 | portal[trappings].left = portal[info].left + (span - portal[trappings].width) / 2 | ||
~position the name on the left and use a suitable amount of space | ~position the name on the left and use a suitable amount of space | ||
portal[name].left = 0 | portal[name].left = 0 | ||
portal[name].width = 200 | portal[name].width = 200 | ||
~position the details next to the name and use the remaining space | ~position the details next to the name and use the remaining space | ||
perform portal[details].alignrel[ltor,name,10] | perform portal[details].alignrel[ltor,name,10] | ||
Line 197: | Line 207: | ||
Once the style is defined, switch back to the template for arcane powers and locate the "name" portal. Change the style to the new one we just defined ("lblLrgLeft"). When you reload the data files, arcane powers should now have their name left-aligned properly. | Once the style is defined, switch back to the template for arcane powers and locate the "name" portal. Change the style to the new one we just defined ("lblLrgLeft"). When you reload the data files, arcane powers should now have their name left-aligned properly. | ||
Now we need a left-aligned solution for the currently centered "details" portal. Looking at the pre-defined styles in the file "styles_ui.aug" again, | Now we need a left-aligned solution for the currently centered "details" portal. Looking at the pre-defined styles in the file "styles_ui.aug" again, the "lblSmlLeft" style uses the "Small" font and is left-aligned. That's exactly what we need, so we'll make use of it within the appropriate portal. Locate the "details" portal and change the style to "lblSmlLeft". After a re-load, the details text should be properly left-aligned. | ||
The last refinement we need to do for the template is to make sure our tab order is appropriate. The tab order of portals within a template is always the order in which the portals are actually defined in the template. As such, the portals should be sequenced so that the flow seems natural to the user. For example, the following sequence seems reasonable: "name", "details", "info", "delete", and "trappings". Revise the sequence as you deem fit and the template is now good to go. | |||
The last refinement we need to do for the template is to make sure our tab order is appropriate. The tab order of portals within a template is always the order in which the portals are actually defined in the template. As such, the portals should be sequenced so that the flow seems natural to the user. For example, the following sequence seems reasonable: "name", "details", "info", "delete", and "trappings". Revise the sequence as you deem fit and the template is now good to go. | |||
===Summary Information=== | ===Summary Information=== | ||
Line 223: | Line 220: | ||
name="Arcane Header" | name="Arcane Header" | ||
compset="Actor"> | compset="Actor"> | ||
<portal | <portal | ||
id="info" | id="info" | ||
Line 230: | Line 228: | ||
~use a color that's is slightly less bright that the normal text for powers | ~use a color that's is slightly less bright that the normal text for powers | ||
@text = "{text c0c0c0}Total Powers: " & #resmax[resPowers] | @text = "{text c0c0c0}Total Powers: " & #resmax[resPowers] | ||
~insert a horizontal gap between the two values to space them nicely | ~insert a horizontal gap between the two values to space them nicely | ||
@text &= "{horz 40} Total Power Points: " & #trkmax[trkPower] | @text &= "{horz 40} Total Power Points: " & #trkmax[trkPower] | ||
Line 235: | Line 234: | ||
</label> | </label> | ||
</portal> | </portal> | ||
<position><![CDATA[ | <position><![CDATA[ | ||
~set up our height based on the tallest portal | ~set up our height based on the tallest portal | ||
height = portal[info].height | height = portal[info].height | ||
~our portal should be centered in the template | ~our portal should be centered in the template | ||
perform portal[info].centerhorz | perform portal[info].centerhorz | ||
Line 253: | Line 254: | ||
<templateref template="apHeader" thing="actor"/> | <templateref template="apHeader" thing="actor"/> | ||
<position><![CDATA[ | <position><![CDATA[ | ||
~size the template and table to span the full layout | ~position and size the template and table to span the full layout | ||
template[apHeader]. | perform template[apHeader].autoplace | ||
perform portal[apPowers].autoplace[8] | |||
perform | |||
]]></position> | ]]></position> | ||
</layout> | </layout> | ||
</pre> | </pre> |
Latest revision as of 22:37, 19 February 2009
Context: HL Kit … Authoring Examples … Savage Worlds Walk-Through
Overview
The "Arcane" tab is currently very minimalist in nature. None of the special fields of powers are shown for selected powers. We also don't show any summary information about the arcane background on the tab, and we really should be doing that. It's time for us to open the file "tab_arcane.dat" and start refining it.
Selecting Arcane Powers
The selection of arcane powers is working properly, but the display has one aspect that we should address. Arcane powers typically have lots of description text associated with them. Consequently, the relatively narrow space that is provided by default when selecting powers should be widened. This can be easily achieved by adding a new attribute to the table portal, within the "table_dynamic" element. The new attribute is "descwidth" and controls the pixel width to be used when allowing the user to select items for the table. We'll choose a width of "350" to make the paragraphs of description text easier to read.
<portal id="apPowers" style="tblNormal"> <table_dynamic component="Power" showtemplate="apPower" choosetemplate="SimpleItem" addpick="resPowers" descwidth="350"> <titlebar><![CDATA[ @text = "Add an Arcane Power - " & hero.child[resPowers].field[resSummary].text ]]></titlebar> <description/> <headertitle><![CDATA[ @text = "Arcane Powers - " & hero.child[resPowers].field[resSummary].text ]]></headertitle> <additem><![CDATA[ ~get the color-highlighted "add" text @text = field[resAddItem].text ]]></additem> </table_dynamic> </portal>
Showing Arcane Powers
Once an arcane power is added to the character, all the user sees is its name. It would be quite helpful to also see the power point cost, range, and duration for the power. In addition, we need to allow the user to specify the actual trappings for the power. None of this can be accomplished with the "SimpleItem" template that we're currently using, so we need to switch that out for a custom template. We need to start with a template that is extremely simple and that we can readily adapt. The "SimpleItem" template is an excellent candidate, but the template for edges is even simpler, so we copy that template from the file "tab_edges.dat". After the copy, all we need to change is the unique id, name, and component set. This gives us something simple to start with like the example below.
<template id="apPower" name="Power Pick" compset="Power" marginhorz="3" marginvert="2"> <portal id="name" style="lblNormal" showinvalid="yes"> <label field="name"> </label> </portal> <portal id="info" style="actInfo"> <action action="info"> </action> <mouseinfo mousepos="middle+above"/> </portal> <portal id="delete" style="actDelete" tiptext="Click to delete this item"> <action action="delete"> </action> </portal> <position><![CDATA[ ~set up our height based on our tallest portal height = portal[info].height ~if this is a "sizing" calculation, we're done if (issizing <> 0) then done endif ~position our tallest portal at the top portal[info].top = 0 ~position the other portals vertically perform portal[name].centervert perform portal[delete].centervert ~position the delete portal on the far right perform portal[delete].alignedge[right,0] ~position the info portal to the left of the delete button perform portal[info].alignrel[rtol,delete,-8] ~position the name on the left and use all availble space portal[name].left = 0 portal[name].width = minimum(portal[name].width,portal[info].left - portal[name].left - 10) ]]></position> </template>
When we add the various fields for arcane powers to what is shown, we can either use separate portals for each field or we can combine them all into a single portal. In the case of arcane powers, we don't need to do anything fancy when presenting the information. Consequently, we simply define a single label portal that is driven by a script. The script will combine the different fields into a useful string of text for display. An example of what such a portal might look like is shown below.
<portal id="details" style="lblSmall"> <label multiline="yes"> <labeltext><![CDATA[ @text = "{/b}Points:{b} " & field[powPoints].text @text &= "{br}{/b}Range:{b} " & field[powRange].text @text &= "{br}{/b}Duration:{b} " & field[powLength].text if (field[powMaint].isempty = 0) then @text &= " (" & field[powMaint].text & ")" endif ]]></labeltext> </label> </portal>
Note that we could have strung all of the fields together on a single line, but then we wouldn't always have room for them all. So we instead string them together with a newline ("{br}") between each, which makes sure that everything is visible. Since this is a multi-line label, we need to make sure to designate it as such so that HL handles it properly for auto-sizing purposes.
Before we revise the template Position script to re-position the portals properly, let's also address the ability for users to specify the trappings for each power. The description of the trappings for a power may be somewhat lengthy, so our first inclination is to use a wide edit portal for the purpose, or perhaps even a multi-line edit portal. However, trappings are not something that the user will likely want to see all the time, so dedicating a large area of screen real estate to trappings is probably not a good idea. A better approach is to do something similar to the way details are handled for Journal entries: an "edit" button allows the user to edit the contents via a dedicated form.
So our plan is to clone the portal used for journal entries and adapt it to our needs. Open the file "tab_journal.dat" and locate the portal with a unique id of "notes". This is the portal used for editing the notes of journal entries. Copy the portal and paste it into the arcane power template that we're developing. We can now give it a more suitable unique id ("trappings"), change the tip text, and associate it with the proper field for the trappings ("powTraps"). This portal will provide a button that the user can click on, which will bring up a separate form where the trappings of the power can be edited. The new portal should look similar to the example below.
<portal id="trappings" style="actNotesSm" tiptext="Click here to edit the trappings for the arcane power."> <action action="notes" field="powTraps"> </action> </portal>
We can now properly position all of our portals. The tallest portal will be the details, and it will always have a height of a full three lines of text, so that will dictate our template height. One important detail, though, is that the initial "sizing" handling of templates within tables performs its task generically (i.e. without a specific pick to process). As a result, dynamic calculations like "textheight" on a script-based label will always retrieve the height for an empty string. This means that we cannot use "textheight" to determine the height of the portal during "sizing" and must rely on "fontheight" instead. Continuing on, we'll center the name vertically, then we'll stack the various buttons on the right, with the "delete" and "info" portals on top and the "trappings" portal beneath. Putting it all together yields a Position script similar to the one below.
~set up our height based on our tallest portal ~Note: Since the portal is a script-based label, it will not have any contents ~when the height of the template is initially determined for general sizing. ~Consequently, we can't use "textheight" here and must use "fontheight" instead. height = portal[details].fontheight * 3 ~if this is a "sizing" calculation, we're done if (issizing <> 0) then done endif ~position our tallest portal at the top portal[details].top = 0 ~center the name vertically perform portal[name].centervert ~center the info and delete portals within the upper half of the template var half as number half = height / 2 portal[info].top = (half - portal[info].height) / 2 portal[delete].top = (half - portal[delete].height) / 2 ~center the trappings portal within the lower half of the template ~Note: The info portal is big, so shift it down a little extra for better spacing. portal[trappings].top = half + (half - portal[trappings].height) / 2 + 1 ~position the delete portal on the far right perform portal[delete].alignedge[right,0] ~position the info portal to the left of the delete button perform portal[info].alignrel[rtol,delete,-6] ~center the trappings portal between the info and delete buttons var span as number span = portal[delete].right - portal[info].left portal[trappings].left = portal[info].left + (span - portal[trappings].width) / 2 ~position the name on the left and use a suitable amount of space portal[name].left = 0 portal[name].width = 200 ~position the details next to the name and use the remaining space perform portal[details].alignrel[ltor,name,10] portal[details].width = portal[info].left - portal[details].left - 10
Refining Arcane Powers
Now that everything is working, we need to refine the behaviors. The first thing we need to address is that centered text just doesn't look very good for either the power name or the details. Open the file "styles_ui.aug", which is where all the styles are defined that are used within the user-interface. Scroll down to where the label styles are defined and scan through the pre-defined options that are available. For the power name, we need something in a "Large" font, just like we're using now, except that we need something that is left-aligned. Unfortunately, no such style exists, so we'll need to define one ourselves. Locate the "lblLarge" style and make a copy of it. Change the unique id to something appropriate (e.g. "lblLrgLeft") and change the alignment to "left". The result should look like the style below.
<style id="lblLrgLeft"> <style_label textcolor="f0f0f0" font="fntLarge" alignment="left"> </style_label> </style>
Once the style is defined, switch back to the template for arcane powers and locate the "name" portal. Change the style to the new one we just defined ("lblLrgLeft"). When you reload the data files, arcane powers should now have their name left-aligned properly.
Now we need a left-aligned solution for the currently centered "details" portal. Looking at the pre-defined styles in the file "styles_ui.aug" again, the "lblSmlLeft" style uses the "Small" font and is left-aligned. That's exactly what we need, so we'll make use of it within the appropriate portal. Locate the "details" portal and change the style to "lblSmlLeft". After a re-load, the details text should be properly left-aligned.
The last refinement we need to do for the template is to make sure our tab order is appropriate. The tab order of portals within a template is always the order in which the portals are actually defined in the template. As such, the portals should be sequenced so that the flow seems natural to the user. For example, the following sequence seems reasonable: "name", "details", "info", "delete", and "trappings". Revise the sequence as you deem fit and the template is now good to go.
Summary Information
The management of arcane powers is fully operational, but the "Arcane" tab should probably include some additional details about the selected arcane background, including the total number of powers and power points available to the character. We can present this in a template at the top of the panel, with the table appearing beneath the template. We'll keep the template simple, so we'll create something that contains only a single, script-based label. All of the info we want to present will exist within the label, allowing the template height to be determined based on the height of the one portal. The net result is something that looks like the following.
<template id="apHeader" name="Arcane Header" compset="Actor"> <portal id="info" style="lblNormal"> <label> <labeltext><![CDATA[ ~use a color that's is slightly less bright that the normal text for powers @text = "{text c0c0c0}Total Powers: " & #resmax[resPowers] ~insert a horizontal gap between the two values to space them nicely @text &= "{horz 40} Total Power Points: " & #trkmax[trkPower] ]]></labeltext> </label> </portal> <position><![CDATA[ ~set up our height based on the tallest portal height = portal[info].height ~our portal should be centered in the template perform portal[info].centerhorz perform portal[info].centervert ]]></position> </template>
With the template in place, we can add the template to the layout. The template is positioned at the top, and the table consumes all remaining vertical space beneath. The result should look similar to the layout below.
<layout id="arcane"> <portalref portal="apPowers" taborder="10"/> <templateref template="apHeader" thing="actor"/> <position><![CDATA[ ~position and size the template and table to span the full layout perform template[apHeader].autoplace perform portal[apPowers].autoplace[8] ]]></position> </layout>