Guidance on Displaying Text for Beginners

,

Platform: Visual Studio - LUA
OS: Windows 11

I'm a novice at this and am self-teaching everything I have learned thus far. As I am building pieces of a project and putting them together, I am now at a stage of displaying some text boxes on a screen and am needing some guidance or tips.

I'm putting this out here incase some other novice like myself might have a similar situation and might find this information useful.

Brief context, this is a utility program for performing Tarot readings. We are programming the screen that you can use to scroll through the dealt cards to review position meanings and card meanings.

Here is my screen:

In the top center we have a list-style gridview and you use the D-pad up / down to swap which position you are reviewing. On changing the selected cell in the gridview, we have the screen redrawn to show the new data. I want the rest of the boxes to update to show the following data:

Left side for Position Data. Right side for Card Data. Top boxes for Label, bottom box for data.

I have all the data accessible via variable and stored within the code, so writing the data should be easy enough, but here's where I come to the limit of my knowledge.

I see the two main functions drawText and drawTextInRect. In both of those I read that the text will be truncated if it does not fit in the space outlined in the draw function.

How does one handle scrollable text? The top boxes I'm not worried about, but the bottom boxes could potentially have several paragraphs of text that could scroll off the screen, especially if we draw it large enough to read comfortably. I would like to use the crank for someone to scroll both pages and be able to read the text.

I've been scanning through the drawing text section of the SDK and either I'm missing the context, or maybe it's somewhere in a different section?

I've also read about the performance hits that come with drawTextInRect. This program is very static and doesn't have a ton happening on the screen at any given time. So I should be fine to use the drawTextInRect function right?

Since the user could flick through the positions to find the one they need, forcing several screen redraws in the process, should we consider handling this whole process differently?

Thank you for your time and consideration,

1 Like

drawTextInRect should be a lot more performant now, it was just recently ported over to be implemented in C so it's much faster. I wouldn't worry.

As for scrolling text, you kind of need to manage your own scroll. That is store a yOffset that gets subtracted from the Y position of your text drawing. Then you can increase and decrease that value with the crank or dpad and then you will get scrolling.
In order to make the top text 'disappear' off the top of the window you can set the graphics clipping rect to be just the text area before you do the drawing. eg.

gfx.setClipRect(x, y, width, height)
gfx.drawTextInRect(Text, x, y-yOffset, width, height, nil, nil, kTextAlignment.center)
gfx.clearClipRect()

Alternatively, you may be able to use the grid view with only 1 item?

1 Like

Thank you for this information and direction. I wasn't fully understanding the setClipRect since it was something you set and then remove. I didn't realize that it would continue to apply after removing it, just another thing to wrap my brain around haha.

This just contains example text that I will replace with variable reference soon, but needed to ensure function first. As part of that function, I find that this scrolls infinitely. Did I not set something correctly with my initializeScrollLimits function?

That function gets called and recalled along with the screen being initially drawn and redrawn.

Screen Draw Coding
-- FUNCTIONS FOR READING REVIEWS
local scrollOffsetPosition = 0
local scrollOffsetCard = 0
local scrollMaxPosition = 0
local scrollMaxCard = 0
local positionText = "This is a demo text for the position scrolling box. Scroll to see more of this text if it gets too long. This is a demo text for the position scrolling box. Scroll to see more of this text if it gets too long. This is a demo text for the position scrolling box. Scroll to see more of this text if it gets too long."
local cardText = "This is a demo text for the card scrolling box. Scroll to see more of this text if it gets too long. This is a demo text for the card scrolling box. Scroll to see more of this text if it gets too long. This is a demo text for the card scrolling box. Scroll to see more of this text if it gets too long."

local function initializeScrollLimits()
    scrollMaxPosition = math.max(0, gfx.getTextSize(positionText) - 100) -- 100 is the height of the scrollable box per the setClipRect used
    scrollMaxCard = math.max(0, gfx.getTextSize(cardText) - 100) -- 100 is the height of the scrollable box per the setClipRect used
end

