Wednesday, September 26, 2012

More PrintStatusLine stuff

Today, I got around to applying my new PrintStatusLine design to status-line-changing library extensions like newautomap.h and newconverse.h. It took some tweaking, but now with the current version of RoodyLib, it involves no finessing at all to have glk-enabled automap working in a game along with top-screen conversation menus. Just because I feel like my PrintStatusLine core code has changed just enough, I'm going to share the entire thing again. It might make some more sense if you are looking at a status-window-drawing extension along with this (like newautomap.h in http://roody.gerynarsabode.org/hbe/newautomap.zip), but maybe you can get some idea through the comments below:

! find_height - property that points to routines for determining status window height
property find_height alias u_to

! draw_window - routines with instructions for drawing the status window
property draw_window alias e_to

!\ bottom_justified - have this return true for status windows where regular
status information shares a window with other information and you want the
regular status information to be printed at the bottom of the window \!
property bottom_justified alias d_to

! terp_type - this property gets set to the current interpreter type automatically
property terp_type alias w_to

!\ status_override - normally, the status window object with the highest
find_height number gets drawn (so have those properties return 0 when not in
use), but sometimes more than one extension *could* be drawn, so we use
status_override to have one override the other (have it return true to initiate
such override) \!
property status_override alias nw_to

!\ chosen_window - set to the window instructions object whose draw_window
property will be executed. authors can ignore this. \!
property chosen_window alias nw_to

! "terp_type" values  0, 2, 4
enumerate step * 2
{
    NORMAL_TERP, GLK_TERP = 2, SIMPLE_TERP
}

!\ a PrintStatusLine object in which we will put our instruction objects in (by
inclusion of extensions and what not. PrintStatusLine will call this directly).
\!
object printstatuslib
{
    find_height
        {
        local highest, i, a
        for i in self
            {
                a = i.find_height
                if i.status_override
                    {
                    self.chosen_window = i
                    highest = i.find_height
                    break
                    }
            if higher(highest,a) = a
                    {
                    self.chosen_window = i
                    highest = i.find_height
                    }
            }
        return highest
        }
    draw_window
        {
        run (self.chosen_window).draw_window
        }
    chosen_window 0
    terp_type NORMAL_TERP
    bottom_justified 1
}

replace PrintStatusline
{
local newstatusheight

! set the "terp_type" value
if IsGlk
    printstatuslib.terp_type = GLK_TERP
elseif system(61) ! minimal port
        printstatuslib.terp_type = SIMPLE_TERP
else
    printstatuslib.terp_type = NORMAL_TERP

#ifset CHEAP
        if cheap and printstatuslib.terp_type ~= SIMPLE_TERP
            {
#if defined GAME_TITLE
            CenterTitle(GAME_TITLE,0,1)
#endif
#if undefined GAME_TITLE
            CenterTitle(CheapTitle,0,1)
#endif
            display.needs_repaint = false
            return
            }
        elseif cheap
            return
#endif ! CHEAP

! figure out the size our window will be
newstatusheight = printstatuslib.find_height

! clear/remove the window if the status window height has changed
if (newstatusheight < display.statusline_height) and not system(61)
    {
    window display.statusline_height
    {cls} ! clear whatever's there
    window 0
    }

display.statusline_height = newstatusheight

Font(BOLD_OFF | ITALIC_OFF | UNDERLINE_OFF | PROP_OFF)
window display.statusline_height
    {
    if printstatuslib.terp_type ~= SIMPLE_TERP
        {
          color SL_TEXTCOLOR, SL_BGCOLOR
        cls
        locate 1,1
        }
    run printstatuslib.draw_window
    }
color TEXTCOLOR, BGCOLOR, INPUTCOLOR
Font(DEFAULT_FONT)
}

! Here is an example status window instruction object. It and its routines
! draw a regular status window
object statuswindow
{
    in printstatuslib
    find_height
        {
        return (call &FindStatusHeight)
        }
    draw_window
        {
        return (call &WriteStatus)
        }
}
!\ Note: These properties *could* just say "return FindStatus". I just used
the above syntax to give a clue as to how one would change a value "mid-game".
If you want statuswindow.find_height to point to *another* routine, you could
have a line like this:
    statuswindow.find_height = call &FindNewStatusHeight  \!


! routine for finding the height of the regular status info
routine FindStatusHeight
{
local a, b
text to _temp_string
! can't start off a string with a space, it seems
!if not location     ! so we'll save this space-writing code for the
!    print "\_";     ! "status-writing" routine
!else
if not light_source
    print "In the dark";
else
    {
        print capital location.name;
         if FORMAT & DESCFORM_F
        print "\_";
    }
text to 0
a = StringLength(_temp_string)

text to _temp_string
select STATUSTYPE
    case 1 : print number score; " / "; number counter;
    case 2 : print HoursMinutes(counter);
    case 3 : print "Score: "; number score; "\_ "; "Moves: "; number counter;
    ! STATUSTYPE case 3 is the "Infocom"-style status
    case 4 : StatusType4 ! routine for configurable statusline
if (FORMAT & DESCFORM_F) and (printstatuslib.terp_type ~= GLK_TERP)
    print "\_";
text to 0
if STATUSTYPE
    b = StringLength(_temp_string)

if (b + a + 4)<display.screenwidth ! let's force a 4 character gap between
    {                              ! the two fields
    return 1
    }
elseif (b + a - 4 ) < display.screenwidth and STATUSTYPE = 3
    {
    text to _temp_string
    print "S: "; number score; "\_ "; "M: "; number counter;
    if (FORMAT & DESCFORM_F) and (printstatuslib.terp_type ~= GLK_TERP)
        print "\_";
    text to 0
    return 1
    }
else
    return 2
}

! Roody's note: Replace this if you want to use the top right area
! for something else ("HUNGRY", "TIRED", or whatever)
routine STATUSTYPE4
{}

! routine for drawing the regular status
routine WriteStatus
{
    if printstatuslib.bottom_justified and
        printstatuslib.terp_type ~= SIMPLE_TERP
        {
        if statuswindow.find_height = 2
            {
            locate 1, (display.windowlines - 1)
            }
        else
            locate 1, display.windowlines
        }
    if not location
        print "\_";
    elseif not light_source
        print "In the dark";
    else
        {
            if FORMAT & DESCFORM_F or (printstatuslib.terp_type = GLK_TERP)
                    print "\_";
            print capital location.name;
        }

    if statuswindow.find_height = 1 and STATUSTYPE
        {
            print to (display.linelength - \
            (StringLength(_temp_string) + \
            ((printstatuslib.terp_type = SIMPLE_TERP)*2) ));
            StringPrint(_temp_string)
        }
    elseif STATUSTYPE and statuswindow.find_height = 2
        {
            if printstatuslib.terp_type ~= SIMPLE_TERP and
            not printstatuslib.bottom_justified
                locate 1, 2
            else
                ""
            if (FORMAT & DESCFORM_F) or (printstatuslib.terp_type = GLK_TERP)
    print "\_";
            StringPrint(_temp_string)
        }
}

No comments:

Post a Comment