fmod/studio/event_instance/
parameters.rs

1// Copyright (c) 2024 Lily 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
14impl EventInstance {
15    /// Sets a parameter value by name.
16    ///
17    /// The value will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
18    ///
19    /// 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.
20    ///
21    /// If the event has no parameter matching name then [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned.
22    pub fn set_parameter_by_name(
23        &self,
24        name: &Utf8CStr,
25        value: c_float,
26        ignore_seek_speed: bool,
27    ) -> Result<()> {
28        unsafe {
29            FMOD_Studio_EventInstance_SetParameterByName(
30                self.inner,
31                name.as_ptr(),
32                value,
33                ignore_seek_speed.into(),
34            )
35            .to_result()
36        }
37    }
38
39    /// Sets a parameter value by name, looking up the value label.
40    ///
41    /// The label will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
42    ///
43    /// 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.
44    ///
45    /// If the event has no parameter matching name then [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned.
46    ///
47    /// If the specified label is not found, [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned. This lookup is case sensitive.
48    pub fn set_parameter_by_name_with_label(
49        &self,
50        name: &Utf8CStr,
51        label: &Utf8CStr,
52        ignore_seek_speed: bool,
53    ) -> Result<()> {
54        unsafe {
55            FMOD_Studio_EventInstance_SetParameterByNameWithLabel(
56                self.inner,
57                name.as_ptr(),
58                label.as_ptr(),
59                ignore_seek_speed.into(),
60            )
61            .to_result()
62        }
63    }
64
65    /// Retrieves a parameter value by name.
66    ///
67    /// Automatic parameters always return value as 0 since they can never have their value set from the public API.
68    ///
69    /// 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.
70    /// This is calculated asynchronously when the Studio system updates.
71    pub fn get_parameter_by_name(&self, name: &Utf8CStr) -> Result<(c_float, c_float)> {
72        let mut value = 0.0;
73        let mut final_value = 0.0;
74        unsafe {
75            FMOD_Studio_EventInstance_GetParameterByName(
76                self.inner,
77                name.as_ptr(),
78                &mut value,
79                &mut final_value,
80            )
81            .to_result()?;
82        }
83        Ok((value, final_value))
84    }
85
86    /// Sets a parameter value by unique identifier.
87    ///
88    /// The value will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
89    ///
90    /// 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.
91    pub fn set_parameter_by_id(
92        &self,
93        id: ParameterID,
94        value: c_float,
95        ignore_seek_speed: bool,
96    ) -> Result<()> {
97        unsafe {
98            FMOD_Studio_EventInstance_SetParameterByID(
99                self.inner,
100                id.into(),
101                value,
102                ignore_seek_speed.into(),
103            )
104            .to_result()
105        }
106    }
107
108    /// Sets a parameter value by unique identifier, looking up the value label.
109    ///
110    /// The label will be set instantly regardless of `ignore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
111    ///
112    /// 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.
113    ///
114    /// If the specified label is not found, [`FMOD_RESULT::FMOD_ERR_EVENT_NOTFOUND`] is returned. This lookup is case sensitive.
115    pub fn set_parameter_by_id_with_label(
116        &self,
117        id: ParameterID,
118        label: &Utf8CStr,
119        ignore_seek_speed: bool,
120    ) -> Result<()> {
121        unsafe {
122            FMOD_Studio_EventInstance_SetParameterByIDWithLabel(
123                self.inner,
124                id.into(),
125                label.as_ptr(),
126                ignore_seek_speed.into(),
127            )
128            .to_result()
129        }
130    }
131
132    /// Retrieves a parameter value by unique identifier.
133    ///
134    /// Automatic parameters always return value as 0 since they can never have their value set from the public API.
135    ///
136    /// 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.
137    /// This is calculated asynchronously when the Studio system updates.
138    pub fn get_parameter_by_id(&self, id: ParameterID) -> Result<(c_float, c_float)> {
139        let mut value = 0.0;
140        let mut final_value = 0.0;
141        unsafe {
142            FMOD_Studio_EventInstance_GetParameterByID(
143                self.inner,
144                id.into(),
145                &mut value,
146                &mut final_value,
147            )
148            .to_result()?;
149        }
150        Ok((value, final_value))
151    }
152
153    /// Sets multiple parameter values by unique identifier.
154    ///
155    /// All values will be set instantly regardless of `ingore_seek_speed` when the Event playback state is [`PlaybackState::Stopped`].
156    ///
157    /// If any ID is set to all zeroes then the corresponding value will be ignored.
158    // TODO iterator version?
159    pub fn set_parameters_by_ids(
160        &self,
161        ids: &[ParameterID], // TODO fmod says that the size of this must range from 1-32. do we need to enforce this?
162        values: &mut [c_float], // TODO is this &mut correct? does fmod perform any writes?
163        ignore_seek_speed: bool,
164    ) -> Result<()> {
165        // TODO don't panic, return result
166        assert_eq!(ids.len(), values.len());
167
168        unsafe {
169            FMOD_Studio_EventInstance_SetParametersByIDs(
170                self.inner,
171                ids.as_ptr().cast(),
172                values.as_mut_ptr(),
173                ids.len() as c_int,
174                ignore_seek_speed.into(),
175            )
176            .to_result()
177        }
178    }
179}