} //mxd #endregion #region ================== Constructor / Disposer // Constructor internal PatchStructure(TexturesParser parser) { // Initialize alpha = 1.0f; renderstyle = TexturePathRenderStyle.COPY; //mxd blendstyle = TexturePathBlendStyle.NONE; //mxd // There should be 3 tokens separated by 2 commas now: // Name, Width, Height // First token is the class name parser.SkipWhitespace(true); if (!parser.ReadTextureName(out name, "patch")) { return; //mxd } if (string.IsNullOrEmpty(name)) { parser.ReportError("Expected patch name"); return; } //mxd. Skip what must be skipped skip = (name.ToUpperInvariant() == IGNORE_SPRITE); //mxd name = name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); // Now we should find a comma if (!parser.NextTokenIs(",")) { return; //mxd } // Next is the patch width parser.SkipWhitespace(true); string tokenstr = parser.ReadToken(); if (string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out offsetx)) { parser.ReportError("Expected offset in pixels"); return; } // Now we should find a comma again if (!parser.NextTokenIs(",")) { return; //mxd } // Next is the patch height parser.SkipWhitespace(true); tokenstr = parser.ReadToken(); if (string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out offsety)) { parser.ReportError("Expected offset in pixels"); return; } // Next token is the beginning of the texture scope. If not, then the patch info ends here. if (!parser.NextTokenIs("{", false)) { return; //mxd } // Now parse the contents of texture structure bool done = false; //mxd while (!done && parser.SkipWhitespace(true)) { string token = parser.ReadToken(); token = token.ToLowerInvariant(); switch (token) { case "flipx": flipx = true; break; case "flipy": flipy = true; break; case "alpha": if (!ReadTokenFloat(parser, token, out alpha)) { return; } alpha = General.Clamp(alpha, 0.0f, 1.0f); break; case "rotate": if (!ReadTokenInt(parser, token, out rotation)) { return; } rotation = rotation % 360; //Coalesce multiples if (rotation < 0) { rotation += 360; //Force positive } if (rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270) { parser.LogWarning("Unsupported rotation (" + rotation + ") in patch \"" + name + "\""); rotation = 0; } break; case "style": //mxd string s; if (!ReadTokenString(parser, token, out s)) { return; } int index = Array.IndexOf(renderStyles, s.ToLowerInvariant()); renderstyle = index == -1 ? TexturePathRenderStyle.COPY : (TexturePathRenderStyle)index; break; case "blend": //mxd parser.SkipWhitespace(false); PixelColor color = new PixelColor(); // Blend <string color>[,<float alpha>] block? token = parser.ReadToken(false); if (!parser.ReadByte(token, ref color.r)) { if (!ZDTextParser.GetColorFromString(token, out color)) { parser.ReportError("Unsupported patch blend definition"); return; } } // That's Blend <int r>,<int g>,<int b>[,<float alpha>] block else { if (!parser.SkipWhitespace(false) || !parser.NextTokenIs(",", false) || !parser.SkipWhitespace(false) || !parser.ReadByte(ref color.g) || !parser.NextTokenIs(",", false) || !parser.SkipWhitespace(false) || !parser.ReadByte(ref color.b)) { parser.ReportError("Unsupported patch blend definition"); return; } } // Alpha block? float blendalpha = -1f; parser.SkipWhitespace(false); if (parser.NextTokenIs(",", false)) { parser.SkipWhitespace(false); if (!ReadTokenFloat(parser, token, out blendalpha)) { parser.ReportError("Unsupported patch blend alpha value"); return; } } // Blend may never be 0 when using the Tint effect if (blendalpha > 0.0f) { color.a = (byte)General.Clamp((int)(blendalpha * 255), 1, 254); blendstyle = TexturePathBlendStyle.TINT; } else if (blendalpha < 0.0f) { color.a = 255; blendstyle = TexturePathBlendStyle.BLEND; } else { // Ignore Blend when alpha == 0 parser.LogWarning("Blend with zero alpha will be ignored by ZDoom"); break; } // Store the color blendcolor = color; break; case "}": // Patch scope ends here, // break out of this parse loop done = true; break; } } }
// Constructor internal TextureStructure(TexturesParser parser, string typename, string virtualpath) { // Initialize this.typename = typename; this.virtualpath = virtualpath; patches = new List <PatchStructure>(4); xscale = 0.0f; yscale = 0.0f; // There should be 3 tokens separated by 2 commas now: // Name, Width, Height // First token is the texture name parser.SkipWhitespace(true); if (!parser.ReadTextureName(out name, typename)) { return; //mxd } //mxd. It can also be "optional" keyword. if (name.ToLowerInvariant() == "optional") { optional = true; parser.SkipWhitespace(true); if (!parser.ReadTextureName(out name, typename)) { return; //mxd } } if (string.IsNullOrEmpty(name)) { parser.ReportError("Expected " + typename + " name"); return; } // Now we should find a comma if (!parser.NextTokenIs(",")) { return; //mxd } // Next is the texture width parser.SkipWhitespace(true); string tokenstr = parser.ReadToken(); if (string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out width)) { parser.ReportError("Expected width in pixels"); return; } // Now we should find a comma again if (!parser.NextTokenIs(",")) { return; //mxd } // Next is the texture height parser.SkipWhitespace(true); tokenstr = parser.ReadToken(); if (string.IsNullOrEmpty(tokenstr) || !int.TryParse(tokenstr, NumberStyles.Integer, CultureInfo.InvariantCulture, out height)) { parser.ReportError("Expected height in pixels"); return; } // Next token should be the beginning of the texture scope if (!parser.NextTokenIs("{", false)) //mxd { parser.ReportError("Expected begin of structure"); return; } // Now parse the contents of texture structure bool done = false; //mxd while (!done && parser.SkipWhitespace(true)) { string token = parser.ReadToken(); token = token.ToLowerInvariant(); switch (token) { case "xscale": if (!ReadTokenFloat(parser, token, out xscale)) { return; } break; case "yscale": if (!ReadTokenFloat(parser, token, out yscale)) { return; } break; case "worldpanning": worldpanning = true; break; case "nulltexture": //mxd nulltexture = true; break; case "offset": // Read x offset if (!ReadTokenInt(parser, token, out xoffset)) { return; } // Now we should find a comma if (!parser.NextTokenIs(",")) { return; //mxd } // Read y offset if (!ReadTokenInt(parser, token, out yoffset)) { return; } break; case "patch": // Read patch structure PatchStructure pt = new PatchStructure(parser); if (parser.HasError) { break; } // Add the patch patches.Add(pt); break; case "}": // Actor scope ends here, // break out of this parse loop done = true; break; } } }