Merge remote-tracking branch 'udb/master'

This commit is contained in:
spherallic 2024-01-28 22:36:53 +01:00
commit 3726bb5a3b
18 changed files with 473 additions and 146 deletions

2
.editorconfig Normal file
View file

@ -0,0 +1,2 @@
[*.cs]
indent_style = tab

View file

@ -7,7 +7,7 @@ compilers
// All others are the required files (the setting names do not matter)
bcc
{
interface = "AccCompiler";
interface = "BccCompiler";
program = "bcc.exe";
zcommon = "zcommon.bcs";
std = "std.acs";

View file

@ -648,6 +648,138 @@ universalfields
default = 0.0;
managed = false;
}
nogradient_top
{
type = 3;
default = false;
managed = false;
}
flipgradient_top
{
type = 3;
default = false;
managed = false;
}
clampgradient_top
{
type = 3;
default = false;
managed = false;
}
useowncolors_top
{
type = 3;
default = false;
managed = false;
}
uppercolor_top
{
type = 10;
default = 16777215;
managed = false;
}
lowercolor_top
{
type = 10;
default = 16777215;
managed = false;
}
nogradient_mid
{
type = 3;
default = false;
managed = false;
}
flipgradient_mid
{
type = 3;
default = false;
managed = false;
}
clampgradient_mid
{
type = 3;
default = false;
managed = false;
}
useowncolors_mid
{
type = 3;
default = false;
managed = false;
}
uppercolor_mid
{
type = 10;
default = 16777215;
managed = false;
}
lowercolor_mid
{
type = 10;
default = 16777215;
managed = false;
}
nogradient_bottom
{
type = 3;
default = false;
managed = false;
}
flipgradient_bottom
{
type = 3;
default = false;
managed = false;
}
clampgradient_bottom
{
type = 3;
default = false;
managed = false;
}
useowncolors_bottom
{
type = 3;
default = false;
managed = false;
}
uppercolor_bottom
{
type = 10;
default = 16777215;
managed = false;
}
lowercolor_bottom
{
type = 10;
default = 16777215;
managed = false;
}
}
thing

View file

@ -141,6 +141,7 @@
-->
<ItemGroup>
<Compile Include="Compilers\AccCompiler.cs" />
<Compile Include="Compilers\BccCompiler.cs" />
<Compile Include="Compilers\NodesCompiler.cs" />
<Compile Include="Config\ArgumentInfo.cs" />
<Compile Include="Config\ExternalCommandSettings.cs" />

View file

@ -138,6 +138,7 @@
-->
<ItemGroup>
<Compile Include="Compilers\AccCompiler.cs" />
<Compile Include="Compilers\BccCompiler.cs" />
<Compile Include="Compilers\NodesCompiler.cs" />
<Compile Include="Config\ArgumentInfo.cs" />
<Compile Include="Config\ExternalCommandSettings.cs" />

View file

