Changeset - 7117d2e703c8
[Not reviewed]
default
1 12 0
Tess Snider (Malkyne) - 3 years ago 2021-07-19 09:49:18
this@malkyne.org
Updated scanner for Tale 10, and fixed several bugs.
13 files changed with 168 insertions and 204 deletions:
0 comments (0 inline, 0 general)
Models/InterfaceSize.cs
Show inline comments
 
deleted file
Services/ReactionScannerService.cs
Show inline comments
...
 
@@ -21,87 +21,34 @@ namespace DesertPaintCodex.Services
 
        }
 
        
 
        // Swatch is 301x20 solid color, 1px darker left/top, 1px black outer left/top, 1px light right/bottom, 1px bright right/bottom
 
        // top-right and bottom-left are bright instead of black
 

	
 
        // Color bars are 4x302 solid color, 2px border on all sides (darker left/top, lighter bottom/right
 

	
 
        private static readonly int[] SWATCH_HEIGHT = 
 
        {
 
            24, // tiny
 
            24, // small
 
            24, // medium
 
            24, // large
 
            24 // huge
 
        };
 

	
 
        private static readonly int[] SWATCH_WIDTH =
 
        {
 
            306, // tiny
 
            306, // small
 
            306, // medium
 
            320, // large
 
            350 // huge
 
        };
 

	
 
        private static readonly int[] COLOR_BAR_WIDTH =
 
        {
 
            306, // tiny
 
            306, // small -- includes left and right borders
 
            306, // medium
 
            320, // large
 
            350 // huge
 
        };
 
        private const int SwatchHeight    = 24;
 
        private const int RedBarSpacing   = 32;
 
        private const int GreenBarSpacing = 42;
 
        private const int BlueBarSpacing  = 52;
 

	
 
        private static readonly int[] RED_BAR_SPACING =
 
        {
 
            32, // tiny
 
            32, // small
 
            32, // medium
 
            32, // large
 
            32 // huge
 
        };
 

	
 
        private static readonly int[] GREEN_BAR_SPACING =
 
        {
 
            42, // tiny
 
            42, // small
 
            42, // medium
 
            42, // large
 
            42 // huge
 
        };
 

	
 
        private static readonly int[] BLUE_BAR_SPACING =
 
        {
 
            52, // tiny
 
            52, // small
 
            52, // medium
 
            52, // large
 
            52 // huge
 
        };
 
        // width to test on ends of swatch (10% on either end)
 
        private static readonly int[] SWATCH_TEST_WIDTH =
 
        {
 
            26, // tiny
 
            26, // small
 
            26, // medium
 
            28, // large
 
            31  // huge
 
        };
 
        private const int MinSwatchWidth = 306;
 
        private const int MaxSwatchWidth = 411;
 

	
 
        private static ReactionScannerService? s_instance;
 
        public static ReactionScannerService Instance => s_instance ??= new ReactionScannerService();
 

	
 
        private int _swatchHeight    = SWATCH_HEIGHT[(int)Constants.DefaultInterfaceSize];
 
        private int _swatchWidth     = SWATCH_WIDTH[(int)Constants.DefaultInterfaceSize];
 
        private int _swatchTestWidth = SWATCH_TEST_WIDTH[(int)Constants.DefaultInterfaceSize];
 
        private int _colorBarWidth   = COLOR_BAR_WIDTH[(int)Constants.DefaultInterfaceSize];
 
        private int _redBarSpacing   = RED_BAR_SPACING[(int)Constants.DefaultInterfaceSize];
 
        private int _greenBarSpacing = GREEN_BAR_SPACING[(int)Constants.DefaultInterfaceSize];
 
        private int _blueBarSpacing  = BLUE_BAR_SPACING[(int)Constants.DefaultInterfaceSize];
 
        private int _swatchHeight    = 0;
 
        private int _minSwatchWidth  = 0;
 
        private int _maxSwatchWidth  = 0;
 
        private int _swatchWidth     = 0;
 
        private int _redBarSpacing   = 0;
 
        private int _greenBarSpacing = 0;
 
        private int _blueBarSpacing  = 0;
 
        private int _swatchTopBorder    = 0;
 
        private int _swatchBottomBorder = 0;
 
        private int _swatchLeftBorder   = 0;
 
        private int _swatchRightBorder  = 0;
 
        private int _swatchTestWidth = 0;
 

	
 
        private bool _lockedSwatchWidth = false;
 

	
 
        // Current Status
 
        public bool IsCaptured { get; private set; }
 

	
 
        private PaintColor _recordedColor = new PaintColor();
 
        private readonly PaintColor _recordedColor = new();
 
        public PaintColor RecordedColor {
 
            get => _recordedColor;
...
 
@@ -111,6 +58,4 @@ namespace DesertPaintCodex.Services
 
        private int _pixelMultiplier = 1;
 

	
 
        private InterfaceSize _interfaceSize = Constants.DefaultInterfaceSize;
 

	
 
        private bool _firstRun   = true;
 
        private int _lastSwatchX = -1;
...
 
@@ -152,9 +97,4 @@ namespace DesertPaintCodex.Services
 
        {
 
            SettingsService.Get(SettingKey.PixelMultiplier, out _pixelMultiplier, Constants.DefaultPixelMultiplier);
 
            SettingsService.Get(SettingKey.InterfaceSize, out int interfaceSize, (int)Constants.DefaultInterfaceSize);
 
            if (Enum.IsDefined(typeof(InterfaceSize), interfaceSize))
 
            {
 
                _interfaceSize = (InterfaceSize)interfaceSize;
 
            }
 

	
 
            SettingsService.Get(SettingKey.ScreenX, out _screenX, Constants.DefaultScreenX);
...
 
@@ -172,11 +112,16 @@ namespace DesertPaintCodex.Services
 
        private void UpdateSwatchSizes()
 
        {
 
            _swatchHeight    = SWATCH_HEIGHT[(int)_interfaceSize]     * _pixelMultiplier;
 
            _swatchWidth     = SWATCH_WIDTH[(int)_interfaceSize]      * _pixelMultiplier;
 
            _colorBarWidth   = COLOR_BAR_WIDTH[(int)_interfaceSize]   * _pixelMultiplier;
 
            _redBarSpacing   = RED_BAR_SPACING[(int)_interfaceSize]   * _pixelMultiplier;
 
            _greenBarSpacing = GREEN_BAR_SPACING[(int)_interfaceSize] * _pixelMultiplier;
 
            _blueBarSpacing  = BLUE_BAR_SPACING[(int)_interfaceSize]  * _pixelMultiplier;
 
            _swatchTestWidth = SWATCH_TEST_WIDTH[(int)_interfaceSize] * _pixelMultiplier;
 
            _swatchWidth     = MinSwatchWidth * _pixelMultiplier;
 
            _swatchHeight    = SwatchHeight    * _pixelMultiplier;
 
            _redBarSpacing   = RedBarSpacing   * _pixelMultiplier;
 
            _greenBarSpacing = GreenBarSpacing * _pixelMultiplier;
 
            _blueBarSpacing  = BlueBarSpacing  * _pixelMultiplier;
 
            _swatchTopBorder    = 2 * _pixelMultiplier;
 
            _swatchBottomBorder = 2 * _pixelMultiplier;
 
            _swatchLeftBorder   = 2 * _pixelMultiplier;
 
            _swatchRightBorder  = 2 * _pixelMultiplier;
 
            _minSwatchWidth = MinSwatchWidth * _pixelMultiplier;
 
            _maxSwatchWidth = MaxSwatchWidth * _pixelMultiplier;
 
            _swatchTestWidth = (int)(0.1f * MinSwatchWidth * _pixelMultiplier);
 
        }
 

	
...
 
@@ -202,5 +147,5 @@ namespace DesertPaintCodex.Services
 
            
 
            // 2.) grab the swatch color 2 down from top border
 
            ColorMatcher.Color = pixels.ColorAt(x, y + 2);
 
            ColorMatcher.Color = pixels.ColorAt(x, y + _swatchTopBorder);
 

	
 
            // Scan the column from 2 below the top to 3 above the bottom to ensure the color matches
...
 
@@ -217,8 +162,8 @@ namespace DesertPaintCodex.Services
 
            bool result = true;
 

	
 
            int swatchSolidWidth = _swatchWidth - 4;
 
            int swatchSolidHeight = _swatchHeight - 5; // 2 top and 3 bottom pixels are slightly different colors
 
            int swatchSolidLeftX = x + 2;
 
            int swatchSolidTopY = y + 2;
 
            int swatchSolidWidth   = _swatchWidth  - _swatchLeftBorder - _swatchRightBorder;
 
            int swatchSolidHeight  = _swatchHeight - _swatchTopBorder - _swatchBottomBorder;
 
            int swatchSolidLeftX   = x + _swatchLeftBorder;
 
            int swatchSolidTopY    = y + _swatchTopBorder;
 
            int swatchSolidRightX = swatchSolidLeftX + swatchSolidWidth - 1;
 
            int swatchSolidBottomY = swatchSolidTopY + swatchSolidHeight - 1;
...
 
@@ -258,6 +203,26 @@ namespace DesertPaintCodex.Services
 
            }
 

	
 
            // Find the right side of the swatch, if necessary.
 
            if (!_lockedSwatchWidth)
 
            {
 
                int xCutoff = Math.Min(x + _maxSwatchWidth - _swatchRightBorder, _targetBitmap.Width);
 
                int newRight = swatchSolidRightX;
 
                for (int px = swatchSolidRightX; px < xCutoff; px++)
 
                {
 
                    if (pixels.DoesPixelMatch(px, swatchSolidTopY, ColorMatcher.IsMatch) &&
 
                        pixels.DoesPixelMatch(px, swatchSolidBottomY, ColorMatcher.IsMatch))
 
                    {
 
                        newRight = px;
 
                    }
 
                    else break;
 
                }
 

	
 
                swatchSolidRightX = newRight;
 
                _swatchWidth = swatchSolidRightX + _swatchRightBorder - x + _pixelMultiplier;
 
                WriteLog(LogVerbosity.High, "Setting new swatch width of {0}.", _swatchWidth);
 
            }
 

	
 
            // scan down the right and left sides
 
            for (int yOff = 1; yOff < (swatchSolidHeight - 1); ++yOff)
 
            for (int yOff = _pixelMultiplier; yOff < (swatchSolidHeight - _pixelMultiplier); ++yOff)
 
            {
 
                result &= pixels.DoesPixelMatch(swatchSolidLeftX, swatchSolidTopY + yOff, ColorMatcher.IsMatch);
...
 
@@ -276,8 +241,8 @@ namespace DesertPaintCodex.Services
 
            if (!result)
 
            {
 
                WriteLog(LogVerbosity.Normal, "Failed to find left/right edges for potential swatch of color {2}, {3}, {4} at {0}, {1} [failed color = {5},{6},{7}]", x, y, swatchColor.R, swatchColor.G, swatchColor.B, testColor.R, testColor.G, testColor.B);
 
                WriteLog(LogVerbosity.Normal, "Failed to find left/right edges for potential swatch of color {2}, {3}, {4} at ({0}, {1}) [failed color = {5},{6},{7}]", x, y, swatchColor.R, swatchColor.G, swatchColor.B, testColor.R, testColor.G, testColor.B);
 
                return false;
 
            }
 
            for (int xOff = 1; xOff < (swatchSolidWidth - 1); ++xOff)
 
            for (int xOff = _pixelMultiplier; xOff < (swatchSolidWidth - _pixelMultiplier); ++xOff)
 
            {
 
                result &= pixels.DoesPixelMatch(swatchSolidLeftX + xOff, swatchSolidTopY, ColorMatcher.IsMatch);
...
 
@@ -296,5 +261,5 @@ namespace DesertPaintCodex.Services
 
            if (!result)
 
            {
 
                WriteLog(LogVerbosity.Normal, "Failed to match upper/lower edges for potential swatch of color {2}, {3}, {4} at {0}, {1} [failed color = {5},{6},{7}]", x, y, swatchColor.R, swatchColor.G, swatchColor.B, testColor.R, testColor.G, testColor.B);
 
                WriteLog(LogVerbosity.Normal, "Failed to match upper/lower edges for potential swatch of color {2}, {3}, {4} at ({0}, {1}) [failed color = {5},{6},{7}]", x, y, swatchColor.R, swatchColor.G, swatchColor.B, testColor.R, testColor.G, testColor.B);
 
                return false;
 
            }
...
 
@@ -303,7 +268,8 @@ namespace DesertPaintCodex.Services
 
            // test the left edge for dark pixels -- the bottom-most pixel is bright now
 
            int i = 0;
 
            for (i = 1; result && i < _swatchHeight - 1; ++i)
 
            for (i = _pixelMultiplier; result && i < _swatchHeight - _pixelMultiplier; ++i)
 
            {
 
                result &= pixels.DoesPixelMatch(x, y + i, PixelColor.IsDark);
 
                if (!result) break;
 
            }
 
            if (!result)
...
 
@@ -314,8 +280,8 @@ namespace DesertPaintCodex.Services
 
            }
 

	
 
            // test the dark top border and for papyrus above and below the swatch
 
            // test the dark top border and for background above and below the swatch
 
            bool borderError = false;
 
            int papyErrorCount = 0;
 
            for (i = 0; result && (i < _swatchWidth - 1); ++i)
 
            int bgErrorCount = 0;
 
            for (i = 0; result && (i < _swatchWidth - _pixelMultiplier); ++i)
 
            {
 
                bool isBorder = pixels.DoesPixelMatch(x + i, y, PixelColor.IsDark);
...
 
@@ -327,35 +293,35 @@ namespace DesertPaintCodex.Services
 
                }
 

	
 
                // Checking along the top of the swatch for papyrus
 
                // Checking along the top of the swatch for background
 
                // The row just above is shaded, so check 2 above
 
                if (y > 1)
 
                {
 
                    bool isPapyrus = pixels.DoesPixelMatch(x + i, y - 2, PixelColor.IsPapyrus);
 
                    papyErrorCount += isPapyrus ? 0 : 1;
 
                    bool isUiBackground = pixels.DoesPixelMatch(x + i, y - _swatchTopBorder, PixelColor.IsUiBackground);
 
                    bgErrorCount += isUiBackground ? 0 : 1;
 

	
 
                }
 
                else
 
                {
 
                    ++papyErrorCount;
 
                    ++bgErrorCount;
 
                }
 

	
 
                // Checking along the bottom of the swatch for papyrus
 
                // Checking along the bottom of the swatch for background
 
                if (y < pixels.Height)
 
                {
 
                    bool isPapyrus = pixels.DoesPixelMatch(x + i, y + _swatchHeight, PixelColor.IsPapyrus);
 
                    papyErrorCount += isPapyrus ? 0 : 1;
 
                    bool isUiBackground = pixels.DoesPixelMatch(x + i, y + _swatchHeight, PixelColor.IsUiBackground);
 
                    bgErrorCount += isUiBackground ? 0 : 1;
 
                }
 
                else
 
                {
 
                    ++papyErrorCount;
 
                    ++bgErrorCount;
 
                }
 
            }
 

	
 
            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))))
 
            result &= (bgErrorCount < (_swatchWidth / 20)); // allow up to 5% error rate checking for background texture, because this seems to be inconsistent
 
            if (!result && ((i > (_swatchWidth * 0.8)) || (bgErrorCount >= (_swatchWidth / 20))))
 
            {
 
                if (!borderError && (papyErrorCount < _swatchWidth))
 
                if (!borderError && (bgErrorCount < _swatchWidth))
 
                {
 
                    WriteLog(LogVerbosity.Normal, "Found a potential swatch candidate of width {0} at {1},{2} that had {3} failures matching papyrus texture", i, x, y, papyErrorCount);
 
                    WriteLog(LogVerbosity.Normal, "Found a potential swatch candidate of width {0} at {1},{2} that had {3} failures matching background color", i, x, y, bgErrorCount);
 
                }
 
            }
