Changeset - 63ce80f17b8c
[Not reviewed]
default
0 21 1
Jason Maltzen - 6 years ago 2018-05-03 04:12:15
jason@hiddenachievement.com
Enable hgeol extension
22 files changed with 2203 insertions and 2196 deletions:
0 comments (0 inline, 0 general)
.hgeol
Show inline comments
 
new file 100644
 
[repository]
 
native = LF
 

 
[patterns]
 
** = native
 
**.vcproj = CRLF
 

AssemblyInfo.cs
Show inline comments
 
using System.Reflection;
 
using System.Runtime.CompilerServices;
 

 
// Information about this assembly is defined by the following attributes. 
 
// Change them to the values specific to your project.
 

 
[assembly: AssemblyTitle("DesertPaintLab")]
 
[assembly: AssemblyDescription("Program to help record pigment lab reactions in ATITD")]
 
[assembly: AssemblyConfiguration("")]
 
[assembly: AssemblyCompany("Tess Snider")]
 
[assembly: AssemblyProduct("")]
 
[assembly: AssemblyCopyright("Tess Snider, 2015")]
 
[assembly: AssemblyTrademark("")]
 
[assembly: AssemblyCulture("")]
 

 
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
 
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
 
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 

 
[assembly: AssemblyVersion("1.0.*")]
 

 
// The following attributes are used to specify the signing key for the assembly, 
 
// if desired. See the Mono documentation for more information about signing.
 

 
//[assembly: AssemblyDelaySign(false)]
 
//[assembly: AssemblyKeyFile("")]
 

 
using System.Reflection;
 
using System.Runtime.CompilerServices;
 

	
 
// Information about this assembly is defined by the following attributes. 
 
// Change them to the values specific to your project.
 

	
 
[assembly: AssemblyTitle("DesertPaintLab")]
 
[assembly: AssemblyDescription("Program to help record pigment lab reactions in ATITD")]
 
[assembly: AssemblyConfiguration("")]
 
[assembly: AssemblyCompany("Tess Snider")]
 
[assembly: AssemblyProduct("")]
 
[assembly: AssemblyCopyright("Tess Snider, 2015")]
 
[assembly: AssemblyTrademark("")]
 
[assembly: AssemblyCulture("")]
 

	
 
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
 
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
 
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 

	
 
[assembly: AssemblyVersion("1.0.*")]
 

	
 
// The following attributes are used to specify the signing key for the assembly, 
 
// if desired. See the Mono documentation for more information about signing.
 

	
 
//[assembly: AssemblyDelaySign(false)]
 
//[assembly: AssemblyKeyFile("")]
 

	
DesertPaintLab.csproj
Show inline comments
 
<?xml version="1.0" encoding="utf-8"?>
 
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
 
  <PropertyGroup>
 
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
 
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
 
    <ProjectGuid>{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}</ProjectGuid>
 
    <OutputType>WinExe</OutputType>
 
    <RootNamespace>DesertPaintLab</RootNamespace>
 
    <AssemblyName>DesertPaintLab</AssemblyName>
 
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
 
    <PublishUrl>publish\</PublishUrl>
 
    <Install>true</Install>
 
    <InstallFrom>Disk</InstallFrom>
 
    <UpdateEnabled>false</UpdateEnabled>
 
    <UpdateMode>Foreground</UpdateMode>
 
    <UpdateInterval>7</UpdateInterval>
 
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
 
    <UpdatePeriodically>false</UpdatePeriodically>
 
    <UpdateRequired>false</UpdateRequired>
 
    <MapFileExtensions>true</MapFileExtensions>
 
    <ApplicationRevision>0</ApplicationRevision>
 
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
 
    <IsWebBootstrapper>false</IsWebBootstrapper>
 
    <UseApplicationTrust>false</UseApplicationTrust>
 
    <BootstrapperEnabled>true</BootstrapperEnabled>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
 
    <DebugSymbols>true</DebugSymbols>
 
    <DebugType>full</DebugType>
 
    <Optimize>false</Optimize>
 
    <OutputPath>bin\Debug</OutputPath>
 
    <DefineConstants>DEBUG</DefineConstants>
 
    <ErrorReport>prompt</ErrorReport>
 
    <WarningLevel>4</WarningLevel>
 
    <PlatformTarget>x86</PlatformTarget>
 
    <ConsolePause>false</ConsolePause>
 
    <additionalargs>/unsafe</additionalargs>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
 
    <DebugType>none</DebugType>
 
    <Optimize>false</Optimize>
 
    <OutputPath>bin\Release</OutputPath>
 
    <ErrorReport>prompt</ErrorReport>
 
    <WarningLevel>4</WarningLevel>
 
    <PlatformTarget>x86</PlatformTarget>
 
    <ConsolePause>false</ConsolePause>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
 
    <DebugSymbols>true</DebugSymbols>
 
    <OutputPath>bin\x64\Debug\</OutputPath>
 
    <DefineConstants>DEBUG</DefineConstants>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <DebugType>full</DebugType>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
 
    <OutputPath>bin\x64\Release\</OutputPath>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="System" />
 
    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="System.IO.Compression.FileSystem" />
 
  </ItemGroup>
 
  <ItemGroup>
 
    <EmbeddedResource Include="gtk-gui\gui.stetic">
 
      <LogicalName>gui.stetic</LogicalName>
 
    </EmbeddedResource>
 
  </ItemGroup>
 
  <ItemGroup>
 
    <Compile Include="gtk-gui\generated.cs" />
 
    <Compile Include="MainWindow.cs" />
 
    <Compile Include="Main.cs" />
 
    <Compile Include="AssemblyInfo.cs" />
 
    <Compile Include="PlayerProfile.cs" />
 
    <Compile Include="FirstRunDialog.cs" />
 
    <Compile Include="SelectProfileDialog.cs" />
 
    <Compile Include="NewProfileDialog.cs" />
 
    <Compile Include="PaintSwatch.cs" />
 
    <Compile Include="Palette.cs" />
 
    <Compile Include="PaintColor.cs" />
 
    <Compile Include="Reaction.cs" />
 
    <Compile Include="ReagentManager.cs" />
 
    <Compile Include="Reagent.cs" />
 
    <Compile Include="gtk-gui\MainWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.FirstRunDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.SelectProfileDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.NewProfileDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.PaintSwatch.cs" />
 
    <Compile Include="ScreenCheckDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ScreenCheckDialog.cs" />
 
    <Compile Include="FileUtils.cs" />
 
    <Compile Include="PaintRecipe.cs" />
 
    <Compile Include="ReactionRecorder.cs" />
 
    <Compile Include="ReactionStatusWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ReactionStatusWindow.cs" />
 
    <Compile Include="ReactionSet.cs" />
 
    <Compile Include="RecipeGenerator.cs" />
 
    <Compile Include="ReagentWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ReagentWindow.cs" />
 
    <Compile Include="RecipeSearchNode.cs" />
 
    <Compile Include="Settings.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.CaptureView.cs" />
 
    <Compile Include="UI\CaptureView.cs" />
 
    <Compile Include="UI\RecipeGeneratorView.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.RecipeGeneratorView.cs" />
 
    <Compile Include="UI\SimulatorView.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.SimulatorView.cs" />
 
    <Compile Include="StatusUpdateEventArgs.cs" />
 
    <Compile Include="AppSettings.cs" />
 
  </ItemGroup>
 
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 
  <ProjectExtensions>
 
    <MonoDevelop>
 
      <Properties>
 
        <Policies>
 
          <TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
 
          <CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
 
        </Policies>
 
        <GtkDesignInfo generateGettext="False" />
 
      </Properties>
 
    </MonoDevelop>
 
  </ProjectExtensions>
 
  <ItemGroup>
 
    <None Include="data\colors.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\template\dp_reactions.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\template\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
  </ItemGroup>
 
  <ItemGroup />
 
  <ItemGroup>
 
    <BootstrapperPackage Include=".NETFramework,Version=v4.5">
 
      <Visible>False</Visible>
 
      <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
 
      <Install>true</Install>
 
    </BootstrapperPackage>
 
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
 
      <Visible>False</Visible>
 
      <ProductName>.NET Framework 3.5 SP1</ProductName>
 
      <Install>false</Install>
 
    </BootstrapperPackage>
 
  </ItemGroup>
 
<?xml version="1.0" encoding="utf-8"?>
 
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
 
  <PropertyGroup>
 
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
 
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
 
    <ProjectGuid>{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}</ProjectGuid>
 
    <OutputType>WinExe</OutputType>
 
    <RootNamespace>DesertPaintLab</RootNamespace>
 
    <AssemblyName>DesertPaintLab</AssemblyName>
 
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
 
    <PublishUrl>publish\</PublishUrl>
 
    <Install>true</Install>
 
    <InstallFrom>Disk</InstallFrom>
 
    <UpdateEnabled>false</UpdateEnabled>
 
    <UpdateMode>Foreground</UpdateMode>
 
    <UpdateInterval>7</UpdateInterval>
 
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
 
    <UpdatePeriodically>false</UpdatePeriodically>
 
    <UpdateRequired>false</UpdateRequired>
 
    <MapFileExtensions>true</MapFileExtensions>
 
    <ApplicationRevision>0</ApplicationRevision>
 
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
 
    <IsWebBootstrapper>false</IsWebBootstrapper>
 
    <UseApplicationTrust>false</UseApplicationTrust>
 
    <BootstrapperEnabled>true</BootstrapperEnabled>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
 
    <DebugSymbols>true</DebugSymbols>
 
    <DebugType>full</DebugType>
 
    <Optimize>false</Optimize>
 
    <OutputPath>bin\Debug</OutputPath>
 
    <DefineConstants>DEBUG</DefineConstants>
 
    <ErrorReport>prompt</ErrorReport>
 
    <WarningLevel>4</WarningLevel>
 
    <PlatformTarget>x86</PlatformTarget>
 
    <ConsolePause>false</ConsolePause>
 
    <additionalargs>/unsafe</additionalargs>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
  </PropertyGroup>
 
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
 
    <DebugType>none</DebugType>
 
    <Optimize>false</Optimize>
 
    <OutputPath>bin\Release</OutputPath>
 
    <ErrorReport>prompt</ErrorReport>
 
    <WarningLevel>4</WarningLevel>
 
    <PlatformTarget>x86</PlatformTarget>
 
    <ConsolePause>false</ConsolePause>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
 
    <DebugSymbols>true</DebugSymbols>
 
    <OutputPath>bin\x64\Debug\</OutputPath>
 
    <DefineConstants>DEBUG</DefineConstants>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <DebugType>full</DebugType>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
 
    <OutputPath>bin\x64\Release\</OutputPath>
 
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 
    <PlatformTarget>x64</PlatformTarget>
 
    <ErrorReport>prompt</ErrorReport>
 
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
 
    <Prefer32Bit>true</Prefer32Bit>
 
  </PropertyGroup>
 
  <ItemGroup>
 
    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="System" />
 
    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
 
    <Reference Include="System.IO.Compression.FileSystem" />
 
  </ItemGroup>
 
  <ItemGroup>
 
    <EmbeddedResource Include="gtk-gui\gui.stetic">
 
      <LogicalName>gui.stetic</LogicalName>
 
    </EmbeddedResource>
 
  </ItemGroup>
 
  <ItemGroup>
 
    <Compile Include="gtk-gui\generated.cs" />
 
    <Compile Include="MainWindow.cs" />
 
    <Compile Include="Main.cs" />
 
    <Compile Include="AssemblyInfo.cs" />
 
    <Compile Include="PlayerProfile.cs" />
 
    <Compile Include="FirstRunDialog.cs" />
 
    <Compile Include="SelectProfileDialog.cs" />
 
    <Compile Include="NewProfileDialog.cs" />
 
    <Compile Include="PaintSwatch.cs" />
 
    <Compile Include="Palette.cs" />
 
    <Compile Include="PaintColor.cs" />
 
    <Compile Include="Reaction.cs" />
 
    <Compile Include="ReagentManager.cs" />
 
    <Compile Include="Reagent.cs" />
 
    <Compile Include="gtk-gui\MainWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.FirstRunDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.SelectProfileDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.NewProfileDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.PaintSwatch.cs" />
 
    <Compile Include="ScreenCheckDialog.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ScreenCheckDialog.cs" />
 
    <Compile Include="FileUtils.cs" />
 
    <Compile Include="PaintRecipe.cs" />
 
    <Compile Include="ReactionRecorder.cs" />
 
    <Compile Include="ReactionStatusWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ReactionStatusWindow.cs" />
 
    <Compile Include="ReactionSet.cs" />
 
    <Compile Include="RecipeGenerator.cs" />
 
    <Compile Include="ReagentWindow.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.ReagentWindow.cs" />
 
    <Compile Include="RecipeSearchNode.cs" />
 
    <Compile Include="Settings.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.CaptureView.cs" />
 
    <Compile Include="UI\CaptureView.cs" />
 
    <Compile Include="UI\RecipeGeneratorView.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.RecipeGeneratorView.cs" />
 
    <Compile Include="UI\SimulatorView.cs" />
 
    <Compile Include="gtk-gui\DesertPaintLab.SimulatorView.cs" />
 
    <Compile Include="StatusUpdateEventArgs.cs" />
 
    <Compile Include="AppSettings.cs" />
 
  </ItemGroup>
 
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 
  <ProjectExtensions>
 
    <MonoDevelop>
 
      <Properties>
 
        <Policies>
 
          <TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
 
          <CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
 
        </Policies>
 
        <GtkDesignInfo generateGettext="False" />
 
      </Properties>
 
    </MonoDevelop>
 
  </ProjectExtensions>
 
  <ItemGroup>
 
    <None Include="data\colors.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\template\dp_reactions.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
    <None Include="data\template\ingredients.txt">
 
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
 
    </None>
 
  </ItemGroup>
 
  <ItemGroup />
 
  <ItemGroup>
 
    <BootstrapperPackage Include=".NETFramework,Version=v4.5">
 
      <Visible>False</Visible>
 
      <ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
 
      <Install>true</Install>
 
    </BootstrapperPackage>
 
    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
 
      <Visible>False</Visible>
 
      <ProductName>.NET Framework 3.5 SP1</ProductName>
 
      <Install>false</Install>
 
    </BootstrapperPackage>
 
  </ItemGroup>
 
</Project>
...
 
\ No newline at end of file
DesertPaintLab.sln
Show inline comments
 

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

 
Microsoft Visual Studio Solution File, Format Version 12.00
 
# Visual Studio 14
 
VisualStudioVersion = 14.0.23107.0
 
MinimumVisualStudioVersion = 10.0.40219.1
 
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesertPaintLab", "DesertPaintLab.csproj", "{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}"
 
EndProject
 
Global
 
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 
		Debug|x64 = Debug|x64
 
		Debug|x86 = Debug|x86
 
		Release|x64 = Release|x64
 
		Release|x86 = Release|x86
 
	EndGlobalSection
 
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x64.ActiveCfg = Debug|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x64.Build.0 = Debug|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.ActiveCfg = Debug|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Debug|x86.Build.0 = Debug|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x64.ActiveCfg = Release|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x64.Build.0 = Release|x64
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.ActiveCfg = Release|x86
 
		{1A885212-5FD2-4EBF-A98F-3EB1491A1CBB}.Release|x86.Build.0 = Release|x86
 
	EndGlobalSection
 
	GlobalSection(SolutionProperties) = preSolution
 
		HideSolutionNode = FALSE
 
	EndGlobalSection
 
