fmod/studio/event_instance/
parameters.rs

1// Copyright (c) 2024 Melody Madeline Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::ffi::{c_float, c_int};
8
9use fmod_sys::*;
10use lanyard::Utf8CStr;
11
12use crate::studio::{EventInstance, ParameterID};
13
14#[cfg(doc)]
15use crate::studio::{ParameterKind, PlaybackState};
16use crate::{FmodResultExt, Result};
17
18impl EventInstance {
19    /// Sets a parameter value by name.
20    ///
21    /// The value will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
22    ///
23    /// If the specified parameter is read only, is an automatic parameter or is not of type [`ParameterKind::GameControlled`] then [`FMOD_RESULT::FMOD_ERR_INVALID_PARAM`] is returned.
24    ///
25    /// If the event has no parameter matching name then [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned.
26    pub fn set_parameter_by_name(
27        &self,
28        name: &Utf8CStr,
29        value: c_float,
30        ignore_seek_speed: bool,
31    ) -> Result<()> {
32        unsafe {
33            FMOD_Studio_EventInstance_SetParameterByName(
34                self.inner.as_ptr(),
35                name.as_ptr(),
36                value,
37                ignore_seek_speed.into(),
38            )
39            .to_result()
40        }
41    }
42
43    /// Sets a parameter value by name, looking up the value label.
44    ///
45    /// The label will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
46    ///
47    /// If the specified parameter is read only, is an automatic parameter or is not of type [`ParameterKind::GameControlled`] then [`FMOD_RESULT::FMOD_ERR_INVALID_PARAM`] is returned.
48    ///
49    /// If the event has no parameter matching name then [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned.
50    ///
51    /// If the specified label is not found, [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned. This lookup is case sensitive.
52    pub fn set_parameter_by_name_with_label(
53        &self,
54        name: &Utf8CStr,
55        label: &Utf8CStr,
56        ignore_seek_speed: bool,
57    ) -> Result<()> {
58        unsafe {
59            FMOD_Studio_EventInstance_SetParameterByNameWithLabel(
60                self.inner.as_ptr(),
61                name.as_ptr(),
62                label.as_ptr(),
63                ignore_seek_speed.into(),
64            )
65            .to_result()
66        }
67    }
68
69    /// Retrieves a parameter value by name.
70    ///
71    /// Automatic parameters always return value as 0 since they can never have their value set from the public API.
72    ///
73    /// The second returned tuple field is the final value of the parameter after applying adjustments due to automation, modulation, seek speed, and parameter velocity to value.
74    /// This is calculated asynchronously when the Studio system updates.
75    pub fn get_parameter_by_name(&self, name: &Utf8CStr) -> Result<(c_float, c_float)> {
76        let mut value = 0.0;
77        let mut final_value = 0.0;
78        unsafe {
79            FMOD_Studio_EventInstance_GetParameterByName(
80                self.inner.as_ptr(),
81                name.as_ptr(),
82                &raw mut value,
83                &raw mut final_value,
84            )
85            .to_result()?;
86        }
87        Ok((value, final_value))
88    }
89
90    /// Sets a parameter value by unique identifier.
91    ///
92    /// The value will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
93    ///
94    /// If the specified parameter is read only, is an automatic parameter or is not of type [`ParameterKind::GameControlled`] then [`FMOD_RESULT::FMOD_ERR_INVALID_PARAM`] is returned.
95    pub fn set_parameter_by_id(
96        &self,
97        id: ParameterID,
98        value: c_float,
99        ignore_seek_speed: bool,
100    ) -> Result<()> {
101        unsafe {
102            FMOD_Studio_EventInstance_SetParameterByID(
103                self.inner.as_ptr(),
104                id.into(),
105                value,
106                ignore_seek_speed.into(),
107            )
108            .to_result()
109        }
110    }
111
112    /// Sets a parameter value by unique identifier, looking up the value label.
113    ///
114    /// The label will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
115    ///
116    /// If the specified parameter is read only, is an automatic parameter or is not of type [`ParameterKind::GameControlled`] then [`FMOD_RESULT::FMOD_ERR_INVALID_PARAM`] is returned.
117    ///
118    /// If the specified label is not found, [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned. This lookup is case sensitive.
119    pub fn set_parameter_by_id_with_label(
120        &self,
121        id: ParameterID,
122        label: &Utf8CStr,
123        ignore_seek_speed: bool,
124    ) -> Result<()> {
125        unsafe {
126            FMOD_Studio_EventInstance_SetParameterByIDWithLabel(
127                self.inner.as_ptr(),
128                id.into(),
129                label.as_ptr(),
130                ignore_seek_speed.into(),
131            )
132            .to_result()
133        }
134    }
135
136    /// Retrieves a parameter value by unique identifier.
137    ///
138    /// Automatic parameters always return value as 0 since they can never have their value set from the public API.
139    ///
140    /// The second returned tuple field is the final value of the parameter after applying adjustments due to automation, modulation, seek speed, and parameter velocity to value.
141    /// This is calculated asynchronously when the Studio system updates.
142    pub fn get_parameter_by_id(&self, id: ParameterID) -> Result<(c_float, c_float)> {
143        let mut value = 0.0;
144        let mut final_value = 0.0;
145        unsafe {
146            FMOD_Studio_EventInstance_GetParameterByID(
147                self.inner.as_ptr(),
148                id.into(),
149                &raw mut value,
150                &raw mut final_value,
151            )
152            .to_result()?;
153        }
154        Ok((value, final_value))
155    }
156
157    /// Sets multiple parameter values by unique identifier.
158    ///
159    /// All values will be set instantly regardless of `ingore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
160    ///
161    /// If any ID is set to all zeroes then the corresponding value will be ignored.
162    ///
163    /// # Panics
164    ///
165    /// This function will panic if `ids.len()` != `values.len()`.
166    pub fn set_parameters_by_ids(
167        &self,
168        ids: &[ParameterID], // TODO fmod says that the size of this must range from 1-32. do we need to enforce this?
169        values: &mut [c_float], // TODO is this &mut correct? does fmod perform any writes?
170        ignore_seek_speed: bool,
171    ) -> Result<()> {
172        // TODO don't panic, return result
173        assert_eq!(ids.len(), values.len());
174
175        unsafe {
176            FMOD_Studio_EventInstance_SetParametersByIDs(
177                self.inner.as_ptr(),
178                ids.as_ptr().cast(),
179                values.as_mut_ptr(),
180                ids.len() as c_int,
181                ignore_seek_speed.into(),
182            )
183            .to_result()
184        }
185    }
186}