Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ on:
branches:
- main
- experimental
- experimental-bevy
pull_request:
release:
types:
- created

env:
BRANCH_TAG: ${{ github.ref_name == 'experimental' && 'experimental' || '' }}
BRANCH_TAG: ${{ github.ref_name == 'experimental' && 'experimental' || github.ref_name == 'experimental-bevy' && 'experimental-bevy' || '' }}

name: build-deploy
jobs:
Expand Down
9 changes: 8 additions & 1 deletion proto/decentraland/common/texture.proto
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ message VideoTexture {
optional TextureFilterMode filter_mode = 3; // default = FilterMode.Bilinear
}

message UiCanvasTexture {
uint32 ui_canvas_entity = 1;
optional TextureWrapMode wrap_mode = 2; // default = TextureWrapMode.Clamp
optional TextureFilterMode filter_mode = 3; // default = FilterMode.Bilinear
}

message TextureUnion {
oneof tex {
Texture texture = 1; // default = null
AvatarTexture avatar_texture = 2; // default = null
VideoTexture video_texture = 3; // default = null
UiCanvasTexture ui_texture = 4;
}
}
}
38 changes: 38 additions & 0 deletions proto/decentraland/kernel/apis/restricted_actions.proto
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,31 @@ message MovePlayerToResponse {
bool success = 1;
}

message WalkPlayerToRequest {
decentraland.common.Vector3 new_relative_position = 1;
float stop_threshold = 2;
optional float timeout = 3; // max seconds before the request is failed; not passed to the movement scene
}

message WalkPlayerToResponse {
bool success = 1;
}

message TeleportToResponse { }

message SetUiFocusRequest {
string element_id = 1;
}

message ClearUiFocusRequest { }

message GetUiFocusRequest { }

message UiFocusResponse {
// the element that is/was focussed
optional string element_id = 1;
}

