First commit

This commit is contained in:
rxi 2014-02-27 20:19:10 +00:00
commit 2f51dce71f
4 changed files with 464 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
__*
*.tmp
*.swp

20
LICENSE Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 2014, rxi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

209
README.md Normal file
View File

@ -0,0 +1,209 @@
# lume
A collection of handy functions for Lua, geared towards game development.
## Installation
The [lume.lua](lume.lua) file should be dropped into an existing project and
required by it:
```lua
lume = require "lume"
```
## Function reference
### lume.clamp(x, min, max)
Returns the value `x` clamped between the values `min` and `max`
### lume.round(x)
Rounds `x` to the nearest integer. Rounds towards zero if we're midway between
two integers.
### lume.sign(x)
Returns `1` if `x` is 0 or above, returns `-1` when `x` is negative.
### lume.lerp(a, b, amount)
Returns the linearly interpolated value between `a` and `b`, `amount` should be
in the range of 0 - 1; if `amount` is outside of this range it is clamped.
### lume.smooth(a, b, amount)
Similar to `lume.lerp()` but uses cosine interpolation.
### lume.pingpong(x, len)
Ping-pongs the value `x` between 0 and `len`.
### lume.distance(x1, y1, x2, y2)
Returns the distance between the two points.
### lume.angle(x1, y2, x2, y2)
Returns the angle between the two points.
### lume.random([a [, b]])
Returns a random number between `a` and `b`. If only `a` is supplied an integer
between `0` and `a` is returned. If no arguments are supplied a random number
between `0` and `1` is returned.
### lume.randomchoice(t)
Returns a random value from the supplied array
### lume.shuffle(t)
Shuffles the values of an array in place, returns the array.
### lume.array(...)
Iterates the supplied iterator and returns an array filled with the values
which it returned.
```lua
lume.array(pairs({a = 1, b = 2})) -- Returns {a, b}
```
### lume.map(t, fn)
Iterates the table `t` on all its values, replaces each value in place with the
return of `fn` when called on that value.
```lua
lume.map({1, 2, 3}, function(x) return x * 2 end) -- Returns {2, 4, 6}
```
### lume.all(t, fn)
Iterates the table `t` and calls `fn` on each value. Returns true if all the
calls to `fn` return true.
```lua
lume.all({1, 2, 1}, function(x) return x == 1 end) -- Returns false
```
### lume.any(t, fn)
Iterates the table `t` and calls `fn` on each value. Returns true if any of the
calls to `fn` return true.
```lua
lume.all({1, 2, 1}, function(x) return x == 1 end) -- Returns true
```
### lume.set(t)
Returns a copy of the array `t` with all the duplicate values removed.
```lua
lume.set({2, 1, 2, "cat", "cat"}) -- Returns {1, 2, cat}
```
### lume.reduce(t, fn [, first])
Applies `fn` on two arguments cumulative to the items of the array `t`, from
left to right, so as to reduce the array to a single value. If the `first`
argument is not supplied the accumulator is initialised to `0`
```lua
lume.reduce({1, 2, 3}, function(a, b) return a + b end) -- Returns 6
```
### lume.filter(t, fn [, isarray])
Iterates the table `t` and calls `fn` on each value. Returns a new table with
only the value which `fn` returned true. If `isarray` is true the table is
treated as an array, `isarray` is false by default.
```lua
lume.filter({1, 2, 3, 4}, function(x) return x % 2 == 0 end, true)
-- Returns {2, 4}
```
### lume.merge(t, t2 [, isarray])
Merges all the values from the table `t2` into `t` in place. If `isarray` is
true the tables are treated as arrays, `isarray` is false by default. If `t2`
overwrites the value of any key which `t` already has when both table not
treating the tables as arrays.
```lua
lume.merge({2, 3}, {4, 5}, true) -- Returns {2, 3, 4, 5}
```
### lume.find(t, value)
Returns the index/key of `value` in `t`. Returns `nil` if that value does not
exist in the table.
```lua
lume.find({"a", "b", "c"}, "b") -- Returns 2
```
### lume.once(fn, ...])
Returns a wrapper function to `fn` which takes the supplied arguments. The
wrapper function will call `fn` on the first call and do nothing on any
subsequent calls.
```lua
local f = lume.once(print, "Hello")
f() -- Prints "Hello"
f() -- Does nothing
```
### lume.slice(t [, i [, j]])
Mimics the behaviour of Lua's `string.sub`, but operates on an array rather
than a string. Creates and returns a new array of the given slice.
```lua
lume.slice({"a", "b", "c", "d", "e"}, 2, 4) -- Returns {"b", "c", "d"}
```
### lume.clone(t)
Returns a shallow copy of the table `t`.
### lume.fn(fn, ...)
Creates a wrapper function around function `fn`, automatically inserting the
arguments into `fn` which will persist every time the wrapper is called.
```lua
local f = lume.fn(print, "Hello")
f() -- Prints "Hello"
```
### lume.serialize(x)
Serialises the argument `x` into a string which can be loaded again using
`lume.deserialize()`. `x` can be a boolean, number, table or string. Circular
are not handled, all nested tables of `x` are serialised as unique tables.
```lua
lume.serialize({a = "test", b = {1, 2, 3}, false})
-- Returns "{[1]=false,["a"]="test",["b"]={[1]=1,[2]=2,[3]=3,},}"
```
### lume.deserialize(str)
Deserializes a string created by `lume.serialize()` and returns the resulting
value. This function should not be run on an untrusted string.
```lua
lume.deserialize("{1, 2, 3}") -- Returns {1, 2, 3}
```
### lume.split(str [, sep])
Splits the string `str` into words and returns a table of the sub strings. If
`sep` is provided the string will be split at any of the characters in `sep`
rather than on whitespace.
```lua
lume.split("One two three") -- Returns {"One", "two", "three}
```
### lume.trim(str [, chars])
Trims the whitespace from the start and end of the string `str` and returns the
new string. If a `chars` value is set the characters in `chars` are trimmed
rather than the whitespace.
```lua
lume.trim(" Hello ") -- Returns "Hello"
```
### lume.format(str, vars)
Returns a formatted string. The values of keys in the table `vars` can be
inserted into the string by using the form `"{key}"` in `str`
```lua
lume.format("Hello {a}, I hope {a} is {b}.", {a = "world", b = "well"})
-- Returns "Hello world, I hope world is well."
```
### lume.dostring(str)
Executes the lua code inside `str`.
```lua
lume.dostring("print('Hello!')") -- Prints "Hello!"
```
### lume.rgba(color)
Takes the 32bit integer `color` argument and returns 4 numbers, one for each
channel, with a range of 0 - 255. Useful for as the argument to
[LÖVE](http://love2d.org)'s setColor() function.
```lua
lume.rgba(0xFF304050) -- Returns 48, 64, 80, 255
```
## License
This library is free software; you can redistribute it and/or modify it under
the terms of the MIT license. See [LICENSE](LICENSE) for details.

232
lume.lua Normal file
View File

@ -0,0 +1,232 @@
--
-- lume
--
-- Copyright (c) 2014, rxi
--
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.
--
local lume = { _version = "1.0.0" }
function lume.clamp(x, min, max)
return math.max(math.min(x, max), min)
end
function lume.round(x)
return x > 0 and math.floor(x + .5) or math.ceil(x - .5)
end
function lume.sign(x)
return x < 0 and -1 or 1
end
function lume.lerp(a, b, amount)
return a + (b - a) * lume.clamp(amount, 0, 1)
end
function lume.smooth(a, b, amount)
local m = (1 - math.cos(lume.clamp(amount, 0, 1) * math.pi)) / 2
return a + (b - a) * m
end
function lume.pingpong(x, len)
return (1 - math.abs(1 - x % 2)) * (len or 1)
end
function lume.distance(x1, y1, x2, y2)
return math.sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
end
function lume.angle(x1, y1, x2, y2)
return math.atan2(x1 - x2, y1 - y2)
end
function lume.random(a, b)
if not a then a, b = 0, 1 end
if not b then b = 0 end
return a + math.random() * (b - a)
end
function lume.randomchoice(t)
return t[math.random(#t)]
end
function lume.shuffle(t)
for i = 1, #t do
local r = math.random(#t)
t[i], t[r] = t[r], t[i]
end
return t
end
function lume.array(...)
local t = {}
for x in unpack({...}) do t[#t + 1] = x end
return t
end
function lume.map(t, fn)
local rtn = {}
for k, v in pairs(t) do rtn[k] = fn(v) end
return rtn
end
function lume.all(t, fn)
for k, v in pairs(t) do
if not fn(v) then return false end
end
return true
end
function lume.any(t, fn)
for k, v in pairs(t) do
if fn(v) then return true end
end
return false
end
function lume.set(t)
local tmp = {}
for k, v in pairs(t) do tmp[v] = k end
local rtn = {}
for k, _ in pairs(tmp) do rtn[#rtn + 1] = k end
return rtn
end
function lume.reduce(t, fn, first)
local acc = first
if acc == nil then acc = 0 end
for i = 1, #t do acc = fn(acc, t[i]) end
return acc
end
function lume.filter(t, fn, isarray)
local rtn = {}
for k, v in pairs(t) do
if fn(v) then rtn[isarray and (#rtn + 1) or k] = v end
end
return rtn
end
function lume.merge(t, t2, isarray)
for k, v in pairs(t2) do
t[isarray and (#t + 1) or k] = v
end
return t
end
function lume.find(t, value)
for k, v in pairs(t) do
if v == value then return k end
end
return nil
end
function lume.once(fn, ...)
local arg = {...}
return function()
if arg == nil then return end
fn(unpack(arg))
arg = nil
end
end
function lume.slice(t, i, j)
i = i or 1
j = j and (j < 0 and (#t + j) or j) or (#t - i + 1)
local rtn = {}
for i = math.max(i, 1), math.min(j, #t) do
rtn[#rtn + 1] = t[i]
end
return rtn
end
function lume.clone(t)
rtn = {}
for k, v in pairs(t) do rtn[k] = v end
return rtn
end
function lume.fn(fn, ...)
local arg = {...}
return function() fn(unpack(arg)) end
end
function lume.serialize(x)
local f = { string = function(v) return string.format("%q", v) end,
number = tostring, boolean = tostring }
f.table = function(t)
local rtn = {}
for k, v in pairs(t) do
rtn[#rtn + 1] = "[" .. f[type(k)](k) .. "]=" .. f[type(v)](v) .. ","
end
return "{" .. table.concat(rtn) .. "}"
end
return f[type(x)](x)
end
function lume.deserialize(str)
return lume.dostring("return " .. str)
end
function lume.split(str, sep)
return lume.array(str:gmatch("([^" .. (sep or "%s") .. "]+)"))
end
function lume.trim(str, chars)
chars = chars or "%s"
return str:match("^[" .. chars .. "]*(.-)[" .. chars .. "]*$")
end
function lume.format(str, vars)
local f = function(x) return tostring(vars[x]) or "{" .. x .. "}" end
return (str:gsub("{(.-)}", f))
end
function lume.dostring(str)
return assert(loadstring(str))()
end
function lume.rgba(color)
local floor = math.floor
local a = floor((color / 2 ^ 24) % 256)
local r = floor((color / 2 ^ 16) % 256)
local g = floor((color / 2 ^ 08) % 256)
local b = floor((color) % 256)
return r, g, b, a
end
return lume