Script Editor:

Added: Tab text now looks differently when appropriate script was changed.
Added: Script Editor now has it's own status bar.
Added: several files can now be opened at once when using "Open File" command.
Added: ACS scripts navigator now shows script and function arguments.
Changed: when closing a tab, previous tab is selected instead of the first tab.
Changed: SCRIPTS lump can't be compiled as a library.
Changed: external acs files can only be compiled as libraries.
Changed: when an external acs file is marked as #library, it will be saved as [library name].o alongside [filename].acs.
Fixed: files opened using "Open File" command were immediately flagged as changed.
Fixed: Script Editor was unable to navigate to error location after clicking on the error description when the error was in include file.
Updated ZDoom ACC.
This commit is contained in:
MaxED 2015-11-30 14:18:42 +00:00
parent 16da2531a6
commit e8cda3c9c5
21 changed files with 646 additions and 143 deletions

View file

@ -9,7 +9,5 @@ compilers
{
interface = "AccCompiler";
program = "bcc.exe";
zcommon = "zcommon.acs";
std = "std.acs";
}
}

View file

@ -9,9 +9,5 @@ compilers
{
interface = "AccCompiler";
program = "acc.exe";
zcommon = "common.acs";
zdefs = "defs.acs";
zspecial = "specials.acs";
zwvars = "wvars.acs";
}
}

Binary file not shown.

View file

@ -9,9 +9,5 @@ compilers
{
interface = "AccCompiler";
program = "acc.exe";
zcommon = "zcommon.acs";
zdefs = "zdefs.acs";
zspecial = "zspecial.acs";
zwvars = "zwvars.acs";
}
}

View file

@ -989,6 +989,9 @@
#define PICKAF_FORCETID 1
#define PICKAF_RETURNTID 2
// magic value to set the ice translation through ACS
#define TRANSLATION_ICE 0x100007
// Actor flags
#define MF_SPECIAL 0x00000001
#define MF_SOLID 0x00000002

View file

@ -9,9 +9,5 @@ compilers
{
interface = "AccCompiler";
program = "acc.exe";
zcommon = "zcommon.acs";
zdefs = "zdefs.acs";
zspecial = "zspecial.acs";
zwvars = "zwvars.acs";
}
}

View file