message CopyToClipboardRequest {
string text = 1;
}
Expand Down Expand Up @@ -97,6 +120,12 @@ service RestrictedActionsService {
rpc MovePlayerTo(MovePlayerToRequest) returns (MovePlayerToResponse) {}

// TeleportTo will move the user to the specified world LAND parcel coordinates
// WalkPlayerTo will walk the player to a position relative to the current scene,
// managed by the movement controller scene. Returns success when the player reaches
// within stop_threshold distance, or false if the path is blocked, the player gets
// stuck, the player interrupts the walk with manual input, or the optional timeout expires.
rpc WalkPlayerTo(WalkPlayerToRequest) returns (WalkPlayerToResponse) {}

rpc TeleportTo(TeleportToRequest) returns (TeleportToResponse) {}

// TriggerEmote will trigger an emote in this current user
Expand All @@ -119,6 +148,15 @@ service RestrictedActionsService {
rpc TriggerSceneEmote(TriggerSceneEmoteRequest) returns (SuccessResponse) {}

// CopyToClipboard copies the provided text into the clipboard
// Sets the focus to a specific UI element
rpc SetUiFocus(SetUiFocusRequest) returns (UiFocusResponse) {}

// Clears the focus from any currently focused textentry or dropdown
rpc ClearUiFocus(ClearUiFocusRequest) returns (UiFocusResponse) {}

// Returns the element_id of any currently focused textentry or dropdown
rpc GetUiFocus(GetUiFocusRequest) returns (UiFocusResponse) {}

rpc CopyToClipboard(CopyToClipboardRequest) returns (EmptyResponse) {}

// StopEmote will stop the current emote
Expand Down
3 changes: 2 additions & 1 deletion proto/decentraland/sdk/components/avatar_equipped_data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ option (common.ecs_component_id) = 1091;
message PBAvatarEquippedData {
repeated string wearable_urns = 1;
repeated string emote_urns = 2;
}
repeated string force_render = 3; // slots that will render even if hidden
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ message PBAvatarModifierArea {
decentraland.common.Vector3 area = 1; // the 3D size of the region
repeated string exclude_ids = 2; // user IDs that can enter and remain unaffected
repeated AvatarModifierType modifiers = 3; // list of modifiers to apply
optional bool use_collider_range = 5; // if true, the player will be considered inside the area when they are within 0.3m of the area. default true
}

// AvatarModifierType is an effect that should be applied to avatars inside the region.
Expand Down
62 changes: 62 additions & 0 deletions proto/decentraland/sdk/components/avatar_movement.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
syntax = "proto3";

package decentraland.sdk.components;

import "decentraland/sdk/components/common/id.proto";
import "decentraland/common/vectors.proto";

option (common.ecs_component_id) = 1501;

message PBAvatarMovement {
decentraland.common.Vector3 velocity = 1;
float orientation = 2; // 0-360, yaw only; this is the authoritative facing (other clients read it, and physics treats the avatar as upright). Lean is expressed separately via tilt_pitch/tilt_roll.
optional decentraland.common.Vector3 ground_direction = 3;
optional bool walk_success = 4; // set for one frame when a walk_target ends: true = reached target, false = failed; absent = in progress or no walk
optional MovementAnimation animation = 5; // if set, the engine plays this animation instead of selecting one from velocity heuristics
optional float tilt_pitch = 6; // render-only forward/back lean in degrees, applied on top of `orientation` (rotation about the avatar's local X axis). Does not affect the physics capsule (stays upright) or the facing other clients read. Defaults to 0.
optional float tilt_roll = 7; // render-only sideways lean in degrees, applied on top of `orientation` (rotation about the avatar's local Z axis). Same constraints as tilt_pitch. Useful e.g. for glider banking. Defaults to 0.
}

// Describes the animation the movement scene wants the avatar to play.
// One GLB = one clip (following the scene-emote convention: single clip, or a clip named with `_Avatar` suffix).
// When absent the engine falls back to its built-in velocity-based selection (walk/run/jump/idle).
message MovementAnimation {
string src = 1; // scene-relative path to the gltf/glb asset (resolved via the scene content map)
bool loop = 2; // whether the clip repeats once it reaches the end
float speed = 3; // playback speed multiplier (1.0 = clip's native rate)
bool idle = 4; // true: a triggerSceneEmote may take over; false: emotes are suppressed while this animation plays
optional float transition_seconds = 5; // cross-fade duration when `src` changes; defaults to 0.2 when unset. Not applied to loop/speed/idle changes.
optional float playback_time = 6; // if set, the engine seeks to this position (in seconds) this frame. Clear on subsequent frames to allow normal playback. The scene can read `AvatarAnimationState.playback_time` first to decide.
repeated string sounds = 7; // scene-relative paths to audio clips (.mp3/.ogg) to play this frame on the avatar audio bus. Fire-and-forget: each listed clip plays once per frame it appears; leaving a clip set for multiple frames re-triggers it. No stop mechanism. Use `AvatarAnimationState.playback_time` to trigger sounds at the right point in the clip (e.g. foot plants).
}

// engine behaviour (uses only capsule shapecasts and GJK closest point for portability):
// 1: set avatar orientation from movement info -> P1
// 2: record "ground collider" - nearest collider within threshold distance in ground_direction using avatar collider shapecast
// 3: update all colliders, record previous transform and new transform.
// 4: apply ground collider movement: take collider closest point, modify P1 translation and rotation by closest point translation and rotation change -> P2
// 5: resolve collisions using position-based constraints
// initialize constraints to -inf, +inf
// repeat
// for each collider[i] that collides with the P3+N player:
// if closest point = capsule middle (i.e. collider collides with P3 collider but with radius 0),
// ignore / continue
// else
// update constraints based on minimum movement to escape collision
// e.g. if avatar is 1cm into the floor, constraint_min = max(constraint_min, vec3(0, 0.01, 0))
// reposition player to satisfy constraints for each axis:
// y: satsify floor before ceiling: new position = max(constraint_min, min(constraint_max, current position))
// x and z: if squashed, take average, else satisfy the required constraint
// if constraint_min > constraint_max then new position = average(constraint_min, constraint_max)
// else new position = clamp(current position, constraint_min, constraint_max)
// while position !~= previous position
// 6: apply velocity (collide and slide)
// disable anything we are initially colliding with
// shapecast avatar from position to position + velocity * timestep
// on impact:
// project velocity onto slide plane (standard "Collide & Slide")
// velocity = old velocity - (normal * dot(velocity, normal))
// repeat continue with residual velocity and residual time
// 7: provide AvatarMovementInfo values
// actual velocity = (final - P3+N) / timestep
// external_velocity = (P3+N - P1) / timestep
36 changes: 36 additions & 0 deletions proto/decentraland/sdk/components/avatar_movement_info.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
syntax = "proto3";

package decentraland.sdk.components;

import "decentraland/sdk/components/common/id.proto";
import "decentraland/common/vectors.proto";
import "decentraland/sdk/components/avatar_locomotion_settings.proto";
import "decentraland/sdk/components/input_modifier.proto";

option (common.ecs_component_id) = 1500;

message PBAvatarMovementInfo {
float step_time = 1; // the length of time the current step velocity will apply for
float previous_step_time = 2; // the length of time the previous step velocity applied for
decentraland.common.Vector3 requested_velocity = 3; // the velocity requested for the previous frame
decentraland.common.Vector3 actual_velocity = 4; // the resulting velocity taking collisions into account
decentraland.common.Vector3 external_velocity = 5; // the velocity imparted by movement of the "ground" platform or pushing from other moving colliders
decentraland.sdk.components.PBAvatarLocomotionSettings active_avatar_locomotion_settings = 6;
decentraland.sdk.components.PBInputModifier active_input_modifier = 7;
optional decentraland.common.Vector3 walk_target = 8; // if set, the movement scene should walk the player to this scene-relative position
optional float walk_threshold = 9; // stop distance for walk_target; considered reached when within this distance
optional AvatarAnimationState active_animation_state = 10; // current state of a scene-driven movement animation. Absent when the engine is using its velocity-based fallback. `playback_time` freezes while a triggerSceneEmote is overriding the animation.
}

// Mirror of the scene-driven movement animation currently playing, reported by the engine.
// Readable by any scene (not just the controller) so niche effects (e.g. dust cloud on landing) can react.
// Active emotes are not represented here — scenes already have their own way to read them.
message AvatarAnimationState {
string src = 1; // same scene-relative path the controlling scene supplied
bool loop = 2; // mirrors the request
float speed = 3; // mirrors the request
bool idle = 4; // mirrors the request
float playback_time = 5; // seconds into the clip; wraps on loop; frozen while an emote override is playing
float duration = 6; // total clip length in seconds
uint32 loop_count = 7; // how many times the clip has completed since it started
}
1 change: 1 addition & 0 deletions proto/decentraland/sdk/components/avatar_shape.proto
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ message PBAvatarShape {
repeated string emotes = 11; // available emotes (default empty)

optional bool show_only_wearables = 12; // hides the skin + hair + facial features (default: false)
repeated string force_render = 13; // slots that will render even if hidden
}

30 changes: 30 additions & 0 deletions proto/decentraland/sdk/components/camera_layer.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
syntax = "proto3";

package decentraland.sdk.components;

import "decentraland/sdk/components/common/id.proto";
import "decentraland/common/colors.proto";

option (common.ecs_component_id) = 1503;

message PBCameraLayer {
// layer to which these settings apply. must be > 0
// Layer 0 is the default "real world" layer viewed by the player and cannot be modified.
uint32 layer = 1;

// should the sun light affect this layer? default false
optional bool directional_light = 2;

// should this layer show player avatars? default false
optional bool show_avatars = 3;

// should this layer show the sky? default false
optional bool show_skybox = 4;

// should this layer show distance fog? default false
optional bool show_fog = 5;

// ambient light overrides for this layer. default -> use same as main camera
optional decentraland.common.Color3 ambient_color_override = 6;
optional float ambient_brightness_override = 7;
}
11 changes: 11 additions & 0 deletions proto/decentraland/sdk/components/camera_layers.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package decentraland.sdk.components;

import "decentraland/sdk/components/common/id.proto";

option (common.ecs_component_id) = 1208;

message PBCameraLayers {
repeated uint32 layers = 1;
}
1 change: 1 addition & 0 deletions proto/decentraland/sdk/components/camera_mode_area.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ option (common.ecs_component_id) = 1071;
message PBCameraModeArea {
decentraland.common.Vector3 area = 1; // the 3D size of the region
common.CameraType mode = 2; // the camera mode to enforce
optional bool use_collider_range = 4; // if true, the player will be considered inside the area when they are within 0.3m of the area. default true
}
3 changes: 3 additions & 0 deletions proto/decentraland/sdk/components/common/input_action.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ enum PointerEventType {
PET_HOVER_LEAVE = 3;
PET_PROXIMITY_ENTER = 4;
PET_PROXIMITY_LEAVE = 5;
PET_DRAG_LOCKED = 6;
PET_DRAG = 7;
PET_DRAG_END = 8;
}

enum InteractionType {
Expand Down
22 changes: 22 additions & 0 deletions proto/decentraland/sdk/components/global_light.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
syntax = "proto3";
package decentraland.sdk.components;

import "decentraland/common/colors.proto";
import "decentraland/common/vectors.proto";

import "decentraland/sdk/components/common/id.proto";
option (common.ecs_component_id) = 1206;

// defines the global scene light settings. must be added to the scene root.
// to control sunlight color, intensity, shadows etc, you can also add a PBLight to the scene root.
message PBGlobalLight {
// the direction the directional light shines in.
// default depends on time of day and explorer implementation
optional decentraland.common.Vector3 direction = 1;
// ambient light color
// default: White
optional decentraland.common.Color3 ambient_color = 2;
// ambient light intensity. the explorer default ambient brightness is multiplied by this non-physical quantity.
// default 1
optional float ambient_brightness = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,17 @@ import "decentraland/sdk/components/common/loading_state.proto";
// the current state of the GltfContainer of an entity.
message PBGltfContainerLoadingState {
common.LoadingState current_state = 1;
repeated string node_paths = 2; // all node paths in the gltf, which can be used with a GltfNode to inspect and modify the gltf contents
repeated string mesh_names = 3; // all meshes in the gltf. unnamed meshes will be auto-assigned a name of the form `MeshX` or `MeshX/PrimitiveY`
// where X is the mesh index and Y is the primitive index (and there is more than 1 primitive). note this may
// conflict with manually named meshes - to avoid any issues make sure all your meshes are explicitly named.
repeated string material_names = 4; // all materials in the gltf. unnamed materials will be auto-assigned a name of the form `MaterialX` where
// X is the material index. note this may conflict with manually named materials - to avoid any issues make
// sure all your materials are explicitly named.
repeated string skin_names = 5; // all mesh skins in the gltf. unnamed skins will be auto-assigned a name of the form `SkinX` where
// X is the skin index. note this may conflict with manually named skins - to avoid any issues make sure all
// your skins are explicitly named.
repeated string animation_names = 6; // all animations in the gltf. unnamed animations will be auto-assigned a name of the form `AnimationX` where
// X is the animation index. note this may conflict with manually named anims - to avoid any issues make sure all
// your animations are explicitly named.
}
42 changes: 42 additions & 0 deletions proto/decentraland/sdk/components/gltf_node.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
syntax = "proto3";
package decentraland.sdk.components;

import "decentraland/sdk/components/common/id.proto";
option (common.ecs_component_id) = 1200;

// a GltfNode links a scene entity with a node from within a gltf, allowing the scene to inspect it or modify it.
// This component must be added to a direct child of an entity with a PBGltfContainer component, or
// to a direct child of another entity with a GltfNode component, and the referenced gltf node must be a descendent of the gltf node
// in the parent.
// The name must match the path of one of the nodes within the Gltf. These are available on the GltfContainerLoadingState component.
//
// The renderer will attach a PBGltfNodeState to the entity describing the state. Once the state is `GNS_READY`,
// - the `Transform` will be updated to match the position of the node within the gltf (relative to the gltf root, or the parent node),
// - a `MeshRenderer` with a GltfMesh mesh type will be added (if the gltf node has a mesh).
// - a `MeshCollider` with a GltfMesh mesh type will be added (if the gltf node has a collider).
// - a `Material` component including a GltfMaterial reference will be added (if the gltf node has a material).
//
// After creation, if an animation moves the node, the `Transform` will be updated.
//
// From the scene, you can modify various components to alter the gltf node:
// - modifying the `Transform` position/rotation/scale will move the node. The position is interpreted relative to the gltf root (or parent node),
// regardless of any intermediate gltf node hierarchy.
// If an animation is playing, the animation takes priority and the scene entity's position will be updated to match the animation.
// - `Visibility` can be added to hide or show the node and it's children in the gltf hierarchy.
// - `MeshRenderer` can be added/modified/removed to create/modify/remove a mesh on the node.
// - `MeshCollider` can be added/modified/removed to create/modify/remove a collider on the node.
// - `Material` can be added or modified to change the material properties. If the gltf node has a material, the original material will be
// used as a base, and any gltf features (e.g. occlusion maps) from the gtlf spec that the renderer supports but that are not exposed in the
// PBMaterial will be maintained.
//
// The scene can add additional entities as children to the gltf node, but structural modifications of the gltf are not possible:
// - changing the scene hierarchy will not change the gltf node hierarchy. Moving the entity out of the gltf will sever the link and
// change the state to `GNS_FAILED`.
// - deleting the scene entity will not delete the gltf node.
//
// Removing the GltfNode will revert any changes to the original gltf. If the GltfNode component is removed and the mesh/collider/material
// are not removed, this will result in a duplication of these components as the previously-linked entity will retain it's components and
// the gltf node will also be displayed.
message PBGltfNode {
string path = 1; // the path of the target node in the Gltf.
}
Loading
Loading