/* * Author: Andrew Robberts * * Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "effects/pseffectobjsound.h" #include "effects/pseffectanchor.h" #include "util/pscssetup.h" #include "util/log.h" #include psEffectObjSound::psEffectObjSound(iView *parentView) : psEffectObj(parentView) { } psEffectObjSound::~psEffectObjSound() { if (soundmanager->GetSoundSystem()) { if (sndSource.IsValid()) { soundmanager->GetSoundSystem()->RemoveSource(sndSource); } if (sndStream.IsValid()) { soundmanager->GetSoundSystem()->RemoveStream(sndStream); } } } bool psEffectObjSound::Load(iDocumentNode *node) { if (!psEffectObj::Load(node)) return false; // get the attributes name = ""; soundName = ""; minDistSquared = 25.0f; maxDistSquared = 100000.0f; loop = true; csRef attribIter = node->GetAttributes(); while (attribIter->HasNext()) { csRef attr = attribIter->Next(); csString attrName = attr->GetName(); attrName.Downcase(); if (attrName == "name") name = attr->GetValue(); else if (attrName == "resource") soundName = attr->GetValue(); else if (attrName == "loop") loop = attr->GetValueAsBool(); } if (!loop && killTime <= 0) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Can't have a looping sound effect without a death.\n"); return false; } csRef dataNode; // min distance dataNode = node->GetNode("mindist"); if (dataNode) { minDistSquared = dataNode->GetContentsValueAsFloat(); minDistSquared *= minDistSquared; } // max distance dataNode = node->GetNode("maxdist"); if (dataNode) { maxDistSquared = dataNode->GetContentsValueAsFloat(); maxDistSquared *= maxDistSquared; } if (name == "") { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Attempting to create an effect obj with no name.\n"); return false; } return PostSetup(); } bool psEffectObjSound::Render(const csVector3 &up) { static unsigned long nextUniqueID = 0; csString effectID = "effect_sound_"; effectID += nextUniqueID++; if (soundmanager->PlayingActions()) { if (!sndStream.IsValid()) { sndStream = soundmanager->GetSoundSystem()->CreateStream(sndData, CS_SND3D_RELATIVE); if (!sndStream.IsValid()) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Could not create stream for sound: %s\n", soundName.GetData()); return false; } } if (!sndSource.IsValid()) { if (!soundmanager->GetSoundSystem()) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Could not create %s effect obj sound source. Sound system not found.\n", name.GetData()); return false; } csRef src = soundmanager->GetSoundSystem()->CreateSource(sndStream); if (!src.IsValid()) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Could not create %s effect obj sound source.\n", name.GetData()); return false; } sndSource=SCF_QUERY_INTERFACE(src, SOUND_SOURCE3D_TYPE); if (!sndSource.IsValid()) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Could not create %s effect obj sound 3D source.\n", name.GetData()); return false; } } // Setup looping on the stream if (loop) sndStream->SetLoopState(CS_SNDSYS_STREAM_LOOP); else sndStream->SetLoopState(CS_SNDSYS_STREAM_DONTLOOP); volumeMultiplier = soundmanager->GetActionsVolume(); sndSource->SetVolume(volumeMultiplier); sndSource->SetPosition(csVector3(0,0,0)); sndSource->SetMinimumDistance(sqrt(minDistSquared)); sndSource->SetMaximumDistance(sqrt(maxDistSquared)); isAlive = false; return true; } return false; } bool psEffectObjSound::AttachToAnchor(psEffectAnchor * newAnchor) { if ( newAnchor && newAnchor->GetMesh() ) anchorMesh = newAnchor->GetMesh(); anchor = newAnchor; return true; } bool psEffectObjSound::Update(csTicks elapsed) { if (!sndSource) //If there was no sound why update? return true; if (!anchor || !anchor->IsReady()) // wait for anchor to be ready return true; life += (float)elapsed; while (life > animLength && killTime <= 0) life -= animLength; if (life >= birth && !isAlive) { isAlive = true; sndStream->ResetPosition(); sndStream->Unpause(); } csVector3 soundPos = anchorMesh->GetMovable()->GetPosition(); if (keyFrames->Length() > 0) { currKeyFrame = FindKeyFrameByTime(life); nextKeyFrame = currKeyFrame + 1; if (nextKeyFrame >= keyFrames->Length()) nextKeyFrame = 0; // position soundPos += LERP_VEC_KEY(KA_POS); // volume sndSource->SetVolume(LERP_KEY(KA_SCALE) * volumeMultiplier); } sndSource->SetPosition(view->GetCamera()->GetTransform().Other2This(soundPos)); if (killTime <= 0) return true; killTime -= (int)elapsed; if (killTime <= 0) return false; return true; } psEffectObj *psEffectObjSound::Clone() const { psEffectObjSound *newObj = new psEffectObjSound(view); CloneBase(newObj); // simp mesh specific newObj->soundName = soundName; newObj->minDistSquared = minDistSquared; newObj->maxDistSquared = maxDistSquared; newObj->loop = loop; newObj->soundmanager = soundmanager; newObj->sndData = sndData; // newObj->sndStream = sndStream; // newObj->sndSource = sndSource; return newObj; } bool psEffectObjSound::PostSetup() { soundmanager = CS_QUERY_REGISTRY(psCSSetup::object_reg, iSoundManager); if ( soundmanager ) { if ( !soundmanager->Setup() ) return false; } else { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "No sound manager to load sound: %s\n", soundName.GetData()); return false; } if (!sndData.IsValid()) { sndData = soundmanager->GetSoundResource(soundName); if (!sndData.IsValid()) { csReport(psCSSetup::object_reg, CS_REPORTER_SEVERITY_ERROR, "planeshift_effects", "Could not load sound: %s\n", soundName.GetData()); return false; } } return true; }