Merged in GZDB r2497.

This commit is contained in:
MascaraSnake 2016-04-07 19:31:06 +02:00
parent 264a883e47
commit 6ad64c1cc0
6 changed files with 302 additions and 65 deletions

View File

@ -87,6 +87,7 @@
<Compile Include="Compilers\AccCompiler.cs" />
<Compile Include="Compilers\NodesCompiler.cs" />
<Compile Include="Config\ArgumentInfo.cs" />
<Compile Include="Config\ScriptDocumentSettings.cs" />
<Compile Include="Config\ScriptLumpInfo.cs" />
<Compile Include="Config\MapLumpInfo.cs" />
<Compile Include="Config\ScriptConfiguration.cs" />

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
namespace CodeImp.DoomBuilder.Config
{
internal struct ScriptDocumentSettings
{
public Dictionary<int, HashSet<int>> FoldLevels; // <fold level, line numbers>
public int CaretPosition;
public int FirstVisibleLine;
public string Filename;
public bool IsActiveTab;
public long Hash;
}
}

View File

@ -409,6 +409,63 @@ namespace CodeImp.DoomBuilder.Controls
editor.IndentSelection(indent);
}
//mxd
internal void SetViewSettings(ScriptDocumentSettings settings)
{
// Text must be exactly the same
long hash = MurmurHash2.Hash(Text);
if (hash != settings.Hash) return;
// Restore fold levels
if (settings.FoldLevels != null && General.Settings.ScriptShowFolding && (Scintilla.Lexer == Lexer.Cpp || Scintilla.Lexer == Lexer.CppNoCase))
{
// We'll want to fold deeper levels first...
int[] fl = new int[settings.FoldLevels.Keys.Count];
settings.FoldLevels.Keys.CopyTo(fl, 0);
List<int> foldlevels = new List<int>(fl);
foldlevels.Sort((a, b) => -1 * a.CompareTo(b)); // Sort in descending order
foreach (int level in foldlevels)
{
foreach (int line in settings.FoldLevels[level])
Scintilla.Lines[line].FoldLine(FoldAction.Contract);
}
}
// Restore scroll
Scintilla.FirstVisibleLine = settings.FirstVisibleLine;
// Restore caret position
Scintilla.SetEmptySelection(settings.CaretPosition);
}
//mxd
internal ScriptDocumentSettings GetViewSettings()
{
Dictionary<int, HashSet<int>> foldlevels = new Dictionary<int, HashSet<int>>();
for (int i = 0; i < Scintilla.Lines.Count; i++)
{
if (!Scintilla.Lines[i].Expanded)
{
if (!foldlevels.ContainsKey(Scintilla.Lines[i].FoldLevel))
foldlevels.Add(Scintilla.Lines[i].FoldLevel, new HashSet<int>());
foldlevels[Scintilla.Lines[i].FoldLevel].Add(i);
}
}
return new ScriptDocumentSettings
{
Filename = this.Filename,
FoldLevels = foldlevels,
CaretPosition = Scintilla.SelectionStart,
IsActiveTab = (this.Panel.ActiveTab == this),
FirstVisibleLine = Scintilla.FirstVisibleLine,
Hash = MurmurHash2.Hash(Text),
};
}
#endregion
#region ================== Events

View File