@ -17,11 +17,13 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using CodeImp.DoomBuilder.Config;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using CodeImp.DoomBuilder.Data;
#endregion
@ -73,27 +75,30 @@ namespace CodeImp.DoomBuilder.Compilers
//xabis
// Copy includes from the resources into the compiler's folder, preserving relative pathing and naming
foreach(string include in General.Map.ScriptIncludes)
if(CopyIncludesToWorkingDirectory) //mxd
{
//grab the script text from the resources
MemoryStream s = General.Map.Data.LoadFile(include);
if(s != null)
foreach(string include in includes)
{
//pull the pk3 or directory sub folder out if applicable
FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));
// Grab the script text from the resources
MemoryStream s = General.Map.Data.LoadFile(include);
//do not allow files to be overwritten, either accidentally or maliciously
if(!fi.Exists)
if(s != null)
{
General.WriteLogLine("Copying script include: " + include);
// Pull the pk3 or directory sub folder out if applicable
FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));
//create the directory path as needed
if(!string.IsNullOrEmpty(fi.DirectoryName)) Directory.CreateDirectory(fi.DirectoryName);
// Do not allow files to be overwritten, either accidentally or maliciously
if(!fi.Exists)
{
General.WriteLogLine("Copying script include: " + include);
//dump the script into the target file
BinaryReader reader = new BinaryReader(s);
File.WriteAllBytes(fi.FullName, reader.ReadBytes((int)s.Length));
// Create the directory path as needed
if(!string.IsNullOrEmpty(fi.DirectoryName)) Directory.CreateDirectory(fi.DirectoryName);
// Dump the script into the target file
BinaryReader reader = new BinaryReader(s);
File.WriteAllBytes(fi.FullName, reader.ReadBytes((int)s.Length));
}
}
}
}
@ -170,11 +175,26 @@ namespace CodeImp.DoomBuilder.Compilers
err.linenumber--;
// Everything before the match is the filename
err.filename = linestr.Substring(0, match.Index);
err.filename = linestr.Substring(0, match.Index).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if(!Path.IsPathRooted(err.filename))
{
// Add working directory to filename
err.filename = Path.Combine(processinfo.WorkingDirectory, err.filename);
//mxd. If the error is in an include file, try to find it in loaded resources
if(includes.Contains(err.filename.ToLowerInvariant()))
{
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

View file

@ -40,6 +40,7 @@ namespace CodeImp.DoomBuilder.Compilers
protected string sourcefile;
protected string outputfile;
protected string inputfile;
protected HashSet<string> includes; //mxd
// Files
protected readonly DirectoryInfo tempdir;
@ -60,6 +61,8 @@ namespace CodeImp.DoomBuilder.Compilers
public string InputFile { get { return inputfile; } set { inputfile = value; } }
public string OutputFile { get { return outputfile; } set { outputfile = value; } }
public string Location { get { return tempdir.FullName; } }
public HashSet<string> Includes { get { return includes; } set { includes = value; } } //mxd
public bool CopyIncludesToWorkingDirectory; //mxd
public bool IsDisposed { get { return isdisposed; } }
public CompilerError[] Errors { get { return errors.ToArray(); } }
@ -73,6 +76,7 @@ namespace CodeImp.DoomBuilder.Compilers
// Initialize
this.info = info;
this.errors = new List<CompilerError>();
this.includes = new HashSet<string>(); //mxd
General.WriteLogLine("Creating compiler '" + info.Name + "' on interface '" + this.GetType().Name + "'...");
@ -134,15 +138,15 @@ namespace CodeImp.DoomBuilder.Compilers
// Copy files
foreach(string f in info.Files)
{
string sourcefile = Path.Combine(info.Path, f);
if (!File.Exists(sourcefile))
string srcfile = Path.Combine(info.Path, f);
if(!File.Exists(srcfile))
{
General.ErrorLogger.Add(ErrorType.Error, "The file '" + f + "' required by the '" + info.Name + "' compiler is missing. According to the compiler configuration in '" + info.FileName + "', the was expected to be found in the following path: " + info.Path);
}
else
{
string targetfile = Path.Combine(tempdir.FullName, f);
File.Copy(sourcefile, targetfile, true);
string tgtfile = Path.Combine(tempdir.FullName, f);
File.Copy(srcfile, tgtfile, true);
}
}
}

View file

@ -25,7 +25,6 @@ using System.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Compilers;
//mxd
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.GZDoom;
@ -50,6 +49,8 @@ namespace CodeImp.DoomBuilder.Controls
// The script edit control
protected readonly ScriptEditorControl editor;
protected readonly ComboBox navigator; //mxd
private bool preventchanges; //mxd
private string title; //mxd
// Derived classes must set this!
protected ScriptConfiguration config;
@ -67,13 +68,20 @@ namespace CodeImp.DoomBuilder.Controls
public virtual bool IsReconfigurable { get { return true; } }
public virtual string Filename { get { return null; } }
public ScriptEditorPanel Panel { get { return panel; } }
public bool IsChanged { get { return editor.IsChanged; } }
public new string Text { get { return title; } } //mxd
public bool IsChanged { get { return editor.IsChanged; } internal set { editor.IsChanged = value; } } //mxd. Added setter
public int SelectionStart { get { return editor.SelectionStart; } set { editor.SelectionStart = value; } }
public int SelectionEnd { get { return editor.SelectionEnd; } set { editor.SelectionEnd = value; } }
public ScriptConfiguration Config { get { return config; } }
#endregion
#region ================== Events (mxd)
public new event EventHandler OnTextChanged; //mxd
#endregion
#region ================== Constructor
// Constructor
@ -112,6 +120,7 @@ namespace CodeImp.DoomBuilder.Controls
editor.OnOpenFindAndReplace += panel.OpenFindAndReplace;
editor.OnFindNext += panel.FindNext;
editor.OnFindPrevious += panel.FindPrevious; //mxd
editor.OnTextChanged += editor_TextChanged; //mxd
}
// Disposer
@ -123,6 +132,7 @@ namespace CodeImp.DoomBuilder.Controls
editor.OnOpenFindAndReplace -= panel.OpenFindAndReplace;
editor.OnFindNext -= panel.FindNext;
editor.OnFindPrevious -= panel.FindPrevious; //mxd
editor.OnTextChanged -= editor_TextChanged; //mxd
base.Dispose(disposing);
}
@ -204,7 +214,14 @@ namespace CodeImp.DoomBuilder.Controls
// Call this to set the tab title
protected void SetTitle(string title)
{
this.Text = title;
this.title = title; //mxd
base.Text = (editor.IsChanged ? "\u25CF " + title : title); //mxd
}
//mxd
protected void UpdateTitle()
{
SetTitle(title);
}
// Perform undo
@ -391,6 +408,14 @@ namespace CodeImp.DoomBuilder.Controls
navigator.Items.Clear();
break;
}
// Put some text in the navigator (but don't actually trigger selection event)
if(navigator.Items.Count > 0)
{
preventchanges = true;
navigator.Text = navigator.Items[0].ToString();
preventchanges = false;
}
}
//mxd
@ -424,8 +449,8 @@ namespace CodeImp.DoomBuilder.Controls
navigator.Items.Clear();
AcsParserSE parser = new AcsParserSE();
if(parser.Parse(stream, "ACS"))
AcsParserSE parser = new AcsParserSE { AddArgumentsToScriptNames = true, IsMapScriptsLump = this is ScriptLumpDocumentTab };
if(parser.Parse(stream, "SCRIPTS"))
{
navigator.Items.AddRange(parser.NamedScripts.ToArray());
navigator.Items.AddRange(parser.NumberedScripts.ToArray());
@ -478,7 +503,7 @@ namespace CodeImp.DoomBuilder.Controls
//mxd
private void navigator_SelectedIndexChanged(object sender, EventArgs e)
{
if (navigator.SelectedItem is ScriptItem)
if(!preventchanges && navigator.SelectedItem is ScriptItem)
{
ScriptItem si = navigator.SelectedItem as ScriptItem;
editor.EnsureLineVisible(editor.LineFromPosition(si.CursorPosition));
@ -494,7 +519,14 @@ namespace CodeImp.DoomBuilder.Controls
//mxd
private void navigator_DropDown(object sender, EventArgs e)
{
if(editor.IsChanged) UpdateNavigator();
if(!preventchanges && editor.IsChanged) UpdateNavigator();
}
//mxd
private void editor_TextChanged(object sender, EventArgs eventArgs)
{
UpdateTitle();
if(OnTextChanged != null) OnTextChanged(this, EventArgs.Empty);
}
#endregion

View file

@ -65,6 +65,7 @@ namespace CodeImp.DoomBuilder.Controls
public event OpenFindReplaceDelegate OnOpenFindAndReplace;
public event FindNextDelegate OnFindNext;
public event FindPreviousDelegate OnFindPrevious; //mxd
public new event EventHandler OnTextChanged; //mxd
#endregion
@ -163,7 +164,10 @@ namespace CodeImp.DoomBuilder.Controls
// Events
scriptedit.ModEventMask = 0x7FFFF; // Which events to receive (see also ScriptModificationFlags)
scriptedit.Modified += scriptedit_Modified;
scriptedit.TextDeleted += scriptedit_TextChanged; //mxd
scriptedit.TextInserted += scriptedit_TextChanged; //mxd
scriptedit.UndoPerformed += scriptedit_UndoRedoPerformed; //mxd
scriptedit.RedoPerformed += scriptedit_UndoRedoPerformed; //mxd
}
#endregion
@ -752,10 +756,18 @@ namespace CodeImp.DoomBuilder.Controls
}
}
// Script modified
private void scriptedit_Modified(ScintillaControl pSender, int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev)
//mxd. Script text changed
private void scriptedit_UndoRedoPerformed(ScintillaControl pSender)
{
changed = true;
if(OnTextChanged != null) OnTextChanged(this, EventArgs.Empty);
}
//mxd. Script text changed
private void scriptedit_TextChanged(ScintillaControl pSender, int position, int length, int linesAdded)
{
changed = true;
if(OnTextChanged != null) OnTextChanged(this, EventArgs.Empty);
}
// Key pressed down

