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}