@ -19,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Compilers;
@ -119,6 +118,7 @@ namespace CodeImp.DoomBuilder.Controls
openfile.Filter = "Script files|" + filterall + "|" + filterseperate + "|All files|*.*";
// Load the script lumps
ScriptDocumentTab activetab = null; //mxd
foreach (MapLumpInfo maplumpinfo in General.Map.Config.MapLumps.Values)
{
// Is this a script lump?
@ -126,6 +126,15 @@ namespace CodeImp.DoomBuilder.Controls
{
// Load this!
ScriptLumpDocumentTab t = new ScriptLumpDocumentTab(this, maplumpinfo.Name, General.CompiledScriptConfigs[General.Map.Options.ScriptCompiler]);
//mxd. Apply stored settings?
if (General.Map.Options.ScriptLumpSettings.ContainsKey(maplumpinfo.Name))
{
t.SetViewSettings(General.Map.Options.ScriptLumpSettings[maplumpinfo.Name]);
if (General.Map.Options.ScriptLumpSettings[maplumpinfo.Name].IsActiveTab)
activetab = t;
}
t.OnTextChanged += tabpage_OnLumpTextChanged; //mxd
t.Scintilla.UpdateUI += scintilla_OnUpdateUI; //mxd
tabs.TabPages.Add(t);
@ -134,6 +143,15 @@ namespace CodeImp.DoomBuilder.Controls
{
// Load this!
ScriptLumpDocumentTab t = new ScriptLumpDocumentTab(this, maplumpinfo.Name, maplumpinfo.Script);
//mxd. Apply stored settings?
if (General.Map.Options.ScriptLumpSettings.ContainsKey(maplumpinfo.Name))
{
t.SetViewSettings(General.Map.Options.ScriptLumpSettings[maplumpinfo.Name]);
if (General.Map.Options.ScriptLumpSettings[maplumpinfo.Name].IsActiveTab)
activetab = t;
}
t.OnTextChanged += tabpage_OnLumpTextChanged; //mxd
t.Scintilla.UpdateUI += scintilla_OnUpdateUI; //mxd
tabs.TabPages.Add(t);
@ -157,6 +175,15 @@ namespace CodeImp.DoomBuilder.Controls
if (l.Name.ToUpperInvariant().StartsWith(scriptlumpinfo.Name.ToUpperInvariant()))
{
GlobalScriptLumpDocumentTab t = new GlobalScriptLumpDocumentTab(this, l.Name, scriptlumpinfo.Script, General.Map.FilePathName);
//mxd. Apply stored settings?
if (General.Map.Options.ScriptFileSettings.ContainsKey(l.Name))
{
t.SetViewSettings(General.Map.Options.ScriptFileSettings[l.Name]);
if (General.Map.Options.ScriptFileSettings[l.Name].IsActiveTab)
activetab = t;
}
t.OnTextChanged += tabpage_OnTextChanged;
t.Scintilla.UpdateUI += scintilla_OnUpdateUI;
tabs.TabPages.Add(t);
@ -166,6 +193,15 @@ namespace CodeImp.DoomBuilder.Controls
else
{
GlobalScriptLumpDocumentTab t = new GlobalScriptLumpDocumentTab(this, scriptlumpinfo.Name, scriptlumpinfo.Script, General.Map.FilePathName);
//mxd. Apply stored settings?
if (General.Map.Options.ScriptFileSettings.ContainsKey(scriptlumpinfo.Name))
{
t.SetViewSettings(General.Map.Options.ScriptFileSettings[scriptlumpinfo.Name]);
if (General.Map.Options.ScriptFileSettings[scriptlumpinfo.Name].IsActiveTab)
activetab = t;
}
t.OnTextChanged += tabpage_OnTextChanged;
t.Scintilla.UpdateUI += scintilla_OnUpdateUI;
tabs.TabPages.Add(t);
@ -175,20 +211,30 @@ namespace CodeImp.DoomBuilder.Controls
}
// Load the files that were previously opened for this map
foreach (String filename in General.Map.Options.ScriptFiles)
foreach (ScriptDocumentSettings settings in General.Map.Options.ScriptFileSettings.Values)
{
// Does this file exist?
if (File.Exists(filename))
if (File.Exists(settings.Filename))
{
// Load this!
OpenFile(filename);
ScriptFileDocumentTab t = OpenFile(settings.Filename);
t.SetViewSettings(settings); //mxd
if (settings.IsActiveTab) activetab = t;
}
}
//mxd. Reselect previously selected tab
if (activetab != null)
{
tabs.SelectedTab = activetab;
}
//mxd. Select "Scripts" tab, because that's what user will want 99% of time
//MascaraSnake: For SRB2, select "MAINCFG" tab
int scriptsindex = General.Map.SRB2 ? GetTabPageIndex("MAINCFG") : GetTabPageIndex("SCRIPTS");
tabs.SelectedIndex = (scriptsindex == -1 ? 0 : scriptsindex);
else
{
int scriptsindex = General.Map.SRB2 ? GetTabPageIndex("MAINCFG") : GetTabPageIndex("SCRIPTS");
tabs.SelectedIndex = (scriptsindex == -1 ? 0 : scriptsindex);
}
//mxd. Apply quick search settings
searchmatchcase.Checked = matchcase;
@ -452,12 +498,16 @@ namespace CodeImp.DoomBuilder.Controls
// This writes all explicitly opened files to the configuration
public void WriteOpenFilesToConfiguration()
{
List<string> files = new List<string>();
foreach (ScriptDocumentTab t in tabs.TabPages)
General.Map.Options.ScriptFileSettings.Clear(); //mxd
General.Map.Options.ScriptLumpSettings.Clear(); //mxd
foreach (ScriptDocumentTab t in tabs.TabPages) //mxd
{
if (t.ExplicitSave) files.Add(t.Filename);
if (t.ExplicitSave)
General.Map.Options.ScriptFileSettings.Add(t.Filename, t.GetViewSettings());
else
General.Map.Options.ScriptLumpSettings.Add(t.Filename, t.GetViewSettings());
}
General.Map.Options.ScriptFiles = files;
}
// This asks to save files and returns the result

View File

@ -251,7 +251,7 @@ namespace CodeImp.DoomBuilder
// Apply settings
this.filetitle = options.CurrentName + ".wad";
this.filepathname = "";
this.filepathname = String.Empty;
this.maploading = true; //mxd
this.changed = false;
this.options = options;
@ -956,9 +956,9 @@ namespace CodeImp.DoomBuilder
General.ShowErrorMessage("Error renaming map lump name: the original map lump could not be found!", MessageBoxButtons.OK);
options.CurrentName = options.PreviousName;
}
}
options.PreviousName = "";
options.PreviousName = String.Empty;
}
// Done with the target file
@ -1194,15 +1194,15 @@ namespace CodeImp.DoomBuilder
else
{
//mxd. collect errors
string compilererrors = "";
string compilererrors = String.Empty;
foreach(CompilerError e in compiler.Errors)
compilererrors += Environment.NewLine + e.description;
// Nodebuilder did not build the lumps!
if(failaswarning)
General.ShowWarningMessage("Unable to build the nodes: The nodebuilder failed to build the expected data structures.\nThe map will be saved without the nodes." + (compiler.Errors.Length > 0 ? Environment.NewLine + compilererrors : ""), MessageBoxButtons.OK);
General.ShowWarningMessage("Unable to build the nodes: The nodebuilder failed to build the expected data structures.\nThe map will be saved without the nodes." + (compiler.Errors.Length > 0 ? Environment.NewLine + compilererrors : String.Empty), MessageBoxButtons.OK);
else
General.ShowErrorMessage("Unable to build the nodes: The nodebuilder failed to build the expected data structures." + (compiler.Errors.Length > 0 ? Environment.NewLine + compilererrors : ""), MessageBoxButtons.OK);
General.ShowErrorMessage("Unable to build the nodes: The nodebuilder failed to build the expected data structures." + (compiler.Errors.Length > 0 ? Environment.NewLine + compilererrors : String.Empty), MessageBoxButtons.OK);
}
// Done with the build wad
@ -1211,7 +1211,7 @@ namespace CodeImp.DoomBuilder
else //mxd
{
//collect errors
string compilererrors = "";
string compilererrors = String.Empty;
foreach(CompilerError e in compiler.Errors)
compilererrors += Environment.NewLine + e.description;
@ -2081,7 +2081,7 @@ namespace CodeImp.DoomBuilder
//INFO: also, error.linenumber is zero-based
foreach(CompilerError error in compilererrors)
{
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + (error.filename.StartsWith("?") ? error.filename.Replace("?", "") : error.filename)
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + (error.filename.StartsWith("?") ? error.filename.Replace("?", String.Empty) : error.filename)
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "', line " + (error.linenumber + 1) : "'")
+ ". " + error.description + ".");
}

