diff --git a/.gitignore b/.gitignore index 27b629a578c0f410ffd187c2babda05f5c9eaa56..2d32e94c782df03ab0c3fdf58e0e07d1b43a32fa 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.bak *.diff *.orig +*.patch *.pyc *.rej *.swp diff --git a/autobuild.xml b/autobuild.xml index 513013700e51516b2f904c612ecac9d52f79731e..0e356f1a0c91508c3ad899d09f52a6033fa1d3c8 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -729,38 +729,28 @@ <key>version</key> <string>2.1.1.500375</string> </map> - <key>fmodex</key> + <key>fmodstudio</key> <map> <key>copyright</key> - <string>COPYRIGHT 2014 FIRELIGHT TECHNOLOGIES PTY LTD. ALL RIGHTS RESERVED</string> + <string>FMOD Studio by Firelight Technologies Pty Ltd.</string> + <key>description</key> + <string>FMOD Studio API</string> <key>license</key> - <string>fmodex</string> + <string>fmod</string> <key>license_file</key> - <string>LICENSES/fmodex.txt</string> + <string>LICENSES/fmodstudio.txt</string> <key>name</key> - <string>fmodex</string> + <string>fmodstudio</string> <key>platforms</key> <map> - <key>darwin</key> - <map> - <key>archive</key> - <map> - <key>hash</key> - <string>ed0d8767652aecd65a7fef3e28645bad</string> - <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/fmodex_3p-update-fmodex/rev/297261/arch/Darwin/installer/fmodex-4.44.31.297261-darwin-297261.tar.bz2</string> - </map> - <key>name</key> - <string>darwin</string> - </map> <key>darwin64</key> <map> <key>archive</key> <map> <key>hash</key> - <string>cba1feed7f6bb671d791a517fddf205a</string> + <string>dc4c9122de8bf77f34cfc8227d10a272</string> <key>url</key> - <string>https://downloads.catznip.com/packages/fmodex-44461-darwin-201601300040-r23.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59038/554626/fmodstudio-2.00.07.541681-darwin64-541681.tar.bz2</string> </map> <key>name</key> <string>darwin64</string> @@ -770,9 +760,9 @@ <key>archive</key> <map> <key>hash</key> - <string>b847ec838da1ad1dd646df9d74e9b395</string> + <string>c491bdc1690f3d920c66be509ccc6ef2</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-fmodex/rev/314207/arch/Linux/installer/fmodex-4.44.61.314207-linux-314207.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59039/554632/fmodstudio-2.00.07.541681-linux-541681.tar.bz2</string> </map> <key>name</key> <string>linux</string> @@ -782,9 +772,9 @@ <key>archive</key> <map> <key>hash</key> - <string>89a75d8719f7b2cbe1e54cd8407bb992</string> + <string>ae75cdb1cc9da824c9e270bf97bfdd6c</string> <key>url</key> - <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/1544/3476/fmodex-4.44.64.501533-linux64-501533.tar.bz2</string> + <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54589/506866/fmodstudio-2.00.07.538806-linux64-538806.tar.bz2</string> </map> <key>name</key> <string>linux64</string> @@ -794,9 +784,9 @@ <key>archive</key> <map> <key>hash</key> - <string>2038da4ab71da8dc086738007c0acdd3</string> + <string>fbd53fad464526e9331332fc0b3fee0b</string> <key>url</key> - <string>http://viewer.catznip.com/downloads/packages/fmodex-4.44.61-windows-171261212.tar.bz2</string> + <string>https://downloads.catznip.com/packages/fmodstudio-2.00.09-windows-201512304.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -806,16 +796,16 @@ <key>archive</key> <map> <key>hash</key> - <string>b4b73cd64bfd72e7ae84aad429d69cf6</string> + <string>af7446fdf8d39e114feae354878ec54b</string> <key>url</key> - <string>http://viewer.catznip.com/downloads/packages/fmodex-4.44.61-windows64-171261211.tar.bz2</string> + <string>https://downloads.catznip.com/packages/fmodstudio-2.00.09-windows64-201512258.tar.bz2</string> </map> <key>name</key> <string>windows64</string> </map> </map> <key>version</key> - <string>4.44.64.501533</string> + <string>2.00.07.541681</string> </map> <key>fontconfig</key> <map> diff --git a/doc/contributions.txt b/doc/contributions.txt index 2153e108882ae9445823a59db37ec683c5f5d388..7bbbf6430a52d84a7c080bc372caf750f71742e3 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1517,6 +1517,7 @@ Whirly Fizzle STORM-1930 BUG-6659 STORM-2078 + BUG-17349 Whoops Babii VWR-631 VWR-1640 diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 84e1c5d6fdee0b417b144d9b314a47817eb8cbac..3a14bf522f0732342bbed80eeac1f059cbeaae0b 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -28,7 +28,6 @@ set(cmake_SOURCE_FILES FindAPR.cmake FindAutobuild.cmake FindBerkeleyDB.cmake - FindFMODEX.cmake FindGLH.cmake FindGoogleBreakpad.cmake FindHUNSPELL.cmake @@ -39,7 +38,7 @@ set(cmake_SOURCE_FILES FindURIPARSER.cmake FindXmlRpcEpi.cmake FindZLIB.cmake - FMODEX.cmake + FMODSTUDIO.cmake FreeType.cmake GLEXT.cmake GLH.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c73a1fdb47b3e78f5de6bfe751d0d76a8b73eb06..82cd5d62e85931060f6bbcc903aa58ccdc6f984b 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -62,14 +62,10 @@ if(WINDOWS) endif(ADDRESS_SIZE EQUAL 32) endif (BUGSPLAT_DB) - if (FMODEX) - - if(ADDRESS_SIZE EQUAL 32) - set(release_files ${release_files} fmodex.dll) - else(ADDRESS_SIZE EQUAL 32) - set(release_files ${release_files} fmodex64.dll) - endif(ADDRESS_SIZE EQUAL 32) - endif (FMODEX) + if (FMODSTUDIO) + set(debug_files ${debug_files} fmodL.dll) + set(release_files ${release_files} fmod.dll) + endif (FMODSTUDIO) #******************************* # Copy MS C runtime dlls, required for packaging. @@ -192,10 +188,10 @@ elseif(DARWIN) libnghttp2.14.14.0.dylib ) - if (FMODEX) - set(debug_files ${debug_files} libfmodexL.dylib) - set(release_files ${release_files} libfmodex.dylib) - endif (FMODEX) + if (FMODSTUDIO) + set(debug_files ${debug_files} libfmodL.dylib) + set(release_files ${release_files} libfmod.dylib) + endif (FMODSTUDIO) elseif(LINUX) # linux is weird, multiple side by side configurations aren't supported @@ -242,10 +238,10 @@ elseif(LINUX) libfontconfig.so.1 ) - if (FMODEX) - set(debug_files ${debug_files} "libfmodexL.so") - set(release_files ${release_files} "libfmodex.so") - endif (FMODEX) + if (FMODSTUDIO) + set(debug_files ${debug_files} "libfmodL.so") + set(release_files ${release_files} "libfmod.so") + endif (FMODSTUDIO) else(WINDOWS) message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake deleted file mode 100644 index 9753412de7b63f85d4f0c6c3837307e6ddbcade5..0000000000000000000000000000000000000000 --- a/indra/cmake/FMODEX.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# -*- cmake -*- - -# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON -# When building using proprietary binaries though (i.e. having access to LL private servers), -# we always build with FMODEX. -# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether -# they are using USESYSTEMLIBS or not. -if (INSTALL_PROPRIETARY) - set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.") -endif (INSTALL_PROPRIETARY) - -if (FMODEX) - if (USESYSTEMLIBS) - # In that case, we use the version of the library installed on the system - set(FMODEX_FIND_REQUIRED ON) - include(FindFMODEX) - else (USESYSTEMLIBS) - if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) - # If the path have been specified in the arguments, use that - set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) - MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}") - else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) - # If not, we're going to try to get the package listed in autobuild.xml - # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) - # as accessing the private LL location will fail if you don't have the credential - include(Prebuilt) - use_prebuilt_binary(fmodex) - if (WINDOWS) - if (ADDRESS_SIZE EQUAL 32) - set(FMODEX_LIBRARY - debug fmodexL_vc - optimized fmodex_vc) - else (ADDRESS_SIZE EQUAL 64) - set(FMODEX_LIBRARY - debug fmodexL64_vc - optimized fmodex64_vc) - endif (ADDRESS_SIZE EQUAL 32) - elseif (DARWIN) - set(FMODEX_LIBRARY - debug fmodexL - optimized fmodex) - elseif (LINUX) - set(FMODEX_LIBRARY - debug fmodexL - optimized fmodex) - endif (WINDOWS) - set(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) - set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex) - endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) - endif (USESYSTEMLIBS) -endif (FMODEX) - diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake new file mode 100644 index 0000000000000000000000000000000000000000..8840354ac6c3d53d7d46040f65019fcc7903d66d --- /dev/null +++ b/indra/cmake/FMODSTUDIO.cmake @@ -0,0 +1,38 @@ +# -*- cmake -*- + +# FMODSTUDIO can be set when launching the make using the argument -DFMODSTUDIO:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with FMODSTUDIO. +if (INSTALL_PROPRIETARY) + set(FMODSTUDIO ON CACHE BOOL "Using FMODSTUDIO sound library.") +endif (INSTALL_PROPRIETARY) + +if (FMODSTUDIO) + if (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) + # If the path have been specified in the arguments, use that + set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY}) + else (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) + # If not, we're going to try to get the package listed in autobuild.xml + # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) + # as accessing the private LL location will fail if you don't have the credential + include(Prebuilt) + use_prebuilt_binary(fmodstudio) + if (WINDOWS) + set(FMODSTUDIO_LIBRARY + debug fmodL_vc + optimized fmod_vc) + elseif (DARWIN) + #despite files being called libfmod.dylib, we are searching for fmod + set(FMODSTUDIO_LIBRARY + debug fmodL + optimized fmod) + elseif (LINUX) + set(FMODSTUDIO_LIBRARY + debug fmodL + optimized fmod) + endif (WINDOWS) + set(FMODSTUDIO_LIBRARIES ${FMODSTUDIO_LIBRARY}) + set(FMODSTUDIO_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodstudio) + endif (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) +endif (FMODSTUDIO) + diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake deleted file mode 100644 index b621727c0ea490c8d55c7d89f243813ab698bda6..0000000000000000000000000000000000000000 --- a/indra/cmake/FindFMODEX.cmake +++ /dev/null @@ -1,65 +0,0 @@ -# -*- cmake -*- - -# - Find FMODEX -# Find the FMODEX includes and library -# This module defines -# FMODEX_INCLUDE_DIR, where to find fmod.h and fmod_errors.h -# FMODEX_LIBRARIES, the libraries needed to use FMODEX. -# FMODEX, If false, do not try to use FMODEX. -# also defined, but not for general use are -# FMODEX_LIBRARY, where to find the FMODEX library. - -FIND_PATH(FMODEX_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod) - -SET(FMODEX_NAMES ${FMODEX_NAMES} fmodex fmodvc fmodexL_vc) -FIND_LIBRARY(FMODEX_LIBRARY - NAMES ${FMODEX_NAMES} - PATH_SUFFIXES fmodex - ) - -IF (FMODEX_SDK_DIR OR WINDOWS) - if(WINDOWS) - set(FMODEX_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODEX") - STRING(REGEX REPLACE "\\\\" "/" FMODEX_SDK_DIR ${FMODEX_SDK_DIR}) - endif(WINDOWS) - find_library(FMODEX_LIBRARY - fmodex_vc fmodexL_vc - PATHS - ${FMODEX_SDK_DIR}/api/lib - ${FMODEX_SDK_DIR}/api - ${FMODEX_SDK_DIR} - ) - find_path(FMODEX_INCLUDE_DIR fmod.h - ${FMODEX_SDK_DIR}/api/inc - ${FMODEX_SDK_DIR}/api - ${FMODEX_SDK_DIR} - ) - find_path(FMODEX_INCLUDE_DIR fmod.h - ${FMODEX_SDK_DIR}/api/inc - ${FMODEX_SDK_DIR}/api - ${FMODEX_SDK_DIR} - ) - IF (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) - SET(FMODEX_LIBRARIES ${FMODEX_LIBRARY}) - SET(FMODEX_FOUND "YES") - endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR) -ENDIF (FMODEX_SDK_DIR OR WINDOWS) - -IF (FMODEX_FOUND) - IF (NOT FMODEX_FIND_QUIETLY) - MESSAGE(STATUS "Found FMODEX: ${FMODEX_LIBRARIES}") - ENDIF (NOT FMODEX_FIND_QUIETLY) -ELSE (FMODEX_FOUND) - IF (FMODEX_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find FMODEX library") - ENDIF (FMODEX_FIND_REQUIRED) -ENDIF (FMODEX_FOUND) - -# Deprecated declarations. -SET (NATIVE_FMODEX_INCLUDE_PATH ${FMODEX_INCLUDE_DIR} ) -GET_FILENAME_COMPONENT (NATIVE_FMODEX_LIB_PATH ${FMODEX_LIBRARY} PATH) - -MARK_AS_ADVANCED( - FMODEX_LIBRARY - FMODEX_INCLUDE_DIR - ) diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index e943dd5d5ccd059100c1ad41507a3f5d377b73d1..8b628a058e0b74b7d8d603185f5a9a3ce76a675e 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -4,7 +4,7 @@ project(llaudio) include(00-Common) include(LLAudio) -include(FMODEX) +include(FMODSTUDIO) include(OPENAL) include(LLCommon) include(LLMath) @@ -42,22 +42,22 @@ set(llaudio_HEADER_FILES llwindgen.h ) -if (FMODEX) +if (FMODSTUDIO) include_directories( - ${FMODEX_INCLUDE_DIR} + ${FMODSTUDIO_INCLUDE_DIR} ) list(APPEND llaudio_SOURCE_FILES - llaudioengine_fmodex.cpp - lllistener_fmodex.cpp - llstreamingaudio_fmodex.cpp + llaudioengine_fmodstudio.cpp + lllistener_fmodstudio.cpp + llstreamingaudio_fmodstudio.cpp ) list(APPEND llaudio_HEADER_FILES - llaudioengine_fmodex.h - lllistener_fmodex.h - llstreamingaudio_fmodex.h + llaudioengine_fmodstudio.h + lllistener_fmodstudio.h + llstreamingaudio_fmodstudio.h ) -endif (FMODEX) +endif (FMODSTUDIO) if (OPENAL) list(APPEND llaudio_SOURCE_FILES diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index f49028aad51955fbc5a606cda3ebcf9f2985e43e..1d447f32ae77ee4f0eb508ff2091e751f4839861 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -111,7 +111,7 @@ void LLAudioEngine::setDefaults() } -bool LLAudioEngine::init(const S32 num_channels, void* userdata) +bool LLAudioEngine::init(const S32 num_channels, void* userdata, const std::string &app_title) { setDefaults(); diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index f1e1b4e308c79a440115011ed64a53c2dfe0343e..97674f15f7a37494baf8da9ef8030a1d389acfb0 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -99,7 +99,7 @@ class LLAudioEngine virtual ~LLAudioEngine(); // initialization/startup/shutdown - virtual bool init(const S32 num_channels, void *userdata); + virtual bool init(const S32 num_channels, void *userdata, const std::string &app_title); virtual std::string getDriverName(bool verbose) = 0; virtual void shutdown(); diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp deleted file mode 100644 index 7e65a05e48ab561f7c65b9cdd406571c5f2bba42..0000000000000000000000000000000000000000 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ /dev/null @@ -1,767 +0,0 @@ -/** - * @file audioengine_fmodex.cpp - * @brief Implementation of LLAudioEngine class abstracting the audio - * support as a FMODEX implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2014, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llstreamingaudio.h" -#include "llstreamingaudio_fmodex.h" - -#include "llaudioengine_fmodex.h" -#include "lllistener_fmodex.h" - -#include "llerror.h" -#include "llmath.h" -#include "llrand.h" - -#include "fmod.hpp" -#include "fmod_errors.h" -#include "lldir.h" -#include "llapr.h" - -#include "sound_ids.h" - -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); - -FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; - -LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler) -{ - mInited = false; - mWindGen = NULL; - mWindDSP = NULL; - mSystem = NULL; - mEnableProfiler = enable_profiler; - mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); -} - - -LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX() -{ - delete mWindDSPDesc; -} - - -inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) -{ - if(result == FMOD_OK) - return false; - LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - return true; -} - -void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - if(type & FMOD_MEMORY_STREAM_DECODE) - { - LL_INFOS() << "Decode buffer size: " << size << LL_ENDL; - } - else if(type & FMOD_MEMORY_STREAM_FILE) - { - LL_INFOS() << "Strean buffer size: " << size << LL_ENDL; - } - return new char[size]; -} -void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - memset(ptr,0,size); - return ptr; -} -void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) -{ - delete[] (char*)ptr; -} - -bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) -{ - U32 version; - FMOD_RESULT result; - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; - - //result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE); - //if(Check_FMOD_Error(result, "FMOD::Memory_Initialize")) - // return false; - - // turn off non-error log spam to fmod.log (TODO: why do we even have an fmod.log if we don't link against log lib?) - FMOD::Debug_SetLevel(FMOD_DEBUG_LEVEL_ERROR); - - result = FMOD::System_Create(&mSystem); - if(Check_FMOD_Error(result, "FMOD::System_Create")) - return false; - - //will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer. - LLAudioEngine::init(num_channels, userdata); - - result = mSystem->getVersion(&version); - Check_FMOD_Error(result, "FMOD::System::getVersion"); - - if (version < FMOD_VERSION) - { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version - << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; - } - - result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); - Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); - - // In this case, all sounds, PLUS wind and stream will be software. - result = mSystem->setSoftwareChannels(num_channels + 2); - Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); - - U32 fmod_flags = FMOD_INIT_NORMAL; - if(mEnableProfiler) - { - fmod_flags |= FMOD_INIT_ENABLE_PROFILE; - mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]); - mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]); - mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]); - mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]); - } - -#if LL_LINUX - bool audio_ok = false; - - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; - if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; - if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK && - (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "OSS audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; - return false; - } - - // We're interested in logging which output method we - // ended up with, for QA purposes. - FMOD_OUTPUTTYPE output_type; - mSystem->getOutput(&output_type); - switch (output_type) - { - case FMOD_OUTPUTTYPE_NOSOUND: - LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_PULSEAUDIO: - LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_ALSA: - LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_OSS: - LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break; - default: - LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; - }; -#else // LL_LINUX - - // initialize the FMOD engine - result = mSystem->init( num_channels + 2, fmod_flags, 0); - if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) - { - /* - Ok, the speaker mode selected isn't supported by this soundcard. Switch it - back to stereo... - */ - result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO); - Check_FMOD_Error(result,"Error falling back to stereo mode"); - /* - ... and re-init. - */ - result = mSystem->init( num_channels + 2, fmod_flags, 0); - } - if(Check_FMOD_Error(result, "Error initializing FMOD Ex")) - return false; -#endif - - // set up our favourite FMOD-native streaming audio implementation if none has already been added - if (!getStreamingAudioImpl()) // no existing implementation added - setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); - - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL; - - int r_numbuffers, r_samplerate, r_channels, r_bits; - unsigned int r_bufferlength; - mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; - - mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits); - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_channels=" << r_channels << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_bits =" << r_bits << LL_ENDL; - - char r_name[512]; - mSystem->getDriverInfo(0, r_name, 511, 0); - r_name[511] = '\0'; - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): r_name=\"" << r_name << "\"" << LL_ENDL; - - int latency = 100; // optimistic default - i suspect if sample rate is 0, everything breaks. - if ( r_samplerate != 0 ) - latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): latency=" << latency << "ms" << LL_ENDL; - - mInited = true; - - LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): initialization complete." << LL_ENDL; - - return true; -} - - -std::string LLAudioEngine_FMODEX::getDriverName(bool verbose) -{ - llassert_always(mSystem); - if (verbose) - { - U32 version; - if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) - { - return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); - } - } - return "FMODEx"; -} - - -void LLAudioEngine_FMODEX::allocateListener(void) -{ - mListenerp = (LLListener *) new LLListener_FMODEX(mSystem); - if (!mListenerp) - { - LL_WARNS() << "Listener creation failed" << LL_ENDL; - } -} - - -void LLAudioEngine_FMODEX::shutdown() -{ - stopInternetStream(); - - LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL; - LLAudioEngine::shutdown(); - - LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL; - if ( mSystem ) // speculative fix for MAINT-2657 - { - mSystem->close(); - mSystem->release(); - } - LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL; - - delete mListenerp; - mListenerp = NULL; -} - - -LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer() -{ - return new LLAudioBufferFMODEX(mSystem); -} - - -LLAudioChannel * LLAudioEngine_FMODEX::createChannel() -{ - return new LLAudioChannelFMODEX(mSystem); -} - -bool LLAudioEngine_FMODEX::initWind() -{ - mNextWindUpdate = 0.0; - - if (!mWindDSP) - { - memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero - strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); - mWindDSPDesc->channels = 2; - mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads - if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP")) - return false; - - if (mWindGen) - delete mWindGen; - - float frequency = 44100; - mWindDSP->getDefaults(&frequency,0,0,0); - mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); - mWindDSP->setUserData((void*)mWindGen); - } - - // *TODO: Should this guard against multiple plays? - if (mWindDSP) - { - mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0); - return true; - } - return false; -} - - -void LLAudioEngine_FMODEX::cleanupWind() -{ - if (mWindDSP) - { - mWindDSP->remove(); - mWindDSP->release(); - mWindDSP = NULL; - } - - delete mWindGen; - mWindGen = NULL; -} - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) -{ - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; - - if (!mEnableWind) - { - return; - } - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards - - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - - // cerr << "Wind update" << endl; - - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMODEX::setInternalGain(F32 gain) -{ - if (!mInited) - { - return; - } - - gain = llclamp( gain, 0.0f, 1.0f ); - - FMOD::ChannelGroup *master_group; - mSystem->getMasterChannelGroup(&master_group); - - master_group->setVolume(gain); - - LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); - if ( saimpl ) - { - // fmod likes its streaming audio channel gain re-asserted after - // master volume change. - saimpl->setGain(saimpl->getGain()); - } -} - -// -// LLAudioChannelFMODEX implementation -// - -LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) -{ -} - - -LLAudioChannelFMODEX::~LLAudioChannelFMODEX() -{ - cleanup(); -} - -bool LLAudioChannelFMODEX::updateBuffer() -{ - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means that we need to actually - // set up the channel for a different buffer. - - LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer(); - - // Grab the FMOD sample associated with the buffer - FMOD::Sound *soundp = bufferp->getSound(); - if (!soundp) - { - // This is bad, there should ALWAYS be a sound associated with a legit - // buffer. - LL_ERRS() << "No FMOD sound!" << LL_ENDL; - return false; - } - - - // Actually play the sound. Start it off paused so we can do all the necessary - // setup. - if(!mChannelp) - { - FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); - Check_FMOD_Error(result, "FMOD::System::playSound"); - } - - //LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL; - } - - // If we have a source for the channel, we need to update its gain. - if (mCurrentSourcep) - { - // SJB: warnings can spam and hurt framerate, disabling - //FMOD_RESULT result; - - mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); - //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); - - mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); - /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) - { - S32 index; - mChannelp->getIndex(&index); - LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() - << " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL; - }*/ - } - - return true; -} - - -void LLAudioChannelFMODEX::update3DPosition() -{ - if (!mChannelp) - { - // We're not actually a live channel (i.e., we're not playing back anything) - return; - } - - LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentBufferp; - if (!bufferp) - { - // We don't have a buffer associated with us (should really have been picked up - // by the above if. - return; - } - - if (mCurrentSourcep->isAmbient()) - { - // Ambient sound, don't need to do any positional updates. - set3DMode(false); - } - else - { - // Localized sound. Update the position and velocity of the sound. - set3DMode(true); - - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); - Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); - } -} - - -void LLAudioChannelFMODEX::updateLoop() -{ - if (!mChannelp) - { - // May want to clear up the loop/sample counters. - return; - } - - // - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - U32 cur_pos; - mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES); - - if (cur_pos < (U32)mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; -} - - -void LLAudioChannelFMODEX::cleanup() -{ - if (!mChannelp) - { - //LL_INFOS() << "Aborting cleanup with no channel handle." << LL_ENDL; - return; - } - - //LL_INFOS() << "Cleaning up channel: " << mChannelID << LL_ENDL; - Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); - - mCurrentBufferp = NULL; - mChannelp = NULL; -} - - -void LLAudioChannelFMODEX::play() -{ - if (!mChannelp) - { - LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; - return; - } - - Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); - - getSource()->setPlayedOnce(true); - - if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) - mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]); -} - - -void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp) -{ - LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp; - if (!(fmod_channelp->mChannelp && mChannelp)) - { - // Don't have channels allocated to both the master and the slave - return; - } - - U32 cur_pos; - if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) - return; - - cur_pos %= mCurrentBufferp->getLength(); - - // Try to match the position of our sync master - Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position"); - - // Start us playing - play(); -} - - -bool LLAudioChannelFMODEX::isPlaying() -{ - if (!mChannelp) - { - return false; - } - - bool paused, playing; - mChannelp->getPaused(&paused); - mChannelp->isPlaying(&playing); - return !paused && playing; -} - - -// -// LLAudioChannelFMODEX implementation -// - - -LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL) -{ -} - - -LLAudioBufferFMODEX::~LLAudioBufferFMODEX() -{ - if(mSoundp) - { - mSoundp->release(); - mSoundp = NULL; - } -} - - -bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) -{ - // Try to open a wav file from disk. This will eventually go away, as we don't - // really want to block doing this. - if (filename.empty()) - { - // invalid filename, abort. - return false; - } - - if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) - { - // File not found, abort. - return false; - } - - if (mSoundp) - { - // If there's already something loaded in this buffer, clean it up. - mSoundp->release(); - mSoundp = NULL; - } - - FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE; - FMOD_CREATESOUNDEXINFO exinfo; - memset(&exinfo,0,sizeof(exinfo)); - exinfo.cbsize = sizeof(exinfo); - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. - // Load up the wav file into an fmod sample -#if LL_WINDOWS - FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp); -#else - FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); -#endif - - if (result != FMOD_OK) - { - // We failed to load the file for some reason. - LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; - - // - // If we EVER want to load wav files provided by end users, we need - // to rethink this! - // - // file is probably corrupt - remove it. - LLFile::remove(filename); - return false; - } - - // Everything went well, return true - return true; -} - - -U32 LLAudioBufferFMODEX::getLength() -{ - if (!mSoundp) - { - return 0; - } - - U32 length; - mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); - return length; -} - - -void LLAudioChannelFMODEX::set3DMode(bool use3d) -{ - FMOD_MODE current_mode; - if(mChannelp->getMode(¤t_mode) != FMOD_OK) - return; - FMOD_MODE new_mode = current_mode; - new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); - new_mode |= use3d ? FMOD_3D : FMOD_2D; - - if(current_mode != new_mode) - { - mChannelp->setMode(new_mode); - } -} - -// *NOTE: This is almost certainly being called on the mixer thread, -// not the main thread. May have implications for callees or audio -// engine shutdown. - -FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels) -{ - // originalbuffer = fmod's original mixbuffer. - // newbuffer = the buffer passed from the previous DSP unit. - // length = length in samples at this mix time. - // userdata = user parameter passed through in FSOUND_DSP_Create. - - LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen; - FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; - - thisdsp->getUserData((void **)&windgen); - S32 channels, configwidth, configheight; - thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight); - - windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length); - - return FMOD_OK; -} diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70b3a0847388a0b7639e1501a62a8bb8980ad16d --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -0,0 +1,753 @@ +/** + * @file audioengine_fmodstudio.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llstreamingaudio.h" +#include "llstreamingaudio_fmodstudio.h" + +#include "llaudioengine_fmodstudio.h" +#include "lllistener_fmodstudio.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); + +FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; + +LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler) +: mInited(false), + mWindGen(NULL), + mWindDSP(NULL), + mSystem(NULL), + mEnableProfiler(enable_profiler), + mWindDSPDesc(NULL) +{ +} + + +LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO() +{ + // mWindDSPDesc, mWindGen and mWindDSP get cleaned up on cleanupWind in LLAudioEngine::shutdown() + // mSystem gets cleaned up at shutdown() +} + + +static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) +{ + if (result == FMOD_OK) + return false; + LL_DEBUGS("FMOD") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; + return true; +} + +bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata, const std::string &app_title) +{ + U32 version; + FMOD_RESULT result; + + LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; + + result = FMOD::System_Create(&mSystem); + if (Check_FMOD_Error(result, "FMOD::System_Create")) + return false; + + //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. + LLAudioEngine::init(num_channels, userdata, app_title); + + result = mSystem->getVersion(&version); + Check_FMOD_Error(result, "FMOD::System::getVersion"); + + if (version < FMOD_VERSION) + { + LL_WARNS("AppInit") << "FMOD Studio version mismatch, actual: " << version + << " expected:" << FMOD_VERSION << LL_ENDL; + } + + // In this case, all sounds, PLUS wind and stream will be software. + result = mSystem->setSoftwareChannels(num_channels + 2); + Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels"); + + FMOD_ADVANCEDSETTINGS settings; + memset(&settings, 0, sizeof(settings)); + settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); + settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR; + + result = mSystem->setAdvancedSettings(&settings); + Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings"); + + // FMOD_INIT_THREAD_UNSAFE Disables thread safety for API calls. + // Only use this if FMOD is being called from a single thread, and if Studio API is not being used. + U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE; + if (mEnableProfiler) + { + fmod_flags |= FMOD_INIT_PROFILE_ENABLE; + } + +#if LL_LINUX + bool audio_ok = false; + + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_PULSEAUDIO"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; + if (mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, const_cast<char*>(app_title.c_str()))) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_ALSA"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if (mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && + (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; + return false; + } + + // We're interested in logging which output method we + // ended up with, for QA purposes. + FMOD_OUTPUTTYPE output_type; + mSystem->getOutput(&output_type); + switch (output_type) + { + case FMOD_OUTPUTTYPE_NOSOUND: + LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_PULSEAUDIO: + LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_ALSA: + LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + default: + LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; + }; +#else // LL_LINUX + + // initialize the FMOD engine + // number of channel in this case looks to be identiacal to number of max simultaneously + // playing objects and we can set practically any number + result = mSystem->init(num_channels + 2, fmod_flags, 0); + if (Check_FMOD_Error(result, "Error initializing FMOD Studio with default settins, retrying with other format")) + { + result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0/*- ignore*/); + if (Check_FMOD_Error(result, "Error setting sotware format. Can't init.")) + { + return false; + } + result = mSystem->init(num_channels + 2, fmod_flags, 0); + } + if (Check_FMOD_Error(result, "Error initializing FMOD Studio")) + { + // If it fails here and (result == FMOD_ERR_OUTPUT_CREATEBUFFER), + // we can retry with other settings + return false; + } +#endif + + // set up our favourite FMOD-native streaming audio implementation if none has already been added + if (!getStreamingAudioImpl()) // no existing implementation added + setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem)); + + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; + + int r_numbuffers, r_samplerate, r_channels; + unsigned int r_bufferlength; + char r_name[512]; + int latency = 100; + mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; + + mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels); + r_name[511] = '\0'; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL; + + if (r_samplerate != 0) + latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL; + + mInited = true; + + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL; + + return true; +} + + +std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) +{ + llassert_always(mSystem); + if (verbose) + { + U32 version; + if (!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) + { + return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); + } + } + return "FMOD STUDIO"; +} + + +void LLAudioEngine_FMODSTUDIO::allocateListener(void) +{ + mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem); + if (!mListenerp) + { + LL_WARNS("FMOD") << "Listener creation failed" << LL_ENDL; + } +} + + +void LLAudioEngine_FMODSTUDIO::shutdown() +{ + stopInternetStream(); + + LL_INFOS("FMOD") << "About to LLAudioEngine::shutdown()" << LL_ENDL; + LLAudioEngine::shutdown(); + + LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL; + if (mSystem) + { + mSystem->close(); + mSystem->release(); + } + LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL; + + delete mListenerp; + mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer() +{ + return new LLAudioBufferFMODSTUDIO(mSystem); +} + + +LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel() +{ + return new LLAudioChannelFMODSTUDIO(mSystem); +} + +bool LLAudioEngine_FMODSTUDIO::initWind() +{ + mNextWindUpdate = 0.0; + + if (!mWindDSPDesc) + { + mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); + } + + if (!mWindDSP) + { + memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero + strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); + mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; + mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads + if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP")) + return false; + + if (mWindGen) + delete mWindGen; + + int frequency = 44100; + + FMOD_SPEAKERMODE mode; + if (Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat")) + { + cleanupWind(); + return false; + } + + mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); + + if (Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData")) + { + cleanupWind(); + return false; + } + if (Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat")) + { + cleanupWind(); + return false; + } + } + + // *TODO: Should this guard against multiple plays? + if (Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP")) + { + cleanupWind(); + return false; + } + return true; +} + + +void LLAudioEngine_FMODSTUDIO::cleanupWind() +{ + if (mWindDSP) + { + FMOD::ChannelGroup* master_group = NULL; + if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") + && master_group) + { + master_group->removeDSP(mWindDSP); + } + mWindDSP->release(); + mWindDSP = NULL; + } + + delete mWindDSPDesc; + mWindDSPDesc = NULL; + + delete mWindGen; + mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODSTUDIO::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) +{ + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; + + if (!mEnableWind) + { + return; + } + + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { + + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards + + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + // cerr << "Wind update" << endl; + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch, 2.5*(mapWindVecToGain(wind_vec) + 1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + } +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODSTUDIO::setInternalGain(F32 gain) +{ + if (!mInited) + { + return; + } + + gain = llclamp(gain, 0.0f, 1.0f); + + FMOD::ChannelGroup* master_group = NULL; + if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") + && master_group) + { + master_group->setVolume(gain); + } + + LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); + if (saimpl) + { + // fmod likes its streaming audio channel gain re-asserted after + // master volume change. + saimpl->setGain(saimpl->getGain()); + } +} + +// +// LLAudioChannelFMODSTUDIO implementation +// + +LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO() +{ + cleanup(); +} + +bool LLAudioChannelFMODSTUDIO::updateBuffer() +{ + if (!mCurrentSourcep) + { + // This channel isn't associated with any source, nothing + // to be updated + return false; + } + + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the channel for a different buffer. + + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentSourcep->getCurrentBuffer(); + + // Grab the FMOD sample associated with the buffer + FMOD::Sound *soundp = bufferp->getSound(); + if (!soundp) + { + // This is bad, there should ALWAYS be a sound associated with a legit + // buffer. + LL_ERRS() << "No FMOD sound!" << LL_ENDL; + return false; + } + + + // Actually play the sound. Start it off paused so we can do all the necessary + // setup. + if (!mChannelp) + { + FMOD_RESULT result = getSystem()->playSound(soundp, NULL /*free channel?*/, true, &mChannelp); + Check_FMOD_Error(result, "FMOD::System::playSound"); + } + + // Setting up channel mChannelID + } + + // If we have a source for the channel, we need to update its gain. + if (mCurrentSourcep) + { + // SJB: warnings can spam and hurt framerate, disabling + //FMOD_RESULT result; + + mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); + //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + + mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) + { + S32 index; + mChannelp->getIndex(&index); + LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() + << " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL; + }*/ + } + + return true; +} + + +void LLAudioChannelFMODSTUDIO::update3DPosition() +{ + if (!mChannelp) + { + // We're not actually a live channel (i.e., we're not playing back anything) + return; + } + + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentBufferp; + if (!bufferp) + { + // We don't have a buffer associated with us (should really have been picked up + // by the above if. + return; + } + + if (mCurrentSourcep->isAmbient()) + { + // Ambient sound, don't need to do any positional updates. + set3DMode(false); + } + else + { + // Localized sound. Update the position and velocity of the sound. + set3DMode(true); + + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); + Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); + } +} + + +void LLAudioChannelFMODSTUDIO::updateLoop() +{ + if (!mChannelp) + { + // May want to clear up the loop/sample counters. + return; + } + + // + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + U32 cur_pos; + mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES); + + if (cur_pos < (U32)mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMODSTUDIO::cleanup() +{ + if (!mChannelp) + { + // Aborting cleanup with no channel handle. + return; + } + + //Cleaning up channel mChannelID + Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop"); + + mCurrentBufferp = NULL; + mChannelp = NULL; +} + + +void LLAudioChannelFMODSTUDIO::play() +{ + if (!mChannelp) + { + LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; + return; + } + + Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + + getSource()->setPlayedOnce(true); + + if (LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]) + mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]); +} + + +void LLAudioChannelFMODSTUDIO::playSynced(LLAudioChannel *channelp) +{ + LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)channelp; + if (!(fmod_channelp->mChannelp && mChannelp)) + { + // Don't have channels allocated to both the master and the slave + return; + } + + U32 cur_pos; + if (Check_FMOD_Error(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) + return; + + cur_pos %= mCurrentBufferp->getLength(); + + // Try to match the position of our sync master + Check_FMOD_Error(mChannelp->setPosition(cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to set current position"); + + // Start us playing + play(); +} + + +bool LLAudioChannelFMODSTUDIO::isPlaying() +{ + if (!mChannelp) + { + return false; + } + + bool paused, playing; + mChannelp->getPaused(&paused); + mChannelp->isPlaying(&playing); + return !paused && playing; +} + + +// +// LLAudioChannelFMODSTUDIO implementation +// + + +LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +{ +} + + +LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO() +{ + if (mSoundp) + { + mSoundp->release(); + mSoundp = NULL; + } +} + + +bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) +{ + // Try to open a wav file from disk. This will eventually go away, as we don't + // really want to block doing this. + if (filename.empty()) + { + // invalid filename, abort. + return false; + } + + if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) + { + // File not found, abort. + return false; + } + + if (mSoundp) + { + // If there's already something loaded in this buffer, clean it up. + mSoundp->release(); + mSoundp = NULL; + } + + FMOD_MODE base_mode = FMOD_LOOP_NORMAL; + FMOD_CREATESOUNDEXINFO exinfo; + memset(&exinfo, 0, sizeof(exinfo)); + exinfo.cbsize = sizeof(exinfo); + exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. + // Load up the wav file into an fmod sample (since 1.05 fmod studio expects everything in UTF-8) + FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); + + if (result != FMOD_OK) + { + // We failed to load the file for some reason. + LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; + + // + // If we EVER want to load wav files provided by end users, we need + // to rethink this! + // + // file is probably corrupt - remove it. + LLFile::remove(filename); + return false; + } + + // Everything went well, return true + return true; +} + + +U32 LLAudioBufferFMODSTUDIO::getLength() +{ + if (!mSoundp) + { + return 0; + } + + U32 length; + mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); + return length; +} + + +void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d) +{ + FMOD_MODE current_mode; + if (mChannelp->getMode(¤t_mode) != FMOD_OK) + return; + FMOD_MODE new_mode = current_mode; + new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); + new_mode |= use3d ? FMOD_3D : FMOD_2D; + + if (current_mode != new_mode) + { + mChannelp->setMode(new_mode); + } +} + +// *NOTE: This is almost certainly being called on the mixer thread, +// not the main thread. May have implications for callees or audio +// engine shutdown. + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) +{ + // inbuffer = fmod's original mixbuffer. + // outbuffer = the buffer passed from the previous DSP unit. + // length = length in samples at this mix time. + + LLWindGen<LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT> *windgen = NULL; + FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + + thisdsp->getUserData((void **)&windgen); + + if (windgen) + { + windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length); + } + + return FMOD_OK; +} diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodstudio.h similarity index 75% rename from indra/llaudio/llaudioengine_fmodex.h rename to indra/llaudio/llaudioengine_fmodstudio.h index ca389d489fd981359e666ae50b250668a7489c90..f2361df1b618005d5ab9f7db595d0353e394afe5 100644 --- a/indra/llaudio/llaudioengine_fmodex.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -1,11 +1,11 @@ /** - * @file audioengine_fmodex.h + * @file audioengine_fmodstudio.h * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMODEX implementation + * support as a FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2014, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,14 +25,14 @@ * $/LicenseInfo$ */ -#ifndef LL_AUDIOENGINE_FMODEX_H -#define LL_AUDIOENGINE_FMODEX_H +#ifndef LL_AUDIOENGINE_FMODSTUDIO_H +#define LL_AUDIOENGINE_FMODSTUDIO_H #include "llaudioengine.h" #include "llwindgen.h" //Stubs -class LLAudioStreamManagerFMODEX; +class LLAudioStreamManagerFMODSTUDIO; namespace FMOD { class System; @@ -44,14 +44,14 @@ namespace FMOD typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION; //Interfaces -class LLAudioEngine_FMODEX : public LLAudioEngine +class LLAudioEngine_FMODSTUDIO : public LLAudioEngine { public: - LLAudioEngine_FMODEX(bool enable_profiler); - virtual ~LLAudioEngine_FMODEX(); + LLAudioEngine_FMODSTUDIO(bool enable_profiler); + virtual ~LLAudioEngine_FMODSTUDIO(); // initialization/startup/shutdown - virtual bool init(const S32 num_channels, void *user_data); + virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title); virtual std::string getDriverName(bool verbose); virtual void allocateListener(); @@ -85,11 +85,11 @@ class LLAudioEngine_FMODEX : public LLAudioEngine }; -class LLAudioChannelFMODEX : public LLAudioChannel +class LLAudioChannelFMODSTUDIO : public LLAudioChannel { public: - LLAudioChannelFMODEX(FMOD::System *audioengine); - virtual ~LLAudioChannelFMODEX(); + LLAudioChannelFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioChannelFMODSTUDIO(); protected: /*virtual*/ void play(); @@ -110,15 +110,15 @@ class LLAudioChannelFMODEX : public LLAudioChannel }; -class LLAudioBufferFMODEX : public LLAudioBuffer +class LLAudioBufferFMODSTUDIO : public LLAudioBuffer { public: - LLAudioBufferFMODEX(FMOD::System *audioengine); - virtual ~LLAudioBufferFMODEX(); + LLAudioBufferFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioBufferFMODSTUDIO(); /*virtual*/ bool loadWAV(const std::string& filename); /*virtual*/ U32 getLength(); - friend class LLAudioChannelFMODEX; + friend class LLAudioChannelFMODSTUDIO; protected: FMOD::System *getSystem() const {return mSystemp;} FMOD::System *mSystemp; @@ -127,4 +127,4 @@ class LLAudioBufferFMODEX : public LLAudioBuffer }; -#endif // LL_AUDIOENGINE_FMODEX_H +#endif // LL_AUDIOENGINE_FMODSTUDIO_H diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index e6ac586618e3cb2855e76a3b308c2a6ab181a8c4..a38d8291fa900a3e907c17b186920858d2d33133 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -52,7 +52,7 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() } // virtual -bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) +bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata, const std::string &app_title) { mWindGen = NULL; LLAudioEngine::init(num_channels, userdata); @@ -239,6 +239,13 @@ bool LLAudioChannelOpenAL::isPlaying() bool LLAudioChannelOpenAL::updateBuffer() { + if (!mCurrentSourcep) + { + // This channel isn't associated with any source, nothing + // to be updated + return false; + } + if (LLAudioChannel::updateBuffer()) { // Base class update returned true, which means that we need to actually diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h index 6639d9dfe648772a5b718c552284765463cffbcf..366f9259e31e825f139763ea04ff7290abe6f9a7 100644 --- a/indra/llaudio/llaudioengine_openal.h +++ b/indra/llaudio/llaudioengine_openal.h @@ -40,8 +40,8 @@ class LLAudioEngine_OpenAL : public LLAudioEngine LLAudioEngine_OpenAL(); virtual ~LLAudioEngine_OpenAL(); - virtual bool init(const S32 num_channels, void *user_data); - virtual std::string getDriverName(bool verbose); + virtual bool init(const S32 num_channels, void *user_data, const std::string &app_title); + virtual std::string getDriverName(bool verbose); virtual void allocateListener(); virtual void shutdown(); diff --git a/indra/llaudio/lllistener_fmodex.cpp b/indra/llaudio/lllistener_fmodex.cpp deleted file mode 100644 index 31ab47a635f34d93fd1ee3e85676c785affa0e28..0000000000000000000000000000000000000000 --- a/indra/llaudio/lllistener_fmodex.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file listener_fmodex.cpp - * @brief Implementation of LISTENER class abstracting the audio - * support as a FMODEX implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llaudioengine.h" -#include "lllistener_fmodex.h" -#include "fmod.hpp" - -//----------------------------------------------------------------------- -// constructor -//----------------------------------------------------------------------- -LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system) -{ - mSystem = system; - init(); -} - -//----------------------------------------------------------------------- -LLListener_FMODEX::~LLListener_FMODEX() -{ -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::init(void) -{ - // do inherited - LLListener::init(); - mDopplerFactor = 1.0f; - mRolloffFactor = 1.0f; -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::translate(LLVector3 offset) -{ - LLListener::translate(offset); - - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::setPosition(LLVector3 pos) -{ - LLListener::setPosition(pos); - - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::setVelocity(LLVector3 vel) -{ - LLListener::setVelocity(vel); - - mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at) -{ - LLListener::orient(up, at); - - // Welcome to the transition between right and left - // (coordinate systems, that is) - // Leaving the at vector alone results in a L/R reversal - // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed - at = -at; - - mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); -} - -//----------------------------------------------------------------------- -void LLListener_FMODEX::commitDeferredChanges() -{ - if(!mSystem) - { - return; - } - - mSystem->update(); -} - - -void LLListener_FMODEX::setRolloffFactor(F32 factor) -{ - //An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment. - //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. - //In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call. - if(mRolloffFactor != factor) - { - LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL); - } - mRolloffFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); -} - - -F32 LLListener_FMODEX::getRolloffFactor() -{ - return mRolloffFactor; -} - - -void LLListener_FMODEX::setDopplerFactor(F32 factor) -{ - mDopplerFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); -} - - -F32 LLListener_FMODEX::getDopplerFactor() -{ - return mDopplerFactor; -} - - diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abd5e345b57c9c07ed0839596e911b916d49ef10 --- /dev/null +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -0,0 +1,136 @@ +/** + * @file listener_fmodstudio.cpp + * @brief Implementation of LISTENER class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llaudioengine.h" +#include "lllistener_fmodstudio.h" +#include "fmodstudio/fmod.hpp" + +//----------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) +{ + mSystem = system; + init(); +} + +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO() +{ +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::init(void) +{ + // do inherited + LLListener::init(); + mDopplerFactor = 1.0f; + mRolloffFactor = 1.0f; +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::translate(LLVector3 offset) +{ + LLListener::translate(offset); + + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setPosition(LLVector3 pos) +{ + LLListener::setPosition(pos); + + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel) +{ + LLListener::setVelocity(vel); + + mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at) +{ + LLListener::orient(up, at); + + // at = -at; by default Fmod studio is 'left-handed' but we are providing + // flag FMOD_INIT_3D_RIGHTHANDED so no correction are needed + + mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::commitDeferredChanges() +{ + if (!mSystem) + { + return; + } + + mSystem->update(); +} + + +void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor) +{ + //An internal FMOD optimization skips 3D updates if there have not been changes to the 3D sound environment. + // (this was true for FMODex, looks to be still true for FMOD STUDIO, but needs a recheck) + //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. + //In short: Changing the position ticks a dirtyflag inside fmod, which makes it not skip 3D processing next update call. + if (mRolloffFactor != factor) + { + LLVector3 pos = mPosition - LLVector3(0.f, 0.f, .1f); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); + } + mRolloffFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); +} + + +F32 LLListener_FMODSTUDIO::getRolloffFactor() +{ + return mRolloffFactor; +} + + +void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor) +{ + mDopplerFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); +} + + +F32 LLListener_FMODSTUDIO::getDopplerFactor() +{ + return mDopplerFactor; +} diff --git a/indra/llaudio/lllistener_fmodex.h b/indra/llaudio/lllistener_fmodstudio.h similarity index 53% rename from indra/llaudio/lllistener_fmodex.h rename to indra/llaudio/lllistener_fmodstudio.h index 073b65d53adc5c68f5f486f3e2d3bc68cbdea5b0..6ad85d9700ca161fdebe67d3023fe544808a5474 100644 --- a/indra/llaudio/lllistener_fmodex.h +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -1,11 +1,11 @@ /** - * @file listener_fmodex.h + * @file listener_fmodstudio.h * @brief Description of LISTENER class abstracting the audio support - * as an FMOD 3D implementation (windows and Linux) + * as an FMOD 3D implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,8 +25,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LISTENER_FMODEX_H -#define LL_LISTENER_FMODEX_H +#ifndef LL_LISTENER_FMODSTUDIO_H +#define LL_LISTENER_FMODSTUDIO_H #include "lllistener.h" @@ -37,27 +37,27 @@ namespace FMOD } //Interfaces -class LLListener_FMODEX : public LLListener +class LLListener_FMODSTUDIO : public LLListener { - public: - LLListener_FMODEX(FMOD::System *system); - virtual ~LLListener_FMODEX(); - virtual void init(); +public: + LLListener_FMODSTUDIO(FMOD::System *system); + virtual ~LLListener_FMODSTUDIO(); + virtual void init(); - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - virtual void commitDeferredChanges(); + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + virtual void commitDeferredChanges(); - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - protected: - FMOD::System *mSystem; - F32 mDopplerFactor; - F32 mRolloffFactor; + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); +protected: + FMOD::System *mSystem; + F32 mDopplerFactor; + F32 mRolloffFactor; }; #endif diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp deleted file mode 100644 index 9c9e85c00cb6d93a924390a6b7b51633a52cf028..0000000000000000000000000000000000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/** - * @file streamingaudio_fmodex.cpp - * @brief LLStreamingAudio_FMODEX implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llmath.h" - -#include "fmod.hpp" -#include "fmod_errors.h" - -#include "llstreamingaudio_fmodex.h" - - -class LLAudioStreamManagerFMODEX -{ -public: - LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url); - FMOD::Channel* startStream(); - bool stopStream(); // Returns true if the stream was successfully stopped. - bool ready(); - - const std::string& getURL() { return mInternetStreamURL; } - - FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL); -protected: - FMOD::System* mSystem; - FMOD::Channel* mStreamChannel; - FMOD::Sound* mInternetStream; - bool mReady; - - std::string mInternetStreamURL; -}; - - - -//--------------------------------------------------------------------------- -// Internet Streaming -//--------------------------------------------------------------------------- -LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) : - mSystem(system), - mCurrentInternetStreamp(NULL), - mFMODInternetStreamChannelp(NULL), - mGain(1.0f) -{ - // Number of milliseconds of audio to buffer for the audio card. - // Must be larger than the usual Second Life frame stutter time. - const U32 buffer_seconds = 10; //sec - const U32 estimated_bitrate = 128; //kbit/sec - mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); - - // Here's where we set the size of the network buffer and some buffering - // parameters. In this case we want a network buffer of 16k, we want it - // to prebuffer 40% of that when we first connect, and we want it - // to rebuffer 80% of that whenever we encounter a buffer underrun. - - // Leave the net buffer properties at the default. - //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); -} - - -LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() -{ - // nothing interesting/safe to do. -} - - -void LLStreamingAudio_FMODEX::start(const std::string& url) -{ - //if (!mInited) - //{ - // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; - // return; - //} - - // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL - stop(); - - if (!url.empty()) - { - LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url); - mURL = url; - } - else - { - LL_INFOS() << "Set internet stream to null" << LL_ENDL; - mURL.clear(); - } -} - - -void LLStreamingAudio_FMODEX::update() -{ - // Kill dead internet streams, if possible - std::list<LLAudioStreamManagerFMODEX *>::iterator iter; - for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) - { - LLAudioStreamManagerFMODEX *streamp = *iter; - if (streamp->stopStream()) - { - LL_INFOS() << "Closed dead stream" << LL_ENDL; - delete streamp; - mDeadStreams.erase(iter++); - } - else - { - iter++; - } - } - - // Don't do anything if there are no streams playing - if (!mCurrentInternetStreamp) - { - return; - } - - unsigned int progress; - bool starving; - bool diskbusy; - FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); - - if (open_state == FMOD_OPENSTATE_READY) - { - // Stream is live - - // start the stream if it's ready - if (!mFMODInternetStreamChannelp && - (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) - { - // Reset volume to previously set volume - setGain(getGain()); - mFMODInternetStreamChannelp->setPaused(false); - } - } - else if(open_state == FMOD_OPENSTATE_ERROR) - { - stop(); - return; - } - - if(mFMODInternetStreamChannelp) - { - FMOD::Sound *sound = NULL; - - if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) - { - FMOD_TAG tag; - S32 tagcount, dirtytagcount; - - if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) - { - for(S32 i = 0; i < tagcount; ++i) - { - if(sound->getTag(NULL, i, &tag)!=FMOD_OK) - continue; - - if (tag.type == FMOD_TAGTYPE_FMOD) - { - if (!strcmp(tag.name, "Sample Rate Change")) - { - LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; - mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)); - } - continue; - } - } - } - - if(starving) - { - bool paused = false; - mFMODInternetStreamChannelp->getPaused(&paused); - if(!paused) - { - LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; - LL_INFOS() << " (diskbusy="<<diskbusy<<")" << LL_ENDL; - LL_INFOS() << " (progress="<<progress<<")" << LL_ENDL; - mFMODInternetStreamChannelp->setPaused(true); - } - } - else if(progress > 80) - { - mFMODInternetStreamChannelp->setPaused(false); - } - } - } -} - -void LLStreamingAudio_FMODEX::stop() -{ - if (mFMODInternetStreamChannelp) - { - mFMODInternetStreamChannelp->setPaused(true); - mFMODInternetStreamChannelp->setPriority(0); - mFMODInternetStreamChannelp = NULL; - } - - if (mCurrentInternetStreamp) - { - LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - if (mCurrentInternetStreamp->stopStream()) - { - delete mCurrentInternetStreamp; - } - else - { - LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - mDeadStreams.push_back(mCurrentInternetStreamp); - } - mCurrentInternetStreamp = NULL; - //mURL.clear(); - } -} - -void LLStreamingAudio_FMODEX::pause(int pauseopt) -{ - if (pauseopt < 0) - { - pauseopt = mCurrentInternetStreamp ? 1 : 0; - } - - if (pauseopt) - { - if (mCurrentInternetStreamp) - { - stop(); - } - } - else - { - start(getURL()); - } -} - - -// A stream is "playing" if it has been requested to start. That -// doesn't necessarily mean audio is coming out of the speakers. -int LLStreamingAudio_FMODEX::isPlaying() -{ - if (mCurrentInternetStreamp) - { - return 1; // Active and playing - } - else if (!mURL.empty()) - { - return 2; // "Paused" - } - else - { - return 0; - } -} - - -F32 LLStreamingAudio_FMODEX::getGain() -{ - return mGain; -} - - -std::string LLStreamingAudio_FMODEX::getURL() -{ - return mURL; -} - - -void LLStreamingAudio_FMODEX::setGain(F32 vol) -{ - mGain = vol; - - if (mFMODInternetStreamChannelp) - { - vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? - - mFMODInternetStreamChannelp->setVolume(vol); - } -} - -/////////////////////////////////////////////////////// -// manager of possibly-multiple internet audio streams - -LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) : - mSystem(system), - mStreamChannel(NULL), - mInternetStream(NULL), - mReady(false) -{ - mInternetStreamURL = url; - - FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); - - if (result!= FMOD_OK) - { - LL_WARNS() << "Couldn't open fmod stream, error " - << FMOD_ErrorString(result) - << LL_ENDL; - mReady = false; - return; - } - - mReady = true; -} - -FMOD::Channel *LLAudioStreamManagerFMODEX::startStream() -{ - // We need a live and opened stream before we try and play it. - if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY) - { - LL_WARNS() << "No internet stream to start playing!" << LL_ENDL; - return NULL; - } - - if(mStreamChannel) - return mStreamChannel; //Already have a channel for this stream. - - mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel); - return mStreamChannel; -} - -bool LLAudioStreamManagerFMODEX::stopStream() -{ - if (mInternetStream) - { - - - bool close = true; - switch (getOpenState()) - { - case FMOD_OPENSTATE_CONNECTING: - close = false; - break; - default: - close = true; - } - - if (close) - { - mInternetStream->release(); - mStreamChannel = NULL; - mInternetStream = NULL; - return true; - } - else - { - return false; - } - } - else - { - return true; - } -} - -FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) -{ - FMOD_OPENSTATE state; - mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); - return state; -} - -void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) -{ - mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES); - FMOD_ADVANCEDSETTINGS settings; - memset(&settings,0,sizeof(settings)); - settings.cbsize=sizeof(settings); - settings.defaultDecodeBufferSize = decodebuffertime;//ms - mSystem->setAdvancedSettings(&settings); -} diff --git a/indra/llaudio/llstreamingaudio_fmodex.h b/indra/llaudio/llstreamingaudio_fmodex.h deleted file mode 100644 index 2787840ba1a8581bba725f3574c0620fa9c7ea3e..0000000000000000000000000000000000000000 --- a/indra/llaudio/llstreamingaudio_fmodex.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file streamingaudio_fmodex.h - * @brief Definition of LLStreamingAudio_FMODEX implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_STREAMINGAUDIO_FMODEX_H -#define LL_STREAMINGAUDIO_FMODEX_H - -#include "stdtypes.h" // from llcommon - -#include "llstreamingaudio.h" -#include "lltimer.h" - -//Stubs -class LLAudioStreamManagerFMODEX; -namespace FMOD -{ - class System; - class Channel; -} - -//Interfaces -class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface -{ - public: - LLStreamingAudio_FMODEX(FMOD::System *system); - /*virtual*/ ~LLStreamingAudio_FMODEX(); - - /*virtual*/ void start(const std::string& url); - /*virtual*/ void stop(); - /*virtual*/ void pause(S32 pause); - /*virtual*/ void update(); - /*virtual*/ S32 isPlaying(); - /*virtual*/ void setGain(F32 vol); - /*virtual*/ F32 getGain(); - /*virtual*/ std::string getURL(); - - /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} - /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); -private: - FMOD::System *mSystem; - - LLAudioStreamManagerFMODEX *mCurrentInternetStreamp; - FMOD::Channel *mFMODInternetStreamChannelp; - std::list<LLAudioStreamManagerFMODEX *> mDeadStreams; - - std::string mURL; - F32 mGain; -}; - - -#endif // LL_STREAMINGAUDIO_FMODEX_H diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08d19209aadf0a80a43f3a49e0df1bc544a0c645 --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -0,0 +1,392 @@ +/** + * @file streamingaudio_fmodstudio.cpp + * @brief LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llmath.h" + +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" + +#include "llstreamingaudio_fmodstudio.h" + + +class LLAudioStreamManagerFMODSTUDIO +{ +public: + LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, const std::string& url); + FMOD::Channel* startStream(); + bool stopStream(); // Returns true if the stream was successfully stopped. + bool ready(); + + const std::string& getURL() { return mInternetStreamURL; } + + FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); +protected: + FMOD::System* mSystem; + FMOD::Channel* mStreamChannel; + FMOD::Sound* mInternetStream; + bool mReady; + + std::string mInternetStreamURL; +}; + + + +//--------------------------------------------------------------------------- +// Internet Streaming +//--------------------------------------------------------------------------- +LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : +mSystem(system), +mCurrentInternetStreamp(NULL), +mFMODInternetStreamChannelp(NULL), +mGain(1.0f) +{ + // Number of milliseconds of audio to buffer for the audio card. + // Must be larger than the usual Second Life frame stutter time. + const U32 buffer_seconds = 10; //sec + const U32 estimated_bitrate = 128; //kbit/sec + mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); + + // Here's where we set the size of the network buffer and some buffering + // parameters. In this case we want a network buffer of 16k, we want it + // to prebuffer 40% of that when we first connect, and we want it + // to rebuffer 80% of that whenever we encounter a buffer underrun. + + // Leave the net buffer properties at the default. + //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); +} + + +LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() +{ + // nothing interesting/safe to do. +} + + +void LLStreamingAudio_FMODSTUDIO::start(const std::string& url) +{ + //if (!mInited) + //{ + // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; + // return; + //} + + // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL + stop(); + + if (!url.empty()) + { + LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url); + mURL = url; + } + else + { + LL_INFOS() << "Set internet stream to null" << LL_ENDL; + mURL.clear(); + } +} + + +void LLStreamingAudio_FMODSTUDIO::update() +{ + // Kill dead internet streams, if possible + std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter; + for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) + { + LLAudioStreamManagerFMODSTUDIO *streamp = *iter; + if (streamp->stopStream()) + { + LL_INFOS() << "Closed dead stream" << LL_ENDL; + delete streamp; + mDeadStreams.erase(iter++); + } + else + { + iter++; + } + } + + // Don't do anything if there are no streams playing + if (!mCurrentInternetStreamp) + { + return; + } + + unsigned int progress; + bool starving; + bool diskbusy; + FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); + + if (open_state == FMOD_OPENSTATE_READY) + { + // Stream is live + + // start the stream if it's ready + if (!mFMODInternetStreamChannelp && + (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) + { + // Reset volume to previously set volume + setGain(getGain()); + mFMODInternetStreamChannelp->setPaused(false); + } + } + else if (open_state == FMOD_OPENSTATE_ERROR) + { + stop(); + return; + } + + if (mFMODInternetStreamChannelp) + { + FMOD::Sound *sound = NULL; + + if (mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) + { + FMOD_TAG tag; + S32 tagcount, dirtytagcount; + + if (sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) + { + for (S32 i = 0; i < tagcount; ++i) + { + if (sound->getTag(NULL, i, &tag) != FMOD_OK) + continue; + + if (tag.type == FMOD_TAGTYPE_FMOD) + { + if (!strcmp(tag.name, "Sample Rate Change")) + { + LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; + mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)); + } + continue; + } + } + } + + if (starving) + { + bool paused = false; + mFMODInternetStreamChannelp->getPaused(&paused); + if (!paused) + { + LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; + LL_INFOS() << " (diskbusy=" << diskbusy << ")" << LL_ENDL; + LL_INFOS() << " (progress=" << progress << ")" << LL_ENDL; + mFMODInternetStreamChannelp->setPaused(true); + } + } + else if (progress > 80) + { + mFMODInternetStreamChannelp->setPaused(false); + } + } + } +} + +void LLStreamingAudio_FMODSTUDIO::stop() +{ + if (mFMODInternetStreamChannelp) + { + mFMODInternetStreamChannelp->setPaused(true); + mFMODInternetStreamChannelp->setPriority(0); + mFMODInternetStreamChannelp = NULL; + } + + if (mCurrentInternetStreamp) + { + LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + if (mCurrentInternetStreamp->stopStream()) + { + delete mCurrentInternetStreamp; + } + else + { + LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + mDeadStreams.push_back(mCurrentInternetStreamp); + } + mCurrentInternetStreamp = NULL; + //mURL.clear(); + } +} + +void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt) +{ + if (pauseopt < 0) + { + pauseopt = mCurrentInternetStreamp ? 1 : 0; + } + + if (pauseopt) + { + if (mCurrentInternetStreamp) + { + stop(); + } + } + else + { + start(getURL()); + } +} + + +// A stream is "playing" if it has been requested to start. That +// doesn't necessarily mean audio is coming out of the speakers. +int LLStreamingAudio_FMODSTUDIO::isPlaying() +{ + if (mCurrentInternetStreamp) + { + return 1; // Active and playing + } + else if (!mURL.empty()) + { + return 2; // "Paused" + } + else + { + return 0; + } +} + + +F32 LLStreamingAudio_FMODSTUDIO::getGain() +{ + return mGain; +} + + +std::string LLStreamingAudio_FMODSTUDIO::getURL() +{ + return mURL; +} + + +void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) +{ + mGain = vol; + + if (mFMODInternetStreamChannelp) + { + vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? + + mFMODInternetStreamChannelp->setVolume(vol); + } +} + +/////////////////////////////////////////////////////// +// manager of possibly-multiple internet audio streams + +LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, const std::string& url) : +mSystem(system), +mStreamChannel(NULL), +mInternetStream(NULL), +mReady(false) +{ + mInternetStreamURL = url; + + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); + + if (result != FMOD_OK) + { + LL_WARNS() << "Couldn't open fmod stream, error " + << FMOD_ErrorString(result) + << LL_ENDL; + mReady = false; + return; + } + + mReady = true; +} + +FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream() +{ + // We need a live and opened stream before we try and play it. + if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY) + { + LL_WARNS() << "No internet stream to start playing!" << LL_ENDL; + return NULL; + } + + if (mStreamChannel) + return mStreamChannel; //Already have a channel for this stream. + + mSystem->playSound(mInternetStream, NULL, true, &mStreamChannel); + return mStreamChannel; +} + +bool LLAudioStreamManagerFMODSTUDIO::stopStream() +{ + if (mInternetStream) + { + + + bool close = true; + switch (getOpenState()) + { + case FMOD_OPENSTATE_CONNECTING: + close = false; + break; + default: + close = true; + } + + if (close) + { + mInternetStream->release(); + mStreamChannel = NULL; + mInternetStream = NULL; + return true; + } + else + { + return false; + } + } + else + { + return true; + } +} + +FMOD_OPENSTATE LLAudioStreamManagerFMODSTUDIO::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) +{ + FMOD_OPENSTATE state; + mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); + return state; +} + +void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) +{ + mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES); + FMOD_ADVANCEDSETTINGS settings; + memset(&settings, 0, sizeof(settings)); + settings.cbSize = sizeof(settings); + settings.defaultDecodeBufferSize = decodebuffertime;//ms + mSystem->setAdvancedSettings(&settings); +} diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h new file mode 100644 index 0000000000000000000000000000000000000000..1fc3c54d79bc7fcb2815234b4a01951d5745103b --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.h @@ -0,0 +1,73 @@ +/** + * @file streamingaudio_fmodstudio.h + * @brief Definition of LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_STREAMINGAUDIO_FMODSTUDIO_H +#define LL_STREAMINGAUDIO_FMODSTUDIO_H + +#include "stdtypes.h" // from llcommon + +#include "llstreamingaudio.h" +#include "lltimer.h" + +//Stubs +class LLAudioStreamManagerFMODSTUDIO; +namespace FMOD +{ + class System; + class Channel; +} + +//Interfaces +class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface +{ +public: + LLStreamingAudio_FMODSTUDIO(FMOD::System *system); + /*virtual*/ ~LLStreamingAudio_FMODSTUDIO(); + + /*virtual*/ void start(const std::string& url); + /*virtual*/ void stop(); + /*virtual*/ void pause(S32 pause); + /*virtual*/ void update(); + /*virtual*/ S32 isPlaying(); + /*virtual*/ void setGain(F32 vol); + /*virtual*/ F32 getGain(); + /*virtual*/ std::string getURL(); + + /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} + /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); +private: + FMOD::System *mSystem; + + LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp; + FMOD::Channel *mFMODInternetStreamChannelp; + std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams; + + std::string mURL; + F32 mGain; +}; + + +#endif // LL_STREAMINGAUDIO_FMODSTUDIO_H diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index e3bb36192c907c3b1efed33ee4442b84d6b52d06..abb043f4282b84df2cd878da7e829900ee8fce11 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1,5 +1,4 @@ /** - * @file llfloater.cpp * @brief LLFloater base class * diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 63baed679345181f875abebe22f2f5419bc5b78b..7360bd76598799dc17e90fc46f2539c694ee8fe2 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -213,7 +213,8 @@ class LLUICtrl virtual void setColor(const LLColor4& color); - F32 getCurrentTransparency(); + // Ansariel: Changed to virtual. We might want to change the transparency ourself! + virtual F32 getCurrentTransparency(); void setTransparencyType(ETypeTransparency type); ETypeTransparency getTransparencyType() const {return mTransparencyType;} diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index ccf4f3ddf50e66928b9a7d42cff491fa71b1bac3..80a414d00f69a993c15e2396273e1141c84b710f 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -40,6 +40,7 @@ #include "v4coloru.h" #include "v4color.h" #include "v3color.h" +#include "llquaternion.h" #include "llrect.h" #include "llxmltree.h" #include "llsdserialize.h" @@ -125,6 +126,9 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) case TYPE_VEC3D: result = LLVector3d(a) == LLVector3d(b); break; + case TYPE_QUAT: + result = LLQuaternion(a) == LLQuaternion(b); + break; case TYPE_RECT: result = LLRect(a) == LLRect(b); break; @@ -361,6 +365,7 @@ const std::string LLControlGroup::mTypeString[TYPE_COUNT] = { "U32" ,"String" ,"Vector3" ,"Vector3D" + ,"Quaternion" ,"Rect" ,"Color4" ,"Color3" @@ -523,6 +528,11 @@ LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const L return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist); } +LLControlVariable* LLControlGroup::declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist) +{ + return declareControl(name, TYPE_QUAT, initial_val.getValue(), comment, persist); +} + LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist); @@ -600,6 +610,11 @@ LLVector3d LLControlGroup::getVector3d(const std::string& name) return get<LLVector3d>(name); } +LLQuaternion LLControlGroup::getQuaternion(const std::string& name) +{ + return get<LLQuaternion>(name); +} + LLRect LLControlGroup::getRect(const std::string& name) { return get<LLRect>(name); @@ -677,6 +692,11 @@ void LLControlGroup::setVector3d(const std::string& name, const LLVector3d &val) set(name, val); } +void LLControlGroup::setQuaternion(const std::string& name, const LLQuaternion &val) +{ + set(name, val); +} + void LLControlGroup::setRect(const std::string& name, const LLRect &val) { set(name, val); @@ -859,6 +879,16 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require validitems++; } break; + case TYPE_QUAT: + { + LLQuaternion quat; + + child_nodep->getAttributeQuat("value", quat); + + control->set(quat.getValue()); + validitems++; + } + break; case TYPE_RECT: { //RN: hack to support reading rectangles from a string @@ -1201,6 +1231,11 @@ template <> eControlType get_control_type<LLVector3d>() return TYPE_VEC3D; } +template <> eControlType get_control_type<LLQuaternion>() +{ + return TYPE_QUAT; +} + template <> eControlType get_control_type<LLRect>() { return TYPE_RECT; @@ -1236,6 +1271,10 @@ template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in) { return in.getValue(); } +template <> LLSD convert_to_llsd<LLQuaternion>(const LLQuaternion& in) +{ + return in.getValue(); +} template <> LLSD convert_to_llsd<LLRect>(const LLRect& in) { @@ -1348,6 +1387,18 @@ LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, cons } } +template<> +LLQuaternion convert_from_llsd<LLQuaternion>(const LLSD& sd, eControlType type, const std::string& control_name) +{ + if (type == TYPE_QUAT) + return (LLQuaternion)sd; + else + { + CONTROL_ERRS << "Invalid LLQuaternion value for " << control_name << ": " << LLControlGroup::typeEnumToString(type) << " " << sd << LL_ENDL; + return LLQuaternion(); + } +} + template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name) { diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index de0d366492fcf475d60695955d8976e975fdd54a..f1369188963b94058bae5be9f1a06dbebf39a46c 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -67,6 +67,7 @@ class LLVector3; class LLVector3d; +class LLQuaternion; class LLColor4; class LLColor3; @@ -80,6 +81,7 @@ typedef enum e_control_type TYPE_STRING, TYPE_VEC3, TYPE_VEC3D, + TYPE_QUAT, TYPE_RECT, TYPE_COL4, TYPE_COL3, @@ -220,6 +222,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); @@ -234,10 +237,10 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> LLWString getWString(const std::string& name); LLVector3 getVector3(const std::string& name); - LLVector3d getVector3d(const std::string& name); + LLVector3d getVector3d(const std::string& name); LLRect getRect(const std::string& name); LLSD getLLSD(const std::string& name); - + LLQuaternion getQuaternion(const std::string& name); LLColor4 getColor(const std::string& name); LLColor4 getColor4(const std::string& name); @@ -270,6 +273,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> void setString(const std::string& name, const std::string& val); void setVector3(const std::string& name, const LLVector3 &val); void setVector3d(const std::string& name, const LLVector3d &val); + void setQuaternion(const std::string& name, const LLQuaternion &val); void setRect(const std::string& name, const LLRect &val); void setColor4(const std::string& name, const LLColor4 &val); void setLLSD(const std::string& name, const LLSD& val); @@ -436,7 +440,8 @@ template <> eControlType get_control_type<bool>(); //template <> eControlType get_control_type<BOOL> () template <> eControlType get_control_type<std::string>(); template <> eControlType get_control_type<LLVector3>(); -template <> eControlType get_control_type<LLVector3d>(); +template <> eControlType get_control_type<LLVector3d>(); +template <> eControlType get_control_type<LLQuaternion>(); template <> eControlType get_control_type<LLRect>(); template <> eControlType get_control_type<LLColor4>(); template <> eControlType get_control_type<LLColor3>(); @@ -444,7 +449,8 @@ template <> eControlType get_control_type<LLSD>(); template <> LLSD convert_to_llsd<U32>(const U32& in); template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in); -template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in); +template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in); +template <> LLSD convert_to_llsd<LLQuaternion>(const LLQuaternion& in); template <> LLSD convert_to_llsd<LLRect>(const LLRect& in); template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in); template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in); @@ -453,6 +459,7 @@ template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlTy template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name); template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name); template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name); +template<> LLQuaternion convert_from_llsd<LLQuaternion>(const LLSD& sd, eControlType type, const std::string& control_name); template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name); template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name); template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name); diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h index 6a27a65499ba226715f610c960127fb993129a1d..fe77d33fc420793e1f725303bd2c5b78902cab5d 100644 --- a/indra/llxml/llcontrolgroupreader.h +++ b/indra/llxml/llcontrolgroupreader.h @@ -65,6 +65,7 @@ class LLControlGroupReader virtual void setString(const std::string& name, const std::string& val) {} virtual void setVector3(const std::string& name, const LLVector3 &val) {} virtual void setVector3d(const std::string& name, const LLVector3d &val) {} + virtual void setQuaternion(const std::string& name, const LLQuaternion &val) {} virtual void setRect(const std::string& name, const LLRect &val) {} virtual void setColor4(const std::string& name, const LLColor4 &val) {} virtual void setLLSD(const std::string& name, const LLSD& val) {} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 366696873051f6d87d9e9b1f10c5bf38a132b009..8208923e6fa364924b7fcb195e997833afc06e9b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -18,7 +18,7 @@ include(DBusGlib) include(DirectX) include(DragDrop) include(EXPAT) -include(FMODEX) +include(FMODSTUDIO) include(GLOD) include(Hunspell) include(JsonCpp) @@ -63,9 +63,9 @@ if (NOT HAVOK_TPV) add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions) endif (NOT HAVOK_TPV) -if(FMODEX) - include_directories(${FMODEX_INCLUDE_DIR}) -endif(FMODEX) +if(FMODSTUDIO) + include_directories(${FMODSTUDIO_INCLUDE_DIR}) +endif(FMODSTUDIO) include_directories( ${DBUSGLIB_INCLUDE_DIRS} @@ -228,6 +228,7 @@ set(viewer_SOURCE_FILES llfloaterbuycurrencyhtml.cpp llfloaterbuyland.cpp llfloatercamera.cpp + llfloatercamerapresets.cpp llfloaterchatvoicevolume.cpp llfloatercolorpicker.cpp llfloaterconversationlog.cpp @@ -288,12 +289,14 @@ set(viewer_SOURCE_FILES llfloaterperms.cpp llfloaterpostprocess.cpp llfloaterpreference.cpp + llfloaterpreferenceviewadvanced.cpp llfloaterpreviewtrash.cpp llfloaterproperties.cpp llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp llfloaterreporter.cpp llfloaterregionrestarting.cpp + llfloatersavecamerapreset.cpp llfloatersaveprefpreset.cpp llfloatersceneloadstats.cpp llfloaterscriptdebug.cpp @@ -481,6 +484,7 @@ set(viewer_SOURCE_FILES llpanelplaceprofile.cpp llpanelplaces.cpp llpanelplacestab.cpp + llpanelpresetscamerapulldown.cpp llpanelpresetspulldown.cpp llpanelprimmediacontrols.cpp llpanelprofile.cpp @@ -494,6 +498,7 @@ set(viewer_SOURCE_FILES llpaneltiptoast.cpp llpanelvoiceeffect.cpp llpaneltopinfobar.cpp + llpanelpulldown.cpp llpanelvoicedevicesettings.cpp llpanelvolume.cpp llpanelvolumepulldown.cpp @@ -852,6 +857,7 @@ set(viewer_HEADER_FILES llfloaterbuycurrency.h llfloaterbuycurrencyhtml.h llfloaterbuyland.h + llfloatercamerapresets.h llfloatercamera.h llfloaterchatvoicevolume.h llfloatercolorpicker.h @@ -916,12 +922,14 @@ set(viewer_HEADER_FILES llfloaterperms.h llfloaterpostprocess.h llfloaterpreference.h + llfloaterpreferenceviewadvanced.h llfloaterpreviewtrash.h llfloaterproperties.h llfloaterregiondebugconsole.h llfloaterregioninfo.h llfloaterreporter.h llfloaterregionrestarting.h + llfloatersavecamerapreset.h llfloatersaveprefpreset.h llfloatersceneloadstats.h llfloaterscriptdebug.h @@ -1099,12 +1107,14 @@ set(viewer_HEADER_FILES llpanelplaceprofile.h llpanelplaces.h llpanelplacestab.h + llpanelpresetscamerapulldown.h llpanelpresetspulldown.h llpanelprimmediacontrols.h llpanelprofile.h llpanelsnapshot.h llpanelteleporthistory.h llpaneltiptoast.h + llpanelpulldown.h llpanelvoicedevicesettings.h llpanelvoiceeffect.h llpaneltopinfobar.h @@ -1712,12 +1722,13 @@ if (OPENAL) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") endif (OPENAL) -if (FMODEX) - set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") - set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY}) -endif (FMODEX) +if (FMODSTUDIO) + set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODSTUDIO") + set(FMODWRAPPER_LIBRARY ${FMODSTUDIO_LIBRARY}) +endif (FMODSTUDIO) set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") +set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}") list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES}) @@ -1832,13 +1843,13 @@ if (WINDOWS) ) endif (ADDRESS_SIZE EQUAL 64) - if (FMODEX) + if (FMODSTUDIO) list(APPEND COPY_INPUT_DEPENDENCIES - ${SHARED_LIB_STAGING_DIR}/Release/fmodex.dll - ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodex.dll - ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll + ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll + ${SHARED_LIB_STAGING_DIR}/Debug/fmodL.dll ) - endif (FMODEX) + endif (FMODSTUDIO) add_custom_command( OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat @@ -1849,6 +1860,7 @@ if (WINDOWS) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" @@ -1925,6 +1937,7 @@ if (WINDOWS) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" @@ -2070,6 +2083,7 @@ if (LINUX) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" @@ -2096,6 +2110,7 @@ if (LINUX) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" @@ -2172,6 +2187,7 @@ if (DARWIN) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} --bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER} @@ -2206,6 +2222,7 @@ if (DARWIN) --arch=${ARCH} --artwork=${ARTWORK_DIR} "--bugsplat=${BUGSPLAT_DB}" + "--fmodstudio=${FMODSTUDIO}" --build=${CMAKE_CURRENT_BINARY_DIR} --buildtype=${CMAKE_BUILD_TYPE} "--channel=${VIEWER_CHANNEL}" diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index a4c853ea2ea69dbd548168a6823f26d772f27f2c..133cad286fdf619d1cbbb26931c01f4e180b36a4 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.4.2 +6.4.3 diff --git a/indra/newview/app_settings/camera/Front.xml b/indra/newview/app_settings/camera/Front.xml new file mode 100644 index 0000000000000000000000000000000000000000..39f44e11a841a8c420096924cfaf5529ea8e109a --- /dev/null +++ b/indra/newview/app_settings/camera/Front.xml @@ -0,0 +1,142 @@ +<llsd> + <map> + <key>AppearanceCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AvatarSitRotation</key> + <map> + <key>Comment</key> + <string>Avatar real sitting rotation used in preset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array> + <real>0</real> + <real>0</real> + <real>0</real> + <real>1</real> + </array> + </map> + <key>CameraAngle</key> + <map> + <key>Comment</key> + <string>Camera field of view angle (Radians)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.047197551</real> + </map> + <key>CameraOffsetBuild</key> + <map> + <key>Comment</key> + <string>Default camera position relative to focus point when entering build mode</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-6</real> + <real>0</real> + <real>6</real> + </array> + </map> + <key>CameraOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial camera offset from avatar in Front View</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>2.2</real> + <real>0.0</real> + <real>0.0</real> + </array> + </map> + <key>CameraOffsetScale</key> + <map> + <key>Comment</key> + <string>Scales the default offset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1</real> + </map> + <key>CameraZoomFraction</key> + <map> + <key>Comment</key> + <string>Mousewheel driven fraction of zoom</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.90322577953338623</real> + </map> + <key>EditCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering build mode, camera moves up above avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FocusOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial focus point offset relative to avatar for the camera preset Front View (x-axis is forward)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3D</string> + <key>Value</key> + <array> + <real>0.0</real> + <real>0.0</real> + <real>0.0</real> + </array> + </map> + <key>PresetCameraActive</key> + <map> + <key>Comment</key> + <string>Name of currently selected preference</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Default</string> + </map> + <key>TrackFocusObject</key> + <map> + <key>Comment</key> + <string>Camera tracks last object zoomed on</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + </map> +</llsd> diff --git a/indra/newview/app_settings/camera/Rear.xml b/indra/newview/app_settings/camera/Rear.xml new file mode 100644 index 0000000000000000000000000000000000000000..8dc36353ce20a3ea3eaa6405c45c07b043f33956 --- /dev/null +++ b/indra/newview/app_settings/camera/Rear.xml @@ -0,0 +1,142 @@ +<llsd> + <map> + <key>AppearanceCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AvatarSitRotation</key> + <map> + <key>Comment</key> + <string>Avatar real sitting rotation used in preset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array> + <real>0</real> + <real>0</real> + <real>0</real> + <real>1</real> + </array> + </map> + <key>CameraAngle</key> + <map> + <key>Comment</key> + <string>Camera field of view angle (Radians)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.047197551</real> + </map> + <key>CameraOffsetBuild</key> + <map> + <key>Comment</key> + <string>Default camera position relative to focus point when entering build mode</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-6</real> + <real>0</real> + <real>6</real> + </array> + </map> + <key>CameraOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial camera offset from avatar in Rear View</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-3</real> + <real>0</real> + <real>0.75</real> + </array> + </map> + <key>CameraOffsetScale</key> + <map> + <key>Comment</key> + <string>Scales the default offset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1</real> + </map> + <key>CameraZoomFraction</key> + <map> + <key>Comment</key> + <string>Mousewheel driven fraction of zoom</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.90322577953338623</real> + </map> + <key>EditCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering build mode, camera moves up above avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FocusOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial focus point offset relative to avatar for the camera preset Rear View (x-axis is forward)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3D</string> + <key>Value</key> + <array> + <real>1.0</real> + <real>0.0</real> + <real>1.0</real> + </array> + </map> + <key>PresetCameraActive</key> + <map> + <key>Comment</key> + <string>Name of currently selected preference</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Default</string> + </map> + <key>TrackFocusObject</key> + <map> + <key>Comment</key> + <string>Camera tracks last object zoomed on</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + </map> +</llsd> diff --git a/indra/newview/app_settings/camera/Side.xml b/indra/newview/app_settings/camera/Side.xml new file mode 100644 index 0000000000000000000000000000000000000000..089ab93a8f67d3033b5a83586cf22d5441d4dbf9 --- /dev/null +++ b/indra/newview/app_settings/camera/Side.xml @@ -0,0 +1,142 @@ +<llsd> + <map> + <key>AppearanceCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering appearance editing mode, camera zooms in on currently selected portion of avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>AvatarSitRotation</key> + <map> + <key>Comment</key> + <string>Avatar real sitting rotation used in preset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array> + <real>0</real> + <real>0</real> + <real>0</real> + <real>1</real> + </array> + </map> + <key>CameraAngle</key> + <map> + <key>Comment</key> + <string>Camera field of view angle (Radians)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.047197551</real> + </map> + <key>CameraOffsetBuild</key> + <map> + <key>Comment</key> + <string>Default camera position relative to focus point when entering build mode</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-6</real> + <real>0</real> + <real>6</real> + </array> + </map> + <key>CameraOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial camera offset from avatar in Side View</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-1.0</real> + <real>0.7</real> + <real>0.5</real> + </array> + </map> + <key>CameraOffsetScale</key> + <map> + <key>Comment</key> + <string>Scales the default offset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1</real> + </map> + <key>CameraZoomFraction</key> + <map> + <key>Comment</key> + <string>Mousewheel driven fraction of zoom</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.90322577953338623</real> + </map> + <key>EditCameraMovement</key> + <map> + <key>Comment</key> + <string>When entering build mode, camera moves up above avatar</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FocusOffsetRearView</key> + <map> + <key>Comment</key> + <string>Initial focus point offset relative to avatar for the camera preset Side View (x-axis is forward)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3D</string> + <key>Value</key> + <array> + <real>1.5</real> + <real>0.7</real> + <real>1.0</real> + </array> + </map> + <key>PresetCameraActive</key> + <map> + <key>Comment</key> + <string>Name of currently selected preference</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Default</string> + </map> + <key>TrackFocusObject</key> + <map> + <key>Comment</key> + <string>Camera tracks last object zoomed on</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + </map> +</llsd> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0cb9ee3aceb4970dd40047c06738f23069e323f5..e8f01f7a6038a9ec0729d349a5caa2de70ba1b78 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1510,6 +1510,21 @@ <real>0.5</real> </array> </map> + <key>CameraOffsetCustomPreset</key> + <map> + <key>Comment</key> + <string>Initial camera offset from avatar for the custom camera preset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>-3.0</real> + <real>0.0</real> + <real>0.75</real> + </array> + </map> <key>CameraOffsetScale</key> <map> <key>Comment</key> @@ -1521,6 +1536,17 @@ <key>Value</key> <real>1.0</real> </map> + <key>CameraZoomFraction</key> + <map> + <key>Comment</key> + <string>Mousewheel driven fraction of zoom</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.9</real> + </map> <key>CameraPosOnLogout</key> <map> <key>Comment</key> @@ -1558,7 +1584,7 @@ <key>Value</key> <real>1.0</real> </map> - <key>CameraPreset</key> + <key>CameraPreset</key> <!-- deprecated (see SL-12429) --> <map> <key>Comment</key> <string>Preset camera position - view (0 - rear, 1 - front, 2 - group)</string> @@ -4378,6 +4404,37 @@ <real>1.0</real> </array> </map> + <key>FocusOffsetCustomPreset</key> + <map> + <key>Comment</key> + <string>Initial focus point offset relative to avatar for the custom camera preset (x-axis is forward)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3D</string> + <key>Value</key> + <array> + <real>1.0</real> + <real>0.0</real> + <real>1.0</real> + </array> + </map> + <key>AvatarSitRotation</key> + <map> + <key>Comment</key> + <string>Avatar real sitting rotation used in preset</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <array> + <real>0</real> + <real>0</real> + <real>0</real> + <real>1</real> + </array> + </map> <key>FocusPosOnLogout</key> <map> <key>Comment</key> @@ -16327,7 +16384,7 @@ <key>FMODExProfilerEnable</key> <map> <key>Comment</key> - <string>Enable profiler tool if using FMOD Ex</string> + <string>Enable profiler tool if using FMOD Ex or FMOD Studio</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -16338,7 +16395,7 @@ <key>FMODExDecodeBufferSize</key> <map> <key>Comment</key> - <string>Sets the streaming decode buffer size (in milliseconds)</string> + <string>Sets the streaming decode buffer size (in milliseconds) for FMOD Ex or FMOD Studio</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -16349,7 +16406,7 @@ <key>FMODExStreamBufferSize</key> <map> <key>Comment</key> - <string>Sets the streaming buffer size (in milliseconds)</string> + <string>Sets the streaming buffer size (in milliseconds) for FMOD Ex or FMOD Studio</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -16492,6 +16549,50 @@ <key>Value</key> <integer>0</integer> </map> + <key>CameraOpacity</key> + <map> + <key>Comment</key> + <string>Opacity of the Camera Controls floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> + <key>PresetCameraActive</key> + <map> + <key>Comment</key> + <string>Name of currently selected preference</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Rear View</string> + </map> + <key>CameraPresetType</key> + <map> + <key>Comment</key> + <string>Preset camera position - view (0 - rear, 1 - front, 2 - group, 3 - custom)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>HoverHeightAffectsCamera</key> + <map> + <key>Comment</key> + <string>Camera view is affected by Hover Height setting</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>CefVerboseLog</key> <map> <key>Comment</key> diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt index e01b9e4bc63548a7d7c8c765ffa73a28a6f675b0..cb8d1af53582be2fd3fb7c464596e730cef883f7 100644 --- a/indra/newview/linux_tools/client-readme.txt +++ b/indra/newview/linux_tools/client-readme.txt @@ -187,8 +187,8 @@ The 'secondlife' script which launches Second Life contains some configuration options for advanced troubleshooters. * AUDIO - Edit the 'secondlife' script and you will see these audio - options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMOD_ESD, LL_BAD_FMOD_OSS, and - LL_BAD_FMOD_ALSA. Second Life tries to use OpenAL, ESD, OSS, then ALSA + options: LL_BAD_OPENAL_DRIVER, LL_BAD_FMODSTUDIO_DRIVER. + Second Life tries to use OpenAL, FMODSTUDIO (PULSEAUDIO, ALSA) audio drivers in this order; you may uncomment the corresponding LL_BAD_* option to skip an audio driver which you believe may be causing you trouble. diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index c23401d5a661fd954536fadf9c9b8fa0c7da3779..eb3ead433b742f687384b6a1da1469317a633909 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,17 +4,15 @@ ## These options are for self-assisted troubleshooting during this beta ## testing phase; you should not usually need to touch them. -## - Avoids using any FMOD Ex audio driver. -#export LL_BAD_FMODEX_DRIVER=x +## - Avoids using any FMOD STUDIO audio driver. +#export LL_BAD_FMODSTUDIO_DRIVER=x ## - Avoids using any OpenAL audio driver. #export LL_BAD_OPENAL_DRIVER=x -## - Avoids using the FMOD Ex PulseAudio audio driver. +## - Avoids using the FMOD Studio or FMOD Ex PulseAudio audio driver. #export LL_BAD_FMOD_PULSEAUDIO=x -## - Avoids using the FMOD or FMOD Ex ALSA audio driver. +## - Avoids using the FMOD Studio or FMOD Ex ALSA audio driver. #export LL_BAD_FMOD_ALSA=x -## - Avoids using the FMOD or FMOD Ex OSS audio driver. -#export LL_BAD_FMOD_OSS=x ## - Avoids the optional OpenGL extensions which have proven most problematic ## on some hardware. Disabling this option may cause BETTER PERFORMANCE but diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 85b7d7b06f3594e750cdb6e73303ac2c57a988a2..9e65409256890db2d751144f91fe990260a42caa 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -184,6 +184,9 @@ LLAgentCamera::LLAgentCamera() : clearGeneralKeys(); clearOrbitKeys(); clearPanKeys(); + + resetPanDiff(); + resetOrbitDiff(); } // Requires gSavedSettings to be initialized. @@ -205,15 +208,10 @@ void LLAgentCamera::init() mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); - mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPreset"); - - mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("CameraOffsetRearView"); - mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("CameraOffsetFrontView"); - mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("CameraOffsetGroupView"); + mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); - mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("FocusOffsetRearView"); - mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("FocusOffsetFrontView"); - mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("FocusOffsetGroupView"); + mCameraOffsetInitial = gSavedSettings.getControl("CameraOffsetRearView"); + mFocusOffsetInitial = gSavedSettings.getControl("FocusOffsetRearView"); mCameraCollidePlane.clearVec(); mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); @@ -353,7 +351,8 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) mCameraFOVZoomFactor = 0.f; } - + resetPanDiff(); + resetOrbitDiff(); mHUDTargetZoom = 1.f; } @@ -723,7 +722,7 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance) return TRUE; } -F32 LLAgentCamera::getCameraZoomFraction() +F32 LLAgentCamera::getCameraZoomFraction(bool get_third_person) { // 0.f -> camera zoomed all the way out // 1.f -> camera zoomed all the way in @@ -733,7 +732,7 @@ F32 LLAgentCamera::getCameraZoomFraction() // already [0,1] return mHUDTargetZoom; } - else if (mFocusOnAvatar && cameraThirdPerson()) + else if (get_third_person || (mFocusOnAvatar && cameraThirdPerson())) { return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); } @@ -795,13 +794,16 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction) if (mFocusObject.notNull()) { - if (mFocusObject->isAvatar()) + if (mFocusObject.notNull()) { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } } } @@ -835,6 +837,7 @@ void LLAgentCamera::cameraOrbitAround(const F32 radians) } else { + mOrbitAroundRadians += radians; mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); cameraZoomIn(1.f); @@ -866,12 +869,34 @@ void LLAgentCamera::cameraOrbitOver(const F32 angle) LLVector3d left_axis; left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); + mOrbitOverAngle += angle_from_up - new_angle; mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); cameraZoomIn(1.f); } } +void LLAgentCamera::resetCameraOrbit() +{ + LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); + camera_offset_unit.normalize(); + + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis); + + mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f); + + cameraZoomIn(1.f); + resetOrbitDiff(); +} + +void LLAgentCamera::resetOrbitDiff() +{ + mOrbitAroundRadians = 0; + mOrbitOverAngle = 0; +} + //----------------------------------------------------------------------------- // cameraZoomIn() //----------------------------------------------------------------------------- @@ -1010,6 +1035,8 @@ void LLAgentCamera::cameraPanIn(F32 meters) LLVector3d at_axis; at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); + mPanFocusDiff += meters * at_axis; + mFocusTargetGlobal += meters * at_axis; mFocusGlobal = mFocusTargetGlobal; // don't enforce zoom constraints as this is the only way for users to get past them easily @@ -1026,6 +1053,8 @@ void LLAgentCamera::cameraPanLeft(F32 meters) LLVector3d left_axis; left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + mPanFocusDiff += meters * left_axis; + mFocusTargetGlobal += meters * left_axis; mFocusGlobal = mFocusTargetGlobal; @@ -1046,6 +1075,8 @@ void LLAgentCamera::cameraPanUp(F32 meters) LLVector3d up_axis; up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); + mPanFocusDiff += meters * up_axis; + mFocusTargetGlobal += meters * up_axis; mFocusGlobal = mFocusTargetGlobal; @@ -1058,6 +1089,26 @@ void LLAgentCamera::cameraPanUp(F32 meters) mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); } +void LLAgentCamera::resetCameraPan() +{ + mFocusTargetGlobal -= mPanFocusDiff; + + mFocusGlobal = mFocusTargetGlobal; + mCameraSmoothingStop = true; + + cameraZoomIn(1.f); + updateFocusOffset(); + + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + + resetPanDiff(); +} + +void LLAgentCamera::resetPanDiff() +{ + mPanFocusDiff.clear(); +} + //----------------------------------------------------------------------------- // updateLookAt() //----------------------------------------------------------------------------- @@ -1609,7 +1660,7 @@ LLVector3d LLAgentCamera::calcThirdPersonFocusOffset() agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); } - focus_offset = convert_from_llsd<LLVector3d>(mFocusOffsetInitial[mCameraPreset]->get(), TYPE_VEC3D, ""); + focus_offset = convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); return focus_offset * agent_rot; } @@ -1684,7 +1735,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) F32 camera_land_height; LLVector3d frame_center_global = !isAgentAvatarValid() ? gAgent.getPositionGlobal() : - gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); + gAgent.getPosGlobalFromAgent(getAvatarRootPosition()); BOOL isConstrained = FALSE; LLVector3d head_offset; @@ -1758,7 +1809,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) at_axis.mV[VZ] = 0.f; at_axis.normalize(); gAgent.resetAxes(at_axis * ~parent_rot); - + local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; } else @@ -1939,9 +1990,38 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } +LLVector3 LLAgentCamera::getCurrentCameraOffset() +{ + return (LLViewerCamera::getInstance()->getOrigin() - getAvatarRootPosition() - mThirdPersonHeadOffset) * ~getCurrentAvatarRotation(); +} + +LLVector3d LLAgentCamera::getCurrentFocusOffset() +{ + return (mFocusTargetGlobal - gAgent.getPositionGlobal()) * ~getCurrentAvatarRotation(); +} + +LLQuaternion LLAgentCamera::getCurrentAvatarRotation() +{ + LLViewerObject* sit_object = (LLViewerObject*)gAgentAvatarp->getParent(); + + LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); + LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; + return av_rot * obj_rot; +} + +bool LLAgentCamera::isJoystickCameraUsed() +{ + return ((mOrbitAroundRadians != 0) || (mOrbitOverAngle != 0) || !mPanFocusDiff.isNull()); +} + LLVector3 LLAgentCamera::getCameraOffsetInitial() { - return convert_from_llsd<LLVector3>(mCameraOffsetInitial[mCameraPreset]->get(), TYPE_VEC3, ""); + return convert_from_llsd<LLVector3>(mCameraOffsetInitial->get(), TYPE_VEC3, ""); +} + +LLVector3d LLAgentCamera::getFocusOffsetInitial() +{ + return convert_from_llsd<LLVector3d>(mFocusOffsetInitial->get(), TYPE_VEC3D, ""); } F32 LLAgentCamera::getCameraMaxZoomDistance() @@ -1952,6 +2032,12 @@ F32 LLAgentCamera::getCameraMaxZoomDistance() LLWorld::getInstance()->getRegionWidthInMeters() - CAMERA_FUDGE_FROM_OBJECT); } +LLVector3 LLAgentCamera::getAvatarRootPosition() +{ + static LLCachedControl<bool> use_hover_height(gSavedSettings, "HoverHeightAffectsCamera"); + return use_hover_height ? gAgentAvatarp->mRoot->getWorldPosition() : gAgentAvatarp->mRoot->getWorldPosition() - gAgentAvatarp->getHoverOffset(); + +} //----------------------------------------------------------------------------- // handleScrollWheel() //----------------------------------------------------------------------------- @@ -2231,15 +2317,7 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) } // Remove any pitch from the avatar - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis * ~obj_rot); - } - else + if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) { at_axis = gAgent.getFrameAgent().getAtAxis(); at_axis.mV[VZ] = 0.f; @@ -2338,7 +2416,10 @@ void LLAgentCamera::switchCameraPreset(ECameraPreset preset) mCameraPreset = preset; - gSavedSettings.setU32("CameraPreset", mCameraPreset); + resetPanDiff(); + resetOrbitDiff(); + + gSavedSettings.setU32("CameraPresetType", mCameraPreset); } @@ -2583,7 +2664,7 @@ void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camer //----------------------------------------------------------------------------- // setFocusOnAvatar() //----------------------------------------------------------------------------- -void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) +void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate, BOOL reset_axes) { if (focus_on_avatar != mFocusOnAvatar) { @@ -2600,22 +2681,14 @@ void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) //RN: when focused on the avatar, we're not "looking" at it // looking implies intent while focusing on avatar means // you're just walking around with a camera on you...eesh. - if (!mFocusOnAvatar && focus_on_avatar) + if (!mFocusOnAvatar && focus_on_avatar && reset_axes) { setFocusGlobal(LLVector3d::zero); mCameraFOVZoomFactor = 0.f; if (mCameraMode == CAMERA_MODE_THIRD_PERSON) { LLVector3 at_axis; - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis * ~obj_rot); - } - else + if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) { at_axis = LLViewerCamera::getInstance()->getAtAxis(); at_axis.mV[VZ] = 0.f; @@ -2763,6 +2836,17 @@ BOOL LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, return mPointAt->setPointAt(target_type, object, position); } +void LLAgentCamera::rotateToInitSitRot() +{ + gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); + gAgent.rotate(mInitSitRot); +} + +void LLAgentCamera::resetCameraZoomFraction() +{ + mCameraZoomFraction = INITIAL_ZOOM_FRACTION; +} + ELookAtType LLAgentCamera::getLookAtType() { if (mLookAt) diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index a4bc8434b0c982892ff99b8710e6a4d721ed9d4f..ec1ed433d7cd9b26564b7c719041db24c7ffa3ee 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -56,7 +56,10 @@ enum ECameraPreset CAMERA_PRESET_FRONT_VIEW, /** "Above and to the left, over the shoulder, pulled back a little on the zoom" */ - CAMERA_PRESET_GROUP_VIEW + CAMERA_PRESET_GROUP_VIEW, + + /** Current view when a preset is saved */ + CAMERA_PRESET_CUSTOM }; //------------------------------------------------------------------------ @@ -109,20 +112,32 @@ class LLAgentCamera //-------------------------------------------------------------------- public: void switchCameraPreset(ECameraPreset preset); -private: /** Determines default camera offset depending on the current camera preset */ LLVector3 getCameraOffsetInitial(); + /** Determines default focus offset depending on the current camera preset */ + LLVector3d getFocusOffsetInitial(); + + LLVector3 getCurrentCameraOffset(); + LLVector3d getCurrentFocusOffset(); + LLQuaternion getCurrentAvatarRotation(); + bool isJoystickCameraUsed(); + void setInitSitRot(LLQuaternion sit_rot) { mInitSitRot = sit_rot; }; + void rotateToInitSitRot(); + +private: /** Determines maximum camera distance from target for mouselook, opposite to LAND_MIN_ZOOM */ F32 getCameraMaxZoomDistance(); /** Camera preset in Third Person Mode */ ECameraPreset mCameraPreset; - /** Initial camera offsets */ - std::map<ECameraPreset, LLPointer<LLControlVariable> > mCameraOffsetInitial; + /** Initial camera offset */ + LLPointer<LLControlVariable> mCameraOffsetInitial; + + /** Initial focus offset */ + LLPointer<LLControlVariable> mFocusOffsetInitial; - /** Initial focus offsets */ - std::map<ECameraPreset, LLPointer<LLControlVariable> > mFocusOffsetInitial; + LLQuaternion mInitSitRot; //-------------------------------------------------------------------- // Position @@ -137,6 +152,8 @@ class LLAgentCamera F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); } void clearCameraLag() { mCameraLag.clearVec(); } private: + LLVector3 getAvatarRootPosition(); + F32 mCurrentCameraDistance; // Current camera offset from avatar F32 mTargetCameraDistance; // Target camera offset from avatar F32 mCameraFOVZoomFactor; // Amount of fov zoom applied to camera when zeroing in on an object @@ -204,7 +221,7 @@ class LLAgentCamera void validateFocusObject(); void setFocusGlobal(const LLPickInfo& pick); void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null); - void setFocusOnAvatar(BOOL focus, BOOL animate); + void setFocusOnAvatar(BOOL focus, BOOL animate, BOOL reset_axes = TRUE); void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); void clearFocusObject(); void setFocusObject(LLViewerObject* object); @@ -256,26 +273,31 @@ class LLAgentCamera void cameraOrbitAround(const F32 radians); // Rotate camera CCW radians about build focus point void cameraOrbitOver(const F32 radians); // Rotate camera forward radians over build focus point void cameraOrbitIn(const F32 meters); // Move camera in toward build focus point - + void resetCameraOrbit(); + void resetOrbitDiff(); //-------------------------------------------------------------------- // Zoom //-------------------------------------------------------------------- public: - void handleScrollWheel(S32 clicks); // Mousewheel driven zoom - void cameraZoomIn(const F32 factor); // Zoom in by fraction of current distance - F32 getCameraZoomFraction(); // Get camera zoom as fraction of minimum and maximum zoom - void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom + void handleScrollWheel(S32 clicks); // Mousewheel driven zoom + void cameraZoomIn(const F32 factor); // Zoom in by fraction of current distance + F32 getCameraZoomFraction(bool get_third_person = false); // Get camera zoom as fraction of minimum and maximum zoom + void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom F32 calcCameraFOVZoomFactor(); F32 getAgentHUDTargetZoom(); + void resetCameraZoomFraction(); + F32 getCurrentCameraZoomFraction() { return mCameraZoomFraction; } + //-------------------------------------------------------------------- // Pan //-------------------------------------------------------------------- public: void cameraPanIn(const F32 meters); void cameraPanLeft(const F32 meters); - void cameraPanUp(const F32 meters); - + void cameraPanUp(const F32 meters); + void resetCameraPan(); + void resetPanDiff(); //-------------------------------------------------------------------- // View //-------------------------------------------------------------------- @@ -362,6 +384,9 @@ class LLAgentCamera F32 mOrbitInKey; F32 mOrbitOutKey; + F32 mOrbitAroundRadians; + F32 mOrbitOverAngle; + //-------------------------------------------------------------------- // Pan //-------------------------------------------------------------------- @@ -389,6 +414,8 @@ class LLAgentCamera F32 mPanInKey; F32 mPanOutKey; + LLVector3d mPanFocusDiff; + /** Keys ** ** *******************************************************************************/ diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index f3406d93bb11ed388397ac50f1ad032d34d73a9b..d574f1433f764e051d6195df8b3fe0d069dc0b9c 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -34,6 +34,7 @@ // Viewer includes #include "llagent.h" #include "llagentcamera.h" +#include "llpresetsmanager.h" #include "lljoystickbutton.h" #include "llviewercontrol.h" #include "llviewercamera.h" @@ -42,6 +43,8 @@ #include "llslider.h" #include "llfirstuse.h" #include "llhints.h" +#include "lltabcontainer.h" +#include "llvoavatarself.h" static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item"); @@ -52,7 +55,6 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed #define ORBIT "cam_rotate_stick" #define PAN "cam_track_stick" #define ZOOM "zoom" -#define PRESETS "preset_views_list" #define CONTROLS "controls" bool LLFloaterCamera::sFreeCamera = false; @@ -269,13 +271,7 @@ void LLFloaterCamera::onAvatarEditingAppearance(bool editing) void LLFloaterCamera::handleAvatarEditingAppearance(bool editing) { - //camera presets (rear, front, etc.) - getChildView("preset_views_list")->setEnabled(!editing); - getChildView("presets_btn")->setEnabled(!editing); - //camera modes (object view, mouselook view) - getChildView("camera_modes_list")->setEnabled(!editing); - getChildView("avatarview_btn")->setEnabled(!editing); } void LLFloaterCamera::update() @@ -322,6 +318,8 @@ void LLFloaterCamera::onOpen(const LLSD& key) else toPrevMode(); mClosed = FALSE; + + populatePresetCombo(); } void LLFloaterCamera::onClose(bool app_quitting) @@ -353,6 +351,8 @@ LLFloaterCamera::LLFloaterCamera(const LLSD& val) { LLHints::getInstance()->registerHintTarget("view_popup", getHandle()); mCommitCallbackRegistrar.add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2)); + mCommitCallbackRegistrar.add("CameraPresets.Save", boost::bind(&LLFloaterCamera::onSavePreset, this)); + mCommitCallbackRegistrar.add("CameraPresets.ShowPresetsList", boost::bind(&LLFloaterReg::showInstance, "camera_presets", LLSD(), FALSE)); } // virtual @@ -363,10 +363,14 @@ BOOL LLFloaterCamera::postBuild() mRotate = getChild<LLJoystickCameraRotate>(ORBIT); mZoom = findChild<LLPanelCameraZoom>(ZOOM); mTrack = getChild<LLJoystickCameraTrack>(PAN); + mPresetCombo = getChild<LLComboBox>("preset_combo"); + + getChild<LLTextBox>("precise_ctrs_label")->setShowCursorHand(false); + getChild<LLTextBox>("precise_ctrs_label")->setSoundFlags(LLView::MOUSE_UP); + getChild<LLTextBox>("precise_ctrs_label")->setClickedCallback(boost::bind(&LLFloaterReg::showInstance, "prefs_view_advanced", LLSD(), FALSE)); - assignButton2Mode(CAMERA_CTRL_MODE_MODES, "avatarview_btn"); - assignButton2Mode(CAMERA_CTRL_MODE_PAN, "pan_btn"); - assignButton2Mode(CAMERA_CTRL_MODE_PRESETS, "presets_btn"); + mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this)); + LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this)); update(); @@ -376,6 +380,15 @@ BOOL LLFloaterCamera::postBuild() return LLFloater::postBuild(); } +F32 LLFloaterCamera::getCurrentTransparency() +{ + + static LLCachedControl<F32> camera_opacity(gSavedSettings, "CameraOpacity"); + static LLCachedControl<F32> active_floater_transparency(gSavedSettings, "ActiveFloaterTransparency"); + return llmin(camera_opacity(), active_floater_transparency()); + +} + void LLFloaterCamera::fillFlatlistFromPanel (LLFlatListView* list, LLPanel* panel) { // copying child list and then iterating over a copy, because list itself @@ -444,13 +457,6 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode) switch (mode) { - case CAMERA_CTRL_MODE_MODES: - if(sFreeCamera) - { - switchMode(CAMERA_CTRL_MODE_FREE_CAMERA); - } - break; - case CAMERA_CTRL_MODE_PAN: sFreeCamera = false; clear_camera_tool(); @@ -474,36 +480,8 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode) } } - -void LLFloaterCamera::onClickBtn(ECameraControlMode mode) -{ - // check for a click on active button - if (mCurrMode == mode) mMode2Button[mode]->setToggleState(TRUE); - - switchMode(mode); - -} - -void LLFloaterCamera::assignButton2Mode(ECameraControlMode mode, const std::string& button_name) -{ - LLButton* button = getChild<LLButton>(button_name); - - button->setClickedCallback(boost::bind(&LLFloaterCamera::onClickBtn, this, mode)); - mMode2Button[mode] = button; -} - void LLFloaterCamera::updateState() { - getChildView(ZOOM)->setVisible(CAMERA_CTRL_MODE_PAN == mCurrMode); - - bool show_presets = (CAMERA_CTRL_MODE_PRESETS == mCurrMode) || (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode - && CAMERA_CTRL_MODE_PRESETS == mPrevMode); - getChildView(PRESETS)->setVisible(show_presets); - - bool show_camera_modes = CAMERA_CTRL_MODE_MODES == mCurrMode || (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode - && CAMERA_CTRL_MODE_MODES == mPrevMode); - getChildView("camera_modes_list")->setVisible( show_camera_modes); - updateItemsSelection(); if (CAMERA_CTRL_MODE_FREE_CAMERA == mCurrMode) @@ -521,13 +499,13 @@ void LLFloaterCamera::updateState() void LLFloaterCamera::updateItemsSelection() { - ECameraPreset preset = (ECameraPreset) gSavedSettings.getU32("CameraPreset"); + ECameraPreset preset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); LLSD argument; - argument["selected"] = preset == CAMERA_PRESET_REAR_VIEW; + argument["selected"] = (preset == CAMERA_PRESET_REAR_VIEW) && !sFreeCamera; getChild<LLPanelCameraItem>("rear_view")->setValue(argument); - argument["selected"] = preset == CAMERA_PRESET_GROUP_VIEW; + argument["selected"] = (preset == CAMERA_PRESET_GROUP_VIEW) && !sFreeCamera; getChild<LLPanelCameraItem>("group_view")->setValue(argument); - argument["selected"] = preset == CAMERA_PRESET_FRONT_VIEW; + argument["selected"] = (preset == CAMERA_PRESET_FRONT_VIEW) && !sFreeCamera; getChild<LLPanelCameraItem>("front_view")->setValue(argument); argument["selected"] = gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK; getChild<LLPanelCameraItem>("mouselook_view")->setValue(argument); @@ -547,19 +525,19 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param) { LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance(); if (camera_floater) - camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA); + { + camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA); + camera_floater->updateItemsSelection(); + camera_floater->fromFreeToPresets(); + } } else { + LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance(); + if (camera_floater) + camera_floater->switchMode(CAMERA_CTRL_MODE_PAN); switchToPreset(name); } - - LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance(); - if (camera_floater) - { - camera_floater->updateItemsSelection(); - camera_floater->fromFreeToPresets(); - } } /*static*/ @@ -567,18 +545,49 @@ void LLFloaterCamera::switchToPreset(const std::string& name) { sFreeCamera = false; clear_camera_tool(); - if ("rear_view" == name) + if (PRESETS_REAR_VIEW == name) { gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); } - else if ("group_view" == name) + else if (PRESETS_SIDE_VIEW == name) { gAgentCamera.switchCameraPreset(CAMERA_PRESET_GROUP_VIEW); } - else if ("front_view" == name) + else if (PRESETS_FRONT_VIEW == name) { gAgentCamera.switchCameraPreset(CAMERA_PRESET_FRONT_VIEW); } + else + { + gAgentCamera.switchCameraPreset(CAMERA_PRESET_CUSTOM); + } + + if (gSavedSettings.getString("PresetCameraActive") != name) + { + LLPresetsManager::getInstance()->loadPreset(PRESETS_CAMERA, name); + } + + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + LLQuaternion sit_rot(gSavedSettings.getLLSD("AvatarSitRotation")); + if (sit_rot != LLQuaternion()) + { + gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); + gAgent.rotate(sit_rot); + } + else + { + gAgentCamera.rotateToInitSitRot(); + } + } + gAgentCamera.resetCameraZoomFraction(); + + LLFloaterCamera* camera_floater = LLFloaterCamera::findInstance(); + if (camera_floater) + { + camera_floater->updateItemsSelection(); + camera_floater->fromFreeToPresets(); + } } void LLFloaterCamera::fromFreeToPresets() @@ -588,3 +597,41 @@ void LLFloaterCamera::fromFreeToPresets() switchMode(CAMERA_CTRL_MODE_PRESETS); } } + +void LLFloaterCamera::populatePresetCombo() +{ + LLPresetsManager::getInstance()->setPresetNamesInComboBox(PRESETS_CAMERA, mPresetCombo, EDefaultOptions::DEFAULT_HIDE); + std::string active_preset_name = gSavedSettings.getString("PresetCameraActive"); + if (active_preset_name.empty()) + { + gSavedSettings.setU32("CameraPresetType", CAMERA_PRESET_CUSTOM); + updateItemsSelection(); + mPresetCombo->setLabel(getString("inactive_combo_text")); + } + else if ((ECameraPreset)gSavedSettings.getU32("CameraPresetType") == CAMERA_PRESET_CUSTOM) + { + mPresetCombo->selectByValue(active_preset_name); + } + else + { + mPresetCombo->setLabel(getString("inactive_combo_text")); + } + updateItemsSelection(); +} + +void LLFloaterCamera::onSavePreset() +{ + LLFloaterReg::hideInstance("delete_pref_preset", PRESETS_CAMERA); + LLFloaterReg::hideInstance("load_pref_preset", PRESETS_CAMERA); + + LLFloaterReg::showInstance("save_camera_preset"); +} + +void LLFloaterCamera::onCustomPresetSelected() +{ + std::string selected_preset = mPresetCombo->getSelectedItemLabel(); + if (getString("inactive_combo_text") != selected_preset) + { + switchToPreset(selected_preset); + } +} diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 4d6d03f22d9078e150720bf44b6ee3fdba7753c1..9440f50c3fd15b6d8787702e6273d0b102f670b7 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -36,10 +36,10 @@ class LLJoystickCameraRotate; class LLJoystickCameraTrack; class LLFloaterReg; class LLPanelCameraZoom; +class LLComboBox; enum ECameraControlMode { - CAMERA_CTRL_MODE_MODES, CAMERA_CTRL_MODE_PAN, CAMERA_CTRL_MODE_FREE_CAMERA, CAMERA_CTRL_MODE_PRESETS @@ -50,7 +50,6 @@ class LLFloaterCamera : public LLFloater friend class LLFloaterReg; public: - /* whether in free camera mode */ static bool inFreeCameraMode(); /* callback for camera items selection changing */ @@ -77,6 +76,11 @@ class LLFloaterCamera : public LLFloater virtual void onOpen(const LLSD& key); virtual void onClose(bool app_quitting); + void onSavePreset(); + void onCustomPresetSelected(); + + void populatePresetCombo(); + LLJoystickCameraRotate* mRotate; LLPanelCameraZoom* mZoom; LLJoystickCameraTrack* mTrack; @@ -91,6 +95,10 @@ class LLFloaterCamera : public LLFloater /*virtual*/ BOOL postBuild(); + F32 getCurrentTransparency(); + + void onViewButtonClick(const LLSD& user_data); + ECameraControlMode determineMode(); /* resets to the previous mode */ @@ -108,9 +116,6 @@ class LLFloaterCamera : public LLFloater /* update camera modes items selection and camera preset items selection according to the currently selected preset */ void updateItemsSelection(); - void onClickBtn(ECameraControlMode mode); - void assignButton2Mode(ECameraControlMode mode, const std::string& button_name); - // fills flatlist with items from given panel void fillFlatlistFromPanel (LLFlatListView* list, LLPanel* panel); @@ -124,6 +129,8 @@ class LLFloaterCamera : public LLFloater ECameraControlMode mPrevMode; ECameraControlMode mCurrMode; std::map<ECameraControlMode, LLButton*> mMode2Button; + + LLComboBox* mPresetCombo; }; /** diff --git a/indra/newview/llfloatercamerapresets.cpp b/indra/newview/llfloatercamerapresets.cpp new file mode 100644 index 0000000000000000000000000000000000000000..300c945a859ca845696350d935b1236a0b5085c0 --- /dev/null +++ b/indra/newview/llfloatercamerapresets.cpp @@ -0,0 +1,145 @@ +/** +* @file llfloatercamerapresets.cpp +* +* $LicenseInfo:firstyear=2019&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2019, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#include "llviewerprecompiledheaders.h" + +#include "llfloatercamerapresets.h" +#include "llfloaterreg.h" +#include "llnotificationsutil.h" +#include "llpresetsmanager.h" +#include "llviewercontrol.h" + +LLFloaterCameraPresets::LLFloaterCameraPresets(const LLSD& key) +: LLFloater(key) +{} + +LLFloaterCameraPresets::~LLFloaterCameraPresets() +{} + +BOOL LLFloaterCameraPresets::postBuild() +{ + mPresetList = getChild<LLFlatListView>("preset_list"); + + LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCameraPresets::populateList, this)); + + return TRUE; +} +void LLFloaterCameraPresets::onOpen(const LLSD& key) +{ + populateList(); +} + +void LLFloaterCameraPresets::populateList() +{ + mPresetList->clear(); + + LLPresetsManager* presetsMgr = LLPresetsManager::getInstance(); + std::list<std::string> preset_names; + + presetsMgr->loadPresetNamesFromDir(PRESETS_CAMERA, preset_names, DEFAULT_BOTTOM); + + for (std::list<std::string>::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it) + { + const std::string& name = *it; + bool is_default = presetsMgr->isDefaultCameraPreset(name); + LLCameraPresetFlatItem* item = new LLCameraPresetFlatItem(name, is_default); + item->postBuild(); + mPresetList->addItem(item); + } +} + +LLCameraPresetFlatItem::LLCameraPresetFlatItem(const std::string &preset_name, bool is_default) + : LLPanel(), + mPresetName(preset_name), + mIsDefaultPrest(is_default) +{ + mCommitCallbackRegistrar.add("CameraPresets.Delete", boost::bind(&LLCameraPresetFlatItem::onDeleteBtnClick, this)); + mCommitCallbackRegistrar.add("CameraPresets.Reset", boost::bind(&LLCameraPresetFlatItem::onResetBtnClick, this)); + buildFromFile("panel_camera_preset_item.xml"); +} + +LLCameraPresetFlatItem::~LLCameraPresetFlatItem() +{ +} + +BOOL LLCameraPresetFlatItem::postBuild() +{ + mDeleteBtn = getChild<LLButton>("delete_btn"); + mDeleteBtn->setVisible(false); + + mResetBtn = getChild<LLButton>("reset_btn"); + mResetBtn->setVisible(false); + + LLStyle::Params style; + LLTextBox* name_text = getChild<LLTextBox>("preset_name"); + LLFontDescriptor new_desc(name_text->getFont()->getFontDesc()); + new_desc.setStyle(mIsDefaultPrest ? LLFontGL::ITALIC : LLFontGL::NORMAL); + LLFontGL* new_font = LLFontGL::getFont(new_desc); + style.font = new_font; + name_text->setText(mPresetName, style); + + return true; +} + +void LLCameraPresetFlatItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mDeleteBtn->setVisible(!mIsDefaultPrest); + mResetBtn->setVisible(mIsDefaultPrest); + getChildView("hovered_icon")->setVisible(true); + LLPanel::onMouseEnter(x, y, mask); +} + +void LLCameraPresetFlatItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mDeleteBtn->setVisible(false); + mResetBtn->setVisible(false); + getChildView("hovered_icon")->setVisible(false); + LLPanel::onMouseLeave(x, y, mask); +} + +void LLCameraPresetFlatItem::setValue(const LLSD& value) +{ + if (!value.isMap()) return;; + if (!value.has("selected")) return; + getChildView("selected_icon")->setVisible(value["selected"]); +} + +void LLCameraPresetFlatItem::onDeleteBtnClick() +{ + if (!LLPresetsManager::getInstance()->deletePreset(PRESETS_CAMERA, mPresetName)) + { + LLSD args; + args["NAME"] = mPresetName; + LLNotificationsUtil::add("PresetNotDeleted", args); + } + else if (gSavedSettings.getString("PresetCameraActive") == mPresetName) + { + gSavedSettings.setString("PresetCameraActive", ""); + } +} + +void LLCameraPresetFlatItem::onResetBtnClick() +{ + LLPresetsManager::getInstance()->resetCameraPreset(mPresetName); +} diff --git a/indra/newview/llfloatercamerapresets.h b/indra/newview/llfloatercamerapresets.h new file mode 100644 index 0000000000000000000000000000000000000000..66430fa399441f67a52aae5944e0ed915b5d8689 --- /dev/null +++ b/indra/newview/llfloatercamerapresets.h @@ -0,0 +1,73 @@ +/** +* @file llfloatercamerapresets.h +* +* $LicenseInfo:firstyear=2019&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2019, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ +#ifndef LLFLOATERCAMERAPRESETS_H +#define LLFLOATERCAMERAPRESETS_H + +#include "llfloater.h" +#include "llflatlistview.h" + +class LLFloaterReg; + +class LLFloaterCameraPresets : public LLFloater +{ + friend class LLFloaterReg; + + virtual BOOL postBuild(); + virtual void onOpen(const LLSD& key); + + void populateList(); + +private: + LLFloaterCameraPresets(const LLSD& key); + ~LLFloaterCameraPresets(); + + LLFlatListView* mPresetList; +}; + +class LLCameraPresetFlatItem : public LLPanel +{ +public: + LLCameraPresetFlatItem(const std::string &preset_name, bool is_default); + virtual ~LLCameraPresetFlatItem(); + + void setValue(const LLSD& value); + + virtual BOOL postBuild(); + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + +private: + void onDeleteBtnClick(); + void onResetBtnClick(); + + LLButton* mDeleteBtn; + LLButton* mResetBtn; + + std::string mPresetName; + bool mIsDefaultPrest; + +}; + +#endif diff --git a/indra/newview/llfloaterdeleteprefpreset.cpp b/indra/newview/llfloaterdeleteprefpreset.cpp index 7dedbbf98430169016ec275228f84c7bcdfae203..0765756b433b86cd260c4165f4cf99ee519779d6 100644 --- a/indra/newview/llfloaterdeleteprefpreset.cpp +++ b/indra/newview/llfloaterdeleteprefpreset.cpp @@ -60,13 +60,15 @@ void LLFloaterDeletePrefPreset::onOpen(const LLSD& key) { mSubdirectory = key.asString(); std::string floater_title = getString(std::string("title_") + mSubdirectory); - setTitle(floater_title); LLComboBox* combo = getChild<LLComboBox>("preset_combo"); - EDefaultOptions option = DEFAULT_HIDE; - LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option); + bool action; + action = LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option); + + LLButton* delete_btn = getChild<LLButton>("delete"); + delete_btn->setEnabled(action); } void LLFloaterDeletePrefPreset::onBtnDelete() @@ -80,6 +82,13 @@ void LLFloaterDeletePrefPreset::onBtnDelete() args["NAME"] = name; LLNotificationsUtil::add("PresetNotDeleted", args); } + else if (mSubdirectory == PRESETS_CAMERA) + { + if (gSavedSettings.getString("PresetCameraActive") == name) + { + gSavedSettings.setString("PresetCameraActive", ""); + } + } closeFloater(); } @@ -87,12 +96,10 @@ void LLFloaterDeletePrefPreset::onBtnDelete() void LLFloaterDeletePrefPreset::onPresetsListChange() { LLComboBox* combo = getChild<LLComboBox>("preset_combo"); - LLButton* delete_btn = getChild<LLButton>("delete"); EDefaultOptions option = DEFAULT_HIDE; - LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option); - delete_btn->setEnabled(0 != combo->getItemCount()); + LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option); } void LLFloaterDeletePrefPreset::onBtnCancel() diff --git a/indra/newview/llfloaterloadprefpreset.cpp b/indra/newview/llfloaterloadprefpreset.cpp index 403db35cc020c57c93c0df43a12fa5c6c15753f1..fa17a9d40e3d08e0e37b99b1044deaa6328d295c 100644 --- a/indra/newview/llfloaterloadprefpreset.cpp +++ b/indra/newview/llfloaterloadprefpreset.cpp @@ -42,7 +42,8 @@ LLFloaterLoadPrefPreset::LLFloaterLoadPrefPreset(const LLSD &key) // virtual BOOL LLFloaterLoadPrefPreset::postBuild() -{ LLFloaterPreference* preferences = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); +{ + LLFloaterPreference* preferences = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); if (preferences) { preferences->addDependentFloater(this); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 093753c9679faea06d43622d97b5ee83315acd37..951d11bbe5461fdeaded6139eedb7566fc37515d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -725,7 +725,7 @@ void LLFloaterPreference::cancel() // hide spellchecker settings folder LLFloaterReg::hideInstance("prefs_spellchecker"); - // hide advancede floater + // hide advanced graphics floater LLFloaterReg::hideInstance("prefs_graphics_advanced"); // reverts any changes to current skin @@ -844,7 +844,8 @@ void LLFloaterPreference::onOpen(const LLSD& key) saveSettings(); // Make sure there is a default preference file - LLPresetsManager::getInstance()->createMissingDefault(); + LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); + LLPresetsManager::getInstance()->createMissingDefault(PRESETS_GRAPHIC); bool started = (LLStartUp::getStartupState() == STATE_STARTED); @@ -853,12 +854,15 @@ void LLFloaterPreference::onOpen(const LLSD& key) LLButton* delete_btn = findChild<LLButton>("PrefDeleteButton"); LLButton* exceptions_btn = findChild<LLButton>("RenderExceptionsButton"); - load_btn->setEnabled(started); - save_btn->setEnabled(started); - delete_btn->setEnabled(started); - exceptions_btn->setEnabled(started); + if (load_btn && save_btn && delete_btn && exceptions_btn) + { + load_btn->setEnabled(started); + save_btn->setEnabled(started); + delete_btn->setEnabled(started); + exceptions_btn->setEnabled(started); + } - collectSearchableItems(); + collectSearchableItems(); if (!mFilterEdit->getText().empty()) { mFilterEdit->setText(LLStringExplicit("")); @@ -2633,20 +2637,17 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) void LLPanelPreference::deletePreset(const LLSD& user_data) { - std::string subdirectory = user_data.asString(); - LLFloaterReg::showInstance("delete_pref_preset", subdirectory); + LLFloaterReg::showInstance("delete_pref_preset", user_data.asString()); } void LLPanelPreference::savePreset(const LLSD& user_data) { - std::string subdirectory = user_data.asString(); - LLFloaterReg::showInstance("save_pref_preset", subdirectory); + LLFloaterReg::showInstance("save_pref_preset", user_data.asString()); } void LLPanelPreference::loadPreset(const LLSD& user_data) { - std::string subdirectory = user_data.asString(); - LLFloaterReg::showInstance("load_pref_preset", subdirectory); + LLFloaterReg::showInstance("load_pref_preset", user_data.asString()); } void LLPanelPreference::setHardwareDefaults() @@ -2704,7 +2705,7 @@ BOOL LLPanelPreferenceGraphics::postBuild() LLPresetsManager* presetsMgr = LLPresetsManager::getInstance(); presetsMgr->setPresetListChangeCallback(boost::bind(&LLPanelPreferenceGraphics::onPresetsListChange, this)); - presetsMgr->createMissingDefault(); // a no-op after the first time, but that's ok + presetsMgr->createMissingDefault(PRESETS_GRAPHIC); // a no-op after the first time, but that's ok return LLPanelPreference::postBuild(); } @@ -2725,11 +2726,6 @@ void LLPanelPreferenceGraphics::onPresetsListChange() { instance->saveSettings(); //make cancel work correctly after changing the preset } - else - { - std::string dummy; - instance->saveGraphicsPreset(dummy); - } } void LLPanelPreferenceGraphics::setPresetText() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index a0f43bd8848e4560e3605d3c014d499e90e6ff37..526214a617b2af0fa67e434c723aa90af28b8ec9 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -191,6 +191,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver, void buildPopupLists(); static void refreshSkin(void* data); void selectPanel(const LLSD& name); + void saveCameraPreset(std::string& preset); void saveGraphicsPreset(std::string& preset); private: @@ -214,6 +215,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver, std::string mDirectoryVisibility; LLAvatarData mAvatarProperties; + std::string mSavedCameraPreset; std::string mSavedGraphicsPreset; LOG_CLASS(LLFloaterPreference); @@ -288,7 +290,6 @@ class LLPanelPreferenceGraphics : public LLPanelPreference bool hasDirtyChilds(); private: - void onPresetsListChange(); LOG_CLASS(LLPanelPreferenceGraphics); }; diff --git a/indra/newview/llfloaterpreferenceviewadvanced.cpp b/indra/newview/llfloaterpreferenceviewadvanced.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8db738923359072443744297795191971ee1e2b --- /dev/null +++ b/indra/newview/llfloaterpreferenceviewadvanced.cpp @@ -0,0 +1,82 @@ +/** + * @file llfloaterpreferenceviewadvanced.cpp + * @brief floater for adjusting camera position + * + * $LicenseInfo:firstyear=2018&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2018, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llagentcamera.h" +#include "llfloaterpreferenceviewadvanced.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lluictrlfactory.h" +#include "llspinctrl.h" +#include "llviewercontrol.h" + + +LLFloaterPreferenceViewAdvanced::LLFloaterPreferenceViewAdvanced(const LLSD& key) +: LLFloater(key) +{ + mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterPreferenceViewAdvanced::onCommitSettings, this)); +} + +LLFloaterPreferenceViewAdvanced::~LLFloaterPreferenceViewAdvanced() +{} + +void LLFloaterPreferenceViewAdvanced::updateCameraControl(const LLVector3& vector) +{ + getChild<LLSpinCtrl>("camera_x")->setValue(vector[VX]); + getChild<LLSpinCtrl>("camera_y")->setValue(vector[VY]); + getChild<LLSpinCtrl>("camera_z")->setValue(vector[VZ]); +} + +void LLFloaterPreferenceViewAdvanced::updateFocusControl(const LLVector3d& vector3d) +{ + getChild<LLSpinCtrl>("focus_x")->setValue(vector3d[VX]); + getChild<LLSpinCtrl>("focus_y")->setValue(vector3d[VY]); + getChild<LLSpinCtrl>("focus_z")->setValue(vector3d[VZ]); +} + + void LLFloaterPreferenceViewAdvanced::draw() +{ + updateCameraControl(gAgentCamera.getCameraOffsetInitial()); + updateFocusControl(gAgentCamera.getFocusOffsetInitial()); + + LLFloater::draw(); +} + +void LLFloaterPreferenceViewAdvanced::onCommitSettings() +{ + LLVector3 vector; + LLVector3d vector3d; + + vector.mV[VX] = (F32)getChild<LLUICtrl>("camera_x")->getValue().asReal(); + vector.mV[VY] = (F32)getChild<LLUICtrl>("camera_y")->getValue().asReal(); + vector.mV[VZ] = (F32)getChild<LLUICtrl>("camera_z")->getValue().asReal(); + gSavedSettings.setVector3("CameraOffsetRearView", vector); + + vector3d.mdV[VX] = (F32)getChild<LLUICtrl>("focus_x")->getValue().asReal(); + vector3d.mdV[VY] = (F32)getChild<LLUICtrl>("focus_y")->getValue().asReal(); + vector3d.mdV[VZ] = (F32)getChild<LLUICtrl>("focus_z")->getValue().asReal(); + gSavedSettings.setVector3d("FocusOffsetRearView", vector3d); +} diff --git a/indra/newview/llfloaterpreferenceviewadvanced.h b/indra/newview/llfloaterpreferenceviewadvanced.h new file mode 100644 index 0000000000000000000000000000000000000000..4619fdaab16b9f79aaea2071b04c5c5252556adb --- /dev/null +++ b/indra/newview/llfloaterpreferenceviewadvanced.h @@ -0,0 +1,51 @@ +/** + * @file llfloaterpreferenceviewadvanced.h + * @brief floater for adjusting camera position + * + * $LicenseInfo:firstyear=2018&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2018, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERPREFERENCEVIEWADVANCED_H +#define LLFLOATERPREFERENCEVIEWADVANCED_H + +#include "llcontrol.h" +#include "llfloater.h" + +class LLFloaterPreferenceViewAdvanced +: public LLFloater +{ + friend class LLFloaterReg; + +public: + LLFloaterPreferenceViewAdvanced(const LLSD& key); + virtual void draw(); + + void onCommitSettings(); + void updateCameraControl(const LLVector3& vector); + void updateFocusControl(const LLVector3d& vector3d); + +private: + virtual ~LLFloaterPreferenceViewAdvanced(); +}; + +#endif //LLFLOATERPREFERENCEVIEWADVANCED_H + diff --git a/indra/newview/llfloatersavecamerapreset.cpp b/indra/newview/llfloatersavecamerapreset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11809f9c824369c5793b7027bede4b48f441a1d4 --- /dev/null +++ b/indra/newview/llfloatersavecamerapreset.cpp @@ -0,0 +1,172 @@ +/** + * @file llfloatersavecamerapreset.cpp + * @brief Floater to save a camera preset + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatersavecamerapreset.h" + +#include "llagent.h" +#include "llagentcamera.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llfloaterpreference.h" +#include "llfloaterreg.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llpresetsmanager.h" +#include "llradiogroup.h" +#include "lltrans.h" +#include "llvoavatarself.h" + +LLFloaterSaveCameraPreset::LLFloaterSaveCameraPreset(const LLSD &key) + : LLModalDialog(key) +{ +} + +// virtual +BOOL LLFloaterSaveCameraPreset::postBuild() +{ + mPresetCombo = getChild<LLComboBox>("preset_combo"); + + mNameEditor = getChild<LLLineEditor>("preset_txt_editor"); + mNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterSaveCameraPreset::onPresetNameEdited, this), NULL); + + mSaveButton = getChild<LLButton>("save"); + mSaveButton->setCommitCallback(boost::bind(&LLFloaterSaveCameraPreset::onBtnSave, this)); + + mSaveRadioGroup = getChild<LLRadioGroup>("radio_save_preset"); + mSaveRadioGroup->setCommitCallback(boost::bind(&LLFloaterSaveCameraPreset::onSwitchSaveReplace, this)); + + getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterSaveCameraPreset::onBtnCancel, this)); + + LLPresetsManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterSaveCameraPreset::onPresetsListChange, this)); + + return TRUE; +} + +void LLFloaterSaveCameraPreset::onPresetNameEdited() +{ + if (mSaveRadioGroup->getSelectedIndex() == 0) + { + // Disable saving a preset having empty name. + std::string name = mNameEditor->getValue(); + mSaveButton->setEnabled(!name.empty()); + } +} + +void LLFloaterSaveCameraPreset::onOpen(const LLSD& key) +{ + LLModalDialog::onOpen(key); + S32 index = 0; + if (key.has("index")) + { + index = key["index"].asInteger(); + } + + LLPresetsManager::getInstance()->setPresetNamesInComboBox(PRESETS_CAMERA, mPresetCombo, DEFAULT_BOTTOM); + + mSaveRadioGroup->setSelectedIndex(index); + onPresetNameEdited(); + onSwitchSaveReplace(); +} + +void LLFloaterSaveCameraPreset::onBtnSave() +{ + bool is_saving_new = mSaveRadioGroup->getSelectedIndex() == 0; + std::string name = is_saving_new ? mNameEditor->getText() : mPresetCombo->getSimple(); + + if ((name == LLTrans::getString(PRESETS_DEFAULT)) || (name == PRESETS_DEFAULT)) + { + LLNotificationsUtil::add("DefaultPresetNotSaved"); + } + else + { + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + gSavedSettings.setLLSD("AvatarSitRotation", gAgent.getFrameAgent().getQuaternion().getValue()); + } + if (gAgentCamera.isJoystickCameraUsed()) + { + gSavedSettings.setVector3("CameraOffsetRearView", gAgentCamera.getCurrentCameraOffset()); + gSavedSettings.setVector3d("FocusOffsetRearView", gAgentCamera.getCurrentFocusOffset()); + gAgentCamera.resetCameraZoomFraction(); + gAgentCamera.setFocusOnAvatar(TRUE, TRUE, FALSE); + } + else + { + LLVector3 camera_offset = gSavedSettings.getVector3("CameraOffsetRearView") * gAgentCamera.getCurrentCameraZoomFraction(); + gSavedSettings.setVector3("CameraOffsetRearView", camera_offset); + gAgentCamera.resetCameraZoomFraction(); + } + if (is_saving_new) + { + std::list<std::string> preset_names; + LLPresetsManager::getInstance()->loadPresetNamesFromDir(PRESETS_CAMERA, preset_names, DEFAULT_HIDE); + if (std::find(preset_names.begin(), preset_names.end(), name) != preset_names.end()) + { + LLSD args; + args["NAME"] = name; + LLNotificationsUtil::add("PresetAlreadyExists", args); + return; + } + } + if (!LLPresetsManager::getInstance()->savePreset(PRESETS_CAMERA, name)) + { + LLSD args; + args["NAME"] = name; + LLNotificationsUtil::add("PresetNotSaved", args); + } + } + + closeFloater(); +} + +void LLFloaterSaveCameraPreset::onPresetsListChange() +{ + LLPresetsManager::getInstance()->setPresetNamesInComboBox(PRESETS_CAMERA, mPresetCombo, DEFAULT_BOTTOM); +} + +void LLFloaterSaveCameraPreset::onBtnCancel() +{ + closeFloater(); +} + +void LLFloaterSaveCameraPreset::onSwitchSaveReplace() +{ + bool is_saving_new = mSaveRadioGroup->getSelectedIndex() == 0; + std::string label = is_saving_new ? getString("btn_label_save") : getString("btn_label_replace"); + mSaveButton->setLabel(label); + mNameEditor->setEnabled(is_saving_new); + mPresetCombo->setEnabled(!is_saving_new); + if (is_saving_new) + { + onPresetNameEdited(); + } + else + { + mSaveButton->setEnabled(true); + } +} diff --git a/indra/newview/llfloatersavecamerapreset.h b/indra/newview/llfloatersavecamerapreset.h new file mode 100644 index 0000000000000000000000000000000000000000..282f213438c7e0b91940941bafa1015d07864a02 --- /dev/null +++ b/indra/newview/llfloatersavecamerapreset.h @@ -0,0 +1,60 @@ +/** + * @file llfloatersavecamerapreset.h + * @brief Floater to save a camera preset + + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERSAVECAMERAPRESET_H +#define LL_LLFLOATERSAVECAMERAPRESET_H + +#include "llmodaldialog.h" + +class LLComboBox; +class LLRadioGroup; +class LLLineEditor; + +class LLFloaterSaveCameraPreset : public LLModalDialog +{ + +public: + LLFloaterSaveCameraPreset(const LLSD &key); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + void onBtnSave(); + void onBtnCancel(); + void onSwitchSaveReplace(); + +private: + LLRadioGroup* mSaveRadioGroup; + LLLineEditor* mNameEditor; + LLComboBox* mPresetCombo; + LLButton* mSaveButton; + + void onPresetsListChange(); + void onPresetNameEdited(); +}; + +#endif // LL_LLFLOATERSAVECAMERAPRESET_H diff --git a/indra/newview/llfloatersaveprefpreset.cpp b/indra/newview/llfloatersaveprefpreset.cpp index 684778c93ac8c1f31389eeaf9478aea19e1c2fef..5f3cf9d95bc195e53c0a066a59a20e9657a3d281 100644 --- a/indra/newview/llfloatersaveprefpreset.cpp +++ b/indra/newview/llfloatersaveprefpreset.cpp @@ -1,6 +1,6 @@ /** * @file llfloatersaveprefpreset.cpp - * @brief Floater to save a graphics / camera preset + * @brief Floater to save a graphics preset * * $LicenseInfo:firstyear=2014&license=viewerlgpl$ * Second Life Viewer Source Code @@ -37,24 +37,27 @@ #include "lltrans.h" LLFloaterSavePrefPreset::LLFloaterSavePrefPreset(const LLSD &key) -: LLFloater(key) + : LLFloater(key) { } // virtual BOOL LLFloaterSavePrefPreset::postBuild() -{ LLFloaterPreference* preferences = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); +{ + LLFloaterPreference* preferences = LLFloaterReg::getTypedInstance<LLFloaterPreference>("preferences"); if (preferences) { preferences->addDependentFloater(this); } + getChild<LLComboBox>("preset_combo")->setTextEntryCallback(boost::bind(&LLFloaterSavePrefPreset::onPresetNameEdited, this)); getChild<LLComboBox>("preset_combo")->setCommitCallback(boost::bind(&LLFloaterSavePrefPreset::onPresetNameEdited, this)); getChild<LLButton>("save")->setCommitCallback(boost::bind(&LLFloaterSavePrefPreset::onBtnSave, this)); + getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterSavePrefPreset::onBtnCancel, this)); LLPresetsManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterSavePrefPreset::onPresetsListChange, this)); - + mSaveButton = getChild<LLButton>("save"); mPresetCombo = getChild<LLComboBox>("preset_combo"); @@ -73,10 +76,6 @@ void LLFloaterSavePrefPreset::onOpen(const LLSD& key) { mSubdirectory = key.asString(); - std::string floater_title = getString(std::string("title_") + mSubdirectory); - - setTitle(floater_title); - EDefaultOptions option = DEFAULT_HIDE; LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, mPresetCombo, option); diff --git a/indra/newview/llfloatersaveprefpreset.h b/indra/newview/llfloatersaveprefpreset.h index 09a87b8c6296b7cb39fdec8b4953736eb19e03db..ae58180e7f46dbc1cc0a8c8f93f45b39ca911120 100644 --- a/indra/newview/llfloatersaveprefpreset.h +++ b/indra/newview/llfloatersaveprefpreset.h @@ -1,6 +1,6 @@ /** * @file llfloatersaveprefpreset.h - * @brief Floater to save a graphics / camera preset + * @brief Floater to save a graphics preset * * $LicenseInfo:firstyear=2014&license=viewerlgpl$ @@ -45,6 +45,7 @@ class LLFloaterSavePrefPreset : public LLFloater void onBtnCancel(); private: + LLComboBox* mPresetCombo; LLButton* mSaveButton; diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index fb202b4c406189156a8a0a86de2316aec649156e..186994c8571c118669aef4a2642e6cf55f4fd526 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -111,6 +111,7 @@ void LLFloaterSettingsDebug::onCommitSettings() LLVector3 vector; LLVector3d vectord; + LLQuaternion quat; LLRect rect; LLColor4 col4; LLColor3 col3; @@ -146,6 +147,13 @@ void LLFloaterSettingsDebug::onCommitSettings() vectord.mdV[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal(); controlp->set(vectord.getValue()); break; + case TYPE_QUAT: + quat.mQ[VX] = getChild<LLUICtrl>("val_spinner_1")->getValue().asReal(); + quat.mQ[VY] = getChild<LLUICtrl>("val_spinner_2")->getValue().asReal(); + quat.mQ[VZ] = getChild<LLUICtrl>("val_spinner_3")->getValue().asReal(); + quat.mQ[VS] = getChild<LLUICtrl>("val_spinner_4")->getValue().asReal();; + controlp->set(quat.getValue()); + break; case TYPE_RECT: rect.mLeft = getChild<LLUICtrl>("val_spinner_1")->getValue().asInteger(); rect.mRight = getChild<LLUICtrl>("val_spinner_2")->getValue().asInteger(); @@ -351,6 +359,40 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) } break; } + case TYPE_QUAT: + { + LLQuaternion q; + q.setValue(sd); + spinner1->setVisible(TRUE); + spinner1->setLabel(std::string("X")); + spinner2->setVisible(TRUE); + spinner2->setLabel(std::string("Y")); + spinner3->setVisible(TRUE); + spinner3->setLabel(std::string("Z")); + spinner4->setVisible(TRUE); + spinner4->setLabel(std::string("S")); + if (!spinner1->hasFocus()) + { + spinner1->setPrecision(4); + spinner1->setValue(q.mQ[VX]); + } + if (!spinner2->hasFocus()) + { + spinner2->setPrecision(4); + spinner2->setValue(q.mQ[VY]); + } + if (!spinner3->hasFocus()) + { + spinner3->setPrecision(4); + spinner3->setValue(q.mQ[VZ]); + } + if (!spinner4->hasFocus()) + { + spinner4->setPrecision(4); + spinner4->setValue(q.mQ[VS]); + } + break; + } case TYPE_RECT: { LLRect r; diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 7fcd6f4361c83f4eeabe918df98ab3ce807931ff..79fafade2d2489cefd87d6ebb70644315824ac11 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -37,6 +37,7 @@ #include "llui.h" #include "llagent.h" #include "llagentcamera.h" +#include "llviewercamera.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewerwindow.h" @@ -54,6 +55,8 @@ static LLDefaultChildRegistry::Register<LLJoystickQuaternion> r6("joystick_quat" const F32 NUDGE_TIME = 0.25f; // in seconds const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed +const S32 CENTER_DOT_RADIUS = 7; + // // Public Methods // @@ -138,9 +141,25 @@ bool LLJoystick::pointInCircle(S32 x, S32 y) const //center is x and y coordinates of center of joystick circle, and also its radius int center = this->getLocalRect().getHeight()/2; bool in_circle = (x - center) * (x - center) + (y - center) * (y - center) <= center * center; + return in_circle; } +bool LLJoystick::pointInCenterDot(S32 x, S32 y, S32 radius) const +{ + if (this->getLocalRect().getHeight() != this->getLocalRect().getWidth()) + { + LL_WARNS() << "Joystick shape is not square" << LL_ENDL; + return true; + } + + S32 center = this->getLocalRect().getHeight() / 2; + + bool in_center_circle = (x - center) * (x - center) + (y - center) * (y - center) <= radius * radius; + + return in_center_circle; +} + BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask) { //LL_INFOS() << "joystick mouse down " << x << ", " << y << LL_ENDL; @@ -403,8 +422,11 @@ LLJoystickCameraRotate::LLJoystickCameraRotate(const LLJoystickCameraRotate::Par mInLeft( FALSE ), mInTop( FALSE ), mInRight( FALSE ), - mInBottom( FALSE ) -{ } + mInBottom( FALSE ), + mInCenter( FALSE ) +{ + mCenterImageName = "Cam_Rotate_Center"; +} void LLJoystickCameraRotate::updateSlop() @@ -434,7 +456,16 @@ BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask) S32 dx = x - horiz_center; S32 dy = y - vert_center; - if (dy > dx && dy > -dx) + if (pointInCenterDot(x, y, CENTER_DOT_RADIUS)) + { + mInitialOffset.mX = 0; + mInitialOffset.mY = 0; + mInitialQuadrant = JQ_ORIGIN; + mInCenter = TRUE; + + resetJoystickCamera(); + } + else if (dy > dx && dy > -dx) { // top mInitialOffset.mX = 0; @@ -469,9 +500,20 @@ BOOL LLJoystickCameraRotate::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLJoystickCameraRotate::handleMouseUp(S32 x, S32 y, MASK mask) { gAgent.setMovementLocked(FALSE); + mInCenter = FALSE; return LLJoystick::handleMouseUp(x, y, mask); } +BOOL LLJoystickCameraRotate::handleHover(S32 x, S32 y, MASK mask) +{ + if (!pointInCenterDot(x, y, CENTER_DOT_RADIUS)) + { + mInCenter = FALSE; + } + + return LLJoystick::handleHover(x, y, mask); +} + void LLJoystickCameraRotate::onHeldDown() { updateSlop(); @@ -504,6 +546,11 @@ void LLJoystickCameraRotate::onHeldDown() } } +void LLJoystickCameraRotate::resetJoystickCamera() +{ + gAgentCamera.resetCameraOrbit(); +} + F32 LLJoystickCameraRotate::getOrbitRate() { F32 time = getElapsedHeldDownTime(); @@ -536,24 +583,31 @@ void LLJoystickCameraRotate::draw() getImageUnselected()->draw( 0, 0 ); LLPointer<LLUIImage> image = getImageSelected(); - if( mInTop ) + if (mInCenter) { - drawRotatedImage( getImageSelected(), 0 ); + drawRotatedImage(LLUI::getUIImage(mCenterImageName), 0); } - - if( mInRight ) + else { - drawRotatedImage( getImageSelected(), 1 ); - } + if (mInTop) + { + drawRotatedImage(getImageSelected(), 0); + } - if( mInBottom ) - { - drawRotatedImage( getImageSelected(), 2 ); - } + if (mInRight) + { + drawRotatedImage(getImageSelected(), 1); + } - if( mInLeft ) - { - drawRotatedImage( getImageSelected(), 3 ); + if (mInBottom) + { + drawRotatedImage(getImageSelected(), 2); + } + + if (mInLeft) + { + drawRotatedImage(getImageSelected(), 3); + } } } @@ -613,7 +667,9 @@ LLJoystickCameraTrack::Params::Params() LLJoystickCameraTrack::LLJoystickCameraTrack(const LLJoystickCameraTrack::Params& p) : LLJoystickCameraRotate(p) -{} +{ + mCenterImageName = "Cam_Tracking_Center"; +} void LLJoystickCameraTrack::onHeldDown() @@ -647,6 +703,11 @@ void LLJoystickCameraTrack::onHeldDown() } } +void LLJoystickCameraTrack::resetJoystickCamera() +{ + gAgentCamera.resetCameraPan(); +} + //------------------------------------------------------------------------------- // LLJoystickQuaternion //------------------------------------------------------------------------------- diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index ee66088b560e77aa1275438263a7f545f5b669e5..b7fdf63e583b4f61e525c5e2b79146053bc134d5 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -80,7 +80,8 @@ class LLJoystick * Image containing circle is square and this square has adherent points with joystick * circle. Make sure to change method according to shape other than square. */ - bool pointInCircle(S32 x, S32 y) const; + bool pointInCircle(S32 x, S32 y) const; + bool pointInCenterDot(S32 x, S32 y, S32 radius) const; static std::string nameFromQuadrant(const EJoystickQuadrant quadrant); static EJoystickQuadrant quadrantFromName(const std::string& name); @@ -148,7 +149,9 @@ class LLJoystickCameraRotate virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual void onHeldDown(); + virtual void resetJoystickCamera(); virtual void draw(); protected: @@ -161,6 +164,9 @@ class LLJoystickCameraRotate BOOL mInTop; BOOL mInRight; BOOL mInBottom; + BOOL mInCenter; + + std::string mCenterImageName; }; @@ -177,6 +183,7 @@ class LLJoystickCameraTrack LLJoystickCameraTrack(const LLJoystickCameraTrack::Params&); virtual void onHeldDown(); + virtual void resetJoystickCamera(); }; // diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index b654e928e2effb2ae4cd04f0c10a71d648bab450..02911313ed41784d3fd020f08a552c560498ea23 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -66,9 +66,6 @@ extern LLControlGroup gSavedSettings; static const LLUUID PARCEL_MEDIA_LIST_ITEM_UUID = LLUUID("CAB5920F-E484-4233-8621-384CF373A321"); static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5D-CA970D694822"); -const F32 AUTO_CLOSE_FADE_TIME_START= 2.0f; -const F32 AUTO_CLOSE_FADE_TIME_END = 3.0f; - // // LLPanelNearByMedia // @@ -82,8 +79,6 @@ LLPanelNearByMedia::LLPanelNearByMedia() mParcelMediaItem(NULL), mParcelAudioItem(NULL) { - mHoverTimer.stop(); - // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 && gSavedSettings.getBOOL("MediaTentativeAutoPlay"); @@ -111,7 +106,7 @@ LLPanelNearByMedia::~LLPanelNearByMedia() BOOL LLPanelNearByMedia::postBuild() { - LLPanel::postBuild(); + LLPanelPulldown::postBuild(); const S32 RESIZE_BAR_THICKNESS = 6; LLResizeBar::Params p; @@ -193,45 +188,10 @@ void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) inst->cancelNotification(); } -/*virtual*/ -void LLPanelNearByMedia::onMouseEnter(S32 x, S32 y, MASK mask) -{ - mHoverTimer.stop(); - LLPanel::onMouseEnter(x,y,mask); -} - - -/*virtual*/ -void LLPanelNearByMedia::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mHoverTimer.start(); - LLPanel::onMouseLeave(x,y,mask); -} - -/*virtual*/ -void LLPanelNearByMedia::onTopLost() -{ - setVisible(FALSE); -} - - -/*virtual*/ -void LLPanelNearByMedia::onVisibilityChange ( BOOL new_visibility ) -{ - if (new_visibility) - { - mHoverTimer.start(); // timer will be stopped when mouse hovers over panel - } - else - { - mHoverTimer.stop(); - } -} - /*virtual*/ void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent) { - LLPanel::reshape(width, height, called_from_parent); + LLPanelPulldown::reshape(width, height, called_from_parent); LLButton* more_btn = findChild<LLButton>("more_btn"); if (more_btn && more_btn->getValue().asBoolean()) @@ -255,24 +215,14 @@ void LLPanelNearByMedia::draw() refreshList(); updateControls(); - - F32 alpha = mHoverTimer.getStarted() - ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), AUTO_CLOSE_FADE_TIME_START, AUTO_CLOSE_FADE_TIME_END, 1.f, 0.f) - : 1.0f; - LLViewDrawContext context(alpha); - LLPanel::draw(); - - if (alpha == 0.f) - { - setVisible(false); - } + LLPanelPulldown::draw(); } /*virtual*/ BOOL LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) { - LLPanel::handleHover(x, y, mask); + LLPanelPulldown::handleHover(x, y, mask); // If we are hovering over this panel, make sure to clear any hovered media // ID. Note that the more general solution would be to clear this ID when diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h index a9c1b190cfb1ae0c6f7cde07c0d7648bd087ad30..2d898d0aa1e08f8a8a788b03dbac336fb3d761bf 100644 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -27,7 +27,7 @@ #ifndef LL_LLPANELNEARBYMEDIA_H #define LL_LLPANELNEARBYMEDIA_H -#include "llpanel.h" +#include "llpanelpulldown.h" class LLPanelNearbyMedia; class LLButton; @@ -39,16 +39,12 @@ class LLTextBox; class LLComboBox; class LLViewerMediaImpl; -class LLPanelNearByMedia : public LLPanel +class LLPanelNearByMedia : public LLPanelPulldown { public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); - /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ void onTopLost(); - /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); @@ -173,7 +169,6 @@ class LLPanelNearByMedia : public LLPanel LLRect mMoreRect; LLRect mLessRect; - LLFrameTimer mHoverTimer; LLScrollListItem* mParcelMediaItem; LLScrollListItem* mParcelAudioItem; }; diff --git a/indra/newview/llpanelpresetscamerapulldown.cpp b/indra/newview/llpanelpresetscamerapulldown.cpp new file mode 100644 index 0000000000000000000000000000000000000000..183123e534e8a333472d94117ae9475e3d203c12 --- /dev/null +++ b/indra/newview/llpanelpresetscamerapulldown.cpp @@ -0,0 +1,149 @@ +/** + * @file llpanelpresetscamerapulldown.cpp + * @brief A panel showing a quick way to pick camera presets + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelpresetscamerapulldown.h" + +#include "llviewercontrol.h" +#include "llstatusbar.h" + +#include "llbutton.h" +#include "lltabcontainer.h" +#include "llfloatercamera.h" +#include "llfloaterreg.h" +#include "llfloaterpreference.h" +#include "llpresetsmanager.h" +#include "llsliderctrl.h" +#include "llscrolllistctrl.h" +#include "lltrans.h" + +///---------------------------------------------------------------------------- +/// Class LLPanelPresetsCameraPulldown +///---------------------------------------------------------------------------- + +// Default constructor +LLPanelPresetsCameraPulldown::LLPanelPresetsCameraPulldown() +{ + mCommitCallbackRegistrar.add("Presets.toggleCameraFloater", boost::bind(&LLPanelPresetsCameraPulldown::onViewButtonClick, this, _2)); + mCommitCallbackRegistrar.add("PresetsCamera.RowClick", boost::bind(&LLPanelPresetsCameraPulldown::onRowClick, this, _2)); + + buildFromFile( "panel_presets_camera_pulldown.xml"); +} + +BOOL LLPanelPresetsCameraPulldown::postBuild() +{ + LLPresetsManager* presetsMgr = LLPresetsManager::getInstance(); + if (presetsMgr) + { + // Make sure there is a default preference file + presetsMgr->createMissingDefault(PRESETS_CAMERA); + + presetsMgr->startWatching(PRESETS_CAMERA); + + presetsMgr->setPresetListChangeCameraCallback(boost::bind(&LLPanelPresetsCameraPulldown::populatePanel, this)); + } + + populatePanel(); + + return LLPanelPulldown::postBuild(); +} + +void LLPanelPresetsCameraPulldown::populatePanel() +{ + LLPresetsManager::getInstance()->loadPresetNamesFromDir(PRESETS_CAMERA, mPresetNames, DEFAULT_BOTTOM); + + LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("preset_camera_list"); + + if (scroll && mPresetNames.begin() != mPresetNames.end()) + { + scroll->clearRows(); + + std::string active_preset = gSavedSettings.getString("PresetCameraActive"); + if (active_preset == PRESETS_DEFAULT) + { + active_preset = LLTrans::getString(PRESETS_DEFAULT); + } + + for (std::list<std::string>::const_iterator it = mPresetNames.begin(); it != mPresetNames.end(); ++it) + { + const std::string& name = *it; + LL_DEBUGS() << "adding '" << name << "'" << LL_ENDL; + + LLSD row; + row["columns"][0]["column"] = "preset_name"; + row["columns"][0]["value"] = name; + + bool is_selected_preset = false; + if (name == active_preset) + { + row["columns"][1]["column"] = "icon"; + row["columns"][1]["type"] = "icon"; + row["columns"][1]["value"] = "Check_Mark"; + + is_selected_preset = true; + } + + LLScrollListItem* new_item = scroll->addElement(row); + new_item->setSelected(is_selected_preset); + } + } +} + +void LLPanelPresetsCameraPulldown::onRowClick(const LLSD& user_data) +{ + LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("preset_camera_list"); + + if (scroll) + { + LLScrollListItem* item = scroll->getFirstSelected(); + if (item) + { + std::string name = item->getColumn(1)->getValue().asString(); + + LL_DEBUGS() << "selected '" << name << "'" << LL_ENDL; + LLFloaterCamera::switchToPreset(name); + + setVisible(FALSE); + } + else + { + LL_DEBUGS() << "none selected" << LL_ENDL; + } + } + else + { + LL_DEBUGS() << "no scroll" << LL_ENDL; + } +} + +void LLPanelPresetsCameraPulldown::onViewButtonClick(const LLSD& user_data) +{ + // close the minicontrol, we're bringing up the big one + setVisible(FALSE); + + LLFloaterReg::toggleInstanceOrBringToFront("camera"); +} diff --git a/indra/newview/llpanelpresetscamerapulldown.h b/indra/newview/llpanelpresetscamerapulldown.h new file mode 100644 index 0000000000000000000000000000000000000000..c49bab042e22d8ba89871471865c7b7a53d10b0d --- /dev/null +++ b/indra/newview/llpanelpresetscamerapulldown.h @@ -0,0 +1,49 @@ +/** + * @file llpanelpresetscamerapulldown.h + * @brief A panel showing a quick way to pick camera presets + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELPRESETSCAMERAPULLDOWN_H +#define LL_LLPANELPRESETSCAMERAPULLDOWN_H + +#include "linden_common.h" + +#include "llpanelpulldown.h" + +class LLPanelPresetsCameraPulldown : public LLPanelPulldown +{ + public: + LLPanelPresetsCameraPulldown(); + /*virtual*/ BOOL postBuild(); + void populatePanel(); + + private: + void onViewButtonClick(const LLSD& user_data); + void onRowClick(const LLSD& user_data); + + std::list<std::string> mPresetNames; + LOG_CLASS(LLPanelPresetsCameraPulldown); +}; + +#endif // LL_LLPANELPRESETSCAMERAPULLDOWN_H diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp index 9b4dc5474a08e644ed0121935862e91ebb848958..aa5ba3f210ea5ccef5052e366ec59db0a6b6d934 100644 --- a/indra/newview/llpanelpresetspulldown.cpp +++ b/indra/newview/llpanelpresetspulldown.cpp @@ -40,9 +40,6 @@ #include "llscrolllistctrl.h" #include "lltrans.h" -/* static */ const F32 LLPanelPresetsPulldown::sAutoCloseFadeStartTimeSec = 2.0f; -/* static */ const F32 LLPanelPresetsPulldown::sAutoCloseTotalTimeSec = 3.0f; - ///---------------------------------------------------------------------------- /// Class LLPanelPresetsPulldown ///---------------------------------------------------------------------------- @@ -63,17 +60,16 @@ BOOL LLPanelPresetsPulldown::postBuild() LLPresetsManager* presetsMgr = LLPresetsManager::getInstance(); presetsMgr->setPresetListChangeCallback(boost::bind(&LLPanelPresetsPulldown::populatePanel, this)); // Make sure there is a default preference file - presetsMgr->createMissingDefault(); + presetsMgr->createMissingDefault(PRESETS_GRAPHIC); populatePanel(); - return LLPanel::postBuild(); + return LLPanelPulldown::postBuild(); } void LLPanelPresetsPulldown::populatePanel() { - std::string presets_dir = LLPresetsManager::getInstance()->getPresetsDir(PRESETS_GRAPHIC); - LLPresetsManager::getInstance()->loadPresetNamesFromDir(presets_dir, mPresetNames, DEFAULT_TOP); + LLPresetsManager::getInstance()->loadPresetNamesFromDir(PRESETS_GRAPHIC, mPresetNames, DEFAULT_TOP); LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("preset_list"); @@ -112,61 +108,6 @@ void LLPanelPresetsPulldown::populatePanel() } } -/*virtual*/ -void LLPanelPresetsPulldown::onMouseEnter(S32 x, S32 y, MASK mask) -{ - mHoverTimer.stop(); - LLPanel::onMouseEnter(x,y,mask); -} - -/*virtual*/ -void LLPanelPresetsPulldown::onTopLost() -{ - setVisible(FALSE); -} - -/*virtual*/ -BOOL LLPanelPresetsPulldown::handleMouseDown(S32 x, S32 y, MASK mask) -{ - LLPanel::handleMouseDown(x,y,mask); - return TRUE; -} - -/*virtual*/ -BOOL LLPanelPresetsPulldown::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - LLPanel::handleRightMouseDown(x, y, mask); - return TRUE; -} - -/*virtual*/ -BOOL LLPanelPresetsPulldown::handleDoubleClick(S32 x, S32 y, MASK mask) -{ - LLPanel::handleDoubleClick(x, y, mask); - return TRUE; -} - -/*virtual*/ -void LLPanelPresetsPulldown::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mHoverTimer.start(); - LLPanel::onMouseLeave(x,y,mask); -} - -/*virtual*/ -void LLPanelPresetsPulldown::onVisibilityChange ( BOOL new_visibility ) -{ - if (new_visibility) - { - mHoverTimer.start(); // timer will be stopped when mouse hovers over panel - } - else - { - mHoverTimer.stop(); - - } -} - void LLPanelPresetsPulldown::onRowClick(const LLSD& user_data) { LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("preset_list"); @@ -213,19 +154,3 @@ void LLPanelPresetsPulldown::onGraphicsButtonClick(const LLSD& user_data) } } } - -//virtual -void LLPanelPresetsPulldown::draw() -{ - F32 alpha = mHoverTimer.getStarted() - ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), sAutoCloseFadeStartTimeSec, sAutoCloseTotalTimeSec, 1.f, 0.f) - : 1.0f; - LLViewDrawContext context(alpha); - - LLPanel::draw(); - - if (alpha == 0.f) - { - setVisible(FALSE); - } -} diff --git a/indra/newview/llpanelpresetspulldown.h b/indra/newview/llpanelpresetspulldown.h index 322bf5a58f5414bf54624677d3d6d7aae825daa3..c0d32b9b21a4df5300efc26c9cf24f19ece191fb 100644 --- a/indra/newview/llpanelpresetspulldown.h +++ b/indra/newview/llpanelpresetspulldown.h @@ -29,22 +29,13 @@ #include "linden_common.h" -#include "llpanel.h" +#include "llpanelpulldown.h" -class LLFrameTimer; -class LLPanelPresetsPulldown : public LLPanel +class LLPanelPresetsPulldown : public LLPanelPulldown { public: LLPanelPresetsPulldown(); - /*virtual*/ void draw(); - /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ void onTopLost(); - /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); /*virtual*/ BOOL postBuild(); void populatePanel(); @@ -53,9 +44,6 @@ class LLPanelPresetsPulldown : public LLPanel void onRowClick(const LLSD& user_data); std::list<std::string> mPresetNames; - LLFrameTimer mHoverTimer; - static const F32 sAutoCloseFadeStartTimeSec; - static const F32 sAutoCloseTotalTimeSec; LOG_CLASS(LLPanelPresetsPulldown); }; diff --git a/indra/newview/llpanelpulldown.cpp b/indra/newview/llpanelpulldown.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4de6ee81829eadd0910a13d049d02035a70bbbba --- /dev/null +++ b/indra/newview/llpanelpulldown.cpp @@ -0,0 +1,118 @@ +/** +* @file llpanelpulldown.cpp +* @brief A panel that serves as a basis for multiple toolbar pulldown panels +* +* $LicenseInfo:firstyear=2020&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2020, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelpulldown.h" + +const F32 AUTO_CLOSE_FADE_TIME_START_SEC = 2.0f; +const F32 AUTO_CLOSE_FADE_TIME_END_SEC = 3.0f; + +///---------------------------------------------------------------------------- +/// Class LLPanelPresetsCameraPulldown +///---------------------------------------------------------------------------- + +// Default constructor +LLPanelPulldown::LLPanelPulldown() +{ + mHoverTimer.stop(); +} + +/*virtual*/ +void LLPanelPulldown::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mHoverTimer.stop(); + LLPanel::onMouseEnter(x, y, mask); +} + +/*virtual*/ +void LLPanelPulldown::onTopLost() +{ + setVisible(FALSE); +} + +/*virtual*/ +BOOL LLPanelPulldown::handleMouseDown(S32 x, S32 y, MASK mask) +{ + LLPanel::handleMouseDown(x, y, mask); + return TRUE; +} + +/*virtual*/ +BOOL LLPanelPulldown::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + LLPanel::handleRightMouseDown(x, y, mask); + return TRUE; +} + +/*virtual*/ +BOOL LLPanelPulldown::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + LLPanel::handleDoubleClick(x, y, mask); + return TRUE; +} + +BOOL LLPanelPulldown::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + LLPanel::handleScrollWheel(x, y, clicks); + return TRUE; //If we got here, then we are in Pulldown's rect, consume the event. +} + +/*virtual*/ +void LLPanelPulldown::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mHoverTimer.start(); + LLPanel::onMouseLeave(x, y, mask); +} + +/*virtual*/ +void LLPanelPulldown::onVisibilityChange(BOOL new_visibility) +{ + if (new_visibility) + { + mHoverTimer.start(); // timer will be stopped when mouse hovers over panel + } + else + { + mHoverTimer.stop(); + } +} + +//virtual +void LLPanelPulldown::draw() +{ + F32 alpha = mHoverTimer.getStarted() + ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), AUTO_CLOSE_FADE_TIME_START_SEC, AUTO_CLOSE_FADE_TIME_END_SEC, 1.f, 0.f) + : 1.0f; + LLViewDrawContext context(alpha); + + LLPanel::draw(); + + if (alpha == 0.f) + { + setVisible(FALSE); + } +} diff --git a/indra/newview/llpanelpulldown.h b/indra/newview/llpanelpulldown.h new file mode 100644 index 0000000000000000000000000000000000000000..705e76d0ab2556771806218d07aa790b731b429b --- /dev/null +++ b/indra/newview/llpanelpulldown.h @@ -0,0 +1,55 @@ +/** + * @file llpanelpulldown.h + * @brief A panel that serves as a basis for multiple toolbar pulldown panels + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELPULLDOWN_H +#define LL_LLPANELPULLDOWN_H + +#include "linden_common.h" + +#include "llpanel.h" + +class LLFrameTimer; + +class LLPanelPulldown : public LLPanel +{ +public: + LLPanelPulldown(); + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + /*virtual*/ void onTopLost(); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); + + /*virtual*/ void draw(); + +protected: + LLFrameTimer mHoverTimer; +}; + +#endif // LL_LLPANELPULLDOWN_H diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp index f063d8427283b670a1f732f8691b9947e3040de3..6f11e76a72d304fa5923bd5fcf20371ac5a04552 100644 --- a/indra/newview/llpanelvolumepulldown.cpp +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -41,9 +41,6 @@ #include "llfloaterpreference.h" #include "llsliderctrl.h" -/* static */ const F32 LLPanelVolumePulldown::sAutoCloseFadeStartTimeSec = 2.0f; -/* static */ const F32 LLPanelVolumePulldown::sAutoCloseTotalTimeSec = 3.0f; - ///---------------------------------------------------------------------------- /// Class LLPanelVolumePulldown ///---------------------------------------------------------------------------- @@ -51,8 +48,6 @@ // Default constructor LLPanelVolumePulldown::LLPanelVolumePulldown() { - mHoverTimer.stop(); - mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this)); mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1)); @@ -62,41 +57,7 @@ LLPanelVolumePulldown::LLPanelVolumePulldown() BOOL LLPanelVolumePulldown::postBuild() { - return LLPanel::postBuild(); -} - -/*virtual*/ -void LLPanelVolumePulldown::onMouseEnter(S32 x, S32 y, MASK mask) -{ - mHoverTimer.stop(); - LLPanel::onMouseEnter(x,y,mask); -} - -/*virtual*/ -void LLPanelVolumePulldown::onTopLost() -{ - setVisible(FALSE); -} - -/*virtual*/ -void LLPanelVolumePulldown::onMouseLeave(S32 x, S32 y, MASK mask) -{ - mHoverTimer.start(); - LLPanel::onMouseLeave(x,y,mask); -} - -/*virtual*/ -void LLPanelVolumePulldown::onVisibilityChange ( BOOL new_visibility ) -{ - if (new_visibility) - { - mHoverTimer.start(); // timer will be stopped when mouse hovers over panel - } - else - { - mHoverTimer.stop(); - - } + return LLPanelPulldown::postBuild(); } void LLPanelVolumePulldown::onAdvancedButtonClick(const LLSD& user_data) @@ -150,20 +111,3 @@ void LLPanelVolumePulldown::onClickSetSounds() // or if sound effects are disabled. getChild<LLCheckBoxCtrl>("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds")); } - -//virtual -void LLPanelVolumePulldown::draw() -{ - F32 alpha = mHoverTimer.getStarted() - ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), sAutoCloseFadeStartTimeSec, sAutoCloseTotalTimeSec, 1.f, 0.f) - : 1.0f; - LLViewDrawContext context(alpha); - - LLPanel::draw(); - - if (alpha == 0.f) - { - setVisible(FALSE); - } -} - diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h index 4f23112f5000112a43a4206dd7679cb35201237f..e907bb0c78fa36dbd4623c8187a14bc39d2e0799 100644 --- a/indra/newview/llpanelvolumepulldown.h +++ b/indra/newview/llpanelvolumepulldown.h @@ -30,19 +30,12 @@ #include "linden_common.h" -#include "llpanel.h" +#include "llpanelpulldown.h" -class LLFrameTimer; - -class LLPanelVolumePulldown : public LLPanel +class LLPanelVolumePulldown : public LLPanelPulldown { public: LLPanelVolumePulldown(); - /*virtual*/ void draw(); - /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ void onTopLost(); - /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); /*virtual*/ BOOL postBuild(); private: @@ -52,10 +45,6 @@ class LLPanelVolumePulldown : public LLPanel // "Streaming Music" and "Media" are unchecked. Otherwise enables it. void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl); void onAdvancedButtonClick(const LLSD& user_data); - - LLFrameTimer mHoverTimer; - static const F32 sAutoCloseFadeStartTimeSec; - static const F32 sAutoCloseTotalTimeSec; }; diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index df93572508283b925c5caf22388adbd6a764dc7f..c267c3c699520752b8d15dfc8453a153fec088dc 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -39,6 +39,8 @@ #include "llfloaterpreference.h" #include "llfloaterreg.h" #include "llfeaturemanager.h" +#include "llagentcamera.h" +#include "llfile.h" LLPresetsManager::LLPresetsManager() { @@ -46,6 +48,12 @@ LLPresetsManager::LLPresetsManager() LLPresetsManager::~LLPresetsManager() { + mCameraChangedSignal.disconnect(); +} + +void LLPresetsManager::triggerChangeCameraSignal() +{ + mPresetListChangeCameraSignal(); } void LLPresetsManager::triggerChangeSignal() @@ -53,41 +61,92 @@ void LLPresetsManager::triggerChangeSignal() mPresetListChangeSignal(); } -void LLPresetsManager::createMissingDefault() +void LLPresetsManager::createMissingDefault(const std::string& subdirectory) { if(gDirUtilp->getLindenUserDir().empty()) { return; } - std::string default_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, PRESETS_GRAPHIC, PRESETS_DEFAULT + ".xml"); + + if (PRESETS_CAMERA == subdirectory) + { + createCameraDefaultPresets(); + return; + } + + std::string default_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, + subdirectory, PRESETS_DEFAULT + ".xml"); if (!gDirUtilp->fileExists(default_file)) { LL_INFOS() << "No default preset found -- creating one at " << default_file << LL_ENDL; - // Write current graphic settings as the default - savePreset(PRESETS_GRAPHIC, PRESETS_DEFAULT, true); + // Write current settings as the default + savePreset(subdirectory, PRESETS_DEFAULT, true); + } + else + { + LL_DEBUGS() << "default preset exists; no-op" << LL_ENDL; + } +} + +void LLPresetsManager::createCameraDefaultPresets() +{ + bool is_default_created = createDefaultCameraPreset(PRESETS_REAR_VIEW); + is_default_created |= createDefaultCameraPreset(PRESETS_FRONT_VIEW); + is_default_created |= createDefaultCameraPreset(PRESETS_SIDE_VIEW); + + if (is_default_created) + { + triggerChangeCameraSignal(); + } +} + +void LLPresetsManager::startWatching(const std::string& subdirectory) +{ + if (PRESETS_CAMERA == subdirectory) + { + std::vector<std::string> name_list; + getControlNames(name_list); + + for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) + { + std::string ctrl_name = *it; + if (gSavedSettings.controlExists(ctrl_name)) + { + LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(ctrl_name); + if (cntrl_ptr.isNull()) + { + LL_WARNS("Init") << "Unable to set signal on global setting '" << ctrl_name + << "'" << LL_ENDL; + } + else + { + mCameraChangedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&settingChanged)); + } + } + } } - else - { - LL_DEBUGS() << "default preset exists; no-op" << LL_ENDL; - } } std::string LLPresetsManager::getPresetsDir(const std::string& subdirectory) { std::string presets_path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR); - std::string full_path; LLFile::mkdir(presets_path); - full_path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, subdirectory); - LLFile::mkdir(full_path); + std::string dest_path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, subdirectory); + if (!gDirUtilp->fileExists(dest_path)) + LLFile::mkdir(dest_path); - return full_path; + return dest_path; } -void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_name_list_t& presets, EDefaultOptions default_option) +void LLPresetsManager::loadPresetNamesFromDir(const std::string& subdirectory, preset_name_list_t& presets, EDefaultOptions default_option) { + bool IS_CAMERA = (PRESETS_CAMERA == subdirectory); + bool IS_GRAPHIC = (PRESETS_GRAPHIC == subdirectory); + + std::string dir = LLPresetsManager::getInstance()->getPresetsDir(subdirectory); LL_INFOS("AppInit") << "Loading list of preset names from " << dir << LL_ENDL; mPresetNames.clear(); @@ -103,16 +162,33 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam { std::string path = gDirUtilp->add(dir, file); std::string name = LLURI::unescape(gDirUtilp->getBaseFileName(path, /*strip_exten = */ true)); - LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL; + LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL; - if (PRESETS_DEFAULT != name) + if (IS_CAMERA) { + if (isTemplateCameraPreset(name)) + { + continue; + } + if ((default_option == DEFAULT_HIDE) || (default_option == DEFAULT_BOTTOM)) + { + if (isDefaultCameraPreset(name)) + { + continue; + } + } mPresetNames.push_back(name); } - else + if (IS_GRAPHIC) { - switch (default_option) + if (PRESETS_DEFAULT != name) { + mPresetNames.push_back(name); + } + else + { + switch (default_option) + { case DEFAULT_SHOW: mPresetNames.push_back(LLTrans::getString(PRESETS_DEFAULT)); break; @@ -124,16 +200,77 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam case DEFAULT_HIDE: default: break; + } } } } } + if (IS_CAMERA) + { + mPresetNames.sort(LLStringUtil::precedesDict); + if (default_option == DEFAULT_BOTTOM) + { + mPresetNames.push_back(PRESETS_FRONT_VIEW); + mPresetNames.push_back(PRESETS_REAR_VIEW); + mPresetNames.push_back(PRESETS_SIDE_VIEW); + } + } + presets = mPresetNames; } +bool LLPresetsManager::mCameraDirty = false; +bool LLPresetsManager::mIgnoreChangedSignal = false; + +void LLPresetsManager::setCameraDirty(bool dirty) +{ + mCameraDirty = dirty; +} + +bool LLPresetsManager::isCameraDirty() +{ + return mCameraDirty; +} + +void LLPresetsManager::settingChanged() +{ + setCameraDirty(true); + + static LLCachedControl<std::string> preset_camera_active(gSavedSettings, "PresetCameraActive", ""); + std::string preset_name = preset_camera_active; + if (!preset_name.empty() && !mIgnoreChangedSignal) + { + gSavedSettings.setString("PresetCameraActive", ""); + + // Hack call because this is a static routine + LLPresetsManager::getInstance()->triggerChangeCameraSignal(); + } +} + +void LLPresetsManager::getControlNames(std::vector<std::string>& names) +{ + const std::vector<std::string> camera_controls = boost::assign::list_of + // From panel_preferences_move.xml + ("CameraAngle") + ("CameraOffsetScale") + ("EditCameraMovement") + ("AppearanceCameraMovement") + // From llagentcamera.cpp + ("CameraOffsetBuild") + ("TrackFocusObject") + ("CameraOffsetRearView") + ("FocusOffsetRearView") + ("AvatarSitRotation") + ; + names = camera_controls; +} + bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string name, bool createDefault) { + bool IS_CAMERA = (PRESETS_CAMERA == subdirectory); + bool IS_GRAPHIC = (PRESETS_GRAPHIC == subdirectory); + if (LLTrans::getString(PRESETS_DEFAULT) == name) { name = PRESETS_DEFAULT; @@ -144,126 +281,174 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n return false; } + if (isTemplateCameraPreset(name)) + { + LL_WARNS() << "Should not overwrite template presets" << LL_ENDL; + return false; + } + bool saved = false; std::vector<std::string> name_list; - if(PRESETS_GRAPHIC == subdirectory) + if (IS_GRAPHIC) { LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); if (instance && !createDefault) { - gSavedSettings.setString("PresetGraphicActive", name); + gSavedSettings.setString("PresetGraphicActive", name); instance->getControlNames(name_list); - LL_DEBUGS() << "saving preset '" << name << "'; " << name_list.size() << " names" << LL_ENDL; + LL_DEBUGS() << "saving preset '" << name << "'; " << name_list.size() << " names" << LL_ENDL; name_list.push_back("PresetGraphicActive"); } - else + else { - LL_WARNS() << "preferences floater instance not found" << LL_ENDL; - } + LL_WARNS("Presets") << "preferences floater instance not found" << LL_ENDL; + } } - else if(PRESETS_CAMERA == subdirectory) + else if (IS_CAMERA) { name_list.clear(); - name_list.push_back("Placeholder"); + getControlNames(name_list); + name_list.push_back("PresetCameraActive"); } - else - { - LL_ERRS() << "Invalid presets directory '" << subdirectory << "'" << LL_ENDL; - } - - if (name_list.size() > 1 // if the active preset name is the only thing in the list, don't save the list - || (createDefault && name == PRESETS_DEFAULT && subdirectory == PRESETS_GRAPHIC)) // or create a default graphics preset from hw recommended settings - { - // make an empty llsd - LLSD paramsData(LLSD::emptyMap()); + else + { + LL_ERRS() << "Invalid presets directory '" << subdirectory << "'" << LL_ENDL; + } + + // make an empty llsd + LLSD paramsData(LLSD::emptyMap()); - if (createDefault) - { - paramsData = LLFeatureManager::getInstance()->getRecommendedSettingsMap(); - if (gSavedSettings.getU32("RenderAvatarMaxComplexity") == 0) - { - // use the recommended setting as an initial one (MAINT-6435) - gSavedSettings.setU32("RenderAvatarMaxComplexity", paramsData["RenderAvatarMaxComplexity"]["Value"].asInteger()); - } - } - else - { - for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) - { - std::string ctrl_name = *it; - LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get(); - std::string comment = ctrl->getComment(); - std::string type = LLControlGroup::typeEnumToString(ctrl->type()); - LLSD value = ctrl->getValue(); - - paramsData[ctrl_name]["Comment"] = comment; - paramsData[ctrl_name]["Persist"] = 1; - paramsData[ctrl_name]["Type"] = type; - paramsData[ctrl_name]["Value"] = value; - } - } - - std::string pathName(getPresetsDir(subdirectory) + gDirUtilp->getDirDelimiter() + LLURI::escape(name) + ".xml"); - - // write to file - llofstream presetsXML(pathName.c_str()); - if (presetsXML.is_open()) - { - - LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); - formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY); - presetsXML.close(); - saved = true; + // Create a default graphics preset from hw recommended settings + if (IS_GRAPHIC && createDefault && name == PRESETS_DEFAULT) + { + paramsData = LLFeatureManager::getInstance()->getRecommendedSettingsMap(); + if (gSavedSettings.getU32("RenderAvatarMaxComplexity") == 0) + { + // use the recommended setting as an initial one (MAINT-6435) + gSavedSettings.setU32("RenderAvatarMaxComplexity", paramsData["RenderAvatarMaxComplexity"]["Value"].asInteger()); + } + } + else + { + ECameraPreset new_camera_preset = (ECameraPreset)gSavedSettings.getU32("CameraPresetType"); + bool new_camera_offsets = false; + if (IS_CAMERA) + { + if (isDefaultCameraPreset(name)) + { + if (PRESETS_REAR_VIEW == name) + { + new_camera_preset = CAMERA_PRESET_REAR_VIEW; + } + else if (PRESETS_SIDE_VIEW == name) + { + new_camera_preset = CAMERA_PRESET_GROUP_VIEW; + } + else if (PRESETS_FRONT_VIEW == name) + { + new_camera_preset = CAMERA_PRESET_FRONT_VIEW; + } + } + else + { + new_camera_preset = CAMERA_PRESET_CUSTOM; + } + new_camera_offsets = (!isDefaultCameraPreset(name) || (ECameraPreset)gSavedSettings.getU32("CameraPresetType") != new_camera_preset); + } + for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) + { + std::string ctrl_name = *it; + + LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get(); + if (ctrl) + { + std::string comment = ctrl->getComment(); + std::string type = LLControlGroup::typeEnumToString(ctrl->type()); + LLSD value = ctrl->getValue(); + + paramsData[ctrl_name]["Comment"] = comment; + paramsData[ctrl_name]["Persist"] = 1; + paramsData[ctrl_name]["Type"] = type; + paramsData[ctrl_name]["Value"] = value; + } + } + if (IS_CAMERA) + { + gSavedSettings.setU32("CameraPresetType", new_camera_preset); + } + } + + std::string pathName(getPresetsDir(subdirectory) + gDirUtilp->getDirDelimiter() + LLURI::escape(name) + ".xml"); + + // If the active preset name is the only thing in the list, don't save the list + if (paramsData.size() > 1) + { + // write to file + llofstream presetsXML(pathName.c_str()); + if (presetsXML.is_open()) + { + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY); + presetsXML.close(); + saved = true; - LL_DEBUGS() << "saved preset '" << name << "'; " << paramsData.size() << " parameters" << LL_ENDL; - - if (!createDefault) - { - gSavedSettings.setString("PresetGraphicActive", name); - // signal interested parties - triggerChangeSignal(); - } - } - else - { - LL_WARNS("Presets") << "Cannot open for output preset file " << pathName << LL_ENDL; - } - } + LL_DEBUGS() << "saved preset '" << name << "'; " << paramsData.size() << " parameters" << LL_ENDL; + + if (IS_GRAPHIC) + { + gSavedSettings.setString("PresetGraphicActive", name); + // signal interested parties + triggerChangeSignal(); + } + + if (IS_CAMERA) + { + gSavedSettings.setString("PresetCameraActive", name); + setCameraDirty(false); + // signal interested parties + triggerChangeCameraSignal(); + } + } + else + { + LL_WARNS("Presets") << "Cannot open for output preset file " << pathName << LL_ENDL; + } + } else - { - LL_INFOS() << "No settings found; preferences floater has not yet been created" << LL_ENDL; - } + { + LL_INFOS() << "No settings available to be saved" << LL_ENDL; + } return saved; } -void LLPresetsManager::setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option) +bool LLPresetsManager::setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option) { + bool sts = true; + combo->clearRows(); + combo->setEnabled(TRUE); - std::string presets_dir = getPresetsDir(subdirectory); + std::list<std::string> preset_names; + loadPresetNamesFromDir(subdirectory, preset_names, default_option); - if (!presets_dir.empty()) + if (preset_names.begin() != preset_names.end()) { - std::list<std::string> preset_names; - loadPresetNamesFromDir(presets_dir, preset_names, default_option); - - std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive"); - - if (preset_names.begin() != preset_names.end()) - { - for (std::list<std::string>::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it) - { - const std::string& name = *it; - combo->add(name, LLSD().with(0, name)); - } - } - else + for (std::list<std::string>::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it) { - combo->setLabel(LLTrans::getString("preset_combo_label")); + const std::string& name = *it; + combo->add(name, name); } } + else + { + combo->setLabel(LLTrans::getString("preset_combo_label")); + combo->setEnabled(PRESETS_CAMERA != subdirectory); + sts = false; + } + + return sts; } void LLPresetsManager::loadPreset(const std::string& subdirectory, std::string name) @@ -277,24 +462,32 @@ void LLPresetsManager::loadPreset(const std::string& subdirectory, std::string n LL_DEBUGS() << "attempting to load preset '"<<name<<"' from '"<<full_path<<"'" << LL_ENDL; + mIgnoreChangedSignal = true; if(gSavedSettings.loadFromFile(full_path, false, true) > 0) { + mIgnoreChangedSignal = false; if(PRESETS_GRAPHIC == subdirectory) { gSavedSettings.setString("PresetGraphicActive", name); - } - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) + LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); + if (instance) + { + instance->refreshEnabledGraphics(); + } + triggerChangeSignal(); + } + if(PRESETS_CAMERA == subdirectory) { - instance->refreshEnabledGraphics(); + gSavedSettings.setString("PresetCameraActive", name); + triggerChangeCameraSignal(); } - triggerChangeSignal(); } - else - { - LL_WARNS() << "failed to load preset '"<<name<<"' from '"<<full_path<<"'" << LL_ENDL; - } + else + { + mIgnoreChangedSignal = false; + LL_WARNS("Presets") << "failed to load preset '"<<name<<"' from '"<<full_path<<"'" << LL_ENDL; + } } bool LLPresetsManager::deletePreset(const std::string& subdirectory, std::string name) @@ -320,17 +513,70 @@ bool LLPresetsManager::deletePreset(const std::string& subdirectory, std::string } // If you delete the preset that is currently marked as loaded then also indicate that no preset is loaded. - if (gSavedSettings.getString("PresetGraphicActive") == name) + if(PRESETS_GRAPHIC == subdirectory) { - gSavedSettings.setString("PresetGraphicActive", ""); + if (gSavedSettings.getString("PresetGraphicActive") == name) + { + gSavedSettings.setString("PresetGraphicActive", ""); + } + // signal interested parties + triggerChangeSignal(); } - // signal interested parties - triggerChangeSignal(); + if(PRESETS_CAMERA == subdirectory) + { + if (gSavedSettings.getString("PresetCameraActive") == name) + { + gSavedSettings.setString("PresetCameraActive", ""); + } + // signal interested parties + triggerChangeCameraSignal(); + } return sts; } +bool LLPresetsManager::isDefaultCameraPreset(std::string preset_name) +{ + return (preset_name == PRESETS_REAR_VIEW || preset_name == PRESETS_SIDE_VIEW || preset_name == PRESETS_FRONT_VIEW); +} + +bool LLPresetsManager::isTemplateCameraPreset(std::string preset_name) +{ + return (preset_name == PRESETS_REAR || preset_name == PRESETS_SIDE || preset_name == PRESETS_FRONT); +} + +void LLPresetsManager::resetCameraPreset(std::string preset_name) +{ + if (isDefaultCameraPreset(preset_name)) + { + createDefaultCameraPreset(preset_name, true); + + if (gSavedSettings.getString("PresetCameraActive") == preset_name) + { + loadPreset(PRESETS_CAMERA, preset_name); + } + } +} + +bool LLPresetsManager::createDefaultCameraPreset(std::string preset_name, bool force_reset) +{ + std::string preset_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, + PRESETS_CAMERA, LLURI::escape(preset_name) + ".xml"); + if (!gDirUtilp->fileExists(preset_file) || force_reset) + { + std::string template_name = preset_name.substr(0, preset_name.size() - PRESETS_VIEW_SUFFIX.size()); + std::string default_template_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, PRESETS_CAMERA, template_name + ".xml"); + return LLFile::copy(default_template_file, preset_file); + } + return false; +} + +boost::signals2::connection LLPresetsManager::setPresetListChangeCameraCallback(const preset_list_signal_t::slot_type& cb) +{ + return mPresetListChangeCameraSignal.connect(cb); +} + boost::signals2::connection LLPresetsManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb) { return mPresetListChangeSignal.connect(cb); diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h index 0014e32267ffd026a9c698e29a3dd20d8b2fb7e6..d5b384ceb9559e25052fedd444581e918ed42d79 100644 --- a/indra/newview/llpresetsmanager.h +++ b/indra/newview/llpresetsmanager.h @@ -36,11 +36,19 @@ static const std::string PRESETS_DEFAULT = "Default"; static const std::string PRESETS_DIR = "presets"; static const std::string PRESETS_GRAPHIC = "graphic"; static const std::string PRESETS_CAMERA = "camera"; +static const std::string PRESETS_REAR = "Rear"; +static const std::string PRESETS_FRONT = "Front"; +static const std::string PRESETS_SIDE = "Side"; +static const std::string PRESETS_VIEW_SUFFIX = " View"; +static const std::string PRESETS_REAR_VIEW = PRESETS_REAR + PRESETS_VIEW_SUFFIX; +static const std::string PRESETS_FRONT_VIEW = PRESETS_FRONT + PRESETS_VIEW_SUFFIX; +static const std::string PRESETS_SIDE_VIEW = PRESETS_SIDE + PRESETS_VIEW_SUFFIX; enum EDefaultOptions { DEFAULT_SHOW, DEFAULT_TOP, + DEFAULT_BOTTOM, DEFAULT_HIDE // Do not display "Default" in a list }; @@ -54,26 +62,47 @@ class LLPresetsManager : public LLSingleton<LLPresetsManager> typedef std::list<std::string> preset_name_list_t; typedef boost::signals2::signal<void()> preset_list_signal_t; - void createMissingDefault(); + void createMissingDefault(const std::string& subdirectory); + void startWatching(const std::string& subdirectory); + void triggerChangeCameraSignal(); void triggerChangeSignal(); static std::string getPresetsDir(const std::string& subdirectory); - void setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option); - void loadPresetNamesFromDir(const std::string& dir, preset_name_list_t& presets, EDefaultOptions default_option); + bool setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option); + void loadPresetNamesFromDir(const std::string& subdirectory, preset_name_list_t& presets, EDefaultOptions default_option); bool savePreset(const std::string& subdirectory, std::string name, bool createDefault = false); void loadPreset(const std::string& subdirectory, std::string name); bool deletePreset(const std::string& subdirectory, std::string name); + bool isCameraDirty(); + static void setCameraDirty(bool dirty); + + void createCameraDefaultPresets(); + + bool isTemplateCameraPreset(std::string preset_name); + bool isDefaultCameraPreset(std::string preset_name); + void resetCameraPreset(std::string preset_name); + bool createDefaultCameraPreset(std::string preset_name, bool force_reset = false); // Emitted when a preset gets loaded, deleted, or saved. + boost::signals2::connection setPresetListChangeCameraCallback(const preset_list_signal_t::slot_type& cb); boost::signals2::connection setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb); // Emitted when a preset gets loaded or saved. preset_name_list_t mPresetNames; + preset_list_signal_t mPresetListChangeCameraSignal; preset_list_signal_t mPresetListChangeSignal; private: - LOG_CLASS(LLPresetsManager); + LOG_CLASS(LLPresetsManager); + + void getControlNames(std::vector<std::string>& names); + static void settingChanged(); + + boost::signals2::connection mCameraChangedSignal; + + static bool mCameraDirty; + static bool mIgnoreChangedSignal; }; #endif // LL_PRESETSMANAGER_H diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 083a913ef8bb1479d0ad248d0a2209eebeb2f367..e9feae3457bec753b914eec5d3969f3dbcf11469 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -229,6 +229,33 @@ void LLProgressView::drawStartTexture(F32 alpha) gGL.popMatrix(); } +void LLProgressView::drawLogos(F32 alpha) +{ + if (mLogosList.empty()) + { + return; + } + + // logos are tied to label, + // due to potential resizes we have to figure offsets out on draw or resize + LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl"); + S32 offset_x, offset_y; + logos_label->localPointToScreen(0, 0, &offset_x, &offset_y); + std::vector<TextureData>::const_iterator iter = mLogosList.begin(); + std::vector<TextureData>::const_iterator end = mLogosList.end(); + for (; iter != end; iter++) + { + gl_draw_scaled_image_with_border(iter->mDrawRect.mLeft + offset_x, + iter->mDrawRect.mBottom + offset_y, + iter->mDrawRect.getWidth(), + iter->mDrawRect.getHeight(), + iter->mTexturep.get(), + UI_VERTEX_COLOR % alpha, + FALSE, + iter->mClipRect, + iter->mOffsetRect); + } +} void LLProgressView::draw() { @@ -245,6 +272,7 @@ void LLProgressView::draw() } LLPanel::draw(); + drawLogos(alpha); return; } @@ -257,6 +285,7 @@ void LLProgressView::draw() drawStartTexture(alpha); LLPanel::draw(); + drawLogos(alpha); // faded out completely - remove panel and reveal world if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME ) @@ -283,7 +312,7 @@ void LLProgressView::draw() // FIXME: this causes a crash that i haven't been able to fix mMediaCtrl->unloadMediaSource(); - gStartTexture = NULL; + releaseTextures(); } return; } @@ -291,6 +320,7 @@ void LLProgressView::draw() drawStartTexture(1.0f); // draw children LLPanel::draw(); + drawLogos(1.0f); } void LLProgressView::setText(const std::string& text) @@ -309,6 +339,196 @@ void LLProgressView::setMessage(const std::string& msg) getChild<LLUICtrl>("message_text")->setValue(mMessage); } +void LLProgressView::loadLogo(const std::string &path, + const U8 image_codec, + const LLRect &pos_rect, + const LLRectf &clip_rect, + const LLRectf &offset_rect) +{ + // We need these images very early, so we have to force-load them, otherwise they might not load in time. + if (!gDirUtilp->fileExists(path)) + { + return; + } + + LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec); + if (!start_image_frmted->load(path)) + { + LL_WARNS("AppInit") << "Image load failed: " << path << LL_ENDL; + return; + } + + LLPointer<LLImageRaw> raw = new LLImageRaw; + if (!start_image_frmted->decode(raw, 0.0f)) + { + LL_WARNS("AppInit") << "Image decode failed " << path << LL_ENDL; + return; + } + // HACK: getLocalTexture allows only power of two dimentions + raw->expandToPowerOfTwo(); + + TextureData data; + data.mTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + data.mDrawRect = pos_rect; + data.mClipRect = clip_rect; + data.mOffsetRect = offset_rect; + mLogosList.push_back(data); +} + +void LLProgressView::initLogos() +{ + mLogosList.clear(); + + const U8 image_codec = IMG_CODEC_PNG; + const LLRectf default_clip(0.f, 1.f, 1.f, 0.f); + const S32 default_height = 28; + const S32 default_pad = 15; + + S32 icon_width, icon_height; + + // We don't know final screen rect yet, so we can't precalculate position fully + LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl"); + S32 texture_start_x = logos_label->getFont()->getWidthF32(logos_label->getText()) + default_pad; + S32 texture_start_y = -7; + + // Normally we would just preload these textures from textures.xml, + // and display them via icon control, but they are only needed on + // startup and preloaded/UI ones stay forever + // (and this code was done already so simply reused it) + std::string temp_str = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "textures", "3p_icons"); + + temp_str += gDirUtilp->getDirDelimiter(); + +#ifdef LL_FMODSTUDIO + // original image size is 264x96, it is on longer side but + // with no internal paddings so it gets additional padding + icon_width = 77; + icon_height = 21; + S32 pad_y = 4; + texture_start_x++; + loadLogo(temp_str + "fmod_logo.png", + image_codec, + LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y), + default_clip, + default_clip); + + texture_start_x += icon_width + default_pad + 1; +#endif + // original image size is 342x113, central element is on a larger side + // plus internal padding, so it gets slightly more height than desired 32 + icon_width = 88; + icon_height = 29; + pad_y = -1; + loadLogo(temp_str + "havok_logo.png", + image_codec, + LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y), + default_clip, + default_clip); + + texture_start_x += icon_width + default_pad; + + // 108x41 + icon_width = 74; + loadLogo(temp_str + "vivox_logo.png", + image_codec, + LLRect(texture_start_x, texture_start_y + default_height, texture_start_x + icon_width, texture_start_y), + default_clip, + default_clip); +} + +void LLProgressView::initStartTexture(S32 location_id, bool is_in_production) +{ + if (gStartTexture.notNull()) + { + gStartTexture = NULL; + LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL; + } + + LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL; + + U8 image_codec = IMG_CODEC_PNG; + std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter(); + + if ((S32)START_LOCATION_ID_LAST == location_id) + { + temp_str += LLStartUp::getScreenLastFilename(); + } + else + { + std::string path = temp_str + LLStartUp::getScreenHomeFilename(); + + if (!gDirUtilp->fileExists(path) && is_in_production) + { + // Fallback to old file, can be removed later + // Home image only sets when user changes home, so it will take time for users to switch to pngs + temp_str += "screen_home.bmp"; + image_codec = IMG_CODEC_BMP; + } + else + { + temp_str = path; + } + } + + LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec); + + // Turn off start screen to get around the occasional readback + // driver bug + if (!gSavedSettings.getBOOL("UseStartScreen")) + { + LL_INFOS("AppInit") << "Bitmap load disabled" << LL_ENDL; + return; + } + else if (!start_image_frmted->load(temp_str)) + { + LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL; + gStartTexture = NULL; + } + else + { + gStartImageWidth = start_image_frmted->getWidth(); + gStartImageHeight = start_image_frmted->getHeight(); + + LLPointer<LLImageRaw> raw = new LLImageRaw; + if (!start_image_frmted->decode(raw, 0.0f)) + { + LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; + gStartTexture = NULL; + } + else + { + // HACK: getLocalTexture allows only power of two dimentions + raw->expandToPowerOfTwo(); + gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + } + } + + if (gStartTexture.isNull()) + { + gStartTexture = LLViewerTexture::sBlackImagep; + gStartImageWidth = gStartTexture->getWidth(); + gStartImageHeight = gStartTexture->getHeight(); + } +} + +void LLProgressView::initTextures(S32 location_id, bool is_in_production) +{ + initStartTexture(location_id, is_in_production); + initLogos(); + + childSetVisible("panel_icons", mLogosList.empty() ? FALSE : TRUE); + childSetVisible("panel_top_spacer", mLogosList.empty() ? TRUE : FALSE); +} + +void LLProgressView::releaseTextures() +{ + gStartTexture = NULL; + mLogosList.clear(); + + childSetVisible("panel_top_spacer", TRUE); + childSetVisible("panel_icons", FALSE); +} + void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label) { mCancelBtn->setVisible( b ); diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 813576b21d181b196061fbe17b12ff044b7fddc6..56377a5889d235eee6973220969a1946ecd5b9c9 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -35,6 +35,7 @@ class LLImageRaw; class LLButton; class LLProgressBar; +class LLViewerTexture; class LLProgressView : public LLPanel, @@ -51,6 +52,7 @@ class LLProgressView : /*virtual*/ void draw(); void drawStartTexture(F32 alpha); + void drawLogos(F32 alpha); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); @@ -70,6 +72,10 @@ class LLProgressView : void setStartupComplete(); + // we have to preload local textures to make sure they won't be grey + void initTextures(S32 location_id, bool is_in_production); + void releaseTextures(); + void setCancelButtonVisible(BOOL b, const std::string& label); static void onCancelButtonClicked( void* ); @@ -95,6 +101,25 @@ class LLProgressView : bool handleUpdate(const LLSD& event_data); static void onIdle(void* user_data); + void loadLogo(const std::string &path, const U8 image_codec, const LLRect &pos_rect, const LLRectf &clip_rect, const LLRectf &offset_rect); + // logos have unusual location and need to be preloaded to not appear grey, then deleted + void initLogos(); + // Loads a bitmap to display during load + void initStartTexture(S32 location_id, bool is_in_production); + +private: + // We need to draw textures on login, but only once. + // So this vector gets filled up for textures to render and gets cleaned later + // Some textures have unusual requirements, so we are rendering directly + class TextureData + { + public: + LLPointer<LLViewerTexture> mTexturep; + LLRect mDrawRect; + LLRectf mClipRect; + LLRectf mOffsetRect; + }; + std::vector<TextureData> mLogosList; }; #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7673bae725aaace68d2b2a8f52d0f05d2f5fe89a..1be1c4ba9661db65d8e18ae4964e2a11be64d8b7 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -39,8 +39,8 @@ #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" -#ifdef LL_FMODEX -# include "llaudioengine_fmodex.h" +#ifdef LL_FMODSTUDIO +# include "llaudioengine_fmodstudio.h" #endif #ifdef LL_OPENAL @@ -71,6 +71,7 @@ #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpersistentnotificationstorage.h" +#include "llpresetsmanager.h" #include "llteleporthistory.h" #include "llregionhandle.h" #include "llsd.h" @@ -622,13 +623,13 @@ bool idle_startup() delete gAudiop; gAudiop = NULL; -#ifdef LL_FMODEX +#ifdef LL_FMODSTUDIO #if !LL_WINDOWS - if (NULL == getenv("LL_BAD_FMODEX_DRIVER")) + if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER")) #endif // !LL_WINDOWS - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable")); - } + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODExProfilerEnable")); + } #endif #ifdef LL_OPENAL @@ -649,7 +650,7 @@ bool idle_startup() #else void* window_handle = NULL; #endif - bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); + bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle, LLAppViewer::instance()->getSecondLifeTitle()); if(init) { gAudiop->setMuted(TRUE); @@ -993,9 +994,8 @@ bool idle_startup() gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT); - init_start_screen(agent_location_id); - // Display the startup progress bar. + gViewerWindow->initTextures(agent_location_id); gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit")); @@ -1965,6 +1965,8 @@ bool idle_startup() // JC - 7/20/2002 gViewerWindow->sendShapeToSim(); + LLPresetsManager::getInstance()->createMissingDefault(PRESETS_CAMERA); + // The reason we show the alert is because we want to // reduce confusion for when you log in and your provided // location is not your expected location. So, if this is @@ -2714,81 +2716,6 @@ std::string LLStartUp::getUserId() return gUserCredential->userID(); } -// Loads a bitmap to display during load -void init_start_screen(S32 location_id) -{ - if (gStartTexture.notNull()) - { - gStartTexture = NULL; - LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL; - } - - LL_DEBUGS("AppInit") << "Loading startup bitmap..." << LL_ENDL; - - U8 image_codec = IMG_CODEC_PNG; - std::string temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter(); - - if ((S32)START_LOCATION_ID_LAST == location_id) - { - temp_str += LLStartUp::getScreenLastFilename(); - } - else - { - std::string path = temp_str + LLStartUp::getScreenHomeFilename(); - - if (!gDirUtilp->fileExists(path) && LLGridManager::getInstance()->isInProductionGrid()) - { - // Fallback to old file, can be removed later - // Home image only sets when user changes home, so it will take time for users to switch to pngs - temp_str += "screen_home.bmp"; - image_codec = IMG_CODEC_BMP; - } - else - { - temp_str = path; - } - } - - LLPointer<LLImageFormatted> start_image_frmted = LLImageFormatted::createFromType(image_codec); - - // Turn off start screen to get around the occasional readback - // driver bug - if(!gSavedSettings.getBOOL("UseStartScreen")) - { - LL_INFOS("AppInit") << "Bitmap load disabled" << LL_ENDL; - return; - } - else if(!start_image_frmted->load(temp_str) ) - { - LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL; - gStartTexture = NULL; - } - else - { - gStartImageWidth = start_image_frmted->getWidth(); - gStartImageHeight = start_image_frmted->getHeight(); - - LLPointer<LLImageRaw> raw = new LLImageRaw; - if (!start_image_frmted->decode(raw, 0.0f)) - { - LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; - gStartTexture = NULL; - } - else - { - raw->expandToPowerOfTwo(); - gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ; - } - } - - if(gStartTexture.isNull()) - { - gStartTexture = LLViewerTexture::sBlackImagep ; - gStartImageWidth = gStartTexture->getWidth() ; - gStartImageHeight = gStartTexture->getHeight() ; - } -} - // frees the bitmap void release_start_screen() diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index b8c227334da1ab21818d0fde9477abf3ead9c359..4d55448d78ae140182b35428a7f08e0ef87f29ad 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -38,6 +38,7 @@ #include "llfloaterbuycurrency.h" #include "llbuycurrencyhtml.h" #include "llpanelnearbymedia.h" +#include "llpanelpresetscamerapulldown.h" #include "llpanelpresetspulldown.h" #include "llpanelvolumepulldown.h" #include "llfloaterregioninfo.h" @@ -172,8 +173,11 @@ BOOL LLStatusBar::postBuild() mBoxBalance = getChild<LLTextBox>("balance"); mBoxBalance->setClickedCallback( &LLStatusBar::onClickBalance, this ); - mIconPresets = getChild<LLIconCtrl>( "presets_icon" ); - mIconPresets->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterPresets, this)); + mIconPresetsCamera = getChild<LLIconCtrl>( "presets_icon_camera" ); + mIconPresetsCamera->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterPresetsCamera, this)); + + mIconPresetsGraphic = getChild<LLIconCtrl>( "presets_icon_graphic" ); + mIconPresetsGraphic->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterPresets, this)); mBtnVolume = getChild<LLButton>( "volume_btn" ); mBtnVolume->setClickedCallback( onClickVolume, this ); @@ -228,6 +232,11 @@ BOOL LLStatusBar::postBuild() mSGPacketLoss = LLUICtrlFactory::create<LLStatGraph>(pgp); addChild(mSGPacketLoss); + mPanelPresetsCameraPulldown = new LLPanelPresetsCameraPulldown(); + addChild(mPanelPresetsCameraPulldown); + mPanelPresetsCameraPulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); + mPanelPresetsCameraPulldown->setVisible(FALSE); + mPanelPresetsPulldown = new LLPanelPresetsPulldown(); addChild(mPanelPresetsPulldown); mPanelPresetsPulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); @@ -344,7 +353,8 @@ void LLStatusBar::setVisibleForMouselook(bool visible) mSGPacketLoss->setVisible(visible); mSearchPanel->setVisible(visible && gSavedSettings.getBOOL("MenuSearch")); setBackgroundVisible(visible); - mIconPresets->setVisible(visible); + mIconPresetsCamera->setVisible(visible); + mIconPresetsGraphic->setVisible(visible); } void LLStatusBar::debitBalance(S32 debit) @@ -485,10 +495,34 @@ void LLStatusBar::onClickBuyCurrency() LLFirstUse::receiveLindens(false); } +void LLStatusBar::onMouseEnterPresetsCamera() +{ + LLView* popup_holder = gViewerWindow->getRootView()->getChildView("popup_holder"); + LLIconCtrl* icon = getChild<LLIconCtrl>( "presets_icon_camera" ); + LLRect icon_rect = icon->getRect(); + LLRect pulldown_rect = mPanelPresetsCameraPulldown->getRect(); + pulldown_rect.setLeftTopAndSize(icon_rect.mLeft - + (pulldown_rect.getWidth() - icon_rect.getWidth()), + icon_rect.mBottom, + pulldown_rect.getWidth(), + pulldown_rect.getHeight()); + + pulldown_rect.translate(popup_holder->getRect().getWidth() - pulldown_rect.mRight, 0); + mPanelPresetsCameraPulldown->setShape(pulldown_rect); + + // show the master presets pull-down + LLUI::getInstance()->clearPopups(); + LLUI::getInstance()->addPopup(mPanelPresetsCameraPulldown); + mPanelNearByMedia->setVisible(FALSE); + mPanelVolumePulldown->setVisible(FALSE); + mPanelPresetsPulldown->setVisible(FALSE); + mPanelPresetsCameraPulldown->setVisible(TRUE); +} + void LLStatusBar::onMouseEnterPresets() { LLView* popup_holder = gViewerWindow->getRootView()->getChildView("popup_holder"); - LLIconCtrl* icon = getChild<LLIconCtrl>( "presets_icon" ); + LLIconCtrl* icon = getChild<LLIconCtrl>( "presets_icon_graphic" ); LLRect icon_rect = icon->getRect(); LLRect pulldown_rect = mPanelPresetsPulldown->getRect(); pulldown_rect.setLeftTopAndSize(icon_rect.mLeft - @@ -527,6 +561,7 @@ void LLStatusBar::onMouseEnterVolume() // show the master volume pull-down LLUI::getInstance()->clearPopups(); LLUI::getInstance()->addPopup(mPanelVolumePulldown); + mPanelPresetsCameraPulldown->setVisible(FALSE); mPanelPresetsPulldown->setVisible(FALSE); mPanelNearByMedia->setVisible(FALSE); mPanelVolumePulldown->setVisible(TRUE); @@ -551,6 +586,7 @@ void LLStatusBar::onMouseEnterNearbyMedia() LLUI::getInstance()->clearPopups(); LLUI::getInstance()->addPopup(mPanelNearByMedia); + mPanelPresetsCameraPulldown->setVisible(FALSE); mPanelPresetsPulldown->setVisible(FALSE); mPanelVolumePulldown->setVisible(FALSE); mPanelNearByMedia->setVisible(TRUE); diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index cad877f7991ed7eb42730c0a9b859c8b2e148305..3002b91c107479ec544d0e33c0003232c6f47aef 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -41,6 +41,7 @@ class LLUICtrl; class LLUUID; class LLFrameTimer; class LLStatGraph; +class LLPanelPresetsCameraPulldown; class LLPanelPresetsPulldown; class LLPanelVolumePulldown; class LLPanelNearByMedia; @@ -99,6 +100,7 @@ class LLStatusBar void onClickBuyCurrency(); void onVolumeChanged(const LLSD& newvalue); + void onMouseEnterPresetsCamera(); void onMouseEnterPresets(); void onMouseEnterVolume(); void onMouseEnterNearbyMedia(); @@ -123,7 +125,8 @@ class LLStatusBar LLStatGraph *mSGBandwidth; LLStatGraph *mSGPacketLoss; - LLIconCtrl *mIconPresets; + LLIconCtrl *mIconPresetsCamera; + LLIconCtrl *mIconPresetsGraphic; LLButton *mBtnVolume; LLTextBox *mBoxBalance; LLButton *mMediaToggle; @@ -135,6 +138,7 @@ class LLStatusBar S32 mSquareMetersCommitted; LLFrameTimer* mBalanceTimer; LLFrameTimer* mHealthTimer; + LLPanelPresetsCameraPulldown* mPanelPresetsCameraPulldown; LLPanelPresetsPulldown* mPanelPresetsPulldown; LLPanelVolumePulldown* mPanelVolumePulldown; LLPanelNearByMedia* mPanelNearByMedia; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c608c589a58aa3e93493446c88a0e8928b8ccd9d..414ae1fad63688b611c735a1f1573b1e0c4f970c 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -53,6 +53,7 @@ #include "llfloaterbuyland.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" +#include "llfloatercamerapresets.h" #include "llfloaterchatvoicevolume.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" @@ -104,12 +105,14 @@ #include "llfloaterperms.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" +#include "llfloaterpreferenceviewadvanced.h" #include "llfloaterpreviewtrash.h" #include "llfloaterproperties.h" #include "llfloaterregiondebugconsole.h" #include "llfloaterregioninfo.h" #include "llfloaterregionrestarting.h" #include "llfloaterreporter.h" +#include "llfloatersavecamerapreset.h" #include "llfloatersaveprefpreset.h" #include "llfloatersceneloadstats.h" #include "llfloaterscriptdebug.h" @@ -212,6 +215,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); + LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>); LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterIMNearbyChat::buildFloater); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); @@ -299,6 +303,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); LLFloaterReg::add("prefs_graphics_advanced", "floater_preferences_graphics_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceGraphicsAdvanced>); + LLFloaterReg::add("prefs_view_advanced", "floater_preferences_view_advanced.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceViewAdvanced>); LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_spellchecker_import", "floater_spellcheck_import.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSpellCheckerImport>); LLFloaterReg::add("prefs_translation", "floater_translation_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTranslationSettings>); @@ -318,6 +323,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("properties", "floater_inventory_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProperties>); LLFloaterReg::add("publish_classified", "floater_publish_classified.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPublishClassifiedFloater>); LLFloaterReg::add("save_pref_preset", "floater_save_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSavePrefPreset>); + LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>); LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>); LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index a14041717f26a52528cb46539751cd7f06da966f..6914e0fc2bcd35787062fc769cf7f784190a7bba 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -345,6 +345,7 @@ void camera_spin_around_ccw_sitting( EKeystate s ) else { //change camera but do not send keystrokes + gAgentCamera.unlockView(); gAgentCamera.setOrbitLeftKey( get_orbit_rate() ); } } @@ -361,6 +362,7 @@ void camera_spin_around_cw_sitting( EKeystate s ) else { //change camera but do not send keystrokes + gAgentCamera.unlockView(); gAgentCamera.setOrbitRightKey( get_orbit_rate() ); } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 162acb74f18098f025e50621ca4a026759057225..b6c7be2ed3550d403fc6af79fbd7111c3b824400 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4104,8 +4104,7 @@ void handle_reset_view() // switching to outfit selector should automagically save any currently edited wearable LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } - - gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); + reset_view_final( TRUE ); LLFloaterCamera::resetCameraMode(); } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index e197591ef86b7f42c22018420861b4430f4ade1b..c966b7d4f93712af29cdd9e7ca5db60be82f221a 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1902,7 +1902,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // If there is a new music URL and it's valid, play it. if (music_url.size() > 12) { - if (music_url.substr(0, 7) == "http://") + if (music_url.substr(0, 7) == "http://" + || music_url.substr(0, 8) == "https://") { LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender()); optionally_start_music(music_url, parcel->mLocalID, region->getRegionID()); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f64dfcf0d462f1c98e29a60cbad6cb1415e3c776..44d02b42248fdc847874ad47dcdcb14100b8f339 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5119,6 +5119,14 @@ void LLViewerWindow::revealIntroPanel() } } +void LLViewerWindow::initTextures(S32 location_id) +{ + if (mProgressView) + { + mProgressView->initTextures(location_id, LLGridManager::getInstance()->isInProductionGrid()); + } +} + void LLViewerWindow::setShowProgress(const BOOL show) { if (mProgressView) @@ -5172,7 +5180,6 @@ void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& } } - LLProgressView *LLViewerWindow::getProgressView() const { return mProgressView; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 385bbd57e542d9950f417a569663ebd0abbd1081..44c1fbd066a2ca4e58af80f5f41680ef4727e164 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -303,6 +303,7 @@ class LLViewerWindow : public LLWindowCallbacks BOOL getCursorHidden() { return mCursorHidden; } void moveCursorToCenter(); // move to center of window + void initTextures(S32 location_id); void setShowProgress(const BOOL show); BOOL getShowProgress() const; void setProgressString(const std::string& string); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index eb461d3140c85203b81d41ebaffadc2108a16bbd..d567623ac04a64659cad560789383f2d99258af8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7373,7 +7373,8 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) mRoot->updateWorldMatrixChildren(); stopMotion(ANIM_AGENT_BODY_NOISE); - + + gAgentCamera.setInitSitRot(gAgent.getFrameAgent().getQuaternion()); } //----------------------------------------------------------------------------- diff --git a/indra/newview/skins/default/textures/3p_icons/fmod_logo.png b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5a50e0ad34b54c63357a87094a102ba26d0782d6 Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png differ diff --git a/indra/newview/skins/default/textures/3p_icons/havok_logo.png b/indra/newview/skins/default/textures/3p_icons/havok_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ff1ea3a72e8baf13cf235021482f9d57bab2ef08 Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/havok_logo.png differ diff --git a/indra/newview/skins/default/textures/3p_icons/vivox_logo.png b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6f20e87b7ae817116bad7d2939b545cea3029c3e Binary files /dev/null and b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png differ diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc3c85ea2a96cb82eeb487625eac03bb1c90aa2 Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png differ diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png new file mode 100644 index 0000000000000000000000000000000000000000..2812d614e6abc12f8f3ec1bcbad8f2f445e6f3e2 Binary files /dev/null and b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png differ diff --git a/indra/newview/skins/default/textures/icons/Presets_Icon.png b/indra/newview/skins/default/textures/icons/Presets_Icon.png index 5a6628816b34fca5623902249385a0b7e836fd68..503ee892a55da5add034fe7055a8baf72ce64cc5 100644 Binary files a/indra/newview/skins/default/textures/icons/Presets_Icon.png and b/indra/newview/skins/default/textures/icons/Presets_Icon.png differ diff --git a/indra/newview/skins/default/textures/icons/Presets_Icon_Graphic.png b/indra/newview/skins/default/textures/icons/Presets_Icon_Graphic.png new file mode 100644 index 0000000000000000000000000000000000000000..5a6628816b34fca5623902249385a0b7e836fd68 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Presets_Icon_Graphic.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 624dca48d264917e9f419cb4cc51119567cbf7de..7325d836d28f105dfda4a91d9798cca917ef4a0c 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -98,7 +98,7 @@ with the same filename but different name <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0" /> <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> - <texture name="Cam_Avatar_Off" file_name="bottomtray/Cam_Avatar_Off.png" preload="false" /> + <texture name="Cam_Avatar_Off" file_name="bottomtray/Cam_Avatar_Off.png" preload="true" /> <texture name="Cam_FreeCam_Off" file_name="bottomtray/Cam_FreeCam_Off.png" preload="false" /> <texture name="Cam_Orbit_Off" file_name="bottomtray/Cam_Orbit_Off.png" preload="false" /> <texture name="Cam_Pan_Off" file_name="bottomtray/Cam_Pan_Off.png" preload="false" /> @@ -113,8 +113,10 @@ with the same filename but different name <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" /> <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" /> + <texture name="Cam_Rotate_Center" file_name="bottomtray/Cam_Rotate_Center.png" preload="false" /> <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" /> <texture name="Cam_Tracking_Out" file_name="bottomtray/Cam_Tracking_Out.png" preload="false" /> + <texture name="Cam_Tracking_Center" file_name="bottomtray/Cam_Tracking_Center.png" preload="false" /> <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" /> <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" /> @@ -204,7 +206,9 @@ with the same filename but different name <texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" /> - <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" /> + <texture name="Presets_Icon" file_name="icons/Presets_Icon.png" preload="true" /> + <texture name="Presets_Icon_Graphic" file_name="icons/Presets_Icon_Graphic.png" preload="true" /> + <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" /> <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" /> <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" /> <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" /> @@ -253,6 +257,7 @@ with the same filename but different name <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" /> <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" /> <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="false" /> + <texture name="Icon_Gear" file_name="windows/Icon_Gear.png" preload="false" /> <texture name="Icon_Help_Foreground" file_name="windows/Icon_Help_Foreground.png" preload="true" /> <texture name="Icon_Help_Press" file_name="windows/Icon_Help_Press.png" preload="true" /> @@ -492,6 +497,7 @@ with the same filename but different name <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" /> <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> + <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" /> <texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> diff --git a/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png new file mode 100644 index 0000000000000000000000000000000000000000..ec0926bfa1cbc70b172f51704227bc30e418cf6b Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/ProgressBarSolid.png differ diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear.png b/indra/newview/skins/default/textures/windows/Icon_Gear.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e89b8f32dfd9c70f89d25776a587d1726871b5 Binary files /dev/null and b/indra/newview/skins/default/textures/windows/Icon_Gear.png differ diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 72a7b5540c0fd7af9700dc68d56540d2e40449b4..9deb38e3afac6397eaee2208b771c8c14badbb8e 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -7,7 +7,7 @@ legacy_header_height="18" can_minimize="true" can_close="true" - height="164" + height="135" layout="topleft" name="camera_floater" help_topic="camera_floater" @@ -16,7 +16,7 @@ title="CAMERA CONTROLS" chrome="true" save_rect="true" - width="228"> + width="400"> <floater.string name="rotate_tooltip"> Rotate Camera Around Focus @@ -33,6 +33,7 @@ name="free_mode_title"> View Object </floater.string> + <string name="inactive_combo_text">Use preset</string> <panel border="false" height="123" @@ -41,112 +42,18 @@ top="0" mouse_opaque="false" name="controls" - width="226"> - <panel - follows="all" - height="102" - layout="topleft" - left="8" - name="preset_views_list" - top="24" - width="212" - visible="false"> - <panel_camera_item - name="front_view"> - <panel_camera_item.mousedown_callback - function="CameraPresets.ChangeView" - parameter="front_view" /> - <panel_camera_item.picture - image_name="Cam_Preset_Front_Off" /> - <panel_camera_item.selected_picture - image_name="Cam_Preset_Front_On" /> - <panel_camera_item.text - name="front_view_text"> - Front View - </panel_camera_item.text> - </panel_camera_item> - <panel_camera_item - name="group_view" - top_pad="4"> - <panel_camera_item.mousedown_callback - function="CameraPresets.ChangeView" - parameter="group_view" /> - <panel_camera_item.picture - image_name="Cam_Preset_Side_Off" /> - <panel_camera_item.selected_picture - image_name="Cam_Preset_Side_On" /> - <panel_camera_item.text - name="side_view_text"> - Side View - </panel_camera_item.text> - </panel_camera_item> - <panel_camera_item - name="rear_view" - layout="topleft" - top_pad="4"> - <panel_camera_item.mousedown_callback - function="CameraPresets.ChangeView" - parameter="rear_view" /> - <panel_camera_item.picture - image_name="Cam_Preset_Back_Off" /> - <panel_camera_item.selected_picture - image_name="Cam_Preset_Back_On" /> - <panel_camera_item.text - name="rear_view_text"> - Rear View - </panel_camera_item.text> - </panel_camera_item> - </panel> - <panel - follows="all" - height="68" - layout="topleft" - left="8" - name="camera_modes_list" - top="24" - width="212" - visible="false"> - <panel_camera_item - name="object_view"> - <panel_camera_item.mousedown_callback - function="CameraPresets.ChangeView" - parameter="object_view" /> - <panel_camera_item.text - name="object_view_text"> - Object View - </panel_camera_item.text> - <panel_camera_item.picture - image_name="Object_View_Off" /> - <panel_camera_item.selected_picture - image_name="Object_View_On" /> - </panel_camera_item> - <panel_camera_item - name="mouselook_view" - layout="topleft"> - <panel_camera_item.mousedown_callback - function="CameraPresets.ChangeView" - parameter="mouselook_view" /> - <panel_camera_item.text - name="mouselook_view_text"> - Mouselook View - </panel_camera_item.text> - <panel_camera_item.picture - image_name="MouseLook_View_Off" /> - <panel_camera_item.selected_picture - image_name="MouseLook_View_On" /> - </panel_camera_item> - </panel> + width="220"> <!--TODO: replace + - images --> <panel border="false" class="camera_zoom_panel" - height="114" + height="123" layout="topleft" left="0" mouse_opaque="false" name="zoom" - top="20" - width="226"> + top="0" + width="220"> <joystick_rotate follows="top|left" height="78" @@ -157,8 +64,8 @@ sound_flags="3" visible="true" tool_tip="Orbit camera around focus" - top="20" - width="78" /> + top="25" + width="78" /> <button follows="top|left" height="18" @@ -169,7 +76,7 @@ left_pad="14" name="zoom_plus_btn" width="18" - top="18"> + top="23"> <commit_callback function="Zoom.plus" /> <mouse_held_callback @@ -214,56 +121,136 @@ scale_image="false" sound_flags="3" tool_tip="Move camera up and down, left and right" - top="20" + top="25" width="78"/> + <text + type="string" + length="1" + follows="left|top" + height="15" + layout="topleft" + left="41" + top_pad="9" + name="precise_ctrs_label" + width="200"> + Use precise controls + </text> </panel> </panel> <panel - border="false" - height="42" + follows="all" + height="102" layout="topleft" - left="2" - top_pad="0" - name="buttons" - width="226"> - <button - height="23" - label="" - layout="topleft" - left="70" - is_toggle="true" - image_overlay="Cam_Avatar_Off" - image_selected="PushButton_Selected_Press" - name="presets_btn" - tab_stop="false" - tool_tip="Preset Views" - top="13" - width="25"> - </button> - <button - height="23" - label="" - layout="topleft" - left_pad="1" - is_toggle="true" - image_overlay="PanOrbit_Off" - image_selected="PushButton_Selected_Press" - name="pan_btn" - tab_stop="false" - tool_tip="Orbit Zoom Pan" - width="25"> - </button> - <button - height="23" - label="" - layout="topleft" - left_pad="1" - image_overlay="Cam_FreeCam_Off" - image_selected="PushButton_Selected_Press" - name="avatarview_btn" - tab_stop="false" - tool_tip="Camera modes" - width="25"> - </button> - </panel> + left_pad="2" + name="buttons_panel" + top="22" + width="212"> + <panel_camera_item + name="front_view" + tool_tip="Front View" + width="30"> + <panel_camera_item.mousedown_callback + function="CameraPresets.ChangeView" + parameter="Front View" /> + <panel_camera_item.picture + image_name="Cam_Preset_Front_Off" /> + <panel_camera_item.selected_picture + image_name="Cam_Preset_Front_On" /> + </panel_camera_item> + <panel_camera_item + name="group_view" + tool_tip="Side View" + width="30" + left_pad="4"> + <panel_camera_item.mousedown_callback + function="CameraPresets.ChangeView" + parameter="Side View" /> + <panel_camera_item.picture + image_name="Cam_Preset_Side_Off" /> + <panel_camera_item.selected_picture + image_name="Cam_Preset_Side_On" /> + </panel_camera_item> + <panel_camera_item + name="rear_view" + tool_tip="Rear View" + width="30" + left_pad="4"> + <panel_camera_item.mousedown_callback + function="CameraPresets.ChangeView" + tool_tip="Rear View" + parameter="Rear View" /> + <panel_camera_item.picture + image_name="Cam_Preset_Back_Off" /> + <panel_camera_item.selected_picture + image_name="Cam_Preset_Back_On" /> + </panel_camera_item> + <panel_camera_item + name="object_view" + tool_tip="Object View" + width="30" + left_pad="4"> + <panel_camera_item.mousedown_callback + function="CameraPresets.ChangeView" + parameter="object_view" /> + <panel_camera_item.picture + image_name="Object_View_Off" /> + <panel_camera_item.selected_picture + image_name="Object_View_On" /> + </panel_camera_item> + <panel_camera_item + name="mouselook_view" + tool_tip="Mouselook View" + width="30" + left_pad="4"> + <panel_camera_item.mousedown_callback + function="CameraPresets.ChangeView" + parameter="mouselook_view" /> + <panel_camera_item.picture + image_name="MouseLook_View_Off" /> + <panel_camera_item.selected_picture + image_name="MouseLook_View_On" /> + </panel_camera_item> + <combo_box + height="23" + left="0" + mouse_opaque="true" + name="preset_combo" + top_pad="10" + width="136"> + <combo_list + mouse_wheel_opaque="true"/> + <combo_box.item + label="Use preset" + name="Use preset" + value="default" /> + </combo_box> + <button + height="16" + width="16" + layout="topleft" + mouse_opaque="true" + name="gear_btn" + tool_tip="My Camera Presets" + top_delta="3" + left_pad="10" + image_selected="Icon_Gear" + image_pressed="Icon_Gear" + image_unselected="Icon_Gear" + is_toggle="true"> + <button.commit_callback + function="CameraPresets.ShowPresetsList"/> + </button> + <button + follows="top|left" + height="25" + label="Save as preset..." + layout="topleft" + left="0" + name="save_preset_btn" + top_pad="18" + width="150"> + <button.commit_callback + function="CameraPresets.Save"/> + </button> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_camera_presets.xml b/indra/newview/skins/default/xui/en/floater_camera_presets.xml new file mode 100644 index 0000000000000000000000000000000000000000..930357f5688d88ced839975a44beeb0f9a0e0deb --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_camera_presets.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + height="200" + min_height="150" + title="MY CAMERA PRESETS" + layout="topleft" + name="floater_camera_presets" + single_instance="true" + min_width="185" + width="250"> + <flat_list_view + allow_select="true" + follows="all" + height="165" + layout="topleft" + left="3" + multi_select="false" + name="preset_list" + top="20" + width="245" /> + </floater> diff --git a/indra/newview/skins/default/xui/en/floater_delete_pref_preset.xml b/indra/newview/skins/default/xui/en/floater_delete_pref_preset.xml index 0688fdb42c2f8d23079d3704c8aa9d7a80f50728..3360d7bec9766fd3868ea01850a6c7dd1fd1ce41 100644 --- a/indra/newview/skins/default/xui/en/floater_delete_pref_preset.xml +++ b/indra/newview/skins/default/xui/en/floater_delete_pref_preset.xml @@ -4,7 +4,7 @@ height="130" help_topic="floater_delete_preset" layout="topleft" - name="Delete Pref Preset" + name="delete_pref_preset" save_rect="true" title="DELETE PREF PRESET" width="300"> diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml index 52084e5f8ed07390d63097c4578346513c01fffb..3570456b444eed0b368135e2fc9707d94572378f 100644 --- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml +++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml @@ -4,18 +4,16 @@ legacy_header_height="225" can_minimize="true" can_close="true" - can_resize="true" - min_height="65" - min_width="515" - height="65" + can_resize="false" + height="80" + width="515" layout="topleft" name="HoverHeight" single_instance="true" help_topic="hover_height" save_rect="true" save_visibility="true" - title="SET HOVER HEIGHT" - width="515"> + title="SET HOVER HEIGHT"> <slider enabled="false" control_name="HoverHeightSlider" @@ -34,4 +32,13 @@ can_edit_text="true" > </slider> + <check_box + control_name="HoverHeightAffectsCamera" + follows="all" + height="15" + label="Bind Camera view" + layout="topleft" + name="BindCameraCheck" + top_pad="7" + width="237"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml index a8342e723bc28d35ef6dee32b7d92e55514c7354..d783d1e23c513d060daf3955052644400b88e585 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml @@ -2,7 +2,7 @@ <floater legacy_header_height="18" can_minimize="false" - height="488" + height="466" layout="topleft" name="Inventory Finder" help_topic="inventory_finder" @@ -202,7 +202,7 @@ left="8" mouse_opaque="true" name="icon_settings" - top="262" + top="242" width="16" /> <check_box height="16" @@ -220,7 +220,7 @@ layout="topleft" left="8" name="All" - top="282" + top="262" width="100" /> <button height="20" @@ -368,6 +368,6 @@ layout="topleft" name="Close" right="-6" - top="454" + top="434" width="76" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_load_pref_preset.xml b/indra/newview/skins/default/xui/en/floater_load_pref_preset.xml index 5f2eb770e25a4670f3e59b16fad27e11c47093d7..49c21f1ea794d2e3bbb9f25b15a2f2f44351932e 100644 --- a/indra/newview/skins/default/xui/en/floater_load_pref_preset.xml +++ b/indra/newview/skins/default/xui/en/floater_load_pref_preset.xml @@ -4,7 +4,7 @@ height="130" help_topic="floater_load_preset" layout="topleft" - name="Load Pref Preset" + name="load_pref_preset" save_rect="true" title="LOAD PREF PRESET" width="300"> diff --git a/indra/newview/skins/default/xui/en/floater_preferences_view_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_view_advanced.xml new file mode 100644 index 0000000000000000000000000000000000000000..4c3c7e49300f0bdb0b28f46c2aceb80bd018d59d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_view_advanced.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + height="190" + layout="topleft" + name="floaterpreferencesviewadvanced" + help_topic="floaterviewadvanced" + title="CAMERA POSITION" + save_rect="true" + width="280"> + + <text + follows="top|left|right" + name="camera_offset_lbl" + height="16" + layout="topleft" + left="10" + top="10" + width="100"> + Camera offset: + </text> + + <spinner + height="20" + label="X" + label_width="12" + follows="top|left" + left="10" + name="camera_x" + top_pad="5" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <spinner + height="20" + label="Y" + label_width="12" + follows="top|left" + name="camera_y" + left_pad="20" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <spinner + height="20" + label="Z" + label_width="12" + follows="top|left" + name="camera_z" + left_pad="20" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <text + follows="top|left|right" + name="focus_offset_lbl" + height="16" + layout="topleft" + left="10" + top_pad="20" + width="100"> + Focus offset: + </text> + + <spinner + height="20" + label="X" + label_width="12" + follows="top|left" + left="10" + name="focus_x" + top_pad="5" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <spinner + height="20" + label="Y" + label_width="12" + follows="top|left" + name="focus_y" + left_pad="20" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <spinner + height="20" + label="Z" + label_width="12" + follows="top|left" + name="focus_z" + left_pad="20" + min_val="-1e+007" + max_val="1e+007" + width="70"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + + <text + follows="top|left|right" + name="offset_scale_lbl" + height="16" + layout="topleft" + left="10" + top_pad="20" + width="140"> + Camera offset scale: + </text> + + <slider + control_name="CameraOffsetScale" + follows="top|left|right" + height="16" + top_pad="5" + increment="0.1" + min_val="-3" + max_val="5" + show_text="false" + layout="topleft" + left="3" + name="offset_scale_sld" + width="196" /> + <spinner + control_name="CameraOffsetScale" + height="20" + follows="top|left|right" + left_pad="5" + name="offset_scale_ctrl" + min_val="-3" + max_val="5" + width="58"> + <spinner.commit_callback + function="CommitSettings" /> + </spinner> + +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_save_camera_preset.xml b/indra/newview/skins/default/xui/en/floater_save_camera_preset.xml new file mode 100644 index 0000000000000000000000000000000000000000..54fdb6d1670810eefa4628e383a6eb33073e99a1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_save_camera_preset.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<floater + legacy_header_height="18" + height="185" + help_topic="floater_save_preset" + layout="topleft" + name="save_camera_preset" + save_rect="true" + title="Save Camera Preset" + width="280"> + + <string name="btn_label_save">Save</string> + <string name="btn_label_replace">Replace</string> + <radio_group + height="85" + layout="topleft" + left="20" + top="15" + width="150" + name="radio_save_preset"> + <radio_item + label="Save as a new preset" + name="new_preset" + top="10" + layout="topleft" + height="16" + value="0"/> + <radio_item + label="Replace a preset" + name="replace_preset" + layout="topleft" + top="70" + height="16" + value="1"/> + </radio_group> + <line_editor + commit_on_focus_lost = "true" + follows="top|left" + height="23" + layout="topleft" + left="41" + name="preset_txt_editor" + width="200" + top="45"/> + <button + follows="top|left" + height="25" + label="Save" + layout="topleft" + top="145" + left="25" + name="save" + width="110"/> + <button + follows="bottom|right" + height="25" + label="Cancel" + layout="topleft" + left_pad="20" + name="cancel" + width="110"/> +<!-- *HACK to correctly draw drop-down list over the buttons--> + <combo_box + follows="top|left" + layout="topleft" + left="41" + name="preset_combo" + top_delta="-40" + width="200"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_save_pref_preset.xml b/indra/newview/skins/default/xui/en/floater_save_pref_preset.xml index 7dee28eff3a1d5111c3e685e1730ee1435f906ee..62260274f5cfca9e4dd4edc067ae02443952bdfd 100644 --- a/indra/newview/skins/default/xui/en/floater_save_pref_preset.xml +++ b/indra/newview/skins/default/xui/en/floater_save_pref_preset.xml @@ -4,14 +4,11 @@ height="145" help_topic="floater_save_preset" layout="topleft" - name="Save Pref Preset" + name="save_pref_preset" save_rect="true" - title="SAVE PREF PRESET" + title="Save Graphic Preset" width="300"> - <string name="title_graphic">Save Graphic Preset</string> - <string name="title_camera">Save Camera Preset</string> - <text follows="top|left|right" height="32" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 089498dfb98959b49bb16be4e1e3990381d6be27..8a91a1f721844c537d59820835926b4005d10131 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8533,6 +8533,18 @@ Error saving preset [NAME]. Can not overwrite default preset. </notification> + <notification + icon="alertmodal.tga" + name="PresetAlreadyExists" + type="alertmodal"> +'[NAME]' is in use. You may replace +this preset or choose another name. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + <notification icon="notifytip.tga" name="PresetNotDeleted" diff --git a/indra/newview/skins/default/xui/en/panel_camera_preset_item.xml b/indra/newview/skins/default/xui/en/panel_camera_preset_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..9417ab4ac2d0de1b36cf36e69b6550bad7dbd1cb --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_camera_preset_item.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="top|right|left" + height="20" + layout="topleft" + left="0" + name="camera_preset_item" + top="0" + width="280"> + <icon + follows="top|right|left" + height="20" + image_name="ListItem_Over" + layout="topleft" + left="0" + name="hovered_icon" + top="0" + visible="false" + width="380" /> + <icon + height="20" + follows="top|right|left" + image_name="ListItem_Select" + layout="topleft" + left="0" + name="selected_icon" + top="0" + visible="false" + width="380" /> + <text + follows="left" + height="20" + layout="topleft" + left="10" + parse_urls="false" + use_ellipses="true" + name="preset_name" + text_color="White" + top="2" + value="Default" + width="159" /> + <button + follows="right" + image_selected="TrashItem_Off" + image_pressed="TrashItem_Off" + image_unselected="TrashItem_Off" + is_toggle="true" + layout="topleft" + left_pad="5" + right="-10" + name="delete_btn" + tool_tip="Delete preset" + top="3" + height="18" + width="18" > + <button.commit_callback + function="CameraPresets.Delete"/> + </button> + <button + follows="right" + image_selected="Refresh_Off" + image_pressed="Refresh_Off" + image_unselected="Refresh_Off" + is_toggle="true" + layout="topleft" + left_pad="5" + right="-10" + name="reset_btn" + tool_tip="Reset preset to default" + top="2" + height="20" + width="20" > + <button.commit_callback + function="CameraPresets.Reset"/> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 4d9152e9a5174094d690e7a42c02aa9b498a22ec..5aff7a512768ab1d69fdf897df8f5c6958598d0b 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -293,6 +293,21 @@ width="65"> 0 </text> +<text +type="string" +length="1" +follows="left|top" +height="16" +layout="topleft" +left_delta="68" +name="IndirectMaxComplexityLink" +mouse_opaque="false" +top_delta="0" +width="120"> +[https://community.secondlife.com/t5/Featured-News/Why-are-all-these-people-made-of-colored-jelly/ba-p/3031255 What's this?] +</text> + + <check_box control_name="AlwaysRenderFriends" height="16" @@ -345,7 +360,6 @@ function="Pref.PrefLoad" parameter="graphic"/> </button> - min_val="0.125" <button follows="top|left" diff --git a/indra/newview/skins/default/xui/en/panel_presets_camera_pulldown.xml b/indra/newview/skins/default/xui/en/panel_presets_camera_pulldown.xml new file mode 100644 index 0000000000000000000000000000000000000000..25d9c47449fac1ba042d2b7c32f3b8029a7b0fa8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_presets_camera_pulldown.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_opaque="true" + background_visible="true" + bg_opaque_image="Volume_Background" + bg_alpha_image="Volume_Background" + border_visible="false" + border="false" + chrome="true" + follows="bottom" + height="155" + layout="topleft" + name="presets_camera_pulldown" + width="225"> + <text + type="string" + length="1" + follows="left|top" + height="12" + layout="topleft" + top="4" + left_delta="5" + font.style="BOLD" + name="Camera Presets" + width="120"> + Camera Presets + </text> + <scroll_list + follows="left|top" + layout="topleft" + column_padding="0" + height="100" + width="215" + draw_heading="false" + draw_stripes="false" + bg_stripe_color="0.25 0.25 0.25 0.25" + top_delta="15" + left_delta="0" + name="preset_camera_list"> + <scroll_list.columns + name="icon" + width="16" /> + <scroll_list.columns + relative_width="1" + name="preset_name" /> + <scroll_list.commit_callback + function="PresetsCamera.RowClick" /> + </scroll_list> + <view_border + bevel_style="none" + follows="top|left" + height="0" + layout="topleft" + left="5" + name="horiz_separator" + top_delta="105" + width="215" /> + <button + name="open_prefs_btn" + label="Open Camera floater" + tool_tip = "Bring up Camera floater" + top_delta="5" + left="15" + height="20" + width="200"> + <button.commit_callback + function="Presets.toggleCameraFloater" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml index 860caf2d217a91a117c9c8da05b799f90f8ea7b3..e77d097d5f6db9cbec8669a19ff03b7c44a178d0 100644 --- a/indra/newview/skins/default/xui/en/panel_progress.xml +++ b/indra/newview/skins/default/xui/en/panel_progress.xml @@ -44,68 +44,129 @@ width="670" /> <layout_panel auto_resize="false" - height="250" + height="275" layout="topleft" - min_height="250" + min_height="275" name="panel4" width="670"> <icon color="LoginProgressBoxCenterColor" follows="left|right|bottom|top" - height="250" + height="275" image_name="Rounded_Square" layout="topleft" left="0" top="0" width="670" /> - <text - follows="left|right|top" - font="SansSerifHuge" - font_shadow="none" - halign="left" - height="20" - layout="topleft" - left_delta="47" - name="title_text" - text_color="LoginProgressBoxTextColor" - top_delta="50" - right="-47"/> - <text - follows="left|right|top" - font="SansSerif" - font_shadow="none" - halign="left" - height="20" - layout="topleft" - left_delta="0" - name="progress_text" - text_color="LoginProgressBoxTextColor" - top_pad="5" - right="-47" - word_wrap="true"/> - <progress_bar - bottom="115" - color_bar="1 1 1 0.96" - follows="left|right|top" - height="16" - layout="topleft" - left="45" - name="login_progress_bar" - right="-45" /> - <text + <layout_stack follows="left|right|top|bottom" - font="SansSerifLarge" - font_shadow="none" - halign="left" - height="100" + height="275" layout="topleft" - left="45" - line_spacing.pixels="2" - name="message_text" - text_color="LoginProgressBoxTextColor" - top="145" - right="-90" - word_wrap="true"/> + left="0" + orientation="vertical" + name="vertical_centering" + animate="false" + top="0" + width="670"> + <layout_panel + auto_resize="false" + height="30" + layout="topleft" + min_height="30" + name="panel_top_spacer" + width="670"> + </layout_panel> + <layout_panel + auto_resize="false" + height="100" + layout="topleft" + min_height="100" + name="panel_login" + width="670"> + <text + follows="left|right|top" + layout="topleft" + font="SansSerifHuge" + font_shadow="none" + halign="left" + height="20" + left="47" + top="32" + right="-47" + name="title_text" + text_color="LoginProgressBoxTextColor"/> + <text + follows="left|right|top" + layout="topleft" + font="SansSerif" + font_shadow="none" + halign="left" + height="20" + top_pad="5" + right="-47" + left_delta="0" + name="progress_text" + text_color="LoginProgressBoxTextColor" + word_wrap="true"/> + <progress_bar + color_bar="0 0.67 0.9 0.96" + follows="left|right|top" + layout="topleft" + image_fill="ProgressBarSolid" + height="16" + left="45" + top_pad="5" + name="login_progress_bar" + right="-45" /> + </layout_panel> + <layout_panel + auto_resize="false" + height="110" + layout="topleft" + min_height="110" + name="panel_motd" + width="670"> + <text + follows="left|right|top|bottom" + font="SansSerifLarge" + font_shadow="none" + halign="left" + valign="center" + height="100" + layout="topleft" + left="45" + line_spacing.pixels="2" + name="message_text" + text_color="LoginProgressBoxTextColor" + top="7" + right="-90" + word_wrap="true"/> + </layout_panel> + <layout_panel + auto_resize="false" + height="40" + layout="topleft" + min_height="40" + name="panel_icons" + width="670"> + <!--Logos are tied to following label from code--> + <text + follows="left|right|top" + layout="topleft" + font="SansSerifLarge" + font_shadow="none" + halign="left" + height="16" + width="240" + left="47" + top="6" + line_spacing.pixels="2" + name="logos_lbl" + text_color="LoginProgressBoxTextColor"> + Second Life uses + </text> + </layout_panel> + </layout_stack> </layout_panel> <layout_panel height="200" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 52bcce01f7d7311471b2d1e3a1a7bf3ce975116d..ada980cda19616fcf60d14e6635fca3b0dc5df3f 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -75,7 +75,7 @@ </panel> <panel height="18" - left="-416" + left="-458" width="185" top="1" follows="right|top" @@ -148,11 +148,19 @@ <icon follows="right|top" height="16" - image_name="Presets_Icon" + image_name="Cam_FreeCam_Off" left_pad="8" top="2" - name="presets_icon" + name="presets_icon_camera" width="18" /> + <icon + follows="right|top" + height="13" + image_name="Presets_Icon" + left_pad="8" + top="4" + name="presets_icon_graphic" + width="16" /> <button follows="right|top" height="16" diff --git a/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml b/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml index 98707b84957005e3148e88319b2dcdb3ef7886d4..564f695cd05c2804a5d7cdbe35bb05fea9b1168e 100644 --- a/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/panel_camera_item.xml @@ -15,7 +15,7 @@ top="30" scale_image="true" visible="false" - width="212" /> + width="30" /> <panel_camera_item.icon_selected follows="top|left" height="30" @@ -27,7 +27,7 @@ top="30" scale_image="true" visible="false" - width="212" /> + width="30" /> <panel_camera_item.picture follows="top|left" height="30" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index a403760670eeff299cf61d3b389e8fc5a054955e..4d6d75659f048e6db96a5ca06a2272c363a6a34f 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -78,6 +78,9 @@ def construct(self): contributor_names = self.extract_names(contributions_path) self.put_in_file(contributor_names, "contributors.txt", src=contributions_path) + # ... and the default camera position settings + self.path("camera") + # ... and the entire windlight directory self.path("windlight") @@ -513,14 +516,12 @@ def construct(self): print err.message print "Skipping GLOD library (assumming linked statically)" - # Get fmodex dll, continue if missing - try: - if(self.address_size == 64): - self.path("fmodex64.dll") + # Get fmodstudio dll if needed + if self.args['fmodstudio'] == 'ON': + if(self.args['configuration'].lower() == 'debug'): + self.path("fmodL.dll") else: - self.path("fmodex.dll") - except: - print "Skipping fmodex audio library(assuming other audio engine)" + self.path("fmod.dll") # For textures self.path("openjpeg.dll") @@ -1046,17 +1047,18 @@ def path_optional(src, dst): ): self.path2basename(relpkgdir, libfile) - # dylibs that vary based on configuration - if self.args['configuration'].lower() == 'debug': - for libfile in ( - "libfmodexL.dylib", - ): - dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) - else: - for libfile in ( - "libfmodex.dylib", - ): - dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) + # Fmod studio dylibs (vary based on configuration) + if self.args['fmodstudio'] == 'ON': + if self.args['configuration'].lower() == 'debug': + for libfile in ( + "libfmodL.dylib", + ): + dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) + else: + for libfile in ( + "libfmod.dylib", + ): + dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) # our apps executable_path = {} @@ -1519,13 +1521,15 @@ def construct(self): print "tcmalloc files not found, skipping" pass - try: - self.path("libfmodex-*.so") - self.path("libfmodex.so") - pass - except: - print "Skipping libfmodex.so - not found" - pass + if self.args['fmodstudio'] == 'ON': + try: + self.path("libfmod.so.11.7") + self.path("libfmod.so.11") + self.path("libfmod.so") + pass + except: + print "Skipping libfmod.so - not found" + pass # Vivox runtimes @@ -1555,6 +1559,7 @@ def construct(self): extra_arguments = [ dict(name='bugsplat', description="""BugSplat database to which to post crashes, if BugSplat crash reporting is desired""", default=''), + dict(name='fmodstudio', description="""Indication if fmod studio libraries are needed""", default='OFF'), ] try: main(extra=extra_arguments)