diff --git a/install/bitmaps/swap_background.png b/install/bitmaps/swap_background.png new file mode 100644 index 0000000000..d1d4354450 Binary files /dev/null and b/install/bitmaps/swap_background.png differ diff --git a/radiant/ui/materials/editor/MaterialPreview.cpp b/radiant/ui/materials/editor/MaterialPreview.cpp index c925e838c3..02c0106a7e 100644 --- a/radiant/ui/materials/editor/MaterialPreview.cpp +++ b/radiant/ui/materials/editor/MaterialPreview.cpp @@ -23,6 +23,21 @@ namespace const char* const FUNC_STATIC_CLASS = "func_static"; const char* const GKEY_DEFAULT_ROOM_MATERIAL = "/materialPreview/defaultRoomMaterial"; const char* const GKEY_DEFAULT_LIGHT_DEF = "/materialPreview/defaultLightDef"; + + inline bool isSkyboxMaterial(const MaterialPtr& material) + { + if (!material) return false; + + for (const auto& layer : material->getAllLayers()) + { + if (layer->getMapType() == IShaderLayer::MapType::CameraCubeMap) + { + return true; + } + } + + return false; + } } MaterialPreview::MaterialPreview(wxWindow* parent) : @@ -68,6 +83,15 @@ void MaterialPreview::setupToolbar() toolbar->Bind(wxEVT_TOOL, &MaterialPreview::onTestModelSelectionChanged, this, _testModelSphereButton->GetId()); toolbar->Bind(wxEVT_TOOL, &MaterialPreview::onTestModelSelectionChanged, this, _testModelTilesButton->GetId()); + toolbar->AddSeparator(); + + _swapBackgroundMaterialButton = toolbar->AddTool(wxID_ANY, "Swap", wxutil::GetLocalBitmap("swap_background.png", wxART_TOOLBAR)); + _swapBackgroundMaterialButton->SetToggle(true); + toolbar->ToggleTool(_swapBackgroundMaterialButton->GetId(), false); + _swapBackgroundMaterialButton->SetShortHelp(_("Swap Background and Foreground Materials")); + + toolbar->Bind(wxEVT_TOOL, &MaterialPreview::onSwapBackgroundMaterialChanged, this, _swapBackgroundMaterialButton->GetId()); + toolbar->Realize(); addToolbar(toolbar); @@ -78,8 +102,13 @@ const MaterialPtr& MaterialPreview::getMaterial() return _material; } -void MaterialPreview::updateModelSkin() +void MaterialPreview::updateModelSkin(const std::string& material) { + // Assign the material to the temporary skin + _testModelSkin->setRemapMaterial(GlobalMaterialManager().getMaterial(material)); + + if (!_model) return; + // Hide the model if there's no material to preview _model->setFiltered(_testModelSkin->isEmpty()); @@ -100,7 +129,7 @@ const std::string& MaterialPreview::getRoomMaterial() void MaterialPreview::setRoomMaterial(const std::string& material) { _roomMaterial = material; - updateRoomSkin(); + updateSceneMaterials(); signal_SceneChanged().emit(); } @@ -155,9 +184,9 @@ std::string MaterialPreview::getDefaultLightDef() return className; } -void MaterialPreview::updateRoomSkin() +void MaterialPreview::updateRoomSkin(const std::string& roomMaterial) { - _testRoomSkin->setRemapMaterial(GlobalMaterialManager().getMaterial(getRoomMaterial())); + _testRoomSkin->setRemapMaterial(GlobalMaterialManager().getMaterial(roomMaterial)); // Let the model update its remaps auto skinnedRoom = std::dynamic_pointer_cast(_room); @@ -184,13 +213,11 @@ void MaterialPreview::setMaterial(const MaterialPtr& material) _sceneIsReady = false; - if (_model) - { - // Assign the material to the temporary skin - _testModelSkin->setRemapMaterial(_material); + // Detect whether we should apply this material to the background + _swapBackgroundMaterial = isSkyboxMaterial(_material); + _swapBackgroundMaterialButton->GetToolBar()->ToggleTool(_swapBackgroundMaterialButton->GetId(), _swapBackgroundMaterial); - updateModelSkin(); - } + updateSceneMaterials(); if (!hadMaterial && _material) { @@ -204,6 +231,20 @@ void MaterialPreview::setMaterial(const MaterialPtr& material) queueDraw(); } +void MaterialPreview::updateSceneMaterials() +{ + auto foregroundMaterial = _material ? _material->getName() : _roomMaterial; + auto backgroundMaterial = _roomMaterial; + + if (_swapBackgroundMaterial) + { + std::swap(foregroundMaterial, backgroundMaterial); + } + + updateModelSkin(foregroundMaterial); + updateRoomSkin(backgroundMaterial); +} + void MaterialPreview::enableFrobHighlight(bool enable) { if (!_entity) return; @@ -313,7 +354,7 @@ void MaterialPreview::setupRoom() roomEntity->addChildNode(_room); - updateRoomSkin(); + updateRoomSkin(getRoomMaterial()); } void MaterialPreview::setupTestModel() @@ -343,7 +384,7 @@ void MaterialPreview::setupTestModel() // The test model is a child of this entity scene::addNodeToContainer(_model, _entity); - updateModelSkin(); + updateSceneMaterials(); } void MaterialPreview::onTestModelSelectionChanged(wxCommandEvent& ev) @@ -364,6 +405,13 @@ void MaterialPreview::onTestModelSelectionChanged(wxCommandEvent& ev) queueDraw(); } +void MaterialPreview::onSwapBackgroundMaterialChanged(wxCommandEvent& ev) +{ + _swapBackgroundMaterial = ev.IsChecked(); + updateSceneMaterials(); + queueDraw(); +} + sigc::signal& MaterialPreview::signal_SceneChanged() { return _sigSceneChanged; diff --git a/radiant/ui/materials/editor/MaterialPreview.h b/radiant/ui/materials/editor/MaterialPreview.h index 5e82b2463c..27fd2de017 100644 --- a/radiant/ui/materials/editor/MaterialPreview.h +++ b/radiant/ui/materials/editor/MaterialPreview.h @@ -35,12 +35,14 @@ class MaterialPreview : std::string _roomMaterial; std::string _lightClassname; + bool _swapBackgroundMaterial; float _defaultCamDistanceFactor; wxToolBarToolBase* _testModelCubeButton; wxToolBarToolBase* _testModelSphereButton; wxToolBarToolBase* _testModelTilesButton; + wxToolBarToolBase* _swapBackgroundMaterialButton; sigc::signal _sigSceneChanged; @@ -91,10 +93,12 @@ class MaterialPreview : void setupToolbar(); void setupTestModel(); void setupRoom(); - void updateModelSkin(); - void updateRoomSkin(); + void updateModelSkin(const std::string& material); + void updateRoomSkin(const std::string& material); + void updateSceneMaterials(); std::string getDefaultLightDef(); void onTestModelSelectionChanged(wxCommandEvent& ev); + void onSwapBackgroundMaterialChanged(wxCommandEvent& ev); }; }