EndGlobal
FirstRunDialog.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class FirstRunDialog : Gtk.Dialog
 
	{
 
		public FirstRunDialog ()
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class FirstRunDialog : Gtk.Dialog
 
	{
 
		public FirstRunDialog ()
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

	
Main.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
using Gtk;
 

 
namespace DesertPaintLab
 
{
 
	class MainClass
 
	{
 
		public static void Main (string[] args)
 
		{
 
			Application.Init ();
 
			MainWindow win = new MainWindow ();
 
			if (!win.ShouldShutDown)
 
			{
 
				win.Show ();
 
				Application.Run ();
 
			}
 
		}
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
using Gtk;
 

	
 
namespace DesertPaintLab
 
{
 
	class MainClass
 
	{
 
		public static void Main (string[] args)
 
		{
 
			Application.Init ();
 
			MainWindow win = new MainWindow ();
 
			if (!win.ShouldShutDown)
 
			{
 
				win.Show ();
 
				Application.Run ();
 
			}
 
		}
 
	}
 
}
 

	
NewProfileDialog.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class NewProfileDialog : Gtk.Dialog
 
	{
 
		public string ProfileName
 
		{
 
			get
 
			{
 
				return profileNameEntry.Text;	
 
			}	
 
		}
 
		
 
		public NewProfileDialog ()
 
		{
 
			this.Build ();
 
		}
 
		
 
		
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class NewProfileDialog : Gtk.Dialog
 
	{
 
		public string ProfileName
 
		{
 
			get
 
			{
 
				return profileNameEntry.Text;	
 
			}	
 
		}
 
		
 
		public NewProfileDialog ()
 
		{
 
			this.Build ();
 
		}
 
		
 
		
 
	}
 
}
 

	
PaintColor.cs
Show inline comments
 
using System;
 
namespace DesertPaintLab
 
{
 
	public class PaintColor
 
	{
 
		byte red;
 
		byte green;
 
		byte blue;
 

 
		string name;
 
		
 
		public byte Red
 
		{
 
			get
 
			{
 
				return red;	
 
			}
 
			set
 
			{
 
				red = value;	
 
			}
 
		}
 

 
		public byte Blue
 
		{
 
			get
 
			{
 
				return blue;	
 
			}
 
			set
 
			{
 
				blue = value;	
 
			}
 
		}
 
		
 
		public byte Green
 
		{
 
			get
 
			{
 
				return green;	
 
			}
 
			set
 
			{
 
				green = value;	
 
			}
 
		}
 
		
 
		public string Name
 
		{
 
			get
 
			{
 
				return name;
 
			}
 
			set
 
			{
 
				name = value;	
 
			}
 
		}
 
		
 
		public PaintColor()
 
		{
 
			name = "Undefined";
 
			red = 0;
 
			green = 0;
 
			blue = 0;
 
		}
 
		
 
		public PaintColor(string name, string hexRed, string hexGreen, string hexBlue)
 
		{
 
			this.name = name;
 
			red = (byte)System.Int32.Parse(hexRed,
 
				System.Globalization.NumberStyles.AllowHexSpecifier);
 
            green = (byte)System.Int32.Parse(hexGreen,
 
			    System.Globalization.NumberStyles.AllowHexSpecifier);
 
         	blue = (byte)System.Int32.Parse(hexBlue,
 
			    System.Globalization.NumberStyles.AllowHexSpecifier);	
 
		}
 
		
 
		public PaintColor(byte red, byte green, byte blue)
 
		{
 
			name = "Undefined";
 
			this.red = red;
 
			this.green = green;
 
			this.blue = blue;			
 
		}
 

 
        public PaintColor(PaintColor other)
 
        {
 
            name = other.name;
 
            red = other.red;
 
            green = other.green;
 
            blue = other.blue;
 
        }
 
				
 
		public int GetDistanceSquared(PaintColor otherColor)
 
		{
 
			return (int)(Math.Pow(this.red - otherColor.red, 2) +
 
				Math.Pow(this.green - otherColor.green, 2) +
 
				Math.Pow(this.blue - otherColor.blue, 2));
 
		}
 
		
 
		public void Clear()
 
		{
 
			red = 0;
 
			green = 0;
 
			blue = 0;
 
		}
 

 
        public void Set(PaintColor other)
 
        {
 
            this.red = other.red;
 
            this.green = other.green;
 
            this.blue = other.blue;
 
            this.name = other.name;
 
        }
 
		
 
		public override string ToString()
 
		{
 
			return "[" + name + ", " + red + ", " + green + ", " + blue + "]";
 
		}
 
		
 
	}
 
}
 

 
using System;
 
namespace DesertPaintLab
 
{
 
	public class PaintColor
 
	{
 
		byte red;
 
		byte green;
 
		byte blue;
 

	
 
		string name;
 
		
 
		public byte Red
 
		{
 
			get
 
			{
 
				return red;	
 
			}
 
			set
 
			{
 
				red = value;	
 
			}
 
		}
 

	
 
		public byte Blue
 
		{
 
			get
 
			{
 
				return blue;	
 
			}
 
			set
 
			{
 
				blue = value;	
 
			}
 
		}
 
		
 
		public byte Green
 
		{
 
			get
 
			{
 
				return green;	
 
			}
 
			set
 
			{
 
				green = value;	
 
			}
 
		}
 
		
 
		public string Name
 
		{
 
			get
 
			{
 
				return name;
 
			}
 
			set
 
			{
 
				name = value;	
 
			}
 
		}
 
		
 
		public PaintColor()
 
		{
 
			name = "Undefined";
 
			red = 0;
 
			green = 0;
 
			blue = 0;
 
		}
 
		
 
		public PaintColor(string name, string hexRed, string hexGreen, string hexBlue)
 
		{
 
			this.name = name;
 
			red = (byte)System.Int32.Parse(hexRed,
 
				System.Globalization.NumberStyles.AllowHexSpecifier);
 
            green = (byte)System.Int32.Parse(hexGreen,
 
			    System.Globalization.NumberStyles.AllowHexSpecifier);
 
         	blue = (byte)System.Int32.Parse(hexBlue,
 
			    System.Globalization.NumberStyles.AllowHexSpecifier);	
 
		}
 
		
 
		public PaintColor(byte red, byte green, byte blue)
 
		{
 
			name = "Undefined";
 
			this.red = red;
 
			this.green = green;
 
			this.blue = blue;			
 
		}
 

	
 
        public PaintColor(PaintColor other)
 
        {
 
            name = other.name;
 
            red = other.red;
 
            green = other.green;
 
            blue = other.blue;
 
        }
 
				
 
		public int GetDistanceSquared(PaintColor otherColor)
 
		{
 
			return (int)(Math.Pow(this.red - otherColor.red, 2) +
 
				Math.Pow(this.green - otherColor.green, 2) +
 
				Math.Pow(this.blue - otherColor.blue, 2));
 
		}
 
		
 
		public void Clear()
 
		{
 
			red = 0;
 
			green = 0;
 
			blue = 0;
 
		}
 

	
 
        public void Set(PaintColor other)
 
        {
 
            this.red = other.red;
 
            this.green = other.green;
 
            this.blue = other.blue;
 
            this.name = other.name;
 
        }
 
		
 
		public override string ToString()
 
		{
 
			return "[" + name + ", " + red + ", " + green + ", " + blue + "]";
 
		}
 
		
 
	}
 
}
 

	
PaintSwatch.cs
Show inline comments
 
using System;
 

 
namespace DesertPaintLab
 
{
 
	[System.ComponentModel.ToolboxItem(true)]
 
	public partial class PaintSwatch : Gtk.Bin
 
	{
 
		PaintColor color;
 
		
 
		public PaintColor Color
 
		{
 
			get
 
			{
 
				return color;
 
			}
 
			
 
			set
 
			{
 
				color.Red = value.Red;
 
				color.Green = value.Green;
 
				color.Blue = value.Blue;
 
				colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
 
				rgbLabel.Text = color.Red.ToString() + ", " +
 
					            color.Green.ToString() + ", " +
 
						        color.Blue.ToString();
 
				colorNameLabel.Text = Palette.FindNearest(color);
 
			}
 
		}
 
		
 
		public PaintSwatch ()
 
		{
 
			color = new PaintColor();
 
			this.Build ();
 
		}
 
		
 
		public void Clear()
 
		{
 
			color.Clear();
 
			colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
 
			rgbLabel.Text = "???, ???, ???";
 
			colorNameLabel.Text = "Unknown";
 
		}	
 
	}
 
}
 

 
using System;
 

	
 
namespace DesertPaintLab
 
{
 
	[System.ComponentModel.ToolboxItem(true)]
 
	public partial class PaintSwatch : Gtk.Bin
 
	{
 
		PaintColor color;
 
		
 
		public PaintColor Color
 
		{
 
			get
 
			{
 
				return color;
 
			}
 
			
 
			set
 
			{
 
				color.Red = value.Red;
 
				color.Green = value.Green;
 
				color.Blue = value.Blue;
 
				colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
 
				rgbLabel.Text = color.Red.ToString() + ", " +
 
					            color.Green.ToString() + ", " +
 
						        color.Blue.ToString();
 
				colorNameLabel.Text = Palette.FindNearest(color);
 
			}
 
		}
 
		
 
		public PaintSwatch ()
 
		{
 
			color = new PaintColor();
 
			this.Build ();
 
		}
 
		
 
		public void Clear()
 
		{
 
			color.Clear();
 
			colorBox.ModifyBg(Gtk.StateType.Normal, new Gdk.Color(color.Red, color.Green, color.Blue));
 
			rgbLabel.Text = "???, ???, ???";
 
			colorNameLabel.Text = "Unknown";
 
		}	
 
	}
 
}
 

	
Palette.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

 
namespace DesertPaintLab
 
{
 
	public class Palette
 
	{
 
		static List<PaintColor> colors = new List<PaintColor>();
 
		static Regex colorEntry = new Regex(@"\#(?<red>\w\w)(?<green>\w\w)(?<blue>\w\w)\s*(?<name>\w+)");
 

 
        public static List<PaintColor> Colors
 
        {
 
            get {
 
                return colors;
 
            }
 
        }
 
		
 
		public Palette ()
 
		{
 
			
 
		}
 
		
 
		public static void Load(string file)
 
		{
 
			string line;
 
			Match match;
 
			using (StreamReader reader = new StreamReader(file))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
                {
 
					match = colorEntry.Match(line);
 
					if (match.Success)
 
					{
 
						colors.Add(new PaintColor(match.Groups["name"].Value,
 
						                          match.Groups["red"].Value,
 
						                          match.Groups["green"].Value,
 
						                          match.Groups["blue"].Value));
 
					}
 
                }
 
			}
 
		}
 

 
        public static int Count
 
        {
 
            get
 
            {
 
                return colors.Count;
 
            }
 
        }
 
		
 
		public static string FindNearest(PaintColor color)
 
		{
 
			int bestDistSq = int.MaxValue;
 
			PaintColor bestColor = null;
 
			foreach (PaintColor paintColor in colors)
 
			{
 
				int distSq = paintColor.GetDistanceSquared(color);
 
				if (distSq < bestDistSq)
 
				{
 
					bestDistSq = distSq;
 
					bestColor = paintColor;
 
				}
 
			}
 
			return bestColor.Name;
 
		}
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

	
 
namespace DesertPaintLab
 
{
 
	public class Palette
 
	{
 
		static List<PaintColor> colors = new List<PaintColor>();
 
		static Regex colorEntry = new Regex(@"\#(?<red>\w\w)(?<green>\w\w)(?<blue>\w\w)\s*(?<name>\w+)");
 

	
 
        public static List<PaintColor> Colors
 
        {
 
            get {
 
                return colors;
 
            }
 
        }
 
		
 
		public Palette ()
 
		{
 
			
 
		}
 
		
 
		public static void Load(string file)
 
		{
 
			string line;
 
			Match match;
 
			using (StreamReader reader = new StreamReader(file))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
                {
 
					match = colorEntry.Match(line);
 
					if (match.Success)
 
					{
 
						colors.Add(new PaintColor(match.Groups["name"].Value,
 
						                          match.Groups["red"].Value,
 
						                          match.Groups["green"].Value,
 
						                          match.Groups["blue"].Value));
 
					}
 
                }
 
			}
 
		}
 

	
 
        public static int Count
 
        {
 
            get
 
            {
 
                return colors.Count;
 
            }
 
        }
 
		
 
		public static string FindNearest(PaintColor color)
 
		{
 
			int bestDistSq = int.MaxValue;
 
			PaintColor bestColor = null;
 
			foreach (PaintColor paintColor in colors)
 
			{
 
				int distSq = paintColor.GetDistanceSquared(color);
 
				if (distSq < bestDistSq)
 
				{
 
					bestDistSq = distSq;
 
					bestColor = paintColor;
 
				}
 
			}
 
			return bestColor.Name;
 
		}
 
	}
 
}
 

	
PlayerProfile.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using Gtk;
 
using System;
 
using System.IO;
 
using System.IO.Compression;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

 
namespace DesertPaintLab
 
{
 
	public class PlayerProfile
 
	{
 
        public string Name { get; private set; }
 
		string directory;
 
		string reactFile;
 
        string reagentFile;
 
        string settingsFile;
 
		
 
        static Regex recipeHeaderRegex = new Regex(@"^--- Recipe: (?<colorname>(\w*\s)*\w+)\s*");
 
        static Regex recipeIngredientRegex = new Regex(@"(?<ingredient>(\w+\s)?\w+)\s*\|\s*(?<quantity>\d+)\s*");
 

 
        ReactionSet reactions = new ReactionSet();
 
        // ingredient -> [ingredient, reaction]
 
		//SortedDictionary<string, SortedDictionary<string, Reaction>> reactions =
 
		//	new SortedDictionary<string, SortedDictionary<string, Reaction>>();
 
        SortedDictionary<string, PaintRecipe> recipes;
 
        SortedDictionary<string, PaintRecipe> ribbonRecipes;
 

 
        Settings settings = new Settings();
 
        public Settings ProfileSettings { 
 
            get { 
 
                return settings;
 
            }
 
        }
 

 
        static PlayerProfile current = null;
 

 
        static PlayerProfile Current
 
        {
 
            get {
 
                return current;
 
            }
 
        }
 

 
        public string LastError { get; private set; }
 
		
 
		public PlayerProfile(string name, string directory)
 
		{
 
			this.Name = name;
 
			this.directory = directory;
 
			this.reactFile = System.IO.Path.Combine(directory, "dp_reactions.txt");
 
            this.reagentFile = System.IO.Path.Combine(directory, "ingredients.txt");
 
            this.settingsFile = System.IO.Path.Combine(directory, "settings");
 
            this.recipes = new SortedDictionary<string, PaintRecipe>();
 
            this.ribbonRecipes = new SortedDictionary<string, PaintRecipe>();
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                this.recipes.Add(color.Name, new PaintRecipe());
 
            }
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                this.ribbonRecipes.Add(color.Name, new PaintRecipe());
 
            }
 
		}
 

 
        public string Directory
 
        {
 
            get {
 
                return this.directory;
 
            }
 
        }
 

 
        public ReactionSet Reactions
 
        {
 
            get {
 
                return this.reactions;
 
            }
 
        }
 

 
        public string ReagentFile
 
        {
 
            get {
 
                return this.reagentFile;
 
            }
 
        }
 

 
        public SortedDictionary<string, PaintRecipe> Recipes
 
        {
 
            get {
 
                return this.recipes;
 
            }
 
        }
 

 
        public SortedDictionary<string, PaintRecipe> RibbonRecipes
 
        {
 
            get {
 
                return this.ribbonRecipes;
 
            }
 
        }
 

 
        public int RecipeCount
 
        {
 
            get {
 
                int count = 0;
 
                foreach (PaintRecipe recipe in this.recipes.Values)
 
                {
 
                    if (recipe.IsValidForConcentration(PaintRecipe.PAINT_RECIPE_MIN_CONCENTRATION))
 
                    {
 
                        ++count;
 
                    }
 
                }
 
                return count;
 
            }
 
        }
 

 
        public int RibbonCount
 
        {
 
            get {
 
                int count = 0;
 
                foreach (PaintRecipe recipe in this.ribbonRecipes.Values)
 
                {
 
                    if (recipe.IsValidForConcentration(PaintRecipe.RIBBON_RECIPE_MIN_CONCENTRATION))
 
                    {
 
                        ++count;
 
                    }
 
                }
 
                return count;
 
            }
 
        }
 
		
 
		public bool Initialize()
 
		{
 
            // Copy template files into new directory.
 
            string templatePath = FileUtils.FindApplicationResourceDirectory("template");
 
            
 
            if (!System.IO.Directory.Exists(templatePath))
 
            {
 
                LastError = "Failed to find profile template folder.";
 
                return false;
 
            }
 

 
			// Create new directory.
 
			System.IO.Directory.CreateDirectory(directory);
 
		    
 
			DirectoryInfo di = new DirectoryInfo(templatePath);
 
			FileInfo[] templateFiles = di.GetFiles();
 

 
			foreach (FileInfo file in templateFiles)
 
			{
 
                string destFile = System.IO.Path.Combine(directory, file.Name);
 
				System.IO.File.Copy(file.FullName, destFile, true);
 
                if (!File.Exists(destFile))
 
                {
 
                    LastError = "Failed to copy template file " + file.Name + ".";
 
                    return false;
 
                }					
 
			}
 
            return true;
 
		}
 
		
 
		public void ConvertFromPP(string ppFile, string dpFile)
 
		{
 
			string line;
 
			using (StreamReader reader = new StreamReader(ppFile))
 
			{
 
				using (StreamWriter writer = new StreamWriter(dpFile))
 
				{
 
					while ((line = reader.ReadLine()) != null) 
 
                	{
 
						string[] tokens = line.Split(null);
 
						if ((tokens.Length > 0) && (tokens[0] != "//"))
 
						{							
 
							// Write reaction.
 
							writer.Write(tokens[0] + " " + tokens[2] + " ");
 
							switch (tokens[4])
 
							{
 
							case "W":
 
								writer.WriteLine(tokens[6] + " " + tokens[6] + " " + tokens[6]);
 
								break;
 
							case "R":
 
								writer.WriteLine(tokens[6] + " 0 0");
 
								break;
 
							case "G":
 
								writer.WriteLine("0 " + tokens[6] + " 0");
 
								break;
 
							case "B":
 
								writer.WriteLine("0 0 " + tokens[6]);
 
								break;	
 
							}
 
							
 
							// Write reverse reaction.
 
							writer.Write(tokens[2] + " " + tokens[0] + " ");
 
							switch (tokens[4])
 
							{
 
							case "W":
 
								writer.WriteLine(tokens[8] + " " + tokens[8] + " " + tokens[8]);
 
								break;
 
							case "R":
 
								writer.WriteLine(tokens[8] + " 0 0");
 
								break;
 
							case "G":
 
								writer.WriteLine("0 " + tokens[8] + " 0");
 
								break;
 
							case "B":
 
								writer.WriteLine("0 0 " + tokens[8]);
 
								break;	
 
							}							
 
						}
 
					}
 
				}
 
			}
 
		}
 
		
 
		public bool SaveToPP(string ppFile)
 
		{
 
			Reaction reaction1, reaction2;
 
			using (StreamWriter writer = new StreamWriter(ppFile))
 
			{
 
                foreach (string reagentName1 in ReagentManager.Names)
 
                {
 
                    // TODO: could be more efficient by only iterating over the names after reagent1
 
                    foreach (string reagentName2 in ReagentManager.Names)
 
                    {
 
                        if (reagentName1.Equals(reagentName2))
 
                        {
 
                            continue;
 
                        }
 
                        Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                        Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                        reaction1 = reactions.Find(reagent1, reagent2);
 
                        if (reaction1 != null && !reaction1.Exported)
 
                        {
 
                            reaction2 = reactions.Find(reagent2, reagent1);
 
                            if (reaction2 != null)
 
                            {
 
								writer.Write(reagent1.PracticalPaintName + " | " + reagent2.PracticalPaintName + " | ");
 
								if ((Math.Abs(reaction1.Red) > Math.Abs(reaction1.Green)) ||
 
								    (Math.Abs(reaction2.Red) > Math.Abs(reaction2.Green)))
 
								{
 
									writer.WriteLine("R | " + reaction1.Red + " | " + reaction2.Red);	
 
								}
 
								else if ((Math.Abs(reaction1.Green) > Math.Abs(reaction1.Red)) ||
 
									(Math.Abs(reaction2.Green) > Math.Abs(reaction2.Red)))
 
								{
 
									writer.WriteLine("G | " + reaction1.Green + " | " + reaction2.Green);	
 
								}
 
								else if ((Math.Abs(reaction1.Blue) > Math.Abs(reaction1.Red)) ||
 
									(Math.Abs(reaction2.Blue) > Math.Abs(reaction2.Red)))
 
								{
 
									writer.WriteLine("B | " + reaction1.Blue + " | " + reaction2.Blue);
 
								}
 
								else
 
								{
 
									writer.WriteLine("W | " + reaction1.Red + " | " + reaction2.Red);	
 
								}
 
								reaction1.Exported = true;
 
								reaction2.Exported = true;
 
							}
 
						}
 
					}
 
				}
 
			}
 
			
 
			// Clear Exported flags.
 
            foreach (string reagentName1 in ReagentManager.Names)
 
            {
 
                // TODO: could be more efficient by only iterating over the names after reagent1
 
                foreach (string reagentName2 in ReagentManager.Names)
 
                {
 
                    if (reagentName1.Equals(reagentName2))
 
                    {
 
                        continue;
 
                    }
 
                    Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                    Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                    reaction1 = reactions.Find(reagent1, reagent2);
 
                    if (reaction1 != null)
 
                    {   
 
                        reaction1.Exported = false;
 
                    }
 
                    reaction2 = reactions.Find(reagent2, reagent1);
 
                    if (reaction2 != null)
 
                    {
 
                        reaction2.Exported = false;
 
                    }
 
				}
 
			}
 
			return true;
 
		}
 
		
 
		public void ImportFromPP(string importDir)
 
		{
 
			// Convert old file.
 
			ConvertFromPP(
 
			    System.IO.Path.Combine(importDir, "reactions.txt"),
 
				reactFile);
 
			try
 
			{
 
				// If there is an ingredients file, move it in.
 
				System.IO.File.Copy(
 
				    System.IO.Path.Combine(importDir, "ingredients.txt"),
 
				    System.IO.Path.Combine(directory, "ingredients.txt"),
 
				    true);
 
			}
 
			catch (Exception)
 
			{
 
				// If there is no ingredients file, we don't really care.	
 
			}
 
		}
 
		
 
        public void Import(string file)
 
        {
 
            ZipFile.ExtractToDirectory(file, directory);
 
        }
 

 
		public void Export(string file)
 
		{
 
            ZipFile.CreateFromDirectory(directory, file);
 
		}
 
		
 
		public bool Load()
 
		{
 
			string line;
 
            settings.Reset();
 
            settings.Load(settingsFile);
 
			reactions.Clear();
 
            if (File.Exists(reagentFile))
 
            {
 
    			ReagentManager.LoadProfileReagents(reagentFile);
 
            }
 
            else
 
            {
 
                LastError = "Failed to find profile reagents file.";
 
                return false;
 
            }
 
			ReagentManager.InitializeReactions(ref reactions);
 
            if (!File.Exists(reactFile))
 
            {
 
                LastError = "Failed to find profile reactions file.";
 
                return false;
 
            }
 
			using (StreamReader reader = new StreamReader(reactFile))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
               	{
 
					string[] tokens = line.Split(null);
 
                    Reagent reagent1 = ReagentManager.GetReagent(tokens[0]);
 
                    Reagent reagent2 = ReagentManager.GetReagent(tokens[1]);
 
					reactions.Set(reagent1, reagent2, new Reaction(int.Parse(tokens[2]), int.Parse(tokens[3]), int.Parse(tokens[4])));
 
				}
 
			}
 
            return true;
 
		}
 
		
 
		public void Save()
 
		{
 
            settings.Save(settingsFile);
 
			Reaction reaction;
 
			using (StreamWriter writer = new StreamWriter(reactFile, false))
 
			{
 
                foreach (string reagentName1 in ReagentManager.Names)
 
                {
 
                    // TODO: could be more efficient by only iterating over the names after reagent1
 
                    foreach (string reagentName2 in ReagentManager.Names)
 
                    {
 
                        if (reagentName1.Equals(reagentName2))
 
                        {
 
                            continue;
 
                        }
 
                        Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                        Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                        reaction = reactions.Find(reagent1, reagent2);
 
    					if (reaction != null)
 
    					{
 
                                writer.WriteLine(reagent1.PracticalPaintName + " " + reagent2.PracticalPaintName + " " +
 
    							reaction.Red + " " + reaction.Green + " " + reaction.Blue);
 
    					}
 
    				}
 
    			}
 
            }
 
		}
 

 
        private void LoadRecipes(SortedDictionary<string, PaintRecipe> recipeDict, string filename, uint concentration)
 
        {
 
            foreach (PaintRecipe recipe in recipeDict.Values)
 
            {
 
                recipe.Clear();
 
            }
 
            string recipeFile = System.IO.Path.Combine(directory, filename);
 
            string line;
 
            Match match;
 
            bool inRecipe = false;
 
            PaintRecipe testRecipe = new PaintRecipe();
 
            testRecipe.Reactions = reactions;
 
            string currentRecipeColor = null;
 
            if (File.Exists(recipeFile))
 
            {
 
                using (StreamReader reader = new StreamReader(recipeFile))
 
                {
 
                    while ((line = reader.ReadLine()) != null) 
 
                    {
 
                        match = recipeHeaderRegex.Match(line); 
 
                        if (match.Success)
 
                        {
 
                            if (testRecipe != null && currentRecipeColor != null)
 
                            {
 
                                if (testRecipe.IsValidForConcentration(concentration))
 
                                {
 
                                    recipeDict[currentRecipeColor].CopyFrom(testRecipe);
 
                                }
 
                            }
 
                            testRecipe.Clear();
 
                            currentRecipeColor = match.Groups["colorname"].Value;
 
                            inRecipe = true;
 
                        }
 
                        else if (inRecipe)
 
                        {
 
                            match = recipeIngredientRegex.Match(line);
 
                            if (match.Success)
 
                            {
 
                                string ingredient = match.Groups["ingredient"].Value;
 
                                uint quantity = uint.Parse(match.Groups["quantity"].Value);
 
                                testRecipe.AddReagent(ingredient, quantity);
 
                            }
 
                        }
 
                    }
 
                    if (inRecipe)
 
                    {
 
                        if (testRecipe.IsValidForConcentration(concentration))
 
                        {
 
                            recipeDict[currentRecipeColor].CopyFrom(testRecipe);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 

 
        private void SaveRecipes(SortedDictionary<string, PaintRecipe> recipeDict, string filename)
 
        {
 
            if (recipeDict != null)
 
            {
 
                string recipeFile = System.IO.Path.Combine(directory, filename);
 
                using (StreamWriter writer = new StreamWriter(recipeFile, false))
 
                {
 
                    foreach (KeyValuePair<string, PaintRecipe> pair in recipeDict)
 
                    {
 
                        writer.WriteLine("--- Recipe: {0}", pair.Key);
 
                        foreach (PaintRecipe.RecipeIngredient ingredient in pair.Value.Ingredients)
 
                        {
 
                            writer.WriteLine("{0,-14} | {1}", ingredient.name, ingredient.quantity);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 

 
        public void LoadRecipes()
 
        {
 
            LoadRecipes(this.recipes, "dp_recipes.txt", PaintRecipe.PAINT_RECIPE_MIN_CONCENTRATION);
 
            LoadRecipes(this.ribbonRecipes, "dp_ribbons.txt", PaintRecipe.RIBBON_RECIPE_MIN_CONCENTRATION);
 
        }
 

 
        public void SaveRecipes()
 
        {
 
            SaveRecipes(this.recipes, "dp_recipes.txt");
 
            SaveRecipes(this.ribbonRecipes, "dp_ribbons.txt");
 
        }
 

 
        public void ExportWikiRecipes(string file)
 
        {
 
            StreamWriter writer = new StreamWriter(file);
 
            ExportWikiFormat(writer, this.recipes);
 
        }
 
		
 
        public void ExportWikiRibbons(string file)
 
        {
 
            StreamWriter writer = new StreamWriter(file);
 
            ExportWikiFormat(writer, this.ribbonRecipes);
 
        }
 
        
 
        public void ExportWikiRecipes(TextWriter writer)
 
        {
 
            ExportWikiFormat(writer, this.recipes);
 
        }
 
        
 
        public void ExportWikiRibbons(TextWriter writer)
 
        {
 
            ExportWikiFormat(writer, this.ribbonRecipes);
 
        }
 
        
 
        public void ExportWikiFormat(TextWriter writer, SortedDictionary<string, PaintRecipe> recipeDict)
 
        {
 
            PaintRecipe recipe;
 
            List<KeyValuePair<string, string>> missing = new List<KeyValuePair<string, string>>();
 
            using (writer)
 
            {
 
                writer.WriteLine("{| class='wikitable sortable' border=\"1\" style=\"background-color:#DEB887;\"");
 
                writer.WriteLine("! Color !! Recipe !! Verified");    
 
                foreach (PaintColor color in Palette.Colors)
 
                {
 
                    writer.WriteLine("|-");
 
                    string colorLine = "| ";
 
                    colorLine += "style=\"font-weight: bold; background-color: #" + color.Red.ToString("X2") + color.Green.ToString("X2") + color.Blue.ToString("X2") + ";";
 
                    float rPortion = color.Red / 255.0f;
 
                    float gPortion = color.Green / 255.0f;
 
                    float bPortion = color.Blue / 255.0f;
 
                    float maxColor = Math.Max(rPortion, Math.Max(gPortion, bPortion));
 
                    float minColor = Math.Min(rPortion, Math.Min(gPortion, bPortion));
 
                    float luminance = (maxColor - minColor) * 0.5f;
 
                    if (luminance < 0.5f)
 
                    {
 
                        // dark color gets light text
 
                        colorLine += " color: #FFFFFF;";
 
                    }
 
                    colorLine += "\" | " + color.Name + " || ";
 
                    if (recipeDict.TryGetValue(color.Name, out recipe))
 
                    {
 
                        foreach (PaintRecipe.RecipeIngredient ingredient in recipe.Ingredients)
 
                        {
 
                            colorLine += " " + ingredient.ToString();
 
                        }
 
                    } 
 
                    else
 
                    {
 
                        // no recipe
 
                    }
 
                    colorLine += " || ";
 
                    
 
                    if (recipe.CheckMissingReactions(ref missing) == false)
 
                    {
 
                        colorLine += "Y";
 
                    }
 
                    writer.WriteLine(colorLine);
 
                }
 
                writer.WriteLine("|}");
 
            }
 
        }
 
 
 
		public Reaction FindReaction(Reagent reagent1, Reagent reagent2)
 
		{
 
            return reactions.Find(reagent1, reagent2);
 
		}
 
		
 
		public void SetReaction(Reagent reagent1, Reagent reagent2, Reaction reaction)
 
		{
 
            reactions.Set(reagent1, reagent2, reaction);
 
		}
 

 
        public void ClearReaction(Reagent reagent1, Reagent reagent2)
 
        {
 
            reactions.Remove(reagent1, reagent2);
 
        }
 

 
        public void SetRecipe(PaintRecipe recipe)
 
        {
 
            string colorName = Palette.FindNearest(recipe.ReactedColor);
 
            recipes[colorName].CopyFrom(recipe);
 
        }
 

 
        public void SetRibbonRecipe(PaintRecipe recipe)
 
        {
 
            string colorName = Palette.FindNearest(recipe.ReactedColor);
 
            ribbonRecipes[colorName].CopyFrom(recipe);
 
        }
 

 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using Gtk;
 
using System;
 
using System.IO;
 
using System.IO.Compression;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

	
 
namespace DesertPaintLab
 
{
 
	public class PlayerProfile
 
	{
 
        public string Name { get; private set; }
 
		string directory;
 
		string reactFile;
 
        string reagentFile;
 
        string settingsFile;
 
		
 
        static Regex recipeHeaderRegex = new Regex(@"^--- Recipe: (?<colorname>(\w*\s)*\w+)\s*");
 
        static Regex recipeIngredientRegex = new Regex(@"(?<ingredient>(\w+\s)?\w+)\s*\|\s*(?<quantity>\d+)\s*");
 

	
 
        ReactionSet reactions = new ReactionSet();
 
        // ingredient -> [ingredient, reaction]
 
		//SortedDictionary<string, SortedDictionary<string, Reaction>> reactions =
 
		//	new SortedDictionary<string, SortedDictionary<string, Reaction>>();
 
        SortedDictionary<string, PaintRecipe> recipes;
 
        SortedDictionary<string, PaintRecipe> ribbonRecipes;
 

	
 
        Settings settings = new Settings();
 
        public Settings ProfileSettings { 
 
            get { 
 
                return settings;
 
            }
 
        }
 

	
 
        static PlayerProfile current = null;
 

	
 
        static PlayerProfile Current
 
        {
 
            get {
 
                return current;
 
            }
 
        }
 

	
 
        public string LastError { get; private set; }
 
		
 
		public PlayerProfile(string name, string directory)
 
		{
 
			this.Name = name;
 
			this.directory = directory;
 
			this.reactFile = System.IO.Path.Combine(directory, "dp_reactions.txt");
 
            this.reagentFile = System.IO.Path.Combine(directory, "ingredients.txt");
 
            this.settingsFile = System.IO.Path.Combine(directory, "settings");
 
            this.recipes = new SortedDictionary<string, PaintRecipe>();
 
            this.ribbonRecipes = new SortedDictionary<string, PaintRecipe>();
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                this.recipes.Add(color.Name, new PaintRecipe());
 
            }
 
            foreach (PaintColor color in Palette.Colors)
 
            {
 
                this.ribbonRecipes.Add(color.Name, new PaintRecipe());
 
            }
 
		}
 

	
 
        public string Directory
 
        {
 
            get {
 
                return this.directory;
 
            }
 
        }
 

	
 
        public ReactionSet Reactions
 
        {
 
            get {
 
                return this.reactions;
 
            }
 
        }
 

	
 
        public string ReagentFile
 
        {
 
            get {
 
                return this.reagentFile;
 
            }
 
        }
 

	
 
        public SortedDictionary<string, PaintRecipe> Recipes
 
        {
 
            get {
 
                return this.recipes;
 
            }
 
        }
 

	
 
        public SortedDictionary<string, PaintRecipe> RibbonRecipes
 
        {
 
            get {
 
                return this.ribbonRecipes;
 
            }
 
        }
 

	
 
        public int RecipeCount
 
        {
 
            get {
 
                int count = 0;
 
                foreach (PaintRecipe recipe in this.recipes.Values)
 
                {
 
                    if (recipe.IsValidForConcentration(PaintRecipe.PAINT_RECIPE_MIN_CONCENTRATION))
 
                    {
 
                        ++count;
 
                    }
 
                }
 
                return count;
 
            }
 
        }
 

	
 
        public int RibbonCount
 
        {
 
            get {
 
                int count = 0;
 
                foreach (PaintRecipe recipe in this.ribbonRecipes.Values)
 
                {
 
                    if (recipe.IsValidForConcentration(PaintRecipe.RIBBON_RECIPE_MIN_CONCENTRATION))
 
                    {
 
                        ++count;
 
                    }
 
                }
 
                return count;
 
            }
 
        }
 
		
 
		public bool Initialize()
 
		{
 
            // Copy template files into new directory.
 
            string templatePath = FileUtils.FindApplicationResourceDirectory("template");
 
            
 
            if (!System.IO.Directory.Exists(templatePath))
 
            {
 
                LastError = "Failed to find profile template folder.";
 
                return false;
 
            }
 

	
 
			// Create new directory.
 
			System.IO.Directory.CreateDirectory(directory);
 
		    
 
			DirectoryInfo di = new DirectoryInfo(templatePath);
 
			FileInfo[] templateFiles = di.GetFiles();
 

	
 
			foreach (FileInfo file in templateFiles)
 
			{
 
                string destFile = System.IO.Path.Combine(directory, file.Name);
 
				System.IO.File.Copy(file.FullName, destFile, true);
 
                if (!File.Exists(destFile))
 
                {
 
                    LastError = "Failed to copy template file " + file.Name + ".";
 
                    return false;
 
                }					
 
			}
 
            return true;
 
		}
 
		
 
		public void ConvertFromPP(string ppFile, string dpFile)
 
		{
 
			string line;
 
			using (StreamReader reader = new StreamReader(ppFile))
 
			{
 
				using (StreamWriter writer = new StreamWriter(dpFile))
 
				{
 
					while ((line = reader.ReadLine()) != null) 
 
                	{
 
						string[] tokens = line.Split(null);
 
						if ((tokens.Length > 0) && (tokens[0] != "//"))
 
						{							
 
							// Write reaction.
 
							writer.Write(tokens[0] + " " + tokens[2] + " ");
 
							switch (tokens[4])
 
							{
 
							case "W":
 
								writer.WriteLine(tokens[6] + " " + tokens[6] + " " + tokens[6]);
 
								break;
 
							case "R":
 
								writer.WriteLine(tokens[6] + " 0 0");
 
								break;
 
							case "G":
 
								writer.WriteLine("0 " + tokens[6] + " 0");
 
								break;
 
							case "B":
 
								writer.WriteLine("0 0 " + tokens[6]);
 
								break;	
 
							}
 
							
 
							// Write reverse reaction.
 
							writer.Write(tokens[2] + " " + tokens[0] + " ");
 
							switch (tokens[4])
 
							{
 
							case "W":
 
								writer.WriteLine(tokens[8] + " " + tokens[8] + " " + tokens[8]);
 
								break;
 
							case "R":
 
								writer.WriteLine(tokens[8] + " 0 0");
 
								break;
 
							case "G":
 
								writer.WriteLine("0 " + tokens[8] + " 0");
 
								break;
 
							case "B":
 
								writer.WriteLine("0 0 " + tokens[8]);
 
								break;	
 
							}							
 
						}
 
					}
 
				}
 
			}
 
		}
 
		
 
		public bool SaveToPP(string ppFile)
 
		{
 
			Reaction reaction1, reaction2;
 
			using (StreamWriter writer = new StreamWriter(ppFile))
 
			{
 
                foreach (string reagentName1 in ReagentManager.Names)
 
                {
 
                    // TODO: could be more efficient by only iterating over the names after reagent1
 
                    foreach (string reagentName2 in ReagentManager.Names)
 
                    {
 
                        if (reagentName1.Equals(reagentName2))
 
                        {
 
                            continue;
 
                        }
 
                        Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                        Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                        reaction1 = reactions.Find(reagent1, reagent2);
 
                        if (reaction1 != null && !reaction1.Exported)
 
                        {
 
                            reaction2 = reactions.Find(reagent2, reagent1);
 
                            if (reaction2 != null)
 
                            {
 
								writer.Write(reagent1.PracticalPaintName + " | " + reagent2.PracticalPaintName + " | ");
 
								if ((Math.Abs(reaction1.Red) > Math.Abs(reaction1.Green)) ||
 
								    (Math.Abs(reaction2.Red) > Math.Abs(reaction2.Green)))
 
								{
 
									writer.WriteLine("R | " + reaction1.Red + " | " + reaction2.Red);	
 
								}
 
								else if ((Math.Abs(reaction1.Green) > Math.Abs(reaction1.Red)) ||
 
									(Math.Abs(reaction2.Green) > Math.Abs(reaction2.Red)))
 
								{
 
									writer.WriteLine("G | " + reaction1.Green + " | " + reaction2.Green);	
 
								}
 
								else if ((Math.Abs(reaction1.Blue) > Math.Abs(reaction1.Red)) ||
 
									(Math.Abs(reaction2.Blue) > Math.Abs(reaction2.Red)))
 
								{
 
									writer.WriteLine("B | " + reaction1.Blue + " | " + reaction2.Blue);
 
								}
 
								else
 
								{
 
									writer.WriteLine("W | " + reaction1.Red + " | " + reaction2.Red);	
 
								}
 
								reaction1.Exported = true;
 
								reaction2.Exported = true;
 
							}
 
						}
 
					}
 
				}
 
			}
 
			
 
			// Clear Exported flags.
 
            foreach (string reagentName1 in ReagentManager.Names)
 
            {
 
                // TODO: could be more efficient by only iterating over the names after reagent1
 
                foreach (string reagentName2 in ReagentManager.Names)
 
                {
 
                    if (reagentName1.Equals(reagentName2))
 
                    {
 
                        continue;
 
                    }
 
                    Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                    Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                    reaction1 = reactions.Find(reagent1, reagent2);
 
                    if (reaction1 != null)
 
                    {   
 
                        reaction1.Exported = false;
 
                    }
 
                    reaction2 = reactions.Find(reagent2, reagent1);
 
                    if (reaction2 != null)
 
                    {
 
                        reaction2.Exported = false;
 
                    }
 
				}
 
			}
 
			return true;
 
		}
 
		
 
		public void ImportFromPP(string importDir)
 
		{
 
			// Convert old file.
 
			ConvertFromPP(
 
			    System.IO.Path.Combine(importDir, "reactions.txt"),
 
				reactFile);
 
			try
 
			{
 
				// If there is an ingredients file, move it in.
 
				System.IO.File.Copy(
 
				    System.IO.Path.Combine(importDir, "ingredients.txt"),
 
				    System.IO.Path.Combine(directory, "ingredients.txt"),
 
				    true);
 
			}
 
			catch (Exception)
 
			{
 
				// If there is no ingredients file, we don't really care.	
 
			}
 
		}
 
		
 
        public void Import(string file)
 
        {
 
            ZipFile.ExtractToDirectory(file, directory);
 
        }
 

	
 
		public void Export(string file)
 
		{
 
            ZipFile.CreateFromDirectory(directory, file);
 
		}
 
		
 
		public bool Load()
 
		{
 
			string line;
 
            settings.Reset();
 
            settings.Load(settingsFile);
 
			reactions.Clear();
 
            if (File.Exists(reagentFile))
 
            {
 
    			ReagentManager.LoadProfileReagents(reagentFile);
 
            }
 
            else
 
            {
 
                LastError = "Failed to find profile reagents file.";
 
                return false;
 
            }
 
			ReagentManager.InitializeReactions(ref reactions);
 
            if (!File.Exists(reactFile))
 
            {
 
                LastError = "Failed to find profile reactions file.";
 
                return false;
 
            }
 
			using (StreamReader reader = new StreamReader(reactFile))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
               	{
 
					string[] tokens = line.Split(null);
 
                    Reagent reagent1 = ReagentManager.GetReagent(tokens[0]);
 
                    Reagent reagent2 = ReagentManager.GetReagent(tokens[1]);
 
					reactions.Set(reagent1, reagent2, new Reaction(int.Parse(tokens[2]), int.Parse(tokens[3]), int.Parse(tokens[4])));
 
				}
 
			}
 
            return true;
 
		}
 
		
 
		public void Save()
 
		{
 
            settings.Save(settingsFile);
 
			Reaction reaction;
 
			using (StreamWriter writer = new StreamWriter(reactFile, false))
 
			{
 
                foreach (string reagentName1 in ReagentManager.Names)
 
                {
 
                    // TODO: could be more efficient by only iterating over the names after reagent1
 
                    foreach (string reagentName2 in ReagentManager.Names)
 
                    {
 
                        if (reagentName1.Equals(reagentName2))
 
                        {
 
                            continue;
 
                        }
 
                        Reagent reagent1 = ReagentManager.GetReagent(reagentName1);
 
                        Reagent reagent2 = ReagentManager.GetReagent(reagentName2);
 
                        reaction = reactions.Find(reagent1, reagent2);
 
    					if (reaction != null)
 
    					{
 
                                writer.WriteLine(reagent1.PracticalPaintName + " " + reagent2.PracticalPaintName + " " +
 
    							reaction.Red + " " + reaction.Green + " " + reaction.Blue);
 
    					}
 
    				}
 
    			}
 
            }
 
		}
 

	
 
        private void LoadRecipes(SortedDictionary<string, PaintRecipe> recipeDict, string filename, uint concentration)
 
        {
 
            foreach (PaintRecipe recipe in recipeDict.Values)
 
            {
 
                recipe.Clear();
 
            }
 
            string recipeFile = System.IO.Path.Combine(directory, filename);
 
            string line;
 
            Match match;
 
            bool inRecipe = false;
 
            PaintRecipe testRecipe = new PaintRecipe();
 
            testRecipe.Reactions = reactions;
 
            string currentRecipeColor = null;
 
            if (File.Exists(recipeFile))
 
            {
 
                using (StreamReader reader = new StreamReader(recipeFile))
 
                {
 
                    while ((line = reader.ReadLine()) != null) 
 
                    {
 
                        match = recipeHeaderRegex.Match(line); 
 
                        if (match.Success)
 
                        {
 
                            if (testRecipe != null && currentRecipeColor != null)
 
                            {
 
                                if (testRecipe.IsValidForConcentration(concentration))
 
                                {
 
                                    recipeDict[currentRecipeColor].CopyFrom(testRecipe);
 
                                }
 
                            }
 
                            testRecipe.Clear();
 
                            currentRecipeColor = match.Groups["colorname"].Value;
 
                            inRecipe = true;
 
                        }
 
                        else if (inRecipe)
 
                        {
 
                            match = recipeIngredientRegex.Match(line);
 
                            if (match.Success)
 
                            {
 
                                string ingredient = match.Groups["ingredient"].Value;
 
                                uint quantity = uint.Parse(match.Groups["quantity"].Value);
 
                                testRecipe.AddReagent(ingredient, quantity);
 
                            }
 
                        }
 
                    }
 
                    if (inRecipe)
 
                    {
 
                        if (testRecipe.IsValidForConcentration(concentration))
 
                        {
 
                            recipeDict[currentRecipeColor].CopyFrom(testRecipe);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 

	
 
        private void SaveRecipes(SortedDictionary<string, PaintRecipe> recipeDict, string filename)
 
        {
 
            if (recipeDict != null)
 
            {
 
                string recipeFile = System.IO.Path.Combine(directory, filename);
 
                using (StreamWriter writer = new StreamWriter(recipeFile, false))
 
                {
 
                    foreach (KeyValuePair<string, PaintRecipe> pair in recipeDict)
 
                    {
 
                        writer.WriteLine("--- Recipe: {0}", pair.Key);
 
                        foreach (PaintRecipe.RecipeIngredient ingredient in pair.Value.Ingredients)
 
                        {
 
                            writer.WriteLine("{0,-14} | {1}", ingredient.name, ingredient.quantity);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 

	
 
        public void LoadRecipes()
 
        {
 
            LoadRecipes(this.recipes, "dp_recipes.txt", PaintRecipe.PAINT_RECIPE_MIN_CONCENTRATION);
 
            LoadRecipes(this.ribbonRecipes, "dp_ribbons.txt", PaintRecipe.RIBBON_RECIPE_MIN_CONCENTRATION);
 
        }
 

	
 
        public void SaveRecipes()
 
        {
 
            SaveRecipes(this.recipes, "dp_recipes.txt");
 
            SaveRecipes(this.ribbonRecipes, "dp_ribbons.txt");
 
        }
 

	
 
        public void ExportWikiRecipes(string file)
 
        {
 
            StreamWriter writer = new StreamWriter(file);
 
            ExportWikiFormat(writer, this.recipes);
 
        }
 
		
 
        public void ExportWikiRibbons(string file)
 
        {
 
            StreamWriter writer = new StreamWriter(file);
 
            ExportWikiFormat(writer, this.ribbonRecipes);
 
        }
 
        
 
        public void ExportWikiRecipes(TextWriter writer)
 
        {
 
            ExportWikiFormat(writer, this.recipes);
 
        }
 
        
 
        public void ExportWikiRibbons(TextWriter writer)
 
        {
 
            ExportWikiFormat(writer, this.ribbonRecipes);
 
        }
 
        
 
        public void ExportWikiFormat(TextWriter writer, SortedDictionary<string, PaintRecipe> recipeDict)
 
        {
 
            PaintRecipe recipe;
 
            List<KeyValuePair<string, string>> missing = new List<KeyValuePair<string, string>>();
 
            using (writer)
 
            {
 
                writer.WriteLine("{| class='wikitable sortable' border=\"1\" style=\"background-color:#DEB887;\"");
 
                writer.WriteLine("! Color !! Recipe !! Verified");    
 
                foreach (PaintColor color in Palette.Colors)
 
                {
 
                    writer.WriteLine("|-");
 
                    string colorLine = "| ";
 
                    colorLine += "style=\"font-weight: bold; background-color: #" + color.Red.ToString("X2") + color.Green.ToString("X2") + color.Blue.ToString("X2") + ";";
 
                    float rPortion = color.Red / 255.0f;
 
                    float gPortion = color.Green / 255.0f;
 
                    float bPortion = color.Blue / 255.0f;
 
                    float maxColor = Math.Max(rPortion, Math.Max(gPortion, bPortion));
 
                    float minColor = Math.Min(rPortion, Math.Min(gPortion, bPortion));
 
                    float luminance = (maxColor - minColor) * 0.5f;
 
                    if (luminance < 0.5f)
 
                    {
 
                        // dark color gets light text
 
                        colorLine += " color: #FFFFFF;";
 
                    }
 
                    colorLine += "\" | " + color.Name + " || ";
 
                    if (recipeDict.TryGetValue(color.Name, out recipe))
 
                    {
 
                        foreach (PaintRecipe.RecipeIngredient ingredient in recipe.Ingredients)
 
                        {
 
                            colorLine += " " + ingredient.ToString();
 
                        }
 
                    } 
 
                    else
 
                    {
 
                        // no recipe
 
                    }
 
                    colorLine += " || ";
 
                    
 
                    if (recipe.CheckMissingReactions(ref missing) == false)
 
                    {
 
                        colorLine += "Y";
 
                    }
 
                    writer.WriteLine(colorLine);
 
                }
 
                writer.WriteLine("|}");
 
            }
 
        }
 
 
 
		public Reaction FindReaction(Reagent reagent1, Reagent reagent2)
 
		{
 
            return reactions.Find(reagent1, reagent2);
 
		}
 
		
 
		public void SetReaction(Reagent reagent1, Reagent reagent2, Reaction reaction)
 
		{
 
            reactions.Set(reagent1, reagent2, reaction);
 
		}
 

	
 
        public void ClearReaction(Reagent reagent1, Reagent reagent2)
 
        {
 
            reactions.Remove(reagent1, reagent2);
 
        }
 

	
 
        public void SetRecipe(PaintRecipe recipe)
 
        {
 
            string colorName = Palette.FindNearest(recipe.ReactedColor);
 
            recipes[colorName].CopyFrom(recipe);
 
        }
 

	
 
        public void SetRibbonRecipe(PaintRecipe recipe)
 
        {
 
            string colorName = Palette.FindNearest(recipe.ReactedColor);
 
            ribbonRecipes[colorName].CopyFrom(recipe);
 
        }
 

	
 
	}
 
}
 

	
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/tale7/File:PracticalPaint.Zip) data format.
 
* Includes simulator for experimenting with recipes without spending ingredients.
 
* Includes a recipe generator
 

 
## Tale 8
 

 
This application has not yet been tested for Tale 8.  We will be testing it out as soon as we get our hands on a Pigment Lab.  If you find any problems with it, please [open an issue](https://bitbucket.org/Malkyne/desert-paint-lab/issues) or /chat Afrah or Snoerr
 
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 15](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC15.zip). For Mac, you can download a [dmg containing a Mac app bundle](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC15.dmg).
 

 
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. On Mac or Linux, download and install the [Mono runtime](http://www.mono-project.com/download).
 

 
### 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.
 

 
1. In your clipped reaction, let's call your **1st** ingredient **A** and your **2nd** ingredient **B**.
 
1. Select a **non-catalyst** ingredient **C** for which you have already tested **C + A** and **C + B**.  It is OK if there was a reaction in those earlier tests.  Desert Paint Lab can work out the math.
 
1. In Desert Paint Lab, select ingredients as follows:
 
    1. **C**
 
    2. **A**
 
    3. **B**
 
1. Add the ingredients in your Pigment Lab _in exactly that order_.
 
1. Capture.
 
1. Record.
 

 
For clipped reactions, your **C** ingredient should be one that corrects for the clipped color.  Here are some suggested **C** ingredients for clipping correction:
 

 

 
Clip Color  | Clip Direction | Correction | Suggested "C" Ingredient
 
------------|----------------|------------|---------------------------
 
Red         | Low            | +Red       | Carrot (224) or Red Sand (144)
 
Red         | High           | -Red       | Silver Powder (16) or Toad Skin (48)
 
Green       | Low            | +Green     | Earth Light (240) or Copper (192)
 
Green       | High           | -Green     | Red Sand (16) or Silver Powder (16)
 
Blue        | Low            | +Blue      | Earth Light (224) or Copper (192)
 
Blue        | High           | -Blue      | Red Sand (24) or Clay (32) or Carrot (32) or Silver Powder (32)
 

 

 
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.
 

 
### Catalysts
 

 
For catalyst to catalyst reaction tests, follow the three-way instructions, as above.
 

 
### 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.
 

 
### Multiple Displays
 

 
When Desert Paint Lab asks for the resolution for a multiple-display setup, enter the combined resolution of all displays. Generally the detected default for this will be correct. For example, two 1920x1080 displays in a side-by-side configuration would be a combined resolution of 3840x1080. In a stacked configuration, they would be 1920x2160.
 

 
### Retina / High-Density Screens
 

 
High DPI screens may be displaying the game at something other than a 1:1 game-pixel to screen-pixel ratio.  These screens didn't exist, back when Desert Paint Lab was created. The current version now prompts you for your screen resolution when it starts to work around this. If you see a crash when trying to capture a reaction, it's likely because the resolution is incorrect. For example, Snoerr's MacBook Pro has a retina screen with a resolution of 2880x1800. Mono (and therefore DesertPaintLab) detects it as having a resolution of 1440x900. He enters his resolution as 2880x1800 and sets the Game pixel width in screen pixels to 2.
 

 
## Mac user FAQ
 

 
Q: How do I find my native screen resolution?
 

 
A: You can find it by opening up "About this Mac" from the Apple menu and clicking on the "Displays" tab. That should show the screen size and resolution to enter.
 

 
## 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/).
 
# 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/tale7/File:PracticalPaint.Zip) data format.
 
* Includes simulator for experimenting with recipes without spending ingredients.
 
* Includes a recipe generator
 

	
 
## Tale 8
 

	
 
This application has not yet been tested for Tale 8.  We will be testing it out as soon as we get our hands on a Pigment Lab.  If you find any problems with it, please [open an issue](https://bitbucket.org/Malkyne/desert-paint-lab/issues) or /chat Afrah or Snoerr
 
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 15](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC15.zip). For Mac, you can download a [dmg containing a Mac app bundle](https://bitbucket.org/Malkyne/desert-paint-lab/downloads/DesertPaintLab_T7_RC15.dmg).
 

	
 
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. On Mac or Linux, download and install the [Mono runtime](http://www.mono-project.com/download).
 

	
 
### 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.
 

	
 
1. In your clipped reaction, let's call your **1st** ingredient **A** and your **2nd** ingredient **B**.
 
1. Select a **non-catalyst** ingredient **C** for which you have already tested **C + A** and **C + B**.  It is OK if there was a reaction in those earlier tests.  Desert Paint Lab can work out the math.
 
1. In Desert Paint Lab, select ingredients as follows:
 
    1. **C**
 
    2. **A**
 
    3. **B**
 
1. Add the ingredients in your Pigment Lab _in exactly that order_.
 
1. Capture.
 
1. Record.
 

	
 
For clipped reactions, your **C** ingredient should be one that corrects for the clipped color.  Here are some suggested **C** ingredients for clipping correction:
 

	
 

	
 
Clip Color  | Clip Direction | Correction | Suggested "C" Ingredient
 
------------|----------------|------------|---------------------------
 
Red         | Low            | +Red       | Carrot (224) or Red Sand (144)
 
Red         | High           | -Red       | Silver Powder (16) or Toad Skin (48)
 
Green       | Low            | +Green     | Earth Light (240) or Copper (192)
 
Green       | High           | -Green     | Red Sand (16) or Silver Powder (16)
 
Blue        | Low            | +Blue      | Earth Light (224) or Copper (192)
 
Blue        | High           | -Blue      | Red Sand (24) or Clay (32) or Carrot (32) or Silver Powder (32)
 

	
 

	
 
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.
 

	
 
### Catalysts
 

	
 
For catalyst to catalyst reaction tests, follow the three-way instructions, as above.
 

	
 
### 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.
 

	
 
### Multiple Displays
 

	
 
When Desert Paint Lab asks for the resolution for a multiple-display setup, enter the combined resolution of all displays. Generally the detected default for this will be correct. For example, two 1920x1080 displays in a side-by-side configuration would be a combined resolution of 3840x1080. In a stacked configuration, they would be 1920x2160.
 

	
 
### Retina / High-Density Screens
 

	
 
High DPI screens may be displaying the game at something other than a 1:1 game-pixel to screen-pixel ratio.  These screens didn't exist, back when Desert Paint Lab was created. The current version now prompts you for your screen resolution when it starts to work around this. If you see a crash when trying to capture a reaction, it's likely because the resolution is incorrect. For example, Snoerr's MacBook Pro has a retina screen with a resolution of 2880x1800. Mono (and therefore DesertPaintLab) detects it as having a resolution of 1440x900. He enters his resolution as 2880x1800 and sets the Game pixel width in screen pixels to 2.
 

	
 
## Mac user FAQ
 

	
 
Q: How do I find my native screen resolution?
 

	
 
A: You can find it by opening up "About this Mac" from the Apple menu and clicking on the "Displays" tab. That should show the screen size and resolution to enter.
 

	
 
## 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/).
Reaction.cs
Show inline comments
 
/*
 
 * Copyright (c) 2015, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
namespace DesertPaintLab
 
{
 
	public class Reaction
 
	{
 
		int red = 0;
 
		int green = 0;
 
		int blue = 0;
 
		bool exported = false;		
 
		
 
		public int Red
 
		{
 
			get
 
			{
 
				return red;
 
			}	
 
		}
 
		
 
		public int Green
 
		{
 
			get
 
			{
 
				return green;	
 
			}
 
		}
 
		
 
		public int Blue
 
		{
 
			get
 
			{
 
				return blue;	
 
			}
 
		}
 
		
 
		public bool Exported
 
		{
 
			get
 
			{
 
				return exported;
 
			}
 
			set
 
			{
 
				exported = value;	
 
			}
 
		}
 
		
 
		public Reaction(int r, int g, int b)
 
		{
 
			red = r;
 
			green = g;
 
			blue = b;
 
		}
 
		
 
		public override string ToString()
 
		{
 
			return "[" + red + ", " + green + ", " + blue + "]";
 
		}
 
		
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2015, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
namespace DesertPaintLab
 
{
 
	public class Reaction
 
	{
 
		int red = 0;
 
		int green = 0;
 
		int blue = 0;
 
		bool exported = false;		
 
		
 
		public int Red
 
		{
 
			get
 
			{
 
				return red;
 
			}	
 
		}
 
		
 
		public int Green
 
		{
 
			get
 
			{
 
				return green;	
 
			}
 
		}
 
		
 
		public int Blue
 
		{
 
			get
 
			{
 
				return blue;	
 
			}
 
		}
 
		
 
		public bool Exported
 
		{
 
			get
 
			{
 
				return exported;
 
			}
 
			set
 
			{
 
				exported = value;	
 
			}
 
		}
 
		
 
		public Reaction(int r, int g, int b)
 
		{
 
			red = r;
 
			green = g;
 
			blue = b;
 
		}
 
		
 
		public override string ToString()
 
		{
 
			return "[" + red + ", " + green + ", " + blue + "]";
 
		}
 
		
 
	}
 
}
 

	
Reagent.cs
Show inline comments
 
/*
 
 * Copyright (c) 2015, Jason Maltzen
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 

 
namespace DesertPaintLab
 
{
 
	public class Reagent
 
	{ 
 
		string name;
 
        string ppName;
 
		bool isCatalyst = false;
 
        uint cost = 0;
 
        bool enabled = true;
 
        uint recipeMax = 10;
 
		PaintColor color;
 
		
 
		public bool IsCatalyst
 
		{
 
			get
 
			{
 
				return isCatalyst;	
 
			}
 
		}
 
		
 
		public PaintColor Color
 
		{
 
			get
 
			{
 
				return color;	
 
			}
 
		}
 
		
 
		public string Name
 
		{
 
			get
 
			{
 
				return name;	
 
			}
 
		}
 

 
        public string PracticalPaintName
 
        {
 
            get
 
            {
 
                return ppName;
 
            }
 
        }
 

 
        public bool Enabled
 
        {
 
            get
 
            {
 
                return enabled;
 
            }
 
            set
 
            {
 
                enabled = value;
 
            }
 
        }
 

 
        public uint Cost
 
        {
 
            get
 
            {
 
                return cost;
 
            }
 
            set
 
            {
 
                cost = Math.Max(1, value);
 
            }
 
        }
 

 
        public uint RecipeMax
 
        {
 
            get
 
            {
 
                return recipeMax;
 
            }
 
            set
 
            {
 
                if (!isCatalyst)
 
                {
 
                    recipeMax = Math.Max(0, value);
 
                }
 
            }
 
        }
 

 
        // catalyst
 
        public Reagent(string name, string ppName)
 
        {
 
            this.name = name;
 
            this.ppName = ppName;
 
            this.cost = 2;
 
            this.enabled = true;
 
            this.recipeMax = 1;
 
            this.isCatalyst = true;
 
        }
 
        
 
        public Reagent(string name, string ppName, byte red, byte green, byte blue)
 
        {
 
            this.color = new PaintColor(red, green, blue);
 
            this.name = name;
 
            this.ppName = ppName;
 
            this.cost = 1;
 
            this.recipeMax = 10;
 
            this.enabled = true;
 
            this.isCatalyst = false;
 
        }
 
        
 
		public override string ToString()
 
		{
 
			if (isCatalyst)
 
			{
 
				return "[" + name + ", catalyst]";
 
			}
 
			else
 
			{
 
				return "[" + name + ", " + color.ToString() + "]";
 
			}
 
		}
 
		
 
		
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2015, Jason Maltzen
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 

	
 
namespace DesertPaintLab
 
{
 
	public class Reagent
 
	{ 
 
		string name;
 
        string ppName;
 
		bool isCatalyst = false;
 
        uint cost = 0;
 
        bool enabled = true;
 
        uint recipeMax = 10;
 
		PaintColor color;
 
		
 
		public bool IsCatalyst
 
		{
 
			get
 
			{
 
				return isCatalyst;	
 
			}
 
		}
 
		
 
		public PaintColor Color
 
		{
 
			get
 
			{
 
				return color;	
 
			}
 
		}
 
		
 
		public string Name
 
		{
 
			get
 
			{
 
				return name;	
 
			}
 
		}
 

	
 
        public string PracticalPaintName
 
        {
 
            get
 
            {
 
                return ppName;
 
            }
 
        }
 

	
 
        public bool Enabled
 
        {
 
            get
 
            {
 
                return enabled;
 
            }
 
            set
 
            {
 
                enabled = value;
 
            }
 
        }
 

	
 
        public uint Cost
 
        {
 
            get
 
            {
 
                return cost;
 
            }
 
            set
 
            {
 
                cost = Math.Max(1, value);
 
            }
 
        }
 

	
 
        public uint RecipeMax
 
        {
 
            get
 
            {
 
                return recipeMax;
 
            }
 
            set
 
            {
 
                if (!isCatalyst)
 
                {
 
                    recipeMax = Math.Max(0, value);
 
                }
 
            }
 
        }
 

	
 
        // catalyst
 
        public Reagent(string name, string ppName)
 
        {
 
            this.name = name;
 
            this.ppName = ppName;
 
            this.cost = 2;
 
            this.enabled = true;
 
            this.recipeMax = 1;
 
            this.isCatalyst = true;
 
        }
 
        
 
        public Reagent(string name, string ppName, byte red, byte green, byte blue)
 
        {
 
            this.color = new PaintColor(red, green, blue);
 
            this.name = name;
 
            this.ppName = ppName;
 
            this.cost = 1;
 
            this.recipeMax = 10;
 
            this.enabled = true;
 
            this.isCatalyst = false;
 
        }
 
        
 
		public override string ToString()
 
		{
 
			if (isCatalyst)
 
			{
 
				return "[" + name + ", catalyst]";
 
			}
 
			else
 
			{
 
				return "[" + name + ", " + color.ToString() + "]";
 
			}
 
		}
 
		
 
		
 
	}
 
}
 

	
ReagentManager.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

 
namespace DesertPaintLab
 
{
 
	public class ReagentManager
 
	{
 
        // PP format
 
		static Regex reagentRegex = new Regex(@"(?<name>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+)\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal))\s*\|\s*(?<max>\d+).*");
 
		static Regex catalystRegex = new Regex(@"(?<name>\w+)\s*\|\s*catalyst\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal)).*");
 
        static Regex internalReagentRegex = new Regex(@"(?<name>(\w*\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+).*");
 
        static Regex internalCatalystRegex = new Regex(@"(?<name>(\w+\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*catalyst.*");
 
		
 
		static SortedDictionary<string,Reagent> reagents = new SortedDictionary<string, Reagent>();
 
        static List<string> names = new List<string>();
 
        static Dictionary<string, string> nameLookup = new Dictionary<string, string>(); // pp name to our name
 
		
 
		static Gtk.ListStore nameStore = new Gtk.ListStore(typeof(string));
 

 
		static public Gtk.ListStore NameListModel
 
		{
 
			get
 
			{
 
				return nameStore;	
 
			}
 
		}
 

 
        static public List<string> Names
 
        {
 
            get
 
            {
 
                return names;
 
            }
 
        }
 
		
 
		public ReagentManager ()
 
		{
 
			
 
		}
 

 
        // Loads reagent name/colors
 
        public static void Load(string file)
 
        {
 
            Match match;
 
            string line;
 
            reagents.Clear();
 
            using (StreamReader reader = new StreamReader(file))
 
            {
 
                while ((line = reader.ReadLine()) != null) 
 
                {
 
                    match = internalReagentRegex.Match(line); 
 
                    if (match.Success)
 
                    {
 
                        string name = match.Groups["name"].Value;
 
                        string ppname = match.Groups["ppname"].Value;
 
                        reagents.Add(name,
 
                            new Reagent(name, ppname,
 
                                byte.Parse(match.Groups["red"].Value),
 
                                byte.Parse(match.Groups["green"].Value),
 
                                byte.Parse(match.Groups["blue"].Value)));
 
                        nameStore.AppendValues(name);
 
                        names.Add(name);
 
                        nameLookup.Add(ppname, name);
 
                    }
 
                    else
 
                    {
 
                        match = internalCatalystRegex.Match(line);
 
                        if (match.Success)
 
                        {
 
                            string name = match.Groups["name"].Value;
 
                            string ppname = match.Groups["ppname"].Value;
 
                            reagents.Add(name, new Reagent(ppname, ppname));
 
                            nameStore.AppendValues(name);
 
                            names.Add(name);
 
                            nameLookup.Add(ppname, name);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 
		
 
		public static void LoadProfileReagents(string file)
 
		{	
 
			Match match;
 
			string line;
 
			using (StreamReader reader = new StreamReader(file))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
                {
 
					match = reagentRegex.Match(line); 
 
					if (match.Success)
 
					{
 
						string ppname = match.Groups["name"].Value;
 
                        string name = null;
 
                        nameLookup.TryGetValue(ppname, out name);
 
                        Reagent reagent = GetReagent(name);
 
                        if (reagent != null && !reagent.IsCatalyst)
 
                        {
 
                            reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
 
                            reagent.Cost = uint.Parse(match.Groups["cost"].Value);
 
                            reagent.RecipeMax = uint.Parse(match.Groups["max"].Value);
 
                        }
 
					}
 
					else
 
					{
 
						match = catalystRegex.Match(line);
 
						if (match.Success)
 
						{
 
							string ppname = match.Groups["name"].Value;
 
                            string name = null;
 
                            nameLookup.TryGetValue(ppname, out name);
 
                            Reagent reagent = GetReagent(name);
 
                            if (reagent != null && reagent.IsCatalyst)
 
                            {
 
                                reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
 
                                reagent.Cost = uint.Parse(match.Groups["cost"].Value);
 
                            }
 
						}
 
					}
 
                }
 
			}
 
		}
 

 
        public static void SaveProfileReagents(string file)
 
        {
 
            using (StreamWriter writer = new StreamWriter(file))
 
            {
 
                writer.WriteLine("// Ingredients are in the form:");
 
                writer.WriteLine("// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)");
 
                writer.WriteLine("//");
 
                writer.WriteLine("// It is recommended to only change the cost value");
 
                writer.WriteLine("// It is not recommended to set many of the ingredients above 10 per paint");
 

 
                List<Reagent> sortedReagents = new List<Reagent>(reagents.Count);
 
                foreach (KeyValuePair<string, Reagent> pair in reagents)
 
                {
 
                    sortedReagents.Add(pair.Value);
 
                }
 
                sortedReagents.Sort( (x,y) => ((x.IsCatalyst && !y.IsCatalyst) ? 1 : ((y.IsCatalyst && !x.IsCatalyst) ? -1 : x.PracticalPaintName.CompareTo(y.PracticalPaintName))) );
 
                foreach (Reagent reagent in sortedReagents)
 
                {
 
                    if (!reagent.IsCatalyst)
 
                    {
 
                        writer.WriteLine("{0,-10} | {1,3}, {2,3}, {3,3} | {4,7} | {5} | {6} | {7}",
 
                            reagent.PracticalPaintName, 
 
                            reagent.Color.Red, reagent.Color.Blue, reagent.Color.Green,
 
                            reagent.Cost,
 
                            reagent.Enabled ? "Y" : "N",
 
                            reagent.RecipeMax >= 10 ? "  bulk" : "normal",
 
                            reagent.RecipeMax);
 
                    }
 
                    else
 
                    {
 
                        writer.WriteLine("{0,-10} | catalyst | {1,7} | {2} | normal | 1",
 
                            reagent.PracticalPaintName, 
 
                            reagent.Cost,
 
                            reagent.Enabled ? "Y" : "N");
 
                    }
 
                }
 
            }
 
        }
 

 
		
 
		public static void InitializeReactions(ref ReactionSet reactions)
 
		{
 
			foreach (KeyValuePair<string, Reagent> pair1 in reagents)
 
			{
 
				foreach (KeyValuePair<string, Reagent> pair2 in reagents)
 
				{
 
					if (pair1.Key != pair2.Key)
 
					{
 
                        reactions.Set(pair1.Value, pair2.Value, null);
 
					}
 
				}
 
			}
 
		}
 
		
 
		public static void PopulateReagents(ref Gtk.ComboBox comboBox)
 
		{
 
			comboBox.Clear();
 
			
 
			Gtk.CellRendererText cell = new Gtk.CellRendererText();
 
	        comboBox.PackStart(cell, false);
 
	        comboBox.AddAttribute(cell, "text", 0);
 
	        Gtk.ListStore store = new Gtk.ListStore(typeof(string));
 
	        comboBox.Model = store;
 
			
 
			store.AppendValues("");
 
            foreach (string name in names)
 
			{
 
				store.AppendValues(name);
 
			}
 
		}
 
		
 
		/*
 
		public static void PopulatePigments(ref Gtk.ComboBox comboBox)
 
		{
 
			comboBox.Clear();
 
			
 
			Gtk.CellRendererText cell = new Gtk.CellRendererText();
 
	        comboBox.PackStart(cell, false);
 
	        comboBox.AddAttribute(cell, "text", 0);
 
	        Gtk.ListStore store = new Gtk.ListStore(typeof(string));
 
	        comboBox.Model = store;
 
			
 
			store.AppendValues("");
 
			foreach (KeyValuePair<string, Reagent> pair in reagents)
 
			{
 
				if (!pair.Value.IsCatalyst)
 
				{
 
					store.AppendValues(pair.Key);
 
				}
 
			}			
 
		}
 
		*/
 
		
 
		public static Reagent GetReagent(string reagentName)
 
		{
 
			Reagent returnVal;
 
			reagents.TryGetValue(reagentName, out returnVal);
 
            if (returnVal == null)
 
            {
 
                // convert pp name to our internal name
 
                string otherName = null;
 
                nameLookup.TryGetValue(reagentName, out otherName);
 
                if (otherName != null)
 
                {
 
                    reagents.TryGetValue(otherName, out returnVal);
 
                }
 
            }
 
			return returnVal;
 
		}
 
	}
 
	
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 
using System;
 
using System.IO;
 
using System.Collections.Generic;
 
using System.Text.RegularExpressions;
 

	
 
namespace DesertPaintLab
 
{
 
	public class ReagentManager
 
	{
 
        // PP format
 
		static Regex reagentRegex = new Regex(@"(?<name>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+)\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal))\s*\|\s*(?<max>\d+).*");
 
		static Regex catalystRegex = new Regex(@"(?<name>\w+)\s*\|\s*catalyst\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal)).*");
 
        static Regex internalReagentRegex = new Regex(@"(?<name>(\w*\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+).*");
 
        static Regex internalCatalystRegex = new Regex(@"(?<name>(\w+\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*catalyst.*");
 
		
 
		static SortedDictionary<string,Reagent> reagents = new SortedDictionary<string, Reagent>();
 
        static List<string> names = new List<string>();
 
        static Dictionary<string, string> nameLookup = new Dictionary<string, string>(); // pp name to our name
 
		
 
		static Gtk.ListStore nameStore = new Gtk.ListStore(typeof(string));
 

	
 
		static public Gtk.ListStore NameListModel
 
		{
 
			get
 
			{
 
				return nameStore;	
 
			}
 
		}
 

	
 
        static public List<string> Names
 
        {
 
            get
 
            {
 
                return names;
 
            }
 
        }
 
		
 
		public ReagentManager ()
 
		{
 
			
 
		}
 

	
 
        // Loads reagent name/colors
 
        public static void Load(string file)
 
        {
 
            Match match;
 
            string line;
 
            reagents.Clear();
 
            using (StreamReader reader = new StreamReader(file))
 
            {
 
                while ((line = reader.ReadLine()) != null) 
 
                {
 
                    match = internalReagentRegex.Match(line); 
 
                    if (match.Success)
 
                    {
 
                        string name = match.Groups["name"].Value;
 
                        string ppname = match.Groups["ppname"].Value;
 
                        reagents.Add(name,
 
                            new Reagent(name, ppname,
 
                                byte.Parse(match.Groups["red"].Value),
 
                                byte.Parse(match.Groups["green"].Value),
 
                                byte.Parse(match.Groups["blue"].Value)));
 
                        nameStore.AppendValues(name);
 
                        names.Add(name);
 
                        nameLookup.Add(ppname, name);
 
                    }
 
                    else
 
                    {
 
                        match = internalCatalystRegex.Match(line);
 
                        if (match.Success)
 
                        {
 
                            string name = match.Groups["name"].Value;
 
                            string ppname = match.Groups["ppname"].Value;
 
                            reagents.Add(name, new Reagent(ppname, ppname));
 
                            nameStore.AppendValues(name);
 
                            names.Add(name);
 
                            nameLookup.Add(ppname, name);
 
                        }
 
                    }
 
                }
 
            }
 
        }
 
		
 
		public static void LoadProfileReagents(string file)
 
		{	
 
			Match match;
 
			string line;
 
			using (StreamReader reader = new StreamReader(file))
 
			{
 
				while ((line = reader.ReadLine()) != null) 
 
                {
 
					match = reagentRegex.Match(line); 
 
					if (match.Success)
 
					{
 
						string ppname = match.Groups["name"].Value;
 
                        string name = null;
 
                        nameLookup.TryGetValue(ppname, out name);
 
                        Reagent reagent = GetReagent(name);
 
                        if (reagent != null && !reagent.IsCatalyst)
 
                        {
 
                            reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
 
                            reagent.Cost = uint.Parse(match.Groups["cost"].Value);
 
                            reagent.RecipeMax = uint.Parse(match.Groups["max"].Value);
 
                        }
 
					}
 
					else
 
					{
 
						match = catalystRegex.Match(line);
 
						if (match.Success)
 
						{
 
							string ppname = match.Groups["name"].Value;
 
                            string name = null;
 
                            nameLookup.TryGetValue(ppname, out name);
 
                            Reagent reagent = GetReagent(name);
 
                            if (reagent != null && reagent.IsCatalyst)
 
                            {
 
                                reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
 
                                reagent.Cost = uint.Parse(match.Groups["cost"].Value);
 
                            }
 
						}
 
					}
 
                }
 
			}
 
		}
 

	
 
        public static void SaveProfileReagents(string file)
 
        {
 
            using (StreamWriter writer = new StreamWriter(file))
 
            {
 
                writer.WriteLine("// Ingredients are in the form:");
 
                writer.WriteLine("// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)");
 
                writer.WriteLine("//");
 
                writer.WriteLine("// It is recommended to only change the cost value");
 
                writer.WriteLine("// It is not recommended to set many of the ingredients above 10 per paint");
 

	
 
                List<Reagent> sortedReagents = new List<Reagent>(reagents.Count);
 
                foreach (KeyValuePair<string, Reagent> pair in reagents)
 
                {
 
                    sortedReagents.Add(pair.Value);
 
                }
 
                sortedReagents.Sort( (x,y) => ((x.IsCatalyst && !y.IsCatalyst) ? 1 : ((y.IsCatalyst && !x.IsCatalyst) ? -1 : x.PracticalPaintName.CompareTo(y.PracticalPaintName))) );
 
                foreach (Reagent reagent in sortedReagents)
 
                {
 
                    if (!reagent.IsCatalyst)
 
                    {
 
                        writer.WriteLine("{0,-10} | {1,3}, {2,3}, {3,3} | {4,7} | {5} | {6} | {7}",
 
                            reagent.PracticalPaintName, 
 
                            reagent.Color.Red, reagent.Color.Blue, reagent.Color.Green,
 
                            reagent.Cost,
 
                            reagent.Enabled ? "Y" : "N",
 
                            reagent.RecipeMax >= 10 ? "  bulk" : "normal",
 
                            reagent.RecipeMax);
 
                    }
 
                    else
 
                    {
 
                        writer.WriteLine("{0,-10} | catalyst | {1,7} | {2} | normal | 1",
 
                            reagent.PracticalPaintName, 
 
                            reagent.Cost,
 
                            reagent.Enabled ? "Y" : "N");
 
                    }
 
                }
 
            }
 
        }
 

	
 
		
 
		public static void InitializeReactions(ref ReactionSet reactions)
 
		{
 
			foreach (KeyValuePair<string, Reagent> pair1 in reagents)
 
			{
 
				foreach (KeyValuePair<string, Reagent> pair2 in reagents)
 
				{
 
					if (pair1.Key != pair2.Key)
 
					{
 
                        reactions.Set(pair1.Value, pair2.Value, null);
 
					}
 
				}
 
			}
 
		}
 
		
 
		public static void PopulateReagents(ref Gtk.ComboBox comboBox)
 
		{
 
			comboBox.Clear();
 
			
 
			Gtk.CellRendererText cell = new Gtk.CellRendererText();
 
	        comboBox.PackStart(cell, false);
 
	        comboBox.AddAttribute(cell, "text", 0);
 
	        Gtk.ListStore store = new Gtk.ListStore(typeof(string));
 
	        comboBox.Model = store;
 
			
 
			store.AppendValues("");
 
            foreach (string name in names)
 
			{
 
				store.AppendValues(name);
 
			}
 
		}
 
		
 
		/*
 
		public static void PopulatePigments(ref Gtk.ComboBox comboBox)
 
		{
 
			comboBox.Clear();
 
			
 
			Gtk.CellRendererText cell = new Gtk.CellRendererText();
 
	        comboBox.PackStart(cell, false);
 
	        comboBox.AddAttribute(cell, "text", 0);
 
	        Gtk.ListStore store = new Gtk.ListStore(typeof(string));
 
	        comboBox.Model = store;
 
			
 
			store.AppendValues("");
 
			foreach (KeyValuePair<string, Reagent> pair in reagents)
 
			{
 
				if (!pair.Value.IsCatalyst)
 
				{
 
					store.AppendValues(pair.Key);
 
				}
 
			}			
 
		}
 
		*/
 
		
 
		public static Reagent GetReagent(string reagentName)
 
		{
 
			Reagent returnVal;
 
			reagents.TryGetValue(reagentName, out returnVal);
 
            if (returnVal == null)
 
            {
 
                // convert pp name to our internal name
 
                string otherName = null;
 
                nameLookup.TryGetValue(reagentName, out otherName);
 
                if (otherName != null)
 
                {
 
                    reagents.TryGetValue(otherName, out returnVal);
 
                }
 
            }
 
			return returnVal;
 
		}
 
	}
 
	
 
}
 

	
ScreenCheckDialog.cs
Show inline comments
 
/*
 
 * Copyright (c) 2014, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 

 
namespace DesertPaintLab
 
{
 
	public partial class ScreenCheckDialog : Gtk.Dialog
 
	{
 
		public int ScreenWidth
 
		{
 
			get
 
			{
 
				return int.Parse(screenWidthEntry.Text);	
 
			}	
 
			set
 
			{
 
				screenWidthEntry.Text = value.ToString(); 
 
			}
 
		}
 

 
		public int ScreenHeight
 
		{
 
			get
 
			{
 
				return int.Parse(screenHeightEntry.Text);	
 
			}	
 
			set
 
			{
 
				screenHeightEntry.Text = value.ToString();
 
			}
 
		}
 

 
		public int GamePixelWidth
 
		{
 
			get
 
			{
 
				return int.Parse(gamePixelWidthEntry.Text);	
 
			}	
 
			set
 
			{
 
				gamePixelWidthEntry.Text = value.ToString();
 
			}
 
		}
 

 
		public ScreenCheckDialog ()
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2014, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 

	
 
namespace DesertPaintLab
 
{
 
	public partial class ScreenCheckDialog : Gtk.Dialog
 
	{
 
		public int ScreenWidth
 
		{
 
			get
 
			{
 
				return int.Parse(screenWidthEntry.Text);	
 
			}	
 
			set
 
			{
 
				screenWidthEntry.Text = value.ToString(); 
 
			}
 
		}
 

	
 
		public int ScreenHeight
 
		{
 
			get
 
			{
 
				return int.Parse(screenHeightEntry.Text);	
 
			}	
 
			set
 
			{
 
				screenHeightEntry.Text = value.ToString();
 
			}
 
		}
 

	
 
		public int GamePixelWidth
 
		{
 
			get
 
			{
 
				return int.Parse(gamePixelWidthEntry.Text);	
 
			}	
 
			set
 
			{
 
				gamePixelWidthEntry.Text = value.ToString();
 
			}
 
		}
 

	
 
		public ScreenCheckDialog ()
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

	
SelectProfileDialog.cs
Show inline comments
 
/*
 
 * Copyright (c) 2010, Tess Snider
 

 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

 
using System;
 
using System.Collections.Generic;
 

 
namespace DesertPaintLab
 
{
 
	public partial class SelectProfileDialog : Gtk.Dialog
 
	{
 
		List<string> profileList = null;
 
		Gtk.ListStore profileStore = new Gtk.ListStore(typeof(string));
 
		string selectedProfile;
 
		                                               
 
		public int ProfileCount
 
		{
 
			get
 
			{
 
				return profileList.Count;	
 
			}		
 
		}
 

 
		public List<string> ProfileList
 
		{
 
			get
 
			{
 
				return profileList;	
 
			}
 
			set
 
			{
 
				profileList = value;
 
				profileStore.Clear();
 
				foreach (string name in profileList)
 
				{
 
					profileStore.AppendValues(name);	
 
				}
 
			}
 
		}
 
		
 
		public string SelectedProfile
 
		{
 
			get
 
			{
 
				return selectedProfile;
 
			}
 
		}
 
		
 
		public SelectProfileDialog()
 
		{
 
			this.Build();
 
			
 
			Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn();
 
			Gtk.CellRendererText nameColumnCell = new Gtk.CellRendererText();
 
			nameColumn.PackStart(nameColumnCell, true);		
 
			nameColumn.Title = "Name";
 
			profileListView.AppendColumn(nameColumn);
 
			nameColumn.AddAttribute(nameColumnCell, "text", 0);
 
			
 
			profileListView.Model = profileStore;
 
		}
 
		
 
		protected virtual void OnCursorChanged(object sender, System.EventArgs e)
 
		{
 
			Gtk.TreeModel model;
 
			Gtk.TreeIter iter;
 

 
			Gtk.TreeSelection selection = profileListView.Selection;
 
			if ((selection != null) && selection.GetSelected(out model, out iter))
 
			{					
 
				selectedProfile = model.GetValue(iter, 0).ToString();	
 
			}
 
			else
 
			{
 
				selectedProfile = "";
 
			}
 
		}
 
		
 
	}
 
}
 

 
/*
 
 * Copyright (c) 2010, Tess Snider
 

	
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 
 of this software and associated documentation files (the "Software"), to deal
 
 in the Software without restriction, including without limitation the rights
 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
 copies of the Software, and to permit persons to whom the Software is
 
 furnished to do so, subject to the following conditions:
 

	
 
 The above copyright notice and this permission notice shall be included in
 
 all copies or substantial portions of the Software.
 

	
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
 THE SOFTWARE.
 
*/
 

	
 
using System;
 
using System.Collections.Generic;
 

	
 
namespace DesertPaintLab
 
{
 
	public partial class SelectProfileDialog : Gtk.Dialog
 
	{
 
		List<string> profileList = null;
 
		Gtk.ListStore profileStore = new Gtk.ListStore(typeof(string));
 
		string selectedProfile;
 
		                                               
 
		public int ProfileCount
 
		{
 
			get
 
			{
 
				return profileList.Count;	
 
			}		
 
		}
 

	
 
		public List<string> ProfileList
 
		{
 
			get
 
			{
 
				return profileList;	
 
			}
 
			set
 
			{
 
				profileList = value;
 
				profileStore.Clear();
 
				foreach (string name in profileList)
 
				{
 
					profileStore.AppendValues(name);	
 
				}
 
			}
 
		}
 
		
 
		public string SelectedProfile
 
		{
 
			get
 
			{
 
				return selectedProfile;
 
			}
 
		}
 
		
 
		public SelectProfileDialog()
 
		{
 
			this.Build();
 
			
 
			Gtk.TreeViewColumn nameColumn = new Gtk.TreeViewColumn();
 
			Gtk.CellRendererText nameColumnCell = new Gtk.CellRendererText();
 
			nameColumn.PackStart(nameColumnCell, true);		
 
			nameColumn.Title = "Name";
 
			profileListView.AppendColumn(nameColumn);
 
			nameColumn.AddAttribute(nameColumnCell, "text", 0);
 
			
 
			profileListView.Model = profileStore;
 
		}
 
		
 
		protected virtual void OnCursorChanged(object sender, System.EventArgs e)
 
		{
 
			Gtk.TreeModel model;
 
			Gtk.TreeIter iter;
 

	
 
			Gtk.TreeSelection selection = profileListView.Selection;
 
			if ((selection != null) && selection.GetSelected(out model, out iter))
 
			{					
 
				selectedProfile = model.GetValue(iter, 0).ToString();	
 
			}
 
			else
 
			{
 
				selectedProfile = "";
 
			}
 
		}
 
		
 
	}
 
}
 

	
SimWindow.cs
Show inline comments
 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class SimWindow : Gtk.Window
 
	{
 
		public SimWindow () : base(Gtk.WindowType.Toplevel)
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

 
using System;
 
namespace DesertPaintLab
 
{
 
	public partial class SimWindow : Gtk.Window
 
	{
 
		public SimWindow () : base(Gtk.WindowType.Toplevel)
 
		{
 
			this.Build ();
 
		}
 
	}
 
}
 

	
UI/CaptureView.cs
Show inline comments
 
using System;
 
using System.IO;
 

 
using System.IO;
 

	
 
namespace DesertPaintLab
 
{
 
    [System.ComponentModel.ToolboxItem(true)]
 
    public partial class CaptureView : Gtk.Bin
 
    {
 

	
...
 
@@ -258,27 +258,27 @@ namespace DesertPaintLab
 
            Gdk.Image rootImage = rootWindow.GetImage(0, 0, screenWidth, screenHeight);
 
            screenBuffer.GetFromImage(rootImage, rootImage.Colormap, 0, 0, 0, 0, screenWidth, screenHeight);
 
            //screenBuffer.GetFromDrawable(rootWindow,
 
            //  rootWindow.Colormap, 0, 0, 0, 0, screenWidth, screenHeight);
 
            int stride = screenBuffer.Rowstride;
 
            byte* pixBytes = (byte*)screenBuffer.Pixels;
 
            int redPixelStart = -1;
 

 
            int redPixelStart = -1;
 

	
 
            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 (enableDebugMenu)
 
            {
 
                string logfile = FileUtils.FindNumberedFile("DesertPaintLab_Capture", "log", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
 
                log = new StreamWriter(logfile);
 
                ReactionRecorder.Instance.Log = log;
 
            }
 
            isCaptured = ReactionRecorder.Instance.CaptureReaction(pixBytes, screenWidth, screenHeight, stride, ref reactedColor, ref redPixelStart);
 
            if (log != null)
 
            {
 
                log.Flush();
 
                log.Close();
 
                log = null;
 
            if (log != null)
 
            {
 
                log.Flush();
 
                log.Close();
 
                log = null;
 
            }
 
            if (enableDebugMenu && debugScreenshot)
 
            {
 
                if (!isCaptured)
 
                {
 
                    // write out the whole screenshot on a failure to capture
data/colors.txt
Show inline comments
 
#F0F8FF	AliceBlue
 
#9966CC	Amethyst
 
#FAEBD7	AntiqueWhite
 
#00FFFF	Aqua
 
#7FFFD4	Aquamarine
 
#F0FFFF	Azure
 
#FF91AF	BakerMillerPink
 
#E3CF57	Banana
 
#7C0A02	BarnRed
 
#8E388E	Beet
 
#F5F5DC	Beige
 
#FFE4C4	Bisque
 
#010101	Black
 
#FFEBCD	BlanchedAlmond
 
#FF6700	BlazeOrange
 
#0000FF	Blue
 
#8A2BE2	BlueViolet
 
#873260	Boysenberry
 
#FF007F	BrightPink
 
#A52A2A	Brown
 
#800020	BurgundyRed
 
#DEB887	BurlyWood
 
#8A360F	BurntSienna
 
#8A3324	BurntUmber
 
#5F9EA0	CadetBlue
 
#FF6103	CadmiumOrange
 
#FF9912	CadmiumYellow
 
#E07020	Carrot
 
#7FFF00	Chartreuse
 
#D2691E	Chocolate
 
#3D59AB	CobaltBlue
 
#3D9140	CobaltGreen
 
#FF7F50	Coral
 
#6495ED	CornflowerBlue
 
#FFF8DC	Cornsilk
 
#DC143C	Crimson
 
#00008B	DarkBlue
 
#008B8B	DarkCyan
 
#B8860B	DarkGoldenRod
 
#006400	DarkGreen
 
#A9A9A9	DarkGrey
 
#1A2421	DarkJungleGreen
 
#BDB76B	DarkKhaki
 
#8B008B	DarkMagenta
 
#556B2F	DarkOliveGreen
 
#FF8C00	DarkOrange
 
#9932CC	DarkOrchid
 
#8B0000	DarkRed
 
#E9967A	DarkSalmon
 
#560319	DarkScarlet
 
#8FBC8F	DarkSeaGreen
 
#3C1414	DarkSienna
 
#483D8B	DarkSlateBlue
 
#2F4F4F	DarkSlateGrey
 
#00CED1	DarkTurquoise
 
#9400D3	DarkViolet
 
#FF1493	DeepPink
 
#00BFFF	DeepSkyBlue
 
#696969	DimGrey
 
#1E90FF	DodgerBlue
 
#00009C	DukeBlue
 
#FCE6C9	EggshellWhite
 
#00C957	EmeraldGreen
 
#D19275	Feldspar
 
#B22222	FireBrick
 
#FFFAF0	FloralWhite
 
#228B22	ForestGreen
 
#FF00FF	Fuchsia
 
#DCDCDC	Gainsboro
 
#F8F8FF	GhostWhite
 
#FFD700	Gold
 
#DAA520	GoldenRod
 
#008000	Green
 
#ADFF2F	GreenYellow
 
#808080	Grey
 
#F0FFF0	HoneyDew
 
#FF69B4	HotPink
 
#002395	ImperialBlue
 
#CD5C5C	IndianRed
 
#4B0082	Indigo
 
#FFFFF0	Ivory
 
#F0E68C	Khaki
 
#E6E6FA	Lavender
 
#FFF0F5	LavenderBlush
 
#7CFC00	LawnGreen
 
#FFFACD	LemonChiffon
 
#1A1110	Licorice
 
#ADD8E6	LightBlue
 
#F08080	LightCoral
 
#E0FFFF	LightCyan
 
#FAFAD2	LightGoldenRodYellow
 
#90EE90	LightGreen
 
#D3D3D3	LightGrey
 
#FFB6C1	LightPink
 
#FFA07A	LightSalmon
 
#20B2AA	LightSeaGreen
 
#87CEFA	LightSkyBlue
 
#8470FF	LightSlateBlue
 
#778899	LightSlateGrey
 
#B0C4DE	LightSteelBlue
 
#FFFFE0	LightYellow
 
#00FF00	Lime
 
#32CD32	LimeGreen
 
#FAF0E6	Linen
 
#800000	Maroon
 
#66CDAA	MediumAquaMarine
 
#0000CD	MediumBlue
 
#BA55D3	MediumOrchid
 
#9370DB	MediumPurple
 
#3CB371	MediumSeaGreen
 
#7B68EE	MediumSlateBlue
 
#00FA9A	MediumSpringGreen
 
#48D1CC	MediumTurquoise
 
#C71585	MediumVioletRed
 
#E3A869	Melon
 
#191970	MidnightBlue
 
#F5FFFA	MintCream
 
#FFE4E1	MistyRose
 
#FFE4B5	Moccasin
 
#FFDEAD	NavajoWhite
 
#000080	Navy
 
#FDF5E6	OldLace
 
#808000	Olive
 
#6B8E23	OliveDrab
 
#FFA500	Orange
 
#FF4500	OrangeRed
 
#DA70D6	Orchid
 
#002147	OxfordBlue
 
#EEE8AA	PaleGoldenRod
 
#98FB98	PaleGreen
 
#AFEEEE	PaleTurquoise
 
#DB7093	PaleVioletRed
 
#FFEFD5	PapayaWhip
 
#FFDAB9	PeachPuff
 
#33A1C9	Peacock
 
#32127A	PersianIndigo
 
#F77FBE	PersianPink
 
#CD853F	Peru
 
#FFC0CB	Pink
 
#DDA0DD	Plum
 
#B0E0E6	PowderBlue
 
#003153	PrussianBlue
 
#800080	Purple
 
#C76114	RawSienna
 
#FF0000	Red
 
#860111	RedDevil
 
#004040	RichBlack
 
#BC8F8F	RosyBrown
 
#4169E1	RoyalBlue
 
#9B111E	RubyRed
 
#8B4513	SaddleBrown
 
#FA8072	Salmon
 
#F4A460	SandyBrown
 
#92000A	Sangria
 
#308014	SapGreen
 
#2E8B57	SeaGreen
 
#321414	SealBrown
 
#FFF5EE	SeaShell
 
#A0522D	Sienna
 
#C0C0C0	Silver
 
#87CEEB	SkyBlue
 
#6A5ACD	SlateBlue
 
#708090	SlateGrey
 
#100C08	SmokeyBlack
 
#FFFAFA	Snow
 
#00FF7F	SpringGreen
 
#4682B4	SteelBlue
 
#CC3366	SteelPink
 
#D2B48C	Tan
 
#008080	Teal
 
#D8BFD8	Thistle
 
#FF6347	Tomato
 
#40E0D0	Turquoise
 
#66023C	TyrianPurple
 
#EE82EE	Violet
 
#D02090	VioletRed
 
#F5DEB3	Wheat
 
#FFFFFF	White
 
#F5F5F5	WhiteSmoke
 
#FFFF00	Yellow
 
#9ACD32	YellowGreen
 
#0014A8	Zaffre
 
#F0F8FF	AliceBlue
 
#9966CC	Amethyst
 
#FAEBD7	AntiqueWhite
 
#00FFFF	Aqua
 
#7FFFD4	Aquamarine
 
#F0FFFF	Azure
 
#FF91AF	BakerMillerPink
 
#E3CF57	Banana
 
#7C0A02	BarnRed
 
#8E388E	Beet
 
#F5F5DC	Beige
 
#FFE4C4	Bisque
 
#010101	Black
 
#FFEBCD	BlanchedAlmond
 
#FF6700	BlazeOrange
 
#0000FF	Blue
 
#8A2BE2	BlueViolet
 
#873260	Boysenberry
 
#FF007F	BrightPink
 
#A52A2A	Brown
 
#800020	BurgundyRed
 
#DEB887	BurlyWood
 
#8A360F	BurntSienna
 
#8A3324	BurntUmber
 
#5F9EA0	CadetBlue
 
#FF6103	CadmiumOrange
 
#FF9912	CadmiumYellow
 
#E07020	Carrot
 
#7FFF00	Chartreuse
 
#D2691E	Chocolate
 
#3D59AB	CobaltBlue
 
#3D9140	CobaltGreen
 
#FF7F50	Coral
 
#6495ED	CornflowerBlue
 
#FFF8DC	Cornsilk
 
#DC143C	Crimson
 
#00008B	DarkBlue
 
#008B8B	DarkCyan
 
#B8860B	DarkGoldenRod
 
#006400	DarkGreen
 
#A9A9A9	DarkGrey
 
#1A2421	DarkJungleGreen
 
#BDB76B	DarkKhaki
 
#8B008B	DarkMagenta
 
#556B2F	DarkOliveGreen
 
#FF8C00	DarkOrange
 
#9932CC	DarkOrchid
 
#8B0000	DarkRed
 
#E9967A	DarkSalmon
 
#560319	DarkScarlet
 
#8FBC8F	DarkSeaGreen
 
#3C1414	DarkSienna
 
#483D8B	DarkSlateBlue
 
#2F4F4F	DarkSlateGrey
 
#00CED1	DarkTurquoise
 
#9400D3	DarkViolet
 
#FF1493	DeepPink
 
#00BFFF	DeepSkyBlue
 
#696969	DimGrey
 
#1E90FF	DodgerBlue
 
#00009C	DukeBlue
 
#FCE6C9	EggshellWhite
 
#00C957	EmeraldGreen
 
#D19275	Feldspar
 
#B22222	FireBrick
 
#FFFAF0	FloralWhite
 
#228B22	ForestGreen
 
#FF00FF	Fuchsia
 
#DCDCDC	Gainsboro
 
#F8F8FF	GhostWhite
 
#FFD700	Gold
 
#DAA520	GoldenRod
 
#008000	Green
 
#ADFF2F	GreenYellow
 
#808080	Grey
 
#F0FFF0	HoneyDew
 
#FF69B4	HotPink
 
#002395	ImperialBlue
 
#CD5C5C	IndianRed
 
#4B0082	Indigo
 
#FFFFF0	Ivory
 
#F0E68C	Khaki
 
#E6E6FA	Lavender
 
#FFF0F5	LavenderBlush
 
#7CFC00	LawnGreen
 
#FFFACD	LemonChiffon
 
#1A1110	Licorice
 
#ADD8E6	LightBlue
 
#F08080	LightCoral
 
#E0FFFF	LightCyan
 
#FAFAD2	LightGoldenRodYellow
 
#90EE90	LightGreen
 
#D3D3D3	LightGrey
 
#FFB6C1	LightPink
 
#FFA07A	LightSalmon
 
#20B2AA	LightSeaGreen
 
#87CEFA	LightSkyBlue
 
#8470FF	LightSlateBlue
 
#778899	LightSlateGrey
 
#B0C4DE	LightSteelBlue
 
#FFFFE0	LightYellow
 
#00FF00	Lime
 
#32CD32	LimeGreen
 
#FAF0E6	Linen
 
#800000	Maroon
 
#66CDAA	MediumAquaMarine
 
#0000CD	MediumBlue
 
#BA55D3	MediumOrchid
 
#9370DB	MediumPurple
 
#3CB371	MediumSeaGreen
 
#7B68EE	MediumSlateBlue
 
#00FA9A	MediumSpringGreen
 
#48D1CC	MediumTurquoise
 
#C71585	MediumVioletRed
 
#E3A869	Melon
 
#191970	MidnightBlue
 
#F5FFFA	MintCream
 
#FFE4E1	MistyRose
 
#FFE4B5	Moccasin
 
#FFDEAD	NavajoWhite
 
#000080	Navy
 
#FDF5E6	OldLace
 
#808000	Olive
 
#6B8E23	OliveDrab
 
#FFA500	Orange
 
#FF4500	OrangeRed
 
#DA70D6	Orchid
 
#002147	OxfordBlue
 
#EEE8AA	PaleGoldenRod
 
#98FB98	PaleGreen
 
#AFEEEE	PaleTurquoise
 
#DB7093	PaleVioletRed
 
#FFEFD5	PapayaWhip
 
#FFDAB9	PeachPuff
 
#33A1C9	Peacock
 
#32127A	PersianIndigo
 
#F77FBE	PersianPink
 
#CD853F	Peru
 
#FFC0CB	Pink
 
#DDA0DD	Plum
 
#B0E0E6	PowderBlue
 
#003153	PrussianBlue
 
#800080	Purple
 
#C76114	RawSienna
 
#FF0000	Red
 
#860111	RedDevil
 
#004040	RichBlack
 
#BC8F8F	RosyBrown
 
#4169E1	RoyalBlue
 
#9B111E	RubyRed
 
#8B4513	SaddleBrown
 
#FA8072	Salmon
 
#F4A460	SandyBrown
 
#92000A	Sangria
 
#308014	SapGreen
 
#2E8B57	SeaGreen
 
#321414	SealBrown
 
#FFF5EE	SeaShell
 
#A0522D	Sienna
 
#C0C0C0	Silver
 
#87CEEB	SkyBlue
 
#6A5ACD	SlateBlue
 
#708090	SlateGrey
 
#100C08	SmokeyBlack
 
#FFFAFA	Snow
 
#00FF7F	SpringGreen
 
#4682B4	SteelBlue
 
#CC3366	SteelPink
 
#D2B48C	Tan
 
#008080	Teal
 
#D8BFD8	Thistle
 
#FF6347	Tomato
 
#40E0D0	Turquoise
 
#66023C	TyrianPurple
 
#EE82EE	Violet
 
#D02090	VioletRed
 
#F5DEB3	Wheat
 
#FFFFFF	White
 
#F5F5F5	WhiteSmoke
 
#FFFF00	Yellow
 
#9ACD32	YellowGreen
 
#0014A8	Zaffre
data/ingredients.txt
Show inline comments
 
// Desert Paint Lab Ingredients
 
// Name | Practical Paint Name | RGB values
 
// These should be kept in the order they show up on the paint bench
 

 
Cabbage Juice	| Cabbage	| 128, 64, 144
 
Carrot		| Carrot	| 224, 112, 32
 
Clay		| Clay		| 128, 96, 32
 
Dead Tongue	| DeadTongue	| 112, 64, 64
 
Toad Skin	| ToadSkin	| 48, 96, 48
 
Earth Light	| EarthLight	| 128, 240, 224
 
Red Sand	| RedSand	| 144, 16, 24
 
Lead		| Lead		| 80, 80, 96
 
Silver Powder	| Silver	| 16, 16, 32
 
Iron		| Iron		| 96, 48, 32
 
Copper		| Copper	| 64, 192, 192
 
Sulfur		| Sulfur	| catalyst
 
Potash		| Potash	| catalyst
 
Lime		| Lime		| catalyst
 
Saltpeter	| Saltpeter	| catalyst
 
// Desert Paint Lab Ingredients
 
// Name | Practical Paint Name | RGB values
 
// These should be kept in the order they show up on the paint bench
 

	
 
Cabbage Juice	| Cabbage	| 128, 64, 144
 
Carrot		| Carrot	| 224, 112, 32
 
Clay		| Clay		| 128, 96, 32
 
Dead Tongue	| DeadTongue	| 112, 64, 64
 
Toad Skin	| ToadSkin	| 48, 96, 48
 
Earth Light	| EarthLight	| 128, 240, 224
 
Red Sand	| RedSand	| 144, 16, 24
 
Lead		| Lead		| 80, 80, 96
 
Silver Powder	| Silver	| 16, 16, 32
 
Iron		| Iron		| 96, 48, 32
 
Copper		| Copper	| 64, 192, 192
 
Sulfur		| Sulfur	| catalyst
 
Potash		| Potash	| catalyst
 
Lime		| Lime		| catalyst
 
Saltpeter	| Saltpeter	| catalyst
data/template/ingredients.txt
Show inline comments
 
// Ingredients are in the form:
 
// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)
 
//
 
// It is recommended to only change the cost value
 
// It is not recommended to set many of the ingredients above 10 per paint
 

 
Cabbage		| 128, 64, 144   | 8      | Y | bulk    | 10
 
Carrot		| 224, 112, 32   | 8      | Y | bulk    | 10
 
Clay		| 128, 96, 32    | 10     | Y | bulk    | 20
 
DeadTongue	| 112, 64, 64    | 500    | Y | normal  | 4
 
ToadSkin	| 48, 96, 48     | 500    | Y | normal  | 4
 
EarthLight	| 128, 240, 224  | 10000  | Y | normal  | 4
 
RedSand		| 144, 16, 24    | 4      | Y | bulk    | 20
 
Lead		| 80, 80, 96     | 50     | Y | normal  | 6
 
Silver		| 16, 16, 32     | 50     | Y | normal  | 6
 
Iron		| 96, 48, 32     | 30     | Y | normal  | 8
 
Copper		| 64, 192, 192   | 30     | Y | normal  | 8
 
Sulfur      | catalyst       | 15     | Y | normal  | 1
 
Potash      | catalyst       | 50     | Y | normal  | 1
 
Lime        | catalyst       | 20     | Y | normal  | 1
 
Saltpeter   | catalyst       | 10     | Y | normal  | 1
 
// Ingredients are in the form:
 
// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)
 
//
 
// It is recommended to only change the cost value
 
// It is not recommended to set many of the ingredients above 10 per paint
 

	
 
Cabbage		| 128, 64, 144   | 8      | Y | bulk    | 10
 
Carrot		| 224, 112, 32   | 8      | Y | bulk    | 10
 
Clay		| 128, 96, 32    | 10     | Y | bulk    | 20
 
DeadTongue	| 112, 64, 64    | 500    | Y | normal  | 4
 
ToadSkin	| 48, 96, 48     | 500    | Y | normal  | 4
 
EarthLight	| 128, 240, 224  | 10000  | Y | normal  | 4
 
RedSand		| 144, 16, 24    | 4      | Y | bulk    | 20
 
Lead		| 80, 80, 96     | 50     | Y | normal  | 6
 
Silver		| 16, 16, 32     | 50     | Y | normal  | 6
 
Iron		| 96, 48, 32     | 30     | Y | normal  | 8
 
Copper		| 64, 192, 192   | 30     | Y | normal  | 8
 
Sulfur      | catalyst       | 15     | Y | normal  | 1
 
Potash      | catalyst       | 50     | Y | normal  | 1
 
Lime        | catalyst       | 20     | Y | normal  | 1
 
Saltpeter   | catalyst       | 10     | Y | normal  | 1
0 comments (0 inline, 0 general)