Changeset - 4ddfeff50454
[Not reviewed]
Tess Snider (Malkyne) - 9 years ago 2015-10-12 16:35:28
this@malkyne.org
Fixed error that was causing upward-clipped colors to not properly trigger the error-checking for that case. Also, corrected warning message for that condition.
2 files changed with 14 insertions and 14 deletions:
0 comments (0 inline, 0 general)
MainWindow.cs
Show inline comments
...
 
@@ -437,224 +437,224 @@ public partial class MainWindow : Gtk.Wi
 
				{
 
					reactionSwatch.Clear();	
 
				}
 
			}
 
		}		
 
	}							
 
	
 
	protected void OnDeleteEvent(object sender, DeleteEventArgs a)
 
	{
 
		if (ConfirmedExit())
 
		{
 
			a.RetVal = true;
 
			Application.Quit();
 
		}
 
		else
 
		{
 
			a.RetVal = false;
 
		}
 
	}
 
	
 
	bool IsPapyTexture(byte r, byte g, byte b)
 
	{
 
		return ((r > 0xD0) && (g > 0xC8) && (b > 0xA0)) &&
 
				((r < 0xF4) && (g < 0xE0) && (b < 0xC4));
 
	}
 
	
 
	unsafe bool CaptureReactionColor()
 
	{
 
		// Take a screenshot.
 
		byte r, g, b;
 
		int pixelStart, otherPixelStart;
 
		bool colorMatch;
 
		screenBuffer.GetFromDrawable(rootWindow,
 
			rootWindow.Colormap, 0, 0, 0, 0, screenWidth, screenHeight);
 
		int stride = screenBuffer.Rowstride;
 
		byte* pixBytes = (byte*)screenBuffer.Pixels;
 
				
 
		for (int x = 0; x < screenWidth - colorBarWidth; ++x)
 
		{
 
			for (int y = 0; y < (screenHeight - 53); ++y)
 
			{
 
				// Look for the color swatch.
 
				pixelStart = (y * stride) + (x * 3);
 
				r = pixBytes[pixelStart];
 
				g = pixBytes[pixelStart + 1];
 
				b = pixBytes[pixelStart + 2];
 
				
 
				// 1.) Check if this is a dark pixel.
 
				if ((r < 0x42) && (g < 0x42) && (b <= 0x42))
 
				if ((r < 0x46) && (g < 0x46) && (b < 0x46))
 
				{
 
					// 2.) Check the pixel above it,
 
					// to see if it's from the papy texture.
 
					otherPixelStart = pixelStart - stride;
 
					if ((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 = pixelStart + (stride * swatchHeight);
 
						if (IsPapyTexture(pixBytes[otherPixelStart++],
 
					                   pixBytes[otherPixelStart++],
 
					                   pixBytes[otherPixelStart]))
 
						{
 
							// pixBytes[pixelStart] = 0xFF;
 
							// pixBytes[pixelStart + 1] = 0x00;
 
							// pixBytes[pixelStart + 2] = 0xFF;
 
							
 
							// 4.) Scan the left border of the potential swatch
 
							// location.
 
							colorMatch = true;
 
							for (int i = 1; i < swatchHeight - 2; ++i)
 
							{
 
								otherPixelStart = pixelStart + (stride * i);
 
								if ((Math.Abs(r - pixBytes[otherPixelStart++]) > colorTolerance) ||
 
								    (Math.Abs(g - pixBytes[otherPixelStart++]) > colorTolerance) ||
 
								    (Math.Abs(b - pixBytes[otherPixelStart]) > colorTolerance))
 
								{
 
									colorMatch = false;
 
									break;
 
								}
 
							}
 
							
 
							if (colorMatch)
 
							{
 
								// WE FOUND THE SWATCH!
 
								// Now we know where the color bars are.
 
								otherPixelStart = pixelStart + (redBarSpacing * stride);
 
								int pixelCount = 0;
 
								while ((Math.Abs(pixBytes[otherPixelStart] - 0xA1) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 1] - 0x04) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 2] - 0x03) < colorTolerance))
 
								while ((pixBytes[otherPixelStart] > 0x9F) &&
 
								       (pixBytes[otherPixelStart + 1] < 0x62) &&
 
								       (pixBytes[otherPixelStart + 2]  < 0x62))
 
								{
 
									pixelCount++;
 
									// pixBytes[otherPixelStart] = 0x00;
 
									// pixBytes[otherPixelStart + 1] = 0xFF;
 
									// pixBytes[otherPixelStart + 2] = 0xFF;
 
									otherPixelStart += 3;
 
								}
 
									
 
								reactedColor.Red = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
 
								otherPixelStart = pixelStart + (greenBarSpacing * stride);
 
								
 
								pixelCount = 0;		
 
								while ((Math.Abs(pixBytes[otherPixelStart] - 0x04) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 1] - 0xA1) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 2] - 0x03) < colorTolerance))
 
								while ((pixBytes[otherPixelStart] < 0x62) &&
 
								       (pixBytes[otherPixelStart + 1] > 0x9F) &&
 
								       (pixBytes[otherPixelStart + 2] < 0x62))
 
								{
 
									pixelCount++;
 
									// pixBytes[otherPixelStart] = 0x00;
 
									// pixBytes[otherPixelStart + 1] = 0xFF;
 
									// pixBytes[otherPixelStart + 2] = 0xFF;
 
									otherPixelStart += 3;
 
								}
 

 
								reactedColor.Green = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
 
								otherPixelStart = pixelStart + (blueBarSpacing * stride);
 
								
 
								pixelCount = 0;
 
								while ((Math.Abs(pixBytes[otherPixelStart] - 0x04) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 1] - 0x04) < colorTolerance) &&
 
								       (Math.Abs(pixBytes[otherPixelStart + 2] - 0xA1) < colorTolerance))
 
								while ((pixBytes[otherPixelStart] < 0x62) &&
 
									(pixBytes[otherPixelStart + 1] < 0x62) &&
 
									(pixBytes[otherPixelStart + 2] > 0x9F))
 
								{
 
									pixelCount++;
 
									// pixBytes[otherPixelStart] = 0x00;
 
									// pixBytes[otherPixelStart + 1] = 0xFF;
 
									// pixBytes[otherPixelStart + 2] = 0xFF;
 
									otherPixelStart += 3;
 
								}
 

 
								reactedColor.Blue = (byte)Math.Round((float)pixelCount * 255f / (float)colorBarWidth);
 
								
 
								
 
								// screenBuffer.Save("screenshot.png", "png");
 
								return true;
 
							}
 
						}					
 
					}
 
				}
 
			}
 
		}
 
		// screenBuffer.Save("screenshot.png", "png");
 
		
 
		return false;
 
		
 
	}
 
	
 
	protected virtual void OnCaptureButton(object sender, System.EventArgs e)
 
	{
 
		if (CaptureReactionColor())
 
		{
 
			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 low.";
 
				warning = warning + "\nRed is too high.";
 
			}
 
			if (reactedColor.Green == 255)
 
			{
 
				warning = warning + "\nGreen is too low.";	
 
				warning = warning + "\nGreen is too high.";	
 
			}
 
			if (reactedColor.Blue == 255)
 
			{
 
				warning = warning + "\nBlue is too low.";	
 
				warning = warning + "\nBlue is too high.";	
 
			}
 
			
 
			if (warning.Length != 0)
 
			{
 
				MessageDialog md = new MessageDialog(this, 
 
	            DialogFlags.DestroyWithParent,
 
	            MessageType.Error, ButtonsType.Ok, 
 
	            "Reaction clipped.  You will need to do a " +
 
	            "3-way reaction to test this pair.  Details: " +
 
	            warning);
 
	   
 
				md.Run();			
 
				md.Destroy();
 
			}
 
			else
 
			{
 
				this.reactionSwatch.Color = reactedColor;
 
				saveButton.Sensitive = true;
 
			}
 
		}
 
		else
 
		{
 
			MessageDialog md = new MessageDialog(this, 
 
	            DialogFlags.DestroyWithParent,
 
	            MessageType.Error, ButtonsType.Ok, 
 
	            "Pigment Lab dialog box NOT FOUND.  Please ensure " +
 
	            "that there is an unobstructed view of the dialog " +
 
	            "when you press the Capture button.");
 
	   
 
			md.Run();			
 
			md.Destroy();	
 
		}
 
	}
 
	
 
	protected virtual void OnSaveButton(object sender, System.EventArgs e)
 
	{
 
		int r, g, b;
 
		if (reagent3 != null)
 
		{
 
			// A 3-reagent reaction.
 
			Reaction reaction1 = profile.FindReaction(reagent1, reagent2);
 
			Reaction reaction2 = profile.FindReaction(reagent1, reagent3);
 
			Reaction reaction3 = profile.FindReaction(reagent2, reagent3);
 
			
 
			r = reactedColor.Red - expectedColor.Red;
 
			g = reactedColor.Green - expectedColor.Green;
 
			b = reactedColor.Blue - expectedColor.Blue;
 
			
README.md
Show inline comments
 
# Desert Paint Lab
 

 
This is a tool for players to record their [Pigment Laboratory](http://www.atitd.org/wiki/tale6/Pigment_Laboratory)
 
ingredient reactions in [A Tale in the Desert](http://www.atitd.com/).
 

 
### Features
 

 
* Easily scans your screen for the paint bench reaction values, without any math, measuring, or manual number entry.
 
* Warns you when a reaction clipped below 0.
 
* Supports multiple character profiles.
 
* Can export to [PracticalPaint](http://www.atitd.org/wiki/tale6/File:PracticalPaint.zip) data format.
 
* Includes simulator for experimenting with recipes without spending ingredients.
 

 
## Tale 7
 

 
This application has been updated for Tale 7.  The current version is a **RELEASE CANDIDATE**.  It may be buggy.
 
If you find any problems with it, please [open an issue](https://bitbucket.org/Malkyne/desert-paint-lab/issues) or /chat Afrah
 
in the game.
 

 
## Directions
 

 
### Download Desert Paint Lab
 

 
You can always find the available downloads, on [the download page](https://bitbucket.org/Malkyne/desert-paint-lab/downloads).
 

 
The most recent version is [T7 Release Candidate 1](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC1.zip).
 
The most recent version is [T7 Release Candidate 2](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC2.zip).
 

 
This application should run under Mono on Mac, Linux, and Windows.  If you are on Windows,
 
and do not have Mono installed, you can install [GTK# for .NET](http://www.mono-project.com/download/#download-win),
 
without the need for installing Mono.
 

 
### Set Up a Profile
 

 
The first time you run Desert Paint Lab, it will prompt you to make a profile.  You may either create a new profile, or import an existing PracticalPaint reactions.txt file.
 

 
### Start Testing!
 

 
Add two ingredients to your paint bench.  Select those same ingredients in Desert Paint Lab.  Then, with the Pigment Lab dialog unobstructred, select the **Capture** button.  Once you are satisfied with the result, click the **Record** button.  The data will automatically be added to your profile.
 

 
### Clipped?  Huh?
 

 
Occasionally, you will see a warning dialog that informs you that a "Reaction clipped."  That means that one or more of the color components moved outside of the testable range.  This makes it impossible to calculate the reaction from these two ingredients.
 

 
You can solve this by doing a three-way test.  To do this, select a third ingredient that has known reaction values with the two ingredients you are attempting to pair, and which will adjust the color component that was clipping, so that it is no longer doing so.  Combine that with your two ingredients.  In Desert Paint Lab, you'll want to select a known pairing in the first two boxes, and the other ingredient in the third.  Desert Paint Lab can then do all the math to figure out the mystery reaction.
 

 
In many cases, it may be easiest to go back and do these three-way tests after you have finished all of your other testing.
 

 
### Finishing Up
 

 
When you're done testing your reactions, you can either use the built-in Pigment Lab simulator (`Window > Run Simulator`) to experiment with recipes, without dipping into your precious ingredient stocks.  Alternatively, you can export your reactions in PracticalPaint format.
 

 
## Known Issues
 

 
### Slowness
 

 
If you are running on a multi-screen system, or a very high-resolution screen, you may find that Desert Paint Lab is rather slow in determining paint reactions.  That's because you have a lot of screen real-estate to scan, to look for the Pigment Lab dialog.  You can speed up the scanning process by ensuring that your Pigment Lab Dialog is as far to the upper-left of the screen as possible.
 

 
## For Developers
 

 
This application was developed using [MonoDevelop](http://www.monodevelop.com/), using the [Stetic GTK UI designer](http://www.monodevelop.com/documentation/stetic-gui-designer/).
...
 
\ No newline at end of file
0 comments (0 inline, 0 general)