~etc-pgh-launchpad/wildpockets/trunk

« back to all changes in this revision

Viewing changes to scripts/Utils.lua

  • Committer: etc-pgh-launchpad at cmu
  • Date: 2010-11-30 20:56:30 UTC
  • Revision ID: etc-pgh-launchpad@lists.andrew.cmu.edu-20101130205630-0blbkcz28ovjl8wj
Committing the Wild Pockets code base to Launchpad.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
--[[
 
2
Wild Pockets
 
3
 
 
4
Copyright (c) 2010 Carnegie Mellon University
 
5
 
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy
 
7
of this software and associated documentation files (the "Software"), to deal
 
8
in the Software without restriction, including without limitation the rights
 
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
10
copies of the Software, and to permit persons to whom the Software is
 
11
furnished to do so, subject to the following conditions:
 
12
 
 
13
The above copyright notice and this permission notice shall be included in
 
14
all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
22
THE SOFTWARE.
 
23
 
 
24
]]
 
25
 
 
26
-- LUA UTILITIES
 
27
-- A collection of utility functions for Lua
 
28
 
 
29
-----------------------------------------------
 
30
 
 
31
docs([[
 
32
    table.sortedkeys(tab [,comp])
 
33
 
 
34
    Returns a list of the keys in table, in sorted order.
 
35
]])
 
36
 
 
37
function table.sortedkeys(tab, comp)
 
38
    -- Sort the list
 
39
    local sorted = {}
 
40
    for k,v in pairs(tab) do
 
41
        table.insert(sorted, k)
 
42
    end
 
43
    table.sort(sorted, comp)
 
44
    return sorted
 
45
end
 
46
 
 
47
sandboxScope(table, "sortedkeys", "USER")
 
48
 
 
49
-----------------------------------------------
 
50
 
 
51
docs([[
 
52
    table.print(tab)
 
53
 
 
54
    Prints the contents of the table. Mostly for
 
55
    debugging purposes.
 
56
]])
 
57
 
 
58
function table.print(tab)
 
59
    local any = false
 
60
    print("Table contents:")
 
61
    for k,v in pairs(tab) do
 
62
        print("  ",k,"->",v)
 
63
        any = true
 
64
    end
 
65
    if not any then
 
66
        print("  Empty table")
 
67
    end
 
68
end
 
69
 
 
70
sandboxScope(table, "print", "USER")
 
71
 
 
72
-----------------------------------------------
 
73
 
 
74
docs([[
 
75
    table.equal(tab1,tab2)
 
76
 
 
77
    checks to see if the contents of two tables are equal.
 
78
    So while {1,2,3} == {1,2,3} returns false
 
79
    table.equal({1,2,3},{1,2,3}) will return true
 
80
    
 
81
    This function does recursively check tables within tables
 
82
    with the same function.
 
83
 
 
84
]])
 
85
 
 
86
function table.equal(tab1,tab2,seen)
 
87
    if type(tab1) ~= "table" then return false end
 
88
    if type(tab2) ~= "table" then return false end
 
89
    
 
90
    if seen==nil then
 
91
        seen = {}
 
92
        seen[tab1] = true
 
93
        seen[tab2] = true
 
94
    end
 
95
    
 
96
    for k,v in pairs(tab1) do
 
97
        if (type(v) == "table") then
 
98
            if (seen[v]==nil) and seen[tab2[k]] == nil then
 
99
 
 
100
                if not (table.equal(v,tab2[k],seen)) then
 
101
                    return false
 
102
                end
 
103
            else
 
104
                if (v ~= tab2[k]) then
 
105
                    return false
 
106
                end
 
107
            end
 
108
        else
 
109
            if (v ~= tab2[k]) then
 
110
                return false
 
111
            end
 
112
        end
 
113
    end
 
114
    return true
 
115
end
 
116
 
 
117
sandboxScope(table, "equal", "USER")
 
118
 
 
119
-----------------------------------------------
 
120
 
 
121
 
 
122
 
 
123
docs([[
 
124
    table.find(tab,elem)
 
125
 
 
126
    Finds an object in a table and returns the
 
127
    location(key) where it is located.
 
128
    
 
129
    Returns nil if object is not found.
 
130
]])
 
131
 
 
132
function table.find(tab,elem)
 
133
    for k,v in pairs(tab) do
 
134
        if v == elem then
 
135
            return k
 
136
        end
 
137
    end
 
138
    return nil
 
139
end
 
140
 
 
141
sandboxScope(table, "find", "USER")
 
142
 
 
143
-----------------------------------------------
 
