STORM-1253 WIP New day cycle editor.

Done:
* Creating new local day cycles.
* Editing existing local day cycles.
* Deleting day cycles.

To do:
* Editing region day cycle, dealing with skies in region scope.
* Handle teleport while editing a day cycle.
* Update UI when a day cycle or sky preset gets deleted.
* Make the time ctrl increase/decrease consistently.
meow-7.2.2
Vadim ProductEngine 2011-05-30 22:34:56 +03:00
parent 6f1cdd4926
commit 657e434fd5
15 changed files with 941 additions and 58 deletions

View File

@ -108,7 +108,7 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p)
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1));
mEditor->setText(LLStringExplicit("0:00 AM"));
mEditor->setText(LLStringExplicit("12:00 AM"));
addChild(mEditor);
//================= Spin Buttons ==========//
@ -130,6 +130,66 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p)
setUseBoundingRect( TRUE );
}
F32 LLTimeCtrl::getTime24() const
{
return getHours24() + getMinutes() / 60.0f;
}
U32 LLTimeCtrl::getHours24() const
{
U32 h = mHours;
if (h == 12)
{
h = 0;
}
if (mCurrentDayPeriod == PM)
{
h += 12;
}
return h;
}
U32 LLTimeCtrl::getMinutes() const
{
return mMinutes;
}
void LLTimeCtrl::setTime24(F32 time)
{
time = llclamp(time, 0.0f, 23.99f); // fix out of range values
U32 h = time;
U32 m = llround((time - h) * 60); // fixes values like 4.99999
// fix rounding error
if (m == 60)
{
m = 0;
++h;
}
mCurrentDayPeriod = (h >= 12 ? PM : AM);
if (h >= 12)
{
h -= 12;
}
if (h == 0)
{
h = 12;
}
mHours = h;
mMinutes = m;
updateText();
}
BOOL LLTimeCtrl::handleKeyHere(KEY key, MASK mask)
{
if (mEditor->hasFocus())
@ -144,6 +204,11 @@ BOOL LLTimeCtrl::handleKeyHere(KEY key, MASK mask)
onDownBtn();
return TRUE;
}
if (key == KEY_RETURN)
{
onCommit();
return TRUE;
}
}
return FALSE;
}
@ -165,8 +230,8 @@ void LLTimeCtrl::onUpBtn()
break;
}
buildTimeString();
mEditor->setText(mTimeString);
updateText();
onCommit();
}
void LLTimeCtrl::onDownBtn()
@ -186,15 +251,14 @@ void LLTimeCtrl::onDownBtn()
break;
}
buildTimeString();
mEditor->setText(mTimeString);
updateText();
onCommit();
}
void LLTimeCtrl::onFocusLost()
{
buildTimeString();
mEditor->setText(mTimeString);
updateText();
onCommit();
LLUICtrl::onFocusLost();
}
@ -300,6 +364,7 @@ LLWString LLTimeCtrl::getMinutesWString(const LLWString& wstr)
void LLTimeCtrl::increaseMinutes()
{
// *TODO: snap to 5 min
if (++mMinutes > MINUTES_MAX)
{
mMinutes = MINUTES_MIN;
@ -316,6 +381,7 @@ void LLTimeCtrl::increaseHours()
void LLTimeCtrl::decreaseMinutes()
{
// *TODO: snap to 5 min
if (mMinutes-- == MINUTES_MIN)
{
mMinutes = MINUTES_MAX;
@ -344,7 +410,7 @@ void LLTimeCtrl::switchDayPeriod()
}
}
void LLTimeCtrl::buildTimeString()
void LLTimeCtrl::updateText()
{
std::stringstream time_buf;
time_buf << mHours << ":";
@ -367,7 +433,7 @@ void LLTimeCtrl::buildTimeString()
break;
}
mTimeString = time_buf.str();
mEditor->setText(time_buf.str());
}
LLTimeCtrl::EEditingPart LLTimeCtrl::getEditingPart()

View File

@ -37,6 +37,7 @@ class LLLineEditor;
class LLTimeCtrl
: public LLUICtrl
{
LOG_CLASS(LLTimeCtrl);
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@ -51,13 +52,17 @@ public:
Params();
};
F32 getTime24() const; // 0.0 - 24.0
U32 getHours24() const; // 0 - 23
U32 getMinutes() const; // 0 - 59
void setTime24(F32 time); // 0.0 - 23.98(3)
protected:
LLTimeCtrl(const Params&);
friend class LLUICtrlFactory;
U32 getHours() const { return mHours; }
U32 getMinutes() const { return mMinutes; }
private:
enum EDayPeriod
@ -101,7 +106,7 @@ private:
void switchDayPeriod();
void buildTimeString();
void updateText();
EEditingPart getEditingPart();
@ -114,11 +119,9 @@ private:
class LLButton* mUpBtn;
class LLButton* mDownBtn;
U32 mHours;
U32 mMinutes;
EDayPeriod mCurrentDayPeriod;
std::string mTimeString;
U32 mHours; // 1 - 12
U32 mMinutes; // 0 - 59
EDayPeriod mCurrentDayPeriod; // AM/PM
BOOL mAllowEdit;
};

