/** * @file llenvmanager.h * @brief Declaration of classes managing WindLight and water settings. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, 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_ENVIRONMENT_H #define LL_ENVIRONMENT_H #include "llsingleton.h" #include "llmemory.h" #include "llsd.h" #include "llsettingsbase.h" #include "llsettingssky.h" #include "llsettingswater.h" #include "llsettingsdaycycle.h" #include "llatmosphere.h" #include "llglslshader.h" #include <boost/signals2.hpp> #include <array> //------------------------------------------------------------------------- class LLViewerCamera; class LLParcel; //------------------------------------------------------------------------- class LLEnvironment : public LLSimpleton<LLEnvironment> { LOG_CLASS(LLEnvironment); public: LLEnvironment(); static const F64Seconds TRANSITION_INSTANT; static const F64Seconds TRANSITION_FAST; static const F64Seconds TRANSITION_DEFAULT; static const F64Seconds TRANSITION_SLOW; static const F64Seconds TRANSITION_ALTITUDE; static const LLUUID KNOWN_SKY_SUNRISE; static const LLUUID KNOWN_SKY_MIDDAY; static const LLUUID KNOWN_SKY_LEGACY_MIDDAY; static const LLUUID KNOWN_SKY_SUNSET; static const LLUUID KNOWN_SKY_MIDNIGHT; static const S32 NO_TRACK; static const S32 NO_VERSION; static const S32 VERSION_CLEANUP; struct EnvironmentInfo { EnvironmentInfo(); typedef std::shared_ptr<EnvironmentInfo> ptr_t; typedef std::array<std::string, 5> namelist_t; S32 mParcelId; LLUUID mRegionId; S64Seconds mDayLength; S64Seconds mDayOffset; size_t mDayHash; LLSettingsDay::ptr_t mDayCycle; std::array<F32, 4> mAltitudes; bool mIsDefault; LLUUID mAssetId; bool mIsLegacy; std::string mDayCycleName; namelist_t mNameList; S32 mEnvVersion; static ptr_t extract(LLSD); static ptr_t extractLegacy(LLSD); }; enum EnvSelection_t { ENV_EDIT = 0, ENV_LOCAL, ENV_PUSH, ENV_PARCEL, ENV_REGION, ENV_DEFAULT, ENV_END, ENV_CURRENT = -1, ENV_NONE = -2 }; typedef boost::signals2::connection connection_t; typedef std::pair<LLSettingsSky::ptr_t, LLSettingsWater::ptr_t> fixedEnvironment_t; typedef std::function<void(S32, EnvironmentInfo::ptr_t)> environment_apply_fn; typedef boost::signals2::signal<void(EnvSelection_t, S32)> env_changed_signal_t; typedef env_changed_signal_t::slot_type env_changed_fn; typedef std::array<F32, 4> altitude_list_t; typedef std::vector<F32> altitudes_vect_t; ~LLEnvironment(); bool canEdit() const; bool isExtendedEnvironmentEnabled() const; bool isInventoryEnabled() const; bool canAgentUpdateParcelEnvironment() const; bool canAgentUpdateParcelEnvironment(LLParcel *parcel) const; bool canAgentUpdateRegionEnvironment() const; LLSettingsDay::ptr_t getCurrentDay() const { return mCurrentEnvironment->getDayCycle(); } LLSettingsSky::ptr_t getCurrentSky() const; LLSettingsWater::ptr_t getCurrentWater() const; static void getAtmosphericModelSettings(AtmosphericModelSettings& settingsOut, const LLSettingsSky::ptr_t &psky); void update(const LLViewerCamera * cam); static void updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting); // apply current sky settings to given shader void updateShaderUniforms(LLGLSLShader *shader); // prepare settings to be applied to shaders (call whenever settings are updated) void updateSettingsUniforms(); void setSelectedEnvironment(EnvSelection_t env, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false); EnvSelection_t getSelectedEnvironment() const { return mSelectedEnvironment; } bool hasEnvironment(EnvSelection_t env); void setEnvironment(EnvSelection_t env, const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version = NO_VERSION); void setEnvironment(EnvSelection_t env, fixedEnvironment_t fixed, S32 env_version = NO_VERSION); void setEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &fixed, S32 env_version = NO_VERSION); void setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixed, LLSettingsWater::ptr_t()), env_version); } void setEnvironment(EnvSelection_t env, const LLSettingsWater::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(LLSettingsSky::ptr_t(), fixed), env_version); } void setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixeds, const LLSettingsWater::ptr_t & fixedw, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixeds, fixedw), env_version); } void setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version); void setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, S32 env_version = NO_VERSION); void setSharedEnvironment(); void clearEnvironment(EnvSelection_t env); static void logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version = NO_VERSION); void setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env); LLSettingsDay::ptr_t getEnvironmentDay(EnvSelection_t env); LLSettingsDay::Seconds getEnvironmentDayLength(EnvSelection_t env); LLSettingsDay::Seconds getEnvironmentDayOffset(EnvSelection_t env); fixedEnvironment_t getEnvironmentFixed(EnvSelection_t env, bool resolve = false); LLSettingsSky::ptr_t getEnvironmentFixedSky(EnvSelection_t env, bool resolve = false) { return getEnvironmentFixed(env, resolve).first; }; LLSettingsWater::ptr_t getEnvironmentFixedWater(EnvSelection_t env, bool resolve = false) { return getEnvironmentFixed(env, resolve).second; }; void updateEnvironment(LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false); inline LLVector2 getCloudScrollDelta() const { return mCloudScrollDelta; } void pauseCloudScroll() { mCloudScrollPaused = true; } void resumeCloudScroll() { mCloudScrollPaused = false; } bool isCloudScrollPaused() const { return mCloudScrollPaused; } F32 getCamHeight() const; F32 getWaterHeight() const; bool getIsSunUp() const; bool getIsMoonUp() const; void saveToSettings(); bool loadFromSettings(); void saveBeaconsState(); void revertBeaconsState(); // Returns either sun or moon direction (depending on which is up and stronger) // Light direction in +x right, +z up, +y at internal coord sys LLVector3 getLightDirection() const; // returns sun or moon depending on which is up LLVector3 getSunDirection() const; LLVector3 getMoonDirection() const; // Returns light direction converted to CFR coord system LLVector4 getLightDirectionCFR() const; // returns sun or moon depending on which is up LLVector4 getSunDirectionCFR() const; LLVector4 getMoonDirectionCFR() const; // Returns light direction converted to OGL coord system // and clamped above -0.1f in Y to avoid render artifacts in sky shaders LLVector4 getClampedLightNorm() const; // returns sun or moon depending on which is up LLVector4 getClampedSunNorm() const; LLVector4 getClampedMoonNorm() const; // Returns light direction converted to OGL coord system // and rotated by last cam yaw needed by water rendering shaders LLVector4 getRotatedLightNorm() const; static LLSettingsWater::ptr_t createWaterFromLegacyPreset(const std::string filename, LLSD &messages); static LLSettingsSky::ptr_t createSkyFromLegacyPreset(const std::string filename, LLSD &messages); static LLSettingsDay::ptr_t createDayCycleFromLegacyPreset(const std::string filename, LLSD &messages); // Construct a new day cycle based on the environment. Replacing either the water or the sky tracks. LLSettingsDay::ptr_t createDayCycleFromEnvironment(EnvSelection_t env, LLSettingsBase::ptr_t settings); F32 getProgress() const { return (mCurrentEnvironment) ? mCurrentEnvironment->getProgress() : -1.0f; } F32 getRegionProgress() const { return (mEnvironments[ENV_REGION]) ? mEnvironments[ENV_REGION]->getProgress() : -1.0f; } void adjustRegionOffset(F32 adjust); // only used on legacy regions, to better sync the viewer with other agents //------------------------------------------- connection_t setEnvironmentChanged(env_changed_fn cb) { return mSignalEnvChanged.connect(cb); } void requestRegion(environment_apply_fn cb = environment_apply_fn()); void updateRegion(const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateRegion(const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateRegion(const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateRegion(const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void resetRegion(environment_apply_fn cb = environment_apply_fn()); void requestParcel(S32 parcel_id, environment_apply_fn cb = environment_apply_fn()); void updateParcel(S32 parcel_id, const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 track_num, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateParcel(S32 parcel_id, const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void updateParcel(S32 parcel_id, const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn()); void resetParcel(S32 parcel_id, environment_apply_fn cb = environment_apply_fn()); void selectAgentEnvironment(); S32 calculateSkyTrackForAltitude(F64 altitude); const altitude_list_t & getRegionAltitudes() const { return mTrackAltitudes; } void handleEnvironmentPush(LLSD &message); //cached uniform values from LLSD values LLShaderUniforms mWaterUniforms[LLGLSLShader::SG_COUNT]; LLShaderUniforms mSkyUniforms[LLGLSLShader::SG_COUNT]; // ======================================================================================= class DayInstance: public std::enable_shared_from_this<DayInstance> { public: typedef std::shared_ptr<DayInstance> ptr_t; static const U32 NO_ANIMATE_SKY; static const U32 NO_ANIMATE_WATER; DayInstance(EnvSelection_t env); virtual ~DayInstance() { }; virtual ptr_t clone() const; virtual bool applyTimeDelta(const LLSettingsBase::Seconds& delta); virtual void setDay(const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset); bool setSky(const LLSettingsSky::ptr_t &psky); virtual void setWater(const LLSettingsWater::ptr_t &pwater); void initialize(); bool isInitialized(); void clear(); void setSkyTrack(S32 trackno); LLSettingsDay::ptr_t getDayCycle() const { return mDayCycle; } LLSettingsSky::ptr_t getSky() const { return mSky; } LLSettingsWater::ptr_t getWater() const { return mWater; } LLSettingsDay::Seconds getDayLength() const { return mDayLength; } LLSettingsDay::Seconds getDayOffset() const { return mDayOffset; } S32 getSkyTrack() const { return mSkyTrack; } void setDayOffset(LLSettingsBase::Seconds offset) { mDayOffset = offset; animate(); } virtual void animate(); void setBlenders(const LLSettingsBlender::ptr_t &skyblend, const LLSettingsBlender::ptr_t &waterblend); EnvSelection_t getEnvironmentSelection() const { return mEnv; } void setEnvironmentSelection(EnvSelection_t env) { mEnv = env; } LLSettingsBase::TrackPosition getProgress() const; void setFlags(U32 flag) { mAnimateFlags |= flag; } void clearFlags(U32 flag) { mAnimateFlags &= ~flag; } U32 getFlags() { return mAnimateFlags; } protected: LLSettingsDay::ptr_t mDayCycle; LLSettingsSky::ptr_t mSky; LLSettingsWater::ptr_t mWater; S32 mSkyTrack; bool mInitialized; LLSettingsDay::Seconds mDayLength; LLSettingsDay::Seconds mDayOffset; S32 mLastTrackAltitude; LLSettingsBlender::ptr_t mBlenderSky; LLSettingsBlender::ptr_t mBlenderWater; EnvSelection_t mEnv; U32 mAnimateFlags; LLSettingsBase::TrackPosition secondsToKeyframe(LLSettingsDay::Seconds seconds); }; class DayTransition : public DayInstance { public: DayTransition(const LLSettingsSky::ptr_t &skystart, const LLSettingsWater::ptr_t &waterstart, DayInstance::ptr_t &end, LLSettingsDay::Seconds time); virtual ~DayTransition() { }; virtual bool applyTimeDelta(const LLSettingsBase::Seconds& delta) override; virtual void animate() override; protected: LLSettingsSky::ptr_t mStartSky; LLSettingsWater::ptr_t mStartWater; DayInstance::ptr_t mNextInstance; LLSettingsDay::Seconds mTransitionTime; }; DayInstance::ptr_t getSelectedEnvironmentInstance(); DayInstance::ptr_t getSharedEnvironmentInstance(); void initSingleton(); protected: void cleanupSingleton(); private: LLVector4 toCFR(const LLVector3 vec) const; LLVector4 toLightNorm(const LLVector3 vec) const; typedef std::array<DayInstance::ptr_t, ENV_END> InstanceArray_t; struct ExpEnvironmentEntry { typedef std::shared_ptr<ExpEnvironmentEntry> ptr_t; S32Seconds mTime; LLUUID mExperienceId; LLSD mEnvironmentOverrides; }; typedef std::deque<ExpEnvironmentEntry::ptr_t> mPushOverrides; LLUUID mPushEnvironmentExpId; static const F32 SUN_DELTA_YAW; F32 mLastCamYaw = 0.0f; LLVector2 mCloudScrollDelta; // cumulative cloud delta bool mCloudScrollPaused; InstanceArray_t mEnvironments; EnvSelection_t mSelectedEnvironment; DayInstance::ptr_t mCurrentEnvironment; LLSettingsSky::ptr_t mSelectedSky; LLSettingsWater::ptr_t mSelectedWater; LLSettingsDay::ptr_t mSelectedDay; LLSettingsBlender::ptr_t mBlenderSky; LLSettingsBlender::ptr_t mBlenderWater; env_changed_signal_t mSignalEnvChanged; S32 mCurrentTrack; altitude_list_t mTrackAltitudes; LLSD mSkyOverrides; LLSD mWaterOverrides; typedef std::map<std::string, LLUUID> experience_overrides_t; experience_overrides_t mExperienceOverrides; DayInstance::ptr_t getEnvironmentInstance(EnvSelection_t env, bool create = false); void updateCloudScroll(); void onRegionChange(); void onParcelChange(); bool mShowSunBeacon; bool mShowMoonBeacon; S32 mEditorCounter; connection_t mParcelCallbackConnection; connection_t mRegionUpdateCallbackConnection; connection_t mRegionChangeCallbackConnection; connection_t mPositionCallbackConnection; struct UpdateInfo { typedef std::shared_ptr<UpdateInfo> ptr_t; UpdateInfo(LLSettingsDay::ptr_t pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes): mDayp(pday), mSettingsAsset(), mDayLength(day_length), mDayOffset(day_offset), mAltitudes(altitudes), mDayName(), mFlags(0) { if (mDayp) { mDayName = mDayp->getName(); mFlags = mDayp->getFlags(); } } UpdateInfo(LLUUID settings_asset, std::string name, S32 day_length, S32 day_offset, altitudes_vect_t altitudes, U32 flags) : mDayp(), mSettingsAsset(settings_asset), mDayLength(day_length), mDayOffset(day_offset), mAltitudes(altitudes), mDayName(name), mFlags(flags) {} LLSettingsDay::ptr_t mDayp; LLUUID mSettingsAsset; S32 mDayLength; S32 mDayOffset; altitudes_vect_t mAltitudes; std::string mDayName; U32 mFlags; }; void coroRequestEnvironment(S32 parcel_id, environment_apply_fn apply); void coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInfo::ptr_t updates, environment_apply_fn apply); void coroResetEnvironment(S32 parcel_id, S32 track_no, environment_apply_fn apply); void recordEnvironment(S32 parcel_id, EnvironmentInfo::ptr_t environment, LLSettingsBase::Seconds transition); void onAgentPositionHasChanged(const LLVector3 &localpos); void onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsBase::Seconds transition, S32 status, S32 env_version); void onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 parcel_id, S32 day_length, S32 day_offset, altitudes_vect_t altitudes); void handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition); void handleEnvironmentPushFull(LLUUID experience_id, LLSD &message, F32 transition); void handleEnvironmentPushPartial(LLUUID experience_id, LLSD &message, F32 transition); void clearExperienceEnvironment(LLUUID experience_id, LLSettingsBase::Seconds transition_time); void setExperienceEnvironment(LLUUID experience_id, LLUUID asset_id, F32 transition_time); void setExperienceEnvironment(LLUUID experience_id, LLSD environment, F32 transition_time); void onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettingsBase::ptr_t setting, F32 transition_time, S32 status); void listenExperiencePump(const LLSD &message); void loadSkyWaterFromSettings(const LLSD &env_data, bool &valid, bool &assets_present); // for use in loadFromSettings() }; class LLTrackBlenderLoopingManual : public LLSettingsBlender { public: LLTrackBlenderLoopingManual(const LLSettingsBase::ptr_t &target, const LLSettingsDay::ptr_t &day, S32 trackno); F64 setPosition(const LLSettingsBase::TrackPosition& position); virtual void switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) override; S32 getTrack() const { return mTrackNo; } typedef std::shared_ptr<LLTrackBlenderLoopingManual> ptr_t; protected: LLSettingsDay::TrackBound_t getBoundingEntries(F64 position); F64 getSpanLength(const LLSettingsDay::TrackBound_t &bounds) const; private: LLSettingsDay::ptr_t mDay; S32 mTrackNo; F64 mPosition; LLSettingsDay::CycleTrack_t::iterator mEndMarker; }; #endif // LL_ENVIRONMENT_H