Compare commits

...

6 commits

Author SHA1 Message Date
Ronja
0cf0dab974 add tiny readme 2022-01-26 21:28:58 +01:00
Ronja
4d9f527efb bump version numbers 2022-01-26 21:27:43 +01:00
Ronja
80c061b527 minor fixes 2022-01-26 21:27:29 +01:00
Ronja
5432879e81 make trail editor-safe
..I think
2022-01-26 21:23:16 +01:00
Ronja
4433e19b63 add docs 2022-01-26 21:01:53 +01:00
Ronja
3e9249934f convert to module 2022-01-26 20:29:00 +01:00
20 changed files with 204 additions and 64 deletions

View file

@ -1 +0,0 @@
preview.png

View file

@ -1,3 +1,4 @@
#hidden
class Queue is Sequence{ class Queue is Sequence{
data{_data} data{_data}
count{_count} count{_count}

View file

@ -5,7 +5,7 @@ import "luxe: io" for IO
import "luxe: bytes" for Byter, Bytes import "luxe: bytes" for Byter, Bytes
import "luxe: world" for Block import "luxe: world" for Block
//`modifiers/trail/trail > runtime` types //`trail: modifier/trail > runtime` types
class ModifierRuntime { class ModifierRuntime {
@ -14,7 +14,7 @@ import "luxe: world" for Block
} //ModifierRuntime } //ModifierRuntime
//`modifiers/trail/trail > runtime` compilers //`trail: modifier/trail > runtime` compilers
class ModifierRuntimeCompiler { class ModifierRuntimeCompiler {
@ -73,7 +73,7 @@ import "luxe: world" for Block
write_block(compiler, out) { write_block(compiler, out) {
//source id //source id
out.write_uint32(compiler.string.hash("modifiers/trail/trail > runtime")) out.write_uint32(compiler.string.hash("trail: modifier/trail > runtime"))
//fields count //fields count
out.write_int32(0) out.write_int32(0)
@ -95,12 +95,12 @@ import "luxe: world" for Block
} //ModifierRuntimeCompiler } //ModifierRuntimeCompiler
//`modifiers/trail/trail > runtime` block types //`trail: modifier/trail > runtime` block types
class BlockModifierRuntime { class BlockModifierRuntime {
field { "trail" } field { "trail" }
source { "modifiers/trail/trail > runtime" } source { "trail: modifier/trail > runtime" }
construct new(block) { construct new(block) {
_block = block _block = block
@ -112,7 +112,7 @@ import "luxe: world" for Block
_block = Block.create() _block = Block.create()
_inst_type = instance_type _inst_type = instance_type
_inst = _inst_type.new(_block, 0) _inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/trail/trail > runtime") Block.set_type(_block, "trail: modifier/trail > runtime")
} //new } //new
instance_type { instance_type {
@ -151,7 +151,7 @@ import "luxe: world" for Block
} //BlockModifierRuntime } //BlockModifierRuntime
//`modifiers/trail/trail > data` types //`trail: modifier/trail > data` types
class ModifierData { class ModifierData {
@ -162,7 +162,7 @@ import "luxe: world" for Block
_length = 0.2 _length = 0.2
_subdivisions_length = 10 _subdivisions_length = 10
_subdivisions_width = 5 _subdivisions_width = 5
_material = "asset/flag" _material = "trail: default_material/flag"
} //new } //new
edge_length { _edge_length } edge_length { _edge_length }
@ -188,7 +188,7 @@ import "luxe: world" for Block
} //ModifierData } //ModifierData
//`modifiers/trail/trail > data` compilers //`trail: modifier/trail > data` compilers
class ModifierDataCompiler { class ModifierDataCompiler {
@ -286,7 +286,7 @@ import "luxe: world" for Block
var material = instance["material"] var material = instance["material"]
if(material == null) material = "asset/flag" if(material == null) material = "trail: default_material/flag"
out.write_uint32((material && material != "") ? compiler.string.hash(material) : 0) out.write_uint32((material && material != "") ? compiler.string.hash(material) : 0)
@ -303,7 +303,7 @@ import "luxe: world" for Block
write_block(compiler, out) { write_block(compiler, out) {
//source id //source id
out.write_uint32(compiler.string.hash("modifiers/trail/trail > data")) out.write_uint32(compiler.string.hash("trail: modifier/trail > data"))
//fields count //fields count
out.write_int32(7) out.write_int32(7)
@ -353,7 +353,7 @@ import "luxe: world" for Block
// material // material
out.write_uint32(compiler.string.hash("material")) out.write_uint32(compiler.string.hash("material"))
out.write_uint32(2729592961) //type id32 out.write_uint32(2729592961) //type id32
var material_default = "asset/flag" var material_default = "trail: default_material/flag"
out.write_uint32((material_default && material_default != "") ? compiler.string.hash(material_default) : 0) out.write_uint32((material_default && material_default != "") ? compiler.string.hash(material_default) : 0)
@ -374,12 +374,12 @@ import "luxe: world" for Block
} //ModifierDataCompiler } //ModifierDataCompiler
//`modifiers/trail/trail > data` block types //`trail: modifier/trail > data` block types
class BlockModifierData { class BlockModifierData {
field { "trail" } field { "trail" }
source { "modifiers/trail/trail > data" } source { "trail: modifier/trail > data" }
construct new(block) { construct new(block) {
_block = block _block = block
@ -397,8 +397,8 @@ import "luxe: world" for Block
Block.add(_block, "length", "number", 0.2) Block.add(_block, "length", "number", 0.2)
Block.add(_block, "subdivisions_length", "number", 10) Block.add(_block, "subdivisions_length", "number", 10)
Block.add(_block, "subdivisions_width", "number", 5) Block.add(_block, "subdivisions_width", "number", 5)
Block.add(_block, "material", "id32", "asset/flag") Block.add(_block, "material", "id32", "trail: default_material/flag")
Block.set_type(_block, "modifiers/trail/trail > data") Block.set_type(_block, "trail: modifier/trail > data")
} //new } //new
instance_type { instance_type {
@ -451,7 +451,7 @@ import "luxe: world" for Block
} //BlockModifierData } //BlockModifierData
//`modifiers/trail/trail > world` types //`trail: modifier/trail > world` types
class ModifierWorld { class ModifierWorld {
@ -460,7 +460,7 @@ import "luxe: world" for Block
} //ModifierWorld } //ModifierWorld
//`modifiers/trail/trail > world` compilers //`trail: modifier/trail > world` compilers
class ModifierWorldCompiler { class ModifierWorldCompiler {
@ -519,7 +519,7 @@ import "luxe: world" for Block
write_block(compiler, out) { write_block(compiler, out) {
//source id //source id
out.write_uint32(compiler.string.hash("modifiers/trail/trail > world")) out.write_uint32(compiler.string.hash("trail: modifier/trail > world"))
//fields count //fields count
out.write_int32(0) out.write_int32(0)
@ -541,12 +541,12 @@ import "luxe: world" for Block
} //ModifierWorldCompiler } //ModifierWorldCompiler
//`modifiers/trail/trail > world` block types //`trail: modifier/trail > world` block types
class BlockModifierWorld { class BlockModifierWorld {
field { "trail" } field { "trail" }
source { "modifiers/trail/trail > world" } source { "trail: modifier/trail > world" }
construct new(block) { construct new(block) {
_block = block _block = block
@ -558,7 +558,7 @@ import "luxe: world" for Block
_block = Block.create() _block = Block.create()
_inst_type = instance_type _inst_type = instance_type
_inst = _inst_type.new(_block, 0) _inst = _inst_type.new(_block, 0)
Block.set_type(_block, "modifiers/trail/trail > world") Block.set_type(_block, "trail: modifier/trail > world")
} //new } //new
instance_type { instance_type {

View file

@ -2,92 +2,211 @@ import "luxe: io" for IO
import "luxe: world" for World, Entity, Modifiers, ModifierSystem, Transform import "luxe: world" for World, Entity, Modifiers, ModifierSystem, Transform
import "luxe: draw" for Draw, PathStyle, LineCap import "luxe: draw" for Draw, PathStyle, LineCap
import "luxe: color" for Color import "luxe: color" for Color
import "luxe: render" for Geometry, Primitive, IndexType, Render import "luxe: render" for Geometry, Primitive, IndexType, Render, Material
import "luxe: assets" for Assets, Strings import "luxe: assets" for Assets, Strings
import "luxe: bytes" for Uint16, Floats import "luxe: bytes" for Uint16, Floats
import "queue" for Queue
import "modifiers/trail/trail.modifier" for ModifierData
import "luxe: math" for Math import "luxe: math" for Math
//User facing API import "trail: _queue" for Queue
//This is what the user of your modifier will interact with
class Trail {
import "trail: modifier/trail.modifier" for ModifierData
#doc="""
Modifier to add simple trails to entities.
Needs a Transform on the same entity to work.
```js
var entity = Entity.create(world)
Transform.create(entity)
Trail.create(entity)
//now just move and rotate the entity around
```
"""
class Trail {
static time_based{true}
static distance_based{false}
#doc="Add a trail modifier to an entity. Entity should also have a Transform."
#args(
entity = "The entity to add the trail modifier to."
)
static create(entity: Entity): None { static create(entity: Entity): None {
Modifiers.create(This, entity) Modifiers.create(This, entity)
} }
#doc="Remove the trail modifier from an entity."
#args(
entity = "The entity to remove the trail modifier from."
)
static destroy(entity: Entity): None { static destroy(entity: Entity): None {
Modifiers.destroy(This, entity) Modifiers.destroy(This, entity)
}
static has(entity: Entity): None {
Modifiers.has(This, entity)
} }
#doc="Check whether an entity has a trail modifier or not."
#args(
entity = "The entity to check whether it has a trail modifier."
)
static has(entity: Entity): Bool {
return Modifiers.has(This, entity)
}
#doc="Reset trail to no length."
#args(
entity = "The entity with the trail modifier."
)
static reset(entity: Entity): None { static reset(entity: Entity): None {
Modifiers.get_system(This, entity).reset(entity ) Modifiers.get_system(This, entity).reset(entity )
} }
#doc="Set the width of a trail."
#args(
entity = "The entity with the trail modifier.",
width = "The new width of the trail."
)
static set_width(entity: Entity, width: Num): None { static set_width(entity: Entity, width: Num): None {
Modifiers.get(This, entity).edge_length = width Modifiers.get(This, entity).edge_length = width
} }
#doc="Get the width of a trail."
#args(
entity = "The entity with the trail modifier."
)
static get_width(entity: Entity): Num { static get_width(entity: Entity): Num {
return Modifiers.get(This, entity).edge_length return Modifiers.get(This, entity).edge_length
} }
#doc="Set the length of a trail."
#args(
entity = "The entity with the trail modifier.",
length = "The new length of the trail."
)
static set_length(entity: Entity, length: Num): None { static set_length(entity: Entity, length: Num): None {
Modifiers.get(This, entity).length = length Modifiers.get(This, entity).length = length
//todo: recalculate transient data? //todo: recalculate transient data?
} }
#doc="Get the length of a trail."
#args(
entity = "The entity with the trail modifier."
)
static get_length(entity: Entity): Num { static get_length(entity: Entity): Num {
return Modifiers.get(This, entity).length return Modifiers.get(This, entity).length
} }
static set_time_based(entity: Entity, time_based: Num): None { #doc="""
Set whether the trail is time based or distance based.
```js
Trail.set_time_based(entity, Trail.distance_based)
```
"""
#args(
entity = "The entity with the trail modifier.",
time_based = "`true` if its time based, `false` if its distance based."
)
static set_time_based(entity: Entity, time_based: Bool): None {
Modifiers.get(This, entity).time_based = time_based Modifiers.get(This, entity).time_based = time_based
} }
static get_time_based(entity: Entity): Num { #doc="""
Get whether the trail is time based or distance based. (true if time based, false if distance based)
"""
#args(
entity = "The entity with the trail modifier."
)
static get_time_based(entity: Entity): Bool {
return Modifiers.get(This, entity).time_based return Modifiers.get(This, entity).time_based
} }
static set_normalize_uvs(entity: Entity, normalize_uvs: Num): None { #doc="""
Set whether the trail should have normalized UVs of a trail.
If the UVs are normalized, they should be linear over distance,
especially with time based trails you otherwise can get very wobbly behaviour as speed changes.
"""
#args(
entity = "The entity with the trail modifier.",
length = "Whether the trail should have normalized uvs."
)
static set_normalize_uvs(entity: Entity, normalize_uvs: Bool): None {
Modifiers.get(This, entity).normalize_uvs = normalize_uvs Modifiers.get(This, entity).normalize_uvs = normalize_uvs
} }
static get_normalize_uvs(entity: Entity): Num { #doc="Get whether a trail has normalized uvs."
#args(
entity = "The entity with the trail modifier."
)
static get_normalize_uvs(entity: Entity): Bool {
return Modifiers.get(This, entity).normalize_uvs return Modifiers.get(This, entity).normalize_uvs
} }
#doc="Set the material the trail is rendered with via its id."
#args(
entity = "The entity with the trail modifier."
)
static set_material_id(entity: Entity, material_id: String): None { static set_material_id(entity: Entity, material_id: String): None {
Strings.add(material_id) Strings.add(material_id)
Modifiers.get(This, entity).material = material_id Modifiers.get(This, entity).material = material_id
Modifiers.get_system(This, entity).set_material(entity, material_id) Modifiers.get_system(This, entity).set_material_id(entity, material_id)
} }
#doc="Set the material the trail is rendered with."
#args(
entity = "The entity with the trail modifier."
)
static set_material(entity: Entity, material: Material): None {
var material_id = Material.get_source_id(material)
Strings.add(material_id)
Modifiers.get(This, entity).material = material_id
Modifiers.get_system(This, entity).set_material(entity, material)
}
#doc="Get the id of the currently used material."
#args(
entity = "The entity with the trail modifier."
)
static get_material_id(entity: Entity): String { static get_material_id(entity: Entity): String {
return Strings.get(Modifiers.get(This, entity).material) return Strings.get(Modifiers.get(This, entity).material)
} }
#doc="""
Set mesh subdivisions around length of the trail.
This will rebuild the mesh entirely and potentially throw away custom materials you set via `set_material`.
"""
#args(
entity = "The entity with the trail modifier.",
subdivisions = "Subdivisions along length."
)
static set_subdivisions_length(entity: Entity, subdivisions: Num){ static set_subdivisions_length(entity: Entity, subdivisions: Num){
Modifiers.get(This, entity).subdivisions_length = subdivisions Modifiers.get(This, entity).subdivisions_length = subdivisions
Modifiers.get_system(This, entity).recreate_buffers(entity) Modifiers.get_system(This, entity).recreate_buffers(entity)
} }
#doc="Get subdivisions in length of trail."
#args(
entity = "The entity with the trail modifier."
)
static get_subdivisions_length(entity: Entity): Num{ static get_subdivisions_length(entity: Entity): Num{
return Modifiers.get(This, entity).subdivisions_length return Modifiers.get(This, entity).subdivisions_length
} }
#doc="""
Set mesh subdivisions around length of the trail.
This will rebuild the mesh entirely and potentially throw away custom materials you set via `set_material`.
"""
#args(
entity = "The entity with the trail modifier.",
subdivisions = "Subdivisions along width."
)
static set_subdivisions_width(entity: Entity, subdivisions: Num){ static set_subdivisions_width(entity: Entity, subdivisions: Num){
Modifiers.get(This, entity).subdivisions_width = subdivisions Modifiers.get(This, entity).subdivisions_width = subdivisions
Modifiers.get_system(This, entity).recreate_buffers(entity) Modifiers.get_system(This, entity).recreate_buffers(entity)
} }
#doc="Get subdivisions in width of trail."
#args(
entity = "The entity with the trail modifier."
)
static get_subdivisions_width(entity: Entity): Num{ static get_subdivisions_width(entity: Entity): Num{
return Modifiers.get(This, entity).subdivisions_width return Modifiers.get(This, entity).subdivisions_width
} }
@ -143,6 +262,7 @@ class TrailData {
//This speaks to the engine and your user facing API //This speaks to the engine and your user facing API
//to do the actual work. You'll get notified when things change //to do the actual work. You'll get notified when things change
//in the world and respond to them here. //in the world and respond to them here.
#hidden
class TrailSystem is ModifierSystem { class TrailSystem is ModifierSystem {
construct new() { construct new() {
@ -153,6 +273,7 @@ class TrailSystem is ModifierSystem {
init(world) { init(world) {
_world = world _world = world
_draw = Draw.create(World.render_set(world)) _draw = Draw.create(World.render_set(world))
var edge_debug = PathStyle.new() var edge_debug = PathStyle.new()
edge_debug.color = [1,1,1,1] edge_debug.color = [1,1,1,1]
edge_debug.thickness = 2 edge_debug.thickness = 2
@ -174,8 +295,12 @@ class TrailSystem is ModifierSystem {
_instance_data[entity].points.clear() _instance_data[entity].points.clear()
} }
set_material(entity: Entity, material_id: String){ set_material_id(entity: Entity, material_id: String){
var material = Assets.material(material_id) var material = Assets.material(material_id)
set_material(entity, material)
}
set_material(entity: Entity, material: Material){
var data = _instance_data[entity] var data = _instance_data[entity]
if(!data || !material) return if(!data || !material) return
Geometry.set_material(entity, material) Geometry.set_material(entity, material)
@ -203,7 +328,7 @@ class TrailSystem is ModifierSystem {
Render.vertex_buffer_replace(inst_data.color_buffer, color_data, color_data.length)*/ Render.vertex_buffer_replace(inst_data.color_buffer, color_data, color_data.length)*/
//...but for now... //...but for now...
var data = get(entity) var data = get(entity)
detach(entity, data) detach(entity, data)
attach(entity, data) attach(entity, data)
} }
@ -213,6 +338,7 @@ class TrailSystem is ModifierSystem {
} }
attach(entity, data: ModifierData) { attach(entity, data: ModifierData) {
var material_id = Strings.get(data.material) var material_id = Strings.get(data.material)
var material = Assets.material(material_id) var material = Assets.material(material_id)
@ -312,6 +438,18 @@ class TrailSystem is ModifierSystem {
} }
tick(delta) { tick(delta) {
if(World.tag_has(_world, "edit")){
each{|entity, data: ModifierData|
if(!Transform.has(entity)) return
var start = Transform.local_point_to_world(entity, 0, data.edge_length * -0.5, 0)
var end = Transform.local_point_to_world(entity, 0, data.edge_length * 0.5, 0)
Draw.path3D(_draw, [start, end], _debug_edge_style, false)
}
Draw.commit(_draw)
return
}
//System.print("positions") //System.print("positions")
record_positions(delta) record_positions(delta)
//System.print("buffers") //System.print("buffers")

View file

@ -1,8 +0,0 @@
material = {
basis = "asset/clamped_sprite"
inputs = {
sprite.image = "asset/flag"
sprite.color = [1 1 1 1]
sprite.uv = [0 0 1 1]
}
}

View file

@ -1,4 +1,4 @@
image = { image = {
source = "asset/flag.png" source = "trail: default_material/flag.png"
generate_mipmaps_at_load = false generate_mipmaps_at_load = false
} }

View file

@ -0,0 +1,8 @@
material = {
basis = "trail: default_material/clamped_sprite"
inputs = {
sprite.image = "trail: default_material/flag"
sprite.color = [1 1 1 1]
sprite.uv = [0 0 1 1]
}
}

View file

Before

Width:  |  Height:  |  Size: 839 B

After

Width:  |  Height:  |  Size: 839 B

View file

@ -1,9 +1,10 @@
modifier = { modifier = {
script = "modifiers/trail/trail" script = "trail: trail"
description = "Trail go brrr." description = "Dynamic trails."
field = "trail" field = "trail"
display = "Trail" //the display in the editor display = "Trail" //the display in the editor
class = "Trail" //The code generated name for the modifier API class = "Trail" //The code generated name for the modifier API
dependency = ["luxe: modifier/transform"]
block = { //The data for the modifiers block = { //The data for the modifiers
fields = [ fields = [
{ name="edge_length" type="number" default=100 } { name="edge_length" type="number" default=100 }
@ -13,7 +14,7 @@ modifier = {
{ name="length" type="number" default=.2 } { name="length" type="number" default=.2 }
{ name="subdivisions_length" type="number" default=10 } { name="subdivisions_length" type="number" default=10 }
{ name="subdivisions_width" type="number" default=5 } { name="subdivisions_width" type="number" default=5 }
{ name="material" type="id32" editor="material" default="asset/flag"} { name="material" type="id32" editor="material" default="trail: default_material/flag"}
] ]
} }
} }

4
module.lx Normal file
View file

@ -0,0 +1,4 @@
name = "trail"
owner = "Ronja"
version = "0.1.0"
description = "Simple trails. Just add a trail modifier to your moving component."

View file

@ -1,3 +0,0 @@
modules = {
luxe = "dev"
} //modules

1
readme.md Normal file
View file

@ -0,0 +1 @@
A small module that provides a trail modifier to be attached to any moving entity with a `Transform` modifier.

View file

@ -7,7 +7,7 @@ import "luxe: draw" for Draw
import "luxe: io" for IO import "luxe: io" for IO
import "outline/app" for App import "outline/app" for App
import "modifiers/trail/trail" for Trail import "trail: modifier/trail" for Trail
class Game is Ready { class Game is Ready {
@ -45,11 +45,6 @@ class Game is Ready {
Trail.reset(_blade) Trail.reset(_blade)
} }
if(Input.key_state_released(Key.key_1)) {
var subs = Trail.get_subdivisions_length(_blade) + 1
Trail.set_subdivisions_length(_blade, subs)
}
//app.color.r = app.color.g = app.color.b = (IO.timestamp()/20 % 1) //app.color.r = app.color.g = app.color.b = (IO.timestamp()/20 % 1)
//System.print(1/delta) //System.print(1/delta)
} //tick } //tick

View file

@ -5,7 +5,7 @@ class Project is Entry {
construct entry(target) { construct entry(target) {
name = "Trail Test" name = "Trail Test"
version = "0.0.0" version = "1.0.0"
renderer = "outline/renderer" renderer = "outline/renderer"
settings = "outline/settings" settings = "outline/settings"

View file

@ -0,0 +1,4 @@
modules = {
luxe = "2022.0.3"
trail = "0.1.0"
} //modules