View file

@ -66,10 +66,16 @@ namespace CodeImp.DoomBuilder.Controls
this.colDescription = new System.Windows.Forms.ColumnHeader();
this.colFile = new System.Windows.Forms.ColumnHeader();
this.errorimages = new System.Windows.Forms.ImageList(this.components);
this.statusbar = new System.Windows.Forms.StatusStrip();
this.statuslabel = new System.Windows.Forms.ToolStripStatusLabel();
this.scripttype = new System.Windows.Forms.ToolStripStatusLabel();
this.statusflasher = new System.Windows.Forms.Timer(this.components);
this.statusresetter = new System.Windows.Forms.Timer(this.components);
this.toolbar.SuspendLayout();
this.splitter.Panel1.SuspendLayout();
this.splitter.Panel2.SuspendLayout();
this.splitter.SuspendLayout();
this.statusbar.SuspendLayout();
this.SuspendLayout();
//
// tabs
@ -82,7 +88,7 @@ namespace CodeImp.DoomBuilder.Controls
this.tabs.Name = "tabs";
this.tabs.Padding = new System.Drawing.Point(12, 3);
this.tabs.SelectedIndex = 0;
this.tabs.Size = new System.Drawing.Size(720, 401);
this.tabs.Size = new System.Drawing.Size(720, 379);
this.tabs.TabIndex = 0;
this.tabs.TabStop = false;
this.tabs.Selecting += new System.Windows.Forms.TabControlCancelEventHandler(this.tabs_Selecting);
@ -361,6 +367,7 @@ namespace CodeImp.DoomBuilder.Controls
//
// openfile
//
this.openfile.Multiselect = true;
this.openfile.Title = "Open Script";
//
// savefile
@ -384,8 +391,8 @@ namespace CodeImp.DoomBuilder.Controls
//
this.splitter.Panel2.Controls.Add(this.label1);
this.splitter.Panel2.Controls.Add(this.errorlist);
this.splitter.Size = new System.Drawing.Size(726, 538);
this.splitter.SplitterDistance = 412;
this.splitter.Size = new System.Drawing.Size(726, 516);
this.splitter.SplitterDistance = 390;
this.splitter.TabIndex = 2;
this.splitter.TabStop = false;
//
@ -449,12 +456,49 @@ namespace CodeImp.DoomBuilder.Controls
this.errorimages.TransparentColor = System.Drawing.Color.Transparent;
this.errorimages.Images.SetKeyName(0, "ScriptError3.png");
//
// statusbar
//
this.statusbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.statuslabel,
this.scripttype});
this.statusbar.Location = new System.Drawing.Point(0, 541);
this.statusbar.Name = "statusbar";
this.statusbar.Size = new System.Drawing.Size(726, 22);
this.statusbar.TabIndex = 3;
this.statusbar.Text = "statusStrip1";
//
// statuslabel
//
this.statuslabel.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
this.statuslabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Status0;
this.statuslabel.Margin = new System.Windows.Forms.Padding(3, 3, 0, 2);
this.statuslabel.Name = "statuslabel";
this.statuslabel.Size = new System.Drawing.Size(60, 17);
this.statuslabel.Text = "Ready.";
//
// scripttype
//
this.scripttype.Name = "scripttype";
this.scripttype.Size = new System.Drawing.Size(648, 17);
this.scripttype.Spring = true;
this.scripttype.Text = "Plain Text";
this.scripttype.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// statusflasher
//
this.statusflasher.Tick += new System.EventHandler(this.statusflasher_Tick);
//
// statusresetter
//
this.statusresetter.Tick += new System.EventHandler(this.statusresetter_Tick);
//
// ScriptEditorPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.SystemColors.Control;
this.Controls.Add(this.splitter);
this.Controls.Add(this.statusbar);
this.Controls.Add(this.toolbar);
this.Name = "ScriptEditorPanel";
this.Size = new System.Drawing.Size(726, 563);
@ -463,6 +507,8 @@ namespace CodeImp.DoomBuilder.Controls
this.splitter.Panel1.ResumeLayout(false);
this.splitter.Panel2.ResumeLayout(false);
this.splitter.ResumeLayout(false);
this.statusbar.ResumeLayout(false);
this.statusbar.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -506,5 +552,10 @@ namespace CodeImp.DoomBuilder.Controls
private System.Windows.Forms.ToolStripButton searchprev;
private System.Windows.Forms.ToolStripButton searchmatchcase;
private System.Windows.Forms.ToolStripButton searchwholeword;
private System.Windows.Forms.StatusStrip statusbar;
private System.Windows.Forms.ToolStripStatusLabel statuslabel;
private System.Windows.Forms.ToolStripStatusLabel scripttype;
private System.Windows.Forms.Timer statusflasher;
private System.Windows.Forms.Timer statusresetter;
}
}

View file

