|
28 | 28 |
|
29 | 29 | #include "llfloaterenvironmentadjust.h" |
30 | 30 |
|
| 31 | +#include "llcolorswatch.h" |
| 32 | +#include "llenvironment.h" |
| 33 | +#include "llinventorymodel.h" |
| 34 | +#include "llinventorypanel.h" // For opening after saving |
31 | 35 | #include "llnotificationsutil.h" |
| 36 | +#include "llsettingsvo.h" |
32 | 37 | #include "llslider.h" |
33 | 38 | #include "llsliderctrl.h" |
34 | | -#include "llcolorswatch.h" |
35 | 39 | #include "lltexturectrl.h" |
36 | 40 | #include "llvirtualtrackball.h" |
37 | | -#include "llenvironment.h" |
38 | 41 | #include "llviewercontrol.h" |
39 | 42 | #include "pipeline.h" |
40 | 43 |
|
| 44 | + |
41 | 45 | //========================================================================= |
42 | 46 | namespace |
43 | 47 | { |
@@ -65,6 +69,7 @@ namespace |
65 | 69 | const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation"); |
66 | 70 | const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance"); |
67 | 71 | const std::string BTN_RESET("btn_reset"); |
| 72 | + const std::string BTN_SAVE_AS("btn_save_as"); |
68 | 73 |
|
69 | 74 | const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f); |
70 | 75 | const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f); |
@@ -110,6 +115,7 @@ bool LLFloaterEnvironmentAdjust::postBuild() |
110 | 115 | getChild<LLUICtrl>(FIELD_SKY_MOON_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); |
111 | 116 | getChild<LLUICtrl>(FIELD_SKY_MOON_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); |
112 | 117 | getChild<LLUICtrl>(BTN_RESET)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onButtonReset(); }); |
| 118 | + getChild<LLUICtrl>(BTN_SAVE_AS)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onButtonSaveAs(); }); |
113 | 119 |
|
114 | 120 | getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudMapChanged(); }); |
115 | 121 | getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setDefaultImageAssetID(LLSettingsSky::GetDefaultCloudNoiseTextureId()); |
@@ -258,8 +264,114 @@ void LLFloaterEnvironmentAdjust::onButtonReset() |
258 | 264 | LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); |
259 | 265 | } |
260 | 266 | }); |
| 267 | +} |
| 268 | + |
| 269 | +void LLFloaterEnvironmentAdjust::onButtonSaveAs() |
| 270 | +{ |
| 271 | + // Note that this saves only the sky, not water. |
| 272 | + // Water is represented as a single texture here, for now |
| 273 | + // might be not worth saving. Consider saving water as well |
| 274 | + // or alternatively generating a day cycle (fixed ones are |
| 275 | + // easier to export/import). |
| 276 | + if (!mLiveSky) |
| 277 | + return; |
| 278 | + |
| 279 | + // Verify every texture embedded in the sky settings is either |
| 280 | + // a sky default, a predefined/library texture, or a copy-permitted |
| 281 | + // inventory item owned by the agent. Collect all failing textures |
| 282 | + // into one list and show a single notification. |
| 283 | + struct TexEntry { LLUUID id; std::string name; }; |
| 284 | + const std::vector<TexEntry> textures_to_check = |
| 285 | + { |
| 286 | + { mLiveSky->getCloudNoiseTextureId(), "cloud_map" }, |
| 287 | + { mLiveSky->getSunTextureId(), "sun_texture" }, |
| 288 | + { mLiveSky->getMoonTextureId(), "moon_texture" }, |
| 289 | + { mLiveSky->getBloomTextureId(), "bloom_texture"}, |
| 290 | + { mLiveSky->getRainbowTextureId(), "rainbow_texture"}, |
| 291 | + { mLiveSky->getHaloTextureId(), "halo_texture" }, |
| 292 | + }; |
| 293 | + |
| 294 | + // Helper: a null UUID is "no texture" and is always allowed. |
| 295 | + // A texture is safe when it is one of the sky defaults, |
| 296 | + // a general predefined texture, or is present in inventory. |
| 297 | + auto is_safe_texture = [](const LLUUID& tex_id) -> bool |
| 298 | + { |
| 299 | + if (tex_id.isNull()) |
| 300 | + return true; |
| 301 | + // TODO: find a graceful way to move these ids (and water ones) into get_can_copy_texture |
| 302 | + // as pickers should permit these textures by default to be able to work well with settings. |
| 303 | + if (tex_id == LLSettingsSky::GetDefaultSunTextureId() |
| 304 | + || tex_id == LLSettingsSky::GetBlankSunTextureId() |
| 305 | + || tex_id == LLSettingsSky::GetDefaultMoonTextureId() |
| 306 | + || tex_id == LLSettingsSky::GetDefaultCloudNoiseTextureId() |
| 307 | + || tex_id == LLSettingsSky::GetDefaultBloomTextureId() |
| 308 | + || tex_id == LLSettingsSky::GetDefaultRainbowTextureId() |
| 309 | + || tex_id == LLSettingsSky::GetDefaultHaloTextureId()) |
| 310 | + { |
| 311 | + return true; |
| 312 | + } |
| 313 | + return get_can_copy_texture(tex_id); |
| 314 | + }; |
| 315 | + |
| 316 | + std::string bad_textures; |
| 317 | + for (const TexEntry& entry : textures_to_check) |
| 318 | + { |
| 319 | + if (!is_safe_texture(entry.id)) |
| 320 | + { |
| 321 | + if (!bad_textures.empty()) |
| 322 | + bad_textures += "\n"; |
| 323 | + std::string label = getString(entry.name); |
| 324 | + bad_textures += " - " + label; |
| 325 | + } |
| 326 | + } |
261 | 327 |
|
| 328 | + if (!bad_textures.empty()) |
| 329 | + { |
| 330 | + LLSD args; |
| 331 | + args["TEXTURES"] = bad_textures; |
| 332 | + LLNotificationsUtil::add("PersonalSettingsTexPermFail", args); |
| 333 | + return; |
| 334 | + } |
| 335 | + |
| 336 | + LLSettingsSky::ptr_t sky_clone = mLiveSky->buildClone(); |
| 337 | + LLSD args; |
| 338 | + args["DESC"] = getString("new_sky"); // note that notification adds (new) at the end |
| 339 | + |
| 340 | + LLNotificationsUtil::add("SaveSettingAs", args, LLSD(), |
| 341 | + [sky_clone](const LLSD& notification, const LLSD& response) |
| 342 | + { |
| 343 | + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); |
| 344 | + if (option != 0) |
| 345 | + return; |
| 346 | + |
| 347 | + std::string settings_name = response["message"].asString(); |
| 348 | + LLInventoryObject::correctInventoryName(settings_name); |
| 349 | + if (settings_name.empty()) |
| 350 | + { |
| 351 | + settings_name = "Unnamed"; |
| 352 | + } |
| 353 | + |
| 354 | + sky_clone->setName(settings_name); |
| 355 | + |
| 356 | + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS); |
| 357 | + LLSettingsVOBase::createInventoryItem(sky_clone, parent_id, settings_name, |
| 358 | + [settings_name](LLUUID /*asset_id*/, LLUUID inventory_id, LLUUID, LLSD results) |
| 359 | + { |
| 360 | + if (inventory_id.notNull()) |
| 361 | + { |
| 362 | + LLInventoryPanel::openInventoryPanelAndSetSelection(true, inventory_id, true); |
| 363 | + } |
| 364 | + else |
| 365 | + { |
| 366 | + LL_WARNS("ENVIRONMENT") << "Failed to create sky settings inventory item. Results: " << results << LL_ENDL; |
| 367 | + LLSD args; |
| 368 | + args["SETTINGS_NAME"] = settings_name; |
| 369 | + LLNotificationsUtil::add("SettingsSaveAsFailure", args); |
| 370 | + } |
| 371 | + }); |
| 372 | + }); |
262 | 373 | } |
| 374 | + |
263 | 375 | //------------------------------------------------------------------------- |
264 | 376 | void LLFloaterEnvironmentAdjust::onAmbientLightChanged() |
265 | 377 | { |
|
0 commit comments