forked from oliver-dew/Soda
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSodaTutorial.lua
More file actions
899 lines (756 loc) · 30.2 KB
/
SodaTutorial.lua
File metadata and controls
899 lines (756 loc) · 30.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
--# Welcome
function setupUI()
overview{content = [[
This is a tutorial that introduces the basic features of Soda.
When you're ready to start the tutorial, press "Begin Tutorial".
]],
ok = "Begin Tutorial",
callback = function() stepSelector.list:selectFromList(stepSelector.list.child[2]) end}
end
--# HelloWorld
function setupUI()
--all Soda elements take a table of keys as their arguments
--in Lua, if a function's sole argument is a table or a string,
--you can omit the enclosing () and just use "" or, in this case, {}
Soda.Window{ --Soda.Window is a basic window, with rounded corners and a title.
title = "Hello World", --title at the top of the window
--when coordinates are between 0 and 1, they represent proportions of the parent
--and the drawing mode is set to CENTER
--as there is no parent here, they are proportions of the entire screen:
x=0.5, --Horizontally, the window is centred,
y=-0.001, --And as we can't write -0, we fix it to the top edge with -0.001
w=0.7, --Its dimensions cover 70% of the screen's width
h=0.51, --and just over half of its height
}
--the advantage of making all coordinates relative to a parent (in this case the screen)
--is that elements automatically resize when device orientation changes.
--try flipping your device now.
end
--# SpecialEffects
function setupUI()
--special effects
Soda.Window{
title = "Hello World",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, --add a blurred effect
shadow = true, --add a drop shadow
--the Style tab of the Soda library contains the Soda.style table
-- this defines what colours, fonts, line widths etc the buttons are drawn with.
--if you don't supply a "style" parameter, the buttons are drawn with Soda.style.default
}
end
--# Parenthood
function setupUI()
--ok lets add some buttons to our window.
--we need to make the window the parent of all the elements it contains
--to do this, we need a handle to refer to it by.
--as Soda automatically remembers all elements you create, this handle should be a local variable, not global
--lets call our window "panel"
local panel = Soda.Window{ --give parent a local handle, in this case "panel", to define children
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
--lets put a button in it. It's going to be one of the pre-defined buttons, a question mark.
Soda.QueryButton{
parent = panel, --make the Window we just defined the parent
--this makes all coordinates relative to the parent
--so, if we want this button to go in the top-left corner, with a 10-pixel border, we write
x = 10, y = -10
}
--the advantage of making coordinates relative to the parent is that if we decide the window is too cluttered
--we just have to resize the parent, we don't have to change the coordinates of everything within
--it also allows elements to resize easily eg when orientation changes. Try flipping your device.
--oh, and try pressing your button!
end
--# Callbacks
--lets make our button do something
--to do this, we use the callback parameter, and assign it a function.
--A question mark button is something you press when you want help, so we're going to make it open
--the help file for Soda using openURL.
--lets define our openHelp function:
function openHelp()
openURL("https://github.com/Utsira/Soda/blob/master/README.md", true)
end
function setupUI()
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
-- now we make the callback attribute point to the openHelp function (nb the openHelp function can be defined anywhere in our code, it doesn't have to be above the button definition, or in the same tab)
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp --note that when we point to a function like this, we just use the function name. Do not add () or the function will be triggered when we define the button, instead of when the button is pressed
}
--You can use this button if you want to check anything in the documentation. Check that it works now.
end
--# Panels
function setupUI()
--Our window is looking a little bare still. Lets start adding some panels.
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp --nb this still works, even though openHelp is in another tab
}
--this panel will eventually allow for the user to enter details about themselves, a user account.
--I'm calling it accountPanel.
local accountPanel = Soda.Frame{ --Frame is a basic holder for other elements
parent = panel,
x = 10, y = 10, w = -10, h = -60, -- a 10 pixel border, except at the top (to give room for the Window title and query button)
shape = Soda.RoundedRectangle, subStyle = {"translucent"}, --omit shape to make the frame invisible
shapeArgs = {radius = 16} --set the radius to be a little smaller than the parent window
}
end
--# TextEntry
function setupUI()
--Lets add a text entry box to our user account panel
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--our text entry box:
Soda.TextEntry{
parent = accountPanel, --this time, the parent is the accountPanel (so this text entry box is the grandchild of the Window)
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name", --some default text, in this case a prompt, that the user will overwrite
}
end
--# Alert
function setupUI()
--Lets make our text entry box do something, so that the user knows her input has been accepted
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--just as we did with the query button, we're going to add a callback to text entry.
--this time however, instead of pointing to a predefined function,
--the callback itself will be a function. Nesting a function inside another block is called
--a closure.
--text entry callbacks are triggered when the user hits return or the close keyboard button.
--our callback is going to produce an alert dialog acknowledging the users input.
--callbacks always pass the sender (ie this particular text entry box, its "self") as the first argument.
--textentry callbacks are passed the entered text as the second argument.
Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name",
callback = function(self, inkey) --in this case, we're not using the "self" variable
Soda.Alert{ --brings up an alert dialog, with a single button to dismiss it
title = "User name registered as \n"..inkey,
ok = "\u{4e86}\u{89e3}", --by default, the ok button says "ok". We can override this with the ok parameter. Here I've set it to the Japanese for "ok"
blurred = true --add some lovely blurriness
}
end
}
end
--# DropdownList
function setupUI()
--Lets add a dropdown list to our accountPanel
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
--account panel
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--text entry:
Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--and, our dropdown list:
Soda.DropdownList{
parent = accountPanel,
--we want it to tuck in below the text entry box, with a 10 pixel gap
--so, y = -60 (the top of the textbox) -40 (height of text box) -10(gap between boxes) = -110
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
--we pass "text" an array of strings for each item in the list
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw"},
--list callbacks return 3 values: self, the selected item, and the label text of the selected item
callback = function(self, selected, txt)
Soda.Alert{
title = txt.." are not\nthe only fruit"
}
end
}
end
--# AnotherButton
function setupUI()
--Lets add a reset button to clear the values that the user has entered
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
--account panel
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--The reset button will need to be able to access the textentry and dropdown list elements, so both of these now need handles:
local userName = Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--dropdown list:
local faveFruit = Soda.DropdownList{
parent = accountPanel,
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw"},
callback = function(self, selected, txt)
Soda.Alert{
title = txt.." are not\nthe only fruit"
}
end
}
--our reset button
Soda.Button{ --We're not using one of the presets, just a standard Soda.Button this time
parent = accountPanel,
x = -10, y = 10, h = 40, --lets put it in the bottom right corner
title = "Reset",
--as this could be wiping some data, let's make this button RED:
subStyle = {"warning"},
--and give the user a chance to cancel the operation, using an proceed/cancel 2 button alert:
callback = function()
Soda.Alert2{
title = "This will reset the values\nentered in the account panel",
--now we nest another callback inside the alert, to say what happens when the user selects "proceed":
callback = function()
userName:inputString("") --blank the username
faveFruit:clearSelection() --and fave fruit
end
--this is one of the most powerful aspects of callbacks:
--they store and remember the variables of the enclosing function (called "upvalues")
--even the local variables, and can continue to access them after this function has ended.
--Here userName and faveFruit are setupUI's local variables. Once setupUI has finished
--executing, there's no way to access them. This stops our project's namespace geting too
--cluttered, and stops us accidentally overwriting or reasigning them.
--But the reset button can continue to access them, because it stores setupUI's local variables.
}
end
}
end
--# Toggle
function setupUI()
--Lets add a switch to toggle our entire interface on and off
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.MenuToggle{ --menu toggle is a preset displaying the "hamburger" menu icon
--no parent, top-level interface element
x = -10, y = -10, --stick it in the top-right corner of the screen
callback = function() panel:show(LEFT) end,
--we're going to use the :show(direction) method to make the entire interface appear.
--direction indicates which side of the screen to animate from
--omit direction to just have the panel appear without animation
--toggles also have a callbackOff, fired when they're turned off:
callbackOff = function() panel:hide(LEFT) end,
--toggles are set to off by default. However, we want our panel to be visible at the start.
--so we can override this with the "on" flag:
on = true
}
--press the button to test!
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
--account panel
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--text entry:
local userName = Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--dropdown list:
local faveFruit = Soda.DropdownList{
parent = accountPanel,
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw"},
callback = function(self, selected, txt)
Soda.Alert{
title = txt.." are not\nthe only fruit"
}
end
}
--reset button:
Soda.Button{
parent = accountPanel,
x = -10, y = 10, h = 40,
title = "Reset",
subStyle = {"warning"},
callback = function()
Soda.Alert2{
title = "This will reset the values\nentered in the account panel",
callback = function()
userName:inputString("")
faveFruit:clearSelection()
end
}
end
}
end
--# SegmentedButton
function setupUI()
--Lets add a second panel, and a segmented button to switch between the panels.
--Having different panels stops our interface from getting too cluttered
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--this is a settings panel. Other than the handle, it is identical to the accountPanel
local settingsPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--now, to choose between the two panels (and stop them both appearing at once)
--we'll add a segmented button
Soda.Segment{
parent = panel,
x = 20, y = -70, w = -20, h = 40,
text = {"Account details", "Settings"}, --like dropdownList, we pass "text" an array of strings. It contains the labels for each button segment
panels = {accountPanel, settingsPanel}, --the panels we just defined, whch correspond to the labels in "text"
defaultNo = 2 --display the second panel ("Settings") by default
}
--our text entry box from the previous step:
local userName = Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Enter name",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--the dropdown list:
local faveFruit = Soda.DropdownList{
parent = accountPanel,
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw"},
callback = function(self, selected, txt)
Soda.Alert{
title = txt.." are not\nthe only fruit"
}
end
}
--reset button:
Soda.Button{
parent = accountPanel,
x = -10, y = 10, h = 40,
title = "Reset",
subStyle = {"warning"},
callback = function()
Soda.Alert2{
title = "This will reset the values\nentered in the account panel",
callback = function()
userName:inputString("")
faveFruit:clearSelection()
end
}
end
}
--see how, when flicking back and forth between the panels, the states of the elements within those panels is retained
end
--# ScrollingThroughText
function setupUI()
--Lets make our second panel a scrolling block of text
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true, shadow = true,
}
Soda.MenuToggle{
x = -10, y = -10,
callback = function() panel:show(LEFT) end,
callbackOff = function() panel:hide(LEFT) end,
on = true
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
--2 panels plus the segmented selector
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--this time, the second panel will be a scrolling body of text. Codea's text command doesn't produce any output if it is bigger than either the width or height of the screen, so Soda TextWindow and TextScroll elements break large text bodies up into chunks
local backStory = Soda.TextScroll{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16},
textBody =
[[
OK, I'll talk! In third grade, I cheated on my history exam.
In fourth grade, I stole my uncle Max's toupee and I glued it on my face when I was Moses in my Hebrew School play.
In fifth grade, I knocked my sister Edie down the stairs and I blamed it on the dog...
when my mom sent me to the summer camp for fat kids and then they served lunch I got nuts and I pigged out and they kicked me out!
[much later]
...but the worst thing I ever done:
I mixed up all this fake puke at home and then I went to this movie theater, hid the puke in my jacket, climbed up to the balcony and then, t-t-then, I made a noise like this:
hua-hua-hua-huaaaaaaa -
and then I dumped it over the side, all over the people in the audience.
And then, this was horrible, all the people started getting sick and throwing up all over each other. And I never felt so bad in my entire life!]]
}
Soda.Segment{
parent = panel,
x = 20, y = -70, w = -20, h = 40,
text = {"Account details", "Life story"},
panels = {accountPanel, backStory},
defaultNo = 2
}
--text entry:
local userName = Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Chunk",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--dropdown list:
local faveFruit = Soda.DropdownList{
parent = accountPanel,
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw", "Babe Ruth"},
defaultNo = 9
}
--reset button:
Soda.Button{
parent = accountPanel,
x = -10, y = 10, h = 40,
title = "Truffle Shuffle",
subStyle = {"warning"},
callback = function()
Soda.Alert2{
title = "This will reset the values\nentered in the account panel",
callback = function()
userName:inputString("")
faveFruit:clearSelection()
end
}
end
}
end
--# ThrowSomeShapes
function setupUI()
--Finally, let's tweak the shape of our main window slightly. We're going to set the shapeArgs attribute so that only the bottom corners of the window are rounded
local panel = Soda.Window{
title = "Tutorial",
x=0.5, y=-0.001, w=0.7, h=0.51,
blurred = true,
shadow = true,
--you can pass a table of arguments to the shape function, such as choosing which corners will be rounded
--Corners are numbered 1,2,4,8 starting in bottom-left and proceeding clockwise. Defaults to 15 (all corners). Use bitwise operators to set. eg to only round the bottom corners set this to `1 | 8` (1 or 8). To round all but the top-right corner, use `~4` (not 4)
shapeArgs = { corners = 1 | 8} --only round bottom corners
}
Soda.MenuToggle{
x = -10, y = -10,
callback = function() panel:show(LEFT) end,
callbackOff = function() panel:hide(LEFT) end,
on = true
}
Soda.QueryButton{
parent = panel,
x = 10, y = -10,
callback = openHelp
}
--2 panels plus the segmented selector
local accountPanel = Soda.Frame{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16}
}
--text scroll
local backStory = Soda.TextScroll{
parent = panel,
x = 10, y = 10, w = -10, h = -60,
shape = Soda.RoundedRectangle, subStyle = {"translucent"},
shapeArgs = {radius = 16},
textBody =
[[
OK, I'll talk! In third grade, I cheated on my history exam.
In fourth grade, I stole my uncle Max's toupee and I glued it on my face when I was Moses in my Hebrew School play.
In fifth grade, I knocked my sister Edie down the stairs and I blamed it on the dog...
when my mom sent me to the summer camp for fat kids and then they served lunch I got nuts and I pigged out and they kicked me out!
[much later]
...but the worst thing I ever done:
I mixed up all this fake puke at home and then I went to this movie theater, hid the puke in my jacket, climbed up to the balcony and then, t-t-then, I made a noise like this:
hua-hua-hua-huaaaaaaa -
and then I dumped it over the side, all over the people in the audience.
And then, this was horrible, all the people started getting sick and throwing up all over each other. And I never felt so bad in my entire life!]]
}
Soda.Segment{
parent = panel,
x = 20, y = -70, w = -20, h = 40,
text = {"Account details", "Life story"},
panels = {accountPanel, backStory},
defaultNo = 2
}
--text entry:
local userName = Soda.TextEntry{
parent = accountPanel,
x = 10, y = -60, w = -10, h = 40,
title = "User name:",
default = "Chunk",
callback = function(self, inkey)
Soda.Alert{
title = "User name registered as \n"..inkey,
ok = "Got it",
blurred = true
}
end
}
--dropdown list:
local faveFruit = Soda.DropdownList{
parent = accountPanel,
x = 10, y = -110, w = -10, h=40,
title = "Favourite fruit",
text = {"Apples", "Oranges", "Pears", "Bananas", "Strawberries", "Jack Fruit", "Dorian", "Paw paw", "Babe Ruth"},
defaultNo = 9
}
--reset button:
Soda.Button{
parent = accountPanel,
x = -10, y = 10, h = 40,
title = "Truffle Shuffle",
subStyle = {"warning"},
callback = function()
Soda.Alert2{
title = "This will reset the values\nentered in the account panel",
callback = function()
userName:inputString("")
faveFruit:clearSelection()
end
}
end
}
end
--# AndFinally
function setupUI()
Soda.Window{
y = 0.75,
title = [[
In the final step of this
tutorial you will see the Main
tab which has the hooks needed
to connect Soda to your own
projects
]]
}
end
--# Main
-- Template for projects using Soda
assert(SodaIsInstalled, "Set Soda as a dependency of this project") --produces an error if Soda not a dependency
displayMode(OVERLAY)
displayMode(FULLSCREEN)
function setup()
Soda.setup()
--do your setting up here:
tutorial()
end
function draw()
--do your updating here
--end of updating
pushMatrix()
Soda.camera() --this scrolls the screen to stop the keyboard covering textEntry fields
Soda.drawing()
popMatrix()
end
function Soda.drawing(breakPoint) --the breakPoint variable stops a blurred window itself from being incorporated into the blurred effect: it ensure only things under the blurred area get drawn.
--in order for gaussian blur to work, do all your drawing here
background(40, 40, 50)
sprite("Cargo Bot:Game Area", WIDTH*0.5, HEIGHT*0.5, WIDTH, HEIGHT)
pushStyle()
Soda.setStyle(Soda.style.default.text)
fontSize(40)
text("Output\narea", WIDTH * 0.5, HEIGHT * 0.75)
popStyle()
--end of your drawing
Soda.draw(breakPoint) --pass the breakPoint variable
end
--user inputs:
function touched(touch)
Soda.touched(touch)
end
function keyboard(key)
Soda.keyboard(key)
end
function orientationChanged(ori)
Soda.orientationChanged(ori)
end
--template ends
function setupUI()
Soda.Window{
y = 0.75, w = 0.4, h = 0.4,
title = "Main",
content =
[[This can be used as a template
for the Main tab in your own
projects running Soda. It contains
all the hooks that you need to
connect Soda into the setup, draw,
touched, keyboard, and
orientationChanged routines.
]]
}
end
--# TutorialInterface
function tutorial()
-- parameter.watch("#Soda.items")
local steps = listProjectTabs() --get the steps of the tutorial
table.remove(steps) --remove this tab
local bookmark = readLocalData("bookmark", 1) --remember last tutorial step looked at
--grab the names of each tutorial step
local stepNames = {}
for i,v in ipairs(steps) do
stepNames[i] = v:gsub("(%w)(%u)", "%1 %2") --insert spaces into tabnames
end
local codeWindow = Soda.TextWindow{
shapeArgs = {corners = 2 | 4, radius = 25}, --just round the top corners
-- subStyle = {"translucent"},
blurred = true,
x = 0, y = 0, w = 1, h = 0.5,
title = "",
textBody = "",
}
stepSelector = Soda.DropdownList{
parent = codeWindow,
shapeArgs = {radius = 20},
x = 0.5, y = -5, w = 400, h = 40,
title = "Tutorial Step",
text = stepNames,
default = bookmark, --default to the last item looked at
enumerate = true, --automatically numbers the steps (requires Soda 0.4)
callback = function(self, obj)
saveLocalData("bookmark", obj.idNo) --save user's place in tutorial
local code = readProjectTab(steps[obj.idNo])
codeWindow:clearString()
codeWindow:inputString(code) --place new code in code window
while #Soda.items>1 do --remove all Soda interface elements except for the code window
table.remove(Soda.items)
end
tween.delay(0.001, function()
loadstring(code)() --load the code
setupUI() --run the code
end)
end
}
end