144
 
 
145
docs([[
 
146
    table.deepprint(tab)
 
147
 
 
148
    Prints the contents of the table, and any tables
 
149
    it contains. Mostly for debugging purposes.
 
150
]])
 
151
 
 
152
function table.deepprint(tab,seen)
 
153
    local ret = true
 
154
    if seen==nil then
 
155
        seen = {}
 
156
        seen[tab] = true
 
157
        ret = false
 
158
    end
 
159
    
 
160
    out = "{ "
 
161
    local first = true
 
162
    for k,v in pairs(tab) do
 
163
        if not first then
 
164
            out = out .. ", "
 
165
        end
 
166
        first = false
 
167
        if type(k)=='table' then
 
168
            if seen[k]==nil then
 
169
                out = out .. table.deepprint(k,seen)
 
170
            else
 
171
                out = out .. "(loop)"
 
172
            end
 
173
        else
 
174
            out = out .. tostring(k)
 
175
        end
 
176
        out = out .. " = "
 
177
        if type(v)=='table' then
 
178
            if seen[v]==nil then
 
179
                out = out .. table.deepprint(v,seen)
 
180
            else
 
181
                out = out .. "(loop)"
 
182
            end
 
183
        else
 
184
            out = out .. tostring(v)
 
185
        end
 
186
    end
 
187
    out = out .. " }"
 
188
    
 
189
    if ret then
 
190
        return out
 
191
    else
 
192
        print(out)
 
193
    end
 
194
end
 
195
 
 
196
sandboxScope(table, "deepprint", "USER")
 
197
 
 
198
 
 
199
docs([[
 
200
    table.toString(tab)
 
201
 
 
202
    Prints the contents of the table, and any tables
 
203
    it contains. Mostly for debugging purposes.
 
204
]])
 
205
 
 
206
function table.toString(tab,seen)
 
207
    local ret = true
 
208
    if seen==nil then
 
209
        seen = {}
 
210
        seen[tab] = true
 
211
        ret = false
 
212
    end
 
213
    
 
214
    out = "{ "
 
215
    local first = true
 
216
    for k,v in pairs(tab) do
 
217
        if not first then
 
218
            out = out .. ", "
 
219
        end
 
220
        first = false
 
221
        if type(k)=='table' then
 
222
            if seen[k]==nil then
 
223
                out = out .. "WTF" --table.toString(k,seen)
 
224
            else
 
225
                --out = out .. "(loop)"
 
226
            end
 
227
        else
 
228
            if type(k) == "string" then
 
229
                out = out .. '["' .. tostring(k).. '"]'
 
230
            else
 
231
                out = out .. '['..tostring(k)..']'
 
232
            end
 
233
        end
 
234
        out = out .. " = "
 
235
        if type(v)=='table' then
 
236
            if seen[v]==nil then
 
237
                out = out .. table.toString(v,seen)
 
238
            else
 
239
                --out = out .. "(loop)"
 
240
            end
 
241
        else
 
242
            if type(v) == "string" then
 
243
                out = out .. '"' .. tostring(v).. '"'
 
244
            else
 
245
                out = out ..tostring(v)
 
246
            end
 
247
        end
 
248
    end
 
249
    out = out .. " }"
 
250
    
 
251
 
 
252
    return out
 
253
end
 
254
 
 
255
sandboxScope(table, "toString", "USER")
 
256
 
 
257
 
 
258
 
 
259
 
 
260
 
 
261
 
 
262
-----------------------------------------------
 
263
 
 
264
docs([[
 
265
    result = table.copy(tab)
 
266
 
 
267
    Makes a shallow copy of the table.
 
268
]])
 
269
function table.copy(tab)
 
270
    result = {}
 
271
    for k,v in pairs(tab) do
 
272
        result[k] = v
 
273
    end
 
274
    return result
 
275
end
 
276
 
 
277
sandboxScope(table, "copy", "USER")
 
278
 
 
279
-----------------------------------------------
 
280
 
 
281
docs([[
 
282
    result = table.deepcopy(tab)
 
283
 
 
284
    Makes a deep copy of the table. The function below also 
 
285
    copies the metatable to the new table if there is one, 
 
286
    so the behaviour of the copied table is the same as the original.
 
287
]])
 
288
function table.deepcopy(tab)
 
289
    local lookup_table = {}
 
290
    local function _copy(tab)
 
291
        if type(tab) ~= "table" then
 
292
            return tab
 
293
        elseif lookup_table[tab] then
 
294
            return lookup_table[tab]
 
295
        end
 
296
        local new_table = {}
 
297
        lookup_table[tab] = new_table
 