local function reviewReadingScreen()
    local reviewScreenImage = gfx.image.new(400, 240)

    -- Draw the background image 
    local backgroundImage = gfx.image.new(SelectedBackground)
    if backgroundImage then
        local bgOffsetX, bgOffsetY = calculateOffsets(backgroundImage, 400, 240)

        gfx.pushContext(reviewScreenImage)
            backgroundImage:draw(bgOffsetX, bgOffsetY)
        gfx.popContext()
    else
        print("Error: Background image not found.")
    end

    -- Draw the review overlay image
    local reviewImage = gfx.image.new("images/Misc/Reading_Review")
    if reviewImage then
        local reviewOffsetX, reviewOffsetY = calculateOffsets(reviewImage, 400, 240)

        gfx.pushContext(reviewScreenImage)
            reviewImage:draw(reviewOffsetX, reviewOffsetY)
            positionSelectorGridview:drawInRect(156, 14, 88, 24)
        gfx.popContext()
    else
        print("Error: Review image not found.")
    end

    -- Add label text boxes
    gfx.pushContext(reviewScreenImage)
        -- Position Name Box
        gfx.drawTextInRect("TEXT A", 10, 10, 150, 20, nil, nil, kTextAlignment.left)

        -- Card Name Box
        gfx.drawTextInRect("TEXT B", 240, 10, 150, 20, nil, nil, kTextAlignment.right)
    gfx.popContext()

    -- Add scrollable text boxes
    gfx.pushContext(reviewScreenImage)
        -- Clip and draw the position scrollable text box
        gfx.setClipRect(10, 80, 180, 100)
        gfx.drawTextInRect(positionText, 10, 80 - scrollOffsetPosition, 180, 500, nil, nil, kTextAlignment.left)
        gfx.clearClipRect()

        -- Clip and draw the card scrollable text box
        gfx.setClipRect(210, 80, 180, 100)
        gfx.drawTextInRect(cardText, 210, 80 - scrollOffsetCard, 180, 500, nil, nil, kTextAlignment.left)
        gfx.clearClipRect()
    gfx.popContext()

    -- If Sprite already exists, remove it to replace with updated one
    if ReviewReadingSprite then
        ReviewReadingSprite:remove()
    end

    ReviewReadingSprite = gfx.sprite.new(reviewScreenImage)
    ReviewReadingSprite:setZIndex(2)
    ReviewReadingSprite:moveTo(200, 120)
    ReviewReadingSprite:add()

    gfx.sprite.update()
end
Update Loop Logic
        -- Return to Manual Reading Mode
        if pd.buttonJustPressed(pd.kButtonB) then
            print("Removing the ReviewReadingSprite")
            ReviewReadingSprite:remove()
            readingActionSprite:add()
            print("Swapping back to manualReading mode")
            gameMode = "manualReading"
        end

        -- Position Selection Change
        if pd.buttonJustPressed(pd.kButtonUp) then
            positionSelectorGridview:selectPreviousRow(true)
        elseif pd.buttonJustPressed(pd.kButtonDown) then
            positionSelectorGridview:selectNextRow(true)
        end

        -- Handle crank input for scrolling text boxes
        local crankDelta = pd.getCrankChange()
        if crankDelta ~= 0 then -- Detect crank movement
            scrollOffsetPosition = math.max(0, math.min(scrollOffsetPosition + crankDelta, scrollMaxPosition)) -- Update position scrollable text box
            scrollOffsetCard = math.max (0, math.min(scrollOffsetCard + crankDelta, scrollMaxCard))
            NeedsRedraw = true
        end

        -- Redraw if needed
        if positionSelectorGridview.needsDisplay == true or NeedsRedraw then
            reviewReadingScreen()
            initializeScrollLimits()
            NeedsRedraw = false
        end

your text has no \n so textSize will be the font height so like 16 - 100.
so you're mins and maxes are probably getting tripped up by max being a negative number.
I think you want to use getTextSizeForMaxWidth
getTextSizeForMaxWidth

1 Like

Ok, that makes a lot more sense!

Thank you so, so much!

1 Like