View File

@ -38,7 +38,7 @@ const LLDayCycleManager::dc_map_t& LLDayCycleManager::getPresets()
return mDayCycleMap;
}
bool LLDayCycleManager::getPreset(const std::string name, LLWLDayCycle& day_cycle)
bool LLDayCycleManager::getPreset(const std::string name, LLWLDayCycle& day_cycle) const
{
dc_map_t::const_iterator it = mDayCycleMap.find(name);
if (it == mDayCycleMap.end())
@ -50,7 +50,7 @@ bool LLDayCycleManager::getPreset(const std::string name, LLWLDayCycle& day_cycl
return true;
}
bool LLDayCycleManager::getPreset(const std::string name, LLSD& day_cycle)
bool LLDayCycleManager::getPreset(const std::string name, LLSD& day_cycle) const
{
LLWLDayCycle dc;
if (!getPreset(name, dc))
@ -62,6 +62,46 @@ bool LLDayCycleManager::getPreset(const std::string name, LLSD& day_cycle)
return true;
}
bool LLDayCycleManager::presetExists(const std::string name) const
{
LLWLDayCycle dummy;
return getPreset(name, dummy);
}
bool LLDayCycleManager::isSystemPreset(const std::string& name) const
{
return gDirUtilp->fileExists(getSysDir() + LLURI::escape(name) + ".xml");
}
bool LLDayCycleManager::savePreset(const std::string& name, const LLSD& data)
{
// Save given preset.
LLWLDayCycle day;
day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
day.save(getUserDir() + LLURI::escape(name) + ".xml");
// Add it to our map.
addPreset(name, data);
return true;
}
bool LLDayCycleManager::deletePreset(const std::string& name)
{
std::string path;
std::string filename = LLURI::escape(name) + ".xml";
// Try removing specified user preset.
path = getUserDir() + filename;
if (gDirUtilp->fileExists(path))
{
gDirUtilp->deleteFilesInDir(getUserDir(), filename);
return true;
}
// Invalid or system preset.
return false;
}
// virtual
void LLDayCycleManager::initSingleton()
{
@ -102,13 +142,25 @@ bool LLDayCycleManager::loadPreset(const std::string& path)
}
std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
LLWLDayCycle day_cycle;
day_cycle.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
mDayCycleMap[name] = day_cycle;
addPreset(name, data);
return true;
}
bool LLDayCycleManager::addPreset(const std::string& name, const LLSD& data)
{
if (name.empty())
{
llassert(name.empty());
return false;
}
LLWLDayCycle day;
day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
mDayCycleMap[name] = day;
return false;
}
// static
std::string LLDayCycleManager::getSysDir()
{

View File

@ -46,8 +46,12 @@ public:
typedef std::map<std::string, LLWLDayCycle> dc_map_t;
const dc_map_t& getPresets();
bool getPreset(const std::string name, LLWLDayCycle& day_cycle);
bool getPreset(const std::string name, LLSD& day_cycle);
bool getPreset(const std::string name, LLWLDayCycle& day_cycle) const;
bool getPreset(const std::string name, LLSD& day_cycle) const;
bool presetExists(const std::string name) const;
bool isSystemPreset(const std::string& name) const;
bool savePreset(const std::string& name, const LLSD& data);
bool deletePreset(const std::string& name);
private:
friend class LLSingleton<LLDayCycleManager>;
@ -56,6 +60,7 @@ private:
void loadAllPresets();
void loadPresets(const std::string& dir);
bool loadPreset(const std::string& path);
bool addPreset(const std::string& name, const LLSD& data);
static std::string getSysDir();
static std::string getUserDir();

View File

@ -746,6 +746,7 @@ void LLEnvManagerNew::setUseRegionSettings(bool val)
void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
{
// *TODO: make sure the preset exists.
if (name.empty())
{
llwarns << "Empty water preset name passed" << llendl;
@ -759,6 +760,7 @@ void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
{
// *TODO: make sure the preset exists.
if (name.empty())
{
llwarns << "Empty sky preset name passed" << llendl;
@ -772,9 +774,9 @@ void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
void LLEnvManagerNew::setUseDayCycle(const std::string& name)
{
if (name.empty())
if (!LLDayCycleManager::instance().presetExists(name))
{
llwarns << "Empty day cycle name passed" << llendl;
llwarns << "Invalid day cycle name passed" << llendl;
return;
}
@ -939,6 +941,8 @@ void LLEnvManagerNew::onRegionChange(bool interpolate)
return;
}
// *TODO: clear environment settings of the previous region?
// Request environment settings of the new region.
LL_DEBUGS("Windlight") << "New viewer region: " << region_uuid << LL_ENDL;
mCurRegionUUID = region_uuid;

View File

@ -31,11 +31,23 @@
// libs
#include "llbutton.h"
#include "llcombobox.h"
#include "llnotificationsutil.h"
// newview
#include "lldaycyclemanager.h"
#include "llwaterparammanager.h"
static bool confirmation_callback(const LLSD& notification, const LLSD& response, boost::function<void()> cb)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
cb();
}
return false;
}
LLFloaterDeleteEnvPreset::LLFloaterDeleteEnvPreset(const LLSD &key)
: LLFloater(key)
, mPresetCombo(NULL)
@ -50,9 +62,6 @@ BOOL LLFloaterDeleteEnvPreset::postBuild()
getChild<LLButton>("delete")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnDelete, this));
getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnCancel, this));
// Deletion is not implemented yet, so disable the button for now.
getChild<LLButton>("delete")->setEnabled(FALSE);
return TRUE;
}
@ -70,14 +79,15 @@ void LLFloaterDeleteEnvPreset::onOpen(const LLSD& key)
getChild<LLUICtrl>("label")->setValue(combo_label);
// Populate the combobox.
mPresetCombo->removeall();
if (param == "water")
{
populateWaterPresetsList();
getChild<LLButton>("delete")->setEnabled(FALSE); // not implemented yet
}
else if (param == "sky")
{
populateSkyPresetsList();
getChild<LLButton>("delete")->setEnabled(FALSE); // not implemented yet
}
else if (param == "day_cycle")
{
@ -91,7 +101,42 @@ void LLFloaterDeleteEnvPreset::onOpen(const LLSD& key)
void LLFloaterDeleteEnvPreset::onBtnDelete()
{
closeFloater();
std::string param = mKey.asString();
boost::function<void()> confirm_cb;
if (param == "water")
{
llwarns << "Deleting water presets not implemented" << llendl;
return;
}
else if (param == "sky")
{
llwarns << "Deleting sky presets not implemented" << llendl;
return;
}
else if (param == "day_cycle")
{
LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
std::string preset_name = mPresetCombo->getValue().asString();
// Don't allow deleting system presets.
if (day_mgr.isSystemPreset(preset_name))
{
LLNotificationsUtil::add("WLNoEditDefault");
return;
}
confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation, this);
}
else
{
llwarns << "Unrecognized key" << llendl;
}
LLSD args;
args["MESSAGE"] = getString("msg_confirm_deletion");
LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(),
boost::bind(&confirmation_callback, _1, _2, confirm_cb));
}
void LLFloaterDeleteEnvPreset::onBtnCancel()
@ -101,6 +146,8 @@ void LLFloaterDeleteEnvPreset::onBtnCancel()
void LLFloaterDeleteEnvPreset::populateWaterPresetsList()
{
mPresetCombo->removeall();
// *TODO: Reload the list when user preferences change.
LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
LL_DEBUGS("Windlight") << "Current water preset: " << water_mgr.mCurParams.mName << LL_ENDL;
@ -116,6 +163,9 @@ void LLFloaterDeleteEnvPreset::populateWaterPresetsList()
void LLFloaterDeleteEnvPreset::populateSkyPresetsList()
{
mPresetCombo->removeall();
// *TODO: Reload the list when user preferences change.
LLWLParamManager& sky_mgr = LLWLParamManager::instance();
LL_DEBUGS("Windlight") << "Current sky preset: " << sky_mgr.mCurParams.mName << LL_ENDL;
@ -130,6 +180,8 @@ void LLFloaterDeleteEnvPreset::populateSkyPresetsList()
void LLFloaterDeleteEnvPreset::populateDayCyclesList()
{
mPresetCombo->removeall();
// *TODO: Disable current day cycle.
const LLDayCycleManager::dc_map_t& map = LLDayCycleManager::instance().getPresets();
for (LLDayCycleManager::dc_map_t::const_iterator it = map.begin(); it != map.end(); ++it)
@ -137,3 +189,9 @@ void LLFloaterDeleteEnvPreset::populateDayCyclesList()
mPresetCombo->add(it->first);
}
}
void LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation()
{
LLDayCycleManager::instance().deletePreset(mPresetCombo->getValue().asString());
populateDayCyclesList();
}

View File

@ -49,6 +49,8 @@ private:
void populateSkyPresetsList();
void populateDayCyclesList();
void onDeleteDayCycleConfirmation();
LLComboBox* mPresetCombo;
};

