Skip to content

Commit

Permalink
#5567: Frob stage detection code
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Apr 2, 2021
1 parent 32ebdcc commit 77a1d50
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 1 deletion.
105 changes: 104 additions & 1 deletion libs/materials/FrobStageSetup.h
Expand Up @@ -6,19 +6,122 @@
namespace shaders
{

/**
* Helper class handling the two default frob stages on TDM materials.
* The two frob stages look like this:
*
* // Blend _white stage
* {
* if ( parm11 > 0 )
* blend gl_dst_color, gl_one
* map _white
* rgb 0.40 * parm11
* }
*
* // Additive blend of the material's diffuse map
* {
* if ( parm11 > 0 )
* blend add
* map textures/numbers/0
* rgb 0.15 * parm11
* }
*/
class FrobStageSetup
{
public:
static bool IsPresent(const MaterialPtr& material)
static bool HasWhiteBlendStage(const MaterialPtr& material)
{
for (const auto& layer : material->getAllLayers())
{
// if ( parm11 > 0 )
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != "(parm11 > 0.0)")
{
continue;
}

// blend gl_dst_color, gl_one
if (layer->getBlendFuncStrings().first != "gl_dst_color" || layer->getBlendFuncStrings().second != "gl_one")
{
continue;
}

// map _white
if (!layer->getMapExpression() || layer->getMapExpression()->getExpressionString() != "_white")
{
continue;
}

// rgb 0.40 * parm11
auto rgb = layer->getColourExpression(IShaderLayer::COMP_RGB);

if (rgb && rgb->getExpressionString() == "0.4 * parm11")
{
return true;
}
}

return false;
}

static bool HasAdditiveDiffuseStage(const MaterialPtr& material)
{
auto diffuse = GetDiffuseMap(material);

if (diffuse.empty()) return false;

for (const auto& layer : material->getAllLayers())
{
// if ( parm11 > 0 )
if (!layer->getConditionExpression() || layer->getConditionExpression()->getExpressionString() != "(parm11 > 0.0)")
{
continue;
}

// blend add
if (layer->getBlendFuncStrings().first != "add" || !layer->getBlendFuncStrings().second.empty())
{
continue;
}

// map <diffuse>
if (!layer->getMapExpression() || layer->getMapExpression()->getExpressionString() != diffuse)
{
continue;
}

// rgb 0.15 * parm11
auto rgb = layer->getColourExpression(IShaderLayer::COMP_RGB);

if (rgb && rgb->getExpressionString() == "0.15 * parm11")
{
return true;
}
}

return false;
}

// Checks whether the default frob stages are present on this material
static bool IsPresent(const MaterialPtr& material)
{
if (!material) return false;

auto diffuse = GetDiffuseMap(material);

return !diffuse.empty() && HasWhiteBlendStage(material) && HasAdditiveDiffuseStage(material);
}

private:
static std::string GetDiffuseMap(const MaterialPtr& material)
{
for (const auto& layer : material->getAllLayers())
{
if (layer->getType() == IShaderLayer::DIFFUSE && layer->getMapExpression())
{
return layer->getMapExpression()->getExpressionString();
}
}

return std::string();
}
};
Expand Down
5 changes: 5 additions & 0 deletions radiant/ui/materials/editor/MaterialEditor.cpp
Expand Up @@ -24,6 +24,7 @@
#include "wxutil/dataview/ResourceTreeViewToolbar.h"
#include "wxutil/dataview/TreeViewItemStyle.h"
#include "wxutil/Bitmap.h"
#include "materials/FrobStageSetup.h"
#include <fmt/format.h>
#include "gamelib.h"
#include "string/join.h"
Expand Down Expand Up @@ -1610,7 +1611,11 @@ void MaterialEditor::updateBasicFrobStageControls()
auto addFrob = getControl<wxButton>("BasicAddFrobStages");
auto removeFrob = getControl<wxButton>("BasicRemoveFrobStages");

bool hasFrobStages = shaders::FrobStageSetup::IsPresent(_material);
bool materialCanBeModified = _material && GlobalMaterialManager().materialCanBeModified(_material->getName());

addFrob->Enable(materialCanBeModified && !hasFrobStages);
removeFrob->Enable(materialCanBeModified && hasFrobStages);
}

void MaterialEditor::updateBasicImagePreview()
Expand Down
12 changes: 12 additions & 0 deletions test/Materials.cpp
Expand Up @@ -1406,21 +1406,33 @@ TEST_F(MaterialsTest, MaterialFrobStageDetection)
{
auto material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_present1");
EXPECT_TRUE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing1");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing2");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing3");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing4");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));

material = GlobalMaterialManager().getMaterial("textures/parsertest/frobstage_missing5");
EXPECT_FALSE(shaders::FrobStageSetup::IsPresent(material));
EXPECT_FALSE(shaders::FrobStageSetup::HasAdditiveDiffuseStage(material));
EXPECT_TRUE(shaders::FrobStageSetup::HasWhiteBlendStage(material));
}

}

0 comments on commit 77a1d50

Please sign in to comment.