1
0
Fork 0
mirror of https://github.com/Reuh/ubiquitousse.git synced 2025-10-27 17:19:31 +00:00

Add doc for ecs, asset

This commit is contained in:
Étienne Fildadut 2021-12-25 17:08:08 +01:00
parent 31472b2a85
commit d4e2a1d94a
14 changed files with 2938 additions and 592 deletions

View file

@ -1,21 +1,44 @@
--- ubiquitousse.asset --- Asset manager.
-- No dependencies. --
-- Loads asset and cache them.
--- Asset manager. Loads asset and cache them. --
-- This file has no dependency to either ubiquitousse or a ubiquitousse backend.
-- This only provides a streamlined way to handle asset, and doesn't handle the actual file loading/object creation itself; you are expected to provide your own asset loaders. -- This only provides a streamlined way to handle asset, and doesn't handle the actual file loading/object creation itself; you are expected to provide your own asset loaders.
-- See the __call method for more details on how assets are loaded. Hopefully this will allow you to use asset which are more game-specific than "image" or "audio". --
-- See the `Asset:__call` method for more details on how assets are loaded. Hopefully this will allow you to use asset which are more game-specific than "image" or "audio".
--
-- No dependencies.
-- @module asset
--- Asset manager.
-- @type Asset
local asset_mt = { local asset_mt = {
--- A prefix for asset names.
-- @ftype string
prefix = nil,
--- The asset cache. Each cached asset is indexed with a string key "type.assetName".
-- @ftype table {["assetName"]=asset}
cache = nil,
--- The loaders table.
-- @ftype table {["prefix"]=function, ...}
loaders = nil,
--- Load (and cache) an asset. --- Load (and cache) an asset.
--
-- Asset name are similar to Lua module names (directory separator is the dot . and no extention should be specified). -- Asset name are similar to Lua module names (directory separator is the dot . and no extention should be specified).
-- To load an asset, ubiquitousse will try every loaders in the loader list with a name that prefix the asset name. -- To load an asset, ubiquitousse will try every loaders in the loader list with a name that prefix the asset name.
-- The first value returned will be used as the asset value. -- The first value returned will be used as the asset value.
--
-- Loaders are called with the arguments: -- Loaders are called with the arguments:
--
-- * path: the asset full path, except extension -- * path: the asset full path, except extension
-- * ...: other arguments given after the asset name. Can only be number and strings. -- * ...: other arguments given after the asset name. Can only be number and strings.
-- @tparam assetName string the asset's full name -- @tparam string assetName string the asset's full name
-- @tparam ... number/string other arguments for the asset loader -- @tparam number/string ... other arguments for the asset loader
-- @return the asset -- @return the asset
-- @usage
-- local image = asset("image.example")
__call = function(self, assetName, ...) __call = function(self, assetName, ...)
local cache = self.cache local cache = self.cache
local hash = table.concat({assetName, ...}, ".") local hash = table.concat({assetName, ...}, ".")
@ -36,6 +59,7 @@ local asset_mt = {
end, end,
--- Preload a list of assets. --- Preload a list of assets.
-- @tparam {"asset1",...} list list of assets to load
load = function(self, list) load = function(self, list)
for _, asset in ipairs(list) do for _, asset in ipairs(list) do
self(asset) self(asset)
@ -50,27 +74,28 @@ local asset_mt = {
} }
asset_mt.__index = asset_mt asset_mt.__index = asset_mt
--- Asset module.
-- @section end
local asset = { local asset = {
--- Create a new asset manager. --- Create a new asset manager.
--
-- If the caching "mode" is set to auto (default), the asset manager will allow assets to be automaticaly garbage collected by Lua. -- If the caching "mode" is set to auto (default), the asset manager will allow assets to be automaticaly garbage collected by Lua.
--
-- If set to "manual", the assets will not be garbage collected unless the clear method is called. -- If set to "manual", the assets will not be garbage collected unless the clear method is called.
-- "manual" mode is useful if you have assets that are particularly slow to load and you want full control on when they are loaded and unloaded (typically a loading screen). -- "manual" mode is useful if you have assets that are particularly slow to load and you want full control on when they are loaded and unloaded (typically a loading screen).
-- @tparam directory string the directory in which the assets will be loaded -- @tparam string directory the directory in which the assets will be loaded
-- @tparam loaders table loaders table: {prefix = function, ...} -- @tparam table loaders loaders table: {prefix = function, ...}
-- @tparam mode string[opt="auto"] caching mode -- @tparam[opt="auto"] string mode caching mode
new = function(dir, loaders, mode) -- @treturn Asset the new asset manager
new = function(directory, loaders, mode)
local cache = {} local cache = {}
if mode == nil or mode == "auto" then if mode == nil or mode == "auto" then
setmetatable(cache, { __mode = "v" }) setmetatable(cache, { __mode = "v" })
end end
return setmetatable({ return setmetatable({
--- A prefix for asset names prefix = directory..".",
prefix = dir..".",
--- The asset cache. Each cached asset is indexed with a string key "type.assetName".
cache = cache, cache = cache,
--- The loaders table.
loaders = loaders loaders = loaders
}, asset_mt) }, asset_mt)
end end

View file

@ -8,11 +8,26 @@ See [main module](modules/init.html) for more information, or the [GitHub page](
--package = "ubiquitousse" --package = "ubiquitousse"
format = "discount" format = "discount"
style = "!fixed" style = "!new"
no_summary = true
not_luadoc = true not_luadoc = true
custom_tags = { { "require", title="Requires" } } custom_tags = {
{ "require", title="Requires" },
{ "ftype", title="Type", format = function(x)
local firstWord, rest = x:match("^([^%s]*)(.*)$")
return ('<code>%s</code>%s'):format(firstWord, rest)
end },
{ "ro", hidden=true },
{ "callback", hidden=true },
}
custom_display_name_handler = function(item, default_handler)
if item.tags.callback then
return default_handler(item) .. ' <sup><em>[callback]</em></sup>'
elseif item.tags.ro then
return default_handler(item) .. ' <sup><em>[read-only]</em></sup>'
end
return default_handler(item)
end
topics = { "README.md", "LICENSE" } topics = { "README.md", "LICENSE" }
file = { "init.lua", "ldtk/ldtk.can" } file = { "init.lua", "ldtk/ldtk.can", "ecs/ecs.can", "asset/asset.lua" }

View file

@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>Ubiquitousse reference</title> <title>Ubiquitousse reference</title>
<link rel="stylesheet" href="ldoc_fixed.css" type="text/css" /> <link rel="stylesheet" href="ldoc_new.css" type="text/css" />
</head> </head>
<body> <body>
@ -32,8 +32,10 @@
<h2>Modules</h2> <h2>Modules</h2>
<ul class="nowrap"> <ul class="nowrap">
<li><a href="modules/init.html">init</a></li> <li><a href="modules/ubiquitousse.html">ubiquitousse</a></li>
<li><a href="modules/ldtk.html">ldtk</a></li> <li><a href="modules/ldtk.html">ldtk</a></li>
<li><a href="modules/ecs.html">ecs</a></li>
<li><a href="modules/asset.html">asset</a></li>
</ul> </ul>
<h2>Topics</h2> <h2>Topics</h2>
<ul class=""> <ul class="">
@ -54,13 +56,23 @@
<h2>Modules</h2> <h2>Modules</h2>
<table class="module_list"> <table class="module_list">
<tr> <tr>
<td class="name" nowrap><a href="modules/init.html">init</a></td> <td class="name" nowrap><a href="modules/ubiquitousse.html">ubiquitousse</a></td>
<td class="summary">Ubiquitousse main module.</td> <td class="summary">Ubiquitousse main module.</td>
</tr> </tr>
<tr> <tr>
<td class="name" nowrap><a href="modules/ldtk.html">ldtk</a></td> <td class="name" nowrap><a href="modules/ldtk.html">ldtk</a></td>
<td class="summary"><a href="https://ldtk.io/">LDtk</a> level importer for LÖVE.</td> <td class="summary"><a href="https://ldtk.io/">LDtk</a> level importer for LÖVE.</td>
</tr> </tr>
<tr>
<td class="name" nowrap><a href="modules/ecs.html">ecs</a></td>
<td class="summary">ECS (entity compenent system) library</p>
<p> Entity Component System library, inspired by the excellent tiny-ecs.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/asset.html">asset</a></td>
<td class="summary">Asset manager.</td>
</tr>
</table> </table>
<h2>Topics</h2> <h2>Topics</h2>
<table class="module_list"> <table class="module_list">
@ -78,7 +90,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i> <i style="float:right;">Last updated 2021-12-25 17:06:47 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -1,311 +0,0 @@
/* BEGIN RESET
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.8.2r1
*/
html {
color: #000;
background: #FFF;
}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
font-style: inherit;
font-weight: inherit;
}
del,ins {
text-decoration: none;
}
li {
margin-left: 20px;
}
caption,th {
text-align: left;
}
h1,h2,h3,h4,h5,h6 {
font-size: 100%;
font-weight: bold;
}
q:before,q:after {
content: '';
}
abbr,acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: baseline;
}
sub {
vertical-align: baseline;
}
legend {
color: #000;
}
input,button,textarea,select,optgroup,option {
font-family: inherit;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
}
input,button,textarea,select {*font-size:100%;
}
/* END RESET */
body {
margin-left: 1em;
margin-right: 1em;
font-family: arial, helvetica, geneva, sans-serif;
background-color: #ffffff; margin: 0px;
}
code, tt { font-family: monospace; font-size: 1.1em; }
span.parameter { font-family:monospace; }
span.parameter:after { content:":"; }
span.types:before { content:"("; }
span.types:after { content:")"; }
.type { font-weight: bold; font-style:italic }
body, p, td, th { font-size: .95em; line-height: 1.2em;}
p, ul { margin: 10px 0 0 0px;}
strong { font-weight: bold;}
em { font-style: italic;}
h1 {
font-size: 1.5em;
margin: 0 0 20px 0;
}
h2, h3, h4 { margin: 15px 0 10px 0; }
h2 { font-size: 1.25em; }
h3 { font-size: 1.15em; }
h4 { font-size: 1.06em; }
a:link { font-weight: bold; color: #004080; text-decoration: none; }
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
a:link:hover { text-decoration: underline; }
hr {
color:#cccccc;
background: #00007f;
height: 1px;
}
blockquote { margin-left: 3em; }
ul { list-style-type: disc; }
p.name {
font-family: "Andale Mono", monospace;
padding-top: 1em;
}
pre {
background-color: rgb(245, 245, 245);
border: 1px solid #C0C0C0; /* silver */
padding: 10px;
margin: 10px 0 10px 0;
overflow: auto;
font-family: "Andale Mono", monospace;
}
pre.example {
font-size: .85em;
}
table.index { border: 1px #00007f; }
table.index td { text-align: left; vertical-align: top; }
#container {
margin-left: 1em;
margin-right: 1em;
background-color: #ffffff;
}
#product {
text-align: center;
border-bottom: 1px solid #cccccc;
background-color: #ffffff;
}
#product big {
font-size: 2em;
}
#main {
background-color:#FFFFFF; // #f0f0f0;
border-left: 1px solid #cccccc;
}
#navigation {
position: fixed;
top: 0;
left: 0;
float: left;
width: 14em;
vertical-align: top;
background-color:#FFFFFF; // #f0f0f0;
border-right: 2px solid #cccccc;
overflow: visible;
overflow-y: scroll;
height: 100%;
padding-left: 1em;
}
#navigation h2 {
background-color:#FFFFFF;//:#e7e7e7;
font-size:1.1em;
color:#000000;
text-align: left;
padding:0.2em;
border-bottom:1px solid #dddddd;
}
#navigation ul
{
font-size:1em;
list-style-type: none;
margin: 1px 1px 10px 1px;
}
#navigation li {
text-indent: -1em;
display: block;
margin: 3px 0px 0px 22px;
}
#navigation li li a {
margin: 0px 3px 0px -1em;
}
#content {
margin-left: 14em;
padding: 1em;
padding-left: 2em;
width: 700px;
border-left: 2px solid #cccccc;
// border-right: 2px solid #cccccc;
background-color: #ffffff;
}
#about {
clear: both;
padding-left: 1em;
margin-left: 14em; // avoid the damn sidebar!
border-top: 2px solid #cccccc;
border-left: 2px solid #cccccc;
background-color: #ffffff;
}
@media print {
body {
font: 12pt "Times New Roman", "TimeNR", Times, serif;
}
a { font-weight: bold; color: #004080; text-decoration: underline; }
#main {
background-color: #ffffff;
border-left: 0px;
}
#container {
margin-left: 2%;
margin-right: 2%;
background-color: #ffffff;
}
#content {
padding: 1em;
background-color: #ffffff;
}
#navigation {
display: none;
}
pre.example {
font-family: "Andale Mono", monospace;
font-size: 10pt;
page-break-inside: avoid;
}
}
table.module_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.module_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; }
table.module_list td.summary { width: 100%; }
table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
}
table.function_list td {
border-width: 1px;
padding: 3px;
border-style: solid;
border-color: #cccccc;
}
table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; }
table.function_list td.summary { width: 100%; }
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
dl.table h3, dl.function h3 {font-size: .95em;}
ul.nowrap {
overflow:auto;
whitespace:nowrap;
}
/* stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* make the target distinct; helps when we're navigating to a function */
a:target + * {
background-color: #FF9;
}
/* styles for prettification of source */
pre .comment { color: #558817; }
pre .constant { color: #a8660d; }
pre .escape { color: #844631; }
pre .keyword { color: #aa5050; font-weight: bold; }
pre .library { color: #0e7c6b; }
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
pre .string { color: #8080ff; }
pre .number { color: #f8660d; }
pre .operator { color: #2239a8; font-weight: bold; }
pre .preprocessor, pre .prepro { color: #a33243; }
pre .global { color: #800080; }
pre .user-keyword { color: #800080; }
pre .prompt { color: #558817; }
pre .url { color: #272fc2; text-decoration: underline; }

313
doc/ldoc_new.css Normal file
View file

@ -0,0 +1,313 @@
body {
color: #47555c;
font-size: 16px;
font-family: "Open Sans", sans-serif;
margin: 0;
background: #eff4ff;
}
a:link { color: #008fee; }
a:visited { color: #008fee; }
a:hover { color: #22a7ff; }
h1 { font-size:26px; font-weight: normal; }
h2 { font-size:22px; font-weight: normal; }
h3 { font-size:18px; font-weight: normal; }
h4 { font-size:16px; font-weight: bold; }
hr {
height: 1px;
background: #c1cce4;
border: 0px;
margin: 15px 0;
}
code, tt {
font-family: monospace;
}
span.parameter {
font-family: monospace;
font-weight: bold;
color: rgb(99, 115, 131);
}
span.parameter:after {
content:":";
}
span.types:before {
content:"(";
}
span.types:after {
content:")";
}
.type {
font-weight: bold; font-style:italic
}
p.name {
font-family: "Andale Mono", monospace;
}
#navigation {
float: left;
background-color: white;
border-right: 1px solid #d3dbec;
border-bottom: 1px solid #d3dbec;
width: 14em;
vertical-align: top;
overflow: visible;
}
#navigation br {
display: none;
}
#navigation h1 {
background-color: white;
border-bottom: 1px solid #d3dbec;
padding: 15px;
margin-top: 0px;
margin-bottom: 0px;
}
#navigation h2 {
font-size: 18px;
background-color: white;
border-bottom: 1px solid #d3dbec;
padding-left: 15px;
padding-right: 15px;
padding-top: 10px;
padding-bottom: 10px;
margin-top: 30px;
margin-bottom: 0px;
}
#navigation h3 {
font-size: 16px;
padding-left: 15px;
padding-right: 15px;
padding-top: 10px;
padding-bottom: 10px;
margin-top: 0px;
margin-bottom: 0px;
}
#content h1 {
background-color: #2c3e67;
color: white;
padding: 15px;
margin: 0px;
}
#content h2 {
background-color: #6c7ea7;
color: white;
padding: 15px;
padding-top: 15px;
padding-bottom: 15px;
margin-top: 0px;
}
#content h2 a {
background-color: #6c7ea7;
color: white;
text-decoration: none;
}
#content h2 a:hover {
text-decoration: underline;
}
#content h3 {
font-style: italic;
padding-top: 15px;
padding-bottom: 4px;
margin-right: 5px;
margin-left: 5px;
margin-bottom: 5px;
border-bottom: solid 1px #bcd;
}
#content h3.doc-title {
font-style: normal;
font-weight: bold;
padding-top: 10px;
}
#content h3.doc-title a {
color: #47555c;
text-decoration: none;
}
#content h3.doc-title a:hover {
text-decoration: underline;
}
#content h4 {
margin-right: 15px;
margin-left: 15px;
border-bottom: solid 1px #bcd;
}
#content pre {
margin: 15px;
}
pre {
background-color: rgb(50, 55, 68);
color: white;
border-radius: 3px;
/* border: 1px solid #C0C0C0; /* silver */
padding: 15px;
overflow: auto;
font-family: "Andale Mono", monospace;
}
#content ul pre.example {
margin-left: 0px;
}
table.index {
/* border: 1px #00007f; */
}
table.index td { text-align: left; vertical-align: top; }
#navigation ul
{
font-size:1em;
list-style-type: none;
margin: 1px 1px 10px 1px;
}
#navigation li {
text-indent: -1em;
display: block;
margin: 3px 0px 0px 22px;
}
#navigation li li a {
margin: 0px 3px 0px -1em;
}
#content {
margin-left: 14em;
}
#content p {
padding-left: 15px;
padding-right: 15px;
}
#content table {
padding-left: 15px;
padding-right: 15px;
background-color: white;
}
#content p, #content table, #content ol, #content ul, #content dl {
max-width: 900px;
}
#about {
padding: 15px;
padding-left: 16em;
background-color: white;
border-top: 1px solid #d3dbec;
border-bottom: 1px solid #d3dbec;
}
table.module_list, table.function_list {
border-width: 1px;
border-style: solid;
border-color: #cccccc;
border-collapse: collapse;
margin: 15px;
}
table.module_list td, table.function_list td {
border-width: 1px;
padding-left: 10px;
padding-right: 10px;
padding-top: 5px;
padding-bottom: 5px;
border: solid 1px rgb(193, 204, 228);
}
table.module_list td.name, table.function_list td.name {
background-color: white; min-width: 200px; border-right-width: 0px;
}
table.module_list td.summary, table.function_list td.summary {
background-color: white; width: 100%; border-left-width: 0px;
}
dl.function {
margin-right: 15px;
margin-left: 15px;
border-bottom: solid 1px rgb(193, 204, 228);
border-left: solid 1px rgb(193, 204, 228);
border-right: solid 1px rgb(193, 204, 228);
background-color: white;
}
dl.function dt {
color: rgb(99, 123, 188);
font-family: monospace;
border-top: solid 1px rgb(193, 204, 228);
padding: 15px;
}
dl.function dd {
margin-left: 15px;
margin-right: 15px;
margin-top: 5px;
margin-bottom: 15px;
}
#content dl.function dd h3 {
margin-top: 0px;
margin-left: 0px;
padding-left: 0px;
font-size: 16px;
color: rgb(128, 128, 128);
border-bottom: solid 1px #def;
}
#content dl.function dd ul, #content dl.function dd ol {
padding: 0px;
padding-left: 15px;
list-style-type: none;
}
ul.nowrap {
overflow:auto;
white-space:nowrap;
}
.section-description, .doc-description {
padding-left: 15px;
padding-right: 15px;
}
/* stop sublists from having initial vertical space */
ul ul { margin-top: 0px; }
ol ul { margin-top: 0px; }
ol ol { margin-top: 0px; }
ul ol { margin-top: 0px; }
/* make the target distinct; helps when we're navigating to a function */
a:target + * {
background-color: #FF9;
}
/* styles for prettification of source */
pre .comment { color: #bbccaa; }
pre .constant { color: #a8660d; }
pre .escape { color: #844631; }
pre .keyword { color: #ffc090; font-weight: bold; }
pre .library { color: #0e7c6b; }
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
pre .string { color: #8080ff; }
pre .number { color: #f8660d; }
pre .operator { color: #2239a8; font-weight: bold; }
pre .preprocessor, pre .prepro { color: #a33243; }
pre .global { color: #c040c0; }
pre .user-keyword { color: #800080; }
pre .prompt { color: #558817; }
pre .url { color: #272fc2; text-decoration: underline; }

332
doc/modules/asset.html Normal file
View file

@ -0,0 +1,332 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_new.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Ubiquitousse</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
<li><a href="#Asset_objects">Asset objects </a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/ubiquitousse.html">ubiquitousse</a></li>
<li><a href="../modules/ldtk.html">ldtk</a></li>
<li><a href="../modules/ecs.html">ecs</a></li>
<li><strong>asset</strong></li>
</ul>
<h2>Topics</h2>
<ul class="">
<li><a href="../topics/README.md.html">README</a></li>
<li><a href="../topics/LICENSE.html">LICENSE</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>asset</code></h1>
<p>Asset manager.</p>
<p> Loads asset and cache them.</p>
<p> This only provides a streamlined way to handle asset, and doesn&rsquo;t handle the actual file loading/object creation itself; you are expected to provide your own asset loaders.</p>
<p> See the <a href="../modules/asset.html#Asset:__call">Asset:__call</a> method for more details on how assets are loaded. Hopefully this will allow you to use asset which are more game-specific than &ldquo;image&rdquo; or &ldquo;audio&rdquo;.</p>
<p> No dependencies.</p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#new">new (directory, loaders[, mode="auto"])</a></td>
<td class="summary">Create a new asset manager.</td>
</tr>
</table>
<h2><a href="#Asset_objects">Asset objects </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Asset.prefix">Asset.prefix</a></td>
<td class="summary">A prefix for asset names.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Asset.cache">Asset.cache</a></td>
<td class="summary">The asset cache.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Asset.loaders">Asset.loaders</a></td>
<td class="summary">The loaders table.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Asset:__call">Asset:__call (assetName, ...)</a></td>
<td class="summary">Load (and cache) an asset.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Asset:load">Asset:load (list)</a></td>
<td class="summary">Preload a list of assets.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Asset:clear">Asset:clear ()</a></td>
<td class="summary">Allow loaded assets to be garbage collected.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "new"></a>
<strong>new (directory, loaders[, mode="auto"])</strong>
</dt>
<dd>
Create a new asset manager. </p>
<p> If the caching &ldquo;mode&rdquo; is set to auto (default), the asset manager will allow assets to be automaticaly garbage collected by Lua.</p>
<p> If set to &ldquo;manual&rdquo;, the assets will not be garbage collected unless the clear method is called.
&ldquo;manual&rdquo; mode is useful if you have assets that are particularly slow to load and you want full control on when they are loaded and unloaded (typically a loading screen).
</ul>
</ul>
</ul>
</ul>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">directory</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the directory in which the assets will be loaded
</li>
<li><span class="parameter">loaders</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
loaders table: {prefix = function, &hellip;}
</li>
<li><span class="parameter">mode</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
caching mode
(<em>default</em> "auto")
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/asset.html#Asset_objects">Asset</a></span>
the new asset manager
</ol>
</dd>
</dl>
<h2 class="section-header has-description"><a name="Asset_objects"></a>Asset objects </h2>
<div class="section-description">
Asset manager.
</div>
<dl class="function">
<dt>
<a name = "Asset.prefix"></a>
<strong>Asset.prefix</strong>
</dt>
<dd>
A prefix for asset names.
</ul>
<h3>Type:</h3>
<ul>
<code>string</code>
</ul>
</ul>
</ul>
</dd>
<dt>
<a name = "Asset.cache"></a>
<strong>Asset.cache</strong>
</dt>
<dd>
The asset cache. Each cached asset is indexed with a string key &ldquo;type.assetName&rdquo;.
</ul>
<h3>Type:</h3>
<ul>
<code>table</code> {["assetName"]=asset}
</ul>
</ul>
</ul>
</dd>
<dt>
<a name = "Asset.loaders"></a>
<strong>Asset.loaders</strong>
</dt>
<dd>
The loaders table.
</ul>
<h3>Type:</h3>
<ul>
<code>table</code> {["prefix"]=function, ...}
</ul>
</ul>
</ul>
</dd>
<dt>
<a name = "Asset:__call"></a>
<strong>Asset:__call (assetName, ...)</strong>
</dt>
<dd>
<p>Load (and cache) an asset. </p>
<p> Asset name are similar to Lua module names (directory separator is the dot . and no extention should be specified).
To load an asset, ubiquitousse will try every loaders in the loader list with a name that prefix the asset name.
The first value returned will be used as the asset value.</p>
<p> Loaders are called with the arguments:</p>
<ul>
<li>path: the asset full path, except extension</li>
<li>&hellip;: other arguments given after the asset name. Can only be number and strings.</li>
</ul>
</ul>
</ul>
</ul>
</ul>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">assetName</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
string the asset&rsquo;s full name
</li>
<li><span class="parameter">...</span>
<span class="types"><span class="type">number/string</span></span>
other arguments for the asset loader
</li>
</ul>
<h3>Returns:</h3>
<ol>
the asset
</ol>
<h3>Usage:</h3>
<ul>
<pre class="example"><span class="keyword">local</span> image = asset(<span class="string">"image.example"</span>)</pre>
</ul>
</dd>
<dt>
<a name = "Asset:load"></a>
<strong>Asset:load (list)</strong>
</dt>
<dd>
Preload a list of assets.
</ul>
</ul>
</ul>
</ul>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">list</span>
<span class="types"><span class="type">{"asset1",...}</span></span>
list of assets to load
</li>
</ul>
</dd>
<dt>
<a name = "Asset:clear"></a>
<strong>Asset:clear ()</strong>
</dt>
<dd>
Allow loaded assets to be garbage collected.
Only useful if the caching mode is set to &ldquo;manual&rdquo; duritng creation.
</ul>
</ul>
</ul>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-25 17:06:47 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

1368
doc/modules/ecs.html Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>Ubiquitousse reference</title> <title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" /> <link rel="stylesheet" href="../ldoc_new.css" type="text/css" />
</head> </head>
<body> <body>
@ -31,24 +31,18 @@
<li><a href="../index.html">Index</a></li> <li><a href="../index.html">Index</a></li>
</ul> </ul>
<h2>Contents</h2>
<ul>
<h2>Fields</h2> <li><a href="#Fields">Fields</a></li>
<ul class="nowrap">
<li><a href="#version">version</a></li>
<li><a href="#asset">asset</a></li>
<li><a href="#ecs">ecs</a></li>
<li><a href="#input">input</a></li>
<li><a href="#ldtk">ldtk</a></li>
<li><a href="#scene">scene</a></li>
<li><a href="#signal">signal</a></li>
<li><a href="#timer">timer</a></li>
<li><a href="#util">util</a></li>
</ul> </ul>
<h2>Modules</h2> <h2>Modules</h2>
<ul class="nowrap"> <ul class="nowrap">
<li><strong>init</strong></li> <li><strong>ubiquitousse</strong></li>
<li><a href="../modules/ldtk.html">ldtk</a></li> <li><a href="../modules/ldtk.html">ldtk</a></li>
<li><a href="../modules/ecs.html">ecs</a></li>
<li><a href="../modules/asset.html">asset</a></li>
</ul> </ul>
<h2>Topics</h2> <h2>Topics</h2>
<ul class=""> <ul class="">
@ -60,7 +54,7 @@
<div id="content"> <div id="content">
<h1>Module <code>init</code></h1> <h1>Module <code>ubiquitousse</code></h1>
<p>Ubiquitousse main module.</p> <p>Ubiquitousse main module.</p>
<p> Set of various Lua libraries to make game development easier, mainly made to be used alongside the <a href="https://love2d.org/">LÖVE</a> game framework. <p> Set of various Lua libraries to make game development easier, mainly made to be used alongside the <a href="https://love2d.org/">LÖVE</a> game framework.
Nothing that hasn&rsquo;t been done before, but these are tailored to what I need. They can be used independently too, and are relatively portable, even without LÖVE.</p> Nothing that hasn&rsquo;t been done before, but these are tailored to what I need. They can be used independently too, and are relatively portable, even without LÖVE.</p>
@ -118,6 +112,49 @@
</ul> </ul>
<h2><a href="#Fields">Fields</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#version">version</a></td>
<td class="summary">Ubiquitousse version string (currently <code>&quot;0.1.0&quot;</code>).</td>
</tr>
<tr>
<td class="name" nowrap><a href="#asset">asset</a></td>
<td class="summary">Asset manager module, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#ecs">ecs</a></td>
<td class="summary">Entity Component System, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#input">input</a></td>
<td class="summary">Input management, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#ldtk">ldtk</a></td>
<td class="summary">LDtk level import, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#scene">scene</a></td>
<td class="summary">Scene management, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#signal">signal</a></td>
<td class="summary">Signal management, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#timer">timer</a></td>
<td class="summary">Timer utilities, if available.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#util">util</a></td>
<td class="summary">Various useful functions, if available.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Fields"></a>Fields</h2> <h2 class="section-header "><a name="Fields"></a>Fields</h2>
@ -130,6 +167,9 @@
Ubiquitousse version string (currently <code>&quot;0.1.0&quot;</code>). Ubiquitousse version string (currently <code>&quot;0.1.0&quot;</code>).
</ul> </ul>
</ul>
</ul>
</ul>
@ -145,13 +185,16 @@
Asset manager module, if available. Asset manager module, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#asset">asset</a> <a href="../modules/asset.html#">asset</a>
</ul> </ul>
@ -164,13 +207,16 @@
Entity Component System, if available. Entity Component System, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#ecs">ecs</a> <a href="../modules/ecs.html#">ecs</a>
</ul> </ul>
@ -183,13 +229,16 @@
Input management, if available. Input management, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#input">input</a> <a href="../modules/ubiquitousse.html#input">input</a>
</ul> </ul>
@ -202,6 +251,9 @@
LDtk level import, if available. LDtk level import, if available.
</ul> </ul>
</ul>
</ul>
</ul>
@ -221,13 +273,16 @@
Scene management, if available. Scene management, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#scene">scene</a> <a href="../modules/ubiquitousse.html#scene">scene</a>
</ul> </ul>
@ -240,13 +295,16 @@
Signal management, if available. Signal management, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#signal">signal</a> <a href="../modules/ubiquitousse.html#signal">signal</a>
</ul> </ul>
@ -259,13 +317,16 @@
Timer utilities, if available. Timer utilities, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#timer">timer</a> <a href="../modules/ubiquitousse.html#timer">timer</a>
</ul> </ul>
@ -278,13 +339,16 @@
Various useful functions, if available. Various useful functions, if available.
</ul> </ul>
</ul>
</ul>
</ul>
<h3>See also:</h3> <h3>See also:</h3>
<ul> <ul>
<a href="../modules/init.html#util">util</a> <a href="../modules/ubiquitousse.html#util">util</a>
</ul> </ul>
@ -296,7 +360,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i> <i style="float:right;">Last updated 2021-12-25 17:06:47 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>Ubiquitousse reference</title> <title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" /> <link rel="stylesheet" href="../ldoc_new.css" type="text/css" />
</head> </head>
<body> <body>
@ -40,8 +40,10 @@
</ul> </ul>
<h2>Modules</h2> <h2>Modules</h2>
<ul class="nowrap"> <ul class="nowrap">
<li><a href="../modules/init.html">init</a></li> <li><a href="../modules/ubiquitousse.html">ubiquitousse</a></li>
<li><a href="../modules/ldtk.html">ldtk</a></li> <li><a href="../modules/ldtk.html">ldtk</a></li>
<li><a href="../modules/ecs.html">ecs</a></li>
<li><a href="../modules/asset.html">asset</a></li>
</ul> </ul>
</div> </div>
@ -58,7 +60,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i> <i style="float:right;">Last updated 2021-12-25 17:06:47 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>Ubiquitousse reference</title> <title>Ubiquitousse reference</title>
<link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" /> <link rel="stylesheet" href="../ldoc_new.css" type="text/css" />
</head> </head>
<body> <body>
@ -40,8 +40,10 @@
</ul> </ul>
<h2>Modules</h2> <h2>Modules</h2>
<ul class="nowrap"> <ul class="nowrap">
<li><a href="../modules/init.html">init</a></li> <li><a href="../modules/ubiquitousse.html">ubiquitousse</a></li>
<li><a href="../modules/ldtk.html">ldtk</a></li> <li><a href="../modules/ldtk.html">ldtk</a></li>
<li><a href="../modules/ecs.html">ecs</a></li>
<li><a href="../modules/asset.html">asset</a></li>
</ul> </ul>
</div> </div>
@ -63,7 +65,7 @@
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2021-12-24 23:49:41 </i> <i style="float:right;">Last updated 2021-12-25 17:06:47 </i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View file

@ -1,19 +1,43 @@
--- ubiquitousse.ecs --- ECS (entity compenent system) library
-- Optional dependency: ubiquitousse.scene, to allow quick creation of ECS-based scenes. --
local loaded, scene = pcall(require, (...):match("^(.-)ecs").."scene") -- Entity Component System library, inspired by the excellent tiny-ecs. Main differences include:
if not loaded then scene = nil end --
--- Entity Component System library, inspired by the excellent tiny-ecs. Main differences include:
-- * ability to nest systems; -- * ability to nest systems;
-- * instanciation of systems for each world (no shared state); -- * instanciation of systems for each world (no shared state);
-- * adding and removing entities is done instantaneously -- * adding and removing entities is done instantaneously
-- * ability to add and remove components from entities after they were added to the world. -- * ability to add and remove components from entities after they were added to the world.
--
-- No mandatory dependency.
-- Optional dependency: `ubiquitousse.scene`, to allow quick creation of ECS-based scenes.
--
-- The module returns a table that contains several functions, `world` or `scene` are starting points
-- to create your world.
--
-- @module ecs
-- @usage TODO
local loaded, scene = pcall(require, (...):match("^(.-)ecs").."scene")
if not loaded then scene = nil end
let ecs let ecs
-- TODO: Implement a skip list for faster search. -- TODO: Implement a skip list for faster search.
-- better control over system order: process, draw, methods? (for lag reasons and dependencies) -- better control over system order: process, draw, methods? (for lag reasons and dependencies)
-- more generic events? -- more generic events?
-- TODO: :reorder (like refresh but update order)
-- TODO: clarify documentation on entity tables and instanciated system table
--- Entity table.
-- TODO
-- @section Entity
--- Entity system table.
-- @doc entity
--- @table entity
-- @field .. d
--- Recursively remove subsystems from a system. --- Recursively remove subsystems from a system.
let recDestroySystems = (system) let recDestroySystems = (system)
for i=#system.systems, 1, -1 do for i=#system.systems, 1, -1 do
@ -63,106 +87,193 @@ let copy = (a, b)
end end
--- System fields and methods. --- System fields and methods.
--
-- When they are added to a world, a new, per-world self table is created and used for every method call (which we call "instancied system"). -- When they are added to a world, a new, per-world self table is created and used for every method call (which we call "instancied system").
-- Instancied systems can be retrieved in system.s or system.systems. -- Instancied systems can be retrieved in `system.s` or `system.systems`.
-- Oh, the "world" is just the top-level system, behaving in exactly the same way as other systems. --
-- Every field defined below is optional unless written otherwise. -- The "world" is just the top-level system, behaving in exactly the same way as other systems.
--
-- Every field defined below is optional and can be accessed or redefined at any time, unless written otherwise. Though you would typically set them
-- when creating your system.
-- @type System
let system_mt = { let system_mt = {
--- Read-only after creation system options --- --- Modifiable fields
-- I mean, you can try to change them afterwards. But, heh. -- @doc modifiable
--- Name of the system. --- Name of the system.
-- Used to create a field with the system's name in world.s and into each entity (the "entity's system table"). -- Used to create a field with the system's name in `world.s` and into each entity (the "entity's system table") that's in this system.
-- If not set, the entity will not have a system table. -- If not set, the entity will not have a system table.
--
-- Do not change after system instanciation.
-- @ftype string
-- @ftype nil if no name
name = nil, name = nil,
--- List of subsystems. --- List of subsystems.
-- On a instancied system, this is a list of the same subsystems, but instancied for this world. -- On a instancied system, this is a list of the same subsystems, but instancied for this world.
--
-- Do not change after system instanciation.
-- @ftype table
-- @ftype nil if no subsystem
systems = nil, systems = nil,
--- Modifiable system options ---
--- Returns true if the entity should be added to this system (and therefore its subsystems).
-- If this is a string or a table, it will be converted to a filter function on instanciation using ecs.any.
-- If this true, will accept every entity; if false, reject every entity.
-- Will only test entities when they are added; changing this after system creation will not affect entities already in the system.
-- By default, rejects everything.
filter = :(e) return false end,
--- Returns true if e1 <= e2. e1 and e2 are two entities.
-- Used to place the entity in the sorted entity list when it is added; changing this after system creation
-- will not change the order of entities already in the system.
compare = :(e1, e2) return true end,
--- Called when adding an entity to the system. s is the entity's system table.
onAdd = :(s) end,
--- Called when removing an entity from the system. s is the entity's system table.
onRemove = :(s) end,
--- Called when the system is instancied, before any call to :onAddToWorld (including other systems in the world).
onInstance = :() end,
--- Called when the system is added to a world.
onAddToWorld = :(world) end,
--- Called when the system is removed from a world (i.e., the world is destroyed).
onRemoveFromWorld = :(world) end,
--- Called when the world is destroyed, after every call to :onRemoveFromWorld (including other systems in the world).
onDestroy = :() end,
--- Called when updating the system.
onUpdate = :(dt) end,
--- Called when drawing the system.
onDraw = :() end,
--- Called when updating the system, for every entity the system contains. Called after :onUpdate was called on the system. s is the entity's system table.
process = :(s, dt) end,
--- Called when drawing the system, for every entity the system contains. Called after :onDraw was called on the system. s is the entity's system table.
render = :(s) end,
--- If not false, the system will only update every interval seconds. --- If not false, the system will only update every interval seconds.
-- `false` by default.
-- @ftype number interval of time between each update
-- @ftype false to disable
interval = false, interval = false,
--- The system and its susbsystems will only update if this is true. --- The system and its susbsystems will only update if this is true.
-- `true` by default.
-- @ftype boolean
active = true, active = true,
--- The system and its subsystems will only draw if this is true. --- The system and its subsystems will only draw if this is true.
-- `true` by default.
-- @ftype boolean
visible = true, visible = true,
--- Defaults value to put into the entities's system table when they are added. Will recursively fill missing values. --- Defaults value to put into the entities's system table when they are added. Will recursively fill missing values.
-- When an entity is added to a system, a .entity field is always set in the system table, referring to the full entity table. --
-- When an entity is added to a system, a `.entity` field is always set in the system table, referring to the full entity table.
--
-- Changing this will not affect entities already in the system. -- Changing this will not affect entities already in the system.
-- @ftype table
-- @ftype nil if no default
default = nil, default = nil,
--- Defaults methods to assign to the entities's system table when they are added. --- Defaults methods to assign to the entities's system table when they are added.
-- When calling the methods with entity.systemName:method(...), the method will actually receive the --
-- arguments method(system, system table, ...). Methamethods are accepted. New methods can be -- When calling the methods with `entity.systemName:method(...)`, the method will actually receive the
-- arguments method(system, `system table, ...)`. Methamethods are accepted. New methods can be
-- created anytime. -- created anytime.
-- @ftype table
-- @ftype nil if no methods
methods = nil, methods = nil,
--- Read-only system options --- --- Callbacks.
--
-- Functions that are called when something happens in the system.
-- Redefine them to change system behaviour.
-- @doc callbacks
--- Called when checking if an entity should be added to this system.
-- Returns true if the entity should be added to this system (and therefore its subsystems).
--
-- If this is a string or a table, it will be converted to a filter function on instanciation using ecs.any.
--
-- If this true, will accept every entity; if false, reject every entity.
--
-- Will only test entities when they are added; changing this after system creation will not affect entities already in the system.
--
-- By default, rejects everything.
-- @callback
-- @tparam table e entity table to check
-- @treturn boolean true if entity should be added
filter = :(e) return false end,
--- Called when adding an entity to this system determining its order.
-- Returns true if e1 <= e2. e1 and e2 are two entities.
--
-- Used to place the entity in the sorted entity list when it is added; changing this after system creation
-- will not change the order of entities already in the system.
--
-- By default, entities are in the same order they were inserted.
-- @callback
-- @tparam table e1 entity table to check for inferiority
-- @tparam table e2 entity table to check for superiority
-- @treturn boolean true if e1 <= e2
compare = :(e1, e2) return true end,
--- Called when adding an entity to the system.
-- @callback
-- @tparam table s the entity's system table
onAdd = :(s) end,
--- Called when removing an entity from the system.
-- @callback
-- @tparam table s the entity's system table
onRemove = :(s) end,
--- Called when the system is instancied, before any call to `System:onAddToWorld` (including other systems in the world).
-- @callback
onInstance = :() end,
--- Called when the system is added to a world.
-- @callback
-- @tparam System world world system
onAddToWorld = :(world) end,
--- Called when the system is removed from a world (i.e., the world is destroyed).
-- @callback
-- @tparam System world world system
onRemoveFromWorld = :(world) end,
--- Called when the world is destroyed, after every call to `System:onRemoveFromWorld` (including other systems in the world).
-- @callback
onDestroy = :() end,
--- Called when updating the system.
-- @callback
-- @number dt delta-time since last update
onUpdate = :(dt) end,
--- Called when drawing the system.
-- @callback
onDraw = :() end,
--- Called when updating the system, for every entity the system contains. Called after `System:onUpdate` was called on the system.
-- @callback
-- @tparam table s the entity's system table
-- @number dt delta-time since last update
process = :(s, dt) end,
--- Called when drawing the system, for every entity the system contains. Called after `System:onDraw` was called on the system.
-- @callback
-- @tparam table s the entity's system table
render = :(s) end,
--- Read-only fields
-- @doc ro
--- The world the system belongs to. --- The world the system belongs to.
-- @ftype System world
-- @ro
world = nil, world = nil,
--- Number of entities in the system. --- Number of entities in the system.
-- @ftype integer
-- @ro
entityCount = 0, entityCount = 0,
--- Map of named systems in the world (not only subsystems). Same for every system from the same world. --- Map of all named systems in the world (not only subsystems). Same for every system from the same world.
-- @ftype table {[system.name]=instanciedSystem, ...}
-- @ro
s = nil, s = nil,
--- Private fields --- --- Private fields ---
--- First element of the linked list of entities: { entity, next_element }. --- First element of the linked list of entities: { entity, next_element }.
-- @local
_first = nil, _first = nil,
--- Associative map of entities in the system and their previous linked list element (or true if first element). --- Associative map of entities in the system and their previous linked list element (or true if first element).
-- This make the list effectively a doubly linked list, but with easy access to the previous element using this map (and therefore O(1) deletion). -- This make the list effectively a doubly linked list, but with easy access to the previous element using this map (and therefore O(1) deletion).
-- @local
_previous = nil, _previous = nil,
--- Amount of time waited since last update (if interval is set). --- Amount of time waited since last update (if interval is set).
-- @local
_waited = 0, _waited = 0,
--- Metatable of entities' system table. --- Metatable of entities' system table.
-- Contains the methods defined in the methods field, wrapped to be called with the correct arguments, as well as a -- Contains the methods defined in the methods field, wrapped to be called with the correct arguments, as well as a
-- __index field (if not redefined in methods). -- __index field (if not redefined in methods).
-- @local
_methods_mt = nil, _methods_mt = nil,
--- Methods --- --- Methods.
--
-- Methods available on instancied system table.
-- @doc smethods
--- Add entities to the system and its subsystems. --- Add entities to the system and its subsystems.
--
-- Will skip entities that are already in the system. -- Will skip entities that are already in the system.
--
-- Entities are added to subsystems after they were succesfully added to their parent system. -- Entities are added to subsystems after they were succesfully added to their parent system.
--
-- If this is called on a subsystem instead of the world, be warned that this will bypass all the parent's systems filters. -- If this is called on a subsystem instead of the world, be warned that this will bypass all the parent's systems filters.
-- Since :remove will not search for entities in systems where they should have been filtered out, the added entities will not be removed --
-- when calling :remove on a parent system or the world. The entity can be removed by calling :remove on the system :add was called on. -- Since `System:remove` will not search for entities in systems where they should have been filtered out, the added entities will not be removed
-- when calling :remove on a parent system or the world. The entity can be removed by calling `System:remove` on the system `System:add` was called on.
--
-- Complexity: O(1) per unordered system, O(entityCount) per ordered system. -- Complexity: O(1) per unordered system, O(entityCount) per ordered system.
-- @tparam table e entity to add
-- @tparam table... ... other entities to add
-- @treturn e,... the function arguments
add = :(e, ...) add = :(e, ...)
if e ~= nil and not @_previous[e] and @filter(e) then if e ~= nil and not @_previous[e] and @filter(e) then
-- setup entity -- setup entity
@ -213,9 +324,14 @@ let system_mt = {
end end
end, end,
--- Refresh an entity's systems. --- Refresh an entity's systems.
-- Behave similarly to :add, but if the entity is already in the system, instead of skipping it, it --
-- Behave similarly to `System:add`, but if the entity is already in the system, instead of skipping it, it
-- will check for new and removed components and add and remove from (sub)systems accordingly. -- will check for new and removed components and add and remove from (sub)systems accordingly.
--
-- Complexity: O(1) per system + add/remove complexity. -- Complexity: O(1) per system + add/remove complexity.
-- @tparam table e entity to refresh
-- @tparam table... ... other entities to refresh
-- @treturn e,... the function arguments
refresh = :(e, ...) refresh = :(e, ...)
if e ~= nil then if e ~= nil then
if not @_previous[e] then if not @_previous[e] then
@ -237,11 +353,19 @@ let system_mt = {
end end
end, end,
--- Remove entities to the system and its subsystems. --- Remove entities to the system and its subsystems.
--
-- Will skip entities that are not in the system. -- Will skip entities that are not in the system.
--
-- Entities are removed from subsystems before they are removed from their parent system. -- Entities are removed from subsystems before they are removed from their parent system.
-- If you intend to call this on a subsystem instead of the world, please read the warning in :add. --
-- If you intend to call this on a subsystem instead of the world, please read the warning in `System:add`.
--
-- Returns all removed entities. -- Returns all removed entities.
--
-- Complexity: O(1) per system. -- Complexity: O(1) per system.
-- @tparam table e entity to remove
-- @tparam table... ... other entities to remove
-- @treturn e,... the function arguments
remove = :(e, ...) remove = :(e, ...)
if e ~= nil then if e ~= nil then
if @_previous[e] then if @_previous[e] then
@ -277,7 +401,11 @@ let system_mt = {
end end
end, end,
--- Returns true if every entity is in the system. --- Returns true if every entity is in the system.
--
-- Complexity: O(1). -- Complexity: O(1).
-- @tparam table e entity that may be in the system
-- @tparam table... ... other entities that may be in the system
-- @treturn boolean true if every entity is in the system
has = :(e, ...) has = :(e, ...)
let has = e == nil or not not @_previous[e] let has = e == nil or not not @_previous[e]
if ... then if ... then
@ -287,6 +415,7 @@ let system_mt = {
end end
end, end,
--- Returns an iterator that iterate through the entties in this system. --- Returns an iterator that iterate through the entties in this system.
-- @treturn iterator iterator over the entities in this system, in order
iter = :() iter = :()
return nextEntity, { @_first } return nextEntity, { @_first }
end, end,
@ -300,7 +429,9 @@ let system_mt = {
end end
end, end,
--- Try to update the system and its subsystems. Should be called on every game update. --- Try to update the system and its subsystems. Should be called on every game update.
--
-- Subsystems are updated after their parent system. -- Subsystems are updated after their parent system.
-- @number dt delta-time since last update
update = :(dt) update = :(dt)
if @active then if @active then
if @interval then if @interval then
@ -324,6 +455,7 @@ let system_mt = {
end end
end, end,
--- Try to draw the system and its subsystems. Should be called on every game draw. --- Try to draw the system and its subsystems. Should be called on every game draw.
--
-- Subsystems are drawn after their parent system. -- Subsystems are drawn after their parent system.
draw = :() draw = :()
if @visible then if @visible then
@ -419,9 +551,12 @@ let recCallOnAddToWorld = (world, systems)
end end
--- ECS module. --- ECS module.
-- @section end
ecs = { ecs = {
--- Create and returns a world system based on a list of systems. --- Create and returns a world system based on a list of systems.
-- The systems will be instancied for this world. -- The systems will be instancied for this world.
-- @tparam table,... ... list of (uninstancied) system tables
-- @treturn System the world system
world = (...) world = (...)
let world = setmetatable({ let world = setmetatable({
filter = ecs.all(), filter = ecs.all(),
@ -435,6 +570,8 @@ ecs = {
end, end,
--- Returns a filter that returns true if, for every argument, a field with the same name exists in the entity. --- Returns a filter that returns true if, for every argument, a field with the same name exists in the entity.
-- @tparam string,... ... list of field names that must be in entity
-- @treturn function(e) that returns true if e has all the fields
all = (...) all = (...)
if ... then if ... then
let l = {...} let l = {...}
@ -452,6 +589,8 @@ ecs = {
end, end,
--- Returns a filter that returns true if one of the arguments if the name of a field in the entity. --- Returns a filter that returns true if one of the arguments if the name of a field in the entity.
-- @tparam string,... ... list of field names that may be in entity
-- @treturn function(e) that returns true if e has at leats one of the fields
any = (...) any = (...)
if ... then if ... then
let l = {...} let l = {...}
@ -468,7 +607,12 @@ ecs = {
end end
end, end,
--- If uqt.scene is available, returns a new scene that will consist of a ECS world with the specified systems and entities. --- If `uqt.scene` is available, returns a new scene that will consist of a ECS world with the specified systems and entities.
-- @require ubiquitousse.scene
-- @string name the name of the new scene
-- @tparam[opt={}] table systems list of systems to add to the world
-- @tparam[opt={}] table entities list of entities to add to the world
-- @treturn scene the new scene
scene = (name, systems={}, entities={}) scene = (name, systems={}, entities={})
assert(scene, "ubiquitousse.scene unavailable") assert(scene, "ubiquitousse.scene unavailable")
let s = scene.new(name) let s = scene.new(name)

View file

@ -45,6 +45,7 @@
-- *UPDATE*: I give up, currently in the process of admitting defat to LDoc and progressively porting all my documentation to it. -- *UPDATE*: I give up, currently in the process of admitting defat to LDoc and progressively porting all my documentation to it.
-- Though I had to modify a few things to get LDoc to like me, so the documentation is generated using [my LDoc fork](https://github.com/Reuh/LDoc). -- Though I had to modify a few things to get LDoc to like me, so the documentation is generated using [my LDoc fork](https://github.com/Reuh/LDoc).
-- --
-- @module ubiquitousse
-- @usage local ubiquitousse = require("ubiquitousse") -- @usage local ubiquitousse = require("ubiquitousse")
local p = ... -- require path local p = ... -- require path

View file

@ -3,7 +3,7 @@
-- --
-- Every unit is in pixel in the API unless written otherwise. -- Every unit is in pixel in the API unless written otherwise.
-- --
-- This modules returns a single function @{LDtk}(path). -- This modules returns a single function, @{LDtk}(path).
-- --
-- Requires LÖVE `love.graphics` (drawing Image, SpriteBatch, Quad). -- Requires LÖVE `love.graphics` (drawing Image, SpriteBatch, Quad).
-- --
@ -12,16 +12,18 @@
-- @usage -- @usage
-- local ldtk = require("ubiquitousse.ldtk") -- local ldtk = require("ubiquitousse.ldtk")
-- --
-- -- load ldtk project file
-- local project = ltdk("example.ldtk") -- local project = ltdk("example.ldtk")
-- --
-- -- can define callbacks when loading: for example to setup entities defined in LDtk
-- local callbacks = { -- local callbacks = {
-- onAddEntity = function(entity) -- onAddEntity = function(entity)
-- -- handle entity... -- -- handle entity...
-- end -- end
-- } -- }
-- --
-- -- load every level -- -- load every level, with callbacks
-- for _, lvl in ipairs(project.levels) do lvl:load() end -- for _, lvl in ipairs(project.levels) do lvl:load(callbacks) end
-- --
-- function love.draw() -- function love.draw()
-- -- draw every level -- -- draw every level
@ -412,7 +414,7 @@ let level_mt = {
-- These callbacks should allow you to capture all the important elements needed to use the level, so you can hopefully -- These callbacks should allow you to capture all the important elements needed to use the level, so you can hopefully
-- integrate it into your current game engine easily. -- integrate it into your current game engine easily.
-- --
-- @tab[opt] callbacks -- @tparam[opt] table callbacks
-- @require love -- @require love
load = :(callbacks={}) load = :(callbacks={})
assert(@loaded == false, "level already loaded") assert(@loaded == false, "level already loaded")
@ -454,7 +456,7 @@ let level_mt = {
-- * `onAddIntTile(tile)` will be called for every new IntGrid tile unloaded, with the @{IntTile} as sole argument -- * `onAddIntTile(tile)` will be called for every new IntGrid tile unloaded, with the @{IntTile} as sole argument
-- * `onAddEntity(entity)` will be called for every new entity unloaded, with the @{Entity} as sole argument -- * `onAddEntity(entity)` will be called for every new entity unloaded, with the @{Entity} as sole argument
-- --
-- @tab[opt] callbacks -- @tparam[opt] table callbacks
unload = :(callbacks={}) unload = :(callbacks={})
assert(@loaded == true, "level not loaded") assert(@loaded == true, "level not loaded")
let onRemoveLayer = callbacks.onRemoveLayer let onRemoveLayer = callbacks.onRemoveLayer
@ -581,11 +583,12 @@ let project_mt = {
project_mt.__index = project_mt project_mt.__index = project_mt
--- Custom fields. --- Custom fields.
-- TODO
-- @section fields -- @section fields
--- Module. --- LDtk module.
-- `ubiquitousse.ldtk` returns a single function, @{LDtk}. -- `ubiquitousse.ldtk` returns a single function, @{LDtk}.
-- @section module -- @section end
--- Load a LDtk project. --- Load a LDtk project.
-- @string path to LDtk project file (.ldtk) -- @string path to LDtk project file (.ldtk)