diff --git a/.gitignore b/.gitignore
index 717f1a0..e6bc0c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,7 @@ Thumbs.db
*.log
[Bb]in
[Dd]ebug*/
+![Dd]ebugging*/
*.lib
*.sbr
obj/
diff --git a/Source/MDK/Debugging/TriggerTracing.cs b/Source/MDK/Debugging/TriggerTracing.cs
new file mode 100644
index 0000000..6ebccab
--- /dev/null
+++ b/Source/MDK/Debugging/TriggerTracing.cs
@@ -0,0 +1,211 @@
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Markup;
+using System.Windows.Media.Animation;
+
+// Code from http://www.wpfmentor.com/2009/01/how-to-debug-triggers-using-trigger.html
+// No license specified - this code is trimmed out from Release build anyway so it should be ok using it this way
+
+// HOWTO: add the following attached property to any trigger and you will see when it is activated/deactivated in the output window
+// TriggerTracing.TriggerName="your debug name"
+// TriggerTracing.TraceEnabled="True"
+
+// Example:
+//
+//
+//
+//
+// As this works on anything that inherits from TriggerBase, it will also work on .
+
+namespace MDK.Debugging
+{
+#if DEBUG
+
+ ///
+ /// Contains attached properties to activate Trigger Tracing on the specified Triggers.
+ /// This file alone should be dropped into your app.
+ ///
+ public static class TriggerTracing
+ {
+ static TriggerTracing()
+ {
+ // Initialise WPF Animation tracing and add a TriggerTraceListener
+ PresentationTraceSources.Refresh();
+ PresentationTraceSources.AnimationSource.Listeners.Clear();
+ PresentationTraceSources.AnimationSource.Listeners.Add(new TriggerTraceListener());
+ PresentationTraceSources.AnimationSource.Switch.Level = SourceLevels.All;
+ }
+
+ #region TriggerName attached property
+
+ ///
+ /// Gets the trigger name for the specified trigger. This will be used
+ /// to identify the trigger in the debug output.
+ ///
+ /// The trigger.
+ ///
+ public static string GetTriggerName(TriggerBase trigger)
+ {
+ return (string)trigger.GetValue(TriggerNameProperty);
+ }
+
+ ///
+ /// Sets the trigger name for the specified trigger. This will be used
+ /// to identify the trigger in the debug output.
+ ///
+ /// The trigger.
+ ///
+ ///
+ public static void SetTriggerName(TriggerBase trigger, string value)
+ {
+ trigger.SetValue(TriggerNameProperty, value);
+ }
+
+ ///
+ ///
+ ///
+ public static readonly DependencyProperty TriggerNameProperty =
+ DependencyProperty.RegisterAttached(
+ "TriggerName",
+ typeof(string),
+ typeof(TriggerTracing),
+ new UIPropertyMetadata(string.Empty));
+
+ #endregion
+
+ #region TraceEnabled attached property
+
+ ///
+ /// Gets a value indication whether trace is enabled for the specified trigger.
+ ///
+ /// The trigger.
+ ///
+ public static bool GetTraceEnabled(TriggerBase trigger)
+ {
+ return (bool)trigger.GetValue(TraceEnabledProperty);
+ }
+
+ ///
+ /// Sets a value specifying whether trace is enabled for the specified trigger
+ ///
+ ///
+ ///
+ public static void SetTraceEnabled(TriggerBase trigger, bool value)
+ {
+ trigger.SetValue(TraceEnabledProperty, value);
+ }
+
+ ///
+ ///
+ ///
+ public static readonly DependencyProperty TraceEnabledProperty =
+ DependencyProperty.RegisterAttached(
+ "TraceEnabled",
+ typeof(bool),
+ typeof(TriggerTracing),
+ new UIPropertyMetadata(false, OnTraceEnabledChanged));
+
+ private static void OnTraceEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var triggerBase = d as TriggerBase;
+
+ if (triggerBase == null)
+ return;
+
+ if (!(e.NewValue is bool))
+ return;
+
+ if ((bool)e.NewValue)
+ {
+ // insert dummy story-boards which can later be traced using WPF animation tracing
+
+ var storyboard = new TriggerTraceStoryboard(triggerBase, TriggerTraceStoryboardType.Enter);
+ triggerBase.EnterActions.Insert(0, new BeginStoryboard() { Storyboard = storyboard });
+
+ storyboard = new TriggerTraceStoryboard(triggerBase, TriggerTraceStoryboardType.Exit);
+ triggerBase.ExitActions.Insert(0, new BeginStoryboard() { Storyboard = storyboard });
+ }
+ else
+ {
+ // remove the dummy storyboards
+
+ foreach (var actionCollection in new[] { triggerBase.EnterActions, triggerBase.ExitActions })
+ {
+ foreach (var triggerAction in actionCollection)
+ {
+ if (triggerAction is BeginStoryboard bsb && bsb.Storyboard is TriggerTraceStoryboard)
+ {
+ actionCollection.Remove(bsb);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ #endregion
+
+ private enum TriggerTraceStoryboardType
+ {
+ Enter, Exit
+ }
+
+ ///
+ /// A dummy storyboard for tracing purposes
+ ///
+ private class TriggerTraceStoryboard : Storyboard
+ {
+ public TriggerTraceStoryboardType StoryboardType { get; }
+ public TriggerBase TriggerBase { get; }
+
+ public TriggerTraceStoryboard(TriggerBase triggerBase, TriggerTraceStoryboardType storyboardType)
+ {
+ TriggerBase = triggerBase;
+ StoryboardType = storyboardType;
+ }
+ }
+
+ ///
+ /// A custom tracelistener.
+ ///
+ private class TriggerTraceListener : TraceListener
+ {
+ public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
+ {
+ base.TraceEvent(eventCache, source, eventType, id, format, args);
+
+ if (format.StartsWith("Storyboard has begun;"))
+ {
+ if (args[1] is TriggerTraceStoryboard storyboard)
+ {
+ // add a breakpoint here to see when your trigger has been
+ // entered or exited
+
+ // the element being acted upon
+ var targetElement = args[5];
+
+ // the namescope of the element being acted upon
+ var namescope = (INameScope)args[7];
+
+ var triggerBase = storyboard.TriggerBase;
+ var triggerName = GetTriggerName(storyboard.TriggerBase);
+
+ Debug.WriteLine($"Element: {targetElement}, {triggerBase.GetType().Name}: {triggerName}: {storyboard.StoryboardType}");
+ }
+ }
+ }
+
+ public override void Write(string message)
+ {
+ }
+
+ public override void WriteLine(string message)
+ {
+ }
+ }
+ }
+#endif
+}
\ No newline at end of file
diff --git a/Source/changelog.1.2.0.md b/Source/changelog.1.2.0.md
index aec1425..34a3858 100644
--- a/Source/changelog.1.2.0.md
+++ b/Source/changelog.1.2.0.md
@@ -1,5 +1,21 @@
-Changed how script options are stored in order to make it easier to work on projects on multiple computers
-Renamed Blueprint Manager to Script Manager
-Deprecated Readme.cs (more or less), changed to Instructions.readme and added item template for it
-Fixed crash while VS is trying to read a project from a network (MDK will ignore this case)
-Added project template for ingame script mixin (shared project)
\ No newline at end of file
+
+- #111 thumb.jpg in existing scripts not recognized in blueprint manager
+- #124 [PRE] [VS2019] Error when attempting to create a new Project
+- #125 [PRE] [VS2019] New projects default to C# 7 or higher.
+- #130 Suggestion: Refreshing whitelist runs SE; Add -skipintro to not show intro video
+
+- Changed how script options are stored in order to make it easier to work on projects on multiple computers
+- Renamed Blueprint Manager to Script Manager
+- Deprecated Readme.cs (more or less), changed to Instructions.readme and added item template for it
+- Fixed crash while VS is trying to read a project from a network (MDK will ignore this case)
+- Added project template for ingame script mixin (shared project)
+- MDK is now more code repository (for example git) friendly.
+ - The paths are now stored in a separate file, MDK.paths.props, which should not be checked in.
+ The file should be restored on the other side.
+- Backup zips are made before any project upgrades or repairs are made
+- Finalizers are reported as prohibited
+- Experimental VS2019 support
+- Proper install-time version checking, finally
+- Fixed #98 Unimportant Non-SE Project Error
+- Added #99 Include "Do not deploy" option in MDK Script Options window / #79 Deploy option in files.
+ "Exclude from Deploy All" checkbox
\ No newline at end of file