almost there with complex
45
README.md
@ -1,15 +1,21 @@
|
|||||||
# light_world.lua
|
# light_world.lua
|
||||||
|
|
||||||
This is the light modeling done by Priorblue [here](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine),
|
A library for Love2d to create a dynamic lighting system, supporting:
|
||||||
only it has been largely refactored and edited to allow for scaling and proper translation.
|
- Shadows for any shape
|
||||||
|
- Normal maps for 3d like reflections
|
||||||
|
- Glow maps
|
||||||
|
- Postshader effects
|
||||||
|
- Animations with normal maps
|
||||||
|
|
||||||
*Supports love 11.2(master branch), 0.10.1(commit 414b9b74c0eb95bfb8b5e26a11caf2b32beccca0)
|
All of this is base of a previous version made by [PriorBlue](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine),
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Copy and rename the lib folder into your project.
|
Copy and rename the lib folder into your project.
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used.
|
||||||
|
This project can be run with love to see the demonstrations in action.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local LightWorld = require "lib" --the path to where light_world is (in this repo "lib")
|
local LightWorld = require "lib" --the path to where light_world is (in this repo "lib")
|
||||||
@ -17,7 +23,7 @@ local LightWorld = require "lib" --the path to where light_world is (in this rep
|
|||||||
--create light world
|
--create light world
|
||||||
function love.load()
|
function love.load()
|
||||||
lightWorld = LightWorld({
|
lightWorld = LightWorld({
|
||||||
ambient = {55/255,55/255,55/255}, --the general ambient light in the environment
|
ambient = {0.21,0.21,0.21}, --the general ambient light in the environment
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -37,35 +43,6 @@ function love.draw()
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used. This project can be run with love to see the demonstrations in action.
|
|
||||||
|
|
||||||
### Gamera & HUMP
|
|
||||||
There are example in the example directory how to use both of these with the library.
|
|
||||||
|
|
||||||
## Features ##
|
|
||||||
* **[Preview (Video)](https://www.youtube.com/watch?v=6V5Dtsa6Nd4)**
|
|
||||||
* polygon shadow calculation [Preview](http://onepixelahead.de/love2d_polyshadow.png)
|
|
||||||
* circle shadow calculation
|
|
||||||
* image shadow calculation [Preview](http://onepixelahead.de/love2d_polyshadow18.png)
|
|
||||||
* shadow blur
|
|
||||||
* light color, range, smooth and glow [Preview](http://onepixelahead.de/love2d_polyshadow2.png)
|
|
||||||
* ambient light
|
|
||||||
* self shadowing on images with normal maps [Preview](http://onepixelahead.de/love2d_polyshadow_pixelshadow.png)
|
|
||||||
* dynamic glow effect on images and circle/poly objects [Preview](http://onepixelahead.de/love2d_polyshadow_glow.png) [Preview](http://onepixelahead.de/love2d_polyshadow15.gif)
|
|
||||||
* generate flat or gradient normal maps [Preview](http://onepixelahead.de/love2d_polyshadow7.png)
|
|
||||||
* convert height maps to normal maps [Preview](http://onepixelahead.de/love2d_polyshadow8.png)
|
|
||||||
* generate a normal map directly from the image (usually gives poor results)
|
|
||||||
* shadow color and alpha (glass) [Preview](http://onepixelahead.de/love2d_polyshadow9.png)
|
|
||||||
* directional light [Preview](http://onepixelahead.de/love2d_polyshadow12.png)
|
|
||||||
* refractions (moveable) [Preview](http://onepixelahead.de/love2d_polyshadow13.gif)
|
|
||||||
* chromatic aberration [Preview](http://onepixelahead.de/love2d_polyshadow16.gif)
|
|
||||||
* postshader with many included postshaders, plus easy to extend
|
|
||||||
* animations in tandem with normal maps thanks to [anim8](https://github.com/kikito/anim8)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
A License has been included in this project
|
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
- Jon @xiejiangzhi
|
- Jon @xiejiangzhi
|
||||||
- Brandon Blanker Lim-it @flamendless
|
- Brandon Blanker Lim-it @flamendless
|
||||||
@ -73,3 +50,5 @@ A License has been included in this project
|
|||||||
- Gustavo Kishima @gukiboy
|
- Gustavo Kishima @gukiboy
|
||||||
- Rose L. Liverman @TangentFoxy
|
- Rose L. Liverman @TangentFoxy
|
||||||
- Kyle McLamb @Alloyed
|
- Kyle McLamb @Alloyed
|
||||||
|
- @Buckle2000
|
||||||
|
- Benoit Giannangeli @giann
|
||||||
|
10
conf.lua
@ -1,9 +1,9 @@
|
|||||||
function love.conf(t)
|
function love.conf(t)
|
||||||
t.identity = nil -- The name of the save directory (string)
|
t.identity = nil -- The name of the save directory (string)
|
||||||
t.version = "11.2" -- The LÖVE version this game was made for (string)
|
t.version = "11.3" -- The LÖVE version this game was made for (string)
|
||||||
t.console = true -- Attach a console (boolean, Windows only)
|
t.console = true -- Attach a console (boolean, Windows only)
|
||||||
|
|
||||||
t.window.title = "Untitled" -- The window title (string)
|
t.window.title = "Light & Shadow" -- The window title (string)
|
||||||
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
||||||
t.window.width = 800 -- The window width (number)
|
t.window.width = 800 -- The window width (number)
|
||||||
t.window.height = 600 -- The window height (number)
|
t.window.height = 600 -- The window height (number)
|
||||||
@ -19,15 +19,15 @@ function love.conf(t)
|
|||||||
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean). Added in 0.9.1
|
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean). Added in 0.9.1
|
||||||
t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean). Added in 0.9.1
|
t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean). Added in 0.9.1
|
||||||
|
|
||||||
t.modules.audio = true -- Enable the audio module (boolean)
|
t.modules.audio = false -- Enable the audio module (boolean)
|
||||||
t.modules.event = true -- Enable the event module (boolean)
|
t.modules.event = true -- Enable the event module (boolean)
|
||||||
t.modules.graphics = true -- Enable the graphics module (boolean)
|
t.modules.graphics = true -- Enable the graphics module (boolean)
|
||||||
t.modules.image = true -- Enable the image module (boolean)
|
t.modules.image = true -- Enable the image module (boolean)
|
||||||
t.modules.joystick = true -- Enable the joystick module (boolean)
|
t.modules.joystick = false -- Enable the joystick module (boolean)
|
||||||
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
||||||
t.modules.math = true -- Enable the math module (boolean)
|
t.modules.math = true -- Enable the math module (boolean)
|
||||||
t.modules.mouse = true -- Enable the mouse module (boolean)
|
t.modules.mouse = true -- Enable the mouse module (boolean)
|
||||||
t.modules.physics = true -- Enable the physics module (boolean)
|
t.modules.physics = false -- Enable the physics module (boolean)
|
||||||
t.modules.sound = true -- Enable the sound module (boolean)
|
t.modules.sound = true -- Enable the sound module (boolean)
|
||||||
t.modules.system = true -- Enable the system module (boolean)
|
t.modules.system = true -- Enable the system module (boolean)
|
||||||
t.modules.timer = true -- Enable the timer module (boolean)
|
t.modules.timer = true -- Enable the timer module (boolean)
|
||||||
|
@ -3,8 +3,8 @@ local x, y, z, scale = 20, -55, 1, 3.5
|
|||||||
|
|
||||||
local function load()
|
local function load()
|
||||||
-- load images
|
-- load images
|
||||||
image = love.graphics.newImage("examples/gfx/scott_pilgrim.png")
|
image = love.graphics.newImage("examples/img/animation/scott_pilgrim.png")
|
||||||
image_normal = love.graphics.newImage("examples/gfx/scott_pilgrim_NRM.png")
|
image_normal = love.graphics.newImage("examples/img/animation/scott_pilgrim_NRM.png")
|
||||||
-- create light world
|
-- create light world
|
||||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||||
-- create light
|
-- create light
|
||||||
|
@ -1,172 +1,43 @@
|
|||||||
|
local gamera = require "examples/vendor/gamera"
|
||||||
local LightWorld = require "lib"
|
local LightWorld = require "lib"
|
||||||
|
local objects = {}
|
||||||
function initScene()
|
local obj = require "examples.lib.object"
|
||||||
-- physic world
|
local keyboard = require "examples.lib.keyboard"
|
||||||
physicWorld = love.physics.newWorld(0, 9.81 * 64, true)
|
local cam, font, quadScreen, imgFloor, imgLight
|
||||||
wall1 = {}
|
local lightRange = 300
|
||||||
wall1.body = love.physics.newBody(physicWorld, 400, 605, "static")
|
local lightDirection = 0.0
|
||||||
wall1.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
local colorAberration = 0.0
|
||||||
wall1.fixture = love.physics.newFixture(wall1.body, wall1.shape)
|
local lightWorld, mouseLight
|
||||||
|
|
||||||
wall2 = {}
|
|
||||||
wall2.body = love.physics.newBody(physicWorld, -5, 300, "static")
|
|
||||||
wall2.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
|
||||||
wall2.fixture = love.physics.newFixture(wall2.body, wall2.shape)
|
|
||||||
|
|
||||||
wall3 = {}
|
|
||||||
wall3.body = love.physics.newBody(physicWorld, 805, 300, "static")
|
|
||||||
wall3.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
|
||||||
wall3.fixture = love.physics.newFixture(wall3.body, wall3.shape)
|
|
||||||
|
|
||||||
wall4 = {}
|
|
||||||
wall4.body = love.physics.newBody(physicWorld, 400, -5, "static")
|
|
||||||
wall4.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
|
||||||
wall4.fixture = love.physics.newFixture(wall4.body, wall4.shape)
|
|
||||||
|
|
||||||
phyCnt = 0
|
|
||||||
phyLight = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function load()
|
local function load()
|
||||||
|
math.randomseed(love.timer.getTime())
|
||||||
|
cam = gamera.new(0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||||
love.graphics.setBackgroundColor(0, 0, 0)
|
love.graphics.setBackgroundColor(0, 0, 0)
|
||||||
love.graphics.setDefaultFilter("nearest", "nearest")
|
love.graphics.setDefaultFilter("nearest", "nearest")
|
||||||
|
font = love.graphics.newImageFont("examples/img/complex/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
|
||||||
-- load image font
|
|
||||||
font = love.graphics.newImageFont("examples/gfx/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
|
|
||||||
love.graphics.setFont(font)
|
love.graphics.setFont(font)
|
||||||
|
|
||||||
-- set background
|
|
||||||
quadScreen = love.graphics.newQuad(0, 0, love.graphics.getWidth() + 32, love.graphics.getHeight() + 24, 32, 24)
|
quadScreen = love.graphics.newQuad(0, 0, love.graphics.getWidth() + 32, love.graphics.getHeight() + 24, 32, 24)
|
||||||
imgFloor = love.graphics.newImage("examples/gfx/floor.png")
|
imgFloor = love.graphics.newImage("examples/img/complex/floor.png")
|
||||||
imgFloor:setWrap("repeat", "repeat")
|
imgFloor:setWrap("repeat", "repeat")
|
||||||
|
imgLight = love.graphics.newImage("examples/img/complex/light.png")
|
||||||
-- load image examples
|
lightWorld = LightWorld({ambient = {15,15,15}, refractionStrength = 16.0, reflectionVisibility = 0.75, shadowBlur = 2.0})
|
||||||
circle = love.graphics.newImage("examples/gfx/circle.png")
|
|
||||||
circle_normal = love.graphics.newImage("examples/gfx/circle_normal.png")
|
|
||||||
cone = love.graphics.newImage("examples/gfx/cone.png")
|
|
||||||
cone_large = love.graphics.newImage("examples/gfx/cone_large.png")
|
|
||||||
cone_large_normal = love.graphics.newImage("examples/gfx/cone_large_normal.png")
|
|
||||||
cone_normal = love.graphics.newImage("examples/gfx/cone_normal.png")
|
|
||||||
chest = love.graphics.newImage("examples/gfx/chest.png")
|
|
||||||
chest_normal = love.graphics.newImage("examples/gfx/chest_normal.png")
|
|
||||||
machine = love.graphics.newImage("examples/gfx/machine.png")
|
|
||||||
machine_normal = love.graphics.newImage("examples/gfx/machine_normal.png")
|
|
||||||
machine_glow = love.graphics.newImage("examples/gfx/machine_glow.png")
|
|
||||||
machine2 = love.graphics.newImage("examples/gfx/machine2.png")
|
|
||||||
machine2_normal = love.graphics.newImage("examples/gfx/machine2_normal.png")
|
|
||||||
machine2_glow = love.graphics.newImage("examples/gfx/machine2_glow.png")
|
|
||||||
blopp = love.graphics.newImage("examples/gfx/blopp.png")
|
|
||||||
tile = love.graphics.newImage("examples/gfx/tile.png")
|
|
||||||
tile_normal = love.graphics.newImage("examples/gfx/tile_normal.png")
|
|
||||||
tile_glow = love.graphics.newImage("examples/gfx/tile_glow.png")
|
|
||||||
refraction_normal = love.graphics.newImage("examples/gfx/refraction_normal.png")
|
|
||||||
water = love.graphics.newImage("examples/gfx/water.png")
|
|
||||||
led = love.graphics.newImage("examples/gfx/led.png")
|
|
||||||
led2 = love.graphics.newImage("examples/gfx/led2.png")
|
|
||||||
led3 = love.graphics.newImage("examples/gfx/led3.png")
|
|
||||||
led_normal = love.graphics.newImage("examples/gfx/led_normal.png")
|
|
||||||
led_glow = love.graphics.newImage("examples/gfx/led_glow.png")
|
|
||||||
led_glow2 = love.graphics.newImage("examples/gfx/led_glow2.png")
|
|
||||||
led_glow3 = love.graphics.newImage("examples/gfx/led_glow3.png")
|
|
||||||
ape = love.graphics.newImage("examples/gfx/ape.png")
|
|
||||||
ape_normal = love.graphics.newImage("examples/gfx/ape_normal.png")
|
|
||||||
ape_glow = love.graphics.newImage("examples/gfx/ape_glow.png")
|
|
||||||
imgLight = love.graphics.newImage("examples/gfx/light.png")
|
|
||||||
|
|
||||||
-- materials
|
|
||||||
material = {}
|
|
||||||
|
|
||||||
local files = love.filesystem.getDirectoryItems("examples/gfx/sphere")
|
|
||||||
for i, file in ipairs(files) do
|
|
||||||
material[i] = love.graphics.newImage("examples/gfx/sphere/" .. file)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- light world
|
|
||||||
lightRange = 400
|
|
||||||
lightSmooth = 1.0
|
|
||||||
|
|
||||||
lightWorld = LightWorld({
|
|
||||||
ambient = {15,15,15},
|
|
||||||
refractionStrength = 16.0,
|
|
||||||
reflectionVisibility = 0.75,
|
|
||||||
shadowBlur = 2.0
|
|
||||||
})
|
|
||||||
|
|
||||||
mouseLight = lightWorld:newLight(0, 0, 1, 191/ 255, 0.5, lightRange)
|
mouseLight = lightWorld:newLight(0, 0, 1, 191/ 255, 0.5, lightRange)
|
||||||
mouseLight:setGlowStrength(0.3)
|
mouseLight:setGlowStrength(0.3)
|
||||||
mouseLight:setSmooth(lightSmooth)
|
|
||||||
mouseLight.z = 63
|
mouseLight.z = 63
|
||||||
lightDirection = 0.0
|
|
||||||
colorAberration = 0.0
|
|
||||||
|
|
||||||
-- init physic world
|
|
||||||
initScene()
|
|
||||||
|
|
||||||
helpOn = false
|
|
||||||
physicOn = false
|
|
||||||
lightOn = true
|
|
||||||
gravityOn = 1
|
|
||||||
shadowBlur = 2.0
|
|
||||||
bloomOn = 0.0
|
|
||||||
textureOn = true
|
|
||||||
normalOn = false
|
|
||||||
glowBlur = 1.0
|
|
||||||
effectOn = 0.0
|
|
||||||
|
|
||||||
offsetX = 0.0
|
|
||||||
offsetY = 0.0
|
|
||||||
scale = 1.0
|
|
||||||
offsetOldX = 0.0
|
|
||||||
offsetOldY = 0.0
|
|
||||||
offsetChanged = false
|
|
||||||
|
|
||||||
tileX = 0
|
|
||||||
tileY = 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update(dt)
|
local function update(dt)
|
||||||
love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")")
|
love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")")
|
||||||
|
local x, y, scale = keyboard.update(dt)
|
||||||
mx, my = (love.mouse.getX() - offsetX)/scale, (love.mouse.getY() - offsetY)/scale
|
cam:setScale(scale)
|
||||||
|
cam:setPosition(x, y)
|
||||||
mouseLight:setPosition(mx, my, 1 + (math.sin(lightDirection)+1.0))
|
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||||
|
lightWorld:setTranslation(offsetX,offsetY, scale)
|
||||||
lightDirection = lightDirection + dt
|
lightDirection = lightDirection + dt
|
||||||
|
mouseLight:setPosition(mx, my, 1 + (math.sin(lightDirection)+1.0))
|
||||||
|
for i, o in ipairs(objects) do o:update(dt) end
|
||||||
colorAberration = math.max(0.0, colorAberration - dt * 10.0)
|
colorAberration = math.max(0.0, colorAberration - dt * 10.0)
|
||||||
|
|
||||||
if love.keyboard.isDown("up") then
|
|
||||||
offsetY = offsetY + dt * 200
|
|
||||||
elseif love.keyboard.isDown("down") then
|
|
||||||
offsetY = offsetY - dt * 200
|
|
||||||
end
|
|
||||||
|
|
||||||
if love.keyboard.isDown("left") then
|
|
||||||
offsetX = offsetX + dt * 200
|
|
||||||
elseif love.keyboard.isDown("right") then
|
|
||||||
offsetX = offsetX - dt * 200
|
|
||||||
end
|
|
||||||
|
|
||||||
if love.keyboard.isDown("-") then
|
|
||||||
scale = scale - 0.01
|
|
||||||
elseif love.keyboard.isDown("=") then
|
|
||||||
scale = scale + 0.01
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, lightWorld:getLightCount() do
|
|
||||||
lightWorld:getLight(i):setDirection(lightDirection)
|
|
||||||
end
|
|
||||||
|
|
||||||
tileX = tileX + dt * 32.0
|
|
||||||
tileY = tileY + dt * 8.0
|
|
||||||
for i = 1, phyCnt do
|
|
||||||
if phyLight[i]:getType() == "refraction" then
|
|
||||||
phyLight[i]:setNormalTileOffset(tileX, tileY)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- draw shader
|
|
||||||
if colorAberration > 0.0 then
|
if colorAberration > 0.0 then
|
||||||
-- vert / horz blur
|
|
||||||
lightWorld.post_shader:addEffect("blur", 2.0, 2.0)
|
lightWorld.post_shader:addEffect("blur", 2.0, 2.0)
|
||||||
lightWorld.post_shader:addEffect("chromatic_aberration",
|
lightWorld.post_shader:addEffect("chromatic_aberration",
|
||||||
{math.sin(lightDirection * 10.0) * colorAberration, math.cos(lightDirection * 10.0) * colorAberration},
|
{math.sin(lightDirection * 10.0) * colorAberration, math.cos(lightDirection * 10.0) * colorAberration},
|
||||||
@ -176,401 +47,76 @@ local function update(dt)
|
|||||||
lightWorld.post_shader:removeEffect("blur")
|
lightWorld.post_shader:removeEffect("blur")
|
||||||
lightWorld.post_shader:removeEffect("chromatic_aberration")
|
lightWorld.post_shader:removeEffect("chromatic_aberration")
|
||||||
end
|
end
|
||||||
|
|
||||||
if bloomOn > 0.0 then
|
|
||||||
-- blur, strength
|
|
||||||
lightWorld.post_shader:addEffect("bloom", 2.0, bloomOn)
|
|
||||||
else
|
|
||||||
lightWorld.post_shader:removeEffect("bloom")
|
|
||||||
end
|
|
||||||
lightWorld:update(dt)
|
lightWorld:update(dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function draw()
|
local function draw()
|
||||||
-- set shader buffer
|
cam:draw(function(l,t,w,h)
|
||||||
lightWorld:setTranslation(offsetX,offsetY, scale)
|
|
||||||
love.graphics.push()
|
|
||||||
love.graphics.translate(offsetX, offsetY)
|
|
||||||
love.graphics.scale(scale)
|
|
||||||
lightWorld:draw(function(l, t, w, h, s)
|
lightWorld:draw(function(l, t, w, h, s)
|
||||||
love.graphics.setBlendMode("alpha")
|
love.graphics.setBlendMode("alpha")
|
||||||
if normalOn then
|
|
||||||
love.graphics.setColor(0.5, 0.5, 1)
|
|
||||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 1, 1)
|
love.graphics.setColor(1, 1, 1)
|
||||||
if textureOn then
|
|
||||||
love.graphics.draw(imgFloor, quadScreen, 0,0)
|
love.graphics.draw(imgFloor, quadScreen, 0,0)
|
||||||
else
|
for i, ob in ipairs(objects) do ob:draw() end
|
||||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, phyCnt do
|
|
||||||
if phyLight[i]:getType() == "refraction" then
|
|
||||||
if not normalOn then
|
|
||||||
love.graphics.setBlendMode("alpha")
|
|
||||||
love.graphics.setColor(1, 1, 1, 191/255)
|
|
||||||
love.graphics.draw(water, phyLight[i].x - phyLight[i].ox, phyLight[i].y - phyLight[i].oy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setBlendMode("alpha")
|
|
||||||
for i = 1, phyCnt do
|
|
||||||
if phyLight[i]:getType() == "polygon" then
|
|
||||||
math.randomseed(i)
|
|
||||||
love.graphics.setColor(math.random(), math.random(), math.random())
|
|
||||||
love.graphics.polygon("fill", phyLight[i]:getPoints())
|
|
||||||
elseif phyLight[i]:getType() == "circle" then
|
|
||||||
math.randomseed(i)
|
|
||||||
love.graphics.setColor(math.random(), math.random(), math.random())
|
|
||||||
local cx, cy = phyLight[i]:getPosition()
|
|
||||||
love.graphics.circle("fill", cx, cy, phyLight[i]:getRadius())
|
|
||||||
elseif phyLight[i]:getType() == "image" then
|
|
||||||
if normalOn and phyLight[i].normal then
|
|
||||||
love.graphics.setColor(1, 1, 1)
|
|
||||||
love.graphics.draw(phyLight[i].normal, phyLight[i].x - phyLight[i].nx, phyLight[i].y - phyLight[i].ny)
|
|
||||||
elseif not phyLight[i].material then
|
|
||||||
math.randomseed(i)
|
|
||||||
love.graphics.setColor(
|
|
||||||
math.random(127, 255) / 255, math.random(127, 255)/ 255, math.random(127, 255) / 255
|
|
||||||
)
|
|
||||||
love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ix, phyLight[i].y - phyLight[i].iy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
love.graphics.pop()
|
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||||
|
|
||||||
love.graphics.draw(imgLight, mx - 5, (my - 5) - (16.0 + (math.sin(lightDirection) + 1.0) * 64.0))
|
love.graphics.draw(imgLight, mx - 5, (my - 5) - (16.0 + (math.sin(lightDirection) + 1.0) * 64.0))
|
||||||
|
end)
|
||||||
-- draw help
|
|
||||||
if helpOn then
|
|
||||||
love.graphics.setBlendMode("alpha")
|
love.graphics.setBlendMode("alpha")
|
||||||
love.graphics.setColor(0, 0, 0, 191)
|
|
||||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), 44)
|
|
||||||
love.graphics.rectangle("fill", 0, love.graphics.getHeight() - 68, 240, 68)
|
|
||||||
love.graphics.rectangle("fill", love.graphics.getWidth() - 244, love.graphics.getHeight() - 84, 244, 84)
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F1: Help (on)", 4 + 152 * 0, 4)
|
|
||||||
if shadowBlur >= 1.0 then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F5: Shadowblur (" .. shadowBlur .. ")", 4 + 152 * 4, 4)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F5: Shadowblur (off)", 4 + 152 * 4, 4)
|
|
||||||
end
|
|
||||||
if bloomOn > 0.0 then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F6: Bloom (" .. (bloomOn * 4) .. ")", 4 + 152 * 0, 4 + 20 * 1)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F6: Bloom (off)", 4 + 152 * 0, 4 + 20 * 1)
|
|
||||||
end
|
|
||||||
if textureOn then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F7: Texture (on)", 4 + 152 * 1, 4 + 20 * 1)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F7: Texture (off)", 4 + 152 * 1, 4 + 20 * 1)
|
|
||||||
end
|
|
||||||
if normalOn then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F8: Normal (on)", 4 + 152 * 2, 4 + 20 * 1)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F8: Normal (off)", 4 + 152 * 2, 4 + 20 * 1)
|
|
||||||
end
|
|
||||||
if glowBlur >= 1.0 then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F9: Glow Blur (" .. glowBlur .. ")", 4 + 152 * 3, 4 + 20 * 1)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F9: Glow Blur (off)", 4 + 152 * 3, 4 + 20 * 1)
|
|
||||||
end
|
|
||||||
if effectOn >= 1.0 then
|
|
||||||
love.graphics.setColor(0, 1, 0)
|
|
||||||
love.graphics.print("F10: Effects (" .. effectOn .. ")", 4 + 152 * 4, 4 + 20 * 1)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 0, 0)
|
|
||||||
love.graphics.print("F10: Effects (off)", 4 + 152 * 4, 4 + 20 * 1)
|
|
||||||
end
|
|
||||||
love.graphics.setColor(1, 0, 1)
|
|
||||||
love.graphics.print("F11: Clear obj.", 4 + 152 * 4, 4 + 20 * 2)
|
|
||||||
love.graphics.print("F12: Clear lights", 4 + 152 * 4, 4 + 20 * 3)
|
|
||||||
love.graphics.setColor(0, 0.5, 1)
|
love.graphics.setColor(0, 0.5, 1)
|
||||||
love.graphics.print("WASD Keys: Move objects", 4, love.graphics.getHeight() - 20 * 3)
|
love.graphics.print("c: chromatic abberation", 4, love.graphics.getHeight() - 20 * 6)
|
||||||
|
love.graphics.print("F1-F9: Shaders", 4, love.graphics.getHeight() - 20 * 5)
|
||||||
|
love.graphics.print("F10: Clear Bodies", 4, love.graphics.getHeight() - 20 * 4)
|
||||||
|
love.graphics.print("F11: Clear Lights", 4, love.graphics.getHeight() - 20 * 3)
|
||||||
love.graphics.print("Arrow Keys: Move map", 4, love.graphics.getHeight() - 20 * 2)
|
love.graphics.print("Arrow Keys: Move map", 4, love.graphics.getHeight() - 20 * 2)
|
||||||
love.graphics.print("0-9 Keys: Add object", 4, love.graphics.getHeight() - 20 * 1)
|
love.graphics.print("0-9 Keys: Add object", 4, love.graphics.getHeight() - 20 * 1)
|
||||||
love.graphics.setColor(1, 0.5, 0)
|
love.graphics.setColor(1, 0.5, 0)
|
||||||
love.graphics.print("M.left: Add cube", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 4)
|
love.graphics.print("M.left: Add cube", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 3)
|
||||||
love.graphics.print("M.middle: Add light", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 3)
|
love.graphics.print("M.middle: Add light", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 2)
|
||||||
love.graphics.print("M.right: Add circle", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 2)
|
love.graphics.print("M.right: Add circle", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 1)
|
||||||
love.graphics.print("M.scroll: Change smooth", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 1)
|
|
||||||
love.graphics.setColor(1, 0.5, 0)
|
|
||||||
else
|
|
||||||
love.graphics.setColor(1, 1, 1, 191/255)
|
|
||||||
love.graphics.print("F1: Help", 4, 4)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function mousepressed(x, y, c)
|
local function mousepressed(x, y, c)
|
||||||
if c == "m" then
|
if c == 3 then
|
||||||
-- add light
|
local light = lightWorld:newLight(x, y, math.random(), math.random(), math.random(), lightRange)
|
||||||
local r = lightWorld:getLightCount() % 3
|
|
||||||
local light
|
|
||||||
|
|
||||||
if r == 0 then
|
|
||||||
light = lightWorld:newLight(x, y, 31/ 255, 0.5, 63/ 255, lightRange)
|
|
||||||
elseif r == 1 then
|
|
||||||
light = lightWorld:newLight(x, y, 0.5, 63/255, 31/255, lightRange)
|
|
||||||
else
|
|
||||||
light = lightWorld:newLight(x, y, 31/255, 63/255, 127/255, lightRange)
|
|
||||||
end
|
|
||||||
light:setSmooth(lightSmooth)
|
|
||||||
light:setGlowStrength(0.3)
|
light:setGlowStrength(0.3)
|
||||||
elseif c == "l" then
|
if love.keyboard.isDown("rshift") or love.keyboard.isDown("lshift") then
|
||||||
-- add rectangle
|
light:setAngle(math.random(1, 5) * 0.1 * math.pi)
|
||||||
math.randomseed(love.timer.getTime())
|
light:setDirection(math.random(1, 5) * 0.1 * math.pi)
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
local w, h = math.random(32, 64), math.random(32, 64)
|
|
||||||
phyLight[phyCnt] = lightWorld:newPolygon(
|
|
||||||
x, y,
|
|
||||||
x+w, y,
|
|
||||||
x+w, y+h,
|
|
||||||
x, y+h
|
|
||||||
)
|
|
||||||
elseif c == "r" then
|
|
||||||
-- add circle
|
|
||||||
math.randomseed(love.timer.getTime())
|
|
||||||
cRadius = math.random(8, 32)
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newCircle(x, y, cRadius)
|
|
||||||
elseif c == "wu" then
|
|
||||||
if lightSmooth < 4.0 then
|
|
||||||
lightSmooth = lightSmooth * 1.1
|
|
||||||
mouseLight:setSmooth(lightSmooth)
|
|
||||||
end
|
|
||||||
elseif c == "wd" then
|
|
||||||
if lightSmooth > 0.5 then
|
|
||||||
lightSmooth = lightSmooth / 1.1
|
|
||||||
mouseLight:setSmooth(lightSmooth)
|
|
||||||
end
|
end
|
||||||
|
elseif c == 1 then table.insert(objects, obj.Rect:new(lightWorld, x, y, math.random(32, 64), math.random(32, 64)))
|
||||||
|
elseif c == 2 then table.insert(objects, obj.Circle:new(lightWorld, x, y, math.random(8, 32)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function keypressed(k, u)
|
local function keypressed(k, u)
|
||||||
-- debug options
|
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||||
if k == "f1" then
|
if k == "f1" then lightWorld.post_shader:toggleEffect("four_colors", {0.05, 0.21, 0.05}, {0.18, 0.38, 0.18}, {0.54, 0.67, 0.05}, {0.60, 0.73, 0.05})
|
||||||
helpOn = not helpOn
|
elseif k == "f2" then lightWorld.post_shader:toggleEffect("scanlines")
|
||||||
elseif k == "f5" then
|
elseif k == "f3" then lightWorld.post_shader:toggleEffect("bloom", 2.0, 0.25)
|
||||||
shadowBlur = math.max(1, shadowBlur * 2.0)
|
elseif k == "f4" then lightWorld.post_shader:toggleEffect("black_and_white")
|
||||||
if shadowBlur > 8.0 then
|
elseif k == "f5" then lightWorld.post_shader:toggleEffect("curvature")
|
||||||
shadowBlur = 0.0
|
elseif k == "f6" then lightWorld.post_shader:toggleEffect("edges")
|
||||||
end
|
elseif k == "f7" then lightWorld.post_shader:toggleEffect("pip")
|
||||||
lightWorld:setShadowBlur(shadowBlur)
|
elseif k == "f8" then lightWorld.post_shader:toggleEffect("pixellate")
|
||||||
elseif k == "f6" or k == "b" then
|
elseif k == "f9" then lightWorld.post_shader:toggleEffect("waterpaint")
|
||||||
bloomOn = math.max(0.25, bloomOn * 2.0)
|
|
||||||
if bloomOn > 1.0 then
|
|
||||||
bloomOn = 0.0
|
|
||||||
end
|
|
||||||
elseif k == "f7" then
|
|
||||||
textureOn = not textureOn
|
|
||||||
elseif k == "f8" then
|
|
||||||
normalOn = not normalOn
|
|
||||||
elseif k == "f9" then
|
|
||||||
glowBlur = glowBlur + 1.0
|
|
||||||
if glowBlur > 8.0 then
|
|
||||||
glowBlur = 0.0
|
|
||||||
end
|
|
||||||
lightWorld:setGlowStrength(glowBlur)
|
|
||||||
elseif k == "f10" then
|
elseif k == "f10" then
|
||||||
effectOn = effectOn + 1.0
|
|
||||||
if effectOn > 4.0 then
|
|
||||||
effectOn = 0.0
|
|
||||||
end
|
|
||||||
|
|
||||||
if effectOn == 1.0 then
|
|
||||||
lightWorld.post_shader:addEffect("four_colors", {15, 56, 15}, {48, 98, 48}, {139, 172, 15}, {155, 188, 15})
|
|
||||||
--lightWorld.post_shader:addEffect("4colors", {108, 108, 78}, {142, 139, 87}, {195, 196, 165}, {227, 230, 201})
|
|
||||||
else
|
|
||||||
lightWorld.post_shader:removeEffect("four_colors")
|
|
||||||
end
|
|
||||||
|
|
||||||
if effectOn == 2.0 then
|
|
||||||
lightWorld.post_shader:addEffect("monochrome")
|
|
||||||
else
|
|
||||||
lightWorld.post_shader:removeEffect("monochrome")
|
|
||||||
end
|
|
||||||
|
|
||||||
if effectOn == 3.0 then
|
|
||||||
lightWorld.post_shader:addEffect("scanlines")
|
|
||||||
else
|
|
||||||
lightWorld.post_shader:removeEffect("scanlines")
|
|
||||||
end
|
|
||||||
|
|
||||||
if effectOn == 4.0 then
|
|
||||||
lightWorld.post_shader:addEffect("tilt_shift", 4.0)
|
|
||||||
else
|
|
||||||
lightWorld.post_shader:removeEffect("tilt_shift")
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif k == "f11" then
|
|
||||||
physicWorld:destroy()
|
|
||||||
lightWorld:clearBodies()
|
lightWorld:clearBodies()
|
||||||
initScene()
|
objects = {}
|
||||||
elseif k == "f12" then
|
elseif k == "f11" then
|
||||||
lightWorld:clearLights()
|
lightWorld:clearLights()
|
||||||
mouseLight = lightWorld:newLight(0, 0, 1, 191/255, 0.5, lightRange)
|
mouseLight = lightWorld:newLight(0, 0, 1, 191/255, 0.5, lightRange)
|
||||||
mouseLight:setGlowStrength(0.3)
|
mouseLight:setGlowStrength(0.3)
|
||||||
mouseLight:setSmooth(lightSmooth)
|
elseif k == "1" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/ape", mx, my, "image"))
|
||||||
elseif k == "1" then
|
elseif k == "2" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/chest", mx, my))
|
||||||
-- add image
|
elseif k == "3" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cone", mx, my, "circle"))
|
||||||
phyCnt = phyCnt + 1
|
elseif k == "4" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cube", mx, my))
|
||||||
phyLight[phyCnt] = lightWorld:newImage(circle, mx, my)
|
elseif k == "5" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cylinder", mx, my, "circle"))
|
||||||
phyLight[phyCnt]:setNormalMap(circle_normal)
|
elseif k == "6" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen1", mx, my))
|
||||||
phyLight[phyCnt]:setShadowType("circle", 16)
|
elseif k == "7" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen2", mx, my))
|
||||||
elseif k == "2" then
|
elseif k == "8" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen3", mx, my))
|
||||||
local r = lightWorld:getBodyCount() % 2
|
elseif k == "9" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/tile", mx, my))
|
||||||
if r == 0 then
|
elseif k == "0" then table.insert(objects, obj.Refraction:new(lightWorld, "examples/img/complex/water", mx, my))
|
||||||
-- add image
|
elseif k == "c" then colorAberration = 3.0
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(cone, mx, my, 24, 12, 12, 16)
|
|
||||||
phyLight[phyCnt]:setNormalMap(cone_normal)
|
|
||||||
phyLight[phyCnt]:setShadowType("circle", 12)
|
|
||||||
elseif r == 1 then
|
|
||||||
-- add image
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(chest, mx, my, 32, 24, 16, 0)
|
|
||||||
phyLight[phyCnt]:setNormalMap(chest_normal)
|
|
||||||
end
|
|
||||||
elseif k == "3" then
|
|
||||||
-- add image
|
|
||||||
local r = lightWorld:getBodyCount() % #material
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(ape, mx, my, 160, 128, 80, 64)
|
|
||||||
phyLight[phyCnt]:setNormalMap(ape_normal)
|
|
||||||
if r == 3 then
|
|
||||||
phyLight[phyCnt]:setGlowMap(ape_glow)
|
|
||||||
end
|
|
||||||
phyLight[phyCnt]:setMaterial(material[r + 1])
|
|
||||||
phyLight[phyCnt]:setShadowType("image", 0, -16, 0.0)
|
|
||||||
elseif k == "4" then
|
|
||||||
-- add glow image
|
|
||||||
local r = lightWorld:getBodyCount() % 5
|
|
||||||
if r == 0 then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(machine, mx, my, 32, 24, 16, 0)
|
|
||||||
phyLight[phyCnt]:setNormalMap(machine_normal)
|
|
||||||
phyLight[phyCnt]:setGlowMap(machine_glow)
|
|
||||||
elseif r == 1 then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(machine2, mx, my, 24, 12, 12, -4)
|
|
||||||
phyLight[phyCnt]:setNormalMap(machine2_normal)
|
|
||||||
phyLight[phyCnt]:setGlowMap(machine2_glow)
|
|
||||||
elseif r == 2 then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(led, mx, my, 32, 6, 16, -8)
|
|
||||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
|
||||||
phyLight[phyCnt]:setGlowMap(led_glow)
|
|
||||||
elseif r == 3 then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(led2, mx, my, 32, 6, 16, -8)
|
|
||||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
|
||||||
phyLight[phyCnt]:setGlowMap(led_glow2)
|
|
||||||
elseif r == 4 then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(led3, mx, my, 32, 6, 16, -8)
|
|
||||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
|
||||||
phyLight[phyCnt]:setGlowMap(led_glow3)
|
|
||||||
end
|
|
||||||
elseif k == "5" then
|
|
||||||
-- add image
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(cone_large, mx, my, 24, 128, 12, 64)
|
|
||||||
phyLight[phyCnt]:setNormalMap(cone_large_normal)
|
|
||||||
phyLight[phyCnt]:setShadowType("image", 0, -6, 0.0)
|
|
||||||
elseif k == "6" then
|
|
||||||
-- add image
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(blopp, mx, my, 42, 16, 21, 0)
|
|
||||||
phyLight[phyCnt]:generateNormalMapGradient("gradient", "gradient")
|
|
||||||
phyLight[phyCnt]:setAlpha(0.5)
|
|
||||||
elseif k == "7" then
|
|
||||||
-- add image
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newImage(tile, mx, my)
|
|
||||||
phyLight[phyCnt]:setHeightMap(tile_normal, 2.0)
|
|
||||||
phyLight[phyCnt]:setGlowMap(tile_glow)
|
|
||||||
phyLight[phyCnt]:setShadow(false)
|
|
||||||
phyLight[phyCnt].reflective = false
|
|
||||||
elseif k == "8" then
|
|
||||||
-- add rectangle
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
local w, h = math.random(32, 64), math.random(32, 64)
|
|
||||||
phyLight[phyCnt] = lightWorld:newPolygon(
|
|
||||||
mx, my,
|
|
||||||
mx+w, my,
|
|
||||||
mx+w, my+h,
|
|
||||||
mx, my+h
|
|
||||||
)
|
|
||||||
phyLight[phyCnt]:setAlpha(0.5)
|
|
||||||
phyLight[phyCnt]:setGlowStrength(1.0)
|
|
||||||
math.randomseed(phyCnt)
|
|
||||||
phyLight[phyCnt]:setGlowColor(math.random(), math.random(), math.random())
|
|
||||||
math.randomseed(phyCnt)
|
|
||||||
phyLight[phyCnt]:setColor(math.random(), math.random(), math.random())
|
|
||||||
elseif k == "9" then
|
|
||||||
-- add circle
|
|
||||||
math.randomseed(love.timer.getTime())
|
|
||||||
cRadius = math.random(8, 32)
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newCircle(mx, my, cRadius)
|
|
||||||
phyLight[phyCnt]:setAlpha(0.5)
|
|
||||||
phyLight[phyCnt]:setGlowStrength(1.0)
|
|
||||||
math.randomseed(phyCnt)
|
|
||||||
phyLight[phyCnt]:setGlowColor(math.random(), math.random(), math.random())
|
|
||||||
math.randomseed(phyCnt)
|
|
||||||
phyLight[phyCnt]:setColor(math.random(), math.random(), math.random())
|
|
||||||
elseif k == "0" then
|
|
||||||
phyCnt = phyCnt + 1
|
|
||||||
phyLight[phyCnt] = lightWorld:newRefraction(refraction_normal, mx, my)
|
|
||||||
phyLight[phyCnt]:setReflection(true)
|
|
||||||
elseif k == "k" then
|
|
||||||
-- add light
|
|
||||||
local r = lightWorld:getLightCount() % 3
|
|
||||||
local light
|
|
||||||
|
|
||||||
if r == 0 then
|
|
||||||
light = lightWorld:newLight(mx, my, 31/255, 127 / 255, 63 / 255, lightRange)
|
|
||||||
elseif r == 1 then
|
|
||||||
light = lightWorld:newLight(mx, my, 127 / 255, 63 / 255, 31 / 255, lightRange)
|
|
||||||
else
|
|
||||||
light = lightWorld:newLight(mx, my, 31 / 255, 63 / 255, 127 / 255, lightRange)
|
|
||||||
end
|
|
||||||
light:setSmooth(lightSmooth)
|
|
||||||
light:setGlowStrength(0.3)
|
|
||||||
elseif k == "l" then
|
|
||||||
-- add light
|
|
||||||
local r = lightWorld:getLightCount() % 3
|
|
||||||
local light
|
|
||||||
|
|
||||||
if r == 0 then
|
|
||||||
light = lightWorld:newLight(mx, my, 31/255, 127/255, 63/255, lightRange)
|
|
||||||
elseif r == 1 then
|
|
||||||
light = lightWorld:newLight(mx, my, 127/255, 63/255, 31/255, lightRange)
|
|
||||||
else
|
|
||||||
light = lightWorld:newLight(mx, my, 31, 63, 127, lightRange)
|
|
||||||
end
|
|
||||||
light:setSmooth(lightSmooth)
|
|
||||||
light:setGlowStrength(0.3)
|
|
||||||
math.randomseed(love.timer.getTime())
|
|
||||||
light:setAngle(math.random(1, 5) * 0.1 * math.pi)
|
|
||||||
elseif k == "c" then
|
|
||||||
if colorAberration == 0.0 then
|
|
||||||
colorAberration = 3.0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
local List = require('examples.lib.list')
|
local List = require('examples.lib.list')
|
||||||
local LightWorld = require('lib')
|
local LightWorld = require('lib')
|
||||||
local examples = {
|
local examples = {
|
||||||
["Animation Example"] = "animation.lua",
|
{"Simple", "simple.lua"},
|
||||||
["Complex Example"] = "complex.lua",
|
{"Gamera", "gamera.lua"},
|
||||||
["Gamera Example"] = "gamera.lua",
|
{"Hump", "hump.lua"},
|
||||||
["Hump Example"] = "hump.lua",
|
{"Normal Map", "normalMap.lua"},
|
||||||
["Normal Map Example"] = "normalMap.lua",
|
{"Animation", "animation.lua"},
|
||||||
["Only Postshader Example"] = "postshaders.lua",
|
{"STI Example", "simple_tiled_impl.lua"},
|
||||||
["Simple Example"] = "simple.lua",
|
{"Only Postshader Example", "postshaders.lua"},
|
||||||
["STI Example"] = "simple_tiled_impl.lua",
|
{"Complex Example", "complex.lua"},
|
||||||
}
|
}
|
||||||
local list, smallfont, bigfont, bigball, lightWorld, lightMouse
|
local list, smallfont, bigfont, bigball, lightWorld, lightMouse
|
||||||
|
|
||||||
@ -34,12 +34,9 @@ local function load()
|
|||||||
smallfont = love.graphics.newFont(12)
|
smallfont = love.graphics.newFont(12)
|
||||||
bigfont = love.graphics.newFont(24)
|
bigfont = love.graphics.newFont(24)
|
||||||
list.font = smallfont
|
list.font = smallfont
|
||||||
bigball = love.graphics.newImage("examples/gfx/love-big-ball.png")
|
bigball = love.graphics.newImage("examples/img/love-big-ball.png")
|
||||||
local n = 0
|
for n, v in ipairs(examples) do
|
||||||
for c, v in pairs(examples) do
|
list:add(string.format("%04d", n).." "..v[1].." ("..v[2]..")", function() start(v[2]) end)
|
||||||
n = n + 1
|
|
||||||
local title = string.format("%04d", n) .. " " .. c .. " (" .. v .. ")"
|
|
||||||
list:add(title, v, function() start(v) end)
|
|
||||||
end
|
end
|
||||||
love.window.setTitle("LOVE Example Browser")
|
love.window.setTitle("LOVE Example Browser")
|
||||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 990 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 967 B After Width: | Height: | Size: 967 B |
Before Width: | Height: | Size: 1019 B After Width: | Height: | Size: 1019 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
examples/img/complex/screen3/normal.png
Normal file
After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1018 B After Width: | Height: | Size: 1018 B |
Before Width: | Height: | Size: 1012 B After Width: | Height: | Size: 1012 B |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
BIN
examples/img/simple/machine.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
examples/img/simple/machine_glow.png
Normal file
After Width: | Height: | Size: 990 B |
BIN
examples/img/simple/machine_normal.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@ -10,10 +10,10 @@ function List:new(x, y, w, h)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:add(item, file, cb)
|
function List:add(label, cb)
|
||||||
local x, y = self.x+2, self.y+((self.h+1)*(#self.items-1)+1)
|
local x, y = self.x+2, self.y+((self.h+1)*(#self.items-1)+1)
|
||||||
local w, h = self.w-3, self.h
|
local w, h = self.w-3, self.h
|
||||||
table.insert(self.items, {item = item, file = file, cb = cb, x = x, y = y, w = w, h = h, hover = false})
|
table.insert(self.items, {label = label, cb = cb, x = x, y = y, w = w, h = h, hover = false})
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:update(dt)
|
function List:update(dt)
|
||||||
@ -36,7 +36,7 @@ function List:draw()
|
|||||||
love.graphics.setColor(0, 0, 0, item.hover and 0.49 or 0.24)
|
love.graphics.setColor(0, 0, 0, item.hover and 0.49 or 0.24)
|
||||||
love.graphics.rectangle("fill", item.x+1, item.y+1, item.w-3, item.h)
|
love.graphics.rectangle("fill", item.x+1, item.y+1, item.w-3, item.h)
|
||||||
love.graphics.setColor(1, 1, 1, item.hover and 1 or 0.49)
|
love.graphics.setColor(1, 1, 1, item.hover and 1 or 0.49)
|
||||||
love.graphics.print(item.item, item.x+10, item.y+6)
|
love.graphics.print(item.label, item.x+10, item.y+6)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
120
examples/lib/object.lua
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
local inspect = require 'examples.vendor.inspect'
|
||||||
|
local ImageObject, Rect, Circle, Refraction = {}, {}, {}, {}
|
||||||
|
ImageObject.__index = ImageObject
|
||||||
|
Rect.__index = Rect
|
||||||
|
Circle.__index = Circle
|
||||||
|
Refraction.__index = Refraction
|
||||||
|
local imageCache = {}
|
||||||
|
|
||||||
|
local function loadImg(path)
|
||||||
|
if imageCache[path] == nil and love.filesystem.getInfo(path) ~= nil then
|
||||||
|
imageCache[path] = love.graphics.newImage(path)
|
||||||
|
end
|
||||||
|
return imageCache[path]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadMaterials(path)
|
||||||
|
if imageCache[path] == nil and love.filesystem.getInfo(path) ~= nil then
|
||||||
|
imageCache[path] = {}
|
||||||
|
local files = love.filesystem.getDirectoryItems(path)
|
||||||
|
for i, file in ipairs(files) do
|
||||||
|
imageCache[path][i] = loadImg(path .."/" .. file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return imageCache[path]
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImageObject:new(lightWorld, path, x, y, shadowType)
|
||||||
|
o = {x = x, y = y, shadowType = shadowType}
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.base = loadImg(path .. "/base.png")
|
||||||
|
o.normal = loadImg(path .. "/normal.png")
|
||||||
|
o.glow = loadImg(path .. "/glow.png")
|
||||||
|
o.materials = loadMaterials(path .. "/materials")
|
||||||
|
o.body = lightWorld:newImage(o.base, x, y)
|
||||||
|
o.x, o.y = o.x - o.base:getWidth() * 0.5, o.y - o.base:getHeight() * 0.5
|
||||||
|
if o.normal ~= nil then o.body:setNormalMap(o.normal) end
|
||||||
|
if o.glow ~= nil then o.body:setGlowMap(o.glow) end
|
||||||
|
if shadowType ~= nil then
|
||||||
|
o.body:setShadowType(shadowType)
|
||||||
|
end
|
||||||
|
if o.materials ~= nil and #o.materials > 0 then
|
||||||
|
o.body:setMaterial(o.materials[math.random(1, #o.materials-1)])
|
||||||
|
end
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function ImageObject:update(dt) end
|
||||||
|
|
||||||
|
function ImageObject:draw()
|
||||||
|
love.graphics.setColor(1, 1, 1)
|
||||||
|
love.graphics.draw(self.base, self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Rect:new(lightWorld, x, y, w, h)
|
||||||
|
local w, h = math.random(32, 64), math.random(32, 64)
|
||||||
|
local r, g, b = math.random(), math.random(), math.random()
|
||||||
|
o = {x = x, y = y, w = w, h = h, r = r, g = g, b = b}
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.body = lightWorld:newRectangle(x, y, w, h)
|
||||||
|
o.x, o.y = o.x - o.w * 0.5, o.y - o.h * 0.5
|
||||||
|
o.body:setGlowStrength(1.0)
|
||||||
|
o.body:setGlowColor(math.random(), math.random(), math.random())
|
||||||
|
o.body:setColor(r, g, b)
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function Rect:update(dt) end
|
||||||
|
|
||||||
|
function Rect:draw()
|
||||||
|
love.graphics.setColor(self.r, self.g, self.b)
|
||||||
|
love.graphics.rectangle("fill", self.x, self.y, self.w, self.h)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Circle:new(lightWorld, x, y, rad)
|
||||||
|
local r, g, b = math.random(), math.random(), math.random()
|
||||||
|
o = {x = x, y = y, rad = rad, r = r, g = g, b = b}
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.body = lightWorld:newCircle(x, y, rad)
|
||||||
|
o.body:setGlowStrength(1.0)
|
||||||
|
o.body:setGlowColor(math.random(), math.random(), math.random())
|
||||||
|
o.body:setColor(r, g, b)
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function Circle:update(dt) end
|
||||||
|
|
||||||
|
function Circle:draw()
|
||||||
|
love.graphics.setColor(self.r, self.g, self.b)
|
||||||
|
love.graphics.circle("fill", self.x, self.y, self.rad)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Refraction:new(lightWorld, path, x, y)
|
||||||
|
o = {x = x, y = y, tx = 0, ty = 0}
|
||||||
|
setmetatable(o, self)
|
||||||
|
o.base = loadImg(path .. "/base.png")
|
||||||
|
o.normal = loadImg(path .. "/normal.png")
|
||||||
|
o.body = lightWorld:newRefraction(o.normal, x, y)
|
||||||
|
o.x, o.y = o.x - o.base:getWidth() * 0.5, o.y - o.base:getHeight() * 0.5
|
||||||
|
o.body:setReflection(true)
|
||||||
|
return o
|
||||||
|
end
|
||||||
|
|
||||||
|
function Refraction:update(dt)
|
||||||
|
self.tx = self.tx + dt * 32.0
|
||||||
|
self.ty = self.ty + dt * 8.0
|
||||||
|
self.body:setNormalTileOffset(self.tx, self.ty)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Refraction:draw()
|
||||||
|
love.graphics.setBlendMode("alpha")
|
||||||
|
love.graphics.setColor(1, 1, 1, 0.74)
|
||||||
|
love.graphics.draw(self.base, self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
ImageObject = ImageObject,
|
||||||
|
Rect = Rect,
|
||||||
|
Circle = Circle,
|
||||||
|
Refraction = Refraction,
|
||||||
|
}
|
@ -5,8 +5,8 @@ local lightWorld, lightMouse
|
|||||||
|
|
||||||
local function load()
|
local function load()
|
||||||
-- load images
|
-- load images
|
||||||
image = love.graphics.newImage("examples/gfx/rock.png")
|
image = love.graphics.newImage("examples/img/normalMap/rock.png")
|
||||||
image_normal = love.graphics.newImage("examples/gfx/rock_n.png")
|
image_normal = love.graphics.newImage("examples/img/normalMap/normal.png")
|
||||||
-- create light world
|
-- create light world
|
||||||
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
||||||
-- create light
|
-- create light
|
||||||
|
@ -6,7 +6,7 @@ local img
|
|||||||
local function load()
|
local function load()
|
||||||
post_shader = PostShader()
|
post_shader = PostShader()
|
||||||
render_buffer = love.graphics.newCanvas(love.graphics.getWidth(), love.graphics.getHeight())
|
render_buffer = love.graphics.newCanvas(love.graphics.getWidth(), love.graphics.getHeight())
|
||||||
img = love.graphics.newImage("examples/gfx/kingscard.jpeg")
|
img = love.graphics.newImage("examples/img/postshaders/kingscard.jpeg")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function keypressed(k)
|
local function keypressed(k)
|
||||||
|
@ -12,9 +12,9 @@ local box_locations = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local function load()
|
local function load()
|
||||||
image = love.graphics.newImage("examples/gfx/machine.png")
|
image = love.graphics.newImage("examples/img/simple/machine.png")
|
||||||
normal = love.graphics.newImage("examples/gfx/machine_normal.png")
|
normal = love.graphics.newImage("examples/img/simple/machine_normal.png")
|
||||||
glow = love.graphics.newImage("examples/gfx/machine_glow.png")
|
glow = love.graphics.newImage("examples/img/simple/machine_glow.png")
|
||||||
-- create light world
|
-- create light world
|
||||||
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
||||||
-- create light
|
-- create light
|
||||||
|
@ -5,8 +5,8 @@ local lightWorld, map, image_normal, lightMouse
|
|||||||
local function load()
|
local function load()
|
||||||
-- create light world
|
-- create light world
|
||||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||||
map = sti.new("examples/gfx/map.lua")
|
map = sti.new("examples/img/sti/map.lua")
|
||||||
image_normal = love.graphics.newImage("examples/gfx/border_NRM.png")
|
image_normal = love.graphics.newImage("examples/img/sti/border_NRM.png")
|
||||||
-- create light
|
-- create light
|
||||||
lightMouse = lightWorld:newLight(0, 0, 1, 0.49, 0.24, 300)
|
lightMouse = lightWorld:newLight(0, 0, 1, 0.49, 0.24, 300)
|
||||||
lightMouse:setGlowStrength(0.3)
|
lightMouse:setGlowStrength(0.3)
|
||||||
|
330
examples/vendor/inspect.lua
vendored
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
local inspect ={
|
||||||
|
_VERSION = 'inspect.lua 3.1.0',
|
||||||
|
_URL = 'http://github.com/kikito/inspect.lua',
|
||||||
|
_DESCRIPTION = 'human-readable representations of tables',
|
||||||
|
_LICENSE = [[
|
||||||
|
MIT LICENSE
|
||||||
|
Copyright (c) 2013 Enrique García Cota
|
||||||
|
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.
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
|
||||||
|
local tostring = tostring
|
||||||
|
|
||||||
|
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
|
||||||
|
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
|
||||||
|
|
||||||
|
local function rawpairs(t)
|
||||||
|
return next, t, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||||
|
-- Otherwise, it returns a regular quoted string
|
||||||
|
local function smartQuote(str)
|
||||||
|
if str:match('"') and not str:match("'") then
|
||||||
|
return "'" .. str .. "'"
|
||||||
|
end
|
||||||
|
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- \a => '\\a', \0 => nil
|
||||||
|
local shortControlCharEscapes = {
|
||||||
|
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||||
|
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127",
|
||||||
|
}
|
||||||
|
local longControlCharEscapes = {["\127"]="\127"} -- \a => nil, \0 => \000, 31 => \031
|
||||||
|
for i=0, 31 do
|
||||||
|
local ch = string.char(i)
|
||||||
|
if not shortControlCharEscapes[ch] then
|
||||||
|
shortControlCharEscapes[ch] = "\\"..i
|
||||||
|
longControlCharEscapes[ch] = string.format("\\%03d", i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--longControlCharEscapes["\127"]="\\127"
|
||||||
|
|
||||||
|
local function escape(str)
|
||||||
|
return (str:gsub("\\", "\\\\")
|
||||||
|
:gsub("(%c)%f[0-9]", longControlCharEscapes)
|
||||||
|
:gsub("%c", shortControlCharEscapes))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isIdentifier(str)
|
||||||
|
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isSequenceKey(k, sequenceLength)
|
||||||
|
return type(k) == 'number'
|
||||||
|
and 1 <= k
|
||||||
|
and k <= sequenceLength
|
||||||
|
and math.floor(k) == k
|
||||||
|
end
|
||||||
|
|
||||||
|
local defaultTypeOrders = {
|
||||||
|
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||||
|
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
local function sortKeys(a, b)
|
||||||
|
local ta, tb = type(a), type(b)
|
||||||
|
|
||||||
|
-- strings and numbers are sorted numerically/alphabetically
|
||||||
|
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||||
|
|
||||||
|
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||||
|
-- Two default types are compared according to the defaultTypeOrders table
|
||||||
|
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||||
|
elseif dta then return true -- default types before custom ones
|
||||||
|
elseif dtb then return false -- custom types after default ones
|
||||||
|
end
|
||||||
|
|
||||||
|
-- custom types are sorted out alphabetically
|
||||||
|
return ta < tb
|
||||||
|
end
|
||||||
|
|
||||||
|
-- For implementation reasons, the behavior of rawlen & # is "undefined" when
|
||||||
|
-- tables aren't pure sequences. So we implement our own # operator.
|
||||||
|
local function getSequenceLength(t)
|
||||||
|
local len = 1
|
||||||
|
local v = rawget(t,len)
|
||||||
|
while v ~= nil do
|
||||||
|
len = len + 1
|
||||||
|
v = rawget(t,len)
|
||||||
|
end
|
||||||
|
return len - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getNonSequentialKeys(t)
|
||||||
|
local keys, keysLength = {}, 0
|
||||||
|
local sequenceLength = getSequenceLength(t)
|
||||||
|
for k,_ in rawpairs(t) do
|
||||||
|
if not isSequenceKey(k, sequenceLength) then
|
||||||
|
keysLength = keysLength + 1
|
||||||
|
keys[keysLength] = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(keys, sortKeys)
|
||||||
|
return keys, keysLength, sequenceLength
|
||||||
|
end
|
||||||
|
|
||||||
|
local function countTableAppearances(t, tableAppearances)
|
||||||
|
tableAppearances = tableAppearances or {}
|
||||||
|
|
||||||
|
if type(t) == 'table' then
|
||||||
|
if not tableAppearances[t] then
|
||||||
|
tableAppearances[t] = 1
|
||||||
|
for k,v in rawpairs(t) do
|
||||||
|
countTableAppearances(k, tableAppearances)
|
||||||
|
countTableAppearances(v, tableAppearances)
|
||||||
|
end
|
||||||
|
countTableAppearances(getmetatable(t), tableAppearances)
|
||||||
|
else
|
||||||
|
tableAppearances[t] = tableAppearances[t] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tableAppearances
|
||||||
|
end
|
||||||
|
|
||||||
|
local copySequence = function(s)
|
||||||
|
local copy, len = {}, #s
|
||||||
|
for i=1, len do copy[i] = s[i] end
|
||||||
|
return copy, len
|
||||||
|
end
|
||||||
|
|
||||||
|
local function makePath(path, ...)
|
||||||
|
local keys = {...}
|
||||||
|
local newPath, len = copySequence(path)
|
||||||
|
for i=1, #keys do
|
||||||
|
newPath[len + i] = keys[i]
|
||||||
|
end
|
||||||
|
return newPath
|
||||||
|
end
|
||||||
|
|
||||||
|
local function processRecursive(process, item, path, visited)
|
||||||
|
if item == nil then return nil end
|
||||||
|
if visited[item] then return visited[item] end
|
||||||
|
|
||||||
|
local processed = process(item, path)
|
||||||
|
if type(processed) == 'table' then
|
||||||
|
local processedCopy = {}
|
||||||
|
visited[item] = processedCopy
|
||||||
|
local processedKey
|
||||||
|
|
||||||
|
for k,v in rawpairs(processed) do
|
||||||
|
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
||||||
|
if processedKey ~= nil then
|
||||||
|
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
||||||
|
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
|
||||||
|
setmetatable(processedCopy, mt)
|
||||||
|
processed = processedCopy
|
||||||
|
end
|
||||||
|
return processed
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Inspector = {}
|
||||||
|
local Inspector_mt = {__index = Inspector}
|
||||||
|
|
||||||
|
function Inspector:puts(...)
|
||||||
|
local args = {...}
|
||||||
|
local buffer = self.buffer
|
||||||
|
local len = #buffer
|
||||||
|
for i=1, #args do
|
||||||
|
len = len + 1
|
||||||
|
buffer[len] = args[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:down(f)
|
||||||
|
self.level = self.level + 1
|
||||||
|
f()
|
||||||
|
self.level = self.level - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:tabify()
|
||||||
|
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:alreadyVisited(v)
|
||||||
|
return self.ids[v] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:getId(v)
|
||||||
|
local id = self.ids[v]
|
||||||
|
if not id then
|
||||||
|
local tv = type(v)
|
||||||
|
id = (self.maxIds[tv] or 0) + 1
|
||||||
|
self.maxIds[tv] = id
|
||||||
|
self.ids[v] = id
|
||||||
|
end
|
||||||
|
return tostring(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putKey(k)
|
||||||
|
if isIdentifier(k) then return self:puts(k) end
|
||||||
|
self:puts("[")
|
||||||
|
self:putValue(k)
|
||||||
|
self:puts("]")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putTable(t)
|
||||||
|
if t == inspect.KEY or t == inspect.METATABLE then
|
||||||
|
self:puts(tostring(t))
|
||||||
|
elseif self:alreadyVisited(t) then
|
||||||
|
self:puts('<table ', self:getId(t), '>')
|
||||||
|
elseif self.level >= self.depth then
|
||||||
|
self:puts('{...}')
|
||||||
|
else
|
||||||
|
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
||||||
|
|
||||||
|
local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
|
||||||
|
local mt = getmetatable(t)
|
||||||
|
|
||||||
|
self:puts('{')
|
||||||
|
self:down(function()
|
||||||
|
local count = 0
|
||||||
|
for i=1, sequenceLength do
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:puts(' ')
|
||||||
|
self:putValue(t[i])
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1, nonSequentialKeysLength do
|
||||||
|
local k = nonSequentialKeys[i]
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:tabify()
|
||||||
|
self:putKey(k)
|
||||||
|
self:puts(' = ')
|
||||||
|
self:putValue(t[k])
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(mt) == 'table' then
|
||||||
|
if count > 0 then self:puts(',') end
|
||||||
|
self:tabify()
|
||||||
|
self:puts('<metatable> = ')
|
||||||
|
self:putValue(mt)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
|
||||||
|
self:tabify()
|
||||||
|
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
||||||
|
self:puts(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
self:puts('}')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Inspector:putValue(v)
|
||||||
|
local tv = type(v)
|
||||||
|
|
||||||
|
if tv == 'string' then
|
||||||
|
self:puts(smartQuote(escape(v)))
|
||||||
|
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
|
||||||
|
tv == 'cdata' or tv == 'ctype' then
|
||||||
|
self:puts(tostring(v))
|
||||||
|
elseif tv == 'table' then
|
||||||
|
self:putTable(v)
|
||||||
|
else
|
||||||
|
self:puts('<', tv, ' ', self:getId(v), '>')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
function inspect.inspect(root, options)
|
||||||
|
options = options or {}
|
||||||
|
|
||||||
|
local depth = options.depth or math.huge
|
||||||
|
local newline = options.newline or '\n'
|
||||||
|
local indent = options.indent or ' '
|
||||||
|
local process = options.process
|
||||||
|
|
||||||
|
if process then
|
||||||
|
root = processRecursive(process, root, {}, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
local inspector = setmetatable({
|
||||||
|
depth = depth,
|
||||||
|
level = 0,
|
||||||
|
buffer = {},
|
||||||
|
ids = {},
|
||||||
|
maxIds = {},
|
||||||
|
newline = newline,
|
||||||
|
indent = indent,
|
||||||
|
tableAppearances = countTableAppearances(root)
|
||||||
|
}, Inspector_mt)
|
||||||
|
|
||||||
|
inspector:putValue(root)
|
||||||
|
|
||||||
|
return table.concat(inspector.buffer)
|
||||||
|
end
|
||||||
|
|
||||||
|
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||||
|
|
||||||
|
return inspect
|
@ -60,6 +60,7 @@ local function new(id, type, ...)
|
|||||||
local ox = args[5] or width * 0.5
|
local ox = args[5] or width * 0.5
|
||||||
local oy = args[6] or height * 0.5
|
local oy = args[6] or height * 0.5
|
||||||
|
|
||||||
|
obj.type = "polygon"
|
||||||
obj:setPoints(
|
obj:setPoints(
|
||||||
x - ox, y - oy,
|
x - ox, y - oy,
|
||||||
x - ox + width, y - oy,
|
x - ox + width, y - oy,
|
||||||
|