]> git.lizzy.rs Git - minetest.git/blobdiff - src/nodedef.cpp
Rework use_texture_alpha to provide three opaque/clip/blend modes
[minetest.git] / src / nodedef.cpp
index b2cfd1f8756f4ac2fea10da4f3ad25f30b28c2c6..57d4c008f4243eef34bf6cfffba7004fc1020b50 100644 (file)
@@ -360,7 +360,7 @@ void ContentFeatures::reset()
                i = TileDef();
        for (auto &j : tiledef_special)
                j = TileDef();
-       alpha = 255;
+       alpha = ALPHAMODE_OPAQUE;
        post_effect_color = video::SColor(0, 0, 0, 0);
        param_type = CPT_NONE;
        param_type_2 = CPT2_NONE;
@@ -405,6 +405,31 @@ void ContentFeatures::reset()
        node_dig_prediction = "air";
 }
 
+void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
+{
+       // No special handling for nodebox/mesh here as it doesn't make sense to
+       // throw warnings when the server is too old to support the "correct" way
+       switch (drawtype) {
+       case NDT_NORMAL:
+               alpha = legacy_alpha == 255 ? ALPHAMODE_OPAQUE : ALPHAMODE_CLIP;
+               break;
+       case NDT_LIQUID:
+       case NDT_FLOWINGLIQUID:
+               alpha = legacy_alpha == 255 ? ALPHAMODE_OPAQUE : ALPHAMODE_BLEND;
+               break;
+       default:
+               alpha = legacy_alpha == 255 ? ALPHAMODE_CLIP : ALPHAMODE_BLEND;
+               break;
+       }
+}
+
+u8 ContentFeatures::getAlphaForLegacy() const
+{
+       // This is so simple only because 255 and 0 mean wildly different things
+       // depending on drawtype...
+       return alpha == ALPHAMODE_OPAQUE ? 255 : 0;
+}
+
 void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
 {
        const u8 version = CONTENTFEATURES_VERSION;
@@ -433,7 +458,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
        for (const TileDef &td : tiledef_special) {
                td.serialize(os, protocol_version);
        }
-       writeU8(os, alpha);
+       writeU8(os, getAlphaForLegacy());
        writeU8(os, color.getRed());
        writeU8(os, color.getGreen());
        writeU8(os, color.getBlue());
@@ -489,6 +514,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
 
        os << serializeString16(node_dig_prediction);
        writeU8(os, leveled_max);
+       writeU8(os, alpha);
 }
 
 void ContentFeatures::deSerialize(std::istream &is)
@@ -524,7 +550,7 @@ void ContentFeatures::deSerialize(std::istream &is)
                throw SerializationError("unsupported CF_SPECIAL_COUNT");
        for (TileDef &td : tiledef_special)
                td.deSerialize(is, version, drawtype);
-       alpha = readU8(is);
+       setAlphaFromLegacy(readU8(is));
        color.setRed(readU8(is));
        color.setGreen(readU8(is));
        color.setBlue(readU8(is));
@@ -582,10 +608,16 @@ void ContentFeatures::deSerialize(std::istream &is)
 
        try {
                node_dig_prediction = deSerializeString16(is);
-               u8 tmp_leveled_max = readU8(is);
+
+               u8 tmp = readU8(is);
                if (is.eof()) /* readU8 doesn't throw exceptions so we have to do this */
                        throw SerializationError("");
-               leveled_max = tmp_leveled_max;
+               leveled_max = tmp;
+
+               tmp = readU8(is);
+               if (is.eof())
+                       throw SerializationError("");
+               alpha = static_cast<enum AlphaMode>(tmp);
        } catch(SerializationError &e) {};
 }
 
@@ -677,6 +709,7 @@ bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *til
        video::IVideoDriver *driver = RenderingEngine::get_video_driver();
        static thread_local bool long_warning_printed = false;
        std::set<std::string> seen;