298
        for index, value in pairs(tab) do
 
299
            new_table[_copy(index)] = _copy(value)
 
300
        end
 
301
        return setmetatable(new_table, _copy( getmetatable(object)))
 
302
    end
 
303
    return _copy(tab)
 
304
end
 
305
sandboxScope(table, "deepcopy", "KERNEL")
 
306
 
 
307
-----------------------------------------------
 
308
 
 
309
docs([[
 
310
    table.copyelts(srcTab, dstTab, keylist)
 
311
 
 
312
    For every key in keylist, copies the value
 
313
    from srcTab to dstTab.
 
314
]])
 
315
function table.copyelts(srcTab, dstTab, keylist)
 
316
    for i,value in ipairs(keylist) do
 
317
        dstTab[value] = srcTab[value]
 
318
    end
 
319
end
 
320
sandboxScope(table, "copyelts", "USER")
 
321
 
 
322
-----------------------------------------------
 
323
 
 
324
function Utils.sprintf(pattern, ...)
 
325
    return string.format(pattern, ...)
 
326
end
 
327
sandboxScope(Utils, "sprintf", "KERNEL")
 
328
 
 
329
function Utils.printf(...)
 
330
    print(Utils.sprintf(...))
 
331
end
 
332
sandboxScope(Utils, "printf", "KERNEL")
 
333
 
 
334
function Utils.splitToPathAndName(fullPath)
 
335
    fullPath = fullPath:reverse()
 
336
    local firstSlash = fullPath:find("/")
 
337
    if firstSlash == nil then
 
338
        return nil, fullPath:reverse()
 
339
    end
 
340
    local path = fullPath:sub(firstSlash):reverse()
 
341
    local name = fullPath:sub(1,firstSlash-1):reverse()
 
342
    return path,name
 
343
end
 
344
sandboxScope(Utils, "splitToPathAndName", "KERNEL")
 
345
 
 
346
do
 
347
    local printf  = Utils.printf
 
348
    local sprintf = Utils.sprintf
 
349
 
 
350
    local function checktype(value_name, value, expected)
 
351
        assert(type(value_name) == "string")
 
352
        assert(type(expected) == "string")
 
353
      
 
354
        local value_type = type(value)
 
355
      
 
356
        if (type(value)) ~= expected then
 
357
            error(("expected argument %s to be of  type %s but got type %s"):format(value_name, expected, value_type))
 
358
        end
 
359
    end
 
360
 
 
361
    local visited
 
362
    local depth = 0
 
363
    local DEPTH_STEPSIZE = 2
 
364
 
 
365
    -- increases print indenting depth
 
366
    local increase_depth = function ()
 
367
      depth = depth + DEPTH_STEPSIZE
 
368
    end
 
369
 
 
370
    -- decreases print indenting depth
 
371
    local decrease_depth = function ()
 
372
        depth = depth - DEPTH_STEPSIZE
 
373
    end
 
374
 
 
375
    -- indents a string
 
376
    local function indent(str)
 
377
        for i=1, depth do
 
378
            str = " " .. str
 
379
        end
 
380
        return str
 
381
    end
 
382
 
 
383
    -- getstring_simple(v)
 
384
    -- Gets a simple one-word string representing a value
 
385
    local getstring_simple
 
386
    do
 
387
        local funcs = {
 
388
            ["string"] = function (str)
 
389
                return ("\"%s\""):format(str)
 
390
            end,
 
391
            ["boolean"] = function (b)
 
392
                return ("%s"):format(tostring(b))
 
393
            end,
 
394
            ["number"] = function (n)
 
395
                return ("%d"):format(n)
 
396
            end,
 
397
            ["userdata"] = function (data)
 
398
                return ("%s"):format(tostring(userdata))
 
399
            end,
 
400
            ["nil"] = function ()
 
401
                return ("(%s)"):format(tostring(nil))
 
402
            end,
 
403
            ["table"] = function (t)
 
404
                return ("%s"):format(tostring(t))
 
405
            end,
 
406
            ["function"] = function (f)
 
407
                return ("%s"):format(tostring(f))
 
408
            end
 
409
        }
 
410
 
 
411
        getstring_simple = function (v)
 
412
            return funcs[type(v)](v)
 
413
        end
 
414
      
 
415
    end
 
416
 
 
417
    -- Gets a detailed string, possibly with nested printing
 
418
    local getstring_detailed
 
419
    do
 
420
        local funcs = {}
 
421
      
 
422
        funcs["string"]   = getstring_simple
 
423
        funcs["boolean"]  = getstring_simple
 
