early experimentation, no modifiers yet

This commit is contained in:
Ronja 2021-07-10 19:43:40 +02:00
parent 12466b5d4e
commit 70edf6d864
11 changed files with 1372 additions and 25 deletions

17
.vscode/tasks.json vendored
View file

@ -1,17 +0,0 @@
{
"tasks": [
{
"type": "luxe",
"script": "run",
"problemMatcher": [
"$luxe-absolute",
"$luxe-relative"
],
"group": {
"kind": "build",
"isDefault": true
},
"label": "luxe: run - Build & Run the project"
}
]
}

View file

@ -0,0 +1,188 @@
prototype = {
elements = {
bone4 = {
modifiers = {
transform = {
pos = [79.12 -28.1 0] //pos
link = "f715d4cc-48e0-4296-8307-bacbf2cac978"
type = "luxe: modifier/transform"
rotation = [0 0 33.19] //rotation
} //transform
} //modifiers
uuid = "c69a08b1-a28b-4761-956b-636d298bffc6"
} //bone4
ekorn = {
modifiers = {
transform = {
pos = [-44.72 35.68 0] //pos
link = "45852121-f880-44de-8490-b8dad645a7b0"
type = "luxe: modifier/transform"
rotation = [0 0 73.74] //rotation
} //transform
} //modifiers
uuid = "91621243-27fb-437b-b200-13e3746af7f3"
} //ekorn
root = {
modifiers = {
transform = {
type = "luxe: modifier/transform"
} //transform
} //modifiers
uuid = "45852121-f880-44de-8490-b8dad645a7b0"
} //root
bone2 = {
modifiers = {
transform = {
pos = [80.92 -0.23 0] //pos
link = "91621243-27fb-437b-b200-13e3746af7f3"
type = "luxe: modifier/transform"
rotation = [0 0 25.16] //rotation
} //transform
} //modifiers
uuid = "f715d4cc-48e0-4296-8307-bacbf2cac978"
} //bone2
bone7 = {
modifiers = {
transform = {
pos = [45.52 0 0] //pos
link = "c51c3eb5-0406-4431-8bfb-6eeffb528e70"
type = "luxe: modifier/transform"
rotation = [0 0 -10.57] //rotation
} //transform
} //modifiers
uuid = "bad44ae5-9512-48fe-ae74-3dcf23478347"
} //bone7
bone14 = {
modifiers = {
transform = {
pos = [63.28 1.15 0] //pos
link = "8605bf9f-4a59-409c-8eb4-d0b74959151f"
type = "luxe: modifier/transform"
rotation = [0 0 23.82] //rotation
} //transform
} //modifiers
uuid = "f85ae39a-98a3-4c53-bd4c-269888f87b8b"
} //bone14
bone13 = {
modifiers = {
transform = {
pos = [88.99 3.78 0] //pos
link = "9adfb00a-555e-4582-ba8e-1a0e234af982"
type = "luxe: modifier/transform"
rotation = [0 0 39.58] //rotation
} //transform
} //modifiers
uuid = "8605bf9f-4a59-409c-8eb4-d0b74959151f"
} //bone13
bone5 = {
modifiers = {
transform = {
pos = [113.11 84.9 0] //pos
link = "91621243-27fb-437b-b200-13e3746af7f3"
type = "luxe: modifier/transform"
rotation = [0 0 75.02] //rotation
} //transform
} //modifiers
uuid = "f50404e9-8c32-4dac-a2d3-95fb2edbeac9"
} //bone5
pinnsvin = {
modifiers = {
transform = {
pos = [23.09 38.13 0] //pos
link = "45852121-f880-44de-8490-b8dad645a7b0"
type = "luxe: modifier/transform"
rotation = [0 0 68.96] //rotation
} //transform
} //modifiers
uuid = "c51c3eb5-0406-4431-8bfb-6eeffb528e70"
} //pinnsvin
bone11 = {
modifiers = {
transform = {
pos = [73.6 32.01 0] //pos
link = "9adfb00a-555e-4582-ba8e-1a0e234af982"
type = "luxe: modifier/transform"
rotation = [0 0 48.43] //rotation
} //transform
} //modifiers
uuid = "7113588f-f121-496a-8da2-b765c867685f"
} //bone11
ekorn2 = {
modifiers = {
transform = {
pos = [-79.85 57.74 0] //pos
link = "45852121-f880-44de-8490-b8dad645a7b0"
type = "luxe: modifier/transform"
rotation = [0 0 90] //rotation
} //transform
} //modifiers
uuid = "f0d5d66c-9477-44f3-b4f2-abf87703fcd2"
} //ekorn2
bone3 = {
modifiers = {
transform = {
pos = [62.87 26.54 0] //pos
link = "f715d4cc-48e0-4296-8307-bacbf2cac978"
type = "luxe: modifier/transform"
rotation = [0 0 49.88] //rotation
} //transform
} //modifiers
uuid = "cae3d09e-9117-4e1c-98dd-624e204300df"
} //bone3
bone8 = {
modifiers = {
transform = {
pos = [34.49 -19.12 0] //pos
link = "c51c3eb5-0406-4431-8bfb-6eeffb528e70"
type = "luxe: modifier/transform"
rotation = [0 0 -101.82] //rotation
} //transform
} //modifiers
uuid = "9477662d-bbb8-44a4-ba0c-de84ddef8544"
} //bone8
bone12 = {
modifiers = {
transform = {
pos = [62.44 0.08 0] //pos
link = "7113588f-f121-496a-8da2-b765c867685f"
type = "luxe: modifier/transform"
rotation = [0 0 22.8] //rotation
} //transform
} //modifiers
uuid = "da3f7d83-b150-451d-9b63-1c9291b27941"
} //bone12
bone15 = {
modifiers = {
transform = {
pos = [148.91 92.05 0] //pos
link = "45852121-f880-44de-8490-b8dad645a7b0"
type = "luxe: modifier/transform"
rotation = [0 0 -43.36] //rotation
} //transform
} //modifiers
uuid = "3aa06ed0-f0cc-4ab9-b19a-2f9bcdfe1b0a"
} //bone15
bone10 = {
modifiers = {
transform = {
pos = [72.36 -0.35 0] //pos
link = "9bb58df9-660a-4ee4-afb1-a237b29ea342"
type = "luxe: modifier/transform"
rotation = [0 0 23.75] //rotation
} //transform
} //modifiers
uuid = "9adfb00a-555e-4582-ba8e-1a0e234af982"
} //bone10
bunny = {
modifiers = {
transform = {
pos = [106.42 38.95 0] //pos
link = "45852121-f880-44de-8490-b8dad645a7b0"
type = "luxe: modifier/transform"
rotation = [0 0 64.87] //rotation
} //transform
} //modifiers
uuid = "9bb58df9-660a-4ee4-afb1-a237b29ea342"
} //bunny
} //elements
} //prototype