...
 
@@ -367,10 +333,10 @@ namespace DesertPaintCodex.Services
 
        {
 
            // Check 4 corners of solid area and left/right solid bar areas
 
            bool foundSwatch = IsPossibleSwatchUpperLeft(pixels, x, y); // ((pixel_r < 0x46) && (pixel_g < 0x46) && (pixel_b < 0x46));
 
            bool foundSwatch = IsPossibleSwatchUpperLeft(pixels, x, y);
 
            if (foundSwatch)
 
            {
 
                WriteLog(LogVerbosity.Normal, "Found probable swatch at {0},{1} - checking border slices", x, y);
 
                int borderXOffset = 0;
 
                for (borderXOffset = 2; foundSwatch && (borderXOffset < _swatchTestWidth); ++borderXOffset)
 
                for (borderXOffset = _swatchLeftBorder; foundSwatch && (borderXOffset < _swatchTestWidth); ++borderXOffset)
 
                {
 
                    foundSwatch &= IsPossibleSwatchSlice(pixels, x + borderXOffset, y);
...
 
@@ -389,15 +355,25 @@ namespace DesertPaintCodex.Services
 
            }
 

	
 
            if (!foundSwatch) return false;
 
            if (!foundSwatch)
 
            {
 
                if (!_lockedSwatchWidth)
 
                {
 
                    // Reset our guess at swatch width.
 
                    _swatchWidth = MinSwatchWidth;
 
                }
 
                return false;
 
            }
 
            
 
            // WE FOUND THE SWATCH!
 
            // Now we know where the color bars are.
 
            _lockedSwatchWidth = true;
 
            int redPixelCount = pixels.LengthOfColorAt(x, y + _redBarSpacing, PixelColor.IsRed);
 
            reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)_colorBarWidth);
 
            reactedColor.Red = (byte)Math.Round(redPixelCount * 255f / _swatchWidth);
 

	
 
            int greenPixelCount = pixels.LengthOfColorAt(x, y + _greenBarSpacing, PixelColor.IsGreen);
 
            reactedColor.Green = (byte)Math.Round((float)greenPixelCount * 255f / (float)_colorBarWidth);
 
            reactedColor.Green = (byte)Math.Round(greenPixelCount * 255f / _swatchWidth);
 

	
 
            int bluePixelCount = pixels.LengthOfColorAt(x, y + _blueBarSpacing, PixelColor.IsBlue);
 
            reactedColor.Blue = (byte)Math.Round((float)bluePixelCount * 255f / (float)_colorBarWidth);
 
            reactedColor.Blue = (byte)Math.Round(bluePixelCount * 255f / _swatchWidth);
 
            WriteLog(LogVerbosity.Low, "Found the color swatch at {0}, {1}. Color={2} Red={3}px Green={4}px Blue={5}px", x, y, reactedColor, redPixelCount, greenPixelCount, bluePixelCount);
 
            return true;