@ -19,13 +19,12 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Config;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Windows;
#endregion
@ -49,6 +48,11 @@ namespace CodeImp.DoomBuilder.Controls
// Quick search bar settings (mxd)
private static bool matchwholeword;
private static bool matchcase;
//mxd. Status update
private ScriptStatusInfo status;
private int statusflashcount;
private bool statusflashicon;
#endregion
@ -140,18 +144,8 @@ namespace CodeImp.DoomBuilder.Controls
}
//mxd. Select "Scripts" tab, because that's what user will want 99% of time
if (tabs.TabPages.Count > 0)
{
foreach (TabPage p in tabs.TabPages)
{
if (p.Text == "SCRIPTS")
{
tabs.SelectedTab = p;
break;
}
}
if (tabs.SelectedIndex == -1) tabs.SelectedIndex = 0;
}
int scriptsindex = GetTabPageIndex("SCRIPTS");
tabs.SelectedIndex = (scriptsindex == -1 ? 0 : scriptsindex);
//mxd. Apply quick search settings
searchmatchcase.Checked = matchcase;
@ -203,9 +197,7 @@ namespace CodeImp.DoomBuilder.Controls
if(!string.IsNullOrEmpty(findoptions.FindText) && (ActiveTab != null))
{
if(!ActiveTab.FindNext(findoptions))
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
}
DisplayStatus(ScriptStatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
}
else
{
@ -226,10 +218,8 @@ namespace CodeImp.DoomBuilder.Controls
{
if(!string.IsNullOrEmpty(findoptions.FindText) && (ActiveTab != null))
{
if (!ActiveTab.FindPrevious(findoptions))
{
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
}
if(!ActiveTab.FindPrevious(findoptions))
DisplayStatus(ScriptStatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
}
else
{
@ -299,9 +289,9 @@ namespace CodeImp.DoomBuilder.Controls
// Show result
if(replacements == 0)
General.MainWindow.DisplayStatus(StatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
DisplayStatus(ScriptStatusType.Warning, "Can't find any occurence of \"" + findoptions.FindText + "\".");
else
General.MainWindow.DisplayStatus(StatusType.Info, "Replaced " + replacements + " occurences of \"" + findoptions.FindText + "\" with \"" + findoptions.ReplaceWith + "\".");
DisplayStatus(ScriptStatusType.Info, "Replaced " + replacements + " occurences of \"" + findoptions.FindText + "\" with \"" + findoptions.ReplaceWith + "\".");
}
else
{
@ -446,6 +436,10 @@ namespace CodeImp.DoomBuilder.Controls
if(!saveonly)
{
//mxd. Select tab to the left of the one we are going to close
if(t == tabs.SelectedTab && tabs.SelectedIndex > 0)
tabs.SelectedIndex--;
// Close file
tabs.TabPages.Remove(t);
t.Dispose();
@ -456,12 +450,11 @@ namespace CodeImp.DoomBuilder.Controls
// This returns true when any of the implicit-save scripts are changed
public bool CheckImplicitChanges()
{
bool changes = false;
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(!t.ExplicitSave && t.IsChanged) changes = true;
if(!t.ExplicitSave && t.IsChanged) return true;
}
return changes;
return false;
}
// This forces the focus to the script editor
@ -501,7 +494,7 @@ namespace CodeImp.DoomBuilder.Controls
t = (tabs.SelectedTab as ScriptDocumentTab);
// Enable/disable buttons
buttonsave.Enabled = (t != null) && t.ExplicitSave;
buttonsave.Enabled = (t != null) && t.ExplicitSave && t.IsChanged;
buttonsaveall.Enabled = (explicitsavescripts > 0);
buttoncompile.Enabled = (t != null) && (t.Config.Compiler != null);
buttonsearch.Enabled = (t != null); //mxd
@ -526,15 +519,30 @@ namespace CodeImp.DoomBuilder.Controls
}
//mxd. Add snippets
if(t.Config.Snippets.Count > 0)
if(t.Config != null && t.Config.Snippets.Count > 0)
{
foreach(KeyValuePair<string, string[]> group in t.Config.Snippets)
buttonsnippets.DropDownItems.Add(group.Key).Click += OnInsertSnippetClick;
if(t.Config.Snippets.Count > 0) foreach(KeyValuePair<string, string[]> group in t.Config.Snippets) buttonsnippets.DropDownItems.Add(group.Key).Click += OnInsertSnippetClick;
}
// Focus to script editor
if(focuseditor) ForceFocus();
}
//mxd. Update script type description
scripttype.Text = ((t != null && t.Config != null) ? t.Config.Description : "Plain Text");
}
//mxd
private int GetTabPageIndex(string title)
{
if(tabs.TabPages.Count == 0) return -1;
for(int i = 0; i < tabs.TabPages.Count; i++)
{
if(tabs.TabPages[i].Text == title) return i;
}
return -1;
}
// This opens the given file, returns null when failed
@ -562,11 +570,11 @@ namespace CodeImp.DoomBuilder.Controls
{
//mxd
ScriptType st = t.VerifyScriptType();
if (st != ScriptType.UNKNOWN)
if(st != ScriptType.UNKNOWN)
{
foreach (ScriptConfiguration cfg in scriptconfigs)
foreach(ScriptConfiguration cfg in scriptconfigs)
{
if (cfg.ScriptType == st)
if(cfg.ScriptType == st)
{
t.ChangeScriptConfig(cfg);
break;
@ -582,6 +590,8 @@ namespace CodeImp.DoomBuilder.Controls
tabs.SelectedTab = t;
// Done
t.OnTextChanged += tabpage_OnTextChanged; //mxd
t.IsChanged = false; //mxd. Not changed yet
UpdateToolbar(true);
return t;
}
@ -619,6 +629,84 @@ namespace CodeImp.DoomBuilder.Controls
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
return t.LaunchKeywordHelp();
}
//mxd. This changes status text
private void DisplayStatus(ScriptStatusType type, string message) { DisplayStatus(new ScriptStatusInfo(type, message)); }
private void DisplayStatus(ScriptStatusInfo newstatus)
{
// Stop timers
if(!newstatus.displayed)
{
statusresetter.Stop();
statusflasher.Stop();
statusflashicon = false;
}
// Determine what to do specifically for this status type
switch(newstatus.type)
{
// Shows information without flashing the icon.
case ScriptStatusType.Ready:
case ScriptStatusType.Info:
if(!newstatus.displayed)
{
statusresetter.Interval = MainForm.INFO_RESET_DELAY;
statusresetter.Start();
}
break;
// Shows a warning, makes a warning sound and flashes a warning icon.
case ScriptStatusType.Warning:
if(!newstatus.displayed)
{
General.MessageBeep(MessageBeepType.Warning);
statusflasher.Interval = MainForm.WARNING_FLASH_INTERVAL;
statusflashcount = MainForm.WARNING_FLASH_COUNT;
statusflasher.Start();
statusresetter.Interval = MainForm.WARNING_RESET_DELAY;
statusresetter.Start();
}
break;
}
// Update status description
status = newstatus;
status.displayed = true;
statuslabel.Text = status.message;
// Update icon as well
UpdateStatusIcon();
// Refresh
statusbar.Invalidate();
this.Update();
}
// This updates the status icon
private void UpdateStatusIcon()
{
int statusflashindex = (statusflashicon ? 1 : 0);
// Status type
switch(status.type)
{
case ScriptStatusType.Ready:
case ScriptStatusType.Info:
statuslabel.Image = General.MainWindow.STATUS_IMAGES[statusflashindex, 0];
break;
case ScriptStatusType.Busy:
statuslabel.Image = General.MainWindow.STATUS_IMAGES[statusflashindex, 2];
break;
case ScriptStatusType.Warning:
statuslabel.Image = General.MainWindow.STATUS_IMAGES[statusflashindex, 3];
break;
default:
throw new NotImplementedException("Unsupported Script Status Type!");
}
}
#endregion
@ -630,6 +718,10 @@ namespace CodeImp.DoomBuilder.Controls
//mxd. Store quick search settings
matchcase = searchmatchcase.Checked;
matchwholeword = searchwholeword.Checked;
//mxd. Stop status timers
statusresetter.Stop();
statusflasher.Stop();
// Close the sub windows now
if(findreplaceform != null) findreplaceform.Dispose();
@ -651,6 +743,9 @@ namespace CodeImp.DoomBuilder.Controls
// Change script config
t.ChangeScriptConfig(scriptconfig);
//mxd. Update script type description
scripttype.Text = scriptconfig.Description;
// Done
UpdateToolbar(true);
}
@ -676,8 +771,30 @@ namespace CodeImp.DoomBuilder.Controls
// Show open file dialog
if(openfile.ShowDialog(this.ParentForm) == DialogResult.OK)
{
// TODO: Make multi-select possible
OpenFile(openfile.FileName);
//mxd. Gather already opened file names
List<string> openedfiles = new List<string>();
foreach(var page in tabs.TabPages)
{
var scriptpage = page as ScriptFileDocumentTab;
if(scriptpage != null) openedfiles.Add(scriptpage.Filename);
}
//mxd. Add new tabs
foreach(string name in openfile.FileNames)
{
if(!openedfiles.Contains(name)) OpenFile(name);
}
// Select the last new item
foreach(var page in tabs.TabPages)
{
var scriptpage = page as ScriptFileDocumentTab;
if(scriptpage != null && scriptpage.Filename == openfile.FileNames[openfile.FileNames.Length - 1])
{
tabs.SelectedTab = scriptpage;
break;
}
}
}
}
@ -772,25 +889,22 @@ namespace CodeImp.DoomBuilder.Controls
return;
}
}
else
else if(t.ExplicitSave && t.IsChanged)
{
if(t.ExplicitSave && t.IsChanged)
{
// We can only compile when the script is saved
if(!SaveScript(t)) return;
}
// We can only compile when the script is saved
if(!SaveScript(t)) return;
}
// Compile now
General.MainWindow.DisplayStatus(StatusType.Busy, "Compiling script " + t.Text + "...");
DisplayStatus(ScriptStatusType.Busy, "Compiling script \"" + t.Text + "\"...");
Cursor.Current = Cursors.WaitCursor;
t.Compile();
// Show warning
if((compilererrors != null) && (compilererrors.Count > 0))
General.MainWindow.DisplayStatus(StatusType.Warning, compilererrors.Count + " errors while compiling " + t.Text + "!");
DisplayStatus(ScriptStatusType.Warning, compilererrors.Count + " errors while compiling \"" + t.Text + "\"!");
else
General.MainWindow.DisplayStatus(StatusType.Info, "Script " + t.Text + " compiled without errors.");
DisplayStatus(ScriptStatusType.Info, "Script \"" + t.Text + "\" compiled without errors.");
Cursor.Current = Cursors.Default;
UpdateToolbar(true);
@ -854,6 +968,16 @@ namespace CodeImp.DoomBuilder.Controls
{
ForceFocus();
}
//mxd
private void tabpage_OnTextChanged(object sender, EventArgs eventArgs)
{
if(tabs.SelectedTab != null)
{
ScriptDocumentTab curtab = tabs.SelectedTab as ScriptDocumentTab;
buttonsave.Enabled = (curtab != null && curtab.ExplicitSave && curtab.IsChanged);
}
}
// User double-clicks and error in the list
private void errorlist_ItemActivate(object sender, EventArgs e)
@ -920,6 +1044,21 @@ namespace CodeImp.DoomBuilder.Controls
ActiveTab.FindPrevious(GetQuickSearchOptions());
}
//mxd. This flashes the status icon
private void statusflasher_Tick(object sender, EventArgs e)
{
statusflashicon = !statusflashicon;
UpdateStatusIcon();
statusflashcount--;
if(statusflashcount == 0) statusflasher.Stop();
}
//mxd. This resets the status to ready
private void statusresetter_Tick(object sender, EventArgs e)
{
DisplayStatus(ScriptStatusType.Ready, null);
}
#endregion
}