View file

@ -0,0 +1,15 @@
modifier = {
description = "Renders Spine asets"
field = "spine_renderer"
display = "Spine Renderer"
class = "SpineRenderer"
dependency = []
blocks = {
data = {
fields = [
{ name="asset" type="string" default="" }
]
}
}
}

View file

@ -0,0 +1,473 @@
//-- this file is generated! don't try editing it.
import "luxe: io" for IO
import "luxe: bytes" for Byter, Bytes
import "luxe: world" for Block
//`modifiers/spine_renderer > runtime` types
class ModifierRuntime {
construct new() {
} //new
} //ModifierRuntime
//`modifiers/spine_renderer > runtime` compilers
class ModifierRuntimeCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
return out
} //write
bytes_count_block() {
return 8
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/spine_renderer > runtime"))
//fields count
out.write_int32(0)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMRTM")
write(instance, out)
return out
} //write
} //ModifierRuntimeCompiler
//`modifiers/spine_renderer > runtime` block types
class BlockModifierRuntime {
field { "spine_renderer" }
source { "modifiers/spine_renderer > runtime" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/spine_renderer > runtime")
} //new
instance_type {
class BlockInstModifierRuntime {
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierRuntime
return BlockInstModifierRuntime
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierRuntime
//`modifiers/spine_renderer > data` types
class ModifierData {
construct new() {
_asset = ""
} //new
asset { _asset }
asset=(vvv) { _asset = vvv }
} //ModifierData
//`modifiers/spine_renderer > data` compilers
class ModifierDataCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 4 //asset length
var asset = instance["asset"]
if(asset == null) asset = ""
var asset_len = asset.bytes.count
var asset_size = asset_len + Bytes.padding(asset_len)
size = size + asset_size
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
"asset": false,
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
var asset = instance["asset"]
if(asset == null) asset = ""
out.write_int32(asset.bytes.count)
out.write_string_aligned4(asset)
return out
} //write
bytes_count_block() {
return 16
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/spine_renderer > data"))
//fields count
out.write_int32(1)
// asset
out.write_uint32(compiler.string.hash("asset"))
out.write_uint32(398550328) //type string
var asset_default = ""
out.write_int32(asset_default.bytes.count)
out.write_string_aligned4(asset_default)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMDTA")
write(instance, out)
return out
} //write
} //ModifierDataCompiler
//`modifiers/spine_renderer > data` block types
class BlockModifierData {
field { "spine_renderer" }
source { "modifiers/spine_renderer > data" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.add(_block, "asset", "string", "")
Block.set_type(_block, "modifiers/spine_renderer > data")
} //new
instance_type {
class BlockInstModifierData {
asset { Block.get(_block, "asset", _slot) }
asset=(v) { Block.set(_block, "asset", _slot, v) }
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierData
return BlockInstModifierData
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierData
//`modifiers/spine_renderer > world` types
class ModifierWorld {
construct new() {
} //new
} //ModifierWorld
//`modifiers/spine_renderer > world` compilers
class ModifierWorldCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
return out
} //write
bytes_count_block() {
return 8
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/spine_renderer > world"))
//fields count
out.write_int32(0)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMWLD")
write(instance, out)
return out
} //write
} //ModifierWorldCompiler
//`modifiers/spine_renderer > world` block types
class BlockModifierWorld {
field { "spine_renderer" }
source { "modifiers/spine_renderer > world" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/spine_renderer > world")
} //new
instance_type {
class BlockInstModifierWorld {
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierWorld
return BlockInstModifierWorld
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierWorld

View file

@ -0,0 +1,51 @@
import "luxe: io" for IO
import "luxe: world" for World, Entity, Modifiers, ModifierSystem
//User facing API
//This is what the user of your modifier will interact with
class SpineRenderer {
static create(entity) { Modifiers.create(This, entity) }
static destroy(entity) { Modifiers.destroy(This, entity) }
static has(entity) { Modifiers.has(This, entity) }
} //SpineRenderer
//Your modifier system implementation.
//This speaks to the engine and your user facing API
//to do the actual work. You'll get notified when things change
//in the world and respond to them here.
class SpineRendererSystem is ModifierSystem {
construct new() {
//called when your system is first created.
}
init(world) {
_world = world
//called when your modifier is created in a world
}
destroy() {
//called when your modifier is removed from a world
}
attach(entity, data) {
//called when attached to an entity
}
detach(entity, data) {
//called when detached from an entity, like on destroy
}
tick(delta) {
//called usually once every frame.
//called when the world that this modifier lives in, is ticked
each {|entity, data|
//use data.*
}
} //tick
} //SpineRendererSystem
var Modifier = SpineRendererSystem //required

View file

@ -0,0 +1,18 @@
modifier = {
description = "A slot on the playing field"
field = "slot"
display = "Slot"
class = "Slot"
dependency = []
blocks = {
data = {
fields = [
{ name="coord" type="float3" default=[0, 0, 0] }
{ name="auto_naming" type="boolean" default=false }
{ name="field" type="id32" editor="entity" default="" }
]
}
}
}

View file

@ -0,0 +1,514 @@
//-- this file is generated! don't try editing it.
import "luxe: io" for IO
import "luxe: bytes" for Byter, Bytes
import "luxe: world" for Block
//`modifiers/test_modifier > runtime` types
class ModifierRuntime {
construct new() {
} //new
} //ModifierRuntime
//`modifiers/test_modifier > runtime` compilers
class ModifierRuntimeCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
return out
} //write
bytes_count_block() {
return 8
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/test_modifier > runtime"))
//fields count
out.write_int32(0)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMRTM")
write(instance, out)
return out
} //write
} //ModifierRuntimeCompiler
//`modifiers/test_modifier > runtime` block types
class BlockModifierRuntime {
field { "slot" }
source { "modifiers/test_modifier > runtime" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/test_modifier > runtime")
} //new
instance_type {
class BlockInstModifierRuntime {
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierRuntime
return BlockInstModifierRuntime
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierRuntime
//`modifiers/test_modifier > data` types
class ModifierData {
construct new() {
_coord = [0, 0, 0]
_auto_naming = false
_field = ""
} //new
coord { _coord }
coord=(vvv) { _coord = vvv }
auto_naming { _auto_naming }
auto_naming=(vvv) { _auto_naming = vvv }
field { _field }
field=(vvv) { _field = vvv }
} //ModifierData
//`modifiers/test_modifier > data` compilers
class ModifierDataCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 12 // coord
size = size + 4 // auto_naming
size = size + 4 // field
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
"coord": false,
"auto_naming": false,
"field": false,
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
var coord = instance["coord"]
if(coord == null) coord = [0, 0, 0]
out.write_float32(coord[0])
out.write_float32(coord[1])
out.write_float32(coord[2])
var auto_naming = instance["auto_naming"]
if(auto_naming == null) auto_naming = false
out.write_int32(auto_naming ? 1 : 0)
var field = instance["field"]
if(field == null) field = ""
out.write_uint32((field && field != "") ? compiler.string.hash(field) : 0)
return out
} //write
bytes_count_block() {
return 52
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/test_modifier > data"))
//fields count
out.write_int32(3)
// coord
out.write_uint32(compiler.string.hash("coord"))
out.write_uint32(1025475970) //type float3
var coord_default = [0, 0, 0]
out.write_float32(coord_default[0])
out.write_float32(coord_default[1])
out.write_float32(coord_default[2])
// auto_naming
out.write_uint32(compiler.string.hash("auto_naming"))
out.write_uint32(1710517951) //type boolean
var auto_naming_default = false
out.write_int32(auto_naming_default ? 1 : 0)
// field
out.write_uint32(compiler.string.hash("field"))
out.write_uint32(2729592961) //type id32
var field_default = ""
out.write_uint32((field_default && field_default != "") ? compiler.string.hash(field_default) : 0)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMDTA")
write(instance, out)
return out
} //write
} //ModifierDataCompiler
//`modifiers/test_modifier > data` block types
class BlockModifierData {
field { "slot" }
source { "modifiers/test_modifier > data" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.add(_block, "coord", "float3", [0, 0, 0])
Block.add(_block, "auto_naming", "boolean", false)
Block.add(_block, "field", "id32", "")
Block.set_type(_block, "modifiers/test_modifier > data")
} //new
instance_type {
class BlockInstModifierData {
coord { Block.get(_block, "coord", _slot) }
coord=(v) { Block.set(_block, "coord", _slot, v) }
auto_naming { Block.get(_block, "auto_naming", _slot) }
auto_naming=(v) { Block.set(_block, "auto_naming", _slot, v) }
field { Block.get(_block, "field", _slot) }
field=(v) { Block.set(_block, "field", _slot, v) }
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierData
return BlockInstModifierData
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierData
//`modifiers/test_modifier > world` types
class ModifierWorld {
construct new() {
} //new
} //ModifierWorld
//`modifiers/test_modifier > world` compilers
class ModifierWorldCompiler {
construct new() {
}
bytes_count(instance) {
var size = 4 //version
size = size + 0
return size
} //bytes_count
validate(from_source_id, elements) {
var fields = {
"type": false, //:luxe:internal
"uuid": false, //:luxe:internal
"luxe.self.modifier": false, //:luxe:internal
}
for(element in elements) {
var instance = element.value
for(field in instance) {
if(fields[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` has extra field `%(field.key)`")
} //if not found
} //each field
for(field in fields) {
var required = field.value
if(required && instance[field.key] == null) {
Fiber.abort("node `%(element.key)` in `%(from_source_id)` is missing a required field `%(field.key)` (and the field has no default value)")
}
} //each field
} //each element
} //validate
write(compiler, instance, out) {
//version
out.write_int32(0)
return out
} //write
bytes_count_block() {
return 8
} //bytes_count_block
write_block(compiler, out) {
//source id
out.write_uint32(compiler.string.hash("modifiers/test_modifier > world"))
//fields count
out.write_int32(0)
} //write_block
write(instance) {
var size = bytes_count(instance)
var out = Byter.new(size+8)
out.write_string("LUXEMWLD")
write(instance, out)
return out
} //write
} //ModifierWorldCompiler
//`modifiers/test_modifier > world` block types
class BlockModifierWorld {
field { "slot" }
source { "modifiers/test_modifier > world" }
construct new(block) {
_block = block
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
}
construct new() {
_block = Block.create()
_inst_type = instance_type
_inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/test_modifier > world")
} //new
instance_type {
class BlockInstModifierWorld {
slot { _slot }
entity { Block.get_handle(_block, _slot) }
block_set_slot(value) {
_slot=value
return this
}
construct new(block, slot) {
_block = block
_slot = slot
} //new
block { _block }
} //BlockInstModifierWorld
return BlockInstModifierWorld
} //instance_type
block { _block }
count { Block.get_count(_block) }
add() { Block.add(_block) }
append(other_block) { Block.append(_block, other_block) }
each(c, fn) {
for(i in 0 ... c) {
fn.call(0, _inst.block_set_slot(i))
}
} //each
[slot, inst] { _inst.block_set_slot(slot) }
[slot] { _inst_type.new(_block, slot) }
} //BlockModifierWorld

View file

@ -0,0 +1,51 @@
import "luxe: io" for IO
import "luxe: world" for World, Entity, Modifiers, ModifierSystem
//User facing API
//This is what the user of your modifier will interact with
class Slot {
static create(entity) { Modifiers.create(This, entity) }
static destroy(entity) { Modifiers.destroy(This, entity) }
static has(entity) { Modifiers.has(This, entity) }
} //Slot
//Your modifier system implementation.
//This speaks to the engine and your user facing API
//to do the actual work. You'll get notified when things change
//in the world and respond to them here.
class SlotSystem is ModifierSystem {
construct new() {
//called when your system is first created.
}
init(world) {
_world = world
//called when your modifier is created in a world
}
destroy() {
//called when your modifier is removed from a world
}
attach(entity, data) {
//called when attached to an entity
}
detach(entity, data) {
//called when detached from an entity, like on destroy
}
tick(delta) {
//called usually once every frame.
//called when the world that this modifier lives in, is ticked
each {|entity, data|
//use data.*
}
} //tick
} //SlotSystem
var Modifier = SlotSystem //required

View file

@ -1,14 +1,34 @@
import "luxe: project" for Entry
import "luxe: project" for Entry, Parcels, ProjectPaths
import "luxe: io" for IO
import "luxe: regex" for Regex
import "luxe: lx" for LX
class Project is Entry {
construct entry(target) {
name = "game"
name = "spine module"
version = "0.0.0"
renderer = "outline/renderer"
settings = "outline/settings"
} //new
entry() {
import "spine" for Spine
//todo: only update files with changes (check file timestamp)
var spine_files = IO.list_recursive(".", [], [ProjectPaths.dev], [".","..",ProjectPaths.dev, ProjectPaths.deploy])
.where{|file| file.path.endsWith(".spine.lx") }
var directory_regex = Regex.new("^[\\w\\s./]*[\\|/]", Regex.gim)
var name_regex = Regex.new("[^\\|/]*$", Regex.gim)
for(file in spine_files){
var base_file_path = file.path[0..-10]
var name = name_regex.exec(base_file_path)[0].string
var directory = directory_regex.exec(base_file_path)[0].string[0..-1]
var data_directory = "%(directory)/%(name)_data"
IO.make_directory(data_directory)
var spine = Spine.parse(base_file_path)
LX.stringify_to_file({"prototype":spine.prototype_skeleton()}, "%(data_directory)/%(name)_skeleton.prototype.lx")
}
} //entry
} //Project

View file

@ -1,3 +1,3 @@
modules = {
luxe = "2021.0.3"
luxe = "2021.0.4"
} //modules

View file

@ -4,6 +4,8 @@ import "luxe: string" for Str
import "luxe: render" for Geometry
import "luxe: draw" for Draw, PathStyle, LineJoin, LineCap
import "luxe: math" for Math
import "luxe: lx" for LX
import "luxe: id" for ID
class Spine{
@ -11,9 +13,9 @@ class Spine{
bones_by_name{_bones_by_name}
static parse(id: String) : Spine{
var asset = Assets.lx(id + ".spine.lx")["spine"]
var skeleton = Assets.lx(asset["skeleton"]+".json")
var atlas = Assets.bytes(asset["atlas"]+".atlas")
var asset = LX.read(id + ".spine.lx")["spine"]
var skeleton = LX.read(asset["skeleton"]+".json")
var atlas = LX.read(asset["atlas"]+".atlas")
var spine_asset = Spine.from_data(skeleton)
return spine_asset
@ -45,6 +47,23 @@ class Spine{
_active_animation = "" //todo: tie this into Anim system
}
prototype_skeleton():Map{
var elements = {}
for(bone in _bones_by_index){
var transform = {"type": "luxe: modifier/transform"}
if(!Util.approximately_vec(bone.position, [0, 0])) transform["pos"] = [bone.position.x, bone.position.y, 0]
if(!Util.approximately_num(bone.rotation, 0)) transform["rotation"] = [0, 0, bone.rotation]
if(!Util.approximately_vec(bone.scale, [1, 1])) transform["scale"] = [bone.scale.x, bone.scale.y, 1]
if(bone.parent != null) transform["link"] = bone.parent.uuid
var modifiers = {"transform": transform}
var entity = {"modifiers": modifiers, "uuid": bone.uuid}
elements[bone.name] = entity
}
return {"elements":elements}
}
load_skeleton(skeleton_data: Map){
_pos = [skeleton_data["x"], skeleton_data["y"]]
_size = [skeleton_data["width"], skeleton_data["height"]]
@ -108,6 +127,20 @@ class Spine{
}
}
class Util{
static approximately_vec(vec1:List, vec2:List):Boolean{
if(vec1.count != vec2.count) return false
for(i in 0...vec1.count){
if(!approximately_num(vec1[i], vec2[i])) return false
}
return true
}
static approximately_num(value1:Num, value2:Num):Boolean{
return (value1 - value2).abs < 0.00001
}
}
class SpineSkin{
name{_name}
@ -269,6 +302,7 @@ class SpineBone{
scale{_scale}
parent{_parent}
length{_length}
uuid{_uuid || (_uuid = ID.uuid())} //assign on first access
//todo: get good information out of bones