Changeset - 991c95f4da74
[Not reviewed]
default
0 6 0
Jason Maltzen - 9 years ago 2016-03-11 09:12:20
jason@hiddenachievement.com
Add some logging, fix a bug finding the paint dialog.
6 files changed with 176 insertions and 42 deletions:
0 comments (0 inline, 0 general)
DesertPaintLab.csproj
Show inline comments
 
<?xml version="1.0" encoding="utf-8"?>
 
<?xml version="1.0" encoding="utf-8"?>
 
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
 
  <PropertyGroup>
 
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
...
 
@@ -8,6 +8,21 @@
 
    <RootNamespace>DesertPaintLab</RootNamespace>
 
    <AssemblyName>DesertPaintLab</AssemblyName>
 
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
 
    <PublishUrl>publish\</PublishUrl>
 
    <Install>true</Install>
 
    <InstallFrom>Disk</InstallFrom>
 
    <UpdateEnabled>false</UpdateEnabled>
 
    <UpdateMode>Foreground</UpdateMode>
 
    <UpdateInterval>7</UpdateInterval>
 
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
 
    <UpdatePeriodically>false</UpdatePeriodically>
 
    <UpdateRequired>false</UpdateRequired>
 
    <MapFileExtensions>true</MapFileExtensions>
 
    <ApplicationRevision>0</ApplicationRevision>
 
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
 
    <IsWebBootstrapper>false</IsWebBootstrapper>
 
    <UseApplicationTrust>false</UseApplicationTrust>
 
    <BootstrapperEnabled>true</BootstrapperEnabled>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
 
    <DebugSymbols>true</DebugSymbols>
...
 
@@ -32,6 +47,25 @@
 
    <ConsolePause>false</ConsolePause>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
 
    <DebugSymbols>true</DebugSymbols>
 
    <OutputPath>bin\x64\Debug\</OutputPath>
 
    <DefineConstants>DEBUG</DefineConstants>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <DebugType>full</DebugType>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
 
    <OutputPath>bin\x64\Release\</OutputPath>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
...
 
@@ -115,7 +149,17 @@
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
  </ItemGroup>
 
  <ItemGroup />
 
  <ItemGroup>
 
    <Folder Include="UI\" />
 
    <BootstrapperPackage Include=".NETFramework,Version=v4.5">
 
      <Visible>False</Visible>
 
      <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
 
      <Install>true</Install>
 
    </BootstrapperPackage>
 
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
 
      <Visible>False</Visible>
 
      <ProductName>.NET Framework 3.5 SP1</ProductName>
 
      <Install>false</Install>
 
    </BootstrapperPackage>
 
  </ItemGroup>
 
</Project>
...
 
\ No newline at end of file
DesertPaintLab.sln
Show inline comments
 

 
Microsoft Visual Studio Solution File, Format Version 12.00
 
# Visual Studio 2012
 
# Visual Studio 14
 
VisualStudioVersion = 14.0.23107.0
 
MinimumVisualStudioVersion = 10.0.40219.1
 
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesertPaintLab", "DesertPaintLab.csproj", "{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}"
 
EndProject
 
Global
 
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 
		Debug|x64 = Debug|x64
 
		Debug|x86 = Debug|x86
 
		Release|x64 = Release|x64
 
		Release|x86 = Release|x86
 
	EndGlobalSection
 
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x64.ActiveCfg = Debug|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x64.Build.0 = Debug|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.ActiveCfg = Debug|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.Build.0 = Debug|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x64.ActiveCfg = Release|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x64.Build.0 = Release|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.ActiveCfg = Release|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.Build.0 = Release|x86
 
	EndGlobalSection
 
	GlobalSection(SolutionProperties) = preSolution
 
		HideSolutionNode = FALSE
 
	EndGlobalSection
 
EndGlobal
FileUtils.cs
Show inline comments
...
 
@@ -115,6 +115,18 @@ namespace DesertPaintLab
 
            }
 
            return filePath;
 
        }
 

	
 
        public static string FindNumberedFile(string baseName, string extension, string folder)
 
        {
 
            string filename = "";
 
            int i = 0;
 
            do
 
            {
 
                ++i;
 
                filename = System.IO.Path.Combine(folder, String.Format("{0}_{1}.{2}", baseName, i, extension));
 
            } while (System.IO.File.Exists(filename));
 
            return filename;
 
        }
 
    }
 
}
 

	
MainWindow.cs
Show inline comments
...
 
@@ -139,7 +139,7 @@ public partial class MainWindow : Gtk.Wi
 

	
 
		screenBuffer = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, screenWidth, screenHeight);
 
	
 
        ReactionRecorder.SetPixelMultiplier(pixelMultiplier);
 
        ReactionRecorder.Instance.SetPixelMultiplier(pixelMultiplier);
 

	
 
		if (!OpenProfile())
 
		{
ReactionRecorder.cs
Show inline comments
...
 
@@ -21,6 +21,7 @@
 
*/
 

	
 
using System;
 
using System.IO;
 

	
 
namespace DesertPaintLab
 
{
...
 
@@ -38,14 +39,66 @@ namespace DesertPaintLab
 

	
 
        const int DEFAULT_SWATCH_TEST_WIDTH = 26; // width to test on ends of swatch (10% on either end)
 

	
 
        static int swatchHeight = DEFAULT_SWATCH_HEIGHT;
 
        static int swatchWidth = DEFAULT_SWATCH_WIDTH;
 
        static int swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH;
 
        static int colorBarWidth = DEFAULT_COLOR_BAR_WIDTH;
 
        static int redBarSpacing = DEFAULT_RED_BAR_SPACING;
 
        static int greenBarSpacing = DEFAULT_GREEN_BAR_SPACING;
 
        static int blueBarSpacing = DEFAULT_BLUE_BAR_SPACING;
 
        static int pixelMultiplier = 1;
 
        int swatchHeight = DEFAULT_SWATCH_HEIGHT;
 
        int swatchWidth = DEFAULT_SWATCH_WIDTH;
 
        int swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH;
 
        int colorBarWidth = DEFAULT_COLOR_BAR_WIDTH;
 
        int redBarSpacing = DEFAULT_RED_BAR_SPACING;
 
        int greenBarSpacing = DEFAULT_GREEN_BAR_SPACING;
 
        int blueBarSpacing = DEFAULT_BLUE_BAR_SPACING;
 
        int pixelMultiplier = 1;
 

	
 
        private static ReactionRecorder _instance;
 
        public static ReactionRecorder Instance
 
        {
 
            get {
 
                if (_instance == null)
 
                {
 
                    _instance = new ReactionRecorder();
 
                }
 
                return _instance;
 
            }
 
        }
 

	
 
        private StreamWriter _log;
 
        public StreamWriter Log
 
        {
 
            set
 
            {
 
                _log = value;
 
            }
 
        }
 
        private void WriteLog(string format, params object[] args)
 
        {
 
            if (_log != null)
 
            {
 
                _log.WriteLine(format, args);
 
            }
 
        }
 

	
 
        public ReactionRecorder()
 
        {
 
            this.pixelMultiplier = 1;
 
            swatchHeight = DEFAULT_SWATCH_HEIGHT * pixelMultiplier;
 
            swatchWidth = DEFAULT_SWATCH_WIDTH * pixelMultiplier;
 
            colorBarWidth = DEFAULT_COLOR_BAR_WIDTH * pixelMultiplier;
 
            redBarSpacing = DEFAULT_RED_BAR_SPACING * pixelMultiplier;
 
            greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier;
 
            blueBarSpacing = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier;
 
            swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier;
 
        }
 

	
 
        public ReactionRecorder(int pixelMultiplier)
 
        {
 
            this.pixelMultiplier = pixelMultiplier;
 
            swatchHeight = DEFAULT_SWATCH_HEIGHT * pixelMultiplier;
 
            swatchWidth = DEFAULT_SWATCH_WIDTH * pixelMultiplier;
 
            colorBarWidth = DEFAULT_COLOR_BAR_WIDTH * pixelMultiplier;
 
            redBarSpacing = DEFAULT_RED_BAR_SPACING * pixelMultiplier;
 
            greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier;
 
            blueBarSpacing = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier;
 
            swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier;
 
        }
 

	
 
        private static bool IsPapyTexture(byte r, byte g, byte b)
 
        {
...
 
@@ -56,7 +109,7 @@ namespace DesertPaintLab
 
                   ((r < 0xF4) && (g <= 0xED) && (b <= 0xCD));
 
        }
 

	
 
        public static void SetPixelMultiplier(int pixelMultiplier)
 
        public void SetPixelMultiplier(int pixelMultiplier)
 
        {
 
            swatchHeight    = DEFAULT_SWATCH_HEIGHT * pixelMultiplier;
 
            swatchWidth     = DEFAULT_SWATCH_WIDTH * pixelMultiplier;
...
 
@@ -65,10 +118,10 @@ namespace DesertPaintLab
 
            greenBarSpacing = DEFAULT_GREEN_BAR_SPACING * pixelMultiplier;
 
            blueBarSpacing  = DEFAULT_BLUE_BAR_SPACING * pixelMultiplier;
 
            swatchTestWidth = DEFAULT_SWATCH_TEST_WIDTH * pixelMultiplier;
 
            ReactionRecorder.pixelMultiplier = pixelMultiplier;
 
            this.pixelMultiplier = pixelMultiplier;
 
        }
 

	
 
        unsafe private static void ColorAt(byte *pixBytes, int x, int y, int stride, out byte r, out byte g, out byte b)
 
        unsafe private void ColorAt(byte *pixBytes, int x, int y, int stride, out byte r, out byte g, out byte b)
 
        {
 
            int pixelStart = (y * stride) + (x * 3);
 
                    r = pixBytes[pixelStart];
...
 
@@ -76,19 +129,19 @@ namespace DesertPaintLab
 
                    b = pixBytes[pixelStart + 2];
 
        }
 

	
 
        private static bool IsDarkPixel(int r, int g, int b)
 
        private bool IsDarkPixel(int r, int g, int b)
 
        {
 
            return ((r < 0x46) && (g < 0x46) && (b < 0x47));
 
        }
 

	
 
        private static bool IsColorMatch(byte test_r, byte test_g, byte test_b, byte target_r, byte target_g, byte target_b)
 
        private bool IsColorMatch(byte test_r, byte test_g, byte test_b, byte target_r, byte target_g, byte target_b)
 
        {
 
            return ((Math.Abs(test_r - target_r) <= COLOR_TOLERANCE) &&
 
                (Math.Abs(test_g - target_g) <= COLOR_TOLERANCE) &&
 
                (Math.Abs(test_b - target_b) <= COLOR_TOLERANCE));
 
        }
 

	
 
        unsafe private static bool IsPossibleSwatchSlice(byte* pixBytes, int x, int y, int stride)
 
        unsafe private bool IsPossibleSwatchSlice(byte* pixBytes, int x, int y, int stride)
 
        {
 
            int testPixelStart = (y * stride) + (x * 3);
 
            byte r = pixBytes[testPixelStart];
...
 
@@ -127,16 +180,22 @@ namespace DesertPaintLab
 
                result &= IsColorMatch(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2], r, g, b);
 
            }
 

	
 
            if (!result)
 
            {
 
                WriteLog("Swatch slice at {0}, {1} failed to match", x, y);
 
            }
 

	
 
            return result;
 
        }
 

	
 
        unsafe private static bool IsPossibleSwatchUpperLeft(byte* pixBytes, int x, int y, int stride)
 
        unsafe private bool IsPossibleSwatchUpperLeft(byte* pixBytes, int x, int y, int stride)
 
        {
 
            int testPixelStart = (y * stride) + (x * 3);
 

	
 
            bool result = true;
 
            // test the left edge for dark pixels
 
            for (int i = 0; result && (i < swatchHeight-pixelMultiplier); ++i)
 
            int i = 0;
 
            for (i = 0; result && (i < swatchHeight-pixelMultiplier); ++i)
 
            {
 
                int otherPixelStart = testPixelStart + (stride * i);
 
                result &= IsDarkPixel(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]);
...
 
@@ -144,21 +203,26 @@ namespace DesertPaintLab
 

	
 
            // test the dark top border and for papyrus above and below the swatch
 
            int papyErrorCount = 0;
 
            for (int i = 0; result && (i < swatchWidth); ++i)
 
            for (i = 0; result && (i < swatchWidth); ++i)
 
            {
 
                int otherPixelStart = testPixelStart + (3 * i);
 
                result &= IsDarkPixel(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]);
 
                otherPixelStart = otherPixelStart - stride;
 
                papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]) ? 1 : 0);
 
                papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]) ? 0 : 1);
 
                otherPixelStart = testPixelStart + (stride * swatchHeight) + (3 * i);
 
                papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]) ? 1 : 0);
 
                papyErrorCount += (IsPapyTexture(pixBytes[otherPixelStart], pixBytes[otherPixelStart+1], pixBytes[otherPixelStart+2]) ? 0 : 1);
 
            }
 

	
 
                result &= (papyErrorCount < (swatchWidth / 20)); // allow up to 5% error rate checking for papy texture, because this seems to be inconsistent
 
            if (!result && ((i > (swatchWidth*0.8)) || (papyErrorCount >= (swatchWidth/20))))
 
            {
 
                WriteLog("Found a potential swatch candidate of width {0} at {1},{2} that had {3} failures matching papyrus texture", i, x, y, papyErrorCount);
 
            }
 

	
 
            return result;
 
        }
 

	
 
        unsafe public static bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart)
 
        unsafe public bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride, ref PaintColor reactedColor, ref int redPixelStart)
 
        {
 
            byte pixel_r, pixel_g, pixel_b;
 
            int pixelStart, otherPixelStart;
...
 
@@ -248,6 +312,7 @@ namespace DesertPaintLab
 
                            }
 

	
 
                            reactedColor.Blue = (byte)Math.Round((float)bluePixelCount * 255f / (float)colorBarWidth);
 
                            WriteLog("Found the color swatch at {0}, {1}. Color={2}", x, y, reactedColor);
 
                            return true;
 
                        }
 
                    }