View file

@ -176,6 +176,15 @@
AQEGAAGAAQEGAAGAAQEGAAGAAQEGAAHAAQMGAAHgAQcGAAHwAQ8GAAL/BgAL
</value>
</data>
<metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>400, 17</value>
</metadata>
<metadata name="statusflasher.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>501, 17</value>
</metadata>
<metadata name="statusresetter.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>588, 17</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View file

@ -18,10 +18,11 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
using System.IO;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.GZDoom;
#endregion
@ -60,8 +61,7 @@ namespace CodeImp.DoomBuilder.Controls
if(config.Extensions.Length > 0) ext = "." + config.Extensions[0];
SetTitle("Untitled" + ext);
editor.ClearUndoRedo();
//mxd
navigator.Enabled = (config.ScriptType != ScriptType.UNKNOWN);
navigator.Enabled = (config.ScriptType != ScriptType.UNKNOWN); //mxd
}
#endregion
@ -71,18 +71,15 @@ namespace CodeImp.DoomBuilder.Controls
// This compiles the script file
public override void Compile()
{
//mxd. List of errors. UpdateScriptNames can return errors and also updates acs includes list
List<CompilerError> errors = (config.ScriptType == ScriptType.ACS ? General.Map.UpdateScriptNames() : new List<CompilerError>());
//mxd. Errors already?..
if(errors.Count > 0)
//mxd. ACS requires special handling...
if(config.ScriptType == ScriptType.ACS)
{
// Feed errors to panel
panel.ShowErrors(errors);
CompileACS();
return;
}
Compiler compiler;
List<CompilerError> errors = new List<CompilerError>();
try
{
@ -93,6 +90,7 @@ namespace CodeImp.DoomBuilder.Controls
{
// Fail
errors.Add(new CompilerError("Unable to initialize compiler. " + e.GetType().Name + ": " + e.Message));
panel.ShowErrors(errors); //mxd
return;
}
@ -135,6 +133,136 @@ namespace CodeImp.DoomBuilder.Controls
panel.ShowErrors(errors);
}
//mxd. ACS requires special handling...
private void CompileACS()
{
Compiler compiler;
List<CompilerError> errors = new List<CompilerError>();
string inputfile = Path.GetFileName(filepathname);
// Which compiler to use?
ScriptConfiguration scriptconfig;
if(!string.IsNullOrEmpty(General.Map.Options.ScriptCompiler))
{
// Boilderplate
if(!General.CompiledScriptConfigs.ContainsKey(General.Map.Options.ScriptCompiler))
{
General.ShowErrorMessage("Unable to compile '" + inputfile + "'. Unable to find required script compiler configuration ('" + General.Map.Options.ScriptCompiler + "').", MessageBoxButtons.OK);
return;
}
scriptconfig = General.CompiledScriptConfigs[General.Map.Options.ScriptCompiler];
}
else
{
scriptconfig = config;
}
// Initialize compiler
try
{
compiler = scriptconfig.Compiler.Create();
}
catch(Exception e)
{
// Fail
errors.Add(new CompilerError("Unable to initialize compiler. " + e.GetType().Name + ": " + e.Message));
panel.ShowErrors(errors);
return;
}
// Preprocess the file
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path) => se.Parse(General.Map.Data.LoadFile(path), path, true, true) };
using(FileStream stream = File.OpenRead(filepathname))
{
if(!parser.Parse(stream, inputfile, scriptconfig.Compiler.Files, true, false))
{
// Check for errors
if(parser.HasError)
{
errors.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
panel.ShowErrors(errors);
compiler.Dispose();
return;
}
}
}
// Only works for libraries
if(!parser.IsLibrary)
{
errors.Add(new CompilerError("External ACS files can only be compiled as libraries!", inputfile));
panel.ShowErrors(errors);
compiler.Dispose();
return;
}
// Make random output filename
string outputfile = General.MakeTempFilename(compiler.Location, "tmp");
// Run compiler
compiler.Parameters = config.Parameters;
compiler.InputFile = inputfile;
compiler.OutputFile = outputfile;
compiler.SourceFile = filepathname;
compiler.WorkingDirectory = Path.GetDirectoryName(filepathname);
compiler.Includes = parser.Includes;
compiler.CopyIncludesToWorkingDirectory = false;
if(compiler.Run())
{
// Fetch errors
foreach(CompilerError e in compiler.Errors)
{
CompilerError newerr = e;
// If the error's filename equals our temporary file,
// replace it with the original source filename
if(string.Compare(e.filename, inputfile, true) == 0)
newerr.filename = filepathname;
errors.Add(newerr);
}
// No errors and output file exists?
if(compiler.Errors.Length == 0)
{
// Output file exists?
if(!File.Exists(outputfile))
{
// Fail
compiler.Dispose();
errors.Add(new CompilerError("Output file '" + outputfile + "' doesn't exist."));
panel.ShowErrors(errors);
return;
}
// Rename and copy to source file directory
string targetfilename = Path.Combine(Path.GetDirectoryName(filepathname), parser.LibraryName + ".o");
try
{
File.Copy(outputfile, targetfilename, true);
}
catch(Exception e)
{
// Fail
compiler.Dispose();
errors.Add(new CompilerError("Unable to create library file '" + targetfilename + "'. " + e.GetType().Name + ": " + e.Message));
panel.ShowErrors(errors);
return;
}
}
}
// Dispose compiler
compiler.Dispose();
// Update script navigator
UpdateNavigator();
// Feed errors to panel
panel.ShowErrors(errors);
}
// This checks if a script error applies to this script
public override bool VerifyErrorForScript(CompilerError e)
{
@ -161,6 +289,7 @@ namespace CodeImp.DoomBuilder.Controls
// Done
editor.IsChanged = false;
UpdateTitle(); //mxd
return true;
}
@ -201,8 +330,10 @@ namespace CodeImp.DoomBuilder.Controls
// Setup
this.filepathname = filepathname;
SetTitle(Path.GetFileName(filepathname));
editor.ClearUndoRedo();
editor.IsChanged = false; //mxd. Not changed yet
SetTitle(Path.GetFileName(filepathname));
UpdateNavigator(); //mxd
return true;
}
@ -210,14 +341,12 @@ namespace CodeImp.DoomBuilder.Controls
// This changes the script configurations
public override void ChangeScriptConfig(ScriptConfiguration newconfig)
{
string ext = "";
this.config = newconfig;
editor.SetupStyles(config);
if(filepathname.Length == 0)
{
if(config.Extensions.Length > 0) ext = "." + config.Extensions[0];
string ext = (config.Extensions.Length > 0 ? "." + config.Extensions[0] : "");
SetTitle("Untitled" + ext);
}

View file

@ -44,6 +44,7 @@ namespace CodeImp.DoomBuilder.Controls
public override bool IsSaveAsRequired { get { return false; } }
public override bool IsClosable { get { return false; } }
public override bool IsReconfigurable { get { return false; } }
public override string Filename { get { return lumpname; } } //mxd
#endregion
@ -75,8 +76,9 @@ namespace CodeImp.DoomBuilder.Controls
editor.ClearUndoRedo();
UpdateNavigator(); //mxd
}
// Done
// Set title
IsChanged = false; //mxd. Not changed yet
SetTitle(ismapheader ? General.Map.Options.CurrentName : this.lumpname.ToUpper());
}
@ -115,6 +117,7 @@ namespace CodeImp.DoomBuilder.Controls
MemoryStream stream = new MemoryStream(editor.GetText());
General.Map.SetLumpData(lumpname, stream);
editor.IsChanged = false;
UpdateTitle(); //mxd
return true;
}

