fmod 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +5 -0
- data/.yardopts +2 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +96 -0
- data/Rakefile +1 -0
- data/bin/console +28 -0
- data/bin/setup +8 -0
- data/ext/fmod.dll +0 -0
- data/ext/fmod64.dll +0 -0
- data/ext/libfmod.dylib +0 -0
- data/ext/llbfmod.zip +0 -0
- data/extras/FMOD Studio Programmers API for Windows.chm +0 -0
- data/fmod.gemspec +58 -0
- data/lib/fmod.rb +564 -0
- data/lib/fmod/channel.rb +151 -0
- data/lib/fmod/channel_control.rb +821 -0
- data/lib/fmod/channel_group.rb +61 -0
- data/lib/fmod/core.rb +35 -0
- data/lib/fmod/core/bool_description.rb +18 -0
- data/lib/fmod/core/channel_mask.rb +24 -0
- data/lib/fmod/core/data_description.rb +14 -0
- data/lib/fmod/core/driver.rb +59 -0
- data/lib/fmod/core/dsp_description.rb +7 -0
- data/lib/fmod/core/dsp_index.rb +9 -0
- data/lib/fmod/core/dsp_type.rb +43 -0
- data/lib/fmod/core/extensions.rb +28 -0
- data/lib/fmod/core/file_system.rb +86 -0
- data/lib/fmod/core/filter_type.rb +19 -0
- data/lib/fmod/core/float_description.rb +16 -0
- data/lib/fmod/core/guid.rb +50 -0
- data/lib/fmod/core/init_flags.rb +19 -0
- data/lib/fmod/core/integer_description.rb +26 -0
- data/lib/fmod/core/mode.rb +36 -0
- data/lib/fmod/core/output_type.rb +30 -0
- data/lib/fmod/core/parameter_info.rb +41 -0
- data/lib/fmod/core/parameter_type.rb +10 -0
- data/lib/fmod/core/result.rb +88 -0
- data/lib/fmod/core/reverb.rb +217 -0
- data/lib/fmod/core/sound_ex_info.rb +7 -0
- data/lib/fmod/core/sound_format.rb +30 -0
- data/lib/fmod/core/sound_group_behavior.rb +9 -0
- data/lib/fmod/core/sound_type.rb +80 -0
- data/lib/fmod/core/speaker_index.rb +18 -0
- data/lib/fmod/core/speaker_mode.rb +16 -0
- data/lib/fmod/core/spectrum_data.rb +12 -0
- data/lib/fmod/core/structure.rb +23 -0
- data/lib/fmod/core/structures.rb +41 -0
- data/lib/fmod/core/tag.rb +51 -0
- data/lib/fmod/core/tag_data_type.rb +14 -0
- data/lib/fmod/core/time_unit.rb +40 -0
- data/lib/fmod/core/vector.rb +42 -0
- data/lib/fmod/core/window_type.rb +12 -0
- data/lib/fmod/dsp.rb +510 -0
- data/lib/fmod/dsp_connection.rb +113 -0
- data/lib/fmod/effects.rb +38 -0
- data/lib/fmod/effects/channel_mix.rb +101 -0
- data/lib/fmod/effects/chorus.rb +30 -0
- data/lib/fmod/effects/compressor.rb +52 -0
- data/lib/fmod/effects/convolution_reverb.rb +31 -0
- data/lib/fmod/effects/delay.rb +44 -0
- data/lib/fmod/effects/distortion.rb +16 -0
- data/lib/fmod/effects/dsps.rb +10 -0
- data/lib/fmod/effects/echo.rb +37 -0
- data/lib/fmod/effects/envelope_follower.rb +31 -0
- data/lib/fmod/effects/fader.rb +16 -0
- data/lib/fmod/effects/fft.rb +38 -0
- data/lib/fmod/effects/flange.rb +37 -0
- data/lib/fmod/effects/high_pass.rb +24 -0
- data/lib/fmod/effects/high_pass_simple.rb +25 -0
- data/lib/fmod/effects/it_echo.rb +56 -0
- data/lib/fmod/effects/it_lowpass.rb +36 -0
- data/lib/fmod/effects/ladspa_plugin.rb +14 -0
- data/lib/fmod/effects/limiter.rb +32 -0
- data/lib/fmod/effects/loudness_meter.rb +19 -0
- data/lib/fmod/effects/low_pass.rb +25 -0
- data/lib/fmod/effects/low_pass_simple.rb +26 -0
- data/lib/fmod/effects/mixer.rb +11 -0
- data/lib/fmod/effects/multiband_eq.rb +153 -0
- data/lib/fmod/effects/normalize.rb +47 -0
- data/lib/fmod/effects/object_pan.rb +62 -0
- data/lib/fmod/effects/oscillator.rb +52 -0
- data/lib/fmod/effects/pan.rb +166 -0
- data/lib/fmod/effects/param_eq.rb +36 -0
- data/lib/fmod/effects/pitch_shift.rb +47 -0
- data/lib/fmod/effects/return.rb +18 -0
- data/lib/fmod/effects/send.rb +21 -0
- data/lib/fmod/effects/sfx_reverb.rb +87 -0
- data/lib/fmod/effects/three_eq.rb +41 -0
- data/lib/fmod/effects/transceiver.rb +57 -0
- data/lib/fmod/effects/tremolo.rb +67 -0
- data/lib/fmod/effects/vst_plugin.rb +12 -0
- data/lib/fmod/effects/winamp_plugin.rb +12 -0
- data/lib/fmod/error.rb +108 -0
- data/lib/fmod/geometry.rb +380 -0
- data/lib/fmod/handle.rb +129 -0
- data/lib/fmod/reverb3D.rb +98 -0
- data/lib/fmod/sound.rb +810 -0
- data/lib/fmod/sound_group.rb +54 -0
- data/lib/fmod/system.rb +1242 -0
- data/lib/fmod/version.rb +3 -0
- metadata +220 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
|
|
2
|
+
module FMOD
|
|
3
|
+
module Effects
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This unit implements SFX reverb.
|
|
7
|
+
#
|
|
8
|
+
# This is a high quality I3DL2 based reverb.
|
|
9
|
+
#
|
|
10
|
+
# On top of the I3DL2 property set, "Dry Level" is also included to allow
|
|
11
|
+
# the dry mix to be changed.
|
|
12
|
+
#
|
|
13
|
+
# @attr decay_time [Float] Reverberation decay time at low-frequencies in
|
|
14
|
+
# milliseconds.
|
|
15
|
+
# * *Minimum:* 100.0
|
|
16
|
+
# * *Maximum:* 20000.0
|
|
17
|
+
# * *Default:* 1500
|
|
18
|
+
# @attr early_delay [Float] Delay time of first reflection in milliseconds.
|
|
19
|
+
# * *Minimum:* 0.0
|
|
20
|
+
# * *Maximum:* 300.0
|
|
21
|
+
# * *Default:* 20.0
|
|
22
|
+
# @attr late_delay [Float] Late reverberation delay time relative to first
|
|
23
|
+
# reflection in milliseconds.
|
|
24
|
+
# * *Minimum:* 0.0
|
|
25
|
+
# * *Maximum:* 100.0
|
|
26
|
+
# * *Default:* 40.0
|
|
27
|
+
# @attr hf_reference [Float] Reference frequency for high-frequency decay in
|
|
28
|
+
# Hz.
|
|
29
|
+
# * *Minimum:* 20.0
|
|
30
|
+
# * *Maximum:* 20000.0
|
|
31
|
+
# * *Default:* 5000.0
|
|
32
|
+
# @attr hf_decay_ratio [Float] High-frequency decay time relative to decay
|
|
33
|
+
# time in percent.
|
|
34
|
+
# * *Minimum:* 10.0
|
|
35
|
+
# * *Maximum:* 100.0
|
|
36
|
+
# * *Default:* 50.0
|
|
37
|
+
# @attr diffusion [Float] Reverberation diffusion (echo density) in percent.
|
|
38
|
+
# * *Minimum:* 0.0
|
|
39
|
+
# * *Maximum:* 100.0
|
|
40
|
+
# * *Default:* 100.0
|
|
41
|
+
# @attr density [Float] Reverberation density (modal density) in percent.
|
|
42
|
+
# * *Minimum:* 0.0
|
|
43
|
+
# * *Maximum:* 100.0
|
|
44
|
+
# * *Default:* 100.0
|
|
45
|
+
# @attr low_shelf_frequency [Float] Transition frequency of low-shelf filter
|
|
46
|
+
# in Hz.
|
|
47
|
+
# * *Minimum:* 20.0
|
|
48
|
+
# * *Maximum:* 1000.0
|
|
49
|
+
# * *Default:* 250.0
|
|
50
|
+
# @attr low_shelf_gain [Float] Gain of low-shelf filter in dB.
|
|
51
|
+
# * *Minimum:* -36.0
|
|
52
|
+
# * *Maximum:* 12.0
|
|
53
|
+
# * *Default:* 0.0
|
|
54
|
+
# @attr high_cut [Float] Cutoff frequency of low-pass filter in Hz.
|
|
55
|
+
# * *Minimum:* 20.0
|
|
56
|
+
# * *Maximum:* 20000.0
|
|
57
|
+
# * *Default:* 20000.0
|
|
58
|
+
# @attr early_late_mix [Float] Blend ratio of late reverb to early
|
|
59
|
+
# reflections in percent.
|
|
60
|
+
# * *Minimum:* 0.0
|
|
61
|
+
# * *Maximum:* 100.0
|
|
62
|
+
# * *Default:* 50.0
|
|
63
|
+
# @attr wet_level [Float] Reverb signal level in dB.
|
|
64
|
+
# * *Minimum:* -80.0
|
|
65
|
+
# * *Maximum:* 20.0
|
|
66
|
+
# * *Default:* -6.0
|
|
67
|
+
# @attr dry_level [Float] Dry signal level in dB.
|
|
68
|
+
# * *Minimum:* -80.0
|
|
69
|
+
# * *Maximum:* 20.0
|
|
70
|
+
# * *Default:* 0.0
|
|
71
|
+
class SfxReverb < Dsp
|
|
72
|
+
float_param(0, :decay_time, min: 100.0, max: 20000.0)
|
|
73
|
+
float_param(0, :early_delay, min: 0.0, max: 300.0)
|
|
74
|
+
float_param(0, :late_delay, min: 0.0, max: 100.0)
|
|
75
|
+
float_param(0, :hf_reference, min: 20.0, max: 20000.0)
|
|
76
|
+
float_param(0, :hf_decay_ratio, min: 10.0, max: 100.0)
|
|
77
|
+
float_param(0, :diffusion, min: 0.0, max: 100.0)
|
|
78
|
+
float_param(0, :density, min: 0.0, max: 100.0)
|
|
79
|
+
float_param(0, :low_shelf_frequency, min: 20.0, max: 1000.0)
|
|
80
|
+
float_param(0, :low_shelf_gain, min: -36.0, max: 12.0)
|
|
81
|
+
float_param(0, :high_cut, min: 20.0, max: 20000.0)
|
|
82
|
+
float_param(0, :early_late_mix, min: 0.0, max: 100.0)
|
|
83
|
+
float_param(0, :wet_level, min: -80.0, max: 20.0)
|
|
84
|
+
float_param(0, :dry_level, min: -80.0, max: 20.0)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module FMOD
|
|
2
|
+
module Effects
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# This unit is a three-band equalizer.
|
|
6
|
+
#
|
|
7
|
+
# @attr low_gain [Float] Low frequency gain in dB. .
|
|
8
|
+
# * *Minimum:* -80.0
|
|
9
|
+
# * *Maximum:* 10.0
|
|
10
|
+
# * *Default:* 0.0
|
|
11
|
+
# @attr mid_gain [Float] Mid frequency gain in dB.
|
|
12
|
+
# * *Minimum:* -80.0
|
|
13
|
+
# * *Maximum:* 10.0
|
|
14
|
+
# * *Default:* 0.0
|
|
15
|
+
# @attr high_gain [Float] High frequency gain in dB.
|
|
16
|
+
# * *Minimum:* -80.0
|
|
17
|
+
# * *Maximum:* 10.0
|
|
18
|
+
# * *Default:* 0.0
|
|
19
|
+
# @attr low_crossover [Float] Low-to-mid crossover frequency in Hz.
|
|
20
|
+
# * *Minimum:* 10.0
|
|
21
|
+
# * *Maximum:* 22000.0
|
|
22
|
+
# * *Default:* 4000.0
|
|
23
|
+
# @attr high_crossover [Float] Mid-to-high crossover frequency in Hz.
|
|
24
|
+
# * *Minimum:* 10.0
|
|
25
|
+
# * *Maximum:* 22000.0
|
|
26
|
+
# * *Default:* 4000.0
|
|
27
|
+
# @attr crossover_slope [Integer] Crossover slope.
|
|
28
|
+
# * *0:* 12dB/Octave
|
|
29
|
+
# * *1:* 24dB/Octave
|
|
30
|
+
# * *2:* 48dB/Octave
|
|
31
|
+
# * *Default:* 1 (24dB/Octave)
|
|
32
|
+
class ThreeEq < Dsp
|
|
33
|
+
float_param(0, :low_gain, min: -80.0, max: 10.0)
|
|
34
|
+
float_param(1, :mid_gain, min: -80.0, max: 10.0)
|
|
35
|
+
float_param(2, :high_gain, min: -80.0, max: 10.0)
|
|
36
|
+
float_param(3, :low_crossover, min: 10.0, max: 22000.0)
|
|
37
|
+
float_param(4, :high_crossover, min: 10.0, max: 22000.0)
|
|
38
|
+
integer_param(5, :crossover_slope, min: 0, max: 2)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
|
|
2
|
+
module FMOD
|
|
3
|
+
module Effects
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This unit "sends" and "receives" from a selection of up to 32 different
|
|
7
|
+
# slots. It is like a send/return but it uses global slots rather than
|
|
8
|
+
# returns as the destination. It also has other features. Multiple
|
|
9
|
+
# transceivers can receive from a single channel, or multiple transceivers
|
|
10
|
+
# can send to a single channel, or a combination of both.
|
|
11
|
+
#
|
|
12
|
+
# The transceiver only transmits and receives to a global array of 32
|
|
13
|
+
# channels. The transceiver can be set to receiver mode (like a {Return})
|
|
14
|
+
# and can receive the signal at a variable {#gain}. The transceiver can also
|
|
15
|
+
# be set to transmit to a channel (like a {Send}) and can transmit the
|
|
16
|
+
# signal with a variable {#gain}.
|
|
17
|
+
#
|
|
18
|
+
# The {#speaker_mode} is only applicable to the transmission format, not the
|
|
19
|
+
# receive format. This means this parameter is ignored in "receive mode".
|
|
20
|
+
# This allows receivers to receive at the speaker mode of the user's choice.
|
|
21
|
+
# Receiving from a mono channel, is cheaper than receiving from a surround
|
|
22
|
+
# channel for example. The 3 speaker modes {SpeakerMode::MONO},
|
|
23
|
+
# {SpeakerMode::STEREO}, {SpeakerMode::SURROUND} are stored as separate
|
|
24
|
+
# buffers in memory for a transmitter channel. To save memory, use 1 common
|
|
25
|
+
# speaker mode for a transmitter.
|
|
26
|
+
#
|
|
27
|
+
# The transceiver is double buffered to avoid de-syncing of transmitters and
|
|
28
|
+
# receivers. This means there will be a 1 block delay on a receiver,
|
|
29
|
+
# compared to the data sent from a transmitter.
|
|
30
|
+
#
|
|
31
|
+
# Multiple transmitters sending to the same channel will be mixed together.
|
|
32
|
+
#
|
|
33
|
+
# @attr transmit [Boolean] The behavior of the unit.
|
|
34
|
+
# * *false:* Transceiver is a "receiver" (like a {Return}) and accepts
|
|
35
|
+
# data from a channel.
|
|
36
|
+
# * *true:* Transceiver is a "transmitter" (like a {Send}).
|
|
37
|
+
# * *Default:* +false+
|
|
38
|
+
# @attr gain [Float] Gain to receive or transmit at in dB.
|
|
39
|
+
# * *Minimum:* -80.0
|
|
40
|
+
# * *Maximum:* 10.0
|
|
41
|
+
# * *Default:* 0.0
|
|
42
|
+
# @attr channel [Integer] Integer to select current global slot, shared by
|
|
43
|
+
# all Transceivers, that can be transmitted to or received from.
|
|
44
|
+
# * *Minimum:* 0
|
|
45
|
+
# * *Maximum:* 31
|
|
46
|
+
# * *Default:* 0
|
|
47
|
+
# @attr speaker_mode [Integer] Speaker mode (transmitter mode only).
|
|
48
|
+
# * *Default:* {SpeakerMode::DEFAULT}
|
|
49
|
+
# @see SpeakerMode
|
|
50
|
+
class Transceiver < Dsp
|
|
51
|
+
bool_param(0, :transmit)
|
|
52
|
+
float_param(1, :gain, min: -80.0, max: 10.0)
|
|
53
|
+
integer_param(2, :channel, min: 0, max: 31)
|
|
54
|
+
integer_param(3, :speaker_mode, min: 0, max: 9)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
module FMOD
|
|
3
|
+
module Effects
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This unit produces a tremolo / chopper effect on the sound.
|
|
7
|
+
#
|
|
8
|
+
# The tremolo effect varies the amplitude of a sound. Depending on the
|
|
9
|
+
# settings, this unit can produce a tremolo, chopper or auto-pan effect.
|
|
10
|
+
#
|
|
11
|
+
# The shape of the LFO (low freq. oscillator) can morphed between sine,
|
|
12
|
+
# triangle and sawtooth waves using the {#shape} and {#skew} parameters.
|
|
13
|
+
#
|
|
14
|
+
# {#duty} and {#square} are useful for a chopper-type effect where the first
|
|
15
|
+
# controls the on-time duration and second controls the flatness of the
|
|
16
|
+
# envelope.
|
|
17
|
+
#
|
|
18
|
+
# {#spread} varies the LFO phase between channels to get an auto-pan effect.
|
|
19
|
+
# This works best with a sine shape LFO.
|
|
20
|
+
#
|
|
21
|
+
# The LFO can be synchronized using the {#phase} parameter which sets its
|
|
22
|
+
# instantaneous phase.
|
|
23
|
+
#
|
|
24
|
+
# @attr frequency [Float] LFO frequency in Hz.
|
|
25
|
+
# * *Minimum:* 0.1
|
|
26
|
+
# * *Maximum:* 20.0
|
|
27
|
+
# * *Default:* 5.0
|
|
28
|
+
# @attr depth [Float] Tremolo depth.
|
|
29
|
+
# * *Minimum:* 0.0
|
|
30
|
+
# * *Maximum:* 1.0
|
|
31
|
+
# * *Default:* 1.0
|
|
32
|
+
# @attr shape [Float] LFO shape morph between triangle and sine.
|
|
33
|
+
# * *Minimum:* 0.0
|
|
34
|
+
# * *Maximum:* 1.0
|
|
35
|
+
# * *Default:* 0.0
|
|
36
|
+
# @attr skew [Float] Time-skewing of LFO cycle.
|
|
37
|
+
# * *Minimum:* -1.0
|
|
38
|
+
# * *Maximum:* 1.0
|
|
39
|
+
# * *Default:* 0.0
|
|
40
|
+
# @attr duty [Float] LFO on-time. 0 to 1.
|
|
41
|
+
# * *Minimum:* 0.0
|
|
42
|
+
# * *Maximum:* 1.0
|
|
43
|
+
# * *Default:* 0.5
|
|
44
|
+
# @attr square [Float] Flatness of the LFO shape.
|
|
45
|
+
# * *Minimum:* 0.0
|
|
46
|
+
# * *Maximum:* 1.0
|
|
47
|
+
# * *Default:* 0.0
|
|
48
|
+
# @attr phase [Float] Instantaneous LFO phase.
|
|
49
|
+
# * *Minimum:* 0.0
|
|
50
|
+
# * *Maximum:* 1.0
|
|
51
|
+
# * *Default:* 0.0
|
|
52
|
+
# @attr spread [Float] Rotation / auto-pan effect.
|
|
53
|
+
# * *Minimum:* -1.0
|
|
54
|
+
# * *Maximum:* 1.0
|
|
55
|
+
# * *Default:* 0.0
|
|
56
|
+
class Tremolo < Dsp
|
|
57
|
+
float_param(0, :frequency, min: 0.1, max: 20.0)
|
|
58
|
+
float_param(1, :depth, min: 0.0, max: 1.0)
|
|
59
|
+
float_param(2, :shape, min: 0.0, max: 1.0)
|
|
60
|
+
float_param(3, :skew, min: -1.0, max: 1.0)
|
|
61
|
+
float_param(4, :duty, min: 0.0, max: 1.0)
|
|
62
|
+
float_param(5, :square, min: 0.0, max: 1.0)
|
|
63
|
+
float_param(6, :phase, min: 0.0, max: 1.0)
|
|
64
|
+
float_param(7, :spread, min: -1.0, max: 1.0)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/lib/fmod/error.rb
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module FMOD
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
|
|
4
|
+
include FMOD::Core
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# @overload initialize(code)
|
|
8
|
+
# @param code [Integer]
|
|
9
|
+
# @overload initialize(message)
|
|
10
|
+
# @param message [String]
|
|
11
|
+
def initialize(code)
|
|
12
|
+
message = code.is_a?(Integer) ? self.class.error_string(code) : code
|
|
13
|
+
super(message)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Retrieves a generic message for the specified result code.
|
|
18
|
+
# @param code [Integer] An FMOD generated error code.
|
|
19
|
+
# @return [String] A generic error message.
|
|
20
|
+
# @see Result
|
|
21
|
+
def self.error_string(code)
|
|
22
|
+
case code
|
|
23
|
+
when Result::BAD_COMMAND then "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound)."
|
|
24
|
+
when Result::CHANNEL_ALLOC then "Error trying to allocate a channel."
|
|
25
|
+
when Result::CHANNEL_STOLEN then "The specified channel has been reused to play another sound."
|
|
26
|
+
when Result::DMA then "DMA Failure. See debug output for more information."
|
|
27
|
+
when Result::DSP_CONNECTION then "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts."
|
|
28
|
+
when Result::DSP_DONT_PROCESS then "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph. "
|
|
29
|
+
when Result::DSP_FORMAT then "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map."
|
|
30
|
+
when Result::DSP_IN_USE then "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released."
|
|
31
|
+
when Result::DSP_NOT_FOUND then "DSP connection error. Couldn't find the DSP unit specified."
|
|
32
|
+
when Result::DSP_RESERVED then "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system."
|
|
33
|
+
when Result::DSP_SILENCE then "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph."
|
|
34
|
+
when Result::DSP_TYPE then "DSP operation cannot be performed on a DSP of this type. "
|
|
35
|
+
when Result::FILE_BAD then "Error loading file."
|
|
36
|
+
when Result::FILE_COULD__SEEK then "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format."
|
|
37
|
+
when Result::FILE_DISK_EJECTED then "Media was ejected while reading."
|
|
38
|
+
when Result::FILE_EOF then "End of file unexpectedly reached while trying to read essential data (truncated?)."
|
|
39
|
+
when Result::FILE_END_OF_DATA then "End of current chunk reached while trying to read data. "
|
|
40
|
+
when Result::FILE_NOT_FOUND then "File not found."
|
|
41
|
+
when Result::FORMAT then "Unsupported file or audio format."
|
|
42
|
+
when Result::HEADER_MISMATCH then "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library."
|
|
43
|
+
when Result::HTTP then " HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere."
|
|
44
|
+
when Result::HTTP_ACCESS then "The specified resource requires authentication or is forbidden."
|
|
45
|
+
when Result::HTTP_PROXY_AUTH then "Proxy authentication is required to access the specified resource. "
|
|
46
|
+
when Result::HTTP_SERVER_ERROR then "A HTTP server error occurred."
|
|
47
|
+
when Result::HTTP_TIMEOUT then "The HTTP request timed out. "
|
|
48
|
+
when Result::INITIALIZATION then "FMOD was not initialized correctly to support this function. "
|
|
49
|
+
when Result::INITIALIZED then "Cannot call this command after System::new."
|
|
50
|
+
when Result::INTERNAL then "An error occurred that wasn't supposed to. Contact support."
|
|
51
|
+
when Result::INVALID_FLOAT then "Value passed in was a NaN, Inf or denormalized float."
|
|
52
|
+
when Result::INVALID_HANDLE then "An invalid object handle was used."
|
|
53
|
+
when Result::INVALID_PARAM then "An invalid parameter was passed to this function."
|
|
54
|
+
when Result::INVALID_POSITION then "An invalid seek position was passed to this function."
|
|
55
|
+
when Result::INVALID_SPEAKER then "An invalid speaker was passed to this function based on the current speaker mode. "
|
|
56
|
+
when Result::INVALID_SYNC_POINT then "The syncpoint did not come from this sound handle."
|
|
57
|
+
when Result::INVALID_THREAD then "Tried to call a function on a thread that is not supported."
|
|
58
|
+
when Result::INVALID_VECTOR then "The vectors passed in are not unit length, or perpendicular."
|
|
59
|
+
when Result::MAX_AUDIBLE then "Reached maximum audible playback count for this sound's soundgroup."
|
|
60
|
+
when Result::MEMORY then "Not enough memory or resources."
|
|
61
|
+
when Result::MEMORY_CANT_POINT then "Can't use OPEN_MEMORY_POINT on non-PCM source data, or non mp3/xma/adpcm data if CREATE_COMPRESSED_SAMPLE was used."
|
|
62
|
+
when Result::NEEDS_3D then "Tried to call a command on a 2d sound when the command was meant for 3d sound."
|
|
63
|
+
when Result::NEEDS_HARDWARE then "Tried to use a feature that requires hardware support."
|
|
64
|
+
when Result::NET_CONNECT then "Couldn't connect to the specified host."
|
|
65
|
+
when Result::NET_SOCKET_ERROR then "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere."
|
|
66
|
+
when Result::NET_URL then "The specified URL couldn't be resolved."
|
|
67
|
+
when Result::NET_WOULD_BLOCK then "Operation on a non-blocking socket could not complete immediately. "
|
|
68
|
+
when Result::NOT_READY then "Operation could not be performed because specified sound/DSP connection is not ready."
|
|
69
|
+
when Result::OUTPUT_ALLOCATED then "Error initializing output device, but more specifically, the output device is already in use and cannot be reused."
|
|
70
|
+
when Result::OUTPUT_CREATE_BUFFER then "Error creating hardware sound buffer."
|
|
71
|
+
when Result::OUTPUT_DRIVER_CALL then "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted."
|
|
72
|
+
when Result::OUTPUT_FORMAT then "Soundcard does not support the specified format."
|
|
73
|
+
when Result::OUTPUT_INIT then "Error initializing output device."
|
|
74
|
+
when Result::OUTPUT_NO_DRIVERS then "The output device has no drivers installed. If pre-init, OUTPUT_NO_SOUND is selected as the output mode. If post-init, the function just fails."
|
|
75
|
+
when Result::PLUGIN then "An unspecified error has been returned from a plugin."
|
|
76
|
+
when Result::PLUGIN_MISSING then "A requested output, dsp unit type or codec was not available."
|
|
77
|
+
when Result::PLUGIN_RESOURCE then "A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback)"
|
|
78
|
+
when Result::PLUGIN_VERSION then "A plugin was built with an unsupported SDK version."
|
|
79
|
+
when Result::RECORD then "An error occurred trying to initialize the recording device."
|
|
80
|
+
when Result::REVERB_CHANNEL_GROUP then "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection."
|
|
81
|
+
when Result::REVERB_INSTANCE then "Specified instance in ReverbProperties couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist"
|
|
82
|
+
when Result::SUBSOUNDS then "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound."
|
|
83
|
+
when Result::SUBSOUND_ALLOCATED then "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first."
|
|
84
|
+
when Result::SUBSOUND_CANT_MOVE then "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file."
|
|
85
|
+
when Result::TAG_NOT_FOUND then "The specified tag could not be found or there are no tags."
|
|
86
|
+
when Result::TOO_MANY_CHANNELS then "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat."
|
|
87
|
+
when Result::TRUNCATED then "The retrieved string is too long to fit in the supplied buffer and has been truncated."
|
|
88
|
+
when Result::UNIMPLEMENTED then "Something in FMOD hasn't been implemented when it should be! contact support!"
|
|
89
|
+
when Result::UNINITIALIZED then "This command failed because System::new or System::set_driver was not called."
|
|
90
|
+
when Result::UNSUPPORTED then "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified"
|
|
91
|
+
when Result::VERSION then "The version number of this file format is not supported."
|
|
92
|
+
when Result::EVENT_ALREADY_LOADED then "The specified bank has already been loaded."
|
|
93
|
+
when Result::EVENT_LIVE_UPDATE_BUSY then "The live update connection failed due to the game already being connected."
|
|
94
|
+
when Result::EVENT_LIVE_UPDATE_MISMATCH then "The live update connection failed due to the game data being out of sync with the tool."
|
|
95
|
+
when Result::EVENT_LIVE_UPDATE_TIMEOUT then "The live update connection timed out."
|
|
96
|
+
when Result::EVENT_NOT_FOUND then "The requested event, bus or vca could not be found."
|
|
97
|
+
when Result::STUDIO_UNINITIALIZED then "The Studio::System object is not yet initialized."
|
|
98
|
+
when Result::STUDIO_NOT_LOADED then "The specified resource is not loaded, so it can't be unloaded."
|
|
99
|
+
when Result::INVALID_STRING then "An invalid string was passed to this function."
|
|
100
|
+
when Result::ALREADY_LOCKED then "The specified resource is already locked."
|
|
101
|
+
when Result::NOT_LOCKED then "The specified resource is not locked, so it can't be unlocked."
|
|
102
|
+
when Result::RECORD_DISCONNECTED then "The specified recording driver has been disconnected."
|
|
103
|
+
when Result::TOO_MANY_SAMPLES then "The length provided exceeds the allowable limit."
|
|
104
|
+
else "Unknown error. Code: #{code}"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
|
|
2
|
+
module FMOD
|
|
3
|
+
class Geometry < Handle
|
|
4
|
+
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# @!attribute active
|
|
9
|
+
# Value indicating if object will be processed in the geometry engine.
|
|
10
|
+
#
|
|
11
|
+
# @return [Boolean]
|
|
12
|
+
bool_reader(:active, :Geometry_GetActive)
|
|
13
|
+
bool_writer(:active=, :Geometry_SetActive)
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# @!attribute polygon_count
|
|
17
|
+
# Retrieves the number of polygons stored within this {Geometry} object.
|
|
18
|
+
#
|
|
19
|
+
# @return [Integer]
|
|
20
|
+
integer_reader(:polygon_count, :Geometry_GetNumPolygons)
|
|
21
|
+
|
|
22
|
+
alias size polygon_count
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# @!attribute position
|
|
26
|
+
# The position of the object in world space, which is the same space FMOD
|
|
27
|
+
# sounds and listeners reside in.
|
|
28
|
+
#
|
|
29
|
+
# @return [Vector]
|
|
30
|
+
|
|
31
|
+
def position
|
|
32
|
+
FMOD.invoke(:Geometry_GetPosition, self, vector = Vector.zero)
|
|
33
|
+
vector
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def position=(vector)
|
|
37
|
+
FMOD.type?(vector, Vector)
|
|
38
|
+
FMOD.invoke(:Geometry_SetPosition, self, vector)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# @!attribute scale
|
|
43
|
+
# The relative scale vector of the geometry object. An object can be
|
|
44
|
+
# scaled/warped in all 3 dimensions separately using the vector without
|
|
45
|
+
# having to modify polygon data.
|
|
46
|
+
# * *Default:* {Vector.one}
|
|
47
|
+
#
|
|
48
|
+
# @return [Vector]
|
|
49
|
+
|
|
50
|
+
def scale
|
|
51
|
+
FMOD.invoke(:Geometry_GetScale, self, vector = Vector.zero)
|
|
52
|
+
vector
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def scale=(vector)
|
|
56
|
+
FMOD.type?(vector, Vector)
|
|
57
|
+
FMOD.invoke(:Geometry_SetScale, self, vector)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# @!attribute rotation
|
|
62
|
+
# The current orientation of the geometry object.
|
|
63
|
+
#
|
|
64
|
+
# @return [Rotation]
|
|
65
|
+
# @see rotate
|
|
66
|
+
|
|
67
|
+
def rotation
|
|
68
|
+
forward, up = Vector.zero, Vector.zero
|
|
69
|
+
FMOD.invoke(:Geometry_GetRotation, self, forward, up)
|
|
70
|
+
Rotation.new(forward, up)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def rotation=(rotation)
|
|
74
|
+
FMOD.type?(rotation, Rotation)
|
|
75
|
+
rotate(*rotation.values)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Sets the orientation of the geometry object.
|
|
80
|
+
# @param forward [Vector] The forwards orientation of the geometry object.
|
|
81
|
+
# This vector must be of unit length and perpendicular to the upward
|
|
82
|
+
# vector. You can specify +nil+ to not update the forwards orientation of
|
|
83
|
+
# the geometry object.
|
|
84
|
+
# @param upward [Vector] The upwards orientation of the geometry object.
|
|
85
|
+
# This vector must be of unit length and perpendicular to the forward
|
|
86
|
+
# vector. You can specify +nil+ to not update the upwards orientation of
|
|
87
|
+
# the geometry object.
|
|
88
|
+
def rotate(forward, upward)
|
|
89
|
+
FMOD.type?(forward, Vector) unless forward.nil?
|
|
90
|
+
FMOD.type?(upward, Vector) unless upward.nil?
|
|
91
|
+
FMOD.invoke(:Geometry_SetRotation, self, forward, upward)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
##
|
|
95
|
+
# Retrieves the maximum number of polygons allocatable for this object.
|
|
96
|
+
#
|
|
97
|
+
# This is not the number of polygons currently present.
|
|
98
|
+
#
|
|
99
|
+
# @return [Integer]
|
|
100
|
+
def max_polygons
|
|
101
|
+
max = "\0" * SIZEOF_INT
|
|
102
|
+
FMOD.invoke(:Geometry_GetMaxPolygons, self, max, nil)
|
|
103
|
+
max.unpack1('l')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Retrieves the maximum number of vertices allocatable for this object.
|
|
107
|
+
#
|
|
108
|
+
# This is not the number of vertices currently present.
|
|
109
|
+
#
|
|
110
|
+
# @return [Integer]
|
|
111
|
+
def max_vertices
|
|
112
|
+
max = "\0" * SIZEOF_INT
|
|
113
|
+
FMOD.invoke(:Geometry_GetMaxPolygons, self, nil, max)
|
|
114
|
+
max.unpack1('l')
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# Retrieves the {Polygon} at the specified index.
|
|
119
|
+
# @param index [Integer] The index of the Polygon to retrieve.
|
|
120
|
+
# @return [Polygon]
|
|
121
|
+
def [](index)
|
|
122
|
+
return nil unless index.between?(0, polygon_count)
|
|
123
|
+
Polygon.send(:new, self, index)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
##
|
|
127
|
+
# Adds a polygon to an geometry object.
|
|
128
|
+
#
|
|
129
|
+
# @note A minimum of 3 vertices is required to create a {Polygon}.
|
|
130
|
+
#
|
|
131
|
+
# @param vertices [Array<Vector>] array of vertices located in object space.
|
|
132
|
+
# @param direct [Float] Occlusion value which affects volume or audible
|
|
133
|
+
# frequencies.
|
|
134
|
+
# * *Minimum:* 0.0 The polygon does not occlude volume or audible
|
|
135
|
+
# frequencies (sound will be fully audible)
|
|
136
|
+
# * *Maximum:* 1.0 The polygon fully occludes (sound will be silent)
|
|
137
|
+
# @param reverb [Float] Occlusion value from 0.0 to 1.0 which affects the
|
|
138
|
+
# reverb mix.
|
|
139
|
+
# * *Minimum:* 0.0 The polygon does not occlude reverb (reverb reflections
|
|
140
|
+
# still travel through this polygon)
|
|
141
|
+
# * *Maximum:* 1.0 The polygon fully occludes reverb (reverb reflections
|
|
142
|
+
# will be silent through this polygon).
|
|
143
|
+
# @param double_sided [Boolean] Description of polygon if it is double sided
|
|
144
|
+
# or single sided.
|
|
145
|
+
# * *true:* Polygon is double sided
|
|
146
|
+
# * *false:* Polygon is single sided, and the winding of the polygon
|
|
147
|
+
# (which determines the polygon's normal) determines which side of the
|
|
148
|
+
# polygon will cause occlusion.
|
|
149
|
+
def add_polygon(vertices, direct = 0.0, reverb = 0.0, double_sided = false)
|
|
150
|
+
size = vertices.size
|
|
151
|
+
unless size >= 3
|
|
152
|
+
message = "3 or more vertices required for polygon: #{size} specified"
|
|
153
|
+
raise ArgumentError, message
|
|
154
|
+
end
|
|
155
|
+
vectors = vertices.map(&:to_str).join
|
|
156
|
+
direct = direct.clamp(0.0, 1.0)
|
|
157
|
+
reverb = reverb.clamp(0.0, 1.0)
|
|
158
|
+
FMOD.invoke(:Geometry_AddPolygon, self, direct, reverb,
|
|
159
|
+
double_sided.to_i, size, vectors, index = "\0" * SIZEOF_INT)
|
|
160
|
+
Polygon.send(:new, self, index.unpack1('l'))
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
##
|
|
164
|
+
# Serializes the {Geometry} object into a binary block.
|
|
165
|
+
#
|
|
166
|
+
# @overload save(filename)
|
|
167
|
+
# @param filename [String] A filename where object will be saved to.
|
|
168
|
+
# @return [Boolean] +true+ if object was successfully flushed to disk,
|
|
169
|
+
# otherwise +false+.
|
|
170
|
+
# @overload save
|
|
171
|
+
# Serializes the {Geometry} object and returns the data as a binary
|
|
172
|
+
# string.
|
|
173
|
+
# @return [String]
|
|
174
|
+
# @see System.load_geometry
|
|
175
|
+
def save(filename = nil)
|
|
176
|
+
FMOD.invoke(:Geometry_Save, self, nil, size = "\0" * SIZEOF_INT)
|
|
177
|
+
data = "\0" * size.unpack1('l')
|
|
178
|
+
FMOD.invoke(:Geometry_Save, self, data, size)
|
|
179
|
+
unless filename.nil?
|
|
180
|
+
File.open(filename, 'wb') { |file| file.write(data) } rescue return false
|
|
181
|
+
return true
|
|
182
|
+
end
|
|
183
|
+
data
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
##
|
|
187
|
+
# Enumerates the polygons contained within the {Geometry}.
|
|
188
|
+
#
|
|
189
|
+
# @overload each
|
|
190
|
+
# When called with block, yields each {Polygon} within the object before
|
|
191
|
+
# returning self.
|
|
192
|
+
# @yield [polygon] Yields a polygon to the block.
|
|
193
|
+
# @yieldparam polygon [Polygon] The current enumerated polygon.
|
|
194
|
+
# @return [self]
|
|
195
|
+
# @overload each
|
|
196
|
+
# When no block specified, returns an Enumerator for the {Geometry}.
|
|
197
|
+
# @return [Enumerator]
|
|
198
|
+
def each
|
|
199
|
+
return to_enum(:each) unless block_given?
|
|
200
|
+
(0...polygon_count).each { |i| yield self[i] }
|
|
201
|
+
self
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
##
|
|
205
|
+
# Retrieves an array of {Polygon} objects within this {Geometry}.
|
|
206
|
+
# @return [Array<Polygon>]
|
|
207
|
+
def polygons
|
|
208
|
+
(0...polygon_count).map { |i| self[i] }
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
##
|
|
212
|
+
# Describes the orientation of a geometry object.
|
|
213
|
+
# @attr forward [Vector] The forwards orientation of the geometry object.
|
|
214
|
+
# This vector must be of unit length and perpendicular to the {#up}
|
|
215
|
+
# vector. You can specify +nil+ to not update the forwards orientation of
|
|
216
|
+
# the geometry object.
|
|
217
|
+
# @attr up [Vector] The upwards orientation of the geometry object. This
|
|
218
|
+
# vector must be of unit length and perpendicular to the {#forward}
|
|
219
|
+
# vector. You can specify +nil+ to not update the upwards orientation of
|
|
220
|
+
# the geometry object.
|
|
221
|
+
Rotation = Struct.new(:forward, :up)
|
|
222
|
+
|
|
223
|
+
##
|
|
224
|
+
# @abstract
|
|
225
|
+
# Wrapper class for a polygon within a {Geometry} object.
|
|
226
|
+
class Polygon
|
|
227
|
+
|
|
228
|
+
include Enumerable
|
|
229
|
+
|
|
230
|
+
private_class_method :new
|
|
231
|
+
|
|
232
|
+
##
|
|
233
|
+
# The parent geometry object.
|
|
234
|
+
# @return [Geometry]
|
|
235
|
+
attr_reader :geometry
|
|
236
|
+
|
|
237
|
+
##
|
|
238
|
+
# The index of the {Polygon} within its parent {Geometry} object.
|
|
239
|
+
# @return [Integer]
|
|
240
|
+
attr_reader :index
|
|
241
|
+
|
|
242
|
+
##
|
|
243
|
+
# Creates a new instance of a Polygon object.
|
|
244
|
+
# @note Polygon objects should not be created by the user, only through
|
|
245
|
+
# {Geometry.add_polygon}, as they are an abstract wrapper only, not
|
|
246
|
+
# backed by an actual object.
|
|
247
|
+
# @param geometry [Geometry] The parent geometry object.
|
|
248
|
+
# @param index [Integer] The index of the polygon within the geometry.
|
|
249
|
+
# @api private
|
|
250
|
+
def initialize(geometry, index)
|
|
251
|
+
@geometry, @index = geometry, index
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
##
|
|
255
|
+
# @!attribute direct_occlusion
|
|
256
|
+
# The occlusion value from 0.0 to 1.0 which affects volume or audible
|
|
257
|
+
# frequencies.
|
|
258
|
+
# * *Minimum:* 0.0 The polygon does not occlude volume or audible
|
|
259
|
+
# frequencies (sound will be fully audible)
|
|
260
|
+
# * *Maximum:* 1.0 The polygon fully occludes (sound will be silent)
|
|
261
|
+
#
|
|
262
|
+
# @return [Float]
|
|
263
|
+
|
|
264
|
+
def direct_occlusion
|
|
265
|
+
occlusion = "\0" * Fiddle::SIZEOF_FLOAT
|
|
266
|
+
FMOD.invoke(:Geometry_GetPolygonAttributes, @geometry, @index,
|
|
267
|
+
occlusion, nil, nil)
|
|
268
|
+
occlusion.unpack1('f')
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def direct_occlusion=(occlusion)
|
|
272
|
+
FMOD.invoke(:Geometry_SetPolygonAttributes, @geometry, @index,
|
|
273
|
+
occlusion.clamp(0.0, 1.0), reverb_occlusion, double_sided.to_i)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
##
|
|
277
|
+
# @!attribute reverb_occlusion
|
|
278
|
+
# The occlusion value from 0.0 to 1.0 which affects the reverb mix.
|
|
279
|
+
# * *Minimum:* 0.0 The polygon does not occlude reverb (reverb
|
|
280
|
+
# reflections still travel through this polygon)
|
|
281
|
+
# * *Maximum:* 1.0 The polygon fully occludes reverb (reverb
|
|
282
|
+
# reflections will be silent through this polygon)
|
|
283
|
+
#
|
|
284
|
+
# @return [Float]
|
|
285
|
+
|
|
286
|
+
def reverb_occlusion
|
|
287
|
+
occlusion = "\0" * Fiddle::SIZEOF_FLOAT
|
|
288
|
+
FMOD.invoke(:Geometry_GetPolygonAttributes, @geometry, @index,
|
|
289
|
+
nil, occlusion, nil)
|
|
290
|
+
occlusion.unpack1('f')
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def reverb_occlusion=(occlusion)
|
|
294
|
+
FMOD.invoke(:Geometry_SetPolygonAttributes, @geometry, @index,
|
|
295
|
+
direct_occlusion, occlusion.clamp(0.0, 1.0), double_sided.to_i)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
##
|
|
299
|
+
# @!attribute double_sided
|
|
300
|
+
# The description of polygon if it is double sided or single sided.
|
|
301
|
+
# * *true:* The polygon is double sided
|
|
302
|
+
# * *false:* The polygon is single sided, and the winding of the polygon
|
|
303
|
+
# (which determines the polygon's normal) determines which side of the
|
|
304
|
+
# polygon will cause occlusion.
|
|
305
|
+
#
|
|
306
|
+
# @return [Boolean]
|
|
307
|
+
|
|
308
|
+
def double_sided
|
|
309
|
+
double = "\0" * Fiddle::SIZEOF_INT
|
|
310
|
+
FMOD.invoke(:Geometry_GetPolygonAttributes, @geometry, @index,
|
|
311
|
+
nil, nil, double)
|
|
312
|
+
double.unpack1('l') != 0
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def double_sided=(double_sided)
|
|
316
|
+
FMOD.invoke(:Geometry_SetPolygonAttributes, @geometry, @index,
|
|
317
|
+
direct_occlusion, reverb_occlusion, double_sided.to_i)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
##
|
|
321
|
+
# Retrieves the number of vertices within the polygon.
|
|
322
|
+
# @return [Integer]
|
|
323
|
+
def vertex_count
|
|
324
|
+
count = "\0" * Fiddle::SIZEOF_INT
|
|
325
|
+
FMOD.invoke(:Geometry_GetPolygonNumVertices, @geometry, @index, count)
|
|
326
|
+
count.unpack1('l')
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
alias size vertex_count
|
|
330
|
+
|
|
331
|
+
##
|
|
332
|
+
# Retrieves the vertex of the polygon at the specified index.
|
|
333
|
+
# @param index [Integer] The index of the vertex to retrieve.
|
|
334
|
+
# @return [Vector]
|
|
335
|
+
def [](index)
|
|
336
|
+
return nil unless index.between?(0, vertex_count - 1)
|
|
337
|
+
vertex = Vector.zero
|
|
338
|
+
FMOD.invoke(:Geometry_GetPolygonVertex, @geometry, @index, index, vertex)
|
|
339
|
+
vertex
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
##
|
|
343
|
+
# Sets the vertex of the polygon at the specified index.
|
|
344
|
+
# @param index [Integer] The index of the vertex to set.
|
|
345
|
+
# @param vertex [Vector] The vertex to set.
|
|
346
|
+
# @return [Vector] The vertex.
|
|
347
|
+
def []=(index, vertex)
|
|
348
|
+
unless index.between?(0, vertex_count - 1)
|
|
349
|
+
message = "Index #{index} outside of bounds: 0...#{vertex.count}"
|
|
350
|
+
raise IndexError, message
|
|
351
|
+
end
|
|
352
|
+
FMOD.type?(vertex, Vector)
|
|
353
|
+
FMOD.invoke(:Geometry_SetPolygonVertex, @geometry, @index, index, vertex)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
##
|
|
357
|
+
# @overload each
|
|
358
|
+
# When called with a block, yields each vertex in turn before returning
|
|
359
|
+
# self.
|
|
360
|
+
# @yield [vertex] Yields a vertex to the block.
|
|
361
|
+
# @yieldparam vertex [Vector] The enumerated vertex.
|
|
362
|
+
# @return [self]
|
|
363
|
+
# @overload each
|
|
364
|
+
# Returns an Enumerator for the polygon.
|
|
365
|
+
# @return [Enumerator]
|
|
366
|
+
def each
|
|
367
|
+
return to_enum(:each) unless block_given?
|
|
368
|
+
(0...vertex_count).each { |i| yield self[i] }
|
|
369
|
+
self
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
##
|
|
373
|
+
# Retrieves an array of the vertices within the polygon.
|
|
374
|
+
# @return [Array<Vector>]
|
|
375
|
+
def vertices
|
|
376
|
+
(0...vertex_count).map { |i| self[i] }
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|