diff --git a/include/ishaders.h b/include/ishaders.h index a543442d3b..309f2ff896 100644 --- a/include/ishaders.h +++ b/include/ishaders.h @@ -341,14 +341,19 @@ class Material // will immediately mark this Material as modified. virtual IEditableShaderLayer::Ptr getEditableLayer(std::size_t index) = 0; - /// Return the 2D light falloff texture, if this is a light shader + /// Return the light falloff texture, if this is a light shader virtual TexturePtr lightFalloffImage() = 0; - // Return the expression of the light falloff texture for use with this shader. + // Return the expression of the light falloff map for use with this shader. virtual shaders::IMapExpression::Ptr getLightFalloffExpression() = 0; - // Return the expression of the light falloff cubemap for use with this shader. - virtual shaders::IMapExpression::Ptr getLightFalloffCubeMapExpression() = 0; + // Return the type of the light fall off image + // (can be MapType::Map (lightFalloffImage or MapType::CameraCubeMap for lightFalloffCubeMap) + virtual IShaderLayer::MapType getLightFalloffCubeMapType() = 0; + + // Set the type of the light fall off image + // (can be MapType::Map (lightFalloffImage or MapType::CameraCubeMap for lightFalloffCubeMap) + virtual void setLightFalloffCubeMapType(IShaderLayer::MapType type) = 0; // greebo: Returns the description as defined in the material virtual std::string getDescription() const = 0; diff --git a/install/ui/materialeditor.fbp b/install/ui/materialeditor.fbp index a314477795..b65c8a4ad4 100644 --- a/install/ui/materialeditor.fbp +++ b/install/ui/materialeditor.fbp @@ -4142,193 +4142,204 @@ -1 - - 0 - wxALIGN_CENTER_VERTICAL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 - - 1 - MaterialLightFalloffMap - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 0 - wxALIGN_CENTER_VERTICAL|wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - lightFalloffCubeMap - 0 - - 0 - - - 0 - - 1 - m_staticText421 - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - + 0 - wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - - 0 + wxEXPAND + 1 + - 1 - MaterialLightFalloffCubeMap - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - + bSizer75 + wxHORIZONTAL + none + + 0 + wxALIGN_CENTER_VERTICAL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + MaterialLightFalloffMap + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 6 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Type: + 0 + + 0 + + + 0 + + 1 + m_staticText53 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 6 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + MaterialLightFalloffCubeMapType + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + diff --git a/install/ui/materialeditor.xrc b/install/ui/materialeditor.xrc index 6732d9cc40..c19ad951ad 100644 --- a/install/ui/materialeditor.xrc +++ b/install/ui/materialeditor.xrc @@ -668,28 +668,37 @@ - - wxALIGN_CENTER_VERTICAL|wxEXPAND - 0 - - - - - - - wxALIGN_CENTER_VERTICAL|wxALL - 0 - - - -1 - - - - - wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND + + wxEXPAND 0 - - + + wxHORIZONTAL + + + wxALIGN_CENTER_VERTICAL + 0 + + + + + + + wxALIGN_CENTER_VERTICAL|wxLEFT + 6 + + + -1 + + + + + wxALIGN_CENTER_VERTICAL|wxLEFT + 6 + + 0 + + + diff --git a/radiant/ui/materials/MaterialEditor.cpp b/radiant/ui/materials/MaterialEditor.cpp index 47328a9579..e6bdb1064c 100644 --- a/radiant/ui/materials/MaterialEditor.cpp +++ b/radiant/ui/materials/MaterialEditor.cpp @@ -234,10 +234,22 @@ void MaterialEditor::setupMaterialProperties() getControl("MaterialSpectrumValue")->Enable(ev.IsChecked()); }); + // For light fall off images, only cameracubemap and map are allowed + auto lightFallOffCubeMapType = getControl("MaterialLightFalloffCubeMapType"); + lightFallOffCubeMapType->AppendString(shaders::getStringForMapType(IShaderLayer::MapType::Map)); + lightFallOffCubeMapType->AppendString(shaders::getStringForMapType(IShaderLayer::MapType::CameraCubeMap)); + + lightFallOffCubeMapType->Bind(wxEVT_CHOICE, [this, lightFallOffCubeMapType] (wxCommandEvent& ev) + { + if (_materialUpdateInProgress || !_material) return; + _material->setLightFalloffCubeMapType(shaders::getMapTypeForString(lightFallOffCubeMapType->GetStringSelection().ToStdString())); + }); + _materialBindings.emplace(std::make_shared>(getControl("MaterialSpectrumValue"), [](const MaterialPtr& material) { return material->getSpectrum(); }, [this](const MaterialPtr& material, const int& value) { + if (_materialUpdateInProgress || !_material) return; material->setSpectrum(value); }, [this]() { onMaterialChanged(); })); @@ -1090,8 +1102,8 @@ void MaterialEditor::updateMaterialPropertiesFromMaterial() auto lightFalloffMap = _material->getLightFalloffExpression(); getControl("MaterialLightFalloffMap")->SetValue(lightFalloffMap ? lightFalloffMap->getExpressionString() : ""); - auto lightFalloffCubeMap = _material->getLightFalloffCubeMapExpression(); - getControl("MaterialLightFalloffCubeMap")->SetValue(lightFalloffCubeMap ? lightFalloffCubeMap->getExpressionString() : ""); + auto lightFalloffCubeMapType = _material->getLightFalloffCubeMapType(); + getControl("MaterialLightFalloffCubeMapType")->SetStringSelection(shaders::getStringForMapType(lightFalloffCubeMapType)); // Spectrum bool hasSpectrum = (_material->getParseFlags() & Material::PF_HasSpectrum) != 0 || _material->getSpectrum() != 0; diff --git a/radiantcore/shaders/CShader.cpp b/radiantcore/shaders/CShader.cpp index d170bf8e5e..9cbe1674c8 100644 --- a/radiantcore/shaders/CShader.cpp +++ b/radiantcore/shaders/CShader.cpp @@ -81,9 +81,15 @@ IMapExpression::Ptr CShader::getLightFalloffExpression() return _template->getLightFalloff(); } -IMapExpression::Ptr CShader::getLightFalloffCubeMapExpression() +IShaderLayer::MapType CShader::getLightFalloffCubeMapType() { - return _template->getLightFalloffCubeMap(); + return _template->getLightFalloffCubeMapType(); +} + +void CShader::setLightFalloffCubeMapType(IShaderLayer::MapType type) +{ + ensureTemplateCopy(); + _template->setLightFalloffCubeMapType(type); } /* diff --git a/radiantcore/shaders/CShader.h b/radiantcore/shaders/CShader.h index 791fc5ac79..1c6a93b27d 100644 --- a/radiantcore/shaders/CShader.h +++ b/radiantcore/shaders/CShader.h @@ -102,7 +102,8 @@ class CShader final : IEditableShaderLayer::Ptr getEditableLayer(std::size_t index) override; IMapExpression::Ptr getLightFalloffExpression() override; - IMapExpression::Ptr getLightFalloffCubeMapExpression() override; + IShaderLayer::MapType getLightFalloffCubeMapType() override; + void setLightFalloffCubeMapType(IShaderLayer::MapType type) override; std::string getRenderBumpArguments() override; std::string getRenderBumpFlatArguments() override; diff --git a/radiantcore/shaders/ShaderTemplate.cpp b/radiantcore/shaders/ShaderTemplate.cpp index 7dde943da7..a7cea96985 100644 --- a/radiantcore/shaders/ShaderTemplate.cpp +++ b/radiantcore/shaders/ShaderTemplate.cpp @@ -26,7 +26,7 @@ ShaderTemplate::ShaderTemplate(const ShaderTemplate& other) : _name(other._name), _currentLayer(new Doom3ShaderLayer(*this)), _lightFalloff(other._lightFalloff), - _lightFalloffCubeMap(other._lightFalloffCubeMap), + _lightFalloffCubeMapType(other._lightFalloffCubeMapType), fogLight(other.fogLight), ambientLight(other.ambientLight), blendLight(other.blendLight), @@ -473,11 +473,13 @@ bool ShaderTemplate::parseLightKeywords(parser::DefTokeniser& tokeniser, const s } else if (!fogLight && token == "lightfalloffimage") { + _lightFalloffCubeMapType = IShaderLayer::MapType::Map; _lightFalloff = MapExpression::createForToken(tokeniser); } else if (token == "lightfalloffcubemap") { - _lightFalloffCubeMap = MapExpression::createForToken(tokeniser); + _lightFalloffCubeMapType = IShaderLayer::MapType::CameraCubeMap; + _lightFalloff = MapExpression::createForToken(tokeniser); } else if (token == "spectrum") { diff --git a/radiantcore/shaders/ShaderTemplate.h b/radiantcore/shaders/ShaderTemplate.h index d17b74f22d..fd989a5c5b 100644 --- a/radiantcore/shaders/ShaderTemplate.h +++ b/radiantcore/shaders/ShaderTemplate.h @@ -41,7 +41,7 @@ class ShaderTemplate final // Map expressions MapExpressionPtr _lightFalloff; - MapExpressionPtr _lightFalloffCubeMap; + IShaderLayer::MapType _lightFalloffCubeMapType; /* Light type booleans */ bool fogLight; @@ -107,26 +107,27 @@ class ShaderTemplate final * \brief * Construct a ShaderTemplate. */ - ShaderTemplate(const std::string& name, const std::string& blockContents) - : _name(name), - _currentLayer(new Doom3ShaderLayer(*this)), - fogLight(false), - ambientLight(false), - blendLight(false), - _cubicLight(false), - _materialFlags(0), - _cullType(Material::CULL_BACK), - _clampType(CLAMP_REPEAT), - _surfaceFlags(0), - _surfaceType(Material::SURFTYPE_DEFAULT), - _deformType(Material::DEFORM_NONE), - _spectrum(0), - _sortReq(SORT_UNDEFINED), // will be set to default values after the shader has been parsed - _polygonOffset(0.0f), - _coverage(Material::MC_UNDETERMINED), - _blockContents(blockContents), - _parsed(false), - _parseFlags(0) + ShaderTemplate(const std::string& name, const std::string& blockContents) : + _name(name), + _currentLayer(new Doom3ShaderLayer(*this)), + _lightFalloffCubeMapType(IShaderLayer::MapType::Map), + fogLight(false), + ambientLight(false), + blendLight(false), + _cubicLight(false), + _materialFlags(0), + _cullType(Material::CULL_BACK), + _clampType(CLAMP_REPEAT), + _surfaceFlags(0), + _surfaceType(Material::SURFTYPE_DEFAULT), + _deformType(Material::DEFORM_NONE), + _spectrum(0), + _sortReq(SORT_UNDEFINED), // will be set to default values after the shader has been parsed + _polygonOffset(0.0f), + _coverage(Material::MC_UNDETERMINED), + _blockContents(blockContents), + _parsed(false), + _parseFlags(0) { _decalInfo.stayMilliSeconds = 0; _decalInfo.fadeMilliSeconds = 0; @@ -330,11 +331,17 @@ class ShaderTemplate final return _lightFalloff; } - const MapExpressionPtr& getLightFalloffCubeMap() - { - if (!_parsed) parseDefinition(); - return _lightFalloffCubeMap; - } + IShaderLayer::MapType getLightFalloffCubeMapType() + { + if (!_parsed) parseDefinition(); + return _lightFalloffCubeMapType; + } + + void setLightFalloffCubeMapType(IShaderLayer::MapType type) + { + if (!_parsed) parseDefinition(); + _lightFalloffCubeMapType = type; + } std::size_t addLayer(IShaderLayer::Type type); void removeLayer(std::size_t index); diff --git a/test/Materials.cpp b/test/Materials.cpp index c154b9b316..38cad8363a 100644 --- a/test/Materials.cpp +++ b/test/Materials.cpp @@ -787,4 +787,23 @@ TEST_F(MaterialsTest, MaterialParserRgbaExpressions) EXPECT_EQ(diffuse->getColourExpression(IShaderLayer::COMP_ALPHA)->getExpressionString(), "time * 7.0"); } +TEST_F(MaterialsTest, MaterialParserLightfallOff) +{ + auto material = GlobalMaterialManager().getMaterial("textures/parsertest/lights/lightfalloff1"); + + EXPECT_EQ(material->getLightFalloffCubeMapType(), IShaderLayer::MapType::Map); + EXPECT_EQ(material->getLightFalloffExpression()->getExpressionString(), "makeIntensity(lights/squarelight1a.tga)"); + + material = GlobalMaterialManager().getMaterial("textures/parsertest/lights/lightfalloff2"); + + EXPECT_EQ(material->getLightFalloffCubeMapType(), IShaderLayer::MapType::CameraCubeMap); + EXPECT_EQ(material->getLightFalloffExpression()->getExpressionString(), "lights/squarelight1a"); + + material = GlobalMaterialManager().getMaterial("textures/parsertest/lights/lightfalloff3"); + + // Second lightFallOff declaration overrides the first one in the material + EXPECT_EQ(material->getLightFalloffCubeMapType(), IShaderLayer::MapType::CameraCubeMap); + EXPECT_EQ(material->getLightFalloffExpression()->getExpressionString(), "lights/squarelight1a"); +} + } diff --git a/test/resources/tdm/materials/parsertest.mtr b/test/resources/tdm/materials/parsertest.mtr index ce77270668..973389994e 100644 --- a/test/resources/tdm/materials/parsertest.mtr +++ b/test/resources/tdm/materials/parsertest.mtr @@ -450,3 +450,41 @@ textures/parsertest/colourexpr10 alpha time*7 } } + +textures/parsertest/lights/lightfalloff1 +{ + lightFalloffImage makeintensity( lights/squarelight1a.tga ) + spectrum 2 + { + forceHighQuality + map lights/fullambient.tga + colored + zeroClamp + } +} + +textures/parsertest/lights/lightfalloff2 +{ + lightFalloffCubeMap lights/squarelight1a + spectrum 2 + { + forceHighQuality + map lights/fullambient.tga + colored + zeroClamp + } +} + + +textures/parsertest/lights/lightfalloff3 +{ + lightFalloffImage makeintensity( lights/squarelight1a.tga ) + lightFalloffCubeMap lights/squarelight1a + spectrum 2 + { + forceHighQuality + map lights/fullambient.tga + colored + zeroClamp + } +}