View File

@ -30,22 +30,53 @@
// libs
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llmultisliderctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llspinctrl.h"
#include "lltimectrl.h"
// newview
#include "llagent.h"
#include "lldaycyclemanager.h"
#include "llenvmanager.h"
#include "llviewerregion.h"
#include "llwlparammanager.h"
const F32 LLFloaterEditDayCycle::sHoursPerDay = 24.0f;
LLFloaterEditDayCycle::LLFloaterEditDayCycle(const LLSD &key)
: LLFloater(key)
, mDayCycleNameEditor(NULL)
, mDayCyclesCombo(NULL)
, mTimeSlider(NULL)
, mKeysSlider(NULL)
, mSkyPresetsCombo(NULL)
, mTimeCtrl(NULL)
, mMakeDefaultCheckBox(NULL)
, mSaveButton(NULL)
{
}
// virtual
BOOL LLFloaterEditDayCycle::postBuild()
{
getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnCancel, this));
mDayCycleNameEditor = getChild<LLLineEditor>("day_cycle_name");
mDayCyclesCombo = getChild<LLComboBox>("day_cycle_combo");
// Disable some non-functional controls.
getChildView("day_cycle_combo")->setEnabled(FALSE);
getChildView("save")->setEnabled(FALSE);
mTimeSlider = getChild<LLMultiSliderCtrl>("WLTimeSlider");
mKeysSlider = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
mSkyPresetsCombo = getChild<LLComboBox>("WLSkyPresets");
mTimeCtrl = getChild<LLTimeCtrl>("time");
mSaveButton = getChild<LLButton>("save");
mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
initCallbacks();
// add the time slider
mTimeSlider->addSlider();
return TRUE;
}
@ -53,6 +84,7 @@ BOOL LLFloaterEditDayCycle::postBuild()
// virtual
void LLFloaterEditDayCycle::onOpen(const LLSD& key)
{
bool new_day = isNewDay();
std::string param = key.asString();
std::string floater_title = getString(std::string("title_") + param);
std::string hint = getString(std::string("hint_" + param));
@ -64,10 +96,567 @@ void LLFloaterEditDayCycle::onOpen(const LLSD& key)
getChild<LLUICtrl>("hint")->setValue(hint);
// Hide the hint to the right of the combo if we're invoked to create a new preset.
getChildView("note")->setVisible(param == "edit");
getChildView("note")->setVisible(!new_day);
// Switch between the day cycle presets combobox and day cycle name input field.
mDayCyclesCombo->setVisible(!new_day);
mDayCycleNameEditor->setVisible(new_day);
// TODO: Make sure only one instance of the floater exists?
reset();
}
// virtual
void LLFloaterEditDayCycle::onClose(bool app_quitting)
{
if (!app_quitting) // there's no point to change environment if we're quitting
{
LLEnvManagerNew::instance().usePrefs(); // revert changes made to current day cycle
}
}
// virtual
void LLFloaterEditDayCycle::draw()
{
syncTimeSlider();
LLFloater::draw();
}
void LLFloaterEditDayCycle::initCallbacks(void)
{
mDayCycleNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleNameEdited, this), NULL);
mDayCyclesCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleSelected, this));
mTimeSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onTimeSliderMoved, this));
mKeysSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeMoved, this));
mTimeCtrl->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeChanged, this));
mSkyPresetsCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyPresetChanged, this));
getChild<LLButton>("WLAddKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onAddKey, this));
getChild<LLButton>("WLDeleteKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onDeleteKey, this));
mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnSave, this));
mSaveButton->setRightMouseDownCallback(boost::bind(&LLFloaterEditDayCycle::dumpTrack, this));
getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnCancel, this));
}
void LLFloaterEditDayCycle::syncTimeSlider()
{
// set time
mTimeSlider->setCurSliderValue((F32)LLWLParamManager::getInstance()->mAnimator.getDayTime() * sHoursPerDay);
}
void LLFloaterEditDayCycle::loadTrack()
{
// clear the slider
mKeysSlider->clear();
mSliderToKey.clear();
// add sliders
lldebugs << "Adding " << LLWLParamManager::getInstance()->mDay.mTimeMap.size() << " keys to slider" << llendl;
LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
{
addSliderKey(it->first * sHoursPerDay, it->second);
}
// set drop-down menu to match preset of currently-selected keyframe (one is automatically selected initially)
const std::string& cur_sldr = mKeysSlider->getCurSlider();
if (strlen(cur_sldr.c_str()) > 0) // only do this if there is a curSldr, otherwise we put an invalid entry into the map
{
mSkyPresetsCombo->selectByValue(mSliderToKey[cur_sldr].keyframe.toStringVal());
}
syncTimeSlider();
}
void LLFloaterEditDayCycle::applyTrack()
{
lldebugs << "Applying track (" << mSliderToKey.size() << ")" << llendl;
// if no keys, do nothing
if (mSliderToKey.size() == 0)
{
lldebugs << "No keys, not syncing" << llendl;
return;
}
llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
// create a new animation track
LLWLParamManager::getInstance()->mDay.clearKeyframes();
// add the keys one by one
for (std::map<std::string, SliderKey>::iterator it = mSliderToKey.begin();
it != mSliderToKey.end(); ++it)
{
LLWLParamManager::getInstance()->mDay.addKeyframe(it->second.time / sHoursPerDay,
it->second.keyframe);
}
// set the param manager's track to the new one
LL_DEBUGS("Windlight") << "Time slider val: " << mTimeSlider->getCurSliderValue() / sHoursPerDay << " (" << mTimeSlider->getCurSliderValue() << ")" << LL_ENDL;
LLWLParamManager::getInstance()->resetAnimator(
mTimeSlider->getCurSliderValue() / sHoursPerDay, false);
LLWLParamManager::getInstance()->mAnimator.update(
LLWLParamManager::getInstance()->mCurParams);
}
void LLFloaterEditDayCycle::refreshSkyPresetsList()
{
LLWLParamManager& sky_mgr = LLWLParamManager::instance();
for (std::map<LLWLParamKey, LLWLParamSet>::iterator it = sky_mgr.mParamList.begin();
it != sky_mgr.mParamList.end(); ++it)
{
const LLWLParamKey& key = it->first;
std::string item_title = key.name;
if (key.scope == LLEnvKey::SCOPE_REGION)
{
item_title += " (" + getRegionName() + ")";
}
mSkyPresetsCombo->add(item_title, LLSD(key.toStringVal()));
}
// set defaults on combo boxes
mSkyPresetsCombo->selectFirstItem();
}
void LLFloaterEditDayCycle::refreshDayCyclesList()
{
llassert(isNewDay() == false);
mDayCyclesCombo->removeall();
const LLSD& region_day = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
if (region_day.size() > 0)
{
LLWLParamKey key(getRegionName(), LLEnvKey::SCOPE_REGION);
mDayCyclesCombo->add(key.name, key.toLLSD());
mDayCyclesCombo->addSeparator();
}
const LLDayCycleManager::dc_map_t& map = LLDayCycleManager::instance().getPresets();
for (LLDayCycleManager::dc_map_t::const_iterator it = map.begin(); it != map.end(); ++it)
{
LLWLParamKey key(it->first, LLEnvKey::SCOPE_LOCAL);
mDayCyclesCombo->add(key.name, key.toLLSD());
}
mDayCyclesCombo->setLabel(getString("combo_label"));
}
void LLFloaterEditDayCycle::onTimeSliderMoved()
{
/// get the slider value
F32 val = mTimeSlider->getCurSliderValue() / sHoursPerDay;
LL_DEBUGS("Windlight") << "Time slider val: " << val << " (" << mTimeSlider->getCurSliderValue() << ")" << LL_ENDL;
// set the value, turn off animation
LLWLParamManager::getInstance()->mAnimator.setDayTime((F64)val);
LLWLParamManager::getInstance()->mAnimator.deactivate();
// then call update once
LLWLParamManager::getInstance()->mAnimator.update(
LLWLParamManager::getInstance()->mCurParams);
}
void LLFloaterEditDayCycle::onKeyTimeMoved()
{
if (mKeysSlider->getValue().size() == 0)
{
return;
}
// make sure we have a slider
const std::string& cur_sldr = mKeysSlider->getCurSlider();
if (cur_sldr == "")
{
return;
}
F32 time24 = mKeysSlider->getCurSliderValue();
// check to see if a key exists
LLWLParamKey key = mSliderToKey[cur_sldr].keyframe;
lldebugs << "Setting key time: " << time24 << LL_ENDL;
mSliderToKey[cur_sldr].time = time24;
// if it exists, turn on check box
mSkyPresetsCombo->selectByValue(key.toStringVal());
mTimeCtrl->setTime24(time24);
applyTrack();
}
void LLFloaterEditDayCycle::onKeyTimeChanged()
{
// if no keys, skipped
if (mSliderToKey.size() == 0)
{
return;
}
F32 time24 = mTimeCtrl->getTime24();
const std::string& cur_sldr = mKeysSlider->getCurSlider();
mKeysSlider->setCurSliderValue(time24, TRUE);
F32 time = mKeysSlider->getCurSliderValue() / sHoursPerDay;
// now set the key's time in the sliderToKey map
lldebugs << "Setting key time: " << time << LL_ENDL;
mSliderToKey[cur_sldr].time = time;
applyTrack();
}
void LLFloaterEditDayCycle::onKeyPresetChanged()
{
// do nothing if no sliders
if (mKeysSlider->getValue().size() == 0)
{
return;
}
// change the map
std::string stringVal = mSkyPresetsCombo->getSelectedValue().asString();
LLWLParamKey new_key(stringVal);
const std::string& cur_sldr = mKeysSlider->getCurSlider();
// if null, don't use
if (cur_sldr == "")
{
return;
}
mSliderToKey[cur_sldr].keyframe = new_key;
// Apply changes to current day cycle.
applyTrack();
}
void LLFloaterEditDayCycle::onAddKey()
{
llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
S32 max_sliders;
LLEnvKey::EScope scope = LLEnvKey::SCOPE_LOCAL; // *TODO: editing region day cycle
switch (scope)
{
case LLEnvKey::SCOPE_LOCAL:
max_sliders = 20; // *HACK this should be LLWLPacketScrubber::MAX_LOCAL_KEY_FRAMES;
break;
case LLEnvKey::SCOPE_REGION:
max_sliders = 12; // *HACK this should be LLWLPacketScrubber::MAX_REGION_KEY_FRAMES;
break;
default:
max_sliders = (S32) mKeysSlider->getMaxValue();
break;
}
if ((S32)mSliderToKey.size() >= max_sliders)
{
LLSD args;
args["SCOPE"] = LLEnvManager::getScopeString(scope);
args["MAX"] = max_sliders;
LLNotificationsUtil::add("DayCycleTooManyKeyframes", args, LLSD(), LLNotificationFunctorRegistry::instance().DONOTHING);
return;
}
// add the slider key
LLWLParamKey sky_params(mSkyPresetsCombo->getSelectedValue());
F32 time = mTimeSlider->getCurSliderValue();
addSliderKey(time, sky_params);
// apply the change to current day cycles
applyTrack();
}
void LLFloaterEditDayCycle::addSliderKey(F32 time, LLWLParamKey keyframe)
{
// make a slider
const std::string& sldr_name = mKeysSlider->addSlider(time);
if (sldr_name.empty())
{
return;
}
// set the key
SliderKey newKey(keyframe, mKeysSlider->getCurSliderValue());
llassert_always(sldr_name != LLStringUtil::null);
// add to map
mSliderToKey.insert(std::pair<std::string, SliderKey>(sldr_name, newKey));
llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
}
LLWLParamKey LLFloaterEditDayCycle::getSelectedDayCycle()
{
LLWLParamKey dc_key;
if (mDayCycleNameEditor->getVisible())
{
dc_key.name = mDayCycleNameEditor->getText();
dc_key.scope = LLEnvKey::SCOPE_LOCAL;
}
else
{
LLSD combo_val = mDayCyclesCombo->getValue();
if (!combo_val.isArray()) // manually typed text
{
dc_key.name = combo_val.asString();
dc_key.scope = LLEnvKey::SCOPE_LOCAL;
}
else
{
dc_key.fromLLSD(combo_val);
}
}
return dc_key;
}
void LLFloaterEditDayCycle::deletePreset(LLWLParamKey keyframe)
{
// *TODO: This should be called when a sky preset gets deleted.
/// delete any reference
std::map<std::string, SliderKey>::iterator curr_preset, next_preset;
for (curr_preset = mSliderToKey.begin(); curr_preset != mSliderToKey.end(); curr_preset = next_preset)
{
next_preset = curr_preset;
++next_preset;
if (curr_preset->second.keyframe == keyframe)
{
mKeysSlider->deleteSlider(curr_preset->first);
mSliderToKey.erase(curr_preset);
}
}
}
bool LLFloaterEditDayCycle::isNewDay() const
{
return mKey.asString() == "new";
}
void LLFloaterEditDayCycle::dumpTrack()
{
LL_DEBUGS("Windlight") << "Dumping day cycle" << LL_ENDL;
LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
{
F32 time = it->first * 24.0f;
S32 h = time;
S32 m = (time - h) * 60.0f;
LL_DEBUGS("Windlight") << llformat("(%.3f) %02d:%02d", time, h, m) << " => " << it->second.name << LL_ENDL;
}
}
void LLFloaterEditDayCycle::enableEditing(bool enable)
{
mSkyPresetsCombo->setEnabled(enable);
mTimeCtrl->setEnabled(enable);
getChild<LLPanel>("day_cycle_slider_panel")->setCtrlsEnabled(enable);
mSaveButton->setEnabled(enable);
mMakeDefaultCheckBox->setEnabled(enable);
}
void LLFloaterEditDayCycle::reset()
{
// clear the slider
mKeysSlider->clear();
mSliderToKey.clear();
refreshSkyPresetsList();
if (isNewDay())
{
mDayCycleNameEditor->setValue(LLSD());
F32 time = 0.5f * sHoursPerDay;
mSaveButton->setEnabled(FALSE); // will be enabled as soon as users enters a name
mTimeSlider->setCurSliderValue(time);
addSliderKey(time, LLWLParamKey("Default", LLEnvKey::SCOPE_LOCAL));
onKeyTimeMoved(); // update the time control and sky sky combo
applyTrack();
}
else
{
refreshDayCyclesList();
// Disable controls until a day cycle to edit is selected.
enableEditing(false);
}
}
void LLFloaterEditDayCycle::onDeleteKey()
{
if (mSliderToKey.size() == 0)
{
return;
}
else if (mSliderToKey.size() == 1)
{
LLNotifications::instance().add("EnvCannotDeleteLastDayCycleKey", LLSD(), LLSD());
return;
}
// delete from map
const std::string& sldr_name = mKeysSlider->getCurSlider();
std::map<std::string, SliderKey>::iterator mIt = mSliderToKey.find(sldr_name);
mSliderToKey.erase(mIt);
mKeysSlider->deleteCurSlider();
if (mSliderToKey.size() == 0)
{
return;
}
const std::string& name = mKeysSlider->getCurSlider();
mSkyPresetsCombo->selectByValue(mSliderToKey[name].keyframe.toStringVal());
F32 time24 = mSliderToKey[name].time;
mTimeCtrl->setTime24(time24);
applyTrack();
}
void LLFloaterEditDayCycle::onDayCycleNameEdited()
{
// Disable saving a day cycle having empty name.
LLWLParamKey key = getSelectedDayCycle();
mSaveButton->setEnabled(!key.name.empty());
}
void LLFloaterEditDayCycle::onDayCycleSelected()
{
LLSD day_data;
LLWLParamKey dc_key = getSelectedDayCycle();
if (dc_key.scope == LLEnvKey::SCOPE_LOCAL)
{
if (!LLDayCycleManager::instance().getPreset(dc_key.name, day_data))
{
llwarns << "No day cycle named " << dc_key.name << llendl;
return;
}
}
else
{
day_data = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
if (day_data.size() == 0)
{
llwarns << "Empty region day cycle" << llendl;
llassert(day_data.size() > 0);
return;
}
}
F32 slider_time = mTimeSlider->getCurSliderValue() / sHoursPerDay;
LL_DEBUGS("Windlight") << "Time slider val: " << slider_time << " (" << mTimeSlider->getCurSliderValue() << ")" << LL_ENDL;
LLWLParamManager::instance().applyDayCycleParams(day_data, dc_key.scope, slider_time);
loadTrack();
enableEditing(true);
}
void LLFloaterEditDayCycle::onBtnSave()
{
LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
LLWLParamKey selected_day = getSelectedDayCycle();
if (selected_day.scope == LLEnvKey::SCOPE_REGION)
{
llwarns << "Saving to a local day cycle" << llendl;
}
std::string name = selected_day.name;
if (name.empty())
{
// *TODO: show an alert
llwarns << "Empty day cycle name" << llendl;
return;
}
// Don't allow overwriting system presets.
if (day_mgr.isSystemPreset(name))
{
LLNotificationsUtil::add("WLNoEditDefault");
return;
}
// Save, ask for confirmation for overwriting an existing preset.
if (day_mgr.presetExists(name))
{
LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditDayCycle::onSaveAnswer, this, _1, _2));
}
else
{
// new preset, hence no confirmation needed
onSaveConfirmed();
}
}
void LLFloaterEditDayCycle::onBtnCancel()
{
#if 0 // temporary
onClose(false);
reset();
#else
closeFloater();
#endif
}
bool LLFloaterEditDayCycle::onSaveAnswer(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// If they choose save, do it. Otherwise, don't do anything
if (option == 0)
{
onSaveConfirmed();
}
return false;
}
void LLFloaterEditDayCycle::onSaveConfirmed()
{
std::string name = getSelectedDayCycle().name;
// Save preset.
LLSD data = LLWLParamManager::instance().mDay.asLLSD();
LL_DEBUGS("Windlight") << "Saving day cycle " << name << ": " << data << LL_ENDL;
LLDayCycleManager::instance().savePreset(name, data);
// Change preference if requested.
if (mMakeDefaultCheckBox->getValue())
{
LL_DEBUGS("Windlight") << name << " is now the new preferred day cycle" << llendl;
LLEnvManagerNew::instance().setUseDayCycle(name);
}
#if 0 // temporary
reset();
#else
closeFloater();
#endif
}
// static
std::string LLFloaterEditDayCycle::getRegionName()
{
return gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
}

