Added ecs
This commit is contained in:
parent
62cee9bd63
commit
8819e10d9e
10
ecs/.gitignore
vendored
Normal file
10
ecs/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/bower_components/
|
||||||
|
/node_modules/
|
||||||
|
/.pulp-cache/
|
||||||
|
/output/
|
||||||
|
/generated-docs/
|
||||||
|
/.psc-package/
|
||||||
|
/.psc*
|
||||||
|
/.purs*
|
||||||
|
/.psa*
|
||||||
|
/.spago
|
8
ecs/package.json
Normal file
8
ecs/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@thi.ng/ecs": "^0.7.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^4.5.2"
|
||||||
|
}
|
||||||
|
}
|
104
ecs/packages.dhall
Normal file
104
ecs/packages.dhall
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
{-
|
||||||
|
Welcome to your new Dhall package-set!
|
||||||
|
|
||||||
|
Below are instructions for how to edit this file for most use
|
||||||
|
cases, so that you don't need to know Dhall to use it.
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
Most will want to do one or both of these options:
|
||||||
|
1. Override/Patch a package's dependency
|
||||||
|
2. Add a package not already in the default package set
|
||||||
|
|
||||||
|
This file will continue to work whether you use one or both options.
|
||||||
|
Instructions for each option are explained below.
|
||||||
|
|
||||||
|
### Overriding/Patching a package
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
- Change a package's dependency to a newer/older release than the
|
||||||
|
default package set's release
|
||||||
|
- Use your own modified version of some dependency that may
|
||||||
|
include new API, changed API, removed API by
|
||||||
|
using your custom git repo of the library rather than
|
||||||
|
the package set's repo
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
where `entityName` is one of the following:
|
||||||
|
- dependencies
|
||||||
|
- repo
|
||||||
|
- version
|
||||||
|
-------------------------------
|
||||||
|
let upstream = --
|
||||||
|
in upstream
|
||||||
|
with packageName.entityName = "new value"
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Example:
|
||||||
|
-------------------------------
|
||||||
|
let upstream = --
|
||||||
|
in upstream
|
||||||
|
with halogen.version = "master"
|
||||||
|
with halogen.repo = "https://example.com/path/to/git/repo.git"
|
||||||
|
|
||||||
|
with halogen-vdom.version = "v4.0.0"
|
||||||
|
with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
### Additions
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
- Add packages that aren't already included in the default package set
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
where `<version>` is:
|
||||||
|
- a tag (i.e. "v4.0.0")
|
||||||
|
- a branch (i.e. "master")
|
||||||
|
- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977")
|
||||||
|
-------------------------------
|
||||||
|
let upstream = --
|
||||||
|
in upstream
|
||||||
|
with new-package-name =
|
||||||
|
{ dependencies =
|
||||||
|
[ "dependency1"
|
||||||
|
, "dependency2"
|
||||||
|
]
|
||||||
|
, repo =
|
||||||
|
"https://example.com/path/to/git/repo.git"
|
||||||
|
, version =
|
||||||
|
"<version>"
|
||||||
|
}
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Example:
|
||||||
|
-------------------------------
|
||||||
|
let upstream = --
|
||||||
|
in upstream
|
||||||
|
with benchotron =
|
||||||
|
{ dependencies =
|
||||||
|
[ "arrays"
|
||||||
|
, "exists"
|
||||||
|
, "profunctor"
|
||||||
|
, "strings"
|
||||||
|
, "quickcheck"
|
||||||
|
, "lcg"
|
||||||
|
, "transformers"
|
||||||
|
, "foldable-traversable"
|
||||||
|
, "exceptions"
|
||||||
|
, "node-fs"
|
||||||
|
, "node-buffer"
|
||||||
|
, "node-readline"
|
||||||
|
, "datetime"
|
||||||
|
, "now"
|
||||||
|
]
|
||||||
|
, repo =
|
||||||
|
"https://github.com/hdgarrood/purescript-benchotron.git"
|
||||||
|
, version =
|
||||||
|
"v7.0.0"
|
||||||
|
}
|
||||||
|
-------------------------------
|
||||||
|
-}
|
||||||
|
let upstream =
|
||||||
|
https://github.com/purescript/package-sets/releases/download/psc-0.14.5-20211116/packages.dhall sha256:7ba810597a275e43c83411d2ab0d4b3c54d0b551436f4b1632e9ff3eb62e327a
|
||||||
|
|
||||||
|
in upstream
|
185
ecs/pnpm-lock.yaml
Normal file
185
ecs/pnpm-lock.yaml
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
lockfileVersion: 5.3
|
||||||
|
|
||||||
|
specifiers:
|
||||||
|
'@thi.ng/ecs': ^0.7.2
|
||||||
|
typescript: ^4.5.2
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/ecs': 0.7.2
|
||||||
|
|
||||||
|
devDependencies:
|
||||||
|
typescript: 4.5.2
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
/@thi.ng/api/8.3.2:
|
||||||
|
resolution: {integrity: sha512-sZBbrBtSzXQlCcyxkFwOysvvU9bqcsEQJCqSpxtSmju16c1RjDGLQ/hdv755QRBkNywKykypNBwutUtpaejUfA==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/arrays/2.1.2:
|
||||||
|
resolution: {integrity: sha512-QS0uJFln7xeCyJcDtqjXdov1ta7PMSYjrb17AjjUvSfvPUkLArCJMVTJBl4k9QrFirp8N3Blc1e8xZJgeK9lrg==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/compare': 2.1.2
|
||||||
|
'@thi.ng/equiv': 2.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/random': 3.2.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/associative/6.1.2:
|
||||||
|
resolution: {integrity: sha512-Bf1gncNPmAxe6j4cRMhi0nj+2qLUVQznA2VA5U+pqMoI42mOf8zvC28U0GpUzJ+9h53Sv6+P11oDHEQs6qsleA==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/arrays': 2.1.2
|
||||||
|
'@thi.ng/binary': 3.1.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/compare': 2.1.2
|
||||||
|
'@thi.ng/dcons': 3.1.2
|
||||||
|
'@thi.ng/equiv': 2.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/transducers': 8.1.2
|
||||||
|
tslib: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/binary/3.1.2:
|
||||||
|
resolution: {integrity: sha512-7PajvPvxT8iG0c4xPg9v/x7tiTWESz/VQMIHvX3pT9mO0wqKJoc4jWUFXCnWqHItnBwNsuEvRPI6I8KjqPnXIg==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/checks/3.1.2:
|
||||||
|
resolution: {integrity: sha512-DyypenoE0bh7hpeBDihHaPqxJmUe2AtQI9dcyGwkizjmaanBSHzJlfckkz46CYoDcq51DnJWn23+GLVJ3qFYhA==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/compare/2.1.2:
|
||||||
|
resolution: {integrity: sha512-0BmxdiG9ybDlzA03dCt6fisjhx9eyP81ODD9JNHT+rNuizt6SApzywjvr+J2GT5HG76SzaSQE8WpvGbScwAS8Q==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/compose/2.1.2:
|
||||||
|
resolution: {integrity: sha512-z0d6G2y3vYlR5IJRn0ehTSyk+2bLhQwnQXxr7EBADq7qlARu0Wco0WIkO2y6FmLDF2M4NKvho8F9K1iqt1jXyQ==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/dcons/3.1.2:
|
||||||
|
resolution: {integrity: sha512-RPxxa0DCbmZ4Y9+ffP6WRv6zbwcH14gthxhDycAnpplryu4vgIjNeOV2XW80S2qAINN2RDkC52jO7iA30HzDIw==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/compare': 2.1.2
|
||||||
|
'@thi.ng/equiv': 2.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/random': 3.2.2
|
||||||
|
'@thi.ng/transducers': 8.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/ecs/0.7.2:
|
||||||
|
resolution: {integrity: sha512-HeEIif+gJm57sdlnWURUrUi/kKWUfc1P/dGk6CNuo4Sg1fo8XPCWR5y2dSLN+dsUyMlw9LAJWR/rvhDOwK//6w==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/associative': 6.1.2
|
||||||
|
'@thi.ng/binary': 3.1.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/dcons': 3.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/idgen': 2.1.2
|
||||||
|
'@thi.ng/logger': 1.1.2
|
||||||
|
'@thi.ng/malloc': 6.1.2
|
||||||
|
'@thi.ng/transducers': 8.1.2
|
||||||
|
tslib: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/equiv/2.1.2:
|
||||||
|
resolution: {integrity: sha512-S0QZmWXIO5d/TQSLsyFLYT3/j9nKRuJMUEJYz8seFnQQ9ydrAjV4o5pIHbXiWnjllHAWYa/iN6LJ8xuV8nXxag==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/errors/2.1.2:
|
||||||
|
resolution: {integrity: sha512-3XdabkDNqrL76HVlt3q01zqMRLnSB8FFjJchiYWT/RVkAI2OBogE+eBy4KhYc0mvssYPfdnP9ikjDrV1CC2rVg==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/hex/2.1.2:
|
||||||
|
resolution: {integrity: sha512-JFUApXIn7HWFYEZMQLtf9rZ1aeXFFI8ggdJrA45PzVC0kl73J8yeRHlXn3kjV7spd7jk7oatdEm4JnvadbT4EQ==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/idgen/2.1.2:
|
||||||
|
resolution: {integrity: sha512-15jngVT0kdlrWeTfeXnLBTN8RZW7nCrs2r8c2dj3OGm8cbQDwnd9LxwlYMhu37flMTG55cFiVbiftTK6TEvGWA==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
tslib: 2.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/logger/1.1.2:
|
||||||
|
resolution: {integrity: sha512-zMUAkz7TJ6maTxerWiimGdoCsKR+v1kCyTkRxT1ii0dtTkvhtjhSPpnFAIMM/S4+7PdKxpiTqAl3oFNTt+EN7A==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/malloc/6.1.2:
|
||||||
|
resolution: {integrity: sha512-PPAJmN17CS+HhmKCwFrgXYNXsSSs5zRZJdE5CsCqvvKHnKg+YsAoHFudkmmpIilLdCzFkyZK6gHBT+63jD/xbw==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/binary': 3.1.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/math/5.1.2:
|
||||||
|
resolution: {integrity: sha512-iOzs+cy19sxlOxk6OW5xDx5+rsvbXahqOf9Y323zs14VPS/I7rJl9SMY2F5MDbxZf65m3si6nolzOVW0a52C4Q==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/random/3.2.2:
|
||||||
|
resolution: {integrity: sha512-QJD+F2kXfFyTI//EEVnVHP4XdeBhm9tlxavaAZizfIRKwWWxhrAHdk8BDPnN3nQe74Ana6UZy2NMrb3nb0A/gQ==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/hex': 2.1.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@thi.ng/transducers/8.1.2:
|
||||||
|
resolution: {integrity: sha512-nMZNrMA8yJfvFpVtIYF31bBHsGJGadci+I3/VqUBneBfWM2aFbJcOjYAyLq7Xe15RBTx9eGfBikPGTcvz5ILfA==}
|
||||||
|
engines: {node: '>=12.7'}
|
||||||
|
dependencies:
|
||||||
|
'@thi.ng/api': 8.3.2
|
||||||
|
'@thi.ng/arrays': 2.1.2
|
||||||
|
'@thi.ng/checks': 3.1.2
|
||||||
|
'@thi.ng/compare': 2.1.2
|
||||||
|
'@thi.ng/compose': 2.1.2
|
||||||
|
'@thi.ng/errors': 2.1.2
|
||||||
|
'@thi.ng/math': 5.1.2
|
||||||
|
'@thi.ng/random': 3.2.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/tslib/2.3.1:
|
||||||
|
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/typescript/4.5.2:
|
||||||
|
resolution: {integrity: sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==}
|
||||||
|
engines: {node: '>=4.2.0'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
26
ecs/spago.dhall
Normal file
26
ecs/spago.dhall
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{-
|
||||||
|
Welcome to a Spago project!
|
||||||
|
You can edit this file as you like.
|
||||||
|
|
||||||
|
Need help? See the following resources:
|
||||||
|
- Spago documentation: https://github.com/purescript/spago
|
||||||
|
- Dhall language tour: https://docs.dhall-lang.org/tutorials/Language-Tour.html
|
||||||
|
|
||||||
|
When creating a new Spago project, you can use
|
||||||
|
`spago init --no-comments` or `spago init -C`
|
||||||
|
to generate this file without the comments in this block.
|
||||||
|
-}
|
||||||
|
{ name = "my-project"
|
||||||
|
, dependencies =
|
||||||
|
[ "arraybuffer-types"
|
||||||
|
, "console"
|
||||||
|
, "effect"
|
||||||
|
, "heterogeneous"
|
||||||
|
, "lazy"
|
||||||
|
, "prelude"
|
||||||
|
, "psci-support"
|
||||||
|
, "undefined-is-not-a-problem"
|
||||||
|
]
|
||||||
|
, packages = ./packages.dhall
|
||||||
|
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||||
|
}
|
10
ecs/src/Main.purs
Normal file
10
ecs/src/Main.purs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Console (log)
|
||||||
|
|
||||||
|
main :: Effect Unit
|
||||||
|
main = do
|
||||||
|
log "🍝"
|
43
ecs/src/Types.js
Normal file
43
ecs/src/Types.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// @ts-check
|
||||||
|
const ecs = require("@thi.ng/ecs");
|
||||||
|
|
||||||
|
exports.makeEcs =
|
||||||
|
({ size, components }) =>
|
||||||
|
() => {
|
||||||
|
const thisEcs = new ecs.ECS({
|
||||||
|
capacity: size,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const key in components) {
|
||||||
|
const component = { id: key };
|
||||||
|
Object.assign(component, components[key]);
|
||||||
|
thisEcs.defComponent(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ecs;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.unsafeCreateEntity = (components, /** @type {ecs.ECS} */ ecs) => {
|
||||||
|
return ecs.defEntity(components);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.deleteEntity =
|
||||||
|
(/** @type {number} */ id) => (/** @type {ecs.ECS} */ ecs) => () => {
|
||||||
|
return ecs.deleteID(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.unsafeCreateGroup = (
|
||||||
|
components,
|
||||||
|
owned,
|
||||||
|
opts,
|
||||||
|
/** @type {ecs.ECS} */ ecs
|
||||||
|
) => {
|
||||||
|
return ecs.defGroup(components, owned, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.unsafeGetComponentManager = (
|
||||||
|
/** @type {string} */ name,
|
||||||
|
/** @type {ecs.ECS} */ ecs
|
||||||
|
) => {
|
||||||
|
return ecs.components.get(name);
|
||||||
|
};
|
227
ecs/src/Types.purs
Normal file
227
ecs/src/Types.purs
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
module Thing.Ecs.Types
|
||||||
|
( Cache
|
||||||
|
, ComponentManager
|
||||||
|
, ComponentSet
|
||||||
|
, ComponentSpec
|
||||||
|
, Ecs
|
||||||
|
, EcsSpec
|
||||||
|
, EntityId
|
||||||
|
, Group
|
||||||
|
, GroupSpec
|
||||||
|
, MakeComponentSet
|
||||||
|
, MemMappedComponent
|
||||||
|
, MemPool
|
||||||
|
, OpaqueComponentManager
|
||||||
|
, SelectGroupComponents
|
||||||
|
, createEntity
|
||||||
|
, createGroup
|
||||||
|
, deleteEntity
|
||||||
|
, makeComponentSet
|
||||||
|
, makeEcs
|
||||||
|
, unsafeCreateEntity
|
||||||
|
, unsafeCreateGroup
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.ArrayBuffer.Types (ArrayBuffer)
|
||||||
|
import Data.List (List)
|
||||||
|
import Data.List as List
|
||||||
|
import Data.Symbol (class IsSymbol, reflectSymbol)
|
||||||
|
import Data.Undefined.NoProblem (Opt)
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Uncurried (EffectFn2, EffectFn4, runEffectFn2, runEffectFn4)
|
||||||
|
import Heterogeneous.Folding (class FoldingWithIndex, class HFoldlWithIndex, hfoldlWithIndex)
|
||||||
|
import Heterogeneous.Mapping (class HMap, class Mapping)
|
||||||
|
import Prim.Row as Row
|
||||||
|
import Prim.RowList as RL
|
||||||
|
import Type.Data.RowList (RLProxy(..))
|
||||||
|
import Type.Proxy (Proxy)
|
||||||
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
|
||||||
|
-- | The entity component system is the core of the library.
|
||||||
|
-- | This is an opaque type, used by the different helpers provided by this library.
|
||||||
|
data Ecs :: Row Type -> Type
|
||||||
|
data Ecs components
|
||||||
|
|
||||||
|
-- | A group is what keeps track of the intersection of multiple component managers
|
||||||
|
data Group :: Row Type -> Type
|
||||||
|
data Group components
|
||||||
|
|
||||||
|
-- | A component manager is the class which manages the lifetime of a particular component
|
||||||
|
data ComponentManager :: Symbol -> Type -> Type
|
||||||
|
data ComponentManager name component
|
||||||
|
|
||||||
|
data OpaqueComponentManager
|
||||||
|
|
||||||
|
-- | Unique id identifying an entity
|
||||||
|
newtype EntityId :: Type
|
||||||
|
newtype EntityId = EntityId Int
|
||||||
|
|
||||||
|
---------- Configuration options
|
||||||
|
-- | Opaque type which represents instances of classes which implement [ICache](https://docs.thi.ng/umbrella/ecs/interfaces/ICache.html)
|
||||||
|
data Cache
|
||||||
|
|
||||||
|
-- | A memory mapped component should lead to more efficient iteration speed (?)
|
||||||
|
-- | and somewhat easy interop with the gpu
|
||||||
|
type MemMappedComponent =
|
||||||
|
{ buffer :: Opt ArrayBuffer
|
||||||
|
, byteOffset :: Opt Int
|
||||||
|
, size :: Opt Int
|
||||||
|
, stride :: Opt Int
|
||||||
|
, cache :: Opt Cache
|
||||||
|
, type :: String -- TODO: fix this
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | An individual component spec specifies how a manager stores it's components
|
||||||
|
data ComponentSpec :: forall k. k -> Type
|
||||||
|
data ComponentSpec a
|
||||||
|
-- | An object component manager can store any javascript value. Useful when the size of the data is not constant
|
||||||
|
= ObjectComponent
|
||||||
|
|
||||||
|
| MemMappedComponent MemMappedComponent
|
||||||
|
|
||||||
|
-- | A component set is just a set of configurations
|
||||||
|
-- | for the components specified by the given row type.
|
||||||
|
data ComponentSet :: Row Type -> Type
|
||||||
|
data ComponentSet components
|
||||||
|
|
||||||
|
-- | Opaque type which represents classes implementing [IMemPoolArray](https://docs.thi.ng/umbrella/malloc/interfaces/imempoolarray.html)
|
||||||
|
data MemPool
|
||||||
|
|
||||||
|
-- TODO: add custom object pool setting
|
||||||
|
-- | The config required to build an ecs
|
||||||
|
type EcsSpec components =
|
||||||
|
{
|
||||||
|
-- | The maximum amount of entities in the system at one point in time
|
||||||
|
size :: Int
|
||||||
|
|
||||||
|
-- | Optional custom implementation of entity allocation / deallocation
|
||||||
|
, pool :: Opt MemPool
|
||||||
|
|
||||||
|
-- | Configuration for all components in the entity component system
|
||||||
|
, components :: ComponentSet components
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Options for creating a group
|
||||||
|
type GroupSpec =
|
||||||
|
{ id :: Opt String
|
||||||
|
, cache :: Opt Cache
|
||||||
|
}
|
||||||
|
|
||||||
|
---------- Component set creation
|
||||||
|
-- | Typelevel tag for the operation of creating component specs.
|
||||||
|
-- | Internal to this module. Exporting can lead to unsafe code.
|
||||||
|
data MakeComponentSet
|
||||||
|
|
||||||
|
-- | Instance used to compute the record of component specs at the typelevel
|
||||||
|
instance Mapping MakeComponentSet n (ComponentSpec n) where
|
||||||
|
mapping = unsafeCoerce
|
||||||
|
|
||||||
|
-- | Dummy function to remove typeclass constrains from a set of component specs
|
||||||
|
makeComponentSet
|
||||||
|
:: forall components specs
|
||||||
|
. HMap MakeComponentSet (Record components) (Record specs)
|
||||||
|
=> Record specs
|
||||||
|
-> ComponentSet components
|
||||||
|
makeComponentSet = unsafeCoerce
|
||||||
|
|
||||||
|
---------- Helpers
|
||||||
|
createEntity
|
||||||
|
:: forall components provided remaining
|
||||||
|
. Row.Union provided remaining components
|
||||||
|
=> Record provided
|
||||||
|
-> Ecs components
|
||||||
|
-> Effect EntityId
|
||||||
|
createEntity = runEffectFn2 unsafeCreateEntity
|
||||||
|
|
||||||
|
---------- Gruop creation
|
||||||
|
createGroup
|
||||||
|
:: forall components group remaining owned remaining' grl orl
|
||||||
|
. Row.Union group remaining components
|
||||||
|
=> Row.Union owned remaining' components
|
||||||
|
=> RL.RowToList owned orl
|
||||||
|
=> RL.RowToList group grl
|
||||||
|
=> HFoldlWithIndex SelectGroupComponents
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
(RLProxy grl)
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
=> HFoldlWithIndex SelectGroupComponents
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
(RLProxy orl)
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
=> Proxy group
|
||||||
|
-> Proxy owned
|
||||||
|
-> GroupSpec
|
||||||
|
-> Ecs components
|
||||||
|
-> Effect (Group remaining)
|
||||||
|
createGroup _ _ options ecs = runEffectFn4 unsafeCreateGroup
|
||||||
|
( List.toUnfoldable $ hfoldlWithIndex
|
||||||
|
SelectGroupComponents
|
||||||
|
(const List.Nil :: Ecs components -> List OpaqueComponentManager)
|
||||||
|
_selected
|
||||||
|
ecs
|
||||||
|
)
|
||||||
|
|
||||||
|
( List.toUnfoldable $ hfoldlWithIndex
|
||||||
|
SelectGroupComponents
|
||||||
|
(const List.Nil :: Ecs components -> List OpaqueComponentManager)
|
||||||
|
_owned
|
||||||
|
ecs
|
||||||
|
)
|
||||||
|
options
|
||||||
|
ecs
|
||||||
|
where
|
||||||
|
_owned :: RLProxy orl
|
||||||
|
_owned = RLProxy
|
||||||
|
|
||||||
|
_selected :: RLProxy grl
|
||||||
|
_selected = RLProxy
|
||||||
|
|
||||||
|
data SelectGroupComponents = SelectGroupComponents
|
||||||
|
|
||||||
|
instance
|
||||||
|
( IsSymbol key
|
||||||
|
) =>
|
||||||
|
FoldingWithIndex SelectGroupComponents
|
||||||
|
(Proxy key)
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
(Proxy ty)
|
||||||
|
(Ecs components -> List OpaqueComponentManager)
|
||||||
|
where
|
||||||
|
foldingWithIndex _ key previous _ ecs = List.Cons
|
||||||
|
(unsafeGetComponentManager name ecs)
|
||||||
|
(previous ecs)
|
||||||
|
where
|
||||||
|
name = reflectSymbol key
|
||||||
|
|
||||||
|
---------- Foreign imports
|
||||||
|
-- | Unsafe version of makeEcs
|
||||||
|
foreign import makeEcs
|
||||||
|
:: forall result components
|
||||||
|
. EcsSpec components
|
||||||
|
-> (Ecs components -> result)
|
||||||
|
-> Effect result
|
||||||
|
|
||||||
|
-- | Foreign, unsafe way of adding an entity to an ecs
|
||||||
|
foreign import unsafeCreateEntity
|
||||||
|
:: forall a b
|
||||||
|
. EffectFn2
|
||||||
|
(Record a)
|
||||||
|
(Ecs b)
|
||||||
|
EntityId
|
||||||
|
|
||||||
|
-- | Unsafe version of createGroup
|
||||||
|
foreign import unsafeCreateGroup
|
||||||
|
:: forall a b
|
||||||
|
. EffectFn4
|
||||||
|
(Array OpaqueComponentManager)
|
||||||
|
(Array OpaqueComponentManager)
|
||||||
|
GroupSpec
|
||||||
|
(Ecs a)
|
||||||
|
(Group b)
|
||||||
|
|
||||||
|
-- | Deletes an entity from the system
|
||||||
|
foreign import deleteEntity :: forall components. EntityId -> Ecs components -> Effect Boolean
|
||||||
|
|
||||||
|
foreign import unsafeGetComponentManager :: forall components. String -> Ecs components -> OpaqueComponentManager
|
40
ecs/src/Utils/Keys.purs
Normal file
40
ecs/src/Utils/Keys.purs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
-- | Modified version of the code from [record-extra](https://github.com/justinwoo/purescript-record-extra/blob/v4.0.0/src/Record/Extra.purs#L123-L127)
|
||||||
|
-- | I did not like how that lib used lists, so I modified it to output to an (initially) mutable array
|
||||||
|
module Thing.Ecs.Utils.Keys (keys, class Keys, keysImpl) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Monad.ST (ST)
|
||||||
|
import Data.Array.ST (STArray)
|
||||||
|
import Data.Array.ST as STArray
|
||||||
|
import Data.Symbol (class IsSymbol, reflectSymbol)
|
||||||
|
import Prim.RowList as RL
|
||||||
|
import Type.Proxy (Proxy(..))
|
||||||
|
|
||||||
|
-- | Typeclass jk
|
||||||
|
class Keys (xs :: RL.RowList Type) where
|
||||||
|
keysImpl :: forall r. Proxy xs -> ST r (STArray r String)
|
||||||
|
|
||||||
|
instance Keys RL.Nil where
|
||||||
|
keysImpl _ = STArray.empty
|
||||||
|
|
||||||
|
instance
|
||||||
|
( IsSymbol name
|
||||||
|
, Keys tail
|
||||||
|
) =>
|
||||||
|
Keys (RL.Cons name ty tail) where
|
||||||
|
keysImpl _ = do
|
||||||
|
rest <- keysImpl (Proxy :: _ tail)
|
||||||
|
_ <- STArray.push first rest
|
||||||
|
pure rest
|
||||||
|
where
|
||||||
|
first = reflectSymbol (Proxy :: _ name)
|
||||||
|
|
||||||
|
-- | Extract a value level array of the keys of a row
|
||||||
|
keys
|
||||||
|
:: forall g row rl
|
||||||
|
. RL.RowToList row rl
|
||||||
|
=> Keys rl
|
||||||
|
=> g row -- this will work for any type with the row as a param!
|
||||||
|
-> Array String
|
||||||
|
keys _ = STArray.run (keysImpl (Proxy :: _ rl))
|
11
ecs/test/Main.purs
Normal file
11
ecs/test/Main.purs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module Test.Main where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Effect (Effect)
|
||||||
|
import Effect.Class.Console (log)
|
||||||
|
|
||||||
|
main :: Effect Unit
|
||||||
|
main = do
|
||||||
|
log "🍝"
|
||||||
|
log "You should add some tests."
|
101
ecs/tsconfig.json
Normal file
101
ecs/tsconfig.json
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
|
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||||
|
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
|
||||||
|
/* Modules */
|
||||||
|
"module": "commonjs" /* Specify what module code is generated. */,
|
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||||
|
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "resolveJsonModule": true, /* Enable importing .json files */
|
||||||
|
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
|
||||||
|
|
||||||
|
/* Emit */
|
||||||
|
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||||
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||||
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||||
|
|
||||||
|
/* Interop Constraints */
|
||||||
|
"isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */,
|
||||||
|
"allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */,
|
||||||
|
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue