Added Command Tooltips feature to Script Editor

Misc bug fixes
This commit is contained in:
AdAstra-LD
2021-08-10 14:20:10 +02:00
parent 91d1250966
commit fb68aff727
9 changed files with 490 additions and 108 deletions

View File

@@ -171,6 +171,12 @@
<Compile Include="RomInfo.cs" />
<Compile Include="ROMFiles\ScriptCommand.cs" />
<Compile Include="ScintillaUtils\HotKeyManager.cs" />
<Compile Include="ScintillaUtils\ScriptTooltip.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ScintillaUtils\ScriptTooltip.Designer.cs">
<DependentUpon>ScriptTooltip.cs</DependentUpon>
</Compile>
<Compile Include="ScintillaUtils\SearchManager.cs" />
<Compile Include="SpawnEditor.cs">
<SubType>Form</SubType>
@@ -290,6 +296,9 @@
<EmbeddedResource Include="CameraView.resx">
<DependentUpon>CameraView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ScintillaUtils\ScriptTooltip.resx">
<DependentUpon>ScriptTooltip.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SpawnEditor.resx">
<DependentUpon>SpawnEditor.cs</DependentUpon>
</EmbeddedResource>

View File

@@ -1,4 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DSPRE {
public static class Extensions {
@@ -9,15 +13,34 @@ namespace DSPRE {
return str.IndexOfNumber() > 0;
}
public static Dictionary<string, ushort> Reverse (this Dictionary<ushort, string> source) {
var dictionary = new Dictionary<string, ushort>();
var dictionary = new Dictionary<string, ushort>(StringComparer.InvariantCultureIgnoreCase);
foreach (var entry in source) {
string newKey = entry.Value.ToLower();
string newKey = entry.Value;
if (!dictionary.ContainsKey(newKey)) {
dictionary.Add(newKey, entry.Key);
}
}
return dictionary;
}
public static void FadeIn(this Form o, int framelength = 16, int frames = 10) {
//Object is not fully invisible. Fade it in
while (o != null && !o.IsDisposed && o.Opacity < 1.0) {
Thread.Sleep(framelength);
o.Opacity += (1.0 / frames);
}
o.Opacity = 1; //make fully visible
}
public static void FadeOut(this Form o, int framelength = 16, int frames = 10) {
//Object is fully visible. Fade it out
while (o != null && o.Opacity > 0.0) {
Thread.Sleep(framelength);
o.Opacity -= (1.0 / frames);
}
o.Opacity = 0; //make fully invisible
Console.WriteLine("Fadeout done");
}
//public static Dictionary<TValue, TKey> Reverse<TKey, TValue>(this IDictionary<TKey, TValue> source) {
// var dictionary = new Dictionary<TValue, TKey>();
// foreach (var entry in source) {

View File

@@ -21,6 +21,9 @@ using Microsoft.WindowsAPICodePack.Dialogs;
using System.Collections.Specialized;
using ScintillaNET;
using ScintillaNET.Utils;
using DSPRE.ScintillaUtils;
using System.Threading;
using System.Globalization;
namespace DSPRE {
public partial class MainProgram : Form {
@@ -5646,12 +5649,15 @@ namespace DSPRE {
#region Script Editor
#region Variables
private static Mutex tooltipMutex = new Mutex();
private ScriptTooltip customTooltip;
private bool scriptsDirty = false;
private bool functionsDirty = false;
private bool actionsDirty = false;
private string cmdKeyWords = "";
private string comparisonOperatorsKeyWords = "";
private string secondaryKeyWords = "";
private ScriptFile currentScriptFile;
#endregion
#region Helper Methods
@@ -5685,14 +5691,15 @@ namespace DSPRE {
}
private void SetupScriptEditorTextAreas() {
//PREPARE SCRIPT EDITOR KEYWORDS
string scriptCmds = String.Join(" ", ScriptCommandNamesDict.Values);
cmdKeyWords = scriptCmds + " " + scriptCmds.ToLower() + " " + scriptCmds.ToUpper();
cmdKeyWords = String.Join(" ", ScriptCommandNamesDict.Values) +
" " + String.Join(" ", ScriptDatabase.movementsDictIDName.Values);
cmdKeyWords += " " + cmdKeyWords.ToUpper() + " " + cmdKeyWords.ToLower();
secondaryKeyWords = String.Join(" ", RomInfo.ScriptComparisonOperatorsDict.Values) +
" " + String.Join(" ", ScriptDatabase.specialOverworlds.Values) +
" " + ScriptFile.ScriptKW + " " + ScriptFile.FunctionKW + " " + ScriptFile.ActionKW + " " + "Overworld";
secondaryKeyWords += " " + secondaryKeyWords.ToUpper() + " " + secondaryKeyWords.ToLower();
string actionCmds = String.Join(" ", ScriptDatabase.movementsDictIDName.Values);
cmdKeyWords += " " + actionCmds + " " + actionCmds.ToLower() + " " + actionCmds.ToUpper();
string cmdOps = String.Join(" ", RomInfo.ScriptComparisonOperatorsDict.Values);
comparisonOperatorsKeyWords = cmdOps + " " + cmdOps.ToLower() + " " + cmdOps.ToUpper();
// CREATE CONTROLS
ScriptTextArea = new ScintillaNET.Scintilla();
@@ -5711,35 +5718,14 @@ namespace DSPRE {
currentSearchBox = panelSearchScriptTextBox;
// BASIC CONFIG
ScriptTextArea.Dock = DockStyle.Fill;
ScriptTextArea.TextChanged += (this.OnTextChangedScript);
FunctionTextArea.Dock = DockStyle.Fill;
FunctionTextArea.TextChanged += (this.OnTextChangedFunction);
ActionTextArea.Dock = DockStyle.Fill;
ActionTextArea.TextChanged += (this.OnTextChangedAction);
// INITIAL VIEW CONFIG
ScriptTextArea.WrapMode = ScintillaNET.WrapMode.None;
ScriptTextArea.IndentationGuides = IndentView.LookBoth;
ScriptTextArea.CaretPeriod = 500;
ScriptTextArea.CaretForeColor = Color.White;
FunctionTextArea.WrapMode = ScintillaNET.WrapMode.None;
FunctionTextArea.IndentationGuides = IndentView.LookBoth;
FunctionTextArea.CaretPeriod = 500;
FunctionTextArea.CaretForeColor = Color.White;
ActionTextArea.WrapMode = ScintillaNET.WrapMode.None;
ActionTextArea.IndentationGuides = IndentView.LookBoth;
ActionTextArea.CaretPeriod = 500;
ActionTextArea.CaretForeColor = Color.White;
// STYLING
ScriptTextArea.SetSelectionBackColor(true, Color.FromArgb(0x114D9C));
FunctionTextArea.SetSelectionBackColor(true, Color.FromArgb(0x114D9C));
ActionTextArea.SetSelectionBackColor(true, Color.FromArgb(0x114D9C));
InitialViewConfig(ScriptTextArea);
InitialViewConfig(FunctionTextArea);
InitialViewConfig(ActionTextArea);
InitSyntaxColoring(ScriptTextArea);
InitSyntaxColoring(FunctionTextArea);
@@ -5765,21 +5751,85 @@ namespace DSPRE {
InitHotkeys(FunctionTextArea, functionSearchManager);
InitHotkeys(ActionTextArea, actionSearchManager);
// INIT DIRTYBIT LOGIC
ScriptTextArea.TextChanged += (sender, e) => {
scriptsDirty = true;
scriptsTabPage.Text = ScriptFile.ScriptKW + "s" + "*";
};
FunctionTextArea.TextChanged += (sender, e) => {
functionsDirty = true;
functionsTabPage.Text = ScriptFile.FunctionKW + "s" + "*";
};
ActionTextArea.TextChanged += (sender, e) => {
actionsDirty = true;
actionsTabPage.Text = ScriptFile.ActionKW + "s" + "*";
};
// INIT TOOLTIPS DWELLING
ScriptTextArea.MouseDwellTime = 300;
ScriptTextArea.DwellEnd += TextArea_DwellEnd;
ScriptTextArea.DwellStart += TextArea_DwellStart;
scriptEditorWordWrapCheckbox_CheckedChanged(null, null);
FunctionTextArea.MouseDwellTime = 300;
FunctionTextArea.DwellEnd += TextArea_DwellEnd;
FunctionTextArea.DwellStart += TextArea_DwellStart;
}
private void TextArea_DwellStart(object sender, DwellEventArgs e) {
TextArea_DwellEnd(sender, e);
Scintilla ctr = sender as Scintilla;
string hoveredWord = ctr.GetWordFromPosition(e.Position);
ushort cmdID;
string commandName = "";
if (RomInfo.ScriptCommandNamesReverseDict.TryGetValue(hoveredWord, out cmdID)) {
commandName = hoveredWord;
} else {
if (!ushort.TryParse(hoveredWord, NumberStyles.HexNumber, new CultureInfo("en-US"), out cmdID)) {
return;
}
}
string tip = "";
tooltipMutex.WaitOne();
tip += cmdID.ToString("X4") + ": " + commandName + "(";
byte[] parameters = ScriptCommandParametersDict[cmdID];
for (int i = 0; i < parameters.Length; i++) {
if (parameters[i] == 0) {
break;
} else if (parameters[i] == 1) {
tip += "byte";
} else {
tip += "uint" + 8 * parameters[i];
}
if (i != parameters.Length - 1) {
tip += ", ";
}
}
tip += ")";
tip += Environment.NewLine + "Command descriptions aren't available yet.";
Point globalCtrCoords = ctr.PointToScreen(ctr.Location);
Point incrementedCoords = new Point(globalCtrCoords.X + e.X, globalCtrCoords.Y + e.Y);
customTooltip = new ScriptTooltip(cmdKeyWords, tip);
customTooltip.Visible = false;
customTooltip.Show();
int newy = incrementedCoords.Y - customTooltip.Size.Height - 5;
customTooltip.Location = new Point(incrementedCoords.X, newy);
customTooltip.BringToFront();
customTooltip.Visible = true;
Thread t = new Thread(() => {
customTooltip.Invoke((MethodInvoker)delegate {
customTooltip.ctrl.Visible = true;
customTooltip.FadeIn();
customTooltip.WriteText(5);
});
});
t.Start();
tooltipMutex.ReleaseMutex();
}
private void TextArea_DwellEnd(object sender, DwellEventArgs e) {
if (customTooltip != null && !customTooltip.IsDisposed) {
tooltipMutex.WaitOne();
Thread t = new Thread(() => {
customTooltip.Invoke((MethodInvoker)delegate {
customTooltip.FadeOut();
customTooltip.Close();
customTooltip.Dispose();
});
});
t.Start();
tooltipMutex.ReleaseMutex();
}
}
private void InitNumberMargin(Scintilla textArea, EventHandler<MarginClickEventArgs> textArea_MarginClick) {
@@ -5828,26 +5878,32 @@ namespace DSPRE {
textArea.Styles[Style.Python.Identifier].ForeColor = Color.FromArgb(0xD0DAE2);
textArea.Styles[Style.Python.CommentLine].ForeColor = Color.FromArgb(0x40BF57);
textArea.Styles[Style.Python.Number].ForeColor = Color.FromArgb(0xFFFF00);
textArea.Styles[Style.Python.String].ForeColor = Color.FromArgb(0xFFFF00);
textArea.Styles[Style.Python.String].ForeColor = Color.FromArgb(0xFF00FF);
textArea.Styles[Style.Python.Character].ForeColor = Color.FromArgb(0xE95454);
textArea.Styles[Style.Python.Operator].ForeColor = Color.FromArgb(0xE0E0E0);
textArea.Styles[Style.Python.Operator].ForeColor = Color.FromArgb(0xFFFF00);
textArea.Styles[Style.Python.Word].ForeColor = Color.FromArgb(0x48A8EE);
textArea.Styles[Style.Python.Word2].ForeColor = Color.FromArgb(0xF98906);
textArea.Lexer = Lexer.Python;
textArea.SetKeywords(0, cmdKeyWords);
textArea.SetKeywords(1, comparisonOperatorsKeyWords + " Function" + " Script" + " Action");
textArea.SetKeywords(1, secondaryKeyWords);
}
private void OnTextChangedScript(object sender, EventArgs e) {
ScriptTextArea.Margins[NUMBER_MARGIN].Width = ScriptTextArea.Lines.Count.ToString().Length * 13;
scriptsDirty = true;
scriptsTabPage.Text = ScriptFile.ScriptKW + "s" + "*";
}
private void OnTextChangedFunction(object sender, EventArgs e) {
FunctionTextArea.Margins[NUMBER_MARGIN].Width = FunctionTextArea.Lines.Count.ToString().Length * 13;
functionsDirty = true;
functionsTabPage.Text = ScriptFile.FunctionKW + "s" + "*";
}
private void OnTextChangedAction(object sender, EventArgs e) {
ActionTextArea.Margins[NUMBER_MARGIN].Width = ActionTextArea.Lines.Count.ToString().Length * 13;
actionsDirty = true;
actionsTabPage.Text = ScriptFile.ActionKW + "s" + "*";
}
@@ -5885,6 +5941,16 @@ namespace DSPRE {
private const bool CODEFOLDING_CIRCULAR = true;
private void InitialViewConfig(Scintilla textArea) {
textArea.Dock = DockStyle.Fill;
textArea.WrapMode = ScintillaNET.WrapMode.None;
textArea.IndentationGuides = IndentView.LookBoth;
textArea.CaretPeriod = 500;
textArea.CaretForeColor = Color.White;
textArea.SetSelectionBackColor(true, Color.FromArgb(0x114D9C));
textArea.WrapIndentMode = WrapIndentMode.Same;
}
private void InitBookmarkMargin(Scintilla textArea) {
//TextArea.SetFoldMarginColor(true, IntToColor(BACK_COLOR));

View File

@@ -52,34 +52,38 @@ namespace DSPRE.ROMFiles {
switch (id) {
case 0x16: // Jump
case 0x1A: // Call
name += " " + "Function_#" + (BitConverter.ToInt32(parametersList[0], 0)).ToString("D");
name += " " + FunctionKW + "#" + BitConverter.ToInt32(parametersList[0], 0).ToString("D");
break;
case 0x17: // JumpIfObjID
case 0x18: // JumpIfBgID
case 0x18: // JumpIfEventID
byte owid = parametersList[0][0];
name += " " + ScriptFile.OverworldFlexDecode(owid);
name += " " + FunctionKW + "#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
break;
case 0x19: // JumpIfPlayerDir
byte param = parametersList[0][0];
name += " " + param.ToString("X") + " " + "Function_#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
name += " " + param.ToString("X") + " " + FunctionKW + "#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
break;
case 0x1C: // CondJump
case 0x1D: // CondCall
case 0x1C: // JumpIf
case 0x1D: // CallIf
byte opcode = parametersList[0][0];
name += " " + RomInfo.ScriptComparisonOperatorsDict[opcode] + " " + "Function_#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
name += " " + RomInfo.ScriptComparisonOperatorsDict[opcode] + " " + FunctionKW + "#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
break;
case 0x5E: // Movement
ushort flexID = BitConverter.ToUInt16(parametersList[0], 0);
name += ScriptFile.OverworldFlexDecode(flexID);
name += " " + "Action_#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
name += " " + ScriptFile.OverworldFlexDecode(flexID);
name += " " + ActionKW + "#" + BitConverter.ToInt32(parametersList[1], 0).ToString("D");
break;
case 0x6A: // CheckOverworldPosition
flexID = BitConverter.ToUInt16(parametersList[0], 0);
name += ScriptFile.OverworldFlexDecode(flexID) + " " + "0x" + BitConverter.ToInt16(parametersList[1], 0).ToString("X") + " " + "0x" + BitConverter.ToInt16(parametersList[2], 0).ToString("X");
name += " " + ScriptFile.OverworldFlexDecode(flexID) + " " + "0x" + BitConverter.ToInt16(parametersList[1], 0).ToString("X") + " " + "0x" + BitConverter.ToInt16(parametersList[2], 0).ToString("X");
break;
case 0x62: // Lock
case 0x63: // Release
case 0x64: // AddOW
case 0x65: // RemoveOW
flexID = BitConverter.ToUInt16(parametersList[0], 0);
name += ScriptFile.OverworldFlexDecode(flexID);
name += " " + ScriptFile.OverworldFlexDecode(flexID);
break;
default:
for (int i = 0; i < parametersList.Count; i++) {
@@ -140,7 +144,7 @@ namespace DSPRE.ROMFiles {
if (RomInfo.ScriptComparisonOperatorsReverseDict.TryGetValue(nameParts[i + 1].ToLower(), out cmdID)) {
cmdParams.Add(new byte[] { (byte)cmdID });
} else { //Not a comparison
int indexOfSpecialCharacter = nameParts[i + 1].IndexOfAny(new char[] { 'x', 'X', '#' });
int indexOfSpecialCharacter = nameParts[i + 1].IndexOfAny(new char[] { 'x', 'X', '#', '.' });
/* If number is preceded by 0x parse it as hex, otherwise as decimal */
NumberStyles style;
@@ -158,25 +162,24 @@ namespace DSPRE.ROMFiles {
cmdParams.Add(new byte[] { Byte.Parse(nameParts[i + 1], style) });
break;
case 2:
if (nameParts[i + 1].Equals("Player", StringComparison.InvariantCultureIgnoreCase)) {
cmdParams.Add(BitConverter.GetBytes((ushort)255));
} else if (nameParts[i + 1].Equals("Following", StringComparison.InvariantCultureIgnoreCase)) {
cmdParams.Add(BitConverter.GetBytes((ushort)253));
} else if (nameParts[i + 1].Equals("Camera", StringComparison.InvariantCultureIgnoreCase)) {
cmdParams.Add(BitConverter.GetBytes((ushort)241));
} else {
cmdParams.Add(BitConverter.GetBytes(ushort.Parse(nameParts[i + 1], style)));
ushort result;
if (!ushort.TryParse(nameParts[i + 1], style, new CultureInfo("en-US"), result: out result)) {
result = ScriptDatabase.specialOverworlds.First(x => x.Value.Equals(nameParts[i + 1])).Key;
}
cmdParams.Add(BitConverter.GetBytes(result));
break;
case 4:
cmdParams.Add(BitConverter.GetBytes(Int32.Parse(nameParts[i + 1], style)));
break;
}
} catch (InvalidOperationException) {
MessageBox.Show("Argument " + '"' + nameParts[i + 1] + '"' + " at line " + lineNumber + " is not " + "a valid " + "Overworld number or identifier.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
id = null;
} catch (FormatException) {
MessageBox.Show("Argument " + '"' + nameParts[i + 1] + '"' + " at line " + lineNumber + " is not a valid " + style , "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("Argument " + '"' + nameParts[i + 1] + '"' + " at line " + lineNumber + " is not " + "a valid " + style, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
id = null;
} catch (OverflowException) {
MessageBox.Show("Argument " + '"' + nameParts[i + 1] + '"' + " at line " + lineNumber + " is not in the range [" + 0 + ", " + (Math.Pow(2, 8 * parametersSizeArr[i]) - 1) + "].", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("Argument " + '"' + nameParts[i + 1] + '"' + " at line " + lineNumber + " is not " + "in the range [" + 0 + ", " + (Math.Pow(2, 8 * parametersSizeArr[i]) - 1) + "].", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
id = null;
}
}

View File

@@ -193,11 +193,11 @@ namespace DSPRE.ROMFiles {
case 0x17: //JumpIfObjID
case 0x18: //JumpIfBgID
case 0x19: //JumpIfPlayerDir
case 0x1C: //CondJump
case 0x1D: //CondCall
//in the case of CondJump and CondCall, the first param is a comparisonOperator
//for CondJumpPlayerDir it's a directionID
//for CondJumpObjID, it's an EventID
case 0x1C: //JumpIf
case 0x1D: //CallIf
//in the case of JumpIf and CallIf, the first param is a comparisonOperator
//for JumpIfPlayerDir it's a directionID
//for JumpIfObjID, it's an EventID
parameterList.Add(new byte[] { dataReader.ReadByte() });
ProcessRelativeJump(dataReader, ref parameterList, ref functionOffsets);
break;
@@ -329,12 +329,12 @@ namespace DSPRE.ROMFiles {
case 0x1A: //Call
ProcessRelativeJump(dataReader, ref parameterList, ref functionOffsets);
break;
case 0x17: //CondJumpObjID
case 0x18: //CondJumpBgID
case 0x19: //CondJumpPlayerDir
case 0x1C: //CondJump
case 0x1D: //CondCall
parameterList.Add(new byte[] { dataReader.ReadByte() }); //in the case of CondJump and CondCall, the first param is a comparisonOperator
case 0x17: //JumpIfObjID
case 0x18: //JumpIfBgID
case 0x19: //JumpIfPlayerDir
case 0x1C: //JumpIf
case 0x1D: //CallIf
parameterList.Add(new byte[] { dataReader.ReadByte() }); //in the case of JumpIf and CallIf, the first param is a comparisonOperator
ProcessRelativeJump(dataReader, ref parameterList, ref functionOffsets);
break;
case 0x5E: // Movement
@@ -536,17 +536,13 @@ namespace DSPRE.ROMFiles {
}
public static string OverworldFlexDecode(ushort flexID) {
if (flexID > 255) {
return " " + "0x" + flexID.ToString("X4");
return "0x" + flexID.ToString("X4");
} else {
switch (flexID) {
case 255:
return " " + "Player";
case 253:
return " " + "Following";
case 241:
return " " + "Camera";
default:
return " " + "Overworld_#" + flexID.ToString("D");
string output;
if (ScriptDatabase.specialOverworlds.TryGetValue(flexID, out output)) {
return output;
} else {
return "Overworld." + flexID.ToString("D");
}
}
}

View File

@@ -1,12 +1,12 @@
using System;
using DSPRE.ROMFiles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DSPRE.Resources {
public static class ScriptDatabase {
public static class ScriptDatabase {
public static Dictionary<ushort, string> comparisonOperatorsDict = new Dictionary<ushort, string>() {
[0] = "LESS",
[1] = "EQUAL",
@@ -21,6 +21,12 @@ namespace DSPRE.Resources {
[7] = "AND",
[0xFF] = "TRUEUP"
};
public static Dictionary<ushort, string> specialOverworlds = new Dictionary<ushort, string>() {
[241] = "Camera",
[242] = "Partner",
[253] = "Following",
[255] = "Player"
};
public static Dictionary<ushort, int> commandsWithRelativeJump = new Dictionary<ushort, int>() {
//commandID, ID of parameter With Jump Address
@@ -30,8 +36,8 @@ namespace DSPRE.Resources {
[0x0018] = 1, //Call
[0x0019] = 1, //Call
[0x001A] = 0, //Call
[0x001C] = 1, //CondJump
[0x001D] = 1, //CondCall
[0x001C] = 1, //JumpIf
[0x001D] = 1, //CallIf
[0x005E] = 1, //Movement
};
@@ -40,7 +46,6 @@ namespace DSPRE.Resources {
0x16,
0x1B
};
public static Dictionary<ushort, string> movementsDictIDName = new Dictionary<ushort, string>() {
[0x0000] = "LookUp",
[0x0001] = "LookDown",
@@ -162,7 +167,6 @@ namespace DSPRE.Resources {
[0x007F] = "Ellipsis",
[0x0080] = "Asleep"
};
public static Dictionary<ushort, string> DPPtScrCmdNames = new Dictionary<ushort, string>() {
[0x0000] = "Nop",
[0x0001] = "Dummy",
@@ -183,17 +187,17 @@ namespace DSPRE.Resources {
[0x0010] = "IfAdrsAdrs",
[0x0011] = "CompareVarValue",
[0x0012] = "CompareVars",
[0x0013] = "ParallelCommonScript",
[0x0014] = "CommonScript",
[0x0015] = "LocalScript",
[0x0016] = "Jump",
[0x0017] = "JumpIfObjID",
[0x0018] = "JumpIfBgID",
[0x0018] = "JumpIfEventID",
[0x0019] = "JumpIfPlayerDir",
[0x001A] = "Call",
[0x001B] = "Return",
[0x001C] = "CondJump",
[0x001D] = "CondCall",
[0x001C] = "JumpIf",
[0x001D] = "CallIf",
[0x001E] = "SetFlag",
[0x001F] = "ClearFlag",
[0x0020] = "CheckFlag",
@@ -1554,7 +1558,7 @@ namespace DSPRE.Resources {
[0x0010] = "IfAdrsAdrs",
[0x0011] = "CompareVarValue",
[0x0012] = "CompareVars",
[0x0013] = "ParallelCommonScript",
[0x0014] = "CommonScript",
[0x0015] = "LocalScript",
[0x0016] = "Jump",
@@ -1563,8 +1567,8 @@ namespace DSPRE.Resources {
[0x0019] = "JumpIfPlayerDir",
[0x001A] = "Call",
[0x001B] = "Return",
[0x001C] = "CondJump",
[0x001D] = "CondCall",
[0x001C] = "JumpIf",
[0x001D] = "CallIf",
[0x001E] = "SetFlag",
[0x001F] = "ClearFlag",
[0x0020] = "CheckFlag",

View File

@@ -0,0 +1,97 @@

namespace DSPRE.ScintillaUtils {
partial class ScriptTooltip {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.panel1 = new System.Windows.Forms.Panel();
this.ctrl = new ScintillaNET.Scintilla();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(47)))), ((int)(((byte)(47)))), ((int)(((byte)(47)))));
this.panel1.Controls.Add(this.ctrl);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Padding = new System.Windows.Forms.Padding(15);
this.panel1.Size = new System.Drawing.Size(326, 126);
this.panel1.TabIndex = 1;
//
// ctrl
//
this.ctrl.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.ctrl.CaretPeriod = 500;
this.ctrl.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrl.EdgeColor = System.Drawing.Color.White;
this.ctrl.EdgeMode = ScintillaNET.EdgeMode.MultiLine;
this.ctrl.HScrollBar = false;
this.ctrl.Lexer = ScintillaNET.Lexer.Cpp;
this.ctrl.Location = new System.Drawing.Point(15, 15);
this.ctrl.Margin = new System.Windows.Forms.Padding(0);
this.ctrl.Margins.Capacity = 0;
this.ctrl.Margins.Left = 0;
this.ctrl.Margins.Right = 0;
this.ctrl.MouseDwellTime = 350;
this.ctrl.Name = "ctrl";
this.ctrl.PhasesDraw = ScintillaNET.Phases.Multiple;
this.ctrl.Size = new System.Drawing.Size(296, 96);
this.ctrl.TabDrawMode = ScintillaNET.TabDrawMode.Strikeout;
this.ctrl.TabIndex = 0;
this.ctrl.Text = "Empty";
this.ctrl.Visible = false;
this.ctrl.VScrollBar = false;
this.ctrl.WrapIndentMode = ScintillaNET.WrapIndentMode.Same;
this.ctrl.WrapMode = ScintillaNET.WrapMode.Word;
//
// ScriptTooltip
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(47)))), ((int)(((byte)(47)))), ((int)(((byte)(47)))));
this.ClientSize = new System.Drawing.Size(326, 126);
this.ControlBox = false;
this.Controls.Add(this.panel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ScriptTooltip";
this.Opacity = 0D;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "ScriptTooltip";
this.TopMost = true;
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
public ScintillaNET.Scintilla ctrl;
}
}

View File

@@ -0,0 +1,64 @@
using ScintillaNET;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DSPRE.ScintillaUtils {
public partial class ScriptTooltip : Form {
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
int nLeftRect, // x-coordinate of upper-left corner
int nTopRect, // y-coordinate of upper-left corner
int nRightRect, // x-coordinate of lower-right corner
int nBottomRect, // y-coordinate of lower-right corner
int nWidthEllipse, // height of ellipse
int nHeightEllipse // width of ellipse
);
public string textBuffer { get; set; } = "";
public ScriptTooltip(string mainKeywords, string textBuffer) {
InitializeComponent();
this.textBuffer = textBuffer;
this.FormBorderStyle = FormBorderStyle.None;
ctrl.ReadOnly = false;
ctrl.StyleResetDefault();
ctrl.Styles[Style.Default].Font = "Consolas";
ctrl.Styles[Style.Default].Size = 10;
ctrl.Styles[Style.Default].BackColor = Color.FromArgb(0x2F2F2F);
ctrl.Styles[Style.Default].ForeColor = Color.FromArgb(0xFFFFFF);
ctrl.StyleClearAll();
// Configure the lexer styles
ctrl.Styles[Style.Cpp.Identifier].ForeColor = Color.FromArgb(0xD0DAE2);
ctrl.Styles[Style.Cpp.CommentLine].ForeColor = Color.FromArgb(0x40BF57);
ctrl.Styles[Style.Cpp.Number].ForeColor = Color.FromArgb(0xFFFF00);
ctrl.Styles[Style.Cpp.String].ForeColor = Color.FromArgb(0xFF00FF);
ctrl.Styles[Style.Cpp.Character].ForeColor = Color.FromArgb(0xE95454);
ctrl.Styles[Style.Cpp.Operator].ForeColor = Color.FromArgb(0xFFFF00);
ctrl.Styles[Style.Cpp.Word].ForeColor = Color.FromArgb(0x48A8EE);
ctrl.Styles[Style.Cpp.Word2].ForeColor = Color.FromArgb(0xF98906);
ctrl.SetKeywords(0, mainKeywords);
Size newSize = TextRenderer.MeasureText(textBuffer, new Font(ctrl.Styles[Style.Default].Font, ctrl.Styles[Style.Default].Size), ctrl.ClientSize, TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl);
this.ClientSize = new Size(this.ClientSize.Width, newSize.Height + this.panel1.Padding.All);
Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 10, 10));
}
public void WriteText(int delay = 15) {
ctrl.Text = "";
ctrl.BufferedDraw = true;
foreach (char c in this.textBuffer) {
Thread.Sleep(delay);
ctrl.Text += c;
ctrl.Update();
}
ctrl.ReadOnly = true;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>