@ -30,18 +30,24 @@ using CodeImp.DoomBuilder.ZDoom.Scripting;
namespace CodeImp.DoomBuilder.Compilers
{
internal sealed class AccCompiler : Compiler
internal class AccCompiler : Compiler
{
#region ================== Constants
private const string ACS_ERROR_FILE = "acs.err";
#region ================== Internal classes
protected class CompileContext { }
#endregion
#region ================== Constants
private const string ACS_ERROR_FILE = "acs.err";
#endregion
#region ================== Variables
private AcsParserSE parser; //mxd
#endregion
#region ================== Properties
@ -52,7 +58,7 @@ namespace CodeImp.DoomBuilder.Compilers
#endregion
#region ================== Constructor
// Constructor
public AccCompiler(CompilerInfo info) : base(info, false)
{
@ -62,7 +68,7 @@ namespace CodeImp.DoomBuilder.Compilers
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
if (!isdisposed)
{
// Clean up
@ -70,26 +76,116 @@ namespace CodeImp.DoomBuilder.Compilers
base.Dispose();
}
}
#endregion
#region ================== Methods
protected virtual CompileContext OnBeforeProcessStart(ProcessStartInfo info)
{
return new CompileContext();
}
protected virtual void OnCheckError(HashSet<string> includes, ProcessStartInfo processinfo, Process process, CompileContext context)
{
int line = 0;
// Now find the error file
string errfile = Path.Combine(this.workingdir, ACS_ERROR_FILE);
if (File.Exists(errfile))
{
try
{
// Regex to find error lines
Regex errlinematcher = new Regex(":[0-9]+: ", RegexOptions.Compiled | RegexOptions.CultureInvariant);
// Read all lines
bool erroradded = false; //mxd
string[] errlines = File.ReadAllLines(errfile);
string temppath = this.tempdir.FullName + Path.DirectorySeparatorChar.ToString(); //mxd. Need trailing slash..
while (line < errlines.Length)
{
// Check line
string linestr = errlines[line];
Match match = errlinematcher.Match(linestr);
if (match.Success && (match.Index > 0))
{
CompilerError err = new CompilerError();
// The match without spaces and semicolon is the line number
string linenr = match.Value.Replace(":", "").Trim();
if (!int.TryParse(linenr, out err.linenumber))
err.linenumber = CompilerError.NO_LINE_NUMBER;
else
err.linenumber--;
// Everything before the match is the filename
err.filename = linestr.Substring(0, match.Index).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
//mxd. Get rid of temp directory path
if (err.filename.StartsWith(temppath)) err.filename = err.filename.Replace(temppath, string.Empty);
if (!Path.IsPathRooted(err.filename))
{
//mxd. If the error is in an include file, try to find it in loaded resources
if (includes.Contains(err.filename))
{
foreach (DataReader dr in General.Map.Data.Containers)
{
if (dr is DirectoryReader && dr.FileExists(err.filename))
{
err.filename = Path.Combine(dr.Location.location, err.filename);
break;
}
}
}
else
{
// Add working directory to filename, so it could be recognized as map namespace lump in MapManager.CompileLump()
err.filename = Path.Combine(processinfo.WorkingDirectory, err.filename);
}
}
// Everything after the match is the description
err.description = linestr.Substring(match.Index + match.Length).Trim();
// Report the error
ReportError(err);
erroradded = true; //mxd
}
// Next line
line++;
}
//mxd. Some ACC errors are not properly formatted. If that's the case, threat the whole acs.err as an error...
if (!erroradded && errlines.Length > 0)
{
ReportError(new CompilerError(string.Join(Environment.NewLine, errlines)));
}
}
catch (Exception e)
{
// Error reading errors (ironic, isn't it)
ReportError(new CompilerError("Failed to retrieve compiler error report. " + e.GetType().Name + ": " + e.Message));
}
}
}
// This runs the compiler
public override bool Run()
{
Process process;
int line = 0;
string sourcedir = Path.GetDirectoryName(sourcefile);
// Preprocess the file
parser = new AcsParserSE
{
IsMapScriptsLump = SourceIsMapScriptsLump,
OnInclude = delegate(AcsParserSE se, string includefile, AcsParserSE.IncludeType includetype)
OnInclude = delegate (AcsParserSE se, string includefile, AcsParserSE.IncludeType includetype)
{
TextResourceData data = General.Map.Data.GetTextResourceData(includefile);
if(data == null)
if (data == null)
{
se.ReportError("Unable to find include file \"" + includefile + "\".");
return false; // Fial
@ -100,31 +196,31 @@ namespace CodeImp.DoomBuilder.Compilers
};
string inputfilepath = Path.Combine(this.tempdir.FullName, inputfile);
using(FileStream stream = File.OpenRead(inputfilepath))
using (FileStream stream = File.OpenRead(inputfilepath))
{
// Map SCRIPTS lump is empty. Abort the process without generating any warnings or errors.
if(SourceIsMapScriptsLump && stream.Length == 0) return false;
if (SourceIsMapScriptsLump && stream.Length == 0) return false;
DataLocation dl = new DataLocation(DataLocation.RESOURCE_DIRECTORY, Path.GetDirectoryName(inputfilepath), false, false, false, null);
//mxd. TextResourceData must point to temp path when compiling WAD lumps for lump to be recognized as map lump when reporting errors...
TextResourceData data = new TextResourceData(stream, dl, (SourceIsMapScriptsLump ? inputfile : sourcefile));
if(!parser.Parse(data, info.Files, true, AcsParserSE.IncludeType.NONE, false))
if (!parser.Parse(data, info.Files, true, AcsParserSE.IncludeType.NONE, false))
{
// Check for errors
if(parser.HasError) ReportError(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
if (parser.HasError) ReportError(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
return true;
}
}
//mxd. External lumps should be libraries
if(!SourceIsMapScriptsLump && !parser.IsLibrary)
if (!SourceIsMapScriptsLump && !parser.IsLibrary)
{
ReportError(new CompilerError("External ACS files can only be compiled as libraries.", sourcefile));
return true;
}
//mxd. Update script names if we are compiling the map SCRIPTS lump
if(SourceIsMapScriptsLump)
if (SourceIsMapScriptsLump)
{
General.Map.UpdateScriptNames(parser);
}
@ -132,22 +228,22 @@ namespace CodeImp.DoomBuilder.Compilers
//xabis
// Copy includes from the resources into the compiler's folder, preserving relative pathing and naming
HashSet<string> includes = parser.GetIncludes(); //mxd
foreach(string include in includes)
foreach (string include in includes)
{
// Grab the script text from the resources
TextResourceData data = General.Map.Data.GetTextResourceData(include);
if(data != null && data.Stream != null)
if (data != null && data.Stream != null)
{
// Pull the pk3 or directory sub folder out if applicable
FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));
// Do not allow files to be overwritten, either accidentally or maliciously
if(!fi.Exists)
if (!fi.Exists)
{
General.WriteLogLine("Copying script include: " + include);
// Create the directory path as needed
if(!string.IsNullOrEmpty(fi.DirectoryName)) Directory.CreateDirectory(fi.DirectoryName);
if (!string.IsNullOrEmpty(fi.DirectoryName)) Directory.CreateDirectory(fi.DirectoryName);
// Dump the script into the target file
BinaryReader reader = new BinaryReader(data.Stream);
@ -164,7 +260,7 @@ namespace CodeImp.DoomBuilder.Compilers
args = args.Replace("%PT", this.tempdir.FullName);
args = args.Replace("%PS", sourcedir);
args = args.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); //mxd. This fixes include path when the map is in a root directory
// Setup process info
ProcessStartInfo processinfo = new ProcessStartInfo();
processinfo.Arguments = args;
@ -174,114 +270,37 @@ namespace CodeImp.DoomBuilder.Compilers
processinfo.UseShellExecute = true;
processinfo.WindowStyle = ProcessWindowStyle.Hidden;
processinfo.WorkingDirectory = this.workingdir;
CompileContext context = OnBeforeProcessStart(processinfo);
// Output info
General.WriteLogLine("Running compiler...");
General.WriteLogLine("Program: " + processinfo.FileName);
General.WriteLogLine("Arguments: " + processinfo.Arguments);
try
{
// Start the compiler
process = Process.Start(processinfo);
}
catch(Exception e)
catch (Exception e)
{
// Unable to start the compiler
General.ShowErrorMessage("Unable to start the compiler (" + info.Name + "). " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
return false;
}
// Wait for compiler to complete
process.WaitForExit();
TimeSpan deltatime = TimeSpan.FromTicks(process.ExitTime.Ticks - process.StartTime.Ticks);
General.WriteLogLine("Compiler process has finished.");
General.WriteLogLine("Compile time: " + deltatime.TotalSeconds.ToString("########0.00") + " seconds");
// Now find the error file
string errfile = Path.Combine(this.workingdir, ACS_ERROR_FILE);
if(File.Exists(errfile))
{
try
{
// Regex to find error lines
Regex errlinematcher = new Regex(":[0-9]+: ", RegexOptions.Compiled | RegexOptions.CultureInvariant);
// Read all lines
bool erroradded = false; //mxd
string[] errlines = File.ReadAllLines(errfile);
string temppath = this.tempdir.FullName + Path.DirectorySeparatorChar.ToString(); //mxd. Need trailing slash..
while(line < errlines.Length)
{
// Check line
string linestr = errlines[line];
Match match = errlinematcher.Match(linestr);
if(match.Success && (match.Index > 0))
{
CompilerError err = new CompilerError();
// The match without spaces and semicolon is the line number
string linenr = match.Value.Replace(":", "").Trim();
if(!int.TryParse(linenr, out err.linenumber))
err.linenumber = CompilerError.NO_LINE_NUMBER;
else
err.linenumber--;
// Everything before the match is the filename
err.filename = linestr.Substring(0, match.Index).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
//mxd. Get rid of temp directory path
if(err.filename.StartsWith(temppath)) err.filename = err.filename.Replace(temppath, string.Empty);
if(!Path.IsPathRooted(err.filename))
{
//mxd. If the error is in an include file, try to find it in loaded resources
if(includes.Contains(err.filename))
{
foreach(DataReader dr in General.Map.Data.Containers)
{
if(dr is DirectoryReader && dr.FileExists(err.filename))
{
err.filename = Path.Combine(dr.Location.location, err.filename);
break;
}
}
}
else
{
// Add working directory to filename, so it could be recognized as map namespace lump in MapManager.CompileLump()
err.filename = Path.Combine(processinfo.WorkingDirectory, err.filename);
}
}
// Everything after the match is the description
err.description = linestr.Substring(match.Index + match.Length).Trim();
// Report the error
ReportError(err);
erroradded = true; //mxd
}
// Next line
line++;
}
OnCheckError(includes, processinfo, process, context);
//mxd. Some ACC errors are not properly formatted. If that's the case, threat the whole acs.err as an error...
if(!erroradded && errlines.Length > 0)
{
ReportError(new CompilerError(string.Join(Environment.NewLine, errlines)));
}
}
catch(Exception e)
{
// Error reading errors (ironic, isn't it)
ReportError(new CompilerError("Failed to retrieve compiler error report. " + e.GetType().Name + ": " + e.Message));
}
}
return true;
}
#endregion
}
}

View file

@ -0,0 +1,83 @@
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace CodeImp.DoomBuilder.Compilers
{
internal class BccCompiler : AccCompiler
{
public BccCompiler(CompilerInfo info) : base(info) { }
protected override CompileContext OnBeforeProcessStart(ProcessStartInfo info)
{
info.UseShellExecute = false;
info.CreateNoWindow = true;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
return new CompileContext();
}
protected override void OnCheckError(HashSet<string> includes, ProcessStartInfo processinfo, Process process, CompileContext context)
{
if (process.ExitCode != 0)
{
bool foundAnyErrors = false;
string[] errorLines = process.StandardOutput.ReadToEnd().Split('\n');
foreach (string rawErrorLine in errorLines)
{
string[] rawError = rawErrorLine.Split(new char[] { ':' }, 4);
if (rawError.Length != 4)
continue;
string errorFile = rawError[0];
int errorLine;
if (!int.TryParse(rawError[1], out errorLine))
continue;
errorLine--;
// rawError[2] is ignored. in BCC, this contains the column at which the error happened. not supported in error viewer.
string errorContent = rawError[3].Trim();
// logic copied from AccCompiler
string temppath = this.tempdir.FullName + Path.DirectorySeparatorChar.ToString(); //mxd. Need trailing slash..
if (errorFile.StartsWith(temppath)) errorFile = errorFile.Replace(temppath, string.Empty);
if (!Path.IsPathRooted(errorFile))
{
//mxd. If the error is in an include file, try to find it in loaded resources
if (includes.Contains(errorFile))
{
foreach (DataReader dr in General.Map.Data.Containers)
{
if (dr is DirectoryReader && dr.FileExists(errorFile))
{
errorFile = Path.Combine(dr.Location.location, errorFile);
break;
}
}
}
else
{
// Add working directory to filename, so it could be recognized as map namespace lump in MapManager.CompileLump()
errorFile = Path.Combine(processinfo.WorkingDirectory, errorFile);
}
}
// end logic copied from AccCompiler
CompilerError err = new CompilerError();
err.linenumber = errorLine;
err.filename = errorFile;
err.description = errorContent;
ReportError(err);
foundAnyErrors = true;
}
if (!foundAnyErrors)
ReportError(new CompilerError(string.Join(Environment.NewLine, errorLines)));
}
}
}
}

View file

@ -640,23 +640,30 @@ namespace CodeImp.DoomBuilder.Config
if (renderradius == 0)
renderradius = radius;
//mxd. DistanceCheck. The value is CVAR. Also we'll need squared value
if(actor.HasPropertyWithValue("distancecheck"))
// DistanceCheck. The value is CVAR. Also we'll need squared value
if (actor.HasPropertyWithValue("distancecheck"))
{
string cvarname = actor.GetPropertyValueString("distancecheck", 0);
if(!General.Map.Data.CVars.Integers.ContainsKey(cvarname))
if (General.Map.Data.CVars.AllNames.Contains(cvarname))
{
General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". DistanceCheck property references undefined cvar \"" + cvarname + "\"");
distancechecksq = double.MaxValue;
if (!General.Map.Data.CVars.Integers.ContainsKey(cvarname))
{
General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". DistanceCheck property references cvar \"" + cvarname + "\" which has to be of type int, but is not");
distancechecksq = double.MaxValue;
}
else
{
distancechecksq = Math.Pow(General.Map.Data.CVars.Integers[cvarname], 2);
}
}
else
{
distancechecksq = Math.Pow(General.Map.Data.CVars.Integers[cvarname], 2);
General.ErrorLogger.Add(ErrorType.Error, "Error in actor \"" + title + "\":" + index + ". DistanceCheck property references undefined cvar \"" + cvarname + "\"");
}
}
//mxd. Renderstyle
if(actor.HasPropertyWithValue("renderstyle") && !actor.HasProperty("$ignorerenderstyle"))
if (actor.HasPropertyWithValue("renderstyle") && !actor.HasProperty("$ignorerenderstyle"))
renderstyle = actor.GetPropertyValueString("renderstyle", 0, true).ToLower();
//mxd. Alpha

View file

@ -69,8 +69,8 @@ namespace CodeImp.DoomBuilder.Controls
if(AllowDecimal)
{
newValue1 = Math.Round(UniFields.GetFloat(fields, field1, defaultValue), 2).ToString();
newValue2 = Math.Round(UniFields.GetFloat(fields, field2, defaultValue), 2).ToString();
newValue1 = UniFields.GetFloat(fields, field1, defaultValue).ToString();
newValue2 = UniFields.GetFloat(fields, field2, defaultValue).ToString();
}
else
{

View file

@ -17,7 +17,7 @@ namespace CodeImp.DoomBuilder.Data
internal readonly Dictionary<string, PixelColor> Colors;
internal readonly Dictionary<string, bool> Booleans;
internal readonly Dictionary<string, string> Strings;
private readonly HashSet<string> allnames;
internal readonly HashSet<string> AllNames;
#endregion
@ -30,7 +30,7 @@ namespace CodeImp.DoomBuilder.Data
Colors = new Dictionary<string, PixelColor>(StringComparer.OrdinalIgnoreCase);
Booleans = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
Strings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
allnames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
AllNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
#endregion
@ -39,40 +39,40 @@ namespace CodeImp.DoomBuilder.Data
public bool AddValue(string name, int value)
{
if(allnames.Contains(name)) return false;
allnames.Add(name);
if(AllNames.Contains(name)) return false;
AllNames.Add(name);
Integers.Add(name, value);
return true;
}
public bool AddValue(string name, float value)
{
if(allnames.Contains(name)) return false;
allnames.Add(name);
if(AllNames.Contains(name)) return false;
AllNames.Add(name);
Floats.Add(name, value);
return true;
}
public bool AddValue(string name, PixelColor value)
{
if(allnames.Contains(name)) return false;
allnames.Add(name);
if(AllNames.Contains(name)) return false;
AllNames.Add(name);
Colors.Add(name, value);
return true;
}
public bool AddValue(string name, bool value)
{
if(allnames.Contains(name)) return false;
allnames.Add(name);
if(AllNames.Contains(name)) return false;
AllNames.Add(name);
Booleans.Add(name, value);
return true;
}
public bool AddValue(string name, string value)
{
if(allnames.Contains(name)) return false;
allnames.Add(name);
if(AllNames.Contains(name)) return false;
AllNames.Add(name);
Strings.Add(name, value);
return true;
}

View file

@ -23,6 +23,7 @@ using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
@ -293,6 +294,13 @@ namespace CodeImp.DoomBuilder
#region ================== Configurations
/// <summary>
/// Checks if a given game configuration file exists.
/// </summary>
/// <param name="filename">The file name of the game configuration file.</param>
/// <returns>true if the game configuration exists, false if it doesn't</returns>
internal static bool ConfigurationInfoExist(string filename) => configs.Any(ci => string.Compare(Path.GetFileNameWithoutExtension(ci.Filename), Path.GetFileNameWithoutExtension(filename), true) == 0);
// This returns the game configuration info by filename
internal static ConfigurationInfo GetConfigurationInfo(string filename)
{

View file

@ -421,7 +421,16 @@ namespace CodeImp.DoomBuilder
// Copy the map lumps to the temp file
General.WriteLogLine("Copying map lumps to temporary file...");
CopyLumpsByType(mapwad, options.CurrentName, tempwadreader.WadFile, TEMP_MAP_HEADER, true, true, true, true);
if (!CopyLumpsByType(mapwad, options.CurrentName, tempwadreader.WadFile, TEMP_MAP_HEADER, true, true, true, true))
{
// Ooops, the map doesn't exit. This should only happend when run from the command line using the "-map" parameter
General.ErrorLogger.Add(ErrorType.Error, $"Map \"{options.CurrentName}\" does not exist in file \"{filepathname}\".");
// Close the map file
mapwad.Dispose();
return false;
}
// Close the map file
mapwad.Dispose();
@ -1660,7 +1669,7 @@ namespace CodeImp.DoomBuilder
}
// This copies specific map lumps from one WAD to another
private void CopyLumpsByType(WAD source, string sourcemapname,
private bool CopyLumpsByType(WAD source, string sourcemapname,
WAD target, string targetmapname,
bool copyrequired, bool copyblindcopy,
bool copynodebuild, bool copyscript,
@ -1734,7 +1743,11 @@ namespace CodeImp.DoomBuilder
target.WriteHeaders(); //mxd
target.Compress(); // [ZZ]
return true;
}
return false;
}
// This finds a lump within the range of known lump names

View file

@ -620,7 +620,7 @@ namespace CodeImp.DoomBuilder.Map
if(args[0] > General.Map.FormatInterface.MaxArgument) // Split sector tag?
{
int hitag = args[0] / 256;
int lotag = args[0] - hitag;
int lotag = args[0] % 256;
args[0] = lotag;
args[4] = hitag;
@ -652,7 +652,7 @@ namespace CodeImp.DoomBuilder.Map
break;
default: // Convert tag to Line_SetIdentification?
if(tags[0] > General.Map.FormatInterface.MinArgument)
if(tags[0] > General.Map.FormatInterface.MaxArgument)
{
if(action != 0)
{
@ -662,7 +662,7 @@ namespace CodeImp.DoomBuilder.Map
else // Convert to Line_SetIdentification
{
int hiid = tags[0] / 256;
int loid = tags[0] - hiid;
int loid = tags[0] % 256;
action = 121;
args[0] = loid;

View file

@ -617,7 +617,7 @@ namespace CodeImp.DoomBuilder.Rendering
{
if(!resourcesunloaded)
{
ShaderName pass = Renderer.FullBrightness ? ShaderName.display2d_fullbright : ShaderName.display2d_normal; //mxd
ShaderName pass = (Renderer.FullBrightness && General.Map.Renderer2D.ViewMode != ViewMode.Brightness) ? ShaderName.display2d_fullbright : ShaderName.display2d_normal; //mxd
foreach(KeyValuePair<ImageData, List<SurfaceEntry>> imgsurfaces in surfaces)
{
graphics.SetShader(pass);

View file

@ -565,7 +565,7 @@ namespace CodeImp.DoomBuilder.Windows
configfile = General.AutoLoadConfig;
if (string.IsNullOrEmpty(configfile)) configfile = mapsettings.ReadSetting("gameconfig", "");
if(configfile.Trim().Length == 0)
if(configfile.Trim().Length == 0 || !General.ConfigurationInfoExist(configfile))
{
showdialog = true;
}

View file

@ -14,11 +14,13 @@ namespace CodeImp.DoomBuilder.ZDoom
{
#region ================== DECORATE Actor Structure parsing
private DecorateParser parser;
internal DecorateActorStructure(ZDTextParser zdparser, DecorateCategoryInfo catinfo)
{
this.catinfo = catinfo; //mxd
DecorateParser parser = (DecorateParser)zdparser;
parser = (DecorateParser)zdparser;
bool done = false; //mxd
// First next token is the class name
@ -170,6 +172,10 @@ namespace CodeImp.DoomBuilder.ZDoom
break;
case "states":
// Skip cast type if there is one
if (!SkipCastTypes())
return;
if (!parser.NextTokenIs("{", true))
return;
@ -456,6 +462,59 @@ namespace CodeImp.DoomBuilder.ZDoom
}
}
#endregion
}
/// <summary>
/// Skips state cast type, it one exists.
/// </summary>
/// <returns>true if there was nothing to skip or if skippen succeeded, false if it failed</returns>
private bool SkipCastTypes()
{
// Alloed casts, see https://zdoom.org/wiki/Converting_DECORATE_code_to_ZScript#Cast_types
string[] allowedcasts = { "actor", "overlay", "weapon", "item" };
// Skip cast types, which can be defined like this:
// States(Actor, Item)
// See https://github.com/UltimateDoomBuilder/UltimateDoomBuilder/issues/977
if (parser.NextTokenIs("(", false))
{
while (parser.SkipWhitespace(true))
{
string token = parser.ReadToken().ToLowerInvariant();
if(!allowedcasts.Contains(token))
{
parser.ReportError($"Unexpected cast type \"{token}\", expected one of: " + string.Join(", ", allowedcasts));
return false;
}
parser.SkipWhitespace(true);
// Get next token
token = parser.ReadToken();
// End of cast type?
if(token == ")")
return true;
// More cast types coming?
if (token == ",")
continue;
// No comma or brace after a cast type, so report an error and return
parser.ReportError($"Expected \",\", or \")\", got {token}");
return false;
}
}
else
{
// We get here if there was no cast type
return true;
}
// We should never get here, since we'll return in the parsing loop,
// but we need to make the compiler happy
return false;
}
#endregion
}
}

View file

@ -549,6 +549,8 @@ namespace CodeImp.DoomBuilder.ZDoom
return false;
}
long prevstreamposition = DataStream.Position;
string token = ReadToken();
if(string.Compare(token, expectedtoken, true) != 0)
@ -556,7 +558,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(reporterror) ReportError("Expected \"" + expectedtoken + "\", but got \"" + token + "\"");
// Rewind so this structure can be read again
DataStream.Seek(-token.Length - 1, SeekOrigin.Current);
DataStream.Seek(prevstreamposition, SeekOrigin.Begin);
return false;
}

View file

@ -284,8 +284,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
offset.y %= texture.Height / s.Fields.GetValue((alignFloors ? "yscalefloor" : "yscaleceiling"), 1.0);
}
UniFields.SetFloat(s.Fields, (alignFloors ? "xpanningfloor" : "xpanningceiling"), Math.Round(-offset.x), 0.0);
UniFields.SetFloat(s.Fields, (alignFloors ? "ypanningfloor" : "ypanningceiling"), Math.Round(offset.y), 0.0);
UniFields.SetFloat(s.Fields, (alignFloors ? "xpanningfloor" : "xpanningceiling"), Math.Round(-offset.x, 6), 0.0);
UniFields.SetFloat(s.Fields, (alignFloors ? "ypanningfloor" : "ypanningceiling"), Math.Round(offset.y, 6), 0.0);
//update
s.UpdateNeeded = true;