View File

@ -29,6 +29,16 @@
#include "llfloater.h"
#include "llwlparammanager.h" // for LLWLParamKey
class LLCheckBoxCtrl;
class LLComboBox;
class LLLineEditor;
class LLMultiSliderCtrl;
class LLTimeCtrl;
/// Menu for all of windlight's functionality.
/// Menuing system for adjusting the atmospheric settings of the world.
class LLFloaterEditDayCycle : public LLFloater
{
LOG_CLASS(LLFloaterEditDayCycle);
@ -38,8 +48,78 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void draw();
private:
/// sync the time slider with day cycle structure
void syncTimeSlider();
// makes sure key slider has what's in day cycle
void loadTrack();
/// makes sure day cycle data structure has what's in menu
void applyTrack();
/// refresh the sky presets combobox
void refreshSkyPresetsList();
/// refresh the day cycle combobox
void refreshDayCyclesList();
/// add a slider to the track
void addSliderKey(F32 time, LLWLParamKey keyframe);
void initCallbacks();
LLWLParamKey getSelectedDayCycle();
void deletePreset(LLWLParamKey keyframe);
bool isNewDay() const;
void dumpTrack();
void enableEditing(bool enable);
void reset();
void onTimeSliderMoved(); /// time slider moved
void onKeyTimeMoved(); /// a key frame moved
void onKeyTimeChanged(); /// a key frame's time changed
void onKeyPresetChanged(); /// sky preset selected
void onAddKey(); /// new key added on slider
void onDeleteKey(); /// a key frame deleted
void onDayCycleNameEdited();
void onDayCycleSelected();
void onBtnSave();
void onBtnCancel();
bool onSaveAnswer(const LLSD& notification, const LLSD& response);
void onSaveConfirmed();
static std::string getRegionName();
/// convenience class for holding keyframes mapped to sliders
struct SliderKey
{
public:
SliderKey(LLWLParamKey kf, F32 t) : keyframe(kf), time(t) {}
SliderKey() : keyframe(), time(0.f) {} // Don't use this default constructor
LLWLParamKey keyframe;
F32 time;
};
static const F32 sHoursPerDay;
LLLineEditor* mDayCycleNameEditor;
LLComboBox* mDayCyclesCombo;
LLMultiSliderCtrl* mTimeSlider;
LLMultiSliderCtrl* mKeysSlider;
LLComboBox* mSkyPresetsCombo;
LLTimeCtrl* mTimeCtrl;
LLCheckBoxCtrl* mMakeDefaultCheckBox;
LLButton* mSaveButton;
// map of sliders to parameters
std::map<std::string, SliderKey> mSliderToKey;
};
#endif // LL_LLFLOATEREDITDAYCYCLE_H

