Seeing the light, using SODA

@yojimbo2000 , here’s my current code.

function addInfoScreen()
    local infoText = [['Double Choose' is two small adventure games written entirely by my daughters Rosie and Charlotte.  Tap on Rosie to play her game, and tap on Charlotte to play hers. 
Rosie did the art for her game, and I did most of Charlotte's game under her firm art-direction. 
You'll enjoy the games most by trying to find all the possible endings.  Rosie's game has awesome emotionally-excruciating endings.  Charlotte actually included a little adventure-game-style inventory management--impressive for a five-year-old! 
We made it with the excellent iPad app Codea.  We hope you enjoy our games, and we especially hope they inspire other kids to make games too.  Try Codea, it rocks!]]
    --define parameters for the info window
    local insetX, insetY = math.floor(WIDTH * 0.04), math.floor(HEIGHT * 0.04)
    local windowW, windowH = WIDTH - (insetX * 2), HEIGHT - (insetY * 2)
    local textW, textH = windowW - (insetX * 2), windowH - (insetY * 2)
    local iFontName = "GillSans-Light"
    local iFontSize = 1.75
    local infoColor = color(198, 110, 198, 255)
    local showInfo = function()
        local window = Soda.Window {
        title = "",
        blurred = true,
        close = true,
            style = {
                shape = {fill = color(37, 37, 37, 255), stroke = "midGrey", strokeWidth = iStrokeWidth}, text = {}}, 
        x = insetX, y = insetY, w = windowW, h = windowH
        local subWindow = Soda.Window {
            parent = window,
            title = infoText,
            style = {
                shape = {fill = color(0, 0, 0, 0), stroke = "midGrey", strokeWidth = iStrokeWidth}, 
                text = {fontSize = iFontSize,  font = iFontName, fill=infoColor, textAlign = LEFT},
            x = 0, y = -1 * windowH / 3.65, w = windowW, h = windowH
    --determine the correct the size of the info circle
    local iCircleSize = WIDTH * 0.065
    --define the placement of the info circle
    local iCircleOffset = iCircleSize * 0.48
    local infoCircleFontSize = iFontSize * 1.9
    local iStrokeWidth = infoCircleFontSize * 0.85
    local iCircleColor = color(144, 125, 144, 255)
    infoButtonTable = Soda.Button{
        title = "i",
        style = {
            shape = {fill = color(0, 0, 0, 0), stroke = iCircleColor, strokeWidth = iStrokeWidth}, 
            text = {fontSize = infoCircleFontSize,  font = "GillSans", fill=iCircleColor},
            highlight = {
                text = {fontSize = infoCircleFontSize,  font = "GillSans", fill=color(0, 0, 0, 0)},
                shape = {fill = iCircleColor}
        shape = Soda.ellipse,
        x = 20, y = 20, w = iCircleSize, h = iCircleSize,
        callback = showInfo

Of note:

  • I couldn’t get text scroll and text window to change their font size, font, and font color, so I ended up using two window elements.
  • Because window elements only display text in the title area, to get the info text placed correctly I had to do kludgy things like ‘y = -1 * windowH / 3.65’, manually scooting the child element down so that the text appeared to be actually contained inside the parent window.
  • I had to use math.floor (…) on my x/y calculations to get my windows to appear at all; as I noted in the main Soda thread, x/y values that have decimals don’t seem to work.

Please let me know if you have any tips!

@UberGoober see my comment on the main Soda thread, so if you’ve made one frame the child of another, you can use relational coordinates, no need to do this x = 0, y = -1 * windowH / 3.65, w = windowW, h = windowH, you should be able to pin a frame to its parent with x=0,y=0,w=1,h=1 (1 parsed as 100%)

@yojimbo2000 , those are two separate issues. The proportional concept is a neat idea, I reply to it in the other thread.

But in this case, I have to do y = -1 * windowH / 3.65.

The reason is that I want to display that big chunk of text in a custom font, size, and color.

But at present I can’t change the font or fontSize or font color of a TextWindow or a TextScroll.

To get a custom font, what I’m actually using is the title value of a Window element. Then I put that element inside a parent Window.

Of course, the title string tries to position itself near the top of its Window’s bounds, so to make the text look centered inside its parent I have to slide the child window down.

Through trial and error I came to the y = -1 * windowH / 3.65 as the value that looked the most vertically centered.

I know this is super, super kludgey but without being able to style the text inTextWindows I couldn’t figure out a better way.

@yojimbo2000 , what soda UI element would you recommend using as a label?

Use Soda.frame. All elements have a title property, use this to label the frame. Confusingly, the coordinates of the title are held in a property called label. It defaults to the centre-top of the frame, but you can override this.

@yojimbo2000, how does the override work?

Set the label. It has x and y coords, which work the same as other positions in soda. Eg 0.5, 0.5 to centre the label.

@yojimbo2000 :smile:


Is there an element that displays images?


Have converted all of the app to Soda except for the images. Your library is awesome and improves the feel of the app a million percent.

One odd bug I wonder if you can advise me on. For some reason I can’t make blurry buttons: setting blurred to true crashes the game.

I’ve made an importable version of the app here:, it replaces all custom images with default images from Codea.

If you want to see the crash happen, import that project, make Soda a dependency, and under the tab “TwoChoiceAdventure” uncomment the text “blurred = true” at line 201.

@yojimbo2000 I’m entering a plea for an Image element in SODA.

The SODA proportional-positioning system becomes so convenient that going back and forth between that and the Codea system starts to be a big hassle.

Placing images is really the only reason I need to use the Codea system anymore. Please make a SODA Image element so my graphics routines can be all-singing, all-dancing, all-SODA all the time!

Shouldn’t it be trivial to implement your own image frame element? You could then post it here and then maybe @yojimbo2000 can pull it into his main project when he has time.

Does really everyone use Soda? Okay, once installed, how to move Soda to your project? Do you have to copy all files there or – ?

@TokOut you just use SODA as a dependency, you can see the menu for that when you press the “+” button for making a new tab inside a project.

@em2 I looked into that and trivial it’s not.

Part of the problem comes from the fact that Codea separates 2D rendering and 3D rendering. SODA is actually all 3D meshes, so its drawing routines all happen during Codea’s 3D rendering phase. To simply stick a normal Codea sprite() call in the middle of a SODA element would be sticking a 2D render in among the 3D rendering, and that has unpredictable results.

Another part of the problem is that @yojimbo2000 has implemented a rather elegant parent-child relationship, wherein the child’s positioning and size information are all interpreted relative to the origin and dimensions of the parent. This way, a button in the corner of a window stays in the same place relative to the window even when the user moves the window around the screen. This is all really great, but it is also fully incompatible with the sprite() coordinate system, which always references the absolute values of the current screen. It is technically possible to pull some wizardry to translate those sprite coordinates based on a parent’s position, but the logistics of that–not mention trying to integrate it with the existing code–are beyond me.

But take a look for yourself, if you want–perhaps an easy solution will occur to you. For me, it looks really really really non-trivial.