+
        for (int i = 0; i < length; i++) {
                if (seen.find(tiles[i].name) != seen.end())
                        continue;
@@ -701,20 +734,21 @@ bool ContentFeatures::textureAlphaCheck(ITextureSource *tsrc, const TileDef *til
 
 break_loop:
                image->drop();
-               if (!ok) {
-                       warningstream << "Texture \"" << tiles[i].name << "\" of "
-                               << name << " has transparent pixels, assuming "
-                               "use_texture_alpha = true." << std::endl;
-                       if (!long_warning_printed) {
-                               warningstream << "  This warning can be a false-positive if "
-                                       "unused pixels in the texture are transparent. However if "
-                                       "it is meant to be transparent, you *MUST* update the "
-                                       "nodedef and set use_texture_alpha = true! This compatibility "
-                                       "code will be removed in a few releases." << std::endl;
-                               long_warning_printed = true;
-                       }
-                       return true;
+               if (ok)
+                       continue;
+               warningstream << "Texture \"" << tiles[i].name << "\" of "
+                       << name << " has transparency, assuming "
+                       "use_texture_alpha = \"clip\"." << std::endl;
+               if (!long_warning_printed) {
+                       warningstream << "  This warning can be a false-positive if "
+                               "unused pixels in the texture are transparent. However if "
+                               "it is meant to be transparent, you *MUST* update the "
+                               "nodedef and set use_texture_alpha = \"clip\"! This "
+                               "compatibility code will be removed in a few releases."
+                               << std::endl;
+                       long_warning_printed = true;
                }
+               return true;
        }
        return false;
 }
@@ -759,14 +793,18 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
 
        bool is_liquid = false;
 
-       MaterialType material_type = (alpha == 255) ?
-               TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
+       if (alpha == ALPHAMODE_LEGACY_COMPAT) {
+               // Before working with the alpha mode, resolve any legacy kludges
+               alpha = textureAlphaCheck(tsrc, tdef, 6) ? ALPHAMODE_CLIP : ALPHAMODE_OPAQUE;
+       }
+
+       MaterialType material_type = alpha == ALPHAMODE_OPAQUE ?
+               TILE_MATERIAL_OPAQUE : (alpha == ALPHAMODE_CLIP ? TILE_MATERIAL_BASIC :
+               TILE_MATERIAL_ALPHA);
 
        switch (drawtype) {
        default:
        case NDT_NORMAL:
-               material_type = (alpha == 255) ?
-                       TILE_MATERIAL_OPAQUE : TILE_MATERIAL_ALPHA;
                solidness = 2;
                break;
        case NDT_AIRLIKE:
@@ -774,14 +812,14 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
                break;
        case NDT_LIQUID:
                if (tsettings.opaque_water)
-                       alpha = 255;
+                       alpha = ALPHAMODE_OPAQUE;
                solidness = 1;
                is_liquid = true;
                break;
        case NDT_FLOWINGLIQUID:
                solidness = 0;
                if (tsettings.opaque_water)
-                       alpha = 255;
+                       alpha = ALPHAMODE_OPAQUE;
                is_liquid = true;
                break;
        case NDT_GLASSLIKE:
@@ -833,19 +871,16 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
                break;
        case NDT_MESH:
        case NDT_NODEBOX:
-               if (alpha == 255 && textureAlphaCheck(tsrc, tdef, 6))
-                       alpha = 0;
-
                solidness = 0;
-               if (waving == 1)
+               if (waving == 1) {
                        material_type = TILE_MATERIAL_WAVING_PLANTS;
-               else if (waving == 2)
+               } else if (waving == 2) {
                        material_type = TILE_MATERIAL_WAVING_LEAVES;
-               else if (waving == 3)
-                       material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE :
-                               TILE_MATERIAL_WAVING_LIQUID_BASIC;
-               else if (alpha == 255)
-                       material_type = TILE_MATERIAL_OPAQUE;
+               } else if (waving == 3) {
+                       material_type = alpha == ALPHAMODE_OPAQUE ?
+                               TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
+                               TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
+               }
                break;
        case NDT_TORCHLIKE:
        case NDT_SIGNLIKE:
@@ -860,10 +895,11 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
 
        if (is_liquid) {
                if (waving == 3) {
-                       material_type = (alpha == 255) ? TILE_MATERIAL_WAVING_LIQUID_OPAQUE :
-                               TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT;
+                       material_type = alpha == ALPHAMODE_OPAQUE ?
+                               TILE_MATERIAL_WAVING_LIQUID_OPAQUE : (alpha == ALPHAMODE_CLIP ?
+                               TILE_MATERIAL_WAVING_LIQUID_BASIC : TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT);
                } else {
-                       material_type = (alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE :
+                       material_type = alpha == ALPHAMODE_OPAQUE ? TILE_MATERIAL_LIQUID_OPAQUE :
                                TILE_MATERIAL_LIQUID_TRANSPARENT;
                }
        }