{"id":15014604,"url":"https://github.com/mikuauahdark/lily","last_synced_at":"2025-04-12T08:13:33.261Z","repository":{"id":133072893,"uuid":"114961511","full_name":"MikuAuahDark/lily","owner":"MikuAuahDark","description":"LÖVE Async Asset Loader","archived":false,"fork":false,"pushed_at":"2022-06-13T03:44:37.000Z","size":102,"stargazers_count":107,"open_issues_count":0,"forks_count":6,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-12T08:13:28.041Z","etag":null,"topics":["async","event","love","love2d","lua"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MikuAuahDark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-12-21T04:11:42.000Z","updated_at":"2025-02-26T09:28:03.000Z","dependencies_parsed_at":"2023-03-14T23:30:59.412Z","dependency_job_id":null,"html_url":"https://github.com/MikuAuahDark/lily","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikuAuahDark%2Flily","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikuAuahDark%2Flily/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikuAuahDark%2Flily/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MikuAuahDark%2Flily/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MikuAuahDark","download_url":"https://codeload.github.com/MikuAuahDark/lily/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248537144,"owners_count":21120711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","event","love","love2d","lua"],"created_at":"2024-09-24T19:45:50.263Z","updated_at":"2025-04-12T08:13:33.241Z","avatar_url":"https://github.com/MikuAuahDark.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"Lily\r\n====\r\n\r\nLOVE Async Loading library. Uses multiple thread to load your assets (depends on amount of CPU)\r\n\r\nExample\r\n-------\r\n\r\nThis code snippet displays \"Loading image\" if the image hasn't been loaded and \"Loading song\" if the audio hasn't been loaded\r\n\r\n```lua\r\nlocal lily = require(\"lily\")\r\nlocal myimage\r\nlocal mysound\r\n\r\nfunction love.load()\r\n\tlily.newImage(\"image.png\"):onComplete(function(userdata, image)\r\n\t\t-- In v2.0, there's \"userdata\" before the return value\r\n\t\tmyimage = image\r\n\tend)\r\n\tlily.newSource(\"song.wav\"):onComplete(function(userdata, sound)\r\n\t\t-- In v2.0, there's \"userdata\" before the return value\r\n\t\tmysound = sound\r\n\t\tsound:play()\r\n\tend)\r\nend\r\n\r\nfunction love.draw()\r\n\tif myimage then love.graphics.draw(myimage, 0, 24, 0, 0.25, 0.25)\r\n\telse love.graphics.print(\"Loading image\") end\r\n\tif not(mysound) then love.graphics.print(\"Loading song\", 0, 12) end\r\nend\r\n```\r\n\r\nExample of multi loading\r\n\r\n```lua\r\nlocal lily = require(\"lily\")\r\n\r\nfunction love.load()\r\n\tmultilily = lily.loadMulti({\r\n\t\t{\"newImage\", \"image1-0.png\"},\t-- You can use string\r\n\t\t{lily.newImage, love.filesystem.newFile(\"image1-1.png\")},\t-- or the function object\r\n\t})\r\n\tmultilily:onComplete(function(_, lilies)\r\n\t\timage1 = lilies[1][1]\r\n\t\timage2 = lilies[2][1]\r\n\tend)\r\nend\r\n\r\nfunction love.update() end\r\nfunction love.draw()\r\n\tif multilily:isComplete() then\r\n\t\tlove.graphics.draw(image1, -1024, -1024)\r\n\t\tlove.graphics.draw(image2)\r\n\tend\r\nend\r\n```\r\n\r\nVersion Compatibility\r\n---------------------\r\n\r\nLily v3.0 is not compatible with LOVE 0.10.x. Latest version which is compatible with LOVE 0.10.x is Lily v2.0.x\r\nand can be found in `v2.0` branch. In case of bug fix, it will be backported to v2.0 branch when applicable.\r\n\r\nInstall\r\n-------\r\n\r\nPut `lily.lua` and `lily_thread.lua` in your LOVE game and `require(\"lily\")`. Or use `lily_single.lua` and `require(\"lily_single\")`.\r\n\r\nHow it Works\r\n------------\r\n\r\nLily tries to load the asset, which can be time consuming, into another thread, called \"TaskPool\". When Lily is loaded, it creates\r\nn-amount of \"TaskPool\", where `n` depends on how many CPU core you have. This allows the main thread to keep rendering while the other\r\nthread do the asset loading. If you have more CPU cores, this is even better because the asset loading will be scattered across \"TaskPool\"\r\n(by selecting \"TaskPool\" which has least amount of pending tasks). CPU core detection requires `love.system` module. Although it's possible\r\nto use Lily without `love.system` by using other methods to find amount of CPU core, such strategy can fail under some system configuration\r\nand fallback to 1 \"TaskPool\".\r\n\r\nWhy there's no `lily.update()` (like `loader.update()` in love-loader)? Lily takes advantage that `love.event.push` is thread-safe and\r\nin fact LOVE allows custom event which can be added via `love.handlers` table. So, instead of using `Channel` to pass the loaded asset\r\nto Lily main thread, Lily register it's own event and then the other thread will send LOVE event using `love.thread.push`. LOVE will\r\nread that this event comes from Lily \"TaskPool\" thread, then execute Lily event handler, which returns the loaded asset ready to use.\r\n\r\nDocumentation\r\n-------------\r\n\r\nMost Lily function to create threaded asset follows LOVE name, like `newSource` for loading playable audio, `newImage` for loading\r\ndrawable image, and such. Additionally, Lily expose these additional function.\r\n\r\nTo call the async version of LOVE function, see function below. The function argument and the return value follows LOVE argument name unless noted. Lily\r\nonly expose function if the corresponding LOVE module is loaded, so load Lily after you `require` your necessary LOVE modules.\r\n\r\nAvailable functions:\r\n\r\n* newSource (`love.audio.newSource`)\r\n\r\n* append (`love.filesystem.append`)\r\n\r\n* newFileData (`love.filesystem.newFileData`)\r\n\r\n* read (`love.filesystem.read`)\r\n\r\n* readFile(`File`, ...) (`File:read(...)`)\r\n\r\n* write (`love.filesystem.write`)\r\n\r\n* writeFile(`File`, ...) (`File:write(...)`)\r\n\r\n* newFont (`love.graphics.newFont`)\r\n\r\n* newImage (`love.graphics.newImage`)\r\n\r\n* newCubeImage (`love.graphics.newCubeImage`) \\*\r\n\r\n* newArrayImage (`love.graphics.newCubeImage`) \\*\r\n\r\n* newVolumeImage (`love.graphics.newCubeImage`) \\*\r\n\r\n* newVideo (`love.graphics.newVideo`)\r\n\r\n* encodeImageData(`ImageData`, ...) (`ImageData:encode(...)`)\r\n\r\n* newImageData (`love.image.newImageData`)\r\n\r\n* newCompressedData (`love.image.newCompressedData`)\r\n\r\n* pasteImageData(`ImageData`, ...) (`ImageData:paste(...)`)\r\n\r\n* compress(`format`, `data`, `level`; returns string) (`love.data.compress(\"data\", data, format, level)`)\r\n\r\n* decompress(`format`, `data`; returns string) (`love.data.decompress(\"data\", data, format)`)\r\n\r\n* newSoundData (`love.sound.newSoundData`)\r\n\r\n* newVideoStream (`love.video.newVideoStream`)\r\n\r\n\\* - Only on supported systems. Nested tables for mipmaps is not supported at the moment.\r\n\r\n*************************************************\r\n\r\n### `number lily.getThreadCount()`\r\n\r\nReturns: Amount of threads used by Lily. This is mostly likely amount of logical CPU available.\r\n\r\n\u003e When `love.system` is not loaded, it uses other ways to get the amount of logical CPU. If all else fails, fallback to 1\r\n\r\n*************************************************\r\n\r\n### `void lily.quit()`\r\n\r\nUninitializes Lily. Uninitialize all threads. Call this just before your game quit (in `love.quit()`). Not calling\r\nthis function in iOS and Android can cause strange crash when re-starting your game!\r\n\r\nIt's good idea to call this function regardless of the platform.\r\n\r\n*************************************************\r\n\r\n### `bool lily.setUpdateMode(string mode)`\r\n\r\nSet update mode, whetever to tell Lily to pull data by using LOVE event handler or\r\nby using `lily.update` function.\r\n\r\nParameters:\r\n\r\n* `mode` - Either `\"automatic\"` (use LOVE event handler) or `\"manual\"` (calling [`lily.update`](#void-lilyupdate) in `love.update`).\r\n\r\nReturns: `true` if success, `false` otherwise.\r\n\r\n\u003e By default, Lily uses `\"automatic\"` method (using LOVE event handler).\r\n\r\n*************************************************\r\n\r\n### `void lily.update()`\r\n\r\nPull processed data from other threads. Signals other loader object when necessary.\r\n\r\nReturns: none\r\n\r\n\u003e This function only takes effect when using `\"manual\"` update mode (see [`lily.setUpdateMode`](#bool-lilysetupdatemodestring-mode))\r\n\r\n*************************************************\r\n\r\n### `MultiLilyObject lily.loadMulti(table list)`\r\n\r\nLoads multiple object simultaneously.\r\n\r\nIt expects `list` as table with these information\r\n\r\n```lua\r\n{\r\n\t{lily_function_name or lily_function, arg1, arg2, ...},\r\n\t...\r\n}\r\n```\r\n\r\nThe index will be used as `lilyindex` in below documentation to refer at nth-`LilyObject`.\r\n\r\nReturns: `MultiLilyObject`\r\n\r\n*************************************************\r\n\r\n### `(Multi)LilyObject (Multi)LilyObject:onComplete(function complete_callback)`\r\n\r\nSets new function as callback when the asset is loaded. Default to noop. Function signature is:\r\n\r\n* `void complete_callback(any userdata, any value1, any value2, ...)` (`value` is the result of such function) (for `LilyObject`)\r\n\r\n* `void complete_callback(any userdata, table lily_return_values)` (`lily_return_values[lilyindex]` is return value of correctponding nth-`LilyObject` in table)\r\n\r\nReturns: itself\r\n\r\n*************************************************\r\n\r\n### `(Multi)LilyObject (Multi)LilyObject:onError(function error_callback)`\r\n\r\nSets new function as callback when there's error when loading asset. Default to Lua built-in `error` function.\r\nFunction signature is:\r\n\r\n* `void error_callback(any userdata, string error_message, string traceback)` (for `LilyObject`)\r\n\r\n* `void error_callback(any userdata, number lilyindex, string error_message, string traceback)` (for `MultiLilyObject`)\r\n\r\nReturns: itself\r\n\r\n\u003e `traceback` parameter is added in v3.0.9\r\n\r\n*************************************************\r\n\r\n### `(Multi)LilyObject (Multi)LilyObject:setUserData(any userdata)`\r\n\r\nSets the userdata. It can be any user-supplied data.\r\n\r\nReturns: itself\r\n\r\n*************************************************\r\n\r\n### `MultiLilyObject MultiLilyObject:onLoaded(function loaded_callback)`\r\n\r\nSets new function as callback when `LilyObject` asset is loaded. Function signature is\r\n`void loaded_callback(any userdata, number lilyindex, any value1, any value2, ...)`\r\n\r\n`valuen` depends on nth-`LilyObject` (correstpond to `lilyindex`).\r\n\r\nReturns: itself\r\n\r\n*************************************************\r\n\r\n### `bool (Multi)LilyObject:isComplete()`\r\n\r\nReturns: `true` if specificed object fully loaded, `false` otherwise.\r\n\r\n*************************************************\r\n\r\n### `value1, value2, ... LilyObject:getValues()`\r\n\r\n### `value1, value2, ... MultiLilyObject:getValues(number lilyindex)`\r\n\r\nGet the result value of corresponding Lily request. Throws error if request is still incomplete.\r\n\r\nReturns: Value depends on Lily request\r\n\r\n*************************************************\r\n\r\n### `table MultiLilyObject:getValues()`\r\n\r\nGets all result value from all `LilyObject`.\r\n\r\nReturns: table, where at index `n` is correstpond to nth-`LilyObject`.\r\n\r\n*************************************************\r\n\r\n### `number MultiLilyObject:getCount()`\r\n\r\nRetrieve amount of Lily objects to be loaded. This includes completed one.\r\n\r\nReturns: Amount of Lily object needs to be loaded.\r\n\r\n*************************************************\r\n\r\n### `number MultiLilyObject:getLoadedCount()`\r\n\r\nGets amount of loaded objects.\r\n\r\nReturns: Amount of objects loaded. If this is same as `MultiLilyObject:getLoadedCount()` then it's fully loaded.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikuauahdark%2Flily","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikuauahdark%2Flily","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikuauahdark%2Flily/lists"}