From eb2cdd3499a8068abde19395b21a91b611b87e15 Mon Sep 17 00:00:00 2001 From: Pravus Date: Fri, 6 Mar 2026 10:06:45 +0900 Subject: [PATCH 1/4] first iteration on component protobuf definition --- .../sdk/components/particle_system.proto | 111 ++++++++++++++++++ public/sdk-components.proto | 1 + 2 files changed, 112 insertions(+) create mode 100644 proto/decentraland/sdk/components/particle_system.proto diff --git a/proto/decentraland/sdk/components/particle_system.proto b/proto/decentraland/sdk/components/particle_system.proto new file mode 100644 index 00000000..3c718ecd --- /dev/null +++ b/proto/decentraland/sdk/components/particle_system.proto @@ -0,0 +1,111 @@ +syntax = "proto3"; + +package decentraland.sdk.components; + +import "decentraland/common/colors.proto"; +import "decentraland/common/texture.proto"; +import "decentraland/common/vectors.proto"; +import "decentraland/sdk/components/common/id.proto"; + +option (common.ecs_component_id) = 1217; + +message PBParticleSystem { + // --- Emission --- + optional bool active = 1; // default = true + optional float rate = 2; // default = 10. Particles emitted per second. + optional uint32 max_particles = 3; // default = 1000. Maximum number of live particles. + optional float lifetime = 4; // default = 5. Particle lifetime in seconds. + + // --- Motion --- + optional float gravity = 5; // default = 0. Unity gravity modifier (multiplier of Physics.gravity). + optional decentraland.common.Vector3 additional_force = 6; // Constant force vector applied to each particle (world space). + + // --- Size --- + optional FloatRange initial_size = 7; // default = {1, 1}. Particle size at spawn. + optional FloatRange size_over_time = 8; // default = {1, 1}. Particle size lerped from start to end over its lifetime. + + // --- Rotation --- + optional FloatRange initial_rotation = 9; // default = {0, 0}. Initial rotation in degrees, randomized between start and end. + optional FloatRange rotation_over_time = 10; // default = {0, 0}. Angular velocity in degrees/sec, lerped over lifetime. + + // --- Color --- + optional ColorRange initial_color = 11; // default = {white, white}. Particle color at spawn, randomized between start and end. + optional ColorRange color_over_time = 12; // default = {white, white}. Particle color lerped from start to end over its lifetime. + + // --- Velocity --- + optional FloatRange initial_velocity_speed = 13; // default = {1, 1}. Initial speed in m/s, randomized between start and end. + + // --- Rendering --- + optional decentraland.common.Texture texture = 14; // Particle texture. default = null (plain white quad). + optional BlendMode blend_mode = 15; // default = PSB_ALPHA + optional bool billboard = 16; // default = true. Particles always face the camera. + + // --- Sprite Sheet Animation --- + optional SpriteSheetAnimation sprite_sheet = 17; + + // --- Emitter Shape --- + oneof shape { + Point point = 18; + Sphere sphere = 19; + Cone cone = 20; + Box box = 21; + } + + // --- Playback --- + optional PlaybackState playback_state = 22; // default = PS_PLAYING + optional uint32 restart_count = 23; // Increment to trigger a restart (stop+clear+play). LWW-safe restart signal. + + // ---- Nested types ---- + + // A range of float values. Randomized or lerped between start and end. + message FloatRange { + float start = 1; + float end = 2; + } + + // A range of Color4 values. Randomized or lerped between start and end. + message ColorRange { + decentraland.common.Color4 start = 1; + decentraland.common.Color4 end = 2; + } + + // Sprite sheet (texture atlas) animation settings. + message SpriteSheetAnimation { + uint32 tiles_x = 1; // Number of columns in the sprite sheet. + uint32 tiles_y = 2; // Number of rows in the sprite sheet. + uint32 start_frame = 3; // First frame index (inclusive). + uint32 end_frame = 4; // Last frame index (inclusive). 0 = use all frames. + optional float cycles_per_lifetime = 5; // default = 1. How many animation cycles to play over a particle's lifetime. + } + + // Emitter spawns particles from a single point. + message Point {} + + // Emitter spawns particles from the surface or volume of a sphere. + message Sphere { + optional float radius = 1; // default = 1 + } + + // Emitter spawns particles from the base of a cone and projects them outward. + message Cone { + optional float angle = 1; // default = 25. Half-angle of the cone in degrees. + optional float radius = 2; // default = 1. Base radius in meters. + } + + // Emitter spawns particles from the surface or volume of a box. + message Box { + optional decentraland.common.Vector3 size = 1; // default = {1, 1, 1} + } + + enum BlendMode { + PSB_ALPHA = 0; // Standard alpha transparency. + PSB_ADD = 1; // Additive blending (brightens underlying pixels). + PSB_MULTIPLY = 2; // Multiply blending (darkens underlying pixels). + } + + enum PlaybackState { + PS_PLAYING = 0; // Particle system is emitting and simulating. + PS_PAUSED = 1; // Simulation is frozen; no new particles are emitted. + PS_STOPPED = 2; // Simulation stopped and existing particles cleared. + } +} diff --git a/public/sdk-components.proto b/public/sdk-components.proto index a2f966cb..25aabb21 100644 --- a/public/sdk-components.proto +++ b/public/sdk-components.proto @@ -21,6 +21,7 @@ import public "decentraland/sdk/components/material.proto"; import public "decentraland/sdk/components/mesh_collider.proto"; import public "decentraland/sdk/components/mesh_renderer.proto"; import public "decentraland/sdk/components/nft_shape.proto"; +import public "decentraland/sdk/components/particle_system.proto"; import public "decentraland/sdk/components/player_identity_data.proto"; import public "decentraland/sdk/components/pointer_events_result.proto"; import public "decentraland/sdk/components/pointer_events.proto"; From be39a56ae3360c603b1de7dc43a8dc82de0569e5 Mon Sep 17 00:00:00 2001 From: Pravus Date: Mon, 9 Mar 2026 19:54:49 +0900 Subject: [PATCH 2/4] added more properties --- .../sdk/components/particle_system.proto | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/proto/decentraland/sdk/components/particle_system.proto b/proto/decentraland/sdk/components/particle_system.proto index 3c718ecd..bb3a1bc4 100644 --- a/proto/decentraland/sdk/components/particle_system.proto +++ b/proto/decentraland/sdk/components/particle_system.proto @@ -51,6 +51,13 @@ message PBParticleSystem { Box box = 21; } + // --- Simulation --- + optional bool loop = 24; // default = true. Loop the emission cycle. + optional bool prewarm = 25; // default = false. Start as if already simulated for one full loop cycle. Requires loop = true. + + // --- Limit Velocity Over Lifetime --- + optional LimitVelocity limit_velocity = 26; // Clamps particle speed over its lifetime. + // --- Playback --- optional PlaybackState playback_state = 22; // default = PS_PLAYING optional uint32 restart_count = 23; // Increment to trigger a restart (stop+clear+play). LWW-safe restart signal. @@ -78,6 +85,12 @@ message PBParticleSystem { optional float cycles_per_lifetime = 5; // default = 1. How many animation cycles to play over a particle's lifetime. } + // Clamps particle speed over lifetime. + message LimitVelocity { + float speed = 1; // Maximum particle speed (m/s). + optional float dampen = 2; // default = 1. Fraction (0–1) of excess velocity removed per frame. 1 = hard clamp. + } + // Emitter spawns particles from a single point. message Point {} From 919e66fc4055550ce986a38fd6060ed8023fdb5f Mon Sep 17 00:00:00 2001 From: Pravus Date: Thu, 19 Mar 2026 01:37:01 +0900 Subject: [PATCH 3/4] added spriteSheet FPS + simulationSpace props --- proto/decentraland/sdk/components/particle_system.proto | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/proto/decentraland/sdk/components/particle_system.proto b/proto/decentraland/sdk/components/particle_system.proto index bb3a1bc4..b4d71e2a 100644 --- a/proto/decentraland/sdk/components/particle_system.proto +++ b/proto/decentraland/sdk/components/particle_system.proto @@ -54,6 +54,7 @@ message PBParticleSystem { // --- Simulation --- optional bool loop = 24; // default = true. Loop the emission cycle. optional bool prewarm = 25; // default = false. Start as if already simulated for one full loop cycle. Requires loop = true. + optional SimulationSpace simulation_space = 27; // default = PSS_LOCAL. Controls whether particles simulate in local or world space. // --- Limit Velocity Over Lifetime --- optional LimitVelocity limit_velocity = 26; // Clamps particle speed over its lifetime. @@ -82,7 +83,7 @@ message PBParticleSystem { uint32 tiles_y = 2; // Number of rows in the sprite sheet. uint32 start_frame = 3; // First frame index (inclusive). uint32 end_frame = 4; // Last frame index (inclusive). 0 = use all frames. - optional float cycles_per_lifetime = 5; // default = 1. How many animation cycles to play over a particle's lifetime. + optional float frames_per_second = 5; // default = 30. Playback speed in frames per second. } // Clamps particle speed over lifetime. @@ -121,4 +122,9 @@ message PBParticleSystem { PS_PAUSED = 1; // Simulation is frozen; no new particles are emitted. PS_STOPPED = 2; // Simulation stopped and existing particles cleared. } + + enum SimulationSpace { + PSS_LOCAL = 0; // Particles move with the entity transform. + PSS_WORLD = 1; // Particles stay in world position after emission. + } } From 84052acaef56654a4f2ef2b80b93a26be389d59a Mon Sep 17 00:00:00 2001 From: Pravus Date: Fri, 20 Mar 2026 22:19:45 +0900 Subject: [PATCH 4/4] reserved billboard prop + added face travel direction one --- proto/decentraland/sdk/components/particle_system.proto | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proto/decentraland/sdk/components/particle_system.proto b/proto/decentraland/sdk/components/particle_system.proto index b4d71e2a..eef7ed0d 100644 --- a/proto/decentraland/sdk/components/particle_system.proto +++ b/proto/decentraland/sdk/components/particle_system.proto @@ -27,6 +27,7 @@ message PBParticleSystem { // --- Rotation --- optional FloatRange initial_rotation = 9; // default = {0, 0}. Initial rotation in degrees, randomized between start and end. optional FloatRange rotation_over_time = 10; // default = {0, 0}. Angular velocity in degrees/sec, lerped over lifetime. + optional bool face_travel_direction = 28; // default = false. Particles orient along their velocity direction. // --- Color --- optional ColorRange initial_color = 11; // default = {white, white}. Particle color at spawn, randomized between start and end. @@ -38,7 +39,7 @@ message PBParticleSystem { // --- Rendering --- optional decentraland.common.Texture texture = 14; // Particle texture. default = null (plain white quad). optional BlendMode blend_mode = 15; // default = PSB_ALPHA - optional bool billboard = 16; // default = true. Particles always face the camera. + reserved 16; // Reserved for future Billboard property. // --- Sprite Sheet Animation --- optional SpriteSheetAnimation sprite_sheet = 17;