Changeset - cbcdc45e1b92
[Not reviewed]
default
0 1 0
Jason Maltzen - 5 years ago 2019-11-02 18:43:43
jason@hiddenachievement.com
Remove a debug message.
1 file changed with 1 insertions and 1 deletions:
0 comments (0 inline, 0 general)
ReactionRecorder.cs
Show inline comments
...
 
@@ -134,573 +134,573 @@ namespace DesertPaintLab
 
        public int SwatchY { get { return lastSwatchY; } }
 

	
 
        private class PixelColor
 
        {
 
            public byte r;
 
            public byte g;
 
            public byte b;
 

	
 
            public bool IsMatch(PixelColor other)
 
            {
 
                return ((Math.Abs(r - other.r) <= COLOR_TOLERANCE) &&
 
                    (Math.Abs(g - other.g) <= COLOR_TOLERANCE) &&
 
                    (Math.Abs(b - other.b) <= COLOR_TOLERANCE));
 
            }
 

	
 
            public static bool IsDark(PixelColor color)
 
            {
 
                return (color.r < 0x47) && (color.g < 0x47) && (color.b < 0x47);
 
            }
 

	
 
            public static bool IsPapyrus(PixelColor color)
 
            {
 
                // red between 208 and 244
 
                // 240 and 255
 
                // green between 192 and 237
 
                // 223 and 248
 
                // blue between 145 and 205
 
                // 178 and 232
 
                //return ((r > 0xD0) && (g >= 0xC0) && (b >= 0x91)) &&
 
                //       ((r < 0xF4) && (g <= 0xED) && (b <= 0xCD));
 
                return ((color.r >= 0xF0) && (color.r <= 0xFF) && (color.g >= 0xDF) && (color.g <= 0xF8) && (color.b >= 0xB2) && (color.b <= 0xE8));
 
            }
 

	
 
            public static bool IsRed(PixelColor color)
 
            {
 
                return (color.r > 0x9F) && (color.g < 0x62) && (color.b < 0x62);
 
            }
 
            public static bool IsGreen(PixelColor color)
 
            {
 
                return (color.r < 0x62) && (color.g > 0x9F) && (color.b < 0x62);
 
            }
 
            public static bool IsBlue(PixelColor color)
 
            {
 
                return (color.r < 0x62) && (color.g < 0x62) && (color.b > 0x9F);
 
            }
 
        }
 

	
 
        unsafe private class Pixels
 
        {
 
            public byte* pixBytes;
 
            public int width;
 
            public int height;
 
            public int stride;
 
            public int pixelMultiplier;
 

	
 
            private PixelColor _tempColor = new PixelColor();
 
            private PixelColor _tempColor2 = new PixelColor();
 

	
 
            public int ComputeOffset(int x, int y)
 
            {
 
                return (y * pixelMultiplier * stride) + (x * pixelMultiplier * 3);
 
            }
 

	
 
            public int UpdateOffset(int offset, int xChange, int yChange)
 
            {
 
                return offset + (yChange * pixelMultiplier * stride) + (xChange * pixelMultiplier * 3);
 
            }
 

	
 
            unsafe public void ColorAt(int offset, ref PixelColor pixel)
 
            {
 
                pixel.r = pixBytes[offset];
 
                pixel.g = pixBytes[offset + 1];
 
                pixel.b = pixBytes[offset + 2];
 
            }
 

	
 
            unsafe public void ColorAt(int x, int y, ref PixelColor pixel)
 
            {
 
                int offset = ComputeOffset(x, y);
 
                ColorAt(offset, ref pixel);
 
            }
 

	
 
            unsafe public bool DoesPixelMatch(int x, int y, Func<PixelColor, bool> matchFunc)
 
            {
 
                int offset = ComputeOffset(x, y);
 
                ColorAt(offset, ref _tempColor);
 
                return matchFunc(_tempColor);
 
            }
 

	
 
            unsafe public bool DoesPixelMatch(int offset, Func<PixelColor, bool> matchFunc)
 
            {
 
                ColorAt(offset, ref _tempColor);
 
                return matchFunc(_tempColor);
 
            }
 

	
 
            // Compute length of horizontal bar starting at x,y using matching function
 
            unsafe public int LengthOfColorAt(int x, int y, Func<PixelColor, bool> matchesColor)
 
            {
 
                int count = 0;
 
                for (int xVal = x; xVal < width; ++xVal)
 
                {
 
                    int offset = ComputeOffset(xVal, y);
 
                    if (!DoesPixelMatch(xVal, y, matchesColor)) break;
 
                    ++count;
 
                }
 
                return count;
 
            }
 

	
 
            unsafe public bool IsSolidPatchAt(int x, int y, int patchWidth, int patchHeight)
 
            {
 
                if ((x + patchWidth >= width) || (y + patchHeight >= height)) return false;
 
                ColorAt(x, y, ref _tempColor2);
 
                bool ok = true;
 
                ok &= DoesPixelMatch(x + patchWidth - 1, y, _tempColor2.IsMatch);
 
                ok &= DoesPixelMatch(x, y + patchHeight - 1, _tempColor2.IsMatch);
 
                ok &= DoesPixelMatch(x + patchWidth - 1, y + patchHeight - 1, _tempColor2.IsMatch);
 
                for (int xOff = 1; ok && (xOff < patchWidth - 1); ++xOff)
 
                {
 
                    ok &= DoesPixelMatch(x + xOff, y, _tempColor2.IsMatch);
 
                    ok &= DoesPixelMatch(x + xOff, y + patchHeight - 1, _tempColor2.IsMatch);
 
                }
 
                for (int yOff = 1; ok && (yOff < patchHeight - 1); ++yOff)
 
                {
 
                    ok &= DoesPixelMatch(x, y + yOff, _tempColor2.IsMatch);
 
                    ok &= DoesPixelMatch(x + patchWidth - 1, y + yOff, _tempColor2.IsMatch);
 
                }
 
                for (int yOff = 1; ok && (yOff < patchHeight - 1); ++yOff)
 
                {
 
                    for (int xOff = 1; ok && (xOff < patchWidth - 1); ++xOff)
 
                    {
 
                        ok &= DoesPixelMatch(x + xOff, y + yOff, _tempColor2.IsMatch);
 
                    }
 
                }
 
                return ok;
 
            }
 
        }
 

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

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

	
 
        public delegate void ReactionRecordedHandler(Reagent reagent1, Reagent reagent2, Reaction reaction);
 
        public ReactionRecordedHandler OnReactionRecorded;
 

	
 
        public ReactionRecorder()
 
        {
 
            pixelMultiplier = 1;
 
            interfaceSize = DEFAULT_INTERFACE_SIZE;
 
            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;
 
        }
 

	
 
        public ReactionRecorder(int pixelMultiplier)
 
        {
 
            this.pixelMultiplier = pixelMultiplier;
 
            this.interfaceSize = DEFAULT_INTERFACE_SIZE;
 
            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;
 
        }
 

	
 
        public ReactionRecorder(int pixelMultiplier, InterfaceSize interfaceSize)
 
        {
 
            this.pixelMultiplier = pixelMultiplier;
 
            this.interfaceSize = interfaceSize;
 
            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;
 
        }
 

	
 
        public void SetPixelMultiplier(int pixelMultiplier)
 
        {
 
            this.pixelMultiplier = pixelMultiplier;
 

	
 
            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;
 
        }
 

	
 
        public void SetInterfaceSize(InterfaceSize interfaceSize)
 
        {
 
            this.interfaceSize = interfaceSize;
 

	
 
            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;
 
        }
 

	
 
        unsafe private bool IsPossibleSwatchSlice(Pixels pixels, int x, int y)
 
        {
 
            int testPixelStart = pixels.ComputeOffset(x, y);
 
            PixelColor color = new PixelColor();
 
            pixels.ColorAt(x, y, ref color);
 

	
 
            bool isDarkPixel = false;
 
            //bool isPapyAbove = false;
 
            //bool isPapyBelow = false;
 

	
 
            // 1.) Check if the top pixel is a dark pixel.
 
            isDarkPixel = PixelColor.IsDark(color);
 
            
 
            //// 2.) Check the pixel above it to see if it's from the papy texture.
 
            //int otherPixelStart = testPixelStart - stride;
 
            //isPapyAbove = ((otherPixelStart >= 0) &&
 
            //    IsPapyTexture(pixBytes[otherPixelStart++], pixBytes[otherPixelStart++], pixBytes[otherPixelStart]));
 

	
 
            //// 3.) Check the pixel below where the swatch should be to see if it's also from the papy texture.
 
            //otherPixelStart = testPixelStart + (stride * swatchHeight);
 
            //isPapyBelow = (IsPapyTexture(pixBytes[otherPixelStart++], pixBytes[otherPixelStart++], pixBytes[otherPixelStart]));
 

	
 
            //bool result = isDarkPixel && isPapyAbove && isPapyBelow;
 
            bool result = isDarkPixel;
 

	
 
            // grab the swatch color
 
            // 2 down from top border
 
            pixels.ColorAt(x, y + 2, ref color);
 

	
 
            // scan the column from 2 below the top to 3 above the bottom to ensure the color matches
 
            for (int i = 2; result && (i < (swatchHeight-3)); ++i)
 
            {
 
                result &= pixels.DoesPixelMatch(x, y + i, color.IsMatch);
 
            }
 

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

	
 
            return result;
 
        }
 

	
 
        unsafe private bool IsPossibleSwatchUpperLeft(Pixels pixels, int x, int y)
 
        {
 
            int testPixelStart = pixels.ComputeOffset(x, y);
 

	
 
            if (testPixelStart < pixels.stride)
 
            {
 
                return false;
 
            }
 

	
 
            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 swatchSolidRightX = swatchSolidLeftX + swatchSolidWidth - 1;
 
            int swatchSolidBottomY = swatchSolidTopY + swatchSolidHeight - 1;
 

	
 
            PixelColor swatchColor = new PixelColor();
 
            pixels.ColorAt(swatchSolidLeftX, swatchSolidTopY, ref swatchColor);
 

	
 
            // Check the other 3 corners of the swatch size for color match
 
            PixelColor testColor = new PixelColor();
 
            result &= pixels.DoesPixelMatch(swatchSolidRightX, swatchSolidTopY, swatchColor.IsMatch);
 
            result &= pixels.DoesPixelMatch(swatchSolidLeftX, swatchSolidBottomY, swatchColor.IsMatch);
 
            result &= pixels.DoesPixelMatch(swatchSolidRightX, swatchSolidBottomY, swatchColor.IsMatch);
 

	
 
            if (!result)
 
            {
 
                // Box corners test failed
 
                // WriteLog("Failed to find left edge for potential swatch of color {2}, {3}, {4} at {0}, {1}", x, y, swatch_r, swatch_g, swatch_b);
 
                return false;
 
            }
 

	
 
            // scan down the right and left sides
 
            for (int yOff = 1; yOff < (swatchSolidHeight - 1); ++yOff)
 
            {
 
                result &= pixels.DoesPixelMatch(swatchSolidLeftX, swatchSolidTopY + yOff, swatchColor.IsMatch);
 
                if (!result)
 
                {
 
                    pixels.ColorAt(swatchSolidLeftX, swatchSolidTopY + yOff, ref testColor);
 
                    break;
 
                }
 
                result &= pixels.DoesPixelMatch(swatchSolidRightX, swatchSolidTopY + yOff, swatchColor.IsMatch);
 
                if (!result)
 
                {
 
                    pixels.ColorAt(swatchSolidRightX, swatchSolidTopY + yOff, ref testColor);
 
                }
 
            }
 
            if (!result)
 
            {
 
                WriteLog("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)
 
            {
 
                result &= pixels.DoesPixelMatch(swatchSolidLeftX + xOff, swatchSolidTopY, swatchColor.IsMatch);
 
                if (!result)
 
                {
 
                    pixels.ColorAt(swatchSolidLeftX + xOff, swatchSolidTopY, ref testColor);
 
                    break;
 
                }
 
                result &= pixels.DoesPixelMatch(swatchSolidLeftX + xOff, swatchSolidBottomY, swatchColor.IsMatch);
 
                if (!result)
 
                {
 
                    pixels.ColorAt(swatchSolidLeftX + xOff, swatchSolidBottomY, ref testColor);
 
                    break;
 
                }
 
            }
 
            if (!result)
 
            {
 
                WriteLog("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;
 
            }
 

	
 

	
 
            // 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)
 
            {
 
                result &= pixels.DoesPixelMatch(x, y + i, PixelColor.IsDark);
 
            }
 
            if (!result)
 
            {
 
                // No dark border on the left side
 
                WriteLog("Failed to find left border for potential swatch of color {2}, {3}, {4} at {0}, {1}", x, y, swatchColor.r, swatchColor.g, swatchColor.b);
 
                return false;
 
            }
 

	
 
            // test the dark top border and for papyrus above and below the swatch
 
            bool borderError = false;
 
            int papyErrorCount = 0;
 
            for (i = 0; result && (i < swatchWidth); ++i)
 
            {
 
                bool isBorder = pixels.DoesPixelMatch(x + i, y, PixelColor.IsDark);
 
                result &= isBorder;
 
                if (!isBorder)
 
                {
 
                    borderError = true;
 
                }
 

	
 
                // Checking along the top of the swatch for papyrus
 
                // 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;
 

	
 
                }
 
                else
 
                {
 
                    ++papyErrorCount;
 
                }
 

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

	
 
            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))))
 
            {
 
                if (!borderError && (papyErrorCount < swatchWidth))
 
                {
 
                    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 private bool TestPosition(int x, int y, Pixels pixels, ref PaintColor reactedColor, ref int redPixelStart)
 
        {
 
            PixelColor pixelColor = new PixelColor();
 

	
 
            // 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));
 
            if (foundSwatch)
 
            {
 
                int borderXOffset = 0;
 
                for (borderXOffset = 2; foundSwatch && (borderXOffset < swatchTestWidth); ++borderXOffset)
 
                {
 
                    foundSwatch &= IsPossibleSwatchSlice(pixels, x + borderXOffset, y);
 
                    foundSwatch &= IsPossibleSwatchSlice(pixels, x + swatchWidth - borderXOffset, y);
 
                }
 
            }
 

	
 
            if (foundSwatch)
 
            {
 
                // WE FOUND THE SWATCH!
 
                // Now we know where the color bars are.
 
                int redPixelCount = pixels.LengthOfColorAt(x, y + redBarSpacing, PixelColor.IsRed);
 
                reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)colorBarWidth);
 

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

	
 
                int bluePixelCount = pixels.LengthOfColorAt(x, y + blueBarSpacing, PixelColor.IsBlue);
 
                reactedColor.Blue = (byte)Math.Round((float)bluePixelCount * 255f / (float)colorBarWidth);
 
                WriteLog("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;
 
            }
 
            return false;
 
        }
 

	
 
        unsafe public bool CaptureReaction(byte* pixBytes, int screenshotWidth, int screenshotHeight, int stride)
 
        {
 
            PaintColor reactedColor = new PaintColor();
 
            int redPixelStart = 0;
 
            ScreenWidth = screenshotWidth;
 
            ScreenHeight = screenshotHeight;
 
            IsCaptured = false;
 
            _recordedColor.Clear();
 

	
 
            Pixels pixels = new Pixels
 
            {
 
                pixBytes = pixBytes,
 
                width = screenshotWidth,
 
                height = screenshotHeight,
 
                stride = stride,
 
                pixelMultiplier = pixelMultiplier
 
            };
 
            IsCaptured = false;
 
            if (!firstRun)
 
            {
 
                // If this is not the first run, let's check the last location, to see if the UI is still there.
 
                if (TestPosition(lastSwatchX, lastSwatchY, pixels, ref reactedColor, ref redPixelStart))
 
                {
 
                    IsCaptured = true;
 
                    RedBarX = (redPixelStart % stride) / 3;
 
                    RedBarY = redPixelStart / stride;
 
                    RecordedColor = reactedColor;
 
                    return true;
 
                }
 
                else
 
                {
 
                    firstRun = true;
 
                }
 
            }
 

	
 
            int startX;
 
            int endX;
 
            int startY;
 
            int endY;
 
            DesertPaintLab.AppSettings.Get("ScanOffsetX", out startX);
 
            DesertPaintLab.AppSettings.Get("ScanOffsetY", out startY);
 
            DesertPaintLab.AppSettings.Get("ScanLimitX", out endX);
 
            DesertPaintLab.AppSettings.Get("ScanLimitY", out endY);
 
            if (endX == 0) endX = screenshotWidth;
 
            if (endY == 0) endY = screenshotHeight;
 

	
 
            int patchTestSize = (swatchHeight / 2) - 1;
 
            PixelColor patchColor = new PixelColor();
 
            for (int roughX = startX; roughX < endX - colorBarWidth - patchTestSize; roughX += patchTestSize)
 
            {
 
                for (int roughY = startY; roughY < (endY - (blueBarSpacing + 10) - patchTestSize  /*53*/); roughY += patchTestSize)
 
                {
 
                    OnCaptureProgress?.Invoke(roughX, roughY);
 
                    if (!pixels.IsSolidPatchAt(roughX, roughY, patchTestSize, patchTestSize)) continue;
 
                    pixels.ColorAt(roughX, roughY, ref patchColor);
 
                    for (X = roughX - patchTestSize; X < roughX; ++X)
 
                    {
 
                        for (Y = roughY - patchTestSize; Y < roughY; ++Y)
 
                        {
 
                            if (TestPosition(X, Y, pixels, ref reactedColor, ref redPixelStart))
 
                            {
 
                                RedBarX = (redPixelStart % stride) / 3;
 
                                RedBarY = redPixelStart / stride;
 
                                RecordedColor = reactedColor;
 
                                lastSwatchX = X;
 
                                lastSwatchY = Y;
 
                                firstRun = false;
 
                                IsCaptured = true;
 
                                return true;
 
                            }
 
                        }
 
                    }
 
                    System.Console.WriteLine("False-positive patch of color {0},{1},{2} at {3},{4}", patchColor.r, patchColor.g, patchColor.b, roughX, roughY);
 
                    //System.Console.WriteLine("False-positive patch of color {0},{1},{2} at {3},{4}", patchColor.r, patchColor.g, patchColor.b, roughX, roughY);
 
                }
 
            }
 
            return false;
 
        }
 

	
 
        public bool RecordReaction(PlayerProfile profile, PaintColor expectedColor, PaintColor reactedColor, Reagent[] reagents)
 
        {
 
            bool saved = false;
 
            int r, g, b;
 
            if (reagents[2] != null)
 
            {
 
                // A 3-reagent reaction.
 
                Reaction reaction1 = profile.FindReaction(reagents[0], reagents[1]);
 
                Reaction reaction2 = profile.FindReaction(reagents[0], reagents[2]);
 
                Reaction reaction3 = profile.FindReaction(reagents[1], reagents[2]);
 
                
 
                r = reactedColor.Red - expectedColor.Red;
 
                g = reactedColor.Green - expectedColor.Green;
 
                b = reactedColor.Blue - expectedColor.Blue;
 
                
 
                if (reaction2 == null)
 
                {
 
                    r = r - reaction1.Red - reaction3.Red;
 
                    g = g - reaction1.Green - reaction3.Green;
 
                    b = b - reaction1.Blue - reaction3.Blue;
 
                    Reaction reaction = new Reaction(r, g, b);
 
                    profile.SetReaction(reagents[0], reagents[2], reaction);
 
                    profile.Save();
 
                    saved = true;
 
                    OnReactionRecorded?.Invoke(reagents[0], reagents[2], reaction);
 
                }
 
                else if (reaction3 == null)
 
                {
 
                    r = r - reaction1.Red - reaction2.Red;
 
                    g = g - reaction1.Green - reaction2.Green;
 
                    b = b - reaction1.Blue - reaction2.Blue;
 
                    Reaction reaction = new Reaction(r, g, b);
 
                    profile.SetReaction(reagents[1], reagents[2], reaction);
 
                    profile.Save();
 
                    saved = true;
 
                    OnReactionRecorded?.Invoke(reagents[1], reagents[2], reaction);
 
                }
 
            }
 
            else if ((reagents[0] != null) && (reagents[1] != null))
 
            {
 
                // A 2-reagent reaction.
 
                r = reactedColor.Red - expectedColor.Red;
 
                g = reactedColor.Green - expectedColor.Green;
 
                b = reactedColor.Blue - expectedColor.Blue;
 
                Reaction reaction = new Reaction(r, g, b);
 
                profile.SetReaction(reagents[0], reagents[1], reaction);
 
                profile.Save();
 
                saved = true;
 
                OnReactionRecorded?.Invoke(reagents[0], reagents[1], reaction);
 
            }
 
            return saved;
 
        }
 
    }
 
}
 

	
0 comments (0 inline, 0 general)