View file

@ -122,6 +122,7 @@ namespace CodeImp.DoomBuilder.Data
public Dictionary<string, KeyValuePair<int, int>> Reverbs { get { return reverbs; } }
public Dictionary<long, GlowingFlatData> GlowingFlats { get { return glowingflats; } }
public List<string> SoundSequences { get { return soundsequences; } }
internal List<DataReader> Containers { get { return containers; } } //mxd
public Playpal Palette { get { return palette; } }
public PreviewManager Previews { get { return previews; } }
@ -2052,11 +2053,11 @@ namespace CodeImp.DoomBuilder.Data
//mxd
internal MemoryStream LoadFile(string name)
{
//relative path?
// Relative path?
if(name.StartsWith("..\\")) name = name.Replace("..\\", "");
foreach (DataReader dr in containers)
if (dr.FileExists(name)) return dr.LoadFile(name);
foreach(DataReader dr in containers)
if(dr.FileExists(name)) return dr.LoadFile(name);
return null;
}

View file

@ -14,7 +14,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
private readonly HashSet<string> parsedlumps;
private readonly HashSet<string> includes;
private List<string> includestoskip;
private List<string> includestoskip;
private string libraryname;
private readonly List<ScriptItem> namedscripts;
private readonly List<ScriptItem> numberedscripts;
@ -23,7 +24,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
internal List<ScriptItem> NamedScripts { get { return namedscripts; } }
internal List<ScriptItem> NumberedScripts { get { return numberedscripts; } }
internal List<ScriptItem> Functions { get { return functions; } }
internal IEnumerable<string> Includes { get { return includes; } }
internal HashSet<string> Includes { get { return includes; } }
internal bool IsLibrary { get { return !string.IsNullOrEmpty(libraryname); } }
internal string LibraryName { get { return libraryname; } }
internal bool AddArgumentsToScriptNames;
internal bool IsMapScriptsLump;
internal AcsParserSE()
{
@ -99,6 +105,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
List<string> argnames = new List<string>();
foreach(KeyValuePair<string, string> group in args) argnames.Add(group.Value);
// Make full name
if(AddArgumentsToScriptNames) scriptname += " " + GetArgumentNames(args);
// Add to collection
namedscripts.Add(new ScriptItem(scriptname, argnames, startpos, isinclude));
}
@ -123,7 +132,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!string.IsNullOrEmpty(token))
{
int commentstart = token.IndexOf("//");
int commentstart = token.IndexOf("//", System.StringComparison.Ordinal);
if(commentstart != -1) //found comment
{
commentstart += 2;
@ -132,11 +141,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
bool customname = (name.Length > 0);
name = (customname ? name + " [" + n + "]" : "Script " + n);
name = (customname ? name + " [Script " + n + "]" : "Script " + n);
List<string> argnames = new List<string>();
foreach(KeyValuePair<string, string> group in args) argnames.Add(group.Value);
// Make full name
if(AddArgumentsToScriptNames) name += " " + GetArgumentNames(args);
// Add to collection
numberedscripts.Add(new ScriptItem(n, name, argnames, startpos, isinclude, customname));
}
@ -157,11 +169,33 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
List<string> argnames = new List<string>();
foreach(KeyValuePair<string, string> group in args) argnames.Add(group.Value);
// Make full name
if(AddArgumentsToScriptNames) funcname += GetArgumentNames(args);
// Add to collection
functions.Add(new ScriptItem(funcname, argnames, startpos, isinclude));
}
break;
case "#library":
if(IsMapScriptsLump)
{
ReportError("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": SCRIPTS lump can not be compiled as library!");
return false;
}
SkipWhitespace(true);
libraryname = ReadToken();
if(string.IsNullOrEmpty(libraryname) || !libraryname.StartsWith("\"") || !libraryname.EndsWith("\""))
{
ReportError("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": invalid #library directive!");
return false;
}
libraryname = StripTokenQuotes(libraryname);
break;
default:
if(processincludes && (token == "#include" || token == "#import"))
{
@ -212,7 +246,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(IsSpecialToken(argtype)) break;
if(argtype.ToUpperInvariant() == "VOID")
{
argnames.Add(new KeyValuePair<string, string>("(void)", string.Empty));
argnames.Add(new KeyValuePair<string, string>("void", string.Empty));
break;
}
@ -227,5 +261,20 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
return argnames;
}
private static string GetArgumentNames(List<KeyValuePair<string, string>> args)
{
// Make full name
if(args.Count > 0)
{
List<string> argdescs = new List<string>(args.Count);
foreach(KeyValuePair<string, string> group in args)
argdescs.Add((group.Key + " " + group.Value).TrimEnd());
return "(" + string.Join(", ", argdescs.ToArray()) + ")";
}
return "(void)";
}
}
}

