Refining the "Arcane" Tab (Savage)

From HLKitWiki
Jump to navigationJump to search

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>