View File

@ -82,7 +82,13 @@ BOOL LLFloaterWindLight::postBuild()
LLWLParamManager::getInstance()->mParamList.begin();
for(; mIt != LLWLParamManager::getInstance()->mParamList.end(); mIt++)
{
comboBox->add(mIt->first.toString(), mIt->first.toLLSD());
const LLWLParamKey& key = mIt->first;
std::string item_title = key.name;
if (key.scope == LLEnvKey::SCOPE_REGION)
{
item_title += std::string(" (") + LLTrans::getString("Region") + std::string(")");
}
comboBox->add(item_title, key.toLLSD());
}
// entry for when we're in estate time

View File

@ -127,12 +127,17 @@ LLSD LLWLDayCycle::loadDayCycleFromPath(const std::string& file_path)
void LLWLDayCycle::saveDayCycle(const std::string & fileName)
{
LLSD day_data = asLLSD();
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/days", fileName));
//llinfos << "Saving WindLight settings to " << pathName << llendl;
llofstream day_cycle_xml(pathName);
save(pathName);
}
void LLWLDayCycle::save(const std::string& file_path)
{
LLSD day_data = asLLSD();
llofstream day_cycle_xml(file_path);
LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
formatter->format(day_data, day_cycle_xml, LLSDFormatter::OPTIONS_PRETTY);
day_cycle_xml.close();

View File

@ -62,9 +62,12 @@ public:
/// load a day cycle
void loadDayCycleFromFile(const std::string & fileName);
/// load a day cycle
/// save a day cycle
void saveDayCycle(const std::string & fileName);
/// save a day cycle
void save(const std::string& file_path);
/// load the LLSD data from a file (returns the undefined LLSD if not found)
static LLSD loadCycleDataFromFile(const std::string & fileName);

View File

@ -139,7 +139,7 @@ public:
}
inline LLWLParamKey() // NOT really valid, just so std::maps can return a default of some sort
: name(NULL), scope(SCOPE_LOCAL)
: name(""), scope(SCOPE_LOCAL)
{
}
@ -168,6 +168,12 @@ public:
return llsd;
}
inline void fromLLSD(const LLSD& llsd)
{
name = llsd[NAME_IDX].asString();
scope = EScope(llsd[SCOPE_IDX].asInteger());
}
inline bool operator <(const LLWLParamKey other) const
{
if (name < other.name)

View File

@ -16,6 +16,8 @@
<string name="label_water">Preset:</string>
<string name="label_sky">Preset:</string>
<string name="label_day_cycle">Day cycle:</string>
<string name="msg_confirm_deletion">Are you sure you want to delete the selected preset?</string>
<text
follows="top|left|right"

View File

@ -13,6 +13,7 @@
<string name="title_edit">Edit Day Cycle</string>
<string name="hint_new">Name your day cycle, adjust the controls to create it, and click "Save".</string>
<string name="hint_edit">To edit your day cycle, adjust the controls below and click "Save".</string>
<string name="combo_label">-Select a preset-</string>
<text
follows="top|left|right"
@ -42,12 +43,14 @@
left_pad="10"
name="day_cycle_combo"
top_delta="-5"
width="200">
<combo_box.item
label="-Select a preset-"
name="item0"
value="any" />
</combo_box>
width="200" />
<line_editor
height="20"
left_delta="0"
name="day_cycle_name"
top_delta="0"
visible="true"
width="200" />
<text
follows="top|left|right"
height="40"
@ -110,7 +113,7 @@
<panel
follows="top|left"
height="100"
name="day_cycle_slider"
name="day_cycle_slider_panel"
layout="topleft"
left_delta="25"
top_pad="25"
@ -428,7 +431,7 @@
label="Preset"
layout="topleft"
left_pad="5"
name="WLKeyPresets"
name="WLSkyPresets"
width="205" />
<text
type="string"
@ -444,24 +447,23 @@
width="35">
Time:
</text>
<text_editor
allow_scroll="false"
follows="left|top|right"
font="SansSerif"
<time
follows="left|top"
height="16"
label_width="0"
layout="topleft"
left_pad="3"
name="time"
top_delta="-1"
value="6:00 AM"
width="60"/>
width="75"/>
<check_box
follows="top|left"
height="10"
label="Make this my new day cycle"
layout="topleft"
left="330"
name="new_water_preset_chb"
name="make_default_cb"
top="430"
width="280"/>
<button