diff --git a/include/ishaderlayer.h b/include/ishaderlayer.h index a28cd3cdb2..7c1f2f8415 100644 --- a/include/ishaderlayer.h +++ b/include/ishaderlayer.h @@ -405,6 +405,9 @@ class IEditableShaderLayer : // Set the map type to use by this stage (map, cameraCubeMap, etc.) virtual void setMapType(MapType mapType) = 0; + // Set the blend func from the given pair of strings + virtual void setBlendFuncStrings(const std::pair& pair) = 0; + // Set the alpha test expression from the given string virtual void setAlphaTestExpressionFromString(const std::string& expression) = 0; diff --git a/radiant/ui/materials/MaterialEditor.cpp b/radiant/ui/materials/MaterialEditor.cpp index 9f4e961312..887574e829 100644 --- a/radiant/ui/materials/MaterialEditor.cpp +++ b/radiant/ui/materials/MaterialEditor.cpp @@ -35,6 +35,7 @@ namespace const std::string RKEY_WINDOW_STATE = RKEY_ROOT + "window"; const char* const SPECIAL_MAP_TYPE = N_("Special"); + const char* const CUSTOM_BLEND_TYPE = N_("Custom"); // Columns for the stages list struct StageColumns : @@ -458,15 +459,15 @@ void MaterialEditor::setupMaterialStageProperties() getControl("MaterialStageHasAlphaTest")->SetValue(layer->hasAlphaTest()); }); - for (const auto& value : { - "diffusemap", "bumpmap", "specularmap", "blend", "add", "filter", "modulate", "none", "Custom" - }) + for (const auto& value : { "diffusemap", "bumpmap", "specularmap", "blend", "add", "filter", "modulate", "none" }) { getControl("MaterialStageBlendType")->Append(value); } + + getControl("MaterialStageBlendType")->Append(_(CUSTOM_BLEND_TYPE)); for (const auto& value : { - "", "gl_one", "gl_zero", "gl_dst_color", "gl_one_minus_dst_color", "gl_src_alpha", + "gl_one", "gl_zero", "gl_dst_color", "gl_one_minus_dst_color", "gl_src_alpha", "gl_one_minus_src_alpha", "gl_dst_alpha", "gl_one_minus_dst_alpha", "gl_src_alpha_saturate" }) { @@ -474,13 +475,17 @@ void MaterialEditor::setupMaterialStageProperties() } for (const auto& value : { - "", "gl_one", "gl_zero", "gl_src_color", "gl_one_minus_src_color", "gl_src_alpha", + "gl_one", "gl_zero", "gl_src_color", "gl_one_minus_src_color", "gl_src_alpha", "gl_one_minus_src_alpha", "gl_dst_alpha", "gl_one_minus_dst_alpha" }) { getControl("MaterialStageBlendTypeDest")->Append(value); } + getControl("MaterialStageBlendType")->Bind(wxEVT_CHOICE, &MaterialEditor::_onStageBlendTypeChanged, this);; + getControl("MaterialStageBlendTypeSrc")->Bind(wxEVT_CHOICE, &MaterialEditor::_onStageBlendTypeChanged, this);; + getControl("MaterialStageBlendTypeDest")->Bind(wxEVT_CHOICE, &MaterialEditor::_onStageBlendTypeChanged, this);; + auto mapTypeDropdown = getControl("MaterialStageMapType"); for (const auto& value : { "map", "cubeMap", "cameraCubeMap" }) @@ -1119,22 +1124,6 @@ void MaterialEditor::updateStageBlendControls() blendType->Enable(); auto blendTypeStrings = selectedStage->getBlendFuncStrings(); - switch (selectedStage->getType()) - { - case IShaderLayer::DIFFUSE: - blendTypeStrings.first = "diffusemap"; - blendTypeStrings.second.clear(); - break; - case IShaderLayer::BUMP: - blendTypeStrings.first = "bumpmap"; - blendTypeStrings.second.clear(); - break; - case IShaderLayer::SPECULAR: - blendTypeStrings.first = "specularmap"; - blendTypeStrings.second.clear(); - break; - }; - blendTypeSrc->Enable(!blendTypeStrings.second.empty()); blendTypeDest->Enable(!blendTypeStrings.second.empty()); @@ -1142,8 +1131,8 @@ void MaterialEditor::updateStageBlendControls() { blendType->SetStringSelection(blendTypeStrings.first); - blendTypeSrc->SetStringSelection(""); - blendTypeDest->SetStringSelection(""); + blendTypeSrc->SetStringSelection("gl_one"); + blendTypeDest->SetStringSelection("gl_zero"); // Get the actual src and dest blend types this shortcut is working with for (const auto& pair : shaders::BlendTypeShortcuts) @@ -1158,7 +1147,7 @@ void MaterialEditor::updateStageBlendControls() } else { - blendType->SetStringSelection("Custom"); + blendType->SetStringSelection(_(CUSTOM_BLEND_TYPE)); blendTypeSrc->SetStringSelection(blendTypeStrings.first); blendTypeDest->SetStringSelection(blendTypeStrings.second); } @@ -1550,6 +1539,44 @@ void MaterialEditor::_onStageMapTypeChanged(wxCommandEvent& ev) updateStageControls(); } +void MaterialEditor::_onStageBlendTypeChanged(wxCommandEvent& ev) +{ + auto stage = getEditableStageForSelection(); + if (!stage) return; + + std::pair blendFuncStrings; + + auto blendTypeString = getControl("MaterialStageBlendType")->GetStringSelection(); + + if (blendTypeString == _(CUSTOM_BLEND_TYPE)) + { + blendFuncStrings.first = getControl("MaterialStageBlendTypeSrc")->GetStringSelection(); + blendFuncStrings.second = getControl("MaterialStageBlendTypeDest")->GetStringSelection(); + } + else + { + // It's one of diffuse/bump/specular or a blend shortcut like add/modulate + blendFuncStrings.first = blendTypeString; + } + + stage->setBlendFuncStrings(blendFuncStrings); + + updateNameOfSelectedStage(); + updateStageControls(); +} + +void MaterialEditor::updateNameOfSelectedStage() +{ + auto item = _stageView->GetSelection(); + if (!item.IsOk()) return; + + auto row = wxutil::TreeModel::Row(item, *_stageList); + + row[STAGE_COLS().name] = getNameForLayer(*getSelectedStage()); + + row.SendItemChanged(); +} + void MaterialEditor::onMaterialChanged() { _preview->onMaterialChanged(); diff --git a/radiant/ui/materials/MaterialEditor.h b/radiant/ui/materials/MaterialEditor.h index ce8d0c1746..4ad4aceb3a 100644 --- a/radiant/ui/materials/MaterialEditor.h +++ b/radiant/ui/materials/MaterialEditor.h @@ -129,6 +129,7 @@ class MaterialEditor : void updateStageProgramControls(); void updateStageTransformControls(); void updateStageColoredStatus(); + void updateNameOfSelectedStage(); void _onTreeViewSelectionChanged(wxDataViewEvent& ev); void _onStageListSelectionChanged(wxDataViewEvent& ev); @@ -138,6 +139,7 @@ class MaterialEditor : void _onStageTransformEdited(wxDataViewEvent& ev); void _onStageColoredChecked(wxCommandEvent& ev); void _onStageMapTypeChanged(wxCommandEvent& ev); + void _onStageBlendTypeChanged(wxCommandEvent& ev); void onMaterialChanged(); diff --git a/radiantcore/shaders/Doom3ShaderLayer.cpp b/radiantcore/shaders/Doom3ShaderLayer.cpp index 38af09e541..8f5cd4a26c 100644 --- a/radiantcore/shaders/Doom3ShaderLayer.cpp +++ b/radiantcore/shaders/Doom3ShaderLayer.cpp @@ -76,6 +76,18 @@ BlendFunc blendFuncFromStrings(const StringPair& blendFunc) } } +StringPair getDefaultBlendFuncStringsForType(IShaderLayer::Type type) +{ + switch (type) + { + case IShaderLayer::DIFFUSE: return { "diffusemap" , "" }; + case IShaderLayer::BUMP: return { "bumpmap" , "" }; + case IShaderLayer::SPECULAR: return { "specularmap" , "" }; + } + + return { "gl_one", "gl_zero" }; // needs to be lowercase +} + inline IShaderExpression::Ptr getDefaultExpressionForTransformType(IShaderLayer::TransformType type) { if (type == IShaderLayer::TransformType::CenterScale || @@ -98,7 +110,7 @@ Doom3ShaderLayer::Doom3ShaderLayer(ShaderTemplate& material, IShaderLayer::Type _bindableTex(btex), _type(type), _mapType(MapType::Map), - _blendFuncStrings("gl_one", "gl_zero"), // needs to be lowercase + _blendFuncStrings(getDefaultBlendFuncStringsForType(type)), _vertexColourMode(VERTEX_COLOUR_NONE), _cubeMapMode(CUBE_MAP_NONE), _stageFlags(0), diff --git a/radiantcore/shaders/Doom3ShaderLayer.h b/radiantcore/shaders/Doom3ShaderLayer.h index 334967c5d3..ba49f674fc 100644 --- a/radiantcore/shaders/Doom3ShaderLayer.h +++ b/radiantcore/shaders/Doom3ShaderLayer.h @@ -287,9 +287,26 @@ class Doom3ShaderLayer : * \brief * Set the blend function string. */ - void setBlendFuncStrings(const StringPair& func) + void setBlendFuncStrings(const StringPair& func) override { _blendFuncStrings = func; + + if (_blendFuncStrings.first == "diffusemap") + { + setLayerType(IShaderLayer::DIFFUSE); + } + else if (_blendFuncStrings.first == "bumpmap") + { + setLayerType(IShaderLayer::BUMP); + } + else if (_blendFuncStrings.first == "specularmap") + { + setLayerType(IShaderLayer::SPECULAR); + } + else + { + setLayerType(IShaderLayer::BLEND); + } } const StringPair& getBlendFuncStrings() const override diff --git a/radiantcore/shaders/ShaderTemplate.cpp b/radiantcore/shaders/ShaderTemplate.cpp index a8decd2278..09d610c87f 100644 --- a/radiantcore/shaders/ShaderTemplate.cpp +++ b/radiantcore/shaders/ShaderTemplate.cpp @@ -538,47 +538,27 @@ bool ShaderTemplate::parseBlendType(parser::DefTokeniser& tokeniser, const std:: { if (token == "blend") { - std::string blendType = string::to_lower_copy(tokeniser.nextToken()); + // Special blend type, either predefined like "add" or "modulate", + // or an explicit combination of GL blend modes + StringPair blendFuncStrings; + blendFuncStrings.first = string::to_lower_copy(tokeniser.nextToken()); - if (blendType == "diffusemap") - { - _currentLayer->setLayerType(IShaderLayer::DIFFUSE); - } - else if (blendType == "bumpmap") - { - _currentLayer->setLayerType(IShaderLayer::BUMP); - } - else if (blendType == "specularmap") - { - _currentLayer->setLayerType(IShaderLayer::SPECULAR); + if (blendFuncStrings.first.substr(0, 3) == "gl_") + { + // This is an explicit GL blend mode + tokeniser.assertNextToken(","); + blendFuncStrings.second = string::to_lower_copy(tokeniser.nextToken()); } else { - // Special blend type, either predefined like "add" or "modulate", - // or an explicit combination of GL blend modes - StringPair blendFuncStrings; - blendFuncStrings.first = blendType; - - if (blendType.substr(0,3) == "gl_") - { - // This is an explicit GL blend mode - tokeniser.assertNextToken(","); - blendFuncStrings.second = tokeniser.nextToken(); - } - else - { - blendFuncStrings.second = ""; - } - - _currentLayer->setBlendFuncStrings(blendFuncStrings); + blendFuncStrings.second = ""; } - } - else - { - return false; // unrecognised token, return false - } - return true; + _currentLayer->setBlendFuncStrings(blendFuncStrings); + return true; + } + + return false; // unrecognised token, return false } /* Searches for the map keyword in stage 2, expects token to be lowercase