} //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); name = parser.StripTokenQuotes(parser.ReadToken(false)); //mxd. Don't skip newline 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, ref 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; } } }