424
        funcs["number"]   = getstring_simple
 
425
        funcs["userdata"] = getstring_simple
 
426
        funcs["nil"]      = getstring_simple
 
427
        funcs["function"] = getstring_simple
 
428
        
 
429
        funcs["table"] =
 
430
            function (t)
 
431
            -- don't recur indefinitely
 
432
            if visited[t] then
 
433
                return ("(%s - nested)"):format(tostring(t))
 
434
            else
 
435
                -- mark that we've been here
 
436
                visited[t] = true
 
437
            
 
438
                local s = ("(%s ---) {\n"):format(tostring(t))
 
439
                increase_depth()
 
440
            
 
441
                -- print our contents
 
442
                for key, val in pairs(t) do
 
443
                    local line = indent("[" .. getstring_simple(key) .. "]")
 
444
                    line = ("%s = %s,\n"):format(line, getstring_detailed(val))
 
445
                    s = s .. line
 
446
                end
 
447
            
 
448
                decrease_depth()
 
449
                s = ("%s%s"):format(s, indent(("} (--- %s)"):format(tostring(t))))
 
450
            
 
451
                return s
 
452
            end
 
453
        end
 
454
      
 
455
        getstring_detailed = function(v)
 
456
            return funcs[type(v)](v)
 
457
        end
 
458
    end
 
459
 
 
460
    function Utils.dodump(label, value)
 
461
        checktype("label", label, "string")
 
462
      
 
463
        depth = 0
 
464
        visited = {}
 
465
        printf("%s = %s", getstring_simple(label), getstring_detailed(value))
 
466
      
 
467
    end
 
468
 
 
469
    -- Performs a dump on _G[global_key]. global_key should be
 
470
    -- of type string.
 
471
    function Utils.dump(global_key)
 
472
        Utils.dodump(global_key, _G[global_key])
 
473
    end
 
474
 
 
475
end
 
476
 
 
477
sandboxScope(Utils, "dodump", "KERNEL")
 
478
sandboxScope(Utils, "dump", "KERNEL")
 
479
 
 
480
alreadyTookFocus = false
 
481
docs([[
 
482
    Utils.takeFocus()
 
483
 
 
484
    Captures keyboard focus to Wild Pockets. This function may only be called from onSceneStart
 
485
    to prevent abuse, and may only be called once.
 
486
]])
 
487
function Utils.takeFocus()
 
488
    -- compare to false specifically; can also return nil
 
489
    if Kernel.isOnSceneStartCompleted() == false then
 
490
        if not alreadyTookFocus then
 
491
            Utils.kernelTakeFocus()
 
492
            alreadyTookFocus = true
 
493
        else
 
494
            warnOnce("Utils.takeFocus() may only be called once.")
 
495
        end
 
496
    else
 
497
        warnOnce("Utils.takeFocus() may only be called from onSceneStart.")
 
498
    end
 
499
end
 
500
sandboxScope(Utils, "takeFocus", "USER")
 
501
 
 
502
docs([[
 
503
    browser, version = Utils.guessBrowser()
 
504
 
 
505
    Tries to figure out what web browser the user is using.
 
506
]])
 
507
function Utils.guessBrowser()
 
508
    local a, b
 
509
    local firefoxVersion, chromeVersion, iexploreVersion, operaVersion, safariVersion
 
510
    local ua = Kernel.getPluginProperty("useragent")
 
511
    a, b, firefoxVersion = string.find(ua, "Firefox/([^%s]*)")
 
512
    a, b, chromeVersion  = string.find(ua, "Chrome/([^%s]*)")
 
513
    a, b, safariVersion  = string.find(ua, "Safari/([^%s]*)")
 
514
    a, b, operaVersion   = string.find(ua, "Opera/([^%s]*)")
 
515
    a, b, iexploreVersion = string.find(ua, "MSIE ([^;]*);")
 
516
    
 
517
    if firefoxVersion ~= nil then
 
518
        return "Firefox", firefoxVersion
 
519
    end
 
520
    if chromeVersion ~= nil then
 
521
        return "Chrome", chromeVersion
 
522
    end
 
523
    if safariVersion ~= nil then  -- after chrome check since chrome also claims safari
 
524
        return "Safari", safariVersion
 
525
    end
 
526
    if operaVersion ~= nil then
 
527
        return "Opera", operaVersion
 
528
    end
 
529
    if iexploreVersion ~= nil then
 
530
        return "Internet Explorer", iexploreVersion
 
531
    end
 
532
    return "Unknown", nil
 
533
end
 
534
sandboxScope(Utils, "guessBrowser", "KERNEL")