...
 
@@ -256,7 +321,7 @@ namespace DesertPaintLab
 
            return false;
 
        }
 

	
 
        public static bool RecordReaction(PlayerProfile profile, PaintColor expectedColor, PaintColor reactedColor, Reagent[] reagents)
 
        public bool RecordReaction(PlayerProfile profile, PaintColor expectedColor, PaintColor reactedColor, Reagent[] reagents)
 
        {
 
            bool saved = false;
 
            int r, g, b;
UI/CaptureView.cs
Show inline comments
 
using System;
 
using System.IO;
 

	
 
namespace DesertPaintLab
 
{
...
 
@@ -262,20 +263,27 @@ namespace DesertPaintLab
 
            byte* pixBytes = (byte*)screenBuffer.Pixels;
 
            int redPixelStart = -1;
 
        
 
            isCaptured = ReactionRecorder.CaptureReaction(pixBytes, screenWidth, screenHeight, stride, ref reactedColor, ref redPixelStart);
 
            StreamWriter log = null;
 
            if (enableDebugMenu)
 
            {
 
                string logfile = FileUtils.FindNumberedFile("DesertPaintLab_Capture", "log", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
 
                log = new StreamWriter(logfile);
 
                ReactionRecorder.Instance.Log = log;
 
            }
 
            isCaptured = ReactionRecorder.Instance.CaptureReaction(pixBytes, screenWidth, screenHeight, stride, ref reactedColor, ref redPixelStart);
 
            if (log != null)
 
            {
 
                log.Flush();
 
                log.Close();
 
                log = null;
 
            }
 
            if (enableDebugMenu && debugScreenshot)
 
            {
 
                if (!isCaptured)
 
                {
 
                    // write out the whole screenshot on a failure to capture
 
                    string screenshotDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
 
                    string filename;
 
                    int i = 0;
 
                    do
 
                    {
 
                        ++i;
 
                        filename = System.IO.Path.Combine(screenshotDir, String.Format("DesertPaintLab_Colormatch{0}.png", i));
 
                    } while (System.IO.File.Exists(filename));
 
                    string filename = FileUtils.FindNumberedFile("DesertPaintLab_Colormatch", "png", screenshotDir);
 
                    screenBuffer.Save(filename, "png");
 
                }
 
                else
...
 
@@ -286,16 +294,10 @@ namespace DesertPaintLab
 
                    int redPixelStartY = (redPixelStart / stride);
 
                    // write out the screenshot
 
                    string screenshotDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
 
                    string filename;
 
                    int i = 0;
 
                    do
 
                    {
 
                        ++i;
 
                        filename = System.IO.Path.Combine(screenshotDir, String.Format("DesertPaintLab_Colormatch{0}.png", i));
 
                    } while (System.IO.File.Exists(filename));
 
                    string filename = FileUtils.FindNumberedFile("DesertPaintLab_Colormatch", "png", screenshotDir);
 
                    int captureAreaWidth = Math.Min(64, screenWidth - redPixelStartX + 64);
 
                    int captureAreaHeight = Math.Min(64, screenHeight - redPixelStartY + 64);
 
                    Gdk.Pixbuf outPixBuf = new Gdk.Pixbuf(screenBuffer, Math.Max(0, redPixelStartX - 16), Math.Max(0, redPixelStartY - 16), captureAreaWidth, captureAreaHeight);
 
                    Gdk.Pixbuf outPixBuf = new Gdk.Pixbuf(screenBuffer, Math.Max(0, redPixelStartX - 32), Math.Max(0, redPixelStartY - 32), captureAreaWidth, captureAreaHeight);
 
                    //screenBuffer.Save(filename, "png");
 
                    outPixBuf.Save(filename, "png");
 
                }
...
 
@@ -371,7 +373,7 @@ namespace DesertPaintLab
 
        
 
        protected virtual void OnRecord(object sender, System.EventArgs e)
 
        {
 
            if (ReactionRecorder.RecordReaction(profile, expectedColor, reactedColor, reagents))
 
            if (ReactionRecorder.Instance.RecordReaction(profile, expectedColor, reactedColor, reagents))
 
            {
 
                recordButton.Sensitive = false;
 
            }
0 comments (0 inline, 0 general)