View file

@ -1054,7 +1054,6 @@ namespace CodeImp.DoomBuilder
// This builds the nodes in the temproary file with the given configuration name
private bool BuildNodes(string nodebuildername, bool failaswarning)
{
string tempfile2;
bool lumpscomplete = false;
WAD buildwad;
@ -1102,6 +1101,7 @@ namespace CodeImp.DoomBuilder
buildwad.Dispose();
// Does the nodebuilder require an output file?
string tempfile2;
if(nodebuilder.HasSpecialOutputFile)
{
// Make a temporary output file for the nodebuilder
@ -1146,7 +1146,7 @@ namespace CodeImp.DoomBuilder
{
//mxd. collect errors
string compilererrors = "";
foreach (CompilerError e in compiler.Errors)
foreach(CompilerError e in compiler.Errors)
compilererrors += Environment.NewLine + e.description;
// Nodebuilder did not build the lumps!
@ -1232,7 +1232,7 @@ namespace CodeImp.DoomBuilder
}
// This writes a copy of the data to a lump in the temp file
public void SetLumpData(string lumpname, MemoryStream data)
public void SetLumpData(string lumpname, MemoryStream lumpdata)
{
int insertindex = tempwad.Lumps.Count;
@ -1245,9 +1245,12 @@ namespace CodeImp.DoomBuilder
}
// Insert new lump
Lump l = tempwad.Insert(lumpname, insertindex, (int)data.Length);
Lump l = tempwad.Insert(lumpname, insertindex, (int)lumpdata.Length);
l.Stream.Seek(0, SeekOrigin.Begin);
data.WriteTo(l.Stream);
lumpdata.WriteTo(l.Stream);
//mxd. Mark the map as changed (will also update the title)
IsChanged = true;
}
// This checks if the specified lump exists in the temp file
@ -1682,7 +1685,7 @@ namespace CodeImp.DoomBuilder
}
// This checks if the scripts are changed
internal bool CheckScriptChanged()
private bool CheckScriptChanged()
{
if(scriptwindow != null)
{
@ -1797,6 +1800,14 @@ namespace CodeImp.DoomBuilder
compiler.OutputFile = Path.GetFileName(outputfile);
compiler.SourceFile = sourcefile;
compiler.WorkingDirectory = Path.GetDirectoryName(inputfile);
//mxd
if(scriptconfig.ScriptType == ScriptType.ACS)
{
compiler.Includes = General.Map.ScriptIncludes;
compiler.CopyIncludesToWorkingDirectory = true;
}
if(compiler.Run())
{
// Process errors
@ -1871,7 +1882,8 @@ namespace CodeImp.DoomBuilder
foreach(CompilerError error in compilererrors)
{
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + error.filename
+ "', line " + error.linenumber + ". " + error.description + ".");
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "', line " + error.linenumber : "'")
+ ". " + error.description + ".");
}
}
@ -1914,7 +1926,7 @@ namespace CodeImp.DoomBuilder
if(stream != null && stream.Length > 0 && scriptconfig != null && scriptconfig.Compiler != null)
{
// Get script names
AcsParserSE parser = new AcsParserSE { OnInclude = UpdateScriptsFromLocation };
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path) => se.Parse(General.Map.Data.LoadFile(path), path, true, true) };
if(parser.Parse(stream, "SCRIPTS", scriptconfig.Compiler.Files, true, false))
{
// Add them to arrays
@ -1960,12 +1972,6 @@ namespace CodeImp.DoomBuilder
return compilererrors;
}
//mxd
private static void UpdateScriptsFromLocation(AcsParserSE parser, string path)
{
parser.Parse(General.Map.Data.LoadFile(path), path, true, true);
}
#endregion
#region ================== Methods

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 240 KiB