View File

@ -16,16 +16,18 @@
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Reflection;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.IO;
using System.IO;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Plugins;
using System.Collections.Specialized;
#endregion
@ -40,7 +42,7 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Variables
// Map configuration
private Configuration mapconfig;
private readonly Configuration mapconfig;
// Game configuration
private string configfile;
@ -55,11 +57,12 @@ namespace CodeImp.DoomBuilder.Map
// Additional resources
private DataLocationList resources;
// Script files opened
private List<string> scriptfiles;
//mxd. View settings for opened script files and lumps
private Dictionary<string, ScriptDocumentSettings> scriptfilesettings;
private Dictionary<string, ScriptDocumentSettings> scriptlumpsettings;
// mxd. Script compiler
private string scriptcompiler;
// mxd. Script compiler
private string scriptcompiler;
//mxd. Sector drawing options
private string defaultfloortexture;
@ -85,8 +88,8 @@ namespace CodeImp.DoomBuilder.Map
private bool uselongtexturenames;
//mxd. Position and scale
private Vector2D viewposition;
private float viewscale;
private readonly Vector2D viewposition;
private readonly float viewscale;
#endregion
@ -95,9 +98,10 @@ namespace CodeImp.DoomBuilder.Map
internal string ConfigFile { get { return configfile; } set { configfile = value; } }
internal DataLocationList Resources { get { return resources; } }
internal bool StrictPatches { get { return strictpatches; } set { strictpatches = value; } }
internal List<string> ScriptFiles { get { return scriptfiles; } set { scriptfiles = value; } }
internal string ScriptCompiler { get { return scriptcompiler; } set { scriptcompiler = value; } } //mxd
internal string PreviousName { get { return previousname; } set { previousname = value; } }
internal Dictionary<string, ScriptDocumentSettings> ScriptFileSettings { get { return scriptfilesettings; } } //mxd
internal Dictionary<string, ScriptDocumentSettings> ScriptLumpSettings { get { return scriptlumpsettings; } } //mxd
internal string ScriptCompiler { get { return scriptcompiler; } set { scriptcompiler = value; } } //mxd
internal string PreviousName { get { return previousname; } set { previousname = value; } }
internal string CurrentName
{
get { return currentname; }
@ -159,9 +163,10 @@ namespace CodeImp.DoomBuilder.Map
this.strictpatches = false;
this.resources = new DataLocationList();
this.mapconfig = new Configuration(true);
this.scriptfiles = new List<string>();
this.scriptcompiler = ""; //mxd
this.tagLabels = new Dictionary<int, string>(); //mxd
this.scriptfilesettings = new Dictionary<string, ScriptDocumentSettings>(); //mxd
this.scriptlumpsettings = new Dictionary<string, ScriptDocumentSettings>(); //mxd
this.scriptcompiler = ""; //mxd
this.tagLabels = new Dictionary<int, string>(); //mxd
this.viewposition = new Vector2D(float.NaN, float.NaN); //mxd
this.viewscale = float.NaN; //mxd
@ -180,7 +185,8 @@ namespace CodeImp.DoomBuilder.Map
this.configfile = cfg.ReadSetting("gameconfig", "");
this.resources = new DataLocationList();
this.mapconfig = new Configuration(true);
this.scriptfiles = new List<string>();
this.scriptfilesettings = new Dictionary<string, ScriptDocumentSettings>(); //mxd
this.scriptlumpsettings = new Dictionary<string, ScriptDocumentSettings>(); //mxd
// Read map configuration
this.mapconfig.Root = cfg.ReadSetting("maps." + mapname, new Hashtable());
@ -243,11 +249,11 @@ namespace CodeImp.DoomBuilder.Map
IDictionary reslist = this.mapconfig.ReadSetting("resources", new Hashtable());
foreach(DictionaryEntry mp in reslist)
{
// Item is a structure?
if(mp.Value is IDictionary)
{
// Item is a structure?
IDictionary resinfo = mp.Value as IDictionary;
if (resinfo != null)
{
// Create resource
IDictionary resinfo = (IDictionary)mp.Value;
DataLocation res = new DataLocation();
// Copy information from Configuration to ResourceLocation
@ -261,25 +267,48 @@ namespace CodeImp.DoomBuilder.Map
}
}
// Scripts
IDictionary scplist = this.mapconfig.ReadSetting("scripts", new Hashtable());
foreach(DictionaryEntry mp in scplist)
scriptfiles.Add(mp.Value.ToString());
}
//mxd. Script files settings
IDictionary sflist = this.mapconfig.ReadSetting("scriptfiles", new Hashtable());
foreach (DictionaryEntry mp in sflist)
{
// Item is a structure?
IDictionary scfinfo = mp.Value as IDictionary;
if (scfinfo != null)
{
ScriptDocumentSettings settings = ReadScriptDocumentSettings(scfinfo);
if (!string.IsNullOrEmpty(settings.Filename)) scriptfilesettings.Add(settings.Filename, settings);
}
}
~MapOptions()
{
// Clean up
this.resources = null;
this.scriptfiles = null;
}
//mxd. Script lumps settings
IDictionary sllist = this.mapconfig.ReadSetting("scriptlumps", new Hashtable());
foreach (DictionaryEntry mp in sllist)
{
// Item is a structure?
IDictionary sclinfo = mp.Value as IDictionary;
if (sclinfo != null)
{
ScriptDocumentSettings settings = ReadScriptDocumentSettings(sclinfo);
if (!string.IsNullOrEmpty(settings.Filename)) scriptlumpsettings.Add(settings.Filename, settings);
}
}
}
#endregion
//mxd. Is that really needed?..
~MapOptions()
{
// Clean up
this.resources = null;
this.scriptfilesettings = null; //mxd
this.scriptlumpsettings = null; //mxd
}
#region ================== Methods
#endregion
// This makes the path prefix for the given assembly
private static string GetPluginPathPrefix(Assembly asm)
#region ================== Methods
// This makes the path prefix for the given assembly
private static string GetPluginPathPrefix(Assembly asm)
{
Plugin p = General.Plugins.FindPluginByAssembly(asm);
return "plugins." + p.Name.ToLowerInvariant() + ".";
@ -375,13 +404,19 @@ namespace CodeImp.DoomBuilder.Map
// Write grid settings
General.Map.Grid.WriteToConfig(mapconfig, "grid");
// Write scripts to config
mapconfig.DeleteSetting("scripts");
for(int i = 0; i < scriptfiles.Count; i++)
mapconfig.WriteSetting("scripts." + "file" + i.ToString(CultureInfo.InvariantCulture), scriptfiles[i]);
//mxd. Write script files settings to config
mapconfig.DeleteSetting("scriptfiles");
foreach (ScriptDocumentSettings settings in scriptfilesettings.Values)
WriteScriptDocumentSettings(mapconfig, "scriptfiles.file", settings);
// Load the file or make a new file
if(File.Exists(settingsfile))
//mxd. Write script lumps settings to config
mapconfig.DeleteSetting("scriptlumps");
foreach (ScriptDocumentSettings settings in scriptlumpsettings.Values)
WriteScriptDocumentSettings(mapconfig, "scriptlumps.lump", settings);
// Load the file or make a new file
if (File.Exists(settingsfile))
wadcfg = new Configuration(settingsfile, true);
else
wadcfg = new Configuration(true);
@ -398,8 +433,88 @@ namespace CodeImp.DoomBuilder.Map
wadcfg.SaveConfiguration(settingsfile);
}
// This adds a resource location and returns the index where the item was added
internal int AddResource(DataLocation res)
//mxd
private static ScriptDocumentSettings ReadScriptDocumentSettings(IDictionary scfinfo)
{
ScriptDocumentSettings settings = new ScriptDocumentSettings { FoldLevels = new Dictionary<int, HashSet<int>>() };
// Copy information from Configuration to ScriptDocumentSaveSettings
if (scfinfo.Contains("filename") && (scfinfo["filename"] is string)) settings.Filename = (string)scfinfo["filename"];
if (scfinfo.Contains("hash") && (scfinfo["hash"] is long)) settings.Hash = (long)scfinfo["hash"];
if (scfinfo.Contains("caretposition") && (scfinfo["caretposition"] is int)) settings.CaretPosition = (int)scfinfo["caretposition"];
if (scfinfo.Contains("firstvisibleline") && (scfinfo["firstvisibleline"] is int)) settings.FirstVisibleLine = (int)scfinfo["firstvisibleline"];
if (scfinfo.Contains("activetab") && (scfinfo["activetab"] is bool)) settings.IsActiveTab = (bool)scfinfo["activetab"];
if (scfinfo.Contains("foldlevels") && (scfinfo["foldlevels"] is string))
{
// 1:12,13,14;2:21,43,36
string foldstr = (string)scfinfo["foldlevels"];
// Convert string to dictionary
if (!string.IsNullOrEmpty(foldstr))
{
//TODO: add all kinds of warnings?
string[] foldlevels = foldstr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string foldlevel in foldlevels)
{
// 1:12,13,14
string[] parts = foldlevel.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2) continue;
int fold;
if (!int.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out fold)) continue;
if (settings.FoldLevels.ContainsKey(fold)) continue;
string[] linenumbersstr = parts[1].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (linenumbersstr.Length == 0) continue;
HashSet<int> linenumbers = new HashSet<int>();
foreach (string linenumber in linenumbersstr)
{
int linenum;
if (int.TryParse(linenumber, NumberStyles.Integer, CultureInfo.InvariantCulture, out linenum))
linenumbers.Add(linenum);
}
if (linenumbers.Count != linenumbersstr.Length) continue;
// Add to collection
settings.FoldLevels.Add(fold, new HashSet<int>(linenumbers));
}
}
}
return settings;
}
//mxd
private static void WriteScriptDocumentSettings(Configuration mapconfig, string prefix, ScriptDocumentSettings settings)
{
// Store data
ListDictionary data = new ListDictionary();
data.Add("filename", settings.Filename);
data.Add("hash", settings.Hash);
if (settings.CaretPosition > 0) data.Add("caretposition", settings.CaretPosition);
if (settings.FirstVisibleLine > 0) data.Add("firstvisibleline", settings.FirstVisibleLine);
if (settings.IsActiveTab) data.Add("activetab", true);
// Convert dictionary to string
List<string> foldlevels = new List<string>();
foreach (KeyValuePair<int, HashSet<int>> group in settings.FoldLevels)
{
List<string> linenums = new List<string>(group.Value.Count);
foreach (int i in group.Value) linenums.Add(i.ToString());
foldlevels.Add(group.Key + ":" + string.Join(",", linenums.ToArray()));
}
// Add to collection
if (foldlevels.Count > 0) data.Add("foldlevels", string.Join(";", foldlevels.ToArray()));
// Write to config
mapconfig.WriteSetting(prefix, data);
}
// This adds a resource location and returns the index where the item was added
internal int AddResource(DataLocation res)
{
// Get a fully qualified path
res.location = Path.GetFullPath(res.location);