Changeset - d792b40d3ef9
[Not reviewed]
Jason Maltzen - 6 years ago 2018-05-17 21:16:24
jason@hiddenachievement.com
Disabling the capture button then re-updating the ingredients to fix button states was having the side effect of clearing the reacted color swatch. That was done to re-enable UI elements that were disabled during recording. Now enabling them explicitly to fix the problem.
2 files changed with 6 insertions and 6 deletions:
0 comments (0 inline, 0 general)
ReactionRecorder.cs
Show inline comments
...
 
@@ -69,97 +69,98 @@ namespace DesertPaintLab
 
        };
 
        public static readonly int[] GREEN_BAR_SPACING =
 
        {
 
            42, // tiny
 
            42, // small
 
            42, // medium
 
            42, // large
 
            42 // huge
 
        };
 
        public 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)
 
        public static readonly int[] SWATCH_TEST_WIDTH =
 
        {
 
            26, // tiny
 
            26, // small
 
            26, // medium
 
            28, // large
 
            31  // huge
 
        };
 

	
 
        int swatchHeight = SWATCH_HEIGHT[(int)DEFAULT_INTERFACE_SIZE];
 
        int swatchWidth = SWATCH_WIDTH[(int)DEFAULT_INTERFACE_SIZE];
 
        int swatchTestWidth = SWATCH_TEST_WIDTH[(int)DEFAULT_INTERFACE_SIZE];
 
        int colorBarWidth = COLOR_BAR_WIDTH[(int)DEFAULT_INTERFACE_SIZE];
 
        int redBarSpacing = RED_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE];
 
        int greenBarSpacing = GREEN_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE];
 
        int blueBarSpacing = BLUE_BAR_SPACING[(int)DEFAULT_INTERFACE_SIZE];
 

	
 
        public int SwatchHeight {  get { return swatchHeight; } }
 
        public int SwatchWidth {  get { return swatchWidth; } }
 
        public int ColorBarWidth { get { return colorBarWidth;  } }
 
        public int RedBarSpacing {  get { return redBarSpacing; } }
 
        public int GreenBarSpacing { get { return greenBarSpacing; } }
 
        public int BlueBarSpacing {  get { return blueBarSpacing; } }
 

	
 
        // Current Status
 
        public bool IsCaptured { get; private set; }
 
        public int X { get; private set; }
 
        public int Y { get; private set; }
 
        public int ScreenWidth { get; private set; }
 
        public int ScreenHeight { get; private set; }
 
        public PaintColor RecordedColor { get; private set; }
 
        private PaintColor _recordedColor = new PaintColor();
 
        public PaintColor RecordedColor { get { return _recordedColor; } private set { _recordedColor.Set(value); } }
 
        public int RedBarX { get; private set; }
 
        public int RedBarY { get; private set; }
 

	
 
        int pixelMultiplier = 1;
 
        InterfaceSize interfaceSize;
 

	
 
        bool firstRun = true;
 
        int lastSwatchX = -1;
 
        int lastSwatchY = -1;
 
        public int SwatchX { get { return lastSwatchX; } }
 
        public int SwatchY { get { return lastSwatchY; } }
 

	
 
        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;
 
        }
...
 
