diff --git a/Makefile b/Makefile index 7949a3c5e..063974364 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ DMD=gdmd -version=Posix NIFFLAGS= # Compiler settings for Ogre + OIS. Change as needed. -OGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags OGRE OIS openal` +OGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags OGRE OIS` # Compiler settings for ffmpeg. Change as needed. AVGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags libavcodec libavformat` diff --git a/README.txt b/README.txt index 49caed009..995282b5e 100644 --- a/README.txt +++ b/README.txt @@ -113,7 +113,7 @@ Thanks goes out to: - Bastien Jansen for continued testing on 64 bit linux. -- Chris Robinson for OpenAL and ALUT support +- Chris Robinson for OpenAL and MP3 support diff --git a/core/config.d b/core/config.d index 1c704b851..34a8037a5 100644 --- a/core/config.d +++ b/core/config.d @@ -237,6 +237,8 @@ struct ConfigManager bind(Keys.SfxVolUp, KC.N4); bind(Keys.Mute, KC.M); + bind(Keys.Fullscreen, KC.F); + bind(Keys.ToggleBattleMusic, KC.SPACE); bind(Keys.Debug, KC.G); diff --git a/input/events.d b/input/events.d index eec90371a..a4413c690 100644 --- a/input/events.d +++ b/input/events.d @@ -90,6 +90,11 @@ void toggleBattle() } } +void toggleFullscreen() +{ + cpp_toggleFullscreen(); +} + const float volDiff = 0.05; void musVolume(bool increase) @@ -212,6 +217,7 @@ extern(C) void d_handleKey(KC keycode, dchar text = 0) case Keys.SfxVolUp: sfxVolume(true); break; case Keys.SfxVolDown: sfxVolume(false); break; case Keys.Mute: toggleMute(); break; + case Keys.Fullscreen: toggleFullscreen(); break; case Keys.Debug: cpp_debug(0); break; case Keys.ScreenShot: takeScreenShot(); break; @@ -265,16 +271,14 @@ bool isPressed(Keys key) extern(C) int d_frameStarted(float time) { - /* tmpTime += time; cnt++; - if(tmpTime >= 1.0) + if(tmpTime >= 1.5) { - writefln("\nfps: ", cnt/tmpTime); + writefln("fps: ", cnt/tmpTime); cnt = 0; tmpTime = 0; } - //*/ if(doExit) return 0; diff --git a/input/keys.d b/input/keys.d index 5ad88deb5..9773f6500 100644 --- a/input/keys.d +++ b/input/keys.d @@ -62,7 +62,8 @@ enum Keys SfxVolUp, SfxVolDown, Mute, - // This will not be part of the finished product :) + // These will not be part of the finished product + Fullscreen, ToggleBattleMusic, Debug, @@ -245,6 +246,7 @@ struct KeyBindings keyToString[Keys.SfxVolDown] = "Decrease SFX Volume"; keyToString[Keys.Mute] = "Mute Sound"; + keyToString[Keys.Fullscreen] = "Toggle Fullscreen Mode"; keyToString[Keys.ToggleBattleMusic] = "Toggle Battle Music"; keyToString[Keys.Debug] = "OGRE Test Action"; diff --git a/ogre/bindings.d b/ogre/bindings.d index 6af7237fd..9df84bab2 100644 --- a/ogre/bindings.d +++ b/ogre/bindings.d @@ -137,6 +137,9 @@ void cpp_createMesh( NodePtr owner // Scene node to attach to. ); +// Toggle fullscreen mode +void cpp_toggleFullscreen(); + // Save a screen shot to the given file name void cpp_screenshot(char *filename); diff --git a/ogre/cpp_interface.cpp b/ogre/cpp_interface.cpp index a597eafac..80446c568 100644 --- a/ogre/cpp_interface.cpp +++ b/ogre/cpp_interface.cpp @@ -215,9 +215,8 @@ extern "C" Light* cpp_attachLight(char *name, SceneNode* base, l->setDiffuseColour(r,g,b); - // Pulled these numbers out of nowhere. Looks OK-ish. I can polish - // it later. - l->setAttenuation(8*radius, 0, 0.008, 0.0); + // This seems to look reasonably ok. + l->setAttenuation(3*radius, 0, 0, 12.0/(radius*radius)); // base might be null, sometimes lights don't have meshes if(base) base->attachObject(l); @@ -225,6 +224,12 @@ extern "C" Light* cpp_attachLight(char *name, SceneNode* base, return l; } +// Toggle between fullscreen and windowed mode. +extern "C" void cpp_toggleFullscreen() +{ + std::cout << "Not implemented yet\n"; +} + extern "C" void cpp_setAmbient(float r, float g, float b, // Ambient light float rs, float gs, float bs) // "Sunlight" { diff --git a/openmw.ini.win32 b/openmw.ini.win32 index fa3680ef3..8089ad85f 100755 --- a/openmw.ini.win32 +++ b/openmw.ini.win32 @@ -29,6 +29,7 @@ Decrease Music Volume=1 Increase SFX Volume=4 Decrease SFX Volume=3 Mute Sound=m +Toggle Fullscreen Mode=f Toggle Battle Music=space OGRE Test Action=g Pause=pause,p diff --git a/scene/soundlist.d b/scene/soundlist.d index 92694af43..ad45526ef 100644 --- a/scene/soundlist.d +++ b/scene/soundlist.d @@ -73,6 +73,10 @@ struct SoundList float upx, float upy, float upz) { SoundInstance.setPlayerPos(x,y,z,frontx,fronty,frontz,upx,upy,upz); + foreach(ref s; list) + { + if(s.owner) s.updateSound(); + } } void kill() diff --git a/sound/audio.d b/sound/audio.d index d564e359e..bf6f913b5 100644 --- a/sound/audio.d +++ b/sound/audio.d @@ -54,11 +54,6 @@ void initializeSound() alcMakeContextCurrent(Context); - // Gross HACK: We should use the default model (inverse distance clamped). - // But without a proper rolloff factor, distance attenuation is completely - // wrong. This at least makes sure the max distance is the 'silence' point - alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); - jukebox.initialize("Main"); battleMusic.initialize("Battle"); } @@ -75,11 +70,14 @@ void shutdownSound() Device = null; } -ALenum checkALError() +bool checkALError(char[] what = "") { ALenum err = alGetError(); + if(what.length) what = " while " ~ what; if(err != AL_NO_ERROR) - writefln("WARNING: Received AL error (%x): %s", err, - toString(alGetString(err))); - return err; + writefln("WARNING: OpenAL error%s: (%x) %s", what, err, + toString(alGetString(err))); + + + return err != AL_NO_ERROR; } diff --git a/sound/music.d b/sound/music.d index f58dbf623..dd4dcd531 100644 --- a/sound/music.d +++ b/sound/music.d @@ -151,17 +151,19 @@ struct MusicManager if(!sID) { alGenSources(1, &sID); - if(checkALError() != AL_NO_ERROR) - return; + if(checkALError()) + fail("Couldn't generate music sources"); alSourcei(sID, AL_SOURCE_RELATIVE, AL_TRUE); } - - // Kill current track - alSourceStop(sID); - alSourcei(sID, AL_BUFFER, 0); - alDeleteBuffers(bIDs.length, bIDs.ptr); - foreach(ref b; bIDs) b = 0; - checkALError(); + else + { + // Kill current track + alSourceStop(sID); + alSourcei(sID, AL_BUFFER, 0); + alDeleteBuffers(bIDs.length, bIDs.ptr); + bIDs[] = 0; + checkALError("killing current track"); + } if(fileHandle) cpp_closeAVFile(fileHandle); fileHandle = null; @@ -175,35 +177,42 @@ struct MusicManager } alGenBuffers(bIDs.length, bIDs.ptr); - if(checkALError() != AL_NO_ERROR) + + // If something fails, clean everything up. + scope(failure) { - writefln("Unable to create %d buffers", bIDs.length); + if(fileHandle) cpp_closeAVFile(fileHandle); + + fileHandle = null; + audioHandle = null; + + alSourceStop(sID); alDeleteSources(1, &sID); - checkALError(); + alDeleteBuffers(bIDs.length, bIDs.ptr); + + checkALError("cleaning up after music failure"); + sID = 0; - return; + bIDs[] = 0; + + // Try the next track if playNext is called again + index++; } + if(checkALError()) + fail("Couldn't generate buffers"); + fileHandle = cpp_openAVFile(toStringz(playlist[index])); if(!fileHandle) - { - writefln("Unable to open %s", playlist[index]); - goto errclose; - } + fail("Unable to open " ~ playlist[index]); audioHandle = cpp_getAVAudioStream(fileHandle, 0); if(!audioHandle) - { - writefln("Unable to load music track %s", playlist[index]); - goto errclose; - } + fail("Unable to load music track " ~ playlist[index]); int ch, bits, rate; if(cpp_getAVAudioInfo(audioHandle, &rate, &ch, &bits) != 0) - { - writefln("Unable to get info for music track %s", playlist[index]); - goto errclose; - } + fail("Unable to get info for music track " ~ playlist[index]); bufRate = rate; bufFormat = 0; @@ -221,24 +230,19 @@ struct MusicManager } if(bufFormat == 0) - { - writefln("Unhandled format (%d channels, %d bits) for music track %s", ch, bits, playlist[index]); - goto errclose; - } + fail(format("Unhandled format (%d channels, %d bits) for music track %s", ch, bits, playlist[index])); foreach(int i, ref b; bIDs) { int length = cpp_getAVAudioData(audioHandle, outData.ptr, outData.length); if(length) alBufferData(b, bufFormat, outData.ptr, length, bufRate); - if(length == 0 || checkALError() != AL_NO_ERROR) + if(length == 0 || checkALError()) { if(i == 0) - { - writefln("No audio data in music track %s", playlist[index]); - goto errclose; - } + fail("No audio data in music track " ~ playlist[index]); + alDeleteBuffers(bIDs.length-i, bIDs.ptr+i); - checkALError(); + checkALError("running alDeleteBuffers"); bIDs[i..$] = 0; break; } @@ -246,25 +250,11 @@ struct MusicManager alSourceQueueBuffers(sID, bIDs.length, bIDs.ptr); alSourcePlay(sID); - if(checkALError() != AL_NO_ERROR) - { - writefln("Unable to start music track %s", playlist[index]); - goto errclose; - } + if(checkALError()) + fail("Unable to start music track " ~ playlist[index]); index++; return; - errclose: - if(fileHandle) cpp_closeAVFile(fileHandle); - fileHandle = null; - audioHandle = null; - alSourceStop(sID); - alDeleteSources(1, &sID); - alDeleteBuffers(bIDs.length, bIDs.ptr); - checkALError(); - sID = 0; - foreach(ref b; bIDs) b = 0; - index++; } // Start playing the jukebox @@ -289,13 +279,13 @@ struct MusicManager { alSourceStop(sID); alDeleteSources(1, &sID); - checkALError(); + checkALError("disabling music"); sID = 0; } alDeleteBuffers(bIDs.length, bIDs.ptr); - checkALError(); - foreach(ref b; bIDs) b = 0; + checkALError("deleting music buffers"); + bIDs[] = 0; musicOn = false; } @@ -326,7 +316,7 @@ struct MusicManager ALint count; alGetSourcei(sID, AL_BUFFERS_PROCESSED, &count); - if(checkALError() != AL_NO_ERROR) return false; + if(checkALError("in isPlaying()")) return false; for(int i = 0;i < count;i++) { @@ -337,7 +327,7 @@ struct MusicManager { ALint state; alGetSourcei(sID, AL_SOURCE_STATE, &state); - if(checkALError() != AL_NO_ERROR || state == AL_STOPPED) + if(checkALError() || state == AL_STOPPED) return false; } break; diff --git a/sound/sfx.d b/sound/sfx.d index d1d8d4d98..af93cd89e 100644 --- a/sound/sfx.d +++ b/sound/sfx.d @@ -119,7 +119,7 @@ struct SoundFile { alGenBuffers(1, &bID); alBufferData(bID, fmt, outData.ptr, total, rate); - if(checkALError() != AL_NO_ERROR) + if(checkALError()) { writefln("Unable to load sound %s", file); alDeleteBuffers(1, &bID); @@ -143,11 +143,11 @@ struct SoundFile SoundInstance si; si.owner = this; alGenSources(1, &si.inst); - if(checkALError() != AL_NO_ERROR || !si.inst) + if(checkALError() || !si.inst) fail("Failed to instantiate sound resource"); alSourcei(si.inst, AL_BUFFER, cast(ALint)bID); - if(checkALError() != AL_NO_ERROR) + if(checkALError()) { alDeleteSources(1, &si.inst); fail("Failed to load sound resource"); @@ -177,6 +177,7 @@ struct SoundFile struct SoundInstance { ALuint inst; + ALfloat volume; SoundFile *owner; // Return this instance to the owner @@ -190,14 +191,14 @@ struct SoundInstance void play() { alSourcePlay(inst); - checkALError(); + checkALError("playing sound instance"); } // Go buy a cookie void stop() { alSourceStop(inst); - checkALError(); + checkALError("stopping sound instance"); } // Set parameters such as max volume and range @@ -208,12 +209,13 @@ struct SoundInstance } body { - alSourcef(inst, AL_GAIN, volume); + this.volume = volume; + alSourcef(inst, AL_GAIN, 0); alSourcef(inst, AL_REFERENCE_DISTANCE, minRange); alSourcef(inst, AL_MAX_DISTANCE, maxRange); alSourcei(inst, AL_LOOPING, repeat ? AL_TRUE : AL_FALSE); alSourcePlay(inst); - checkALError(); + checkALError("setting sound parameters"); } // Set 3D position of sounds. Need to convert from app's world coords to @@ -221,7 +223,31 @@ struct SoundInstance void setPos(float x, float y, float z) { alSource3f(inst, AL_POSITION, x, z, -y); - checkALError(); + checkALError("setting sound position"); + } + + // TODO: This should probably be merged in setPos. All active sounds + // should respecify their position after the listener does, which would + // be ideal for keeping moving sounds moving while handling distance + // culling for moving and stationary sounds + void updateSound() + { + ALfloat lp[3]; + ALfloat p[3]; + ALfloat dist; + alGetSourcef(inst, AL_MAX_DISTANCE, &dist); + alGetSourcefv(inst, AL_POSITION, p.ptr); + alGetListenerfv(AL_POSITION, lp.ptr); + if(!checkALError("updating sound position")) + { + p[0] -= lp[0]; + p[1] -= lp[1]; + p[2] -= lp[2]; + if((p[0]*p[0] + p[1]*p[1] + p[2]*p[2]) > dist*dist) + alSourcef(inst, AL_GAIN, 0); + else + alSourcef(inst, AL_GAIN, volume); + } } static void setPlayerPos(float x, float y, float z, @@ -237,6 +263,6 @@ struct SoundInstance orient[5] =-upy; alListener3f(AL_POSITION, x, z, -y); alListenerfv(AL_ORIENTATION, orient.ptr); - checkALError(); + checkALError("setting player position"); } }