View file

@ -55,15 +55,15 @@ namespace CodeImp.DoomBuilder.Windows
private const int MAX_RECENT_FILES_PIXELS = 250;
// Status bar
private const int WARNING_FLASH_COUNT = 10;
private const int WARNING_FLASH_INTERVAL = 100;
private const int WARNING_RESET_DELAY = 5000;
private const int INFO_RESET_DELAY = 5000;
private const int ACTION_FLASH_COUNT = 3;
private const int ACTION_FLASH_INTERVAL = 50;
private const int ACTION_RESET_DELAY = 5000;
internal const int WARNING_FLASH_COUNT = 10;
internal const int WARNING_FLASH_INTERVAL = 100;
internal const int WARNING_RESET_DELAY = 5000;
internal const int INFO_RESET_DELAY = 5000;
internal const int ACTION_FLASH_COUNT = 3;
internal const int ACTION_FLASH_INTERVAL = 50;
internal const int ACTION_RESET_DELAY = 5000;
private readonly Image[,] STATUS_IMAGES = new Image[,]
internal readonly Image[,] STATUS_IMAGES = new Image[,]
{
// Normal versions
{
@ -424,7 +424,7 @@ namespace CodeImp.DoomBuilder.Windows
if(General.Map != null)
{
// Show map name and filename in caption
this.Text = General.Map.FileTitle + (mapchanged ? "* (" : " (") + General.Map.Options.CurrentName + ") - " + Application.ProductName;
this.Text = (mapchanged ? "\u25CF " : "") + General.Map.FileTitle + " (" + General.Map.Options.CurrentName + ") - " + Application.ProductName;
}
else
{

View file

@ -16,6 +16,8 @@
#region ================== Namespaces
using System;
#endregion
namespace CodeImp.DoomBuilder.Windows
@ -99,4 +101,61 @@ namespace CodeImp.DoomBuilder.Windows
/// </summary>
Warning
}
//mxd. StatusInfo used by Script Editor
public struct ScriptStatusInfo
{
public const string READY_TEXT = "Ready.";
public readonly ScriptStatusType type;
public readonly string message;
internal bool displayed;
internal ScriptStatusInfo(ScriptStatusType type, string message)
{
this.type = type;
switch(type)
{
case ScriptStatusType.Ready:
this.message = READY_TEXT;
break;
case ScriptStatusType.Info:
case ScriptStatusType.Warning:
case ScriptStatusType.Busy:
this.message = message;
break;
default:
throw new NotImplementedException("Unsupported Script Status Type!");
}
this.displayed = false;
}
}
//mxd. StatusType used by Script Editor
public enum ScriptStatusType
{
/// <summary>
/// When no particular information is to be displayed.
/// </summary>
Ready,
/// <summary>
/// Shows information without flashing the icon.
/// </summary>
Info,
/// <summary>
/// Shows information with the busy icon.
/// </summary>
Busy,
/// <summary>
/// Shows a warning, makes a warning sound and flashes a warning icon.
/// </summary>
Warning
}
}