@@ -414,96 +415,98 @@ namespace DesertPaintLab
 
                    WriteLog("Color {0}, {1}, {2} is no longer red at {3},{4}", pixBytes[redPixel], pixBytes[redPixel + 1], pixBytes[redPixel + 2], (redPixel % stride)/3, redPixel / stride);
 

	
 
                    reactedColor.Red = (byte)Math.Round((float)redPixelCount * 255f / (float)colorBarWidth);
 
                    int greenPixelStart = pixelStart + (greenBarSpacing * stride);
 

	
 
                    int greenPixelCount = 0;
 
                    while ((pixBytes[greenPixelStart] < 0x62) &&
 
                           (pixBytes[greenPixelStart + 1] > 0x9F) &&
 
                           (pixBytes[greenPixelStart + 2] < 0x62))
 
                    {
 
                        greenPixelCount++;
 
                        // pixBytes[greenPixelStart] = 0x00;
 
                        // pixBytes[greenPixelStart + 1] = 0xFF;
 
                        // pixBytes[greenPixelStart + 2] = 0xFF;
 
                        greenPixelStart += 3;
 
                    }
 
                    WriteLog("Color {0}, {1}, {2} is no longer green at pixel offset {3},{4}", pixBytes[greenPixelStart], pixBytes[greenPixelStart + 1], pixBytes[greenPixelStart + 2], (greenPixelStart % stride)/3, greenPixelStart / stride);
 

	
 
                    reactedColor.Green = (byte)Math.Round((float)greenPixelCount * 255f / (float)colorBarWidth);
 
                    int bluePixelStart = pixelStart + (blueBarSpacing * stride);
 

	
 
                    int bluePixelCount = 0;
 
                    while ((pixBytes[bluePixelStart] < 0x62) &&
 
                        (pixBytes[bluePixelStart + 1] < 0x62) &&
 
                        (pixBytes[bluePixelStart + 2] > 0x9F))
 
                    {
 
                        bluePixelCount++;
 
                        // pixBytes[bluePixelStart] = 0x00;
 
                        // pixBytes[bluePixelStart + 1] = 0xFF;
 
                        // pixBytes[bluePixelStart + 2] = 0xFF;
 
                        bluePixelStart += 3;
 
                    }
 
                    WriteLog("Color {0}, {1}, {2} is no longer blue at pixel offset {3},{4}", pixBytes[bluePixelStart], pixBytes[bluePixelStart + 1], pixBytes[bluePixelStart + 2], (bluePixelStart % stride)/3, bluePixelStart / stride);
 

	
 
                    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();
 

	
 
            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, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart))
 
                {
 
                    IsCaptured = true;
 
                    RedBarX = (redPixelStart % stride) / 3;
 
                    RedBarY = redPixelStart / stride;
 
                    RecordedColor = reactedColor;
 
                    return true;
 
                }
 
                else
 
                {
 
                    firstRun = true;
 
                }
 
            }
 

	
 
            for (X = 0; X < screenshotWidth - colorBarWidth; ++X)
 
            {
 
                for (int Y = 0; Y < (screenshotHeight - (blueBarSpacing + 10)  /*53*/); ++Y)
 
                {
 
                    if (TestPosition(X, Y, pixBytes, screenshotWidth, screenshotHeight, stride, ref reactedColor, ref redPixelStart))
 
                    {
 
                        RedBarX = (redPixelStart % stride) / 3;
 
                        RedBarY = redPixelStart / stride;
 
                        RecordedColor = reactedColor;
 
                        lastSwatchX = X;
 
                        lastSwatchY = Y;
 
                        firstRun = false;
 
                        IsCaptured = true;
 
                        return true;
 
                    }
 
                    OnCaptureProgress?.Invoke(X, Y);
 
                }
 
            }
 
            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]);
UI/CaptureView.cs
Show inline comments
...
 
