Last active
July 27, 2020 03:15
-
-
Save gilzoide/7545553b03ed0de2c79b5ba1ae674183 to your computer and use it in GitHub Desktop.
A module for detecting updated files in a LÖVE game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Detecting updated files for hot reloading in a LÖVE game | |
local hotreload = {} | |
-- Monitor the "src" and "assets" paths, can be changed to any existing folders in your project, separated by spaces | |
local monitor_path = "src assets" | |
-- External command for monitoring the filesystem | |
-- Needs fswatch available for execution in PATH (no errors will be thrown, but reload will not work) | |
-- https://github.com/emcrisostomo/fswatch | |
local fswatch_cmd = "fswatch --recursive --event Updated " .. monitor_path | |
function hotreload.load() | |
hotreload.channel = love.thread.newChannel() | |
-- This may be used to retrieve the relative file paths from fswatch's output | |
hotreload.source = love.filesystem.getSource() | |
-- Reading a subprocess output is a blocking operation, so it must run in a separate thread | |
local thread = love.thread.newThread([[ | |
local channel, fswatch_cmd = ... | |
local fswatch = io.popen(fswatch_cmd) | |
-- `io.popen` returns an open file even if the command failed | |
-- This `if` is not mandatory, but this will make the thread finish instead of being blocked forever for nothing | |
if fswatch:read(0) then | |
for line in fswatch:lines() do | |
channel:push(line) | |
end | |
else | |
print(string.format('HOTRELOAD failed running %q and is disabled', fswatch_cmd)) | |
end | |
]]) | |
thread:start(hotreload.channel, fswatch_cmd) | |
end | |
function hotreload.update() | |
-- Note: if no files are updated or if the fswatch command failed, nothing happens =] | |
while hotreload.channel:getCount() > 0 do | |
local filename = hotreload.channel:pop() | |
-- Note: fswatch returns full file paths. | |
-- You can get the relative path by trimming the project source path with the following line | |
-- `+2` is for skipping the trailing "/" or "\" | |
filename = filename:sub(#hotreload.source + 2) | |
print('UPDATED', filename) | |
-- Example: reload image assets into global table | |
local imagename = filename:match("([^/\\]+)%.png$") | |
if imagename then | |
print(string.format('Reloading image %q into global table', imagename)) | |
_G[imagename] = love.graphics.newImage(filename) | |
end | |
end | |
end | |
return hotreload |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local hotreload = require 'hotreload' | |
function love.load() | |
-- do your usual loading here | |
hotreload.load() | |
end | |
function love.update(dt) | |
-- hotreloading stuff in the beginning of the update means the new stuff is readily available in your update cycle | |
hotreload.update() | |
-- your usual update here | |
end | |
function love.draw() | |
-- your usual draw here, no drawing is needed for hotreload | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment