Skip to main content

sl_types/
lsl.rs

1//! LSL types and parsers/printers to use LSL format for them
2
3#[cfg(feature = "chumsky")]
4use chumsky::{Parser, prelude::just, text::whitespace};
5
6#[cfg(feature = "chumsky")]
7use crate::utils::f32_parser;
8
9/// LSL Vector of 3 float components
10#[derive(Debug, Clone, PartialEq)]
11pub struct Vector {
12    /// x component
13    pub x: f32,
14    /// y component
15    pub y: f32,
16    /// z component
17    pub z: f32,
18}
19
20/// parse an LSL vector
21///
22/// "<1.234,3.456,4.567>"
23///
24/// # Errors
25///
26/// returns an error if the string could not be parsed
27#[cfg(feature = "chumsky")]
28#[must_use]
29pub fn vector_parser<'src>()
30-> impl Parser<'src, &'src str, Vector, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
31    just('<')
32        .then(whitespace().or_not())
33        .ignore_then(f32_parser())
34        .then_ignore(whitespace().or_not())
35        .then_ignore(just(','))
36        .then_ignore(whitespace().or_not())
37        .then(f32_parser())
38        .then_ignore(whitespace().or_not())
39        .then_ignore(just(','))
40        .then_ignore(whitespace().or_not())
41        .then(f32_parser())
42        .then_ignore(whitespace().or_not())
43        .then_ignore(just('>'))
44        .map(|((x, y), z)| Vector { x, y, z })
45}
46
47impl From<crate::map::RegionCoordinates> for Vector {
48    fn from(value: crate::map::RegionCoordinates) -> Self {
49        Self {
50            x: value.x(),
51            y: value.y(),
52            z: value.z(),
53        }
54    }
55}
56
57/// LSL Rotation (quaternion) of 4 float components
58#[derive(Debug, Clone, PartialEq)]
59pub struct Rotation {
60    /// x component
61    pub x: f32,
62    /// y component
63    pub y: f32,
64    /// z component
65    pub z: f32,
66    /// s component
67    pub s: f32,
68}
69
70/// parse an LSL rotation
71///
72/// "<1.234,3.456,4.567,5.678>"
73///
74/// # Errors
75///
76/// returns an error if the string could not be parsed
77#[cfg(feature = "chumsky")]
78#[must_use]
79pub fn rotation_parser<'src>()
80-> impl Parser<'src, &'src str, Rotation, chumsky::extra::Err<chumsky::error::Rich<'src, char>>> {
81    just('<')
82        .then(whitespace().or_not())
83        .ignore_then(f32_parser())
84        .then_ignore(whitespace().or_not())
85        .then_ignore(just(','))
86        .then_ignore(whitespace().or_not())
87        .then(f32_parser())
88        .then_ignore(whitespace().or_not())
89        .then_ignore(just(','))
90        .then_ignore(whitespace().or_not())
91        .then(f32_parser())
92        .then_ignore(whitespace().or_not())
93        .then_ignore(just(','))
94        .then_ignore(whitespace().or_not())
95        .then(f32_parser())
96        .then_ignore(whitespace().or_not())
97        .then_ignore(just('>'))
98        .map(|(((x, y), z), s)| Rotation { x, y, z, s })
99}
100
101/// The permissions an in-world script may request via `llRequestPermissions`, a
102/// bitfield shared by the `ScriptQuestion` (request) and `ScriptAnswerYes`
103/// (grant) messages. The flag values match the LSL `PERMISSION_*` constants.
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
105pub struct ScriptPermissions(pub i32);
106
107impl ScriptPermissions {
108    /// Debit the agent's account (`PERMISSION_DEBIT`).
109    pub const DEBIT: i32 = 1 << 1;
110    /// Take control inputs (`PERMISSION_TAKE_CONTROLS`).
111    pub const TAKE_CONTROLS: i32 = 1 << 2;
112    /// Trigger animations on the agent (`PERMISSION_TRIGGER_ANIMATION`).
113    pub const TRIGGER_ANIMATION: i32 = 1 << 4;
114    /// Attach to the agent (`PERMISSION_ATTACH`).
115    pub const ATTACH: i32 = 1 << 5;
116    /// Change link-set membership (`PERMISSION_CHANGE_LINKS`).
117    pub const CHANGE_LINKS: i32 = 1 << 7;
118    /// Track the agent's camera (`PERMISSION_TRACK_CAMERA`).
119    pub const TRACK_CAMERA: i32 = 1 << 10;
120    /// Control the agent's camera (`PERMISSION_CONTROL_CAMERA`).
121    pub const CONTROL_CAMERA: i32 = 1 << 11;
122    /// Teleport the agent (`PERMISSION_TELEPORT`).
123    pub const TELEPORT: i32 = 1 << 12;
124    /// Participate in an experience (`PERMISSION_EXPERIENCE`).
125    pub const EXPERIENCE: i32 = 1 << 13;
126    /// Silently manage estate access (`PERMISSION_SILENT_ESTATE_MANAGEMENT`).
127    pub const SILENT_ESTATE_MANAGEMENT: i32 = 1 << 14;
128    /// Override the agent's animations (`PERMISSION_OVERRIDE_ANIMATIONS`).
129    pub const OVERRIDE_ANIMATIONS: i32 = 1 << 15;
130    /// Return objects (`PERMISSION_RETURN_OBJECTS`).
131    pub const RETURN_OBJECTS: i32 = 1 << 16;
132
133    /// Whether all of the bits in `mask` are granted/requested.
134    #[must_use]
135    pub const fn contains(self, mask: i32) -> bool {
136        self.0 & mask == mask
137    }
138}