...
 
@@ -422,5 +398,5 @@ namespace DesertPaintCodex.Services
 
            }
 
            
 
            _targetBitmap.Save(Path.Combine(ProfileManager.CurrentProfile?.Directory ?? "", "screenshot.png"), ImageFormat.Png);
 
            // _targetBitmap.Save(Path.Combine(ProfileManager.CurrentProfile?.Directory ?? "", "screenshot.png"), ImageFormat.Png);
 

	
 
            Pixels pixels = new(_targetBitmap, _pixelMultiplier);
...
 
@@ -443,5 +419,5 @@ namespace DesertPaintCodex.Services
 
            _logVerbosity = (LogVerbosity)verbosityIdx;
 
            
 
            int patchTestSize = ((_swatchHeight - 5) / 2) - 1;
 
            int patchTestSize = ((_swatchHeight - _swatchTopBorder - _swatchBottomBorder) / 2) - 1;
 

	
 
            SettingsService.Get("ScanArea.Min.X", out var startX, 0);
...
 
@@ -452,8 +428,8 @@ namespace DesertPaintCodex.Services
 
            startX = Math.Max(2, Math.Min(startX, _targetBitmap.Width - 2));
 
            startY = Math.Max(2, Math.Min(startY, _targetBitmap.Height - 2));
 
            endX = Math.Min(_targetBitmap.Width - 2, Math.Max(2, endX)) - _colorBarWidth; //  + patchTestSize;
 
            endX = Math.Min(_targetBitmap.Width  - 2, Math.Max(2, endX)) - _minSwatchWidth; //  + patchTestSize;
 
            endY = Math.Min(_targetBitmap.Height - 2, Math.Max(2, endY)) - (_blueBarSpacing + 10); // + patchTestSize;
 

	
 
            Debug.WriteLine("startX: " + startX + " endX: " + endX + " startY: " + startY + " endY: " + endY);
 
            Debug.WriteLine("startX: " + startX + " endX: " + endX + " startY: " + startY + " endY: " + endY + " with patch test size of " + patchTestSize);
 
            
 
            int xSpan = endX - startX;
