18 | function SoundNode:new(soundNode, group, customMt) |
19 | |
20 | local self = {} |
21 | setmetatable(self, customMt or SoundNode_mt) |
22 | |
23 | if not getHasClassId(soundNode, ClassIds.AUDIO_SOURCE) then |
24 | g_logManager:warning("SoundNode '%s' is not an AUDIO_SOURCE!", tostring(getName(soundNode))) |
25 | return nil |
26 | end |
27 | |
28 | self.soundNode = soundNode |
29 | self.nodes = {} |
30 | self.currentNode = nil |
31 | self.nextNode = nil |
32 | self.outerRange = getAudioSourceRange(soundNode) |
33 | self.innerRange = getAudioSourceInnerRange(soundNode) |
34 | self.nextPlayTime = g_time |
35 | self.nextCheckTime = nil |
36 | |
37 | local function addSoundSource(node, group) |
38 | local sample = getAudioSourceSample(node) |
39 | local duration = getSampleDuration(sample) |
40 | setSampleGroup(sample, group) |
41 | local volume = getSampleVolume(sample) |
42 | setAudioSourceAutoPlay(node, false) |
43 | stopSample(sample, 0, 0) |
44 | table.insert(self.nodes, {index=#self.nodes+1, node=node, sample=sample, volume=volume, duration=duration}) |
45 | end |
46 | |
47 | addSoundSource(soundNode, group) |
48 | |
49 | for i=getNumOfChildren(soundNode)-1, 0, -1 do |
50 | local child = getChildAt(soundNode, i) |
51 | if getHasClassId(child, ClassIds.AUDIO_SOURCE) then |
52 | setAudioSourceRange(child, self.outerRange) |
53 | setAudioSourceInnerRange(child, self.innerRange) |
54 | addSoundSource(child, group) |
55 | end |
56 | end |
57 | |
58 | self.retriggerMinDelay = Utils.getNoNil(getUserAttribute(soundNode, "retriggerMinDelay"), 0) * 1000 |
59 | self.retriggerMaxDelay = Utils.getNoNil(getUserAttribute(soundNode, "retriggerMaxDelay"), 0) * 1000 |
60 | |
61 | -- if retriggerMinDelay = 0 we need to make sure that there are at least 2 sounds to calculate offsets and seamless playing |
62 | if self.retriggerMinDelay == 0 then |
63 | if #self.nodes == 1 then |
64 | -- copy sound |
65 | local node = self.nodes[1] |
66 | local newNode = clone(node.node, true, false, false) |
67 | setName(newNode, getName(newNode).."_copy") |
68 | addSoundSource(newNode, group) |
69 | end |
70 | end |
71 | |
72 | local tx,ty,tz = getTranslation(soundNode) |
73 | local rx,ry,rz = getRotation(soundNode) |
74 | |
75 | self.parent = createTransformGroup("soundGroup_"..getName(soundNode)) |
76 | link(getParent(soundNode), self.parent, getChildIndex(soundNode)) |
77 | setTranslation(self.parent, tx, ty, tz) |
78 | setRotation(self.parent, rx, ry, rz) |
79 | |
80 | for _, soundNode in ipairs(self.nodes) do |
81 | link(self.parent, soundNode.node) |
82 | setTranslation(soundNode.node, 0, 0, 0) |
83 | setRotation(soundNode.node, 0, 0, 0) |
84 | end |
85 | |
86 | self.playByDay = Utils.getNoNil(getUserAttribute(soundNode, "playByDay"), false) |
87 | self.playByNight = Utils.getNoNil(getUserAttribute(soundNode, "playByNight"), false) |
88 | if not self.playByDay and not self.playByNight then |
89 | g_logManager:warning("Ambient 3D sound '%s' has invalid time state. At least one of the states 'playByDay' or 'playByNight' need to be 'true'", getName(soundNode)) |
90 | end |
91 | self.playDuringHail = Utils.getNoNil(getUserAttribute(soundNode, "playDuringHail"), false) |
92 | self.playDuringRain = Utils.getNoNil(getUserAttribute(soundNode, "playDuringRain"), false) |
93 | self.playDuringSun = Utils.getNoNil(getUserAttribute(soundNode, "playDuringSun"), false) |
94 | if not self.playDuringHail and not self.playDuringRain and not self.playDuringSun then |
95 | g_logManager:warning("Ambient 3D sound '%s' has invalid weather state. At least one of the states 'playDuringHail', 'playDuringRain' or 'playDuringSun' need to be 'true'", getName(soundNode)) |
96 | end |
97 | self.playInsideBuilding = Utils.getNoNil(getUserAttribute(soundNode, "playInsideBuilding"), true) |
98 | |
99 | self.playExterior = Utils.getNoNil(getUserAttribute(soundNode, "playExterior"), false) |
100 | self.playInterior = Utils.getNoNil(getUserAttribute(soundNode, "playInterior"), false) |
101 | if not self.playExterior and not self.playInterior then |
102 | g_logManager:warning("Ambient 3D sound '%s' has invalid position state. At least one of the states 'playExterior' or 'playInterior' need to be 'true'", getName(soundNode)) |
103 | end |
104 | |
105 | self.playHourStart = MathUtil.clamp(Utils.getNoNil(getUserAttribute(soundNode, "playHourStart"), 0), 0, 24) * 1000 * 60 * 60 |
106 | self.playHourEnd = MathUtil.clamp(Utils.getNoNil(getUserAttribute(soundNode, "playHourEnd"), 24), 0, 24) * 1000 * 60 * 60 |
107 | self.playHourInverted = Utils.getNoNil(getUserAttribute(soundNode, "playHourInverted"), false) |
108 | self.playHour = Utils.getNoNil(getUserAttribute(soundNode, "playHour"), false) |
109 | |
110 | self.autoStop = Utils.getNoNil(getUserAttribute(soundNode, "autoStop"), true) |
111 | self.isLooping = Utils.getNoNil(getUserAttribute(soundNode, "isLooping"), false) |
112 | self.fadeOutDuration = Utils.getNoNil(getUserAttribute(soundNode, "fadeOutDuration"), 0) * 1000 |
113 | |
114 | return self |
115 | end |