@@ -243,97 +243,97 @@ namespace DesertPaintLab
 
            {
 
                reactionKnown = false;
 
                ingredient3ComboBox.Sensitive = false;
 
            }
 
        
 
            expectedColor.Set(recipe.BaseColor);
 
            unmodifiedSwatch.Color = expectedColor;
 
            //SetExpectedColor(recipeColor.Red, recipeColor.Green, recipeColor.Blue);
 
            
 
            if (reactionKnown)
 
            {
 
                reactedColor.Set(recipe.ReactedColor);
 
                reactionSwatch.Color = reactedColor;
 
            }
 
            else
 
            {
 
                reactionSwatch.Clear(); 
 
            }
 
        }
 

	
 
        unsafe void BeginCapture()
 
        {
 
            captureButton.Sensitive = false;
 
            ingredient1ComboBox.Sensitive = false;
 
            ingredient2ComboBox.Sensitive = false;
 
            ingredient3ComboBox.Sensitive = false;
 
            clearReactionButton.Sensitive = false;
 

	
 
            progressBar.Show();
 
            recordButton.Hide();
 

	
 
            bool enableDebugMenu = false;
 
            DesertPaintLab.AppSettings.Get("EnableDebugMenu", out enableDebugMenu);
 

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

	
 
            if (notifyCaptureProgress == null)
 
            {
 
                notifyCaptureProgress = new Gtk.ThreadNotify(new Gtk.ReadyEvent(NotifyCaptureProgress));
 
                notifyCaptureComplete = new Gtk.ThreadNotify(new Gtk.ReadyEvent(NotifyCaptureComplete));
 
            }
 

	
 
            this.reactionSwatch.Color = new PaintColor("Searching", "00", "00", "00");
 
            this.reactionSwatch.Clear();
 

	
 
            Thread thr = new Thread(new ThreadStart(this.CaptureReactionThread));
 
            thr.Priority = ThreadPriority.AboveNormal;
 
            thr.Start();
 
            //OnCaptureComplete(isCaptured, reactedColor, screenWidth, screenHeight, stride, redPixelStart);
 
        }
 

	
 
        unsafe private void CaptureReactionThread()
 
        {
 
            byte* pixBytes = (byte*)screenBuffer.Pixels;
 

	
 
            ReactionRecorder.Instance.OnCaptureProgress += OnCaptureProgress;
 
            ReactionRecorder.Instance.CaptureReaction(pixBytes, screenBuffer.Width, screenBuffer.Height, screenBuffer.Rowstride);
 
            ReactionRecorder.Instance.OnCaptureProgress -= OnCaptureProgress;
 

	
 
            notifyCaptureComplete.WakeupMain();
 
        }
 

	
 
        private void OnCaptureProgress(int x, int y)
 
        {
 
            notifyCaptureProgress.WakeupMain();
 
        }
 

	
 
        private void NotifyCaptureProgress()
 
        {
 
            // TODO: progress bar
 
            //ReactionRecorder.Instance.X;
 
            //ReactionRecorder.Instance.Y;
 
            progressBar.Fraction = ((double)(ReactionRecorder.Instance.X) / (double)(ReactionRecorder.Instance.ScreenWidth - ReactionRecorder.Instance.ColorBarWidth));
 
        }
 

	
 
        void OnCaptureComplete(bool isCaptured, PaintColor reactedColor, int swatchX, int swatchY)
 
        {
 
            int screenWidth = screenBuffer.Width;
 
            int screenHeight = screenBuffer.Height;
 
            int stride = screenBuffer.Rowstride;
 

	
 
            StreamWriter log = ReactionRecorder.Instance.Log;
 
            if (log != null)
 
            {
 
                log.Flush();
 
                log.Close();
 
                log = null;
 
                ReactionRecorder.Instance.Log = null;
 
            }
 

	
 
            bool enableDebugMenu = false;
 
            DesertPaintLab.AppSettings.Get("EnableDebugMenu", out enableDebugMenu);
...
 
@@ -375,120 +375,117 @@ namespace DesertPaintLab
 
            {
 
                string warning = "";
 
                if (reactedColor.Red == 0)
 
                {
 
                    warning = warning + "\nRed is too low.";
 
                }
 
                if (reactedColor.Green == 0)
 
                {
 
                    warning = warning + "\nGreen is too low.";
 
                }
 
                if (reactedColor.Blue == 0)
 
                {
 
                    warning = warning + "\nBlue is too low.";
 
                }
 
                if (reactedColor.Red == 255)
 
                {
 
                    warning = warning + "\nRed is too high.";
 
                }
 
                if (reactedColor.Green == 255)
 
                {
 
                    warning = warning + "\nGreen is too high.";
 
                }
 
                if (reactedColor.Blue == 255)
 
                {
 
                    warning = warning + "\nBlue is too high.";
 
                }
 

	
 
                // Always update the reacted swatch
 
                this.reactionSwatch.Color = reactedColor;
 
                if (warning.Length != 0)
 
                {
 
                    isCaptured = true;
 
                    Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel,
 
                    Gtk.DialogFlags.DestroyWithParent,
 
                    Gtk.MessageType.Error, Gtk.ButtonsType.Ok,
 
                    "Reaction clipped.  You will need to do a " +
 
                    "3-way reaction to test this pair.  Details: " +
 
                    warning);
 

	
 
                    md.Run();
 
                    md.Destroy();
 
                    // reaction clipped - don't let them record
 
                    recordButton.Sensitive = false;
 
                }
 
                else
 
                {
 
                    recordButton.Sensitive = recordEnabled;
 
                }
 

	
 
                captureButton.Sensitive = false;
 
            }
 
            else
 
            {
 
                Gtk.MessageDialog md = new Gtk.MessageDialog((Gtk.Window)Toplevel,
 
                    Gtk.DialogFlags.DestroyWithParent,
 
                    Gtk.MessageType.Error, Gtk.ButtonsType.Ok,
 
                    "Pigment Lab dialog box NOT FOUND.  Please ensure " +
 
                    "that there is an unobstructed view of the dialog " +
 
                    "and that your interface size is set to 'small' " +
 
                    "when you press the Capture button.");
 

	
 
                md.Run();
 
                md.Destroy();
 
            }
 

	
 
            progressBar.Hide();
 
            recordButton.Show();
 

	
 
            ingredient1ComboBox.Sensitive = true;
 
            ingredient2ComboBox.Sensitive = true;
 
            ingredient3ComboBox.Sensitive = false;
 
            UpdateIngredients();
 
            ingredient3ComboBox.Sensitive = (GetSelectedReagentName(1) != null) && (GetSelectedReagentName(2) != null);
 
        }
 

	
 
        private void NotifyCaptureComplete()
 
        {
 
            OnCaptureComplete(
 
                ReactionRecorder.Instance.IsCaptured,
 
                ReactionRecorder.Instance.RecordedColor,
 
                ReactionRecorder.Instance.SwatchX,
 
                ReactionRecorder.Instance.SwatchY);
 
        }
 

	
 
        unsafe void CaptureReactionColor()
 
        {
 
            // Take a screenshot.
 
            int screenWidth, screenHeight;
 
            Gdk.Window rootWindow = Gdk.Global.DefaultRootWindow;
 
            DesertPaintLab.AppSettings.Get("ScreenWidth", out screenWidth);
 
            DesertPaintLab.AppSettings.Get("ScreenHeight", out screenHeight);
 
            Gdk.Image rootImage = rootWindow.GetImage(0, 0, screenWidth, screenHeight);
 
            screenBuffer.GetFromImage(rootImage, rootImage.Colormap, 0, 0, 0, 0, screenWidth, screenHeight);
 
            rootImage.Unref();
 
            System.GC.Collect(); // really, clean up now
 

	
 
            BeginCapture();
 
        }
 

	
 
        protected virtual void OnCapture(object sender, System.EventArgs e)
 
        {
 
            CaptureReactionColor();
 
        }
 
        
 
        protected virtual void OnRecord(object sender, System.EventArgs e)
 
        {
 
            if (ReactionRecorder.Instance.RecordReaction(profile, expectedColor, reactedColor, reagents))
 
            {
 
                recordButton.Sensitive = false;
 
            }
 
        }
 
        
 
        protected virtual void OnChangedIngredient1(object sender, System.EventArgs e)
 
        {
 
            UpdateIngredients();
 
        }
 
        
 
        protected virtual void OnChangedIngredient2(object sender, System.EventArgs e)
 
        {
 
            UpdateIngredients();
 
        }
0 comments (0 inline, 0 general)