...
 
@@ -475,7 +451,7 @@ namespace DesertPaintCodex.Services
 

	
 
                    WriteLog(LogVerbosity.Excessive, "Found a solid patch of {2},{3},{4} at {0}, {1}", roughX, roughY, patchColor.R, patchColor.G, patchColor.B);
 
                    for (int x = Math.Max(0, roughX - patchTestSize); x < roughX; ++x)
 
                    for (int x = Math.Max(0, roughX - patchTestSize - _swatchLeftBorder + _pixelMultiplier); x < roughX; ++x)
 
                    {
 
                        for (int y = Math.Max(0, roughY - patchTestSize); y < roughY; ++y)
 
                        for (int y = Math.Max(0, roughY - patchTestSize - _swatchTopBorder + _pixelMultiplier); y < roughY; ++y)
 
                        {
 
                            WriteLog(LogVerbosity.Excessive, "Searching for potential swatch at {0},{1} after found square at {2},{3}", x, y, roughX, roughY);
...
 
@@ -514,5 +490,4 @@ namespace DesertPaintCodex.Services
 
        }
 

	
 

	
 
        public static Reaction CalculateReaction(PaintColor expectedColor, PaintColor reactedColor)
 
        {
Services/SettingKey.cs
Show inline comments
...
 
@@ -3,5 +3,4 @@ namespace DesertPaintCodex.Services
 
    public static class SettingKey
 
    {
 
        public const string InterfaceSize   = "interfacesize";
 
        public const string PixelMultiplier = "pixelmultiplier";
 
        public const string ScreenIndex     = "screenindex";
Util/Constants.cs
Show inline comments
...
 
@@ -5,5 +5,4 @@ namespace DesertPaintCodex.Util
 
    public static class Constants
 
    {
 
        public const InterfaceSize DefaultInterfaceSize = InterfaceSize.Small;
 
        public static int DefaultPixelMultiplier = 1;
 
        public static int DefaultScreenWidth = 1920;
...
 
@@ -30,8 +29,4 @@ namespace DesertPaintCodex.Util
 
            
 
        }
 
            
 
            
 
            
 

	
 
    }
 
}
...
 
\ No newline at end of file
Util/PixelColor.cs
Show inline comments
...
 
@@ -7,5 +7,5 @@ namespace DesertPaintCodex.Util
 
    public class PixelColor
 
    {
 
        private const int ColorTolerance = 3;
 
        private const int ColorTolerance = 2;
 
        
 
        public static bool IsMatch(Color colorA, Color colorB)
...
 
@@ -21,28 +21,20 @@ namespace DesertPaintCodex.Util
 
        }
 

	
 
        public static bool IsPapyrus(Color color)
 
        public static bool IsUiBackground(Color color)
 
        {
 
            // red between 208 and 244
 
            // 240 and 255
 
            // green between 192 and 237
 
            // 223 and 250
 
            // blue between 145 and 205
 
            // 178 and 232
 
            //return ((r > 0xD0) && (g >= 0xC0) && (b >= 0x91)) &&
 
            //       ((r < 0xF4) && (g <= 0xED) && (b <= 0xCD));
 
            return ((color.R >= 0xD0) && (color.R <= 0xFF) && (color.G >= 0xC0) && (color.G <= 0xFA) && (color.B >= 0x91) && (color.B <= 0xE8));
 
            return (color.R is >= 0x27 and <= 0x2F) && (color.G is >= 0x3B and <= 0x42) && (color.B is >= 0x41 and <= 0x48);
 
        }
 

	
 
        public static bool IsRed(Color color)
 
        {
 
            return (color.R > 0x9F) && (color.G < 0x70) && (color.B < 0x70);
 
            return (color.R > 0x9D) && (color.G < 0x60) && (color.B < 0x60);
 
        }
 
        public static bool IsGreen(Color color)
 
        {
 
            return (color.R < 0x70) && (color.G > 0x9F) && (color.B < 0x70);
 
            return (color.R < 0x60) && (color.G > 0x9D) && (color.B < 0x60);
 
        }
 
        public static bool IsBlue(Color color)
 
        {
 
            return (color.R < 0x70) && (color.G < 0x70) && (color.B > 0x9F);
 
            return (color.R < 0x60) && (color.G < 0x60) && (color.B > 0x9D);
 
        }
 

	
ViewModels/ExperimentLogViewModel.cs
Show inline comments
...
 
@@ -61,4 +61,5 @@ namespace DesertPaintCodex.ViewModels
 
            TestView.SaveReaction.Subscribe(_ => OnSaveReaction());
 
            TestView.ClearReaction.Subscribe(_ => OnClearReaction());
 
            TestView.FinalizeTestResults.Subscribe(_ => OnReactionResults());
 
        }
 

	
...
 
@@ -71,4 +72,6 @@ namespace DesertPaintCodex.ViewModels
 
        }
 

	
 
        #region Command Handlers
 

	
 
        private void OnSaveReaction()
 
        {
...
 
@@ -113,4 +116,22 @@ namespace DesertPaintCodex.ViewModels
 
        }
 

	
 
        private void OnReactionResults()
 
        {
 
            ReactionTest? test = null;
 
            int selectedTest = SelectedRemainingTest;
 
            if (selectedTest >= 0)
 
            {
 
                test = RemainingTests[selectedTest];
 
            }
 
            ReactionTestService.PopulateRemainingTests(RemainingTests);
 
            if (test != null)
 
            {
 
                int newIndex = RemainingTests.IndexOf(test);
 
                SelectedRemainingTest = newIndex;
 
            }
 
        }
 
        
 
        #endregion
 

	
 
        private static void InsertTestIntoList(ReactionTest test, IList<ReactionTest> list)
 
        {
ViewModels/ReactionTestViewModel.cs
Show inline comments
...
 
@@ -43,4 +43,5 @@ namespace DesertPaintCodex.ViewModels
 
            SaveReaction = ReactiveCommand.Create(() => ReactionTest.SaveReaction());
 
            ClearReaction = ReactiveCommand.Create(() => ReactionTest.ClearReaction());
 
            FinalizeTestResults = ReactiveCommand.Create(Test);
 
        }
 

	
...
 
@@ -76,4 +77,5 @@ namespace DesertPaintCodex.ViewModels
 
            {
 
                await ReactionTest.StartScan();
 
                await FinalizeTestResults.Execute();
 
            }
 
            catch (OperationCanceledException)
...
 
@@ -103,8 +105,14 @@ namespace DesertPaintCodex.ViewModels
 
        }
 
        
 
        private void Test()
 
        {
 
            Debug.WriteLine("Test complete");
 
        }
 
        
 
        public Interaction<ScreenSettingsViewModel, Unit> ShowScreenSettingsDialog { get; }
 

	
 
        public ReactiveCommand<Unit, Unit> ClearReaction { get; }
 
        public ReactiveCommand<Unit, Unit> SaveReaction { get; }
 
        public ReactiveCommand<Unit, Unit> FinalizeTestResults { get; }
 
    }
 
}
...
 
\ No newline at end of file
ViewModels/ScreenSettingsViewModel.cs
Show inline comments
 

 
using Avalonia.Controls;
 
using Avalonia.Platform;
 
using DesertPaintCodex.Models;
...
 
@@ -7,5 +6,4 @@ using ReactiveUI;
 
using System.Collections.Generic;
 
using System.Collections.ObjectModel;
 
using System.Diagnostics;
 
using System.Reactive;
 
using Avalonia;
...
 
@@ -17,10 +15,6 @@ namespace DesertPaintCodex.ViewModels
 
    public class ScreenSettingsViewModel : ViewModelBase
 
    {
 
        public ObservableCollection<string> InterfaceSizes { get; } = new();
 
        public ObservableCollection<ScreenMetrics> Screens { get; } = new();
 

	
 
        private int _selectedInterfaceSize;
 
        public int SelectedInterfaceSize { get => _selectedInterfaceSize; private set => this.RaiseAndSetIfChanged(ref _selectedInterfaceSize, value); }
 

	
 
        private int _pixeMultiplier;
 
        public int PixelMultiplier { get => _pixeMultiplier; private set => this.RaiseAndSetIfChanged(ref _pixeMultiplier, value); }
...
 
@@ -34,9 +28,4 @@ namespace DesertPaintCodex.ViewModels
 
            {
 
                IScreenImpl screen = desktop.MainWindow.PlatformImpl.Screen;
 
                for (int i = 0; i < (int)InterfaceSize.Count; i++)
 
                {
 
                    InterfaceSizes.Add(((InterfaceSize)i).ToString());
 
                }
 

	
 
                IReadOnlyList<Screen> screens = screen.AllScreens;
 

	
...
 
@@ -46,5 +35,4 @@ namespace DesertPaintCodex.ViewModels
 
                }
 
            
 
                SettingsService.Get(SettingKey.InterfaceSize,   out _selectedInterfaceSize, (int)Constants.DefaultInterfaceSize);
 
                SettingsService.Get(SettingKey.PixelMultiplier, out _pixeMultiplier, Constants.DefaultPixelMultiplier);
 
                SettingsService.Get(SettingKey.ScreenIndex,     out _screenIndex, 0);
...
 
@@ -53,5 +41,4 @@ namespace DesertPaintCodex.ViewModels
 

	
 
                Save = ReactiveCommand.Create(() => {
 
                    SettingsService.Set(SettingKey.InterfaceSize,   _selectedInterfaceSize);
 
                    SettingsService.Set(SettingKey.PixelMultiplier, _pixeMultiplier);
 
                    SettingsService.Set(SettingKey.ScreenIndex,     _screenIndex);
...
 
@@ -69,14 +56,7 @@ namespace DesertPaintCodex.ViewModels
 
            {
 
                // Placeholder stuff.
 
                
 
                for (int i = 0; i < (int)InterfaceSize.Count; i++)
 
                {
 
                    InterfaceSizes.Add(((InterfaceSize)i).ToString());
 
                }
 
            
 
                Screens.Add(new ScreenMetrics(new Avalonia.PixelRect(0, 0, 1920, 1080), true));
 
                Screens.Add(new ScreenMetrics(new Avalonia.PixelRect(1920, 0, 1920, 1080), false));
 
            
 
                SelectedInterfaceSize = 0;
 
                PixelMultiplier       = 1;
 
                ScreenIndex           = 0;
ViewModels/SelectProfileViewModel.cs
Show inline comments
...
 
@@ -2,6 +2,9 @@
 
using ReactiveUI;
 
using System.Collections.Generic;
 
using System.Collections.ObjectModel;
 
using System.Diagnostics;
 
using DesertPaintCodex.Models;
 
using DesertPaintCodex.Services;
 
using DynamicData;
 

	
 
namespace DesertPaintCodex.ViewModels
...
 
@@ -9,5 +12,5 @@ namespace DesertPaintCodex.ViewModels
 
    public class SelectProfileViewModel : ViewModelBase
 
    {
 
        public List<string> Profiles { get; private set; }
 
        public ObservableCollection<string> Profiles { get; } = new();
 

	
 
        private string? _selectedItem;
...
 
@@ -16,5 +19,5 @@ namespace DesertPaintCodex.ViewModels
 
        public SelectProfileViewModel()
 
        {
 
            Profiles = ProfileManager.GetProfileList();
 
            Profiles.AddRange(ProfileManager.GetProfileList());
 

	
 
            var okEnabled = this.WhenAnyValue(
ViewModels/WelcomeViewModel.cs
Show inline comments
...
 
@@ -31,6 +31,5 @@ namespace DesertPaintCodex.ViewModels
 
        private void ShowSelectProfile()
 
        {
 
            if (_selectProfileVM == null)
 
            {
 

	
 
                _selectProfileVM = new SelectProfileViewModel();
 
                _selectProfileVM.NewProfile.Subscribe(_ => ShowCreateProfile());
...
 
@@ -38,5 +37,4 @@ namespace DesertPaintCodex.ViewModels
 
                    .Take(1)
 
                    .InvokeCommand(FinishWelcome);
 
            }
 

	
 
            ProfileActivity = _selectProfileVM;
...
 
@@ -45,9 +43,6 @@ namespace DesertPaintCodex.ViewModels
 
        private void ShowCreateProfile()
 
        {
 
            if (_createProfileVM == null)
 
            {
 
                _createProfileVM = new CreateProfileViewModel();
 
                Observable.Merge(_createProfileVM.Ok, _createProfileVM.Cancel).Subscribe(_ => ShowSelectProfile());
 
            }
 

	
 
            ProfileActivity = _createProfileVM;
Views/ExperimentLogView.axaml
Show inline comments
...
 
@@ -64,8 +64,12 @@
 
        <TabControl DockPanel.Dock="Left" Width="318" Classes="ListFilter" SelectedIndex="{Binding SelectedList}">
 
            <TabItem Header="Pending Tests">
 
                <ListBox Items="{Binding RemainingTests}" SelectedIndex="{Binding SelectedRemainingTest}" />
 
                <ListBox Name="RemainingList"
 
                         Items="{Binding RemainingTests}"
 
                         SelectedIndex="{Binding SelectedRemainingTest}"
 
                         SelectionChanged="RemainingSelectionChanged"/>
 
            </TabItem>
 
            <TabItem Header="Completed Tests">
 
                <ListBox Items="{Binding CompletedTests}" SelectedIndex="{Binding SelectedCompletedTest}" />
 
                <ListBox Items="{Binding CompletedTests}"
 
                         SelectedIndex="{Binding SelectedCompletedTest}" />
 
            </TabItem>
 
        </TabControl>
Views/ExperimentLogView.axaml.cs
Show inline comments
 
using Avalonia.Markup.Xaml;
 
using Avalonia.Controls;
 
using Avalonia.Markup.Xaml;
 
using Avalonia.ReactiveUI;
 
using DesertPaintCodex.ViewModels;
...
 
@@ -8,7 +9,11 @@ namespace DesertPaintCodex.Views
 
    public class ExperimentLogView : ReactiveUserControl<ExperimentLogViewModel>
 
    {
 
        private readonly ListBox? _remainingList;
 
        
 
        public ExperimentLogView()
 
        {
 
            InitializeComponent();
 

	
 
            _remainingList = this.FindControl<ListBox>("RemainingList");
 
        }
 

	
...
 
@@ -17,4 +22,15 @@ namespace DesertPaintCodex.Views
 
            AvaloniaXamlLoader.Load(this);
 
        }
 
        
 
        private void RemainingSelectionChanged(object? sender, SelectionChangedEventArgs e)
 
        {
 
            if (_remainingList == null) return;
 
            
 
            foreach (var item in e.AddedItems)
 
            {
 
                _remainingList.ScrollIntoView(item);
 
                return;
 
    }
 
}
 
    }
 
}
Views/ScreenSettingsView.axaml
Show inline comments
...
 
@@ -25,16 +25,4 @@
 
    
 
    <Grid DockPanel.Dock="Bottom" ColumnDefinitions="*,12,80,12,24" RowDefinitions="Auto,30,Auto" Margin="0, 0, 0, 30">
 
      <TextBlock VerticalAlignment="Center" TextWrapping="Wrap" TextAlignment="Right" Grid.Row="0" Grid.Column="0">Game UI Size</TextBlock>
 
      <ComboBox Items="{Binding InterfaceSizes}" SelectedIndex="{Binding SelectedInterfaceSize, Mode=TwoWay}" Grid.Row="0" Grid.Column="2" /> 
 
      <Border Classes="Help" Grid.Row="0" Grid.Column="4">
 
        <TextBlock>?</TextBlock>
 
        <ToolTip.Tip>
 
          <StackPanel Margin="5" Spacing="20" Orientation="Vertical">
 
            <TextBlock Classes="BlockHeader">Game UI Size</TextBlock>
 
            <TextBlock TextWrapping="Wrap">[Coming Soon]</TextBlock>
 
          </StackPanel>
 
        </ToolTip.Tip>
 
      </Border>
 
      
 
      <TextBlock VerticalAlignment="Center" TextWrapping="Wrap" TextAlignment="Right" Grid.Row="2" Grid.Column="0">
 
        Screen pixels to game pixels:
...
 
@@ -46,8 +34,9 @@
 
          <StackPanel Margin="5" Spacing="20" Orientation="Vertical">
 
            <TextBlock Classes="BlockHeader">Screen Pixels to Game Pixels</TextBlock>
 
            <TextBlock TextWrapping="Wrap">[Coming Soon]</TextBlock>
 
            <TextBlock TextWrapping="Wrap">If your screen is scaled at the system-level, you may need to adjust this number to measure UI elements correctly.</TextBlock>
 
          </StackPanel>
 
        </ToolTip.Tip>
 
      </Border></Grid>
 
      </Border>
 
    </Grid>
 

	
 
    <ListBox Items="{Binding Screens}" SelectedIndex="{Binding ScreenIndex, Mode=TwoWay}" Margin="0,4,0,20">
0 comments (0 inline, 0 general)