GZDoomBuilder 1.05:

Added Color Picker plugin
Point, Flicker and Pulse light animation should now look almost exactly as seen in GZDoom.
Fixed a bug when editing thing properties in Visual mode didn't update visual thing.
Fixed incorrect doom-style walls shading when sector has "lightcolor" property set.
Fixed "Index was outside the bounds of the array in CalculateNormalsAndShading()" error.
GZDoomBuilder will now show error message prior to failing.
This commit is contained in:
MaxED 2012-05-11 12:28:20 +00:00
parent 506f4054a5
commit 36f391653a
67 changed files with 6045 additions and 974 deletions

BIN
Build/Builder.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,57 @@
Doom Builder Plugin Information
===========================================================================
Title: (G)ZDoom Editing Plugin
Author: Pascal vd Heiden
Plugin version: 0.0
Core version needed: 2.1.0.1394
Description
===========================================================================
This plugins adds features to help editing with the new features in the
ZDoom and GZDoom sourceports and those derived from these sourceports.
List of supported features in this plugin:
- Slopes
- 3D floors (also sloped)
- Colored sector lighting
- Light levels in sectors (also sloped)
- Flat scaling, rotation and offsets
- Texture scaling and offsets
Installation
===========================================================================
1) Place the GZDoomEditing.dll file in Doom Builder's "Plugins" directory.
2) Start Doom Builder and go to Tools menu, Preferences. Choose the
Controls tab and find the "GZDoom Visual Mode" action in the Modes group.
Set this action to a key you wish to use to switch into and out from
Visual Mode. You can give this the same key as your original mode, because
now we will replace the original Visual Mode with the new one.
3) Go to Tools menu, Game Configurations. Choose the game configuration on
which you wish to use the new Visual Mode. This plugin is made for UDMF
formats, but some features also work for Hexen format. Go to the Modes tab
and UNCHECK the original Visual Mode and CHECK the "GZDoom Visual Mode".
You can also have both Visual Modes together (simply do not uncheck the
original Visual Modein step 3) but you will need a different key for the
action that switches to the mode.
Usage
===========================================================================
I don't feel like writing this now. Figure it out yourself.

Binary file not shown.

View file

@ -705,6 +705,12 @@
<Compile Include="General\ErrorItem.cs" />
<Compile Include="General\ErrorLogger.cs" />
<Compile Include="General\SavePurpose.cs" />
<Compile Include="GZBuilder\Controls\ConsoleDocker.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GZBuilder\Controls\ConsoleDocker.Designer.cs">
<DependentUpon>ConsoleDocker.cs</DependentUpon>
</Compile>
<Compile Include="GZBuilder\Data\BoundingBox.cs" />
<Compile Include="GZBuilder\Data\GZDoomLight.cs" />
<Compile Include="GZBuilder\Data\ModelDefEntry.cs" />
@ -713,12 +719,6 @@
<Compile Include="GZBuilder\IO\ModelDefParser.cs" />
<Compile Include="GZBuilder\md3\GZModel.cs" />
<Compile Include="GZBuilder\md3\ModelReader.cs" />
<Compile Include="GZBuilder\Windows\DebugForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="GZBuilder\Windows\DebugForm.designer.cs">
<DependentUpon>DebugForm.cs</DependentUpon>
</Compile>
<Compile Include="IO\DoomColormapReader.cs" />
<Compile Include="Map\SelectionType.cs" />
<Compile Include="Map\MapElementCollection.cs" />
@ -785,8 +785,8 @@
<SubType>Designer</SubType>
<DependentUpon>ThingBrowserControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="GZBuilder\Windows\DebugForm.resx">
<DependentUpon>DebugForm.cs</DependentUpon>
<EmbeddedResource Include="GZBuilder\Controls\ConsoleDocker.resx">
<DependentUpon>ConsoleDocker.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Crosshair.png" />
<EmbeddedResource Include="Resources\CrosshairBusy.png" />

View file

@ -3,16 +3,64 @@ Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C# Express 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj", "{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker", "..\Plugins\ColorPicker\ColorPicker.csproj", "{A4761900-0EA3-4FE4-A919-847FD5080EFC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "..\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuilderModes", "..\Plugins\BuilderModes\BuilderModes.csproj", "{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Any CPU.ActiveCfg = Debug|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|Mixed Platforms.Build.0 = Debug|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.ActiveCfg = Debug|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.Build.0 = Debug|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Any CPU.ActiveCfg = Release|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.ActiveCfg = Release|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86
{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.ActiveCfg = Debug|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.Build.0 = Debug|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Any CPU.Build.0 = Release|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86
{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Any CPU.ActiveCfg = Debug|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|Mixed Platforms.Build.0 = Debug|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Any CPU.ActiveCfg = Release|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.ActiveCfg = Release|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|Mixed Platforms.Build.0 = Release|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -0,0 +1,90 @@
namespace CodeImp.DoomBuilder.GZBuilder.Controls
{
partial class ConsoleDocker
{
#if DEBUG
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.buttonClear = new System.Windows.Forms.Button();
this.textBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// buttonClear
//
this.buttonClear.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.buttonClear.Location = new System.Drawing.Point(3, 274);
this.buttonClear.Name = "buttonClear";
this.buttonClear.Size = new System.Drawing.Size(244, 23);
this.buttonClear.TabIndex = 0;
this.buttonClear.Text = "Clear";
this.buttonClear.UseVisualStyleBackColor = true;
this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click);
//
// textBox
//
this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBox.Location = new System.Drawing.Point(3, 24);
this.textBox.Multiline = true;
this.textBox.Name = "textBox";
this.textBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.textBox.Size = new System.Drawing.Size(244, 244);
this.textBox.TabIndex = 1;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.label1.Location = new System.Drawing.Point(3, 7);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(53, 14);
this.label1.TabIndex = 2;
this.label1.Text = "Console";
//
// ConsoleDocker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox);
this.Controls.Add(this.buttonClear);
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.Name = "ConsoleDocker";
this.Size = new System.Drawing.Size(250, 300);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonClear;
private System.Windows.Forms.TextBox textBox;
private System.Windows.Forms.Label label1;
#endif
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Windows.Forms;
namespace CodeImp.DoomBuilder.GZBuilder.Controls
{
public partial class ConsoleDocker : UserControl
{
#if DEBUG
public ConsoleDocker() {
InitializeComponent();
}
public void TraceInHeader(string message) {
label1.Text = message;
}
public void Trace(string message) {
Trace(message, true);
}
public void Trace(string message, bool addLineBreak) {
textBox.AppendText(message + (addLineBreak ? Environment.NewLine : ""));
}
public void Clear() {
textBox.Clear();
}
//events
private void buttonClear_Click(object sender, EventArgs e) {
textBox.Clear();
}
#endif
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Controls;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.Actions;
@ -11,7 +12,7 @@ using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.IO;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.Windows;
using CodeImp.DoomBuilder.GZBuilder.Controls;
using ColladaDotNet.Pipeline.MD3;
@ -24,17 +25,20 @@ namespace CodeImp.DoomBuilder.GZBuilder
public static Dictionary<int, ModelDefEntry> ModelDefEntries { get { return modelDefEntries; } }
//gzdoom light types
private static int[] gz_lights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503};
public static int[] GZ_LIGHTS { get { return gz_lights; } }
private static int[] gz_lightTypes = { 5, 10, 15 };
public static int[] GZ_LIGHT_TYPES { get { return gz_lightTypes; } }
private static int[] gzLights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503};
public static int[] GZ_LIGHTS { get { return gzLights; } }
private static int[] gzLightTypes = { 5, 10, 15 }; //this is actually offsets in gz_lights
public static int[] GZ_LIGHT_TYPES { get { return gzLightTypes; } }
private static int[] gzAnimatedLightTypes = { (int)GZDoomLightType.FLICKER, (int)GZDoomLightType.RANDOM, (int)GZDoomLightType.PULSE };
public static int[] GZ_ANIMATED_LIGHT_TYPES { get { return gzAnimatedLightTypes; } }
//version
public const string Version = "1.04";
public const float Version = 1.05f;
//debug form
//debug console
#if DEBUG
private static DebugForm form;
private static Docker console;
#endif
@ -43,26 +47,33 @@ namespace CodeImp.DoomBuilder.GZBuilder
General.Actions.BindMethods(typeof(GZGeneral));
General.MainWindow.UpdateGZDoomPannel();
//create debug form
//create console
#if DEBUG
form = new DebugForm();
form.Show();
form.Location = new Point(General.MainWindow.Location.X + General.MainWindow.Width, General.MainWindow.Location.Y);
form.Height = General.MainWindow.Height;
ConsoleDocker cd = new ConsoleDocker();
console = new Docker("consoledockerpannel", "Console", cd);
((MainForm)General.Interface).addDocker(console);
((MainForm)General.Interface).selectDocker(console);
#endif
}
public static void OnMapOpenEnd() {
loadModelDefs();
loadModels();
General.MainWindow.UpdateGZDoomPannel();
}
public static void OnReloadResources() {
loadModelDefs();
loadModels();
#if DEBUG
((ConsoleDocker)console.Control).Clear();
#endif
}
//!!!!!!!!!!! General.Map.FormatInterface.HasCustomFields == UMDF!!!!!!!!
//General.Map.Config.FormatInterface == "UniversalMapSetIO" == UMDF
//General.Interface.RedrawDisplay();
//General.Editing.Mode is ClassicMode
public static bool LoadModelForThing(Thing t) {
if (modelDefEntries.ContainsKey(t.Type)) {
@ -129,23 +140,23 @@ namespace CodeImp.DoomBuilder.GZBuilder
//debug
public static void Trace(string message) {
#if DEBUG
form.TextPannel.AppendText(message);
((ConsoleDocker)console.Control).Trace(message);
#endif
}
public static void TraceLine(string message) {
public static void Trace(string message, bool addLineBreak) {
#if DEBUG
form.TextPannel.AppendText(message + Environment.NewLine);
((ConsoleDocker)console.Control).Trace(message, addLineBreak);
#endif
}
public static void ClearTrace() {
#if DEBUG
form.TextPannel.Text = "";
((ConsoleDocker)console.Control).Clear();
#endif
}
public static void TraceInHeader(string message) {
#if DEBUG
form.Text = message;
((ConsoleDocker)console.Control).TraceInHeader(message);
#endif
}
@ -211,16 +222,9 @@ namespace CodeImp.DoomBuilder.GZBuilder
General.MainWindow.RedrawDisplay();
}
[BeginAction("gztogglelightpannel")]
public static void ToggleLightPannel() {
General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
}
[BeginAction("gztogglefogpannel")]
public static void ToggleFogPannel() {
General.ShowWarningMessage("Not implemented yet...", MessageBoxButtons.OK);
}
}
}

View file

@ -16,17 +16,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.IO
Parse(modelDefEntriesByName, path, fileName);
}
//dbg
#if DEBUG
General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
#else
General.WriteLogLine("ModelDefParser: parsed " + modelDefEntriesByName.Count + " definitions;");
#endif
}
public static void Parse(Dictionary<string, ModelDefEntry> modelDefEntriesByName, string path, string fileName) {
//dbg
#if DEBUG
General.ErrorLogger.Add(ErrorType.Warning, "ModelDefParser: Parsing '" + fileName + "'");
#else

View file

@ -0,0 +1,16 @@
using System;
namespace CodeImp.DoomBuilder.GZBuilder.Windows {
public class ColorChangedEventArgs : EventArgs {
private ColorHandler.RGB mRGB;
private ColorHandler.HSV mHSV;
public ColorChangedEventArgs(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
mRGB = RGB;
mHSV = HSV;
}
public ColorHandler.RGB RGB { get { return mRGB; } }
public ColorHandler.HSV HSV { get { return mHSV; } }
}
}

View file

@ -0,0 +1,493 @@
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Windows;
namespace CodeImp.DoomBuilder.GZBuilder.Windows {
public class ColorChooserForm : DelayedForm {
internal System.Windows.Forms.Button btnCancel;
internal System.Windows.Forms.Button btnOK;
internal System.Windows.Forms.Label Label3;
internal System.Windows.Forms.NumericUpDown nudRed;
internal System.Windows.Forms.Panel pnlColor;
internal System.Windows.Forms.Label Label1;
internal System.Windows.Forms.Panel pnlBrightness;
internal System.Windows.Forms.NumericUpDown nudBlue;
internal System.Windows.Forms.NumericUpDown nudGreen;
internal System.Windows.Forms.Label Label2;
private Dotnetrix.Controls.TrackBar trackBar1;
internal Label labelName1;
internal Label labelName2;
private Dotnetrix.Controls.TrackBar trackBar2;
internal NumericUpDown numericUpDown1;
internal NumericUpDown numericUpDown2;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public ColorChooserForm() {
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing) {
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.btnCancel = new System.Windows.Forms.Button();
this.btnOK = new System.Windows.Forms.Button();
this.Label3 = new System.Windows.Forms.Label();
this.nudRed = new System.Windows.Forms.NumericUpDown();
this.pnlColor = new System.Windows.Forms.Panel();
this.Label1 = new System.Windows.Forms.Label();
this.pnlBrightness = new System.Windows.Forms.Panel();
this.nudBlue = new System.Windows.Forms.NumericUpDown();
this.nudGreen = new System.Windows.Forms.NumericUpDown();
this.Label2 = new System.Windows.Forms.Label();
this.trackBar1 = new Dotnetrix.Controls.TrackBar();
this.labelName1 = new System.Windows.Forms.Label();
this.labelName2 = new System.Windows.Forms.Label();
this.trackBar2 = new Dotnetrix.Controls.TrackBar();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.numericUpDown2 = new System.Windows.Forms.NumericUpDown();
((System.ComponentModel.ISupportInitialize)(this.nudRed)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudBlue)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudGreen)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit();
this.SuspendLayout();
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.btnCancel.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnCancel.Location = new System.Drawing.Point(219, 49);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(94, 42);
this.btnCancel.TabIndex = 11;
this.btnCancel.Text = "Cancel";
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// btnOK
//
this.btnOK.BackColor = System.Drawing.SystemColors.Control;
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.btnOK.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnOK.ForeColor = System.Drawing.SystemColors.ControlText;
this.btnOK.Location = new System.Drawing.Point(219, 8);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(94, 42);
this.btnOK.TabIndex = 10;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// Label3
//
this.Label3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label3.Location = new System.Drawing.Point(219, 152);
this.Label3.Name = "Label3";
this.Label3.Size = new System.Drawing.Size(40, 23);
this.Label3.TabIndex = 45;
this.Label3.Text = "Blue:";
this.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// nudRed
//
this.nudRed.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudRed.Location = new System.Drawing.Point(265, 106);
this.nudRed.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudRed.Name = "nudRed";
this.nudRed.Size = new System.Drawing.Size(48, 20);
this.nudRed.TabIndex = 38;
this.nudRed.ValueChanged += new System.EventHandler(this.HandleRGBChange);
//
// pnlColor
//
this.pnlColor.Location = new System.Drawing.Point(8, 8);
this.pnlColor.Name = "pnlColor";
this.pnlColor.Size = new System.Drawing.Size(176, 176);
this.pnlColor.TabIndex = 51;
this.pnlColor.Visible = false;
this.pnlColor.MouseUp += new System.Windows.Forms.MouseEventHandler(this.frmMain_MouseUp);
//
// Label1
//
this.Label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label1.Location = new System.Drawing.Point(219, 104);
this.Label1.Name = "Label1";
this.Label1.Size = new System.Drawing.Size(40, 23);
this.Label1.TabIndex = 43;
this.Label1.Text = "Red:";
this.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// pnlBrightness
//
this.pnlBrightness.Location = new System.Drawing.Point(190, 8);
this.pnlBrightness.Name = "pnlBrightness";
this.pnlBrightness.Size = new System.Drawing.Size(16, 176);
this.pnlBrightness.TabIndex = 52;
this.pnlBrightness.Visible = false;
//
// nudBlue
//
this.nudBlue.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudBlue.Location = new System.Drawing.Point(265, 154);
this.nudBlue.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudBlue.Name = "nudBlue";
this.nudBlue.Size = new System.Drawing.Size(48, 20);
this.nudBlue.TabIndex = 40;
this.nudBlue.ValueChanged += new System.EventHandler(this.HandleRGBChange);
//
// nudGreen
//
this.nudGreen.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudGreen.Location = new System.Drawing.Point(265, 130);
this.nudGreen.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudGreen.Name = "nudGreen";
this.nudGreen.Size = new System.Drawing.Size(48, 20);
this.nudGreen.TabIndex = 39;
this.nudGreen.ValueChanged += new System.EventHandler(this.HandleRGBChange);
//
// Label2
//
this.Label2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label2.Location = new System.Drawing.Point(219, 128);
this.Label2.Name = "Label2";
this.Label2.Size = new System.Drawing.Size(40, 23);
this.Label2.TabIndex = 44;
this.Label2.Text = "Green:";
this.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// trackBar1
//
this.trackBar1.LargeChange = 64;
this.trackBar1.Location = new System.Drawing.Point(91, 190);
this.trackBar1.Maximum = 512;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(166, 45);
this.trackBar1.SmallChange = 8;
this.trackBar1.TabIndex = 56;
this.trackBar1.TickFrequency = 16;
this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.Both;
this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
//
// labelName1
//
this.labelName1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelName1.Location = new System.Drawing.Point(5, 199);
this.labelName1.Name = "labelName1";
this.labelName1.Size = new System.Drawing.Size(80, 23);
this.labelName1.TabIndex = 57;
this.labelName1.Text = "Start intensity:";
this.labelName1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// labelName2
//
this.labelName2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelName2.Location = new System.Drawing.Point(5, 250);
this.labelName2.Name = "labelName2";
this.labelName2.Size = new System.Drawing.Size(80, 23);
this.labelName2.TabIndex = 60;
this.labelName2.Text = "Start intensity:";
this.labelName2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// trackBar2
//
this.trackBar2.LargeChange = 64;
this.trackBar2.Location = new System.Drawing.Point(91, 241);
this.trackBar2.Maximum = 512;
this.trackBar2.Name = "trackBar2";
this.trackBar2.Size = new System.Drawing.Size(166, 45);
this.trackBar2.SmallChange = 8;
this.trackBar2.TabIndex = 59;
this.trackBar2.TickFrequency = 16;
this.trackBar2.TickStyle = System.Windows.Forms.TickStyle.Both;
this.trackBar2.ValueChanged += new System.EventHandler(this.trackBar2_ValueChanged);
//
// numericUpDown1
//
this.numericUpDown1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.numericUpDown1.Location = new System.Drawing.Point(257, 200);
this.numericUpDown1.Maximum = new decimal(new int[] {
9000,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(56, 20);
this.numericUpDown1.TabIndex = 57;
this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
//
// numericUpDown2
//
this.numericUpDown2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.numericUpDown2.Location = new System.Drawing.Point(257, 250);
this.numericUpDown2.Maximum = new decimal(new int[] {
9000,
0,
0,
0});
this.numericUpDown2.Name = "numericUpDown2";
this.numericUpDown2.Size = new System.Drawing.Size(56, 20);
this.numericUpDown2.TabIndex = 62;
this.numericUpDown2.ValueChanged += new System.EventHandler(this.numericUpDown2_ValueChanged);
//
// ColorChooserForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(319, 286);
this.Controls.Add(this.numericUpDown2);
this.Controls.Add(this.numericUpDown1);
this.Controls.Add(this.labelName2);
this.Controls.Add(this.trackBar2);
this.Controls.Add(this.labelName1);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.Label3);
this.Controls.Add(this.nudRed);
this.Controls.Add(this.pnlColor);
this.Controls.Add(this.Label1);
this.Controls.Add(this.pnlBrightness);
this.Controls.Add(this.nudBlue);
this.Controls.Add(this.nudGreen);
this.Controls.Add(this.Label2);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ColorChooserForm";
this.Opacity = 0;
this.Text = "Select Color";
this.Load += new System.EventHandler(this.ColorChooser1_Load);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.frmMain_MouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.ColorChooser1_Paint);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.HandleMouse);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.HandleMouse);
((System.ComponentModel.ISupportInitialize)(this.nudRed)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudBlue)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudGreen)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private enum ChangeStyle {
MouseMove,
RGB,
None
}
private ChangeStyle changeType = ChangeStyle.None;
private Point selectedPoint;
private ColorWheel colorWheel;
private ColorHandler.RGB RGB;
private bool isInUpdate = false;
private List<Thing> selectedLights;
private List<Sector> selectedLights;
//private Color startColor;
/*public void SetData(Color startColor, string[] labels) {
btnCancel.BackColor = startColor;
btnOK.BackColor = startColor;
if (startColor.R < 128 && startColor.G < 128 && startColor.B < 128) {
btnCancel.ForeColor = Color.White;
btnOK.ForeColor = Color.White;
}
this.startColor = startColor;
if (labels == null || labels.Length == 0) {
numericUpDown1.Visible = false;
numericUpDown2.Visible = false;
labelName1.Visible = false;
labelName2.Visible = false;
trackBar1.Visible = false;
trackBar2.Visible = false;
this.ClientSize = new Size(this.ClientSize.Width, trackBar1.Location.Y);
} else if (labels.Length == 1) {
labelName1.Text = labels[0] + ":";
numericUpDown2.Visible = false;
labelName2.Visible = false;
trackBar2.Visible = false;
this.ClientSize = new Size(this.ClientSize.Width, trackBar2.Location.Y);
} else {
labelName1.Text = labels[0] + ":";
labelName2.Text = labels[1] + ":";
}
}*/
private void ColorChooser1_Load(object sender, System.EventArgs e) {
// Turn on double-buffering, so the form looks better.
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
Rectangle BrightnessRectangle = new Rectangle(pnlBrightness.Location, pnlBrightness.Size);
Rectangle ColorRectangle = new Rectangle(pnlColor.Location, pnlColor.Size);
// Create the new ColorWheel class, indicating the locations of the color wheel itself, the
// brightness area, and the position of the selected color.
colorWheel = new ColorWheel(ColorRectangle, BrightnessRectangle);
colorWheel.ColorChanged += new ColorWheel.ColorChangedEventHandler(this.myColorWheel_ColorChanged);
//set initial color
isInUpdate = true;
changeType = ChangeStyle.RGB;
RGB = new ColorHandler.RGB(startColor.R, startColor.G, startColor.B);
RefreshValue(nudRed, RGB.Red);
RefreshValue(nudBlue, RGB.Blue);
RefreshValue(nudGreen, RGB.Green);
isInUpdate = false;
this.Invalidate();
}
private void HandleMouse(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
changeType = ChangeStyle.MouseMove;
selectedPoint = new Point(e.X, e.Y);
this.Invalidate();
}
}
private void frmMain_MouseUp(object sender, MouseEventArgs e) {
colorWheel.SetMouseUp();
changeType = ChangeStyle.None;
}
private void HandleRGBChange(object sender, System.EventArgs e) {
// If the R, G, or B values change, use this code to update the HSV values and invalidate
// the color wheel (so it updates the pointers).
// Check the isInUpdate flag to avoid recursive events when you update the NumericUpdownControls.
if (!isInUpdate) {
changeType = ChangeStyle.RGB;
RGB = new ColorHandler.RGB((int)nudRed.Value, (int)nudGreen.Value, (int)nudBlue.Value);
this.Invalidate();
}
}
private void SetRGB(ColorHandler.RGB RGB) {
// Update the RGB values on the form, but don't trigger the ValueChanged event of the form. The isInUpdate
// variable ensures that the event procedures exit without doing anything.
isInUpdate = true;
RefreshValue(nudRed, RGB.Red);
RefreshValue(nudBlue, RGB.Blue);
RefreshValue(nudGreen, RGB.Green);
btnOK.BackColor = ColorHandler.RGBtoColor(RGB);
if (RGB.Red < 128 && RGB.Green < 128 && RGB.Blue < 128)
btnOK.ForeColor = Color.White;
else
btnOK.ForeColor = Color.Black;
isInUpdate = false;
}
private void RefreshValue(NumericUpDown nud, int value) {
// Update the value of the NumericUpDown control, if the value is different than the current value.
// Refresh the control, causing an immediate repaint.
if (nud.Value != value) {
nud.Value = value;
nud.Refresh();
}
}
//Properties
public Color Color { get { return colorWheel.Color; } }
public int Value1 { get { return (int)numericUpDown1.Value; } }
public int Value2 { get { return (int)numericUpDown2.Value; } }
//Events
private void myColorWheel_ColorChanged(object sender, ColorChangedEventArgs e) {
SetRGB(e.RGB);
}
private void ColorChooser1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) {
// Depending on the circumstances, force a repaint of the color wheel passing different information.
switch (changeType) {
case ChangeStyle.MouseMove:
case ChangeStyle.None:
colorWheel.Draw(e.Graphics, selectedPoint);
break;
case ChangeStyle.RGB:
colorWheel.Draw(e.Graphics, RGB);
break;
}
}
private void trackBar1_ValueChanged(object sender, EventArgs e) {
numericUpDown1.Value = trackBar1.Value;
}
private void trackBar2_ValueChanged(object sender, EventArgs e) {
numericUpDown2.Value = trackBar2.Value;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
trackBar1.Value = (int)numericUpDown1.Value > trackBar1.Maximum ? trackBar1.Maximum : (int)numericUpDown1.Value;
}
private void numericUpDown2_ValueChanged(object sender, EventArgs e) {
trackBar2.Value = (int)numericUpDown2.Value > trackBar2.Maximum ? trackBar2.Maximum : (int)numericUpDown2.Value;
}
//buttons
private void btnOK_Click(object sender, EventArgs e) {
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e) {
this.Close();
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,210 @@
using System;
using System.Drawing;
namespace CodeImp.DoomBuilder.GZBuilder.Windows {
public class ColorHandler {
// Handle conversions between RGB and HSV
// (and Color types, as well).
public struct RGB {
// All values are between 0 and 255.
public int Red;
public int Green;
public int Blue;
public RGB(int R, int G, int B) {
Red = R;
Green = G;
Blue = B;
}
}
public struct HSV {
// All values are between 0 and 255.
public int Hue;
public int Saturation;
public int value;
public HSV(int H, int S, int V) {
Hue = H;
Saturation = S;
value = V;
}
public override string ToString() {
return String.Format("({0}, {1}, {2})", Hue, Saturation, value);
}
}
public static RGB HSVtoRGB(int H, int S, int V) {
// H, S, and V must all be between 0 and 255.
return HSVtoRGB(new HSV(H, S, V));
}
public static Color HSVtoColor(HSV hsv) {
RGB RGB = HSVtoRGB(hsv);
return Color.FromArgb(RGB.Red, RGB.Green, RGB.Blue);
}
public static Color HSVtoColor(int H, int S, int V) {
return HSVtoColor(new HSV(H, S, V));
}
public static Color RGBtoColor(RGB rgb) {
return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
}
public static RGB HSVtoRGB(HSV HSV) {
// HSV contains values scaled as in the color wheel:
// that is, all from 0 to 255.
// for ( this code to work, HSV.Hue needs
// to be scaled from 0 to 360 (it//s the angle of the selected
// point within the circle). HSV.Saturation and HSV.value must be
// scaled to be between 0 and 1.
double h;
double s;
double v;
double r = 0;
double g = 0;
double b = 0;
// Scale Hue to be between 0 and 360. Saturation
// and value scale to be between 0 and 1.
h = ((double)HSV.Hue / 255 * 360) % 360;
s = (double)HSV.Saturation / 255;
v = (double)HSV.value / 255;
if (s == 0) {
// If s is 0, all colors are the same.
// This is some flavor of gray.
r = v;
g = v;
b = v;
} else {
double p;
double q;
double t;
double fractionalSector;
int sectorNumber;
double sectorPos;
// The color wheel consists of 6 sectors.
// Figure out which sector you//re in.
sectorPos = h / 60;
sectorNumber = (int)(Math.Floor(sectorPos));
// get the fractional part of the sector.
// That is, how many degrees into the sector
// are you?
fractionalSector = sectorPos - sectorNumber;
// Calculate values for the three axes
// of the color.
p = v * (1 - s);
q = v * (1 - (s * fractionalSector));
t = v * (1 - (s * (1 - fractionalSector)));
// Assign the fractional colors to r, g, and b
// based on the sector the angle is in.
switch (sectorNumber) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
}
// return an RGB structure, with values scaled
// to be between 0 and 255.
return new RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
}
public static HSV RGBtoHSV(RGB RGB) {
// In this function, R, G, and B values must be scaled
// to be between 0 and 1.
// HSV.Hue will be a value between 0 and 360, and
// HSV.Saturation and value are between 0 and 1.
// The code must scale these to be between 0 and 255 for
// the purposes of this application.
double min;
double max;
double delta;
double r = (double)RGB.Red / 255;
double g = (double)RGB.Green / 255;
double b = (double)RGB.Blue / 255;
double h;
double s;
double v;
min = Math.Min(Math.Min(r, g), b);
max = Math.Max(Math.Max(r, g), b);
v = max;
delta = max - min;
if (max == 0 || delta == 0) {
// R, G, and B must be 0, or all the same. In this case, S is 0, and H is undefined.
// Using H = 0 is as good as any...
s = 0;
h = 0;
} else {
s = delta / max;
if (r == max) {
// Between Yellow and Magenta
h = (g - b) / delta;
} else if (g == max) {
// Between Cyan and Yellow
h = 2 + (b - r) / delta;
} else {
// Between Magenta and Cyan
h = 4 + (r - g) / delta;
}
}
// Scale h to be between 0 and 360.
// This may require adding 360, if the value is negative.
h *= 60;
if (h < 0) {
h += 360;
}
// Scale to the requirements of this application. All values are between 0 and 255.
return new HSV((int)(h / 360 * 255), (int)(s * 255), (int)(v * 255));
}
}
}

View file

@ -0,0 +1,469 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace CodeImp.DoomBuilder.GZBuilder.Windows {
public class ColorWheel : IDisposable {
// These resources should be disposed
// of when you're done with them.
private Graphics g;
private Region colorRegion;
private Region brightnessRegion;
private Bitmap colorImage;
public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);
public ColorChangedEventHandler ColorChanged;
// Keep track of the current mouse state.
public enum MouseState {
MouseUp,
ClickOnColor,
DragInColor,
ClickOnBrightness,
DragInBrightness,
ClickOutsideRegion,
DragOutsideRegion,
}
private MouseState currentState = MouseState.MouseUp;
// The code needs to convert back and forth between
// degrees and radians. There are 2*PI radians in a
// full circle, and 360 degrees. This constant allows
// you to convert back and forth.
private const double DEGREES_PER_RADIAN = 180.0 / Math.PI;
// COLOR_COUNT represents the number of distinct colors
// used to create the circular gradient. Its value
// is somewhat arbitrary -- change this to 6, for
// example, to see what happens. 1536 (6 * 256) seems
// a good compromise -- it's enough to get a full
// range of colors, but it doesn't overwhelm the processor
// attempting to generate the image. The color wheel
// contains 6 sections, and each section displays
// 256 colors. Seems like a reasonable compromise.
private const int COLOR_COUNT = 6 * 256;
private Point centerPoint;
private int radius;
private Rectangle colorRectangle;
private Rectangle brightnessRectangle;
private int brightnessX;
private double brightnessScaling;
// selectedColor is the actual value selected
// by the user. fullColor is the same color,
// with its brightness set to 255.
private Color selectedColor = Color.White;
private Color fullColor;
private ColorHandler.RGB RGB;
private ColorHandler.HSV HSV;
// Locations for the two "pointers" on the form.
private Point colorPoint;
private Point brightnessPoint;
private int brightness;
private int brightnessMin;
private int brightnessMax;
public Color Color { get { return selectedColor; } }
public ColorWheel(Rectangle colorRectangle, Rectangle brightnessRectangle) {
// Caller must provide locations for color wheel
// (colorRectangle), brightness "strip" (brightnessRectangle)
// and location to display selected color (selectedColorRectangle).
using (GraphicsPath path = new GraphicsPath()) {
// Store away locations for later use.
this.colorRectangle = colorRectangle;
this.brightnessRectangle = brightnessRectangle;
//this.selectedColorRectangle = selectedColorRectangle;
// Calculate the center of the circle.
// Start with the location, then offset
// the point by the radius.
// Use the smaller of the width and height of
// the colorRectangle value.
this.radius = (int)Math.Min(colorRectangle.Width, colorRectangle.Height) / 2;
this.centerPoint = colorRectangle.Location;
this.centerPoint.Offset(radius, radius);
// Start the pointer in the center.
this.colorPoint = this.centerPoint;
// Create a region corresponding to the color circle.
// Code uses this later to determine if a specified
// point is within the region, using the IsVisible
// method.
path.AddEllipse(colorRectangle);
colorRegion = new Region(path);
// set { the range for the brightness selector.
this.brightnessMin = this.brightnessRectangle.Top;
this.brightnessMax = this.brightnessRectangle.Bottom;
// Create a region corresponding to the
// brightness rectangle, with a little extra
// "breathing room".
path.AddRectangle(new Rectangle(brightnessRectangle.Left, brightnessRectangle.Top - 10, brightnessRectangle.Width + 10, brightnessRectangle.Height + 20));
// Create region corresponding to brightness
// rectangle. Later code uses this to
// determine if a specified point is within
// the region, using the IsVisible method.
brightnessRegion = new Region(path);
// Set the location for the brightness indicator "marker".
// Also calculate the scaling factor, scaling the height
// to be between 0 and 255.
brightnessX = brightnessRectangle.Left + brightnessRectangle.Width;
brightnessScaling = (double)255 / (brightnessMax - brightnessMin);
// Calculate the location of the brightness
// pointer. Assume it's at the highest position.
brightnessPoint = new Point(brightnessX, brightnessMax);
// Create the bitmap that contains the circular gradient.
CreateGradient();
}
}
protected void OnColorChanged(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
ColorChangedEventArgs e = new ColorChangedEventArgs(RGB, HSV);
ColorChanged(this, e);
}
void IDisposable.Dispose() {
// Dispose of graphic resources
if (colorImage != null)
colorImage.Dispose();
if (colorRegion != null)
colorRegion.Dispose();
if (brightnessRegion != null)
brightnessRegion.Dispose();
if (g != null)
g.Dispose();
}
public void SetMouseUp() {
// Indicate that the user has
// released the mouse.
currentState = MouseState.MouseUp;
}
public void Draw(Graphics g, ColorHandler.RGB RGB) {
// Given RGB values, calculate HSV and then update the screen.
this.g = g;
this.HSV = ColorHandler.RGBtoHSV(RGB);
CalcCoordsAndUpdate(this.HSV);
UpdateDisplay();
}
public void Draw(Graphics g, Point mousePoint) {
// You've moved the mouse.
// Now update the screen to match.
double distance;
int degrees;
Point delta;
Point newColorPoint;
Point newBrightnessPoint;
Point newPoint;
// Keep track of the previous color pointer point,
// so you can put the mouse there in case the
// user has clicked outside the circle.
newColorPoint = colorPoint;
newBrightnessPoint = brightnessPoint;
// Store this away for later use.
this.g = g;
if (currentState == MouseState.MouseUp) {
if (!mousePoint.IsEmpty) {
if (colorRegion.IsVisible(mousePoint)) {
// Is the mouse point within the color circle?
// If so, you just clicked on the color wheel.
currentState = MouseState.ClickOnColor;
} else if (brightnessRegion.IsVisible(mousePoint)) {
// Is the mouse point within the brightness area?
// You clicked on the brightness area.
currentState = MouseState.ClickOnBrightness;
} else {
// Clicked outside the color and the brightness
// regions. In that case, just put the
// pointers back where they were.
currentState = MouseState.ClickOutsideRegion;
}
}
}
switch (currentState) {
case MouseState.ClickOnBrightness:
case MouseState.DragInBrightness:
// Calculate new color information
// based on the brightness, which may have changed.
newPoint = mousePoint;
if (newPoint.Y < brightnessMin) {
newPoint.Y = brightnessMin;
} else if (newPoint.Y > brightnessMax) {
newPoint.Y = brightnessMax;
}
newBrightnessPoint = new Point(brightnessX, newPoint.Y);
brightness = (int)((brightnessMax - newPoint.Y) * brightnessScaling);
HSV.value = brightness;
RGB = ColorHandler.HSVtoRGB(HSV);
break;
case MouseState.ClickOnColor:
case MouseState.DragInColor:
// Calculate new color information
// based on selected color, which may have changed.
newColorPoint = mousePoint;
// Calculate x and y distance from the center,
// and then calculate the angle corresponding to the
// new location.
delta = new Point(
mousePoint.X - centerPoint.X, mousePoint.Y - centerPoint.Y);
degrees = CalcDegrees(delta);
// Calculate distance from the center to the new point
// as a fraction of the radius. Use your old friend,
// the Pythagorean theorem, to calculate this value.
distance = Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y) / radius;
if (currentState == MouseState.DragInColor) {
if (distance > 1) {
// Mouse is down, and outside the circle, but you
// were previously dragging in the color circle.
// What to do?
// In that case, move the point to the edge of the
// circle at the correct angle.
distance = 1;
newColorPoint = GetPoint(degrees, radius, centerPoint);
}
}
// Calculate the new HSV and RGB values.
HSV.Hue = (int)(degrees * 255 / 360);
HSV.Saturation = (int)(distance * 255);
HSV.value = brightness;
RGB = ColorHandler.HSVtoRGB(HSV);
fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
break;
}
selectedColor = ColorHandler.HSVtoColor(HSV);
// Raise an event back to the parent form,
// so the form can update any UI it's using
// to display selected color values.
OnColorChanged(RGB, HSV);
// On the way out, set the new state.
switch (currentState) {
case MouseState.ClickOnBrightness:
currentState = MouseState.DragInBrightness;
break;
case MouseState.ClickOnColor:
currentState = MouseState.DragInColor;
break;
case MouseState.ClickOutsideRegion:
currentState = MouseState.DragOutsideRegion;
break;
}
// Store away the current points for next time.
colorPoint = newColorPoint;
brightnessPoint = newBrightnessPoint;
// Draw the gradients and points.
UpdateDisplay();
}
private Point CalcBrightnessPoint(int brightness) {
// Take the value for brightness (0 to 255), scale to the
// scaling used in the brightness bar, then add the value
// to the bottom of the bar. return the correct point at which
// to display the brightness pointer.
return new Point(brightnessX, (int)(brightnessMax - brightness / brightnessScaling));
}
/*public void SetColor(Color c) {
fullColor = c;
UpdateDisplay();
}*/
private void UpdateDisplay() {
// Update the gradients, and place the pointers correctly based on colors and
// brightness.
using (Brush selectedBrush = new SolidBrush(selectedColor)) {
// Draw the saved color wheel image.
g.DrawImage(colorImage, colorRectangle);
// Draw the "brightness" rectangle.
DrawLinearGradient(fullColor);
// Draw the two pointers.
DrawColorPointer(colorPoint);
DrawBrightnessPointer(brightnessPoint);
}
}
private void CalcCoordsAndUpdate(ColorHandler.HSV HSV) {
// Convert color to real-world coordinates and then calculate
// the various points. HSV.Hue represents the degrees (0 to 360),
// HSV.Saturation represents the radius.
// This procedure doesn't draw anything--it simply
// updates class-level variables. The UpdateDisplay
// procedure uses these values to update the screen.
// Given the angle (HSV.Hue), and distance from
// the center (HSV.Saturation), and the center,
// calculate the point corresponding to
// the selected color, on the color wheel.
colorPoint = GetPoint((double)HSV.Hue / 255 * 360,
(double)HSV.Saturation / 255 * radius,
centerPoint);
// Given the brightness (HSV.value), calculate the
// point corresponding to the brightness indicator.
brightnessPoint = CalcBrightnessPoint(HSV.value);
// Store information about the selected color.
brightness = HSV.value;
selectedColor = ColorHandler.HSVtoColor(HSV);
RGB = ColorHandler.HSVtoRGB(HSV);
// The full color is the same as HSV, except that the
// brightness is set to full (255). This is the top-most
// color in the brightness gradient.
fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
}
private void DrawLinearGradient(Color TopColor) {
// Given the top color, draw a linear gradient
// ranging from black to the top color. Use the
// brightness rectangle as the area to fill.
using (LinearGradientBrush lgb =
new LinearGradientBrush(brightnessRectangle, TopColor,
Color.Black, LinearGradientMode.Vertical)) {
g.FillRectangle(lgb, brightnessRectangle);
}
}
private int CalcDegrees(Point pt) {
int degrees;
if (pt.X == 0) {
// The point is on the y-axis. Determine whether it's above or below the x-axis, and return the
// corresponding angle. Note that the orientation of the y-coordinate is backwards. That is,
// A positive Y value indicates a point BELOW the x-axis.
if (pt.Y > 0) {
degrees = 270;
} else {
degrees = 90;
}
} else {
// This value needs to be multiplied by -1 because the y-coordinate
// is opposite from the normal direction here.
// That is, a y-coordinate that's "higher" on the form has a lower y-value, in this coordinate
// system. So everything's off by a factor of -1 when performing the ratio calculations.
degrees = (int)(-Math.Atan((double)pt.Y / pt.X) * DEGREES_PER_RADIAN);
// If the x-coordinate of the selected point is to the left of the center of the circle, you
// need to add 180 degrees to the angle. ArcTan only gives you a value on the right-hand side
// of the circle.
if (pt.X < 0) {
degrees += 180;
}
// Ensure that the return value is between 0 and 360.
degrees = (degrees + 360) % 360;
}
return degrees;
}
private void CreateGradient() {
// Create a new PathGradientBrush, supplying an array of points created by calling
// the GetPoints method.
using (PathGradientBrush pgb =
new PathGradientBrush(GetPoints(radius, new Point(radius, radius)))) {
// Set the various properties. Note the SurroundColors property, which contains an array of points,
// in a one-to-one relationship with the points that created the gradient.
pgb.CenterColor = Color.White;
pgb.CenterPoint = new PointF(radius, radius);
pgb.SurroundColors = GetColors();
// Create a new bitmap containing the color wheel gradient, so the
// code only needs to do all this work once. Later code uses the bitmap
// rather than recreating the gradient.
colorImage = new Bitmap(
colorRectangle.Width, colorRectangle.Height,
PixelFormat.Format32bppArgb);
using (Graphics newGraphics =
Graphics.FromImage(colorImage)) {
newGraphics.FillEllipse(pgb, 0, 0,
colorRectangle.Width, colorRectangle.Height);
}
}
}
private Color[] GetColors() {
// Create an array of COLOR_COUNT colors, looping through all the hues between 0 and 255, broken
// into COLOR_COUNT intervals. HSV is particularly well-suited for this, because the only value
// that changes as you create colors is the Hue.
Color[] Colors = new Color[COLOR_COUNT];
for (int i = 0; i <= COLOR_COUNT - 1; i++)
Colors[i] = ColorHandler.HSVtoColor((int)((double)(i * 255) / COLOR_COUNT), 255, 255);
return Colors;
}
private Point[] GetPoints(double radius, Point centerPoint) {
// Generate the array of points that describe the locations of the COLOR_COUNT colors to be
// displayed on the color wheel.
Point[] Points = new Point[COLOR_COUNT];
for (int i = 0; i <= COLOR_COUNT - 1; i++)
Points[i] = GetPoint((double)(i * 360) / COLOR_COUNT, radius, centerPoint);
return Points;
}
private Point GetPoint(double degrees, double radius, Point centerPoint) {
// Given the center of a circle and its radius, along
// with the angle corresponding to the point, find the coordinates.
// In other words, conver t from polar to rectangular coordinates.
double radians = degrees / DEGREES_PER_RADIAN;
return new Point((int)(centerPoint.X + Math.Floor(radius * Math.Cos(radians))),
(int)(centerPoint.Y - Math.Floor(radius * Math.Sin(radians))));
}
private void DrawColorPointer(Point pt) {
// Given a point, draw the color selector. The constant SIZE represents half
// the width -- the square will be twice this value in width and height.
const int SIZE = 3;
g.DrawRectangle(Pens.Black,
pt.X - SIZE, pt.Y - SIZE, SIZE * 2, SIZE * 2);
}
private void DrawBrightnessPointer(Point pt) {
// Draw a triangle for the brightness indicator that "points" at the provided point.
const int HEIGHT = 10;
const int WIDTH = 7;
Point[] Points = new Point[3];
Points[0] = pt;
Points[1] = new Point(pt.X + WIDTH, pt.Y + HEIGHT / 2);
Points[2] = new Point(pt.X + WIDTH, pt.Y - HEIGHT / 2);
g.FillPolygon(Brushes.Black, Points);
}
}
}

View file

@ -206,7 +206,7 @@ namespace CodeImp.DoomBuilder
internal static Dictionary<string, ScriptConfiguration> ScriptConfigs { get { return scriptconfigs; } }
public static MapManager Map { get { return map; } }
public static ActionManager Actions { get { return actions; } }
internal static PluginManager Plugins { get { return plugins; } }
internal static PluginManager Plugins { get { return plugins; } }
public static Clock Clock { get { return clock; } }
public static bool DebugBuild { get { return debugbuild; } }
internal static TypesManager Types { get { return types; } }
@ -219,7 +219,7 @@ namespace CodeImp.DoomBuilder
public static bool NoSettings { get { return nosettings; } }
public static EditingManager Editing { get { return editing; } }
public static ErrorLogger ErrorLogger { get { return errorlogger; } }
#endregion
#region ================== Configurations
@ -1436,7 +1436,12 @@ namespace CodeImp.DoomBuilder
public static void Fail(string message)
{
General.WriteLogLine("FAIL: " + message);
//mxd. Lets notify the user about our Epic Failure before crashing...
#if DEBUG
Debug.Fail(message);
#else
ShowErrorMessage(message, MessageBoxButtons.OK);
#endif
Terminate(false);
}
@ -1527,6 +1532,14 @@ namespace CodeImp.DoomBuilder
{
return Math.Min(Math.Max(min, value), max);
}
//mxd. This clamps angle between 0 and 359
public static int ClampAngle(int angle) {
if (angle > -1 && angle < 360) return angle;
int n = angle / 360;
if (angle > 0) return angle - n * 360;
return 360 - Math.Abs(angle) + Math.Abs(n) * 360;
}
// This returns an element from a collection by index
public static T GetByIndex<T>(ICollection<T> collection, int index)

View file

@ -1,6 +1,7 @@
#region ================== Namespaces
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
@ -37,6 +38,18 @@ namespace CodeImp.DoomBuilder.Plugins
// Disposing
private bool isdisposed = false;
//mxd. It's nice to have these avaliable to plugins...
protected static Point DisplayLocationAbs {
get {
if (General.MainWindow == null || General.MainWindow.Display == null)
return new Point();
return new Point(General.MainWindow.Location.X + General.MainWindow.ClientRectangle.X + General.MainWindow.Display.Location.X, General.MainWindow.Location.Y + General.MainWindow.ClientRectangle.Y + General.MainWindow.Display.Location.Y);
}
}
//mxd. It's nice to have these avaliable to plugins...
protected static Size DisplaySize { get { return (General.MainWindow == null || General.MainWindow.Display == null) ? new Size() : General.MainWindow.Display.Size; } }
#endregion
#region ================== Properties
@ -115,6 +128,15 @@ namespace CodeImp.DoomBuilder.Plugins
return plugin.GetResourceStream(resourcename);
}
//mxd. It's nice to have these avaliable to plugins...
public static bool DisplayStatus(StatusType type, string message) {
if (General.MainWindow != null) {
General.MainWindow.DisplayStatus(type, message);
return true;
}
return false;
}
#endregion
#region ================== Events

View file

@ -119,7 +119,9 @@ namespace CodeImp.DoomBuilder.Rendering
// To ColorRef (alpha-less)
public int ToColorRef()
{
return ((int)r + ((int)b << 16) + ((int)g << 8));
//mxd
//return ((int)r + ((int)b << 16) + ((int)g << 8));
return (((int)r << 16) + ((int)g << 8) + (int)b);
}
// To ColorValue

View file

@ -1065,6 +1065,7 @@ namespace CodeImp.DoomBuilder.Rendering
int locksize = (things.Count > THING_BUFFER_SIZE) ? THING_BUFFER_SIZE : things.Count;
FlatVertex[] verts = new FlatVertex[THING_BUFFER_SIZE * 12];
//mxd
thingsWithModel = new Dictionary<Vector2D, Thing>();
// Go for all things
@ -1113,7 +1114,6 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd. Render models
if (thingsWithModel.Count > 0) {
// Set renderstates for rendering
//graphics.Device.SetRenderState(RenderState.ZEnable, false);
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
graphics.Device.SetRenderState(RenderState.TextureFactor, -1);

View file

@ -742,9 +742,11 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd. Seems that translucent lines aren't affected by dynamic lights in GZDoom
if (g.RenderPass != RenderPass.Alpha && General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) {
if (!litGeometry.ContainsKey(curtexture.Texture))
litGeometry[curtexture.Texture] = new List<VisualGeometry>();
litGeometry[curtexture.Texture].Add(g);
if (curtexture.Texture != null) {
if (!litGeometry.ContainsKey(curtexture.Texture))
litGeometry[curtexture.Texture] = new List<VisualGeometry>();
litGeometry[curtexture.Texture].Add(g);
}
}
// Switch shader pass?
@ -1103,7 +1105,7 @@ namespace CodeImp.DoomBuilder.Rendering
t.CalculateCameraDistance3D(D3DDevice.V3(cameraposition));
//t.CameraDistance3D is actually squared distance, hence (t.LightRadius * t.LightRadius)
if (t.CameraDistance3D < (t.LightRadius * t.LightRadius) || isThingOnScreen(t.BoundingBox)) { //always render light if camera is within it's radius
if (t.LightType == (int)GZDoomLightType.FLICKER || t.LightType == (int)GZDoomLightType.PULSE || t.LightType == (int)GZDoomLightType.RANDOM)
if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1)
t.UpdateBoundingBox(t.LightRadius, t.LightRadius * 2);
thingsWithLight.Add(t);
}

View file

@ -878,17 +878,6 @@ gzdrawselectedmodelsonly
allowscroll = false;
}
//panels
gztogglelightpannel
{
title = "Toggle dynamic light pannel";
category = "gzdoombuilder";
description = "Select dynamic light thing(s), then use this pannel to set light properties quickly.";
allowkeys = true;
allowmouse = true;
allowscroll = false;
}
gztogglefogpannel
{
title = "Toggle fog pannel";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 152 KiB

View file

@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.VisualModes
{
// Initialize
this.movemultiplier = new Vector3D(1.0f, 1.0f, 1.0f);
this.position = position;
//this.position = position;
this.anglexy = 0.0f;
this.anglez = Angle2D.PI;
this.sector = null;

View file

@ -99,7 +99,6 @@ namespace CodeImp.DoomBuilder.VisualModes
//mxd
internal Vector3[] BoundingBox { get { return boundingBox; } }
//internal Vector3D Normal { get { return normal; } }
/// <summary>
/// Render pass in which this geometry must be rendered. Default is Solid.
@ -175,48 +174,51 @@ namespace CodeImp.DoomBuilder.VisualModes
//mxd. Taken from OpenGl wiki
protected void CalculateNormalsAndShading() {
int startIndex;
Vector3 U, V;
if (vertices.Length > 0) {
int startIndex;
Vector3 U, V;
BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
BoundingBoxSizes bbs = new BoundingBoxSizes(vertices[0]);
for (int i = 0; i < triangles; i++) {
startIndex = i * 3;
WorldVertex p1 = vertices[startIndex];
WorldVertex p2 = vertices[startIndex + 1];
WorldVertex p3 = vertices[startIndex + 2];
for (int i = 0; i < triangles; i++) {
startIndex = i * 3;
WorldVertex p1 = vertices[startIndex];
WorldVertex p2 = vertices[startIndex + 1];
WorldVertex p3 = vertices[startIndex + 2];
U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y);
p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);
p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X);
//doom-style walls shading
//not very apropriate place to put this, but most convinient :)
if (sidedef != null) {
byte valMod = (byte)(Math.Abs((float)Math.Sin(sidedef.Angle)) * 0.07f * 255);
PixelColor modColor = new PixelColor(255, valMod, valMod, valMod);
PixelColor pc = PixelColor.FromInt(p1.c);
//doom-style walls shading
//not very apropriate place to put this, but most convinient :)
if (sidedef != null) {
float valMod = 1.0f - Math.Abs((float)Math.Sin(sidedef.Angle)) * 0.07f; //0.07
PixelColor pc = PixelColor.FromInt(p1.c);
if (pc.r < modColor.r) modColor.r = pc.r;
if (pc.g < modColor.g) modColor.g = pc.g;
if (pc.b < modColor.b) modColor.b = pc.b;
pc.r = (byte)((float)pc.r * valMod);
pc.g = (byte)((float)pc.g * valMod);
pc.b = (byte)((float)pc.b * valMod);
p1.c = p2.c = p3.c -= modColor.ToColorRef();
int colorRef = pc.ToColorRef();
p1.c = colorRef;
p2.c = colorRef;
p3.c = colorRef;
}
vertices[startIndex] = p1;
vertices[startIndex + 1] = p2;
vertices[startIndex + 2] = p3;
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
}
vertices[startIndex] = p1;
vertices[startIndex + 1] = p2;
vertices[startIndex + 2] = p3;
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p1);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p2);
BoundingBoxTools.UpdateBoundingBoxSizes(ref bbs, p3);
boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);
}
if (triangles > 0)
boundingBox = BoundingBoxTools.CalculateBoundingPlane(bbs);
}
// This compares for sorting by sector

View file

@ -70,6 +70,10 @@ namespace CodeImp.DoomBuilder.VisualModes
private bool keyup;
private bool keydown;
//mxd
private bool visibleThingsUpdated;
private List<VisualThing> selectedThings;
// Map
protected VisualBlockMap blockmap;
protected Dictionary<Thing, VisualThing> allthings;
@ -78,6 +82,21 @@ namespace CodeImp.DoomBuilder.VisualModes
protected List<VisualThing> visiblethings;
protected Dictionary<Sector, VisualSector> visiblesectors;
protected List<VisualGeometry> visiblegeometry;
//mxd
public List<VisualThing> SelectedVisualThings {
get {
if (visibleThingsUpdated) {
visibleThingsUpdated = false;
selectedThings = new List<VisualThing>();
foreach (VisualThing t in visiblethings) {
if (t.Selected)
selectedThings.Add(t);
}
}
return selectedThings;
}
}
#endregion
@ -318,6 +337,9 @@ namespace CodeImp.DoomBuilder.VisualModes
visiblegeometry = new List<VisualGeometry>(visiblegeometry.Capacity);
visiblethings = new List<VisualThing>(visiblethings.Capacity);
//mxd
visibleThingsUpdated = true;
// Get the blocks within view range
visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D);

View file

@ -129,6 +129,9 @@ namespace CodeImp.DoomBuilder.VisualModes
// Make new geometry
//Update();
}
//mxd
public virtual void UpdateSectorData() { }
// This updates the visual sector
public void Update()

View file

@ -88,8 +88,8 @@ namespace CodeImp.DoomBuilder.VisualModes
private int lightRenderStyle;
private Color4 lightColor;
private float lightRadius; //current radius. used in light animation
private float lightRadiusMin;
private float lightRadiusMax;
private float lightPrimaryRadius;
private float lightSecondaryRadius;
private Vector3 position_v3;
private float lightDelta; //used in light animation
private Vector3[] boundingBox;
@ -172,8 +172,8 @@ namespace CodeImp.DoomBuilder.VisualModes
//mxd
lightType = -1;
lightRenderStyle = -1;
lightRadiusMin = -1;
lightRadiusMax = -1;
lightPrimaryRadius = -1;
lightSecondaryRadius = -1;
lightColor = new Color4();
boundingBox = new Vector3[9];
@ -340,8 +340,8 @@ namespace CodeImp.DoomBuilder.VisualModes
}
lightType = -1;
lightRadius = -1;
lightRadiusMin = -1;
lightRadiusMax = -1;
lightPrimaryRadius = -1;
lightSecondaryRadius = -1;
lightRenderStyle = -1;
}
@ -350,6 +350,17 @@ namespace CodeImp.DoomBuilder.VisualModes
}
}
//used in ColorPicker to update light
public void UpdateLight() {
int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type);
if (light_id != -1) {
updateLight(light_id);
//if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, lightType) != -1)
UpdateBoundingBox(lightRadius, lightRadius * 2);
}
}
//mxd update light info
private void updateLight(int light_id) {
float scaled_intensity = 255.0f / General.Settings.GZDynamicLightIntensity;
@ -376,18 +387,11 @@ namespace CodeImp.DoomBuilder.VisualModes
int scaler = 1;
if (thing.Sector != null)
scaler = thing.Sector.Brightness / 4;
lightRadiusMin = (float)(thing.Args[3] * scaler) * General.Settings.GZDynamicLightRadius;
lightPrimaryRadius = (float)(thing.Args[3] * scaler) * General.Settings.GZDynamicLightRadius;
} else {
lightRadiusMin = (float)(thing.Args[3] * 2) * General.Settings.GZDynamicLightRadius; //works... that.. way in GZDoom
if (lightType > 0) {
lightRadiusMax = (float)(thing.Args[4] * 2) * General.Settings.GZDynamicLightRadius;
if (lightRadiusMin > lightRadiusMax) { //swap them
float lrm = lightRadiusMin;
lightRadiusMin = lightRadiusMax;
lightRadiusMax = lrm;
}
}
lightPrimaryRadius = (float)(thing.Args[3] * 2) * General.Settings.GZDynamicLightRadius; //works... that.. way in GZDoom
if (lightType > 0)
lightSecondaryRadius = (float)(thing.Args[4] * 2) * General.Settings.GZDynamicLightRadius;
}
} else { //it's one of vavoom lights
lightRenderStyle = (int)GZDoomLightRenderStyle.VAVOOM;
@ -396,7 +400,7 @@ namespace CodeImp.DoomBuilder.VisualModes
lightColor = new Color4((float)lightRenderStyle / 100.0f, (float)thing.Args[1] / scaled_intensity, (float)thing.Args[2] / scaled_intensity, (float)thing.Args[3] / scaled_intensity);
else
lightColor = new Color4((float)lightRenderStyle / 100.0f, General.Settings.GZDynamicLightIntensity, General.Settings.GZDynamicLightIntensity, General.Settings.GZDynamicLightIntensity);
lightRadiusMin = (float)(thing.Args[0] * 8) * General.Settings.GZDynamicLightRadius;
lightPrimaryRadius = (float)(thing.Args[0] * 8) * General.Settings.GZDynamicLightRadius;
}
UpdateLightRadius();
}
@ -408,39 +412,45 @@ namespace CodeImp.DoomBuilder.VisualModes
return;
}
if (!General.Settings.GZAnimateLights || lightType == (int)GZDoomLightType.NORMAL
|| lightType == (int)GZDoomLightType.SECTOR
|| lightType == (int)GZDoomLightType.VAVOOM
|| lightType == (int)GZDoomLightType.VAVOOM_COLORED) {
lightRadius = lightRadiusMin;
if (!General.Settings.GZAnimateLights || Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, lightType) == -1) {
lightRadius = lightPrimaryRadius;
return;
}
double time = General.Clock.GetCurrentTime();
float diff = lightRadiusMax - lightRadiusMin;
float rMin, rMax;
if (lightPrimaryRadius > lightSecondaryRadius) {
rMax = lightPrimaryRadius;
rMin = lightSecondaryRadius;
} else {
rMin = lightPrimaryRadius;
rMax = lightSecondaryRadius;
}
float diff = rMax - rMin;
//pulse
if (lightType == (int)GZDoomLightType.PULSE) {
lightDelta = (float)Math.Sin(time / (100.0f * thing.Angle * 2.3f)); //just playing by the eye here...
lightRadius = Math.Abs((int)(lightRadiusMin + diff/2 + diff/2 * lightDelta));
lightDelta = ((float)Math.Sin(time / (thing.AngleDoom * 4.0f)) + 1.0f) / 2.0f; //just playing by the eye here... in [0.0 ... 1.0] interval
lightRadius = rMin + diff * lightDelta;
//flicker
} else if (lightType == (int)GZDoomLightType.FLICKER) {
float delta = (float)Math.Sin(time / (100.0f * thing.Angle * 0.02f)); //just playing by the eye here...
//float delta = (float)Math.Sin(time / thing.AngleDoom);
float delta = (float)Math.Sin(time / 0.1f); //just playing by the eye here...
if (Math.Sign(delta) != Math.Sign(lightDelta)) {
lightDelta = delta;
int angle = (int)(thing.Angle * 180 / Math.PI);
if (new Random().Next(0, 360) > angle) {
lightRadius = lightRadiusMax;
} else {
lightRadius = lightRadiusMin;
}
if (new Random().Next(0, 359) < thing.AngleDoom)
lightRadius = rMax;
else
lightRadius = rMin;
}
//random
} else if (lightType == (int)GZDoomLightType.RANDOM) {
float delta = (float)Math.Sin(time / (100.0f * thing.Angle * 4.6f)); //just playing by the eye here...
//float delta = (float)Math.Sin(time / (thing.AngleDoom));
float delta = (float)Math.Sin(time / (thing.AngleDoom * 9.0f)); //just playing by the eye here...
if (Math.Sign(delta) != Math.Sign(lightDelta))
lightRadius = lightRadiusMin + (float)(new Random().Next(0, (int)(diff * 10))) / 10.0f;
lightRadius = rMin + (float)(new Random().Next(0, (int)(diff * 10))) / 10.0f;
lightDelta = delta;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1778,30 +1778,26 @@ namespace CodeImp.DoomBuilder.Windows
//mxd
public void UpdateGZDoomPannel() {
if (General.Settings.GZToolbarGZDoom) {
buttontogglemodels.Checked = General.Settings.GZDrawModels;
buttonselectedmodelsonly.Checked = General.Settings.GZDrawSelectedModelsOnly;
buttontoggledynlight.Checked = General.Settings.GZDrawLights;
buttontoggleanimatedlight.Checked = General.Settings.GZAnimateLights;
if (General.Map != null) {
buttontogglemodels.Enabled = true;
buttonselectedmodelsonly.Enabled = true;
buttontoggledynlight.Enabled = true;
buttontoggleanimatedlight.Enabled = true;
if (General.Settings.GZToolbarGZDoom) {
buttontogglemodels.Checked = General.Settings.GZDrawModels;
buttonselectedmodelsonly.Checked = General.Settings.GZDrawSelectedModelsOnly;
buttontoggledynlight.Checked = General.Settings.GZDrawLights;
buttontoggleanimatedlight.Checked = General.Settings.GZAnimateLights;
}
} else {
buttontogglemodels.Enabled = false;
buttonselectedmodelsonly.Enabled = false;
buttontoggledynlight.Enabled = false;
buttontoggleanimatedlight.Enabled = false;
}
}
private void buttontoggledynlight_Click(object sender, EventArgs e) {
GZBuilder.GZGeneral.ToggleLights();
}
private void buttontoggleanimatedlight_Click(object sender, EventArgs e) {
GZBuilder.GZGeneral.ToggleLightsAnimation();
}
private void buttontogglemodels_Click(object sender, EventArgs e) {
GZBuilder.GZGeneral.ToggleModels();
}
private void buttonselectedmodelsonly_Click(object sender, EventArgs e) {
GZBuilder.GZGeneral.ToggleDrawSelectedModelsOnly();
}
#endregion
#region ================== Menus
@ -2762,6 +2758,11 @@ namespace CodeImp.DoomBuilder.Windows
#endregion
#region ================== Dockers
//mxd. used to add a docker from DoomBuilder's core code.
internal void addDocker(Docker d) {
d.MakeFullName("gzdoombuilder");
dockerspanel.Add(d);
}
// This adds a docker
public void AddDocker(Docker d)
@ -2786,6 +2787,13 @@ namespace CodeImp.DoomBuilder.Windows
return dockerspanel.Remove(d);
}
//mxd
internal bool selectDocker(Docker d) {
d.MakeFullName("gzdoombuilder");
ReleaseAllKeys();
return dockerspanel.SelectDocker(d);
}
// This selects a docker
public bool SelectDocker(Docker d)

View file

@ -126,6 +126,12 @@
<metadata name="toolStripSeparator12.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="toolStripMenuItem4.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="menumain.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@ -151,22 +157,16 @@
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY2CgJnjdLnGRFIxiN0wjMQ7CUAsSAGmE0fgM
wVD7rkP6KykYZjjcMpBmDEEcTsCqllgD5igq/gepBdEo3iXFgOfNkr9ABuQXljeR7AWQRrwGgBQgY1gw
wVD7rkP6KykYZjjcMpBmDEEcTsCqllgD5igq/gepBdEo3iXFgKf1kr9ABuQXljeR7AWQRrwGgBQgY1gw
IIvhNADmLGw0yCCQk/G6AJ8BIM0gQwgasLzG/wW6QTCNMG/AvACLCbA3QbEAClGYTeg0zAsgcZABMLUw
dWADSMHE5BWS1AAAQvokPWS9KEkAAAAASUVORK5CYII=
dWADSMHE5BWS1AAACnwkE01c7eYAAAAASUVORK5CYII=
</value>
</data>
<metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>218, 17</value>
</metadata>
<metadata name="statusbar.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="toolStripMenuItem4.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
<metadata name="statusbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>218, 17</value>
</metadata>
<metadata name="panelinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>

View file

@ -240,7 +240,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This forces to rebuild the whole thing
public void Rebuild()
{
// Setup visual thing
// Find thing information //mxd. I think it should be here
info = General.Map.Data.GetThingInfo(Thing.Type);
// Find sprite texture //mxd. and this
if (info.Sprite.Length > 0) {
sprite = General.Map.Data.GetSpriteImage(info.Sprite);
if (sprite != null) sprite.AddReference();
}
// Setup visual thing
Setup();
}

View file

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Plugins;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.ColorPicker.Windows;
namespace CodeImp.DoomBuilder.ColorPicker
{
public class BuilderPlug : Plug
{
private static BuilderPlug me;
public static BuilderPlug Me { get { return me; } }
public override string Name { get { return "Color Picker"; } }
private IColorPicker form;
private ToolsForm toolsform;
private string currentModeName = "";
private Point formLocation; //used to keep forms location constant
public override void OnInitialize() {
//yeeees, I used string to store version number before 1.05...
if (GZBuilder.GZGeneral.Version.GetType().Name != "Single") {
General.ErrorLogger.Add(ErrorType.Error, "ColorPicker plugin: GZDoomBuilder 1.05 or later required!");
return;
}
base.OnInitialize();
me = this;
General.Actions.BindMethods(this);
}
public override void OnMapOpenEnd() {
if (toolsform == null)
toolsform = new ToolsForm();
//dbg
/*CodeImp.DoomBuilder.Rendering.PixelColor c = new CodeImp.DoomBuilder.Rendering.PixelColor(255, 255, 64, 3);
int ic = c.ToColorRef();
CodeImp.DoomBuilder.Rendering.PixelColor c2 = CodeImp.DoomBuilder.Rendering.PixelColor.FromInt(ic);
GZBuilder.GZGeneral.Trace("c: "+c.r+","+c.g+","+c.b);
GZBuilder.GZGeneral.Trace("ic: " + ic);
GZBuilder.GZGeneral.Trace("c2: " + c2.r + "," + c2.g + "," + c2.b);*/
}
public override void OnMapNewEnd() {
OnMapOpenEnd();
}
public override void Dispose() {
base.Dispose();
General.Actions.UnbindMethods(this);
if (form != null) form.Close();
form = null;
if (toolsform != null) toolsform.Dispose();
toolsform = null;
}
[BeginAction("togglelightpannel")]
private void toggleLightPannel() {
if (General.Editing.Mode == null)
return;
currentModeName = General.Editing.Mode.GetType().Name;
bool udmf = General.Map.Config.FormatInterface == "UniversalMapSetIO";
//display one of colorPickers or tell the user why we can't do that
if (currentModeName == "ThingsMode") {
if(General.Map.Map.SelectedThingsCount == 0){
Plug.DisplayStatus(StatusType.Warning, "Select some lights first!");
return;
}
form = new LightColorPicker();
} else if (currentModeName == "SectorsMode") {
if (udmf) {
if (General.Map.Map.SelectedSectorsCount == 0) {
Plug.DisplayStatus(StatusType.Warning, "Select some sectors first!");
return;
}
form = new SectorColorPicker();
} else {
Plug.DisplayStatus(StatusType.Warning, "Sector colors can only be set if map is in UDMF format!");
return;
}
} else if (currentModeName == "BaseVisualMode") {
//nothing selected in visual mode?
if ( ((VisualMode)General.Editing.Mode).SelectedVisualThings.Count == 0 ) {
//check sectors
if (udmf && General.Map.Map.SelectedSectorsCount > 0) {
form = new SectorColorPicker();
} else {
Plug.DisplayStatus(StatusType.Warning, "Select some lights " + (udmf ? "or sectors " : "") + "first!");
return;
}
} else {
form = new LightColorPicker();
}
} else { //wrong mode
Plug.DisplayStatus(StatusType.Warning, "Switch to" + (udmf ? " Sectors," : "") + " Things or GZDoom Visual Mode first!");
return;
}
if (form.Setup(currentModeName)) {
if (formLocation.X == 0 && formLocation.Y == 0) {
Size displaySize = Plug.DisplaySize;
Point displayLocation = Plug.DisplayLocationAbs;
formLocation = new Point(displayLocation.X + displaySize.Width - form.Width - 16, displayLocation.Y + 32);
}
form.Location = formLocation;
form.FormClosed += new FormClosedEventHandler(form_FormClosed);
form.ShowDialog(Form.ActiveForm);
} else {
form.Dispose();
form = null;
}
}
private void form_FormClosed(object sender, FormClosedEventArgs e) {
formLocation = form.Location;
form.Dispose();
form = null;
}
}
}

View file

@ -0,0 +1,17 @@
using System;
namespace CodeImp.DoomBuilder.ColorPicker
{
public class ColorChangedEventArgs : EventArgs {
private ColorHandler.RGB mRGB;
private ColorHandler.HSV mHSV;
public ColorChangedEventArgs(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
mRGB = RGB;
mHSV = HSV;
}
public ColorHandler.RGB RGB { get { return mRGB; } }
public ColorHandler.HSV HSV { get { return mHSV; } }
}
}

View file

@ -0,0 +1,211 @@
using System;
using System.Drawing;
namespace CodeImp.DoomBuilder.ColorPicker
{
public class ColorHandler {
// Handle conversions between RGB and HSV
// (and Color types, as well).
public struct RGB {
// All values are between 0 and 255.
public int Red;
public int Green;
public int Blue;
public RGB(int R, int G, int B) {
Red = R;
Green = G;
Blue = B;
}
}
public struct HSV {
// All values are between 0 and 255.
public int Hue;
public int Saturation;
public int value;
public HSV(int H, int S, int V) {
Hue = H;
Saturation = S;
value = V;
}
public override string ToString() {
return String.Format("({0}, {1}, {2})", Hue, Saturation, value);
}
}
public static RGB HSVtoRGB(int H, int S, int V) {
// H, S, and V must all be between 0 and 255.
return HSVtoRGB(new HSV(H, S, V));
}
public static Color HSVtoColor(HSV hsv) {
RGB RGB = HSVtoRGB(hsv);
return Color.FromArgb(RGB.Red, RGB.Green, RGB.Blue);
}
public static Color HSVtoColor(int H, int S, int V) {
return HSVtoColor(new HSV(H, S, V));
}
public static Color RGBtoColor(RGB rgb) {
return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
}
public static RGB HSVtoRGB(HSV HSV) {
// HSV contains values scaled as in the color wheel:
// that is, all from 0 to 255.
// for ( this code to work, HSV.Hue needs
// to be scaled from 0 to 360 (it//s the angle of the selected
// point within the circle). HSV.Saturation and HSV.value must be
// scaled to be between 0 and 1.
double h;
double s;
double v;
double r = 0;
double g = 0;
double b = 0;
// Scale Hue to be between 0 and 360. Saturation
// and value scale to be between 0 and 1.
h = ((double)HSV.Hue / 255 * 360) % 360;
s = (double)HSV.Saturation / 255;
v = (double)HSV.value / 255;
if (s == 0) {
// If s is 0, all colors are the same.
// This is some flavor of gray.
r = v;
g = v;
b = v;
} else {
double p;
double q;
double t;
double fractionalSector;
int sectorNumber;
double sectorPos;
// The color wheel consists of 6 sectors.
// Figure out which sector you//re in.
sectorPos = h / 60;
sectorNumber = (int)(Math.Floor(sectorPos));
// get the fractional part of the sector.
// That is, how many degrees into the sector
// are you?
fractionalSector = sectorPos - sectorNumber;
// Calculate values for the three axes
// of the color.
p = v * (1 - s);
q = v * (1 - (s * fractionalSector));
t = v * (1 - (s * (1 - fractionalSector)));
// Assign the fractional colors to r, g, and b
// based on the sector the angle is in.
switch (sectorNumber) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
}
// return an RGB structure, with values scaled
// to be between 0 and 255.
return new RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
}
public static HSV RGBtoHSV(RGB RGB) {
// In this function, R, G, and B values must be scaled
// to be between 0 and 1.
// HSV.Hue will be a value between 0 and 360, and
// HSV.Saturation and value are between 0 and 1.
// The code must scale these to be between 0 and 255 for
// the purposes of this application.
double min;
double max;
double delta;
double r = (double)RGB.Red / 255;
double g = (double)RGB.Green / 255;
double b = (double)RGB.Blue / 255;
double h;
double s;
double v;
min = Math.Min(Math.Min(r, g), b);
max = Math.Max(Math.Max(r, g), b);
v = max;
delta = max - min;
if (max == 0 || delta == 0) {
// R, G, and B must be 0, or all the same. In this case, S is 0, and H is undefined.
// Using H = 0 is as good as any...
s = 0;
h = 0;
} else {
s = delta / max;
if (r == max) {
// Between Yellow and Magenta
h = (g - b) / delta;
} else if (g == max) {
// Between Cyan and Yellow
h = 2 + (b - r) / delta;
} else {
// Between Magenta and Cyan
h = 4 + (r - g) / delta;
}
}
// Scale h to be between 0 and 360.
// This may require adding 360, if the value is negative.
h *= 60;
if (h < 0) {
h += 360;
}
// Scale to the requirements of this application. All values are between 0 and 255.
return new HSV((int)(h / 360 * 255), (int)(s * 255), (int)(v * 255));
}
}
}

View file

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A4761900-0EA3-4FE4-A919-847FD5080EFC}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CodeImp.DoomBuilder.ColorPicker</RootNamespace>
<AssemblyName>ColorPicker</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="Trackbar, Version=1.0.2486.37933, Culture=neutral, PublicKeyToken=503bf28f63ad27b4">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\Build\Trackbar.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BuilderPlug.cs" />
<Compile Include="ColorChangedEventArgs.cs" />
<Compile Include="ColorHandler.cs" />
<Compile Include="ColorPickerType.cs" />
<Compile Include="ColorWheel.cs" />
<Compile Include="Controls\ColorPickerControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\ColorPickerControl.designer.cs">
<DependentUpon>ColorPickerControl.cs</DependentUpon>
</Compile>
<Compile Include="Controls\ColorPickerSlider.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\ColorPickerSlider.Designer.cs">
<DependentUpon>ColorPickerSlider.cs</DependentUpon>
</Compile>
<Compile Include="Controls\ColorPickerSliderEventArgs.cs" />
<Compile Include="IColorPicker.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Windows\LightColorPicker.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Windows\LightColorPicker.Designer.cs">
<DependentUpon>LightColorPicker.cs</DependentUpon>
</Compile>
<Compile Include="Windows\SectorColorPicker.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Windows\SectorColorPicker.Designer.cs">
<DependentUpon>SectorColorPicker.cs</DependentUpon>
</Compile>
<Compile Include="Windows\ToolForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Windows\ToolForm.Designer.cs">
<DependentUpon>ToolForm.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Controls\ColorPickerControl.resx">
<DependentUpon>ColorPickerControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Windows\LightColorPicker.resx">
<DependentUpon>LightColorPicker.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Windows\ToolForm.resx">
<DependentUpon>ToolForm.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Core\Builder.csproj">
<Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
<Name>Builder</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Controls\ColorPickerSlider.resx">
<DependentUpon>ColorPickerSlider.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Resources\Actions.cfg" />
<EmbeddedResource Include="Windows\SectorColorPicker.resx">
<DependentUpon>SectorColorPicker.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Resources\cp.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Binary file not shown.

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CodeImp.DoomBuilder.ColorPicker {
public enum ColorPickerType : int {
CP_LIGHT = 1,
CP_SECTOR = 2
}
}

View file

@ -0,0 +1,468 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace CodeImp.DoomBuilder.ColorPicker {
public class ColorWheel : IDisposable {
// These resources should be disposed
// of when you're done with them.
private Graphics g;
private Region colorRegion;
private Region brightnessRegion;
private Bitmap colorImage;
public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);
public ColorChangedEventHandler ColorChanged;
// Keep track of the current mouse state.
public enum MouseState {
MouseUp,
ClickOnColor,
DragInColor,
ClickOnBrightness,
DragInBrightness,
ClickOutsideRegion,
DragOutsideRegion,
}
private MouseState currentState = MouseState.MouseUp;
// The code needs to convert back and forth between
// degrees and radians. There are 2*PI radians in a
// full circle, and 360 degrees. This constant allows
// you to convert back and forth.
private const double DEGREES_PER_RADIAN = 180.0 / Math.PI;
// COLOR_COUNT represents the number of distinct colors
// used to create the circular gradient. Its value
// is somewhat arbitrary -- change this to 6, for
// example, to see what happens. 1536 (6 * 256) seems
// a good compromise -- it's enough to get a full
// range of colors, but it doesn't overwhelm the processor
// attempting to generate the image. The color wheel
// contains 6 sections, and each section displays
// 256 colors. Seems like a reasonable compromise.
private const int COLOR_COUNT = 6 * 256;
private Point centerPoint;
private int radius;
private Rectangle colorRectangle;
private Rectangle brightnessRectangle;
private int brightnessX;
private double brightnessScaling;
// selectedColor is the actual value selected by the user. fullColor is the same color,
// with its brightness set to 255.
private Color selectedColor = Color.White;
private Color fullColor;
private ColorHandler.RGB RGB;
private ColorHandler.HSV HSV;
// Locations for the two "pointers" on the form.
private Point colorPoint;
private Point brightnessPoint;
private int brightness;
private int brightnessMin;
private int brightnessMax;
public Color Color { get { return selectedColor; } }
public ColorWheel(Rectangle colorRectangle, Rectangle brightnessRectangle) {
// Caller must provide locations for color wheel
// (colorRectangle), brightness "strip" (brightnessRectangle)
// and location to display selected color (selectedColorRectangle).
using (GraphicsPath path = new GraphicsPath()) {
// Store away locations for later use.
this.colorRectangle = colorRectangle;
this.brightnessRectangle = brightnessRectangle;
//this.selectedColorRectangle = selectedColorRectangle;
// Calculate the center of the circle.
// Start with the location, then offset
// the point by the radius.
// Use the smaller of the width and height of
// the colorRectangle value.
this.radius = (int)Math.Min(colorRectangle.Width, colorRectangle.Height) / 2;
this.centerPoint = colorRectangle.Location;
this.centerPoint.Offset(radius, radius);
// Start the pointer in the center.
this.colorPoint = this.centerPoint;
// Create a region corresponding to the color circle.
// Code uses this later to determine if a specified
// point is within the region, using the IsVisible
// method.
path.AddEllipse(colorRectangle);
colorRegion = new Region(path);
// set { the range for the brightness selector.
this.brightnessMin = this.brightnessRectangle.Top;
this.brightnessMax = this.brightnessRectangle.Bottom;
// Create a region corresponding to the
// brightness rectangle, with a little extra
// "breathing room".
path.AddRectangle(new Rectangle(brightnessRectangle.Left, brightnessRectangle.Top - 10, brightnessRectangle.Width + 10, brightnessRectangle.Height + 20));
// Create region corresponding to brightness
// rectangle. Later code uses this to
// determine if a specified point is within
// the region, using the IsVisible method.
brightnessRegion = new Region(path);
// Set the location for the brightness indicator "marker".
// Also calculate the scaling factor, scaling the height
// to be between 0 and 255.
brightnessX = brightnessRectangle.Left + brightnessRectangle.Width;
brightnessScaling = (double)255 / (brightnessMax - brightnessMin);
// Calculate the location of the brightness
// pointer. Assume it's at the highest position.
brightnessPoint = new Point(brightnessX, brightnessMax);
// Create the bitmap that contains the circular gradient.
CreateGradient();
}
}
protected void OnColorChanged(ColorHandler.RGB RGB, ColorHandler.HSV HSV) {
ColorChangedEventArgs e = new ColorChangedEventArgs(RGB, HSV);
ColorChanged(this, e);
}
void IDisposable.Dispose() {
// Dispose of graphic resources
if (colorImage != null)
colorImage.Dispose();
if (colorRegion != null)
colorRegion.Dispose();
if (brightnessRegion != null)
brightnessRegion.Dispose();
if (g != null)
g.Dispose();
}
public void SetMouseUp() {
// Indicate that the user has
// released the mouse.
currentState = MouseState.MouseUp;
}
public void Draw(Graphics g, ColorHandler.RGB RGB) {
// Given RGB values, calculate HSV and then update the screen.
this.g = g;
this.HSV = ColorHandler.RGBtoHSV(RGB);
CalcCoordsAndUpdate(this.HSV);
UpdateDisplay();
}
public void Draw(Graphics g, Point mousePoint) {
// You've moved the mouse.
// Now update the screen to match.
double distance;
int degrees;
Point delta;
Point newColorPoint;
Point newBrightnessPoint;
Point newPoint;
// Keep track of the previous color pointer point,
// so you can put the mouse there in case the
// user has clicked outside the circle.
newColorPoint = colorPoint;
newBrightnessPoint = brightnessPoint;
// Store this away for later use.
this.g = g;
if (currentState == MouseState.MouseUp) {
if (!mousePoint.IsEmpty) {
if (colorRegion.IsVisible(mousePoint)) {
// Is the mouse point within the color circle?
// If so, you just clicked on the color wheel.
currentState = MouseState.ClickOnColor;
} else if (brightnessRegion.IsVisible(mousePoint)) {
// Is the mouse point within the brightness area?
// You clicked on the brightness area.
currentState = MouseState.ClickOnBrightness;
} else {
// Clicked outside the color and the brightness
// regions. In that case, just put the
// pointers back where they were.
currentState = MouseState.ClickOutsideRegion;
}
}
}
switch (currentState) {
case MouseState.ClickOnBrightness:
case MouseState.DragInBrightness:
// Calculate new color information
// based on the brightness, which may have changed.
newPoint = mousePoint;
if (newPoint.Y < brightnessMin) {
newPoint.Y = brightnessMin;
} else if (newPoint.Y > brightnessMax) {
newPoint.Y = brightnessMax;
}
newBrightnessPoint = new Point(brightnessX, newPoint.Y);
brightness = (int)((brightnessMax - newPoint.Y) * brightnessScaling);
HSV.value = brightness;
RGB = ColorHandler.HSVtoRGB(HSV);
break;
case MouseState.ClickOnColor:
case MouseState.DragInColor:
// Calculate new color information
// based on selected color, which may have changed.
newColorPoint = mousePoint;
// Calculate x and y distance from the center,
// and then calculate the angle corresponding to the
// new location.
delta = new Point(
mousePoint.X - centerPoint.X, mousePoint.Y - centerPoint.Y);
degrees = CalcDegrees(delta);
// Calculate distance from the center to the new point
// as a fraction of the radius. Use your old friend,
// the Pythagorean theorem, to calculate this value.
distance = Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y) / radius;
if (currentState == MouseState.DragInColor) {
if (distance > 1) {
// Mouse is down, and outside the circle, but you
// were previously dragging in the color circle.
// What to do?
// In that case, move the point to the edge of the
// circle at the correct angle.
distance = 1;
newColorPoint = GetPoint(degrees, radius, centerPoint);
}
}
// Calculate the new HSV and RGB values.
HSV.Hue = (int)(degrees * 255 / 360);
HSV.Saturation = (int)(distance * 255);
HSV.value = brightness;
RGB = ColorHandler.HSVtoRGB(HSV);
fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
break;
}
selectedColor = ColorHandler.HSVtoColor(HSV);
// Raise an event back to the parent form,
// so the form can update any UI it's using
// to display selected color values.
OnColorChanged(RGB, HSV);
// On the way out, set the new state.
switch (currentState) {
case MouseState.ClickOnBrightness:
currentState = MouseState.DragInBrightness;
break;
case MouseState.ClickOnColor:
currentState = MouseState.DragInColor;
break;
case MouseState.ClickOutsideRegion:
currentState = MouseState.DragOutsideRegion;
break;
}
// Store away the current points for next time.
colorPoint = newColorPoint;
brightnessPoint = newBrightnessPoint;
// Draw the gradients and points.
UpdateDisplay();
}
private Point CalcBrightnessPoint(int brightness) {
// Take the value for brightness (0 to 255), scale to the
// scaling used in the brightness bar, then add the value
// to the bottom of the bar. return the correct point at which
// to display the brightness pointer.
return new Point(brightnessX, (int)(brightnessMax - brightness / brightnessScaling));
}
/*public void SetColor(Color c) {
fullColor = c;
UpdateDisplay();
}*/
private void UpdateDisplay() {
// Update the gradients, and place the pointers correctly based on colors and
// brightness.
CreateGradient();
using (Brush selectedBrush = new SolidBrush(selectedColor)) {
// Draw the saved color wheel image.
g.DrawImage(colorImage, colorRectangle);
// Draw the "brightness" rectangle.
DrawLinearGradient(fullColor);
// Draw the two pointers.
DrawColorPointer(colorPoint);
DrawBrightnessPointer(brightnessPoint);
}
}
private void CalcCoordsAndUpdate(ColorHandler.HSV HSV) {
// Convert color to real-world coordinates and then calculate
// the various points. HSV.Hue represents the degrees (0 to 360),
// HSV.Saturation represents the radius.
// This procedure doesn't draw anything--it simply
// updates class-level variables. The UpdateDisplay
// procedure uses these values to update the screen.
// Given the angle (HSV.Hue), and distance from
// the center (HSV.Saturation), and the center,
// calculate the point corresponding to
// the selected color, on the color wheel.
colorPoint = GetPoint((double)HSV.Hue / 255 * 360,
(double)HSV.Saturation / 255 * radius,
centerPoint);
// Given the brightness (HSV.value), calculate the
// point corresponding to the brightness indicator.
brightnessPoint = CalcBrightnessPoint(HSV.value);
// Store information about the selected color.
brightness = HSV.value;
selectedColor = ColorHandler.HSVtoColor(HSV);
RGB = ColorHandler.HSVtoRGB(HSV);
// The full color is the same as HSV, except that the
// brightness is set to full (255). This is the top-most
// color in the brightness gradient.
fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 255);
}
private void DrawLinearGradient(Color TopColor) {
// Given the top color, draw a linear gradient
// ranging from black to the top color. Use the
// brightness rectangle as the area to fill.
using (LinearGradientBrush lgb =
new LinearGradientBrush(brightnessRectangle, TopColor,
Color.Black, LinearGradientMode.Vertical)) {
g.FillRectangle(lgb, brightnessRectangle);
}
}
private int CalcDegrees(Point pt) {
int degrees;
if (pt.X == 0) {
// The point is on the y-axis. Determine whether it's above or below the x-axis, and return the
// corresponding angle. Note that the orientation of the y-coordinate is backwards. That is,
// A positive Y value indicates a point BELOW the x-axis.
if (pt.Y > 0) {
degrees = 270;
} else {
degrees = 90;
}
} else {
// This value needs to be multiplied by -1 because the y-coordinate
// is opposite from the normal direction here.
// That is, a y-coordinate that's "higher" on the form has a lower y-value, in this coordinate
// system. So everything's off by a factor of -1 when performing the ratio calculations.
degrees = (int)(-Math.Atan((double)pt.Y / pt.X) * DEGREES_PER_RADIAN);
// If the x-coordinate of the selected point is to the left of the center of the circle, you
// need to add 180 degrees to the angle. ArcTan only gives you a value on the right-hand side
// of the circle.
if (pt.X < 0) {
degrees += 180;
}
// Ensure that the return value is between 0 and 360.
degrees = (degrees + 360) % 360;
}
return degrees;
}
private void CreateGradient() {
// Create a new PathGradientBrush, supplying an array of points created by calling
// the GetPoints method.
using (PathGradientBrush pgb =
new PathGradientBrush(GetPoints(radius, new Point(radius, radius)))) {
// Set the various properties. Note the SurroundColors property, which contains an array of points,
// in a one-to-one relationship with the points that created the gradient.
pgb.CenterColor = Color.White;
pgb.CenterPoint = new PointF(radius, radius);
pgb.SurroundColors = GetColors();
// Create a new bitmap containing the color wheel gradient, so the
// code only needs to do all this work once. Later code uses the bitmap
// rather than recreating the gradient.
colorImage = new Bitmap(
colorRectangle.Width, colorRectangle.Height,
PixelFormat.Format32bppArgb);
using (Graphics newGraphics =
Graphics.FromImage(colorImage)) {
newGraphics.FillEllipse(pgb, 0, 0,
colorRectangle.Width, colorRectangle.Height);
}
}
}
private Color[] GetColors() {
// Create an array of COLOR_COUNT colors, looping through all the hues between 0 and 255, broken
// into COLOR_COUNT intervals. HSV is particularly well-suited for this, because the only value
// that changes as you create colors is the Hue.
Color[] Colors = new Color[COLOR_COUNT];
for (int i = 0; i < COLOR_COUNT; i++)
Colors[i] = ColorHandler.HSVtoColor((int)((double)(i * 255) / COLOR_COUNT), 255, HSV.value);
return Colors;
}
private Point[] GetPoints(double radius, Point centerPoint) {
// Generate the array of points that describe the locations of the COLOR_COUNT colors to be
// displayed on the color wheel.
Point[] Points = new Point[COLOR_COUNT];
for (int i = 0; i < COLOR_COUNT; i++)
Points[i] = GetPoint((double)(i * 360) / COLOR_COUNT, radius, centerPoint);
return Points;
}
private Point GetPoint(double degrees, double radius, Point centerPoint) {
// Given the center of a circle and its radius, along
// with the angle corresponding to the point, find the coordinates.
// In other words, conver t from polar to rectangular coordinates.
double radians = degrees / DEGREES_PER_RADIAN;
return new Point((int)(centerPoint.X + Math.Floor(radius * Math.Cos(radians))),
(int)(centerPoint.Y - Math.Floor(radius * Math.Sin(radians))));
}
private void DrawColorPointer(Point pt) {
// Given a point, draw the color selector. The constant SIZE represents half
// the width -- the square will be twice this value in width and height.
const int SIZE = 3;
g.DrawRectangle(Pens.Black,
pt.X - SIZE, pt.Y - SIZE, SIZE * 2, SIZE * 2);
}
private void DrawBrightnessPointer(Point pt) {
// Draw a triangle for the brightness indicator that "points" at the provided point.
const int HEIGHT = 10;
const int WIDTH = 7;
Point[] Points = new Point[3];
Points[0] = pt;
Points[1] = new Point(pt.X + WIDTH, pt.Y + HEIGHT / 2);
Points[2] = new Point(pt.X + WIDTH, pt.Y - HEIGHT / 2);
g.FillPolygon(Brushes.Black, Points);
}
}
}

View file

@ -0,0 +1,191 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace CodeImp.DoomBuilder.ColorPicker.Controls {
public partial class ColorPickerControl : UserControl {
private enum ChangeStyle {
MouseMove,
RGB,
None
}
private ChangeStyle changeType = ChangeStyle.None;
private Point selectedPoint;
private ColorWheel colorWheel;
private ColorHandler.RGB RGB;
public ColorHandler.RGB CurrentColor {
get
{
//GZBuilder.GZGeneral.Trace("get CurrentColor: " + RGB.Red + "," + RGB.Green + "," + RGB.Blue);
return RGB;
}
}
private bool isInUpdate = false;
private Color startColor;
//events
public event EventHandler<ColorChangedEventArgs> ColorChanged;
public event EventHandler OnOkPressed;
public event EventHandler OnCancelPressed;
public Button OkButton { get { return btnOK; } }
public Button CancelButton { get { return btnCancel; } }
public void Initialize(Color startColor){
this.startColor = startColor;
InitializeComponent();
}
private void nudValueChanged(object sender, System.EventArgs e) {
// If the R, G, or B values change, use this code to update the HSV values and invalidate
// the color wheel (so it updates the pointers).
// Check the isInUpdate flag to avoid recursive events when you update the NumericUpdownControls.
if (!isInUpdate) {
changeType = ChangeStyle.RGB;
RGB = new ColorHandler.RGB((int)nudRed.Value, (int)nudGreen.Value, (int)nudBlue.Value);
updateOKButton(RGB);
this.Invalidate();
}
}
private void setRGB(ColorHandler.RGB RGB) {
// Update the RGB values on the form, but don't trigger the ValueChanged event of the form. The isInUpdate
// variable ensures that the event procedures exit without doing anything.
isInUpdate = true;
refreshNudValue(nudRed, RGB.Red);
refreshNudValue(nudBlue, RGB.Blue);
refreshNudValue(nudGreen, RGB.Green);
updateOKButton(RGB);
isInUpdate = false;
}
private void updateOKButton(ColorHandler.RGB RGB) {
this.RGB = RGB;
btnOK.BackColor = ColorHandler.RGBtoColor(RGB);
btnOK.ForeColor = (RGB.Red < 180 && RGB.Green < 180) ? Color.White : Color.Black;
//dispatch event further
EventHandler<ColorChangedEventArgs> handler = ColorChanged;
if (handler != null)
handler(this, new ColorChangedEventArgs(RGB, ColorHandler.RGBtoHSV(RGB)));
}
private void updateCancelButton(ColorHandler.RGB RGB) {
btnCancel.BackColor = ColorHandler.RGBtoColor(RGB);
btnCancel.ForeColor = (RGB.Red < 180 && RGB.Green < 180) ? Color.White : Color.Black;
}
private void refreshNudValue(NumericUpDown nud, int value) {
// Update the value of the NumericUpDown control, if the value is different than the current value.
// Refresh the control, causing an immediate repaint.
if (nud.Value != value) {
nud.Value = value;
nud.Refresh();
}
}
public void SetCurrentColor(Color c) {
isInUpdate = true;
changeType = ChangeStyle.RGB;
RGB = new ColorHandler.RGB(c.R, c.G, c.B);
refreshNudValue(nudRed, RGB.Red);
refreshNudValue(nudBlue, RGB.Blue);
refreshNudValue(nudGreen, RGB.Green);
updateOKButton(RGB);
isInUpdate = false;
this.Invalidate();
}
public void SetInitialColor(Color c) {
updateCancelButton(new ColorHandler.RGB(c.R, c.G, c.B));
}
//events
private void ColorPickerControl_Load(object sender, EventArgs e) {
// Turn on double-buffering, so the form looks better.
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
Rectangle BrightnessRectangle = new Rectangle(pnlBrightness.Location, pnlBrightness.Size);
Rectangle ColorRectangle = new Rectangle(pnlColor.Location, pnlColor.Size);
// Create the new ColorWheel class, indicating the locations of the color wheel itself, the
// brightness area, and the position of the selected color.
colorWheel = new ColorWheel(ColorRectangle, BrightnessRectangle);
colorWheel.ColorChanged += new ColorWheel.ColorChangedEventHandler(this.colorChanged);
//set initial colors
SetCurrentColor(startColor);
updateCancelButton(RGB);
}
private void ColorPickerControl_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
changeType = ChangeStyle.MouseMove;
selectedPoint = new Point(e.X, e.Y);
this.Invalidate();
}
}
private void colorChanged(object sender, ColorChangedEventArgs e) {
setRGB(e.RGB);
}
private void onPaint(object sender, System.Windows.Forms.PaintEventArgs e) {
// Depending on the circumstances, force a repaint
// of the color wheel passing different information.
switch (changeType) {
case ChangeStyle.MouseMove:
case ChangeStyle.None:
colorWheel.Draw(e.Graphics, selectedPoint);
break;
case ChangeStyle.RGB:
colorWheel.Draw(e.Graphics, RGB);
break;
}
}
private void handleMouse(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
changeType = ChangeStyle.MouseMove;
selectedPoint = new Point(e.X, e.Y);
this.Invalidate();
}
}
private void onMouseUp(object sender, MouseEventArgs e) {
colorWheel.SetMouseUp();
changeType = ChangeStyle.None;
}
private void onMouseUp(object sender, EventArgs e) {
colorWheel.SetMouseUp();
changeType = ChangeStyle.None;
}
private void btnOK_Click(object sender, EventArgs e) {
//dispatch event further
EventHandler handler = OnOkPressed;
if (handler != null)
handler(this, e);
}
private void btnCancel_Click(object sender, EventArgs e) {
//dispatch event further
EventHandler handler = OnCancelPressed;
if (handler != null)
handler(this, e);
}
}
}

View file

@ -0,0 +1,198 @@
namespace CodeImp.DoomBuilder.ColorPicker.Controls {
partial class ColorPickerControl {
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.btnCancel = new System.Windows.Forms.Button();
this.btnOK = new System.Windows.Forms.Button();
this.Label3 = new System.Windows.Forms.Label();
this.nudRed = new System.Windows.Forms.NumericUpDown();
this.pnlColor = new System.Windows.Forms.Panel();
this.Label1 = new System.Windows.Forms.Label();
this.pnlBrightness = new System.Windows.Forms.Panel();
this.nudBlue = new System.Windows.Forms.NumericUpDown();
this.nudGreen = new System.Windows.Forms.NumericUpDown();
this.Label2 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.nudRed)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudBlue)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudGreen)).BeginInit();
this.SuspendLayout();
//
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.btnCancel.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnCancel.Location = new System.Drawing.Point(214, 44);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(94, 42);
this.btnCancel.TabIndex = 54;
this.btnCancel.Text = "Cancel";
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// btnOK
//
this.btnOK.BackColor = System.Drawing.SystemColors.Control;
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.btnOK.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnOK.ForeColor = System.Drawing.SystemColors.ControlText;
this.btnOK.Location = new System.Drawing.Point(214, 3);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(94, 42);
this.btnOK.TabIndex = 53;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
//
// Label3
//
this.Label3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label3.Location = new System.Drawing.Point(214, 147);
this.Label3.Name = "Label3";
this.Label3.Size = new System.Drawing.Size(40, 23);
this.Label3.TabIndex = 60;
this.Label3.Text = "Blue:";
this.Label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// nudRed
//
this.nudRed.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudRed.Location = new System.Drawing.Point(260, 101);
this.nudRed.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudRed.Name = "nudRed";
this.nudRed.Size = new System.Drawing.Size(48, 20);
this.nudRed.TabIndex = 55;
this.nudRed.ValueChanged += new System.EventHandler(this.nudValueChanged);
//
// pnlColor
//
this.pnlColor.Location = new System.Drawing.Point(3, 3);
this.pnlColor.Name = "pnlColor";
this.pnlColor.Size = new System.Drawing.Size(176, 176);
this.pnlColor.TabIndex = 61;
this.pnlColor.Visible = false;
//
// Label1
//
this.Label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label1.Location = new System.Drawing.Point(214, 99);
this.Label1.Name = "Label1";
this.Label1.Size = new System.Drawing.Size(40, 23);
this.Label1.TabIndex = 58;
this.Label1.Text = "Red:";
this.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// pnlBrightness
//
this.pnlBrightness.Location = new System.Drawing.Point(185, 3);
this.pnlBrightness.Name = "pnlBrightness";
this.pnlBrightness.Size = new System.Drawing.Size(16, 176);
this.pnlBrightness.TabIndex = 62;
this.pnlBrightness.Visible = false;
//
// nudBlue
//
this.nudBlue.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudBlue.Location = new System.Drawing.Point(260, 149);
this.nudBlue.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudBlue.Name = "nudBlue";
this.nudBlue.Size = new System.Drawing.Size(48, 20);
this.nudBlue.TabIndex = 57;
this.nudBlue.ValueChanged += new System.EventHandler(this.nudValueChanged);
//
// nudGreen
//
this.nudGreen.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudGreen.Location = new System.Drawing.Point(260, 125);
this.nudGreen.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.nudGreen.Name = "nudGreen";
this.nudGreen.Size = new System.Drawing.Size(48, 20);
this.nudGreen.TabIndex = 56;
this.nudGreen.ValueChanged += new System.EventHandler(this.nudValueChanged);
//
// Label2
//
this.Label2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label2.Location = new System.Drawing.Point(214, 123);
this.Label2.Name = "Label2";
this.Label2.Size = new System.Drawing.Size(40, 23);
this.Label2.TabIndex = 59;
this.Label2.Text = "Green:";
this.Label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// ColorPickerControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.Label3);
this.Controls.Add(this.nudRed);
this.Controls.Add(this.pnlColor);
this.Controls.Add(this.Label1);
this.Controls.Add(this.pnlBrightness);
this.Controls.Add(this.nudBlue);
this.Controls.Add(this.nudGreen);
this.Controls.Add(this.Label2);
this.Name = "ColorPickerControl";
this.Size = new System.Drawing.Size(311, 183);
this.Load += new System.EventHandler(this.ColorPickerControl_Load);
this.MouseLeave += new System.EventHandler(this.onMouseUp);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.onPaint);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.handleMouse);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ColorPickerControl_MouseDown);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.onMouseUp);
((System.ComponentModel.ISupportInitialize)(this.nudRed)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudBlue)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudGreen)).EndInit();
this.ResumeLayout(false);
}
#endregion
internal System.Windows.Forms.Button btnCancel;
internal System.Windows.Forms.Button btnOK;
internal System.Windows.Forms.Label Label3;
internal System.Windows.Forms.NumericUpDown nudRed;
internal System.Windows.Forms.Panel pnlColor;
internal System.Windows.Forms.Label Label1;
internal System.Windows.Forms.Panel pnlBrightness;
internal System.Windows.Forms.NumericUpDown nudBlue;
internal System.Windows.Forms.NumericUpDown nudGreen;
internal System.Windows.Forms.Label Label2;
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,109 @@
namespace CodeImp.DoomBuilder.ColorPicker.Controls {
partial class ColorPickerSlider {
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.trackBar1 = new Dotnetrix.Controls.TrackBar();
this.label1 = new System.Windows.Forms.Label();
this.labelMin = new System.Windows.Forms.Label();
this.labelMax = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
this.SuspendLayout();
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(263, 16);
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(44, 20);
this.numericUpDown1.TabIndex = 5;
this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
//
// trackBar1
//
this.trackBar1.LargeChange = 32;
this.trackBar1.Location = new System.Drawing.Point(115, 7);
this.trackBar1.Maximum = 512;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(142, 45);
this.trackBar1.SmallChange = 4;
this.trackBar1.TabIndex = 4;
this.trackBar1.TickFrequency = 16;
this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.Both;
this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
//
// label1
//
this.label1.Location = new System.Drawing.Point(3, 15);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(106, 14);
this.label1.TabIndex = 3;
this.label1.Text = "Secondary intensity:";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// labelMin
//
this.labelMin.Location = new System.Drawing.Point(111, -1);
this.labelMin.Name = "labelMin";
this.labelMin.Size = new System.Drawing.Size(36, 15);
this.labelMin.TabIndex = 6;
this.labelMin.Text = "0";
this.labelMin.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// labelMax
//
this.labelMax.Location = new System.Drawing.Point(231, -1);
this.labelMax.Name = "labelMax";
this.labelMax.Size = new System.Drawing.Size(36, 15);
this.labelMax.TabIndex = 7;
this.labelMax.Text = "512";
this.labelMax.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ColorPickerSlider
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.labelMax);
this.Controls.Add(this.labelMin);
this.Controls.Add(this.numericUpDown1);
this.Controls.Add(this.trackBar1);
this.Controls.Add(this.label1);
this.Name = "ColorPickerSlider";
this.Size = new System.Drawing.Size(311, 45);
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.NumericUpDown numericUpDown1;
private Dotnetrix.Controls.TrackBar trackBar1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label labelMin;
private System.Windows.Forms.Label labelMax;
}
}

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CodeImp.DoomBuilder.ColorPicker.Controls {
public partial class ColorPickerSlider : UserControl {
private bool blockEvents;
public event EventHandler<ColorPickerSliderEventArgs> OnValueChanged;
public int Value {
get
{
return (int)numericUpDown1.Value;
}
set
{
blockEvents = true;
numericUpDown1.Value = General.Clamp(value, (int)numericUpDown1.Minimum, (int)numericUpDown1.Maximum);
blockEvents = false;
}
}
private bool showLimits;
public bool ShowLimits {
get
{
return showLimits;
}
set
{
showLimits = value;
labelMin.Visible = showLimits;
labelMax.Visible = showLimits;
}
}
public string Label { set { label1.Text = value; } }
public ColorPickerSlider() {
InitializeComponent();
}
public void SetLimits(int tbMin, int tbMax, int nudMin, int nudMax) {
bool blockEventsStatus = blockEvents;
blockEvents = true;
trackBar1.Value = General.Clamp(trackBar1.Value, tbMin, tbMax);
trackBar1.Minimum = tbMin;
trackBar1.Maximum = tbMax;
labelMin.Text = tbMin.ToString();
labelMax.Text = tbMax.ToString();
numericUpDown1.Value = General.Clamp((int)numericUpDown1.Value, nudMin, nudMax);
numericUpDown1.Minimum = nudMin;
numericUpDown1.Maximum = nudMax;
blockEvents = blockEventsStatus;
}
//events
private void trackBar1_ValueChanged(object sender, EventArgs e) {
numericUpDown1.Value = ((TrackBar)sender).Value;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
bool blockEventsStatus = blockEvents;
int val = (int)((NumericUpDown)sender).Value;
if (!blockEventsStatus) {
EventHandler<ColorPickerSliderEventArgs> handler = OnValueChanged;
if (handler != null)
handler(this, new ColorPickerSliderEventArgs(val));
}
blockEvents = true;
trackBar1.Value = General.Clamp(val, trackBar1.Minimum, trackBar1.Maximum); //clamp it!
blockEvents = blockEventsStatus;
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,12 @@
using System;
namespace CodeImp.DoomBuilder.ColorPicker.Controls {
public class ColorPickerSliderEventArgs : EventArgs {
private int value;
public int Value { get { return value; } }
public ColorPickerSliderEventArgs(int value) {
this.value = value;
}
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace CodeImp.DoomBuilder.ColorPicker {
interface IColorPicker : IWin32Window {
Point Location { get; set; }
bool Visible { get; set; }
int Width { get; set; }
ColorPickerType Type { get; }
bool Setup(string editingModeName);
//void OnBeforeClose();
//void UpdateSelection();
//void UpdateSelection(string editingModeName);
DialogResult ShowDialog(IWin32Window w);
//void Show(IWin32Window w);
void Close();
void Dispose();
//void Activate();
event FormClosedEventHandler FormClosed;
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Управление общими сведениями о сборке осуществляется с помощью
// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
// связанные со сборкой.
[assembly: AssemblyTitle("ColorPicker")]
[assembly: AssemblyDescription("ColorPicker control for GZDoomBuilder")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ColorPicker")]
[assembly: AssemblyCopyright("Copyright © MaxED 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми
// для COM-компонентов. Если требуется обратиться к типу в этой сборке через
// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
[assembly: ComVisible(false)]
// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
[assembly: Guid("82178b31-4cd7-43e0-a25f-6a58de2fae4e")]
// Сведения о версии сборки состоят из следующих четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер построения
// Редакция
//
// Можно задать все значения или принять номер построения и номер редакции по умолчанию,
// используя "*", как показано ниже:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:2.0.50727.5420
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CodeImp.DoomBuilder.ColorPicker.Properties {
using System;
/// <summary>
/// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
/// </summary>
// Этот класс создан автоматически классом StronglyTypedResourceBuilder
// с помощью такого средства, как ResGen или Visual Studio.
// Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
// с параметром /str или перестройте свой проект VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.ColorPicker.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Перезаписывает свойство CurrentUICulture текущего потока для всех
/// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static System.Drawing.Bitmap cp {
get {
object obj = ResourceManager.GetObject("cp", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="cp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\cp.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -0,0 +1,10 @@
togglelightpannel
{
title = "Toggle color picker";
category = "tools";
description = "Select dynamic light thing(s) or sectors, then use this pannel to set light properties quickly.";
allowkeys = true;
allowmouse = true;
allowscroll = false;
default = 75; //K
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

View file

@ -0,0 +1,106 @@
namespace CodeImp.DoomBuilder.ColorPicker.Windows {
partial class LightColorPicker {
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.colorPickerControl1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl();
this.cbRelativeMode = new System.Windows.Forms.CheckBox();
this.colorPickerSlider1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
this.colorPickerSlider2 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
this.colorPickerSlider3 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider();
this.SuspendLayout();
//
// colorPickerControl1
//
this.colorPickerControl1.Location = new System.Drawing.Point(8, 8);
this.colorPickerControl1.Name = "colorPickerControl1";
this.colorPickerControl1.Size = new System.Drawing.Size(311, 183);
this.colorPickerControl1.TabIndex = 0;
//
// cbRelativeMode
//
this.cbRelativeMode.AutoSize = true;
this.cbRelativeMode.Location = new System.Drawing.Point(14, 209);
this.cbRelativeMode.Name = "cbRelativeMode";
this.cbRelativeMode.Size = new System.Drawing.Size(93, 18);
this.cbRelativeMode.TabIndex = 5;
this.cbRelativeMode.Text = "Relative Mode";
this.cbRelativeMode.UseVisualStyleBackColor = true;
//
// colorPickerSlider1
//
this.colorPickerSlider1.Location = new System.Drawing.Point(8, 233);
this.colorPickerSlider1.Name = "colorPickerSlider1";
this.colorPickerSlider1.ShowLimits = true;
this.colorPickerSlider1.Size = new System.Drawing.Size(311, 45);
this.colorPickerSlider1.TabIndex = 6;
//
// colorPickerSlider2
//
this.colorPickerSlider2.Location = new System.Drawing.Point(8, 284);
this.colorPickerSlider2.Name = "colorPickerSlider2";
this.colorPickerSlider2.ShowLimits = false;
this.colorPickerSlider2.Size = new System.Drawing.Size(311, 48);
this.colorPickerSlider2.TabIndex = 7;
//
// colorPickerSlider3
//
this.colorPickerSlider3.Location = new System.Drawing.Point(8, 338);
this.colorPickerSlider3.Name = "colorPickerSlider3";
this.colorPickerSlider3.ShowLimits = true;
this.colorPickerSlider3.Size = new System.Drawing.Size(311, 48);
this.colorPickerSlider3.TabIndex = 8;
//
// LightColorPicker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(327, 391);
this.Controls.Add(this.colorPickerSlider3);
this.Controls.Add(this.colorPickerSlider2);
this.Controls.Add(this.colorPickerSlider1);
this.Controls.Add(this.cbRelativeMode);
this.Controls.Add(this.colorPickerControl1);
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "LightColorPicker";
this.Opacity = 0;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "LightColorPicker";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl colorPickerControl1;
private System.Windows.Forms.CheckBox cbRelativeMode;
private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider1;
private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider2;
private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerSlider colorPickerSlider3;
}
}

View file

@ -0,0 +1,364 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Plugins;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.GZBuilder;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.ColorPicker.Controls;
namespace CodeImp.DoomBuilder.ColorPicker.Windows {
public partial class LightColorPicker : DelayedForm, IColorPicker {
public ColorPickerType Type { get { return ColorPickerType.CP_LIGHT; } }
private static bool RELATIVE_MODE = false;
private static int[] LIGHT_USES_ANGLE_VALUE = { 9801, 9802, 9804, 9811, 9812, 9814, 9821, 9822, 9824 };
private List<Thing> selection;
private List<VisualThing> visualSelection;
private List<LightProps> fixedValues; //this gets filled with radius / intencity values before RELATIVE_MODE is engaged
private string editingModeName;
private bool showAllControls;
private LightProps lightProps;
//maximum and minimum values for sliders for relative and absolute modes
//numericUpDown
private const int NUD_ABS_MIN = 0;
private const int NUD_ABS_MAX = 16384;
private const int NUD_REL_MIN = -16384;
private const int NUD_REL_MAX = 16384;
//trackBar
private const int TB_ABS_MIN = 0;
private const int TB_ABS_MAX = 512;
private const int TB_REL_MIN = -256;
private const int TB_REL_MAX = 256;
//trackBar controlling thing angle
private const int TB_ANGLE_ABS_MIN = 0;
private const int TB_ANGLE_ABS_MAX = 359;
private const int TB_ANGLE_REL_MIN = -180;
private const int TB_ANGLE_REL_MAX = 180;
//initialise pannel
public bool Setup(string editingModeName) {
this.editingModeName = editingModeName;
setupSelection();
int selCount = selection.Count;
if (selCount == 0) {
Plug.DisplayStatus(StatusType.Warning, "No lights found in selection!");
return false;
}
lightProps = new LightProps();
//initialise
InitializeComponent();
setupSliders(selection[0]);
updateLightPropsFromThing(selection[0]);
setControlsMode();
colorPickerControl1.Initialize(getThingColor(selection[0]));
colorPickerControl1.ColorChanged += new EventHandler<ColorChangedEventArgs>(colorPickerControl1_ColorChanged);
colorPickerControl1.OnOkPressed += new EventHandler(colorPickerControl1_OnOkPressed);
colorPickerControl1.OnCancelPressed += new EventHandler(colorPickerControl1_OnCancelPressed);
cbRelativeMode.Checked = RELATIVE_MODE;
cbRelativeMode.CheckStateChanged += new EventHandler(cbRelativeMode_CheckStateChanged);
this.AcceptButton = colorPickerControl1.OkButton;
this.CancelButton = colorPickerControl1.CancelButton;
this.Text = "Editing " + selCount + " light" + (selCount > 1 ? "s" : "");
//undo
makeUndo(this.Text);
return true;
}
//create selection of lights. This is called only once
private void setupSelection() {
selection = new List<Thing>();
//check things
if (editingModeName == "BaseVisualMode") {
visualSelection = new List<VisualThing>();
List<VisualThing> selectedVisualThings = ((VisualMode)General.Editing.Mode).SelectedVisualThings;
foreach (VisualThing t in selectedVisualThings) {
if (Array.IndexOf(GZGeneral.GZ_LIGHTS, t.Thing.Type) != -1) {
selection.Add(t.Thing);
visualSelection.Add(t);
}
}
} else {
ICollection<Thing> list = General.Map.Map.GetSelectedThings(true);
foreach (Thing t in list) {
if (Array.IndexOf(GZGeneral.GZ_LIGHTS, t.Type) != -1)
selection.Add(t);
}
}
}
//set sliders count and labels based on given thing, set lightProps start values
//this is called only once
private void setupSliders(Thing referenceThing) {
ThingTypeInfo typeInfo = General.Map.Data.GetThingInfoEx(referenceThing.Type);
int firstArg = 3;
if (referenceThing.Type == 1502 || referenceThing.Type == 1503)
firstArg = 0;
//first slider is always used
colorPickerSlider1.Label = typeInfo.Args[firstArg].Title + ":";
colorPickerSlider1.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
//either both of them or none are used
if (Array.IndexOf(LIGHT_USES_ANGLE_VALUE, referenceThing.Type) != -1) {
showAllControls = true;
colorPickerSlider2.Label = typeInfo.Args[4].Title + ":";
colorPickerSlider2.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
colorPickerSlider3.Label = "Interval:";
colorPickerSlider3.OnValueChanged += new EventHandler<ColorPickerSliderEventArgs>(onSliderValueChanged);
} else {
colorPickerSlider2.Visible = false;
colorPickerSlider3.Visible = false;
}
//set window height
int newHeight = 0;
if (showAllControls) {
newHeight = colorPickerSlider3.Location.Y + colorPickerSlider3.Height + 8;
} else {
newHeight = colorPickerSlider1.Location.Y + colorPickerSlider1.Height + 8;
}
this.ClientSize = new Size(this.ClientSize.Width, newHeight);
}
//this sets lightProps values from given thing
private void updateLightPropsFromThing(Thing referenceThing) {
//color
Color c = getThingColor(referenceThing);
lightProps.Red = c.R;
lightProps.Green = c.G;
lightProps.Blue = c.B;
//size
int firstArg = 3;
if (referenceThing.Type == 1502 || referenceThing.Type == 1503)
firstArg = 0;
lightProps.PrimaryRadius = referenceThing.Args[firstArg];
//either both of them or none are used
if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, referenceThing.Type) != -1) {
lightProps.SecondaryRadius = referenceThing.Args[4];
lightProps.Interval = referenceThing.AngleDoom;
}
}
//this sets lightProps values from sliders
private void updateLightPropsFromSliders() {
ColorHandler.RGB curColor = colorPickerControl1.CurrentColor;
bool colorChanged = false; //need this check to allow relative mode to work properly
if ((byte)curColor.Red != lightProps.Red || (byte)curColor.Green != lightProps.Green || (byte)curColor.Blue != lightProps.Blue) {
lightProps.Red = (byte)curColor.Red;
lightProps.Green = (byte)curColor.Green;
lightProps.Blue = (byte)curColor.Blue;
colorChanged = true;
}
lightProps.PrimaryRadius = colorPickerSlider1.Value;
if (showAllControls) {
lightProps.SecondaryRadius = colorPickerSlider2.Value;
lightProps.Interval = colorPickerSlider3.Value;
}
updateSelection(colorChanged);
}
//this sets values from lightProps to things in selection
private void updateSelection(bool colorChanged) {
for (int i = 0; i < selection.Count; i++) {
Thing t = selection[i];
//update color
if (colorChanged) { //need this check to allow relative mode to work properly
if (t.Type == 1503) { //Vavoom Light Color
t.Args[1] = lightProps.Red;
t.Args[2] = lightProps.Green;
t.Args[3] = lightProps.Blue;
} else if (t.Type != 1502) { //vavoom light has no color settings
t.Args[0] = lightProps.Red;
t.Args[1] = lightProps.Green;
t.Args[2] = lightProps.Blue;
}
}
int firstArg = 3;
if (t.Type == 1502 || t.Type == 1503)
firstArg = 0;
//update radius and intensity
if (RELATIVE_MODE) {
LightProps fixedVal = fixedValues[i];
t.Args[firstArg] = fixedVal.PrimaryRadius + lightProps.PrimaryRadius;
if (t.Args[firstArg] < 0) t.Args[firstArg] = 0;
if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
t.Args[4] = fixedVal.SecondaryRadius + lightProps.SecondaryRadius;
if (t.Args[4] < 0) t.Args[4] = 0;
t.Rotate(General.ClampAngle(fixedVal.Interval + lightProps.Interval));
}
} else {
if (lightProps.PrimaryRadius != -1)
t.Args[firstArg] = lightProps.PrimaryRadius;
if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
t.Args[4] = lightProps.SecondaryRadius;
t.Rotate(General.ClampAngle(lightProps.Interval));
}
}
}
//update VisualThings
if (editingModeName == "BaseVisualMode") {
foreach (VisualThing t in visualSelection)
t.UpdateLight();
}
}
//switch between absolute and relative mode
private void setControlsMode() {
if (RELATIVE_MODE) {
setFixedValues();
colorPickerSlider1.SetLimits(TB_REL_MIN, TB_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
colorPickerSlider1.Value = 0;
if (showAllControls) {
colorPickerSlider2.SetLimits(TB_REL_MIN, TB_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
colorPickerSlider2.Value = 0;
colorPickerSlider3.SetLimits(TB_ANGLE_REL_MIN, TB_ANGLE_REL_MAX, NUD_REL_MIN, NUD_REL_MAX);
colorPickerSlider3.Value = 0;
}
} else {
updateLightPropsFromThing(selection[0]);
colorPickerSlider1.SetLimits(TB_ABS_MIN, TB_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
colorPickerSlider1.Value = lightProps.PrimaryRadius;
if (showAllControls) {
colorPickerSlider2.SetLimits(TB_ABS_MIN, TB_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
colorPickerSlider2.Value = lightProps.SecondaryRadius;
colorPickerSlider3.SetLimits(TB_ANGLE_ABS_MIN, TB_ANGLE_ABS_MAX, NUD_ABS_MIN, NUD_ABS_MAX);
colorPickerSlider3.Value = lightProps.Interval;
}
}
}
private void makeUndo(string description) {
General.Map.UndoRedo.CreateUndo(description);
//tricky way to actually store undo information...
foreach (Thing t in selection)
t.Move(t.Position);
}
//this is called only once
private Color getThingColor(Thing thing) {
if (thing.Type == 1502) { //vavoom light
return Color.White;
} else if (thing.Type == 1503) { //vavoom colored light
return Color.FromArgb((byte)thing.Args[1], (byte)thing.Args[2], (byte)thing.Args[3]);
}
return Color.FromArgb((byte)thing.Args[0], (byte)thing.Args[1], (byte)thing.Args[2]); ;
}
//this sets data to use as a reference for relative mode
private void setFixedValues() {
fixedValues = new List<LightProps>();
for (int i = 0; i < selection.Count; i++) {
Thing t = selection[i];
//ThingTypeInfo typeInfo = General.Map.Data.GetThingInfoEx(t.Type);
LightProps lp = new LightProps();
int firstArg = 3;
if (t.Type == 1502 || t.Type == 1503)
firstArg = 0;
//if(typeInfo.Args[firstArg].Used)
lp.PrimaryRadius = t.Args[firstArg];
//if(typeInfo.Args[4].Used)
//lp.SecondaryRadius = t.Args[4];
//either both of them or none are used
if (showAllControls && Array.IndexOf(LIGHT_USES_ANGLE_VALUE, t.Type) != -1) {
lp.SecondaryRadius = t.Args[4];
lp.Interval = t.AngleDoom;
}
fixedValues.Add(lp);
}
}
//events
private void colorPickerControl1_ColorChanged(object sender, ColorChangedEventArgs e) {
//need this check to allow relative mode to work properly
if ((byte)e.RGB.Red != lightProps.Red || (byte)e.RGB.Green != lightProps.Green || (byte)e.RGB.Blue != lightProps.Blue) {
updateLightPropsFromSliders();
}
}
private void colorPickerControl1_OnCancelPressed(object sender, EventArgs e) {
//undo changes
General.Map.UndoRedo.PerformUndo();
Close();
}
private void colorPickerControl1_OnOkPressed(object sender, EventArgs e) {
Close();
}
private void cbRelativeMode_CheckStateChanged(object sender, EventArgs e) {
RELATIVE_MODE = ((CheckBox)sender).Checked;
setControlsMode();
}
private void onSliderValueChanged(object sender, ColorPickerSliderEventArgs e) {
updateLightPropsFromSliders();
}
}
struct LightProps {
public byte Red;
public byte Green;
public byte Blue;
public int PrimaryRadius;
public int SecondaryRadius;
public int Interval;
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,104 @@
namespace CodeImp.DoomBuilder.ColorPicker.Windows
{
partial class SectorColorPicker
{
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.rbFadeColor = new System.Windows.Forms.RadioButton();
this.rbSectorColor = new System.Windows.Forms.RadioButton();
this.colorPickerControl1 = new CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.rbFadeColor);
this.groupBox1.Controls.Add(this.rbSectorColor);
this.groupBox1.Location = new System.Drawing.Point(8, 212);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(311, 62);
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Edit:";
//
// rbFadeColor
//
this.rbFadeColor.AutoSize = true;
this.rbFadeColor.Location = new System.Drawing.Point(7, 41);
this.rbFadeColor.Name = "rbFadeColor";
this.rbFadeColor.Size = new System.Drawing.Size(76, 18);
this.rbFadeColor.TabIndex = 1;
this.rbFadeColor.Tag = "fadecolor";
this.rbFadeColor.Text = "Fade color";
this.rbFadeColor.UseVisualStyleBackColor = true;
//
// rbSectorColor
//
this.rbSectorColor.AutoSize = true;
this.rbSectorColor.Checked = true;
this.rbSectorColor.Location = new System.Drawing.Point(7, 20);
this.rbSectorColor.Name = "rbSectorColor";
this.rbSectorColor.Size = new System.Drawing.Size(84, 18);
this.rbSectorColor.TabIndex = 0;
this.rbSectorColor.TabStop = true;
this.rbSectorColor.Tag = "lightcolor";
this.rbSectorColor.Text = "Sector color";
this.rbSectorColor.UseVisualStyleBackColor = true;
//
// colorPickerControl1
//
this.colorPickerControl1.Location = new System.Drawing.Point(8, 9);
this.colorPickerControl1.Name = "colorPickerControl1";
this.colorPickerControl1.Size = new System.Drawing.Size(311, 197);
this.colorPickerControl1.TabIndex = 1;
//
// SectorColorPicker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(327, 278);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.colorPickerControl1);
this.DoubleBuffered = true;
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "SectorColorPicker";
this.Opacity = 0;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "SectorColorPicker";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private CodeImp.DoomBuilder.ColorPicker.Controls.ColorPickerControl colorPickerControl1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.RadioButton rbFadeColor;
private System.Windows.Forms.RadioButton rbSectorColor;
}
}

View file

@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Plugins;
namespace CodeImp.DoomBuilder.ColorPicker.Windows
{
public partial class SectorColorPicker : DelayedForm, IColorPicker
{
public ColorPickerType Type { get { return ColorPickerType.CP_SECTOR; } }
private List<Sector> selection;
private int curSectorColor;
private int curFadeColor;
private int initialSectorColor;
private int initialFadeColor;
private int defaultSectorColor;
private int defaultFadeColor;
private static string currentColorTag = "lightcolor"; //lightcolor or fadecolor
private string mode;
public bool Setup(string editingModeName) {
mode = editingModeName;
selection = (List<Sector>)(General.Map.Map.GetSelectedSectors(true));
//create undo
string rest = selection.Count + " sector" + (selection.Count > 1 ? "s" : "");
General.Map.UndoRedo.CreateUndo("Edit color of " + rest);
foreach (Sector s in selection)
s.Fields.BeforeFieldsChange();
//get default values
List<UniversalFieldInfo> sectorFields = General.Map.Config.SectorFields;
foreach (UniversalFieldInfo i in sectorFields) {
if (i.Name == "lightcolor")
defaultSectorColor = (int)i.Default;
else if (i.Name == "fadecolor")
defaultFadeColor = (int)i.Default;
}
//set colors
curSectorColor = selection[0].Fields.GetValue<int>("lightcolor", -1);
if (curSectorColor == -1) { //add lightcolor field
curSectorColor = defaultSectorColor;
selection[0].Fields.Add("lightcolor", new UniValue(UniversalType.Color, curSectorColor));
}
curFadeColor = selection[0].Fields.GetValue<int>("fadecolor", -1);
if (curFadeColor == -1) { //add fadecolor field
curFadeColor = defaultFadeColor;
selection[0].Fields.Add("fadecolor", new UniValue(UniversalType.Color, curFadeColor));
}
initialSectorColor = curSectorColor;
initialFadeColor = curFadeColor;
InitializeComponent();
colorPickerControl1.ColorChanged += new EventHandler<ColorChangedEventArgs>(colorPickerControl1_ColorChanged);
colorPickerControl1.OnOkPressed += new EventHandler(colorPickerControl1_OnOkPressed);
colorPickerControl1.OnCancelPressed += new EventHandler(colorPickerControl1_OnCancelPressed);
colorPickerControl1.Initialize(Color.FromArgb(currentColorTag == "lightcolor" ? curSectorColor : curFadeColor));
if (currentColorTag == "lightcolor")
rbSectorColor.Checked = true;
else
rbFadeColor.Checked = true;
rbSectorColor.CheckedChanged += new EventHandler(rbColor_CheckedChanged);
rbFadeColor.CheckedChanged += new EventHandler(rbColor_CheckedChanged);
Text = "Editing " + rest;
//cannot fail here :)
return true;
}
private void colorPickerControl1_OnCancelPressed(object sender, EventArgs e) {
//restore initial values
General.Map.UndoRedo.PerformUndo();
Close();
}
private void colorPickerControl1_OnOkPressed(object sender, EventArgs e) {
//check if values are default
foreach (Sector s in selection) {
if ((int)s.Fields["lightcolor"].Value == defaultSectorColor)
s.Fields.Remove("lightcolor");
if ((int)s.Fields["fadecolor"].Value == defaultFadeColor)
s.Fields.Remove("fadecolor");
}
Close();
}
private void colorPickerControl1_ColorChanged(object sender, ColorChangedEventArgs e) {
foreach (Sector s in selection) {
s.Fields[currentColorTag].Value = e.RGB.Red << 16 | e.RGB.Green << 8 | e.RGB.Blue;
s.UpdateNeeded = true;
s.UpdateCache();
}
//update display
if (mode == "SectorsMode") {
General.Interface.RedrawDisplay();
} else { //should be visual mode
VisualMode vm = (VisualMode)General.Editing.Mode;
foreach (Sector s in selection) {
if (vm.VisualSectorExists(s)) {
VisualSector vs = vm.GetVisualSector(s);
vs.UpdateSectorData();
}
}
}
}
private void rbColor_CheckedChanged(object sender, EventArgs e) {
RadioButton b = (RadioButton)sender;
if (b.Checked) {
currentColorTag = (string)b.Tag;
//update color picker
if (currentColorTag == "lightcolor")
colorPickerControl1.SetInitialColor(Color.FromArgb(initialSectorColor));
else
colorPickerControl1.SetInitialColor(Color.FromArgb(initialFadeColor));
colorPickerControl1.SetCurrentColor(Color.FromArgb((int)selection[0].Fields[currentColorTag].Value));
}
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,90 @@
namespace CodeImp.DoomBuilder.ColorPicker
{
partial class ToolsForm
{
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
private void InitializeComponent() {
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.separator1 = new System.Windows.Forms.ToolStripSeparator();
this.cpButton = new System.Windows.Forms.ToolStripButton();
this.separator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStrip1.SuspendLayout();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.separator1,
this.cpButton,
this.separator2});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(284, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
//
// separator1
//
this.separator1.Name = "separator1";
this.separator1.Size = new System.Drawing.Size(6, 25);
//
// cpButton
//
this.cpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.cpButton.Image = global::CodeImp.DoomBuilder.ColorPicker.Properties.Resources.cp;
this.cpButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.cpButton.Name = "cpButton";
this.cpButton.Size = new System.Drawing.Size(23, 22);
this.cpButton.Tag = "togglelightpannel";
this.cpButton.Text = "Color Picker";
this.cpButton.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// separator2
//
this.separator2.Name = "separator2";
this.separator2.Size = new System.Drawing.Size(6, 25);
//
// ToolsForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.toolStrip1);
this.Name = "ToolsForm";
this.Text = "ToolStrip";
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolStrip toolStrip1;
private System.Windows.Forms.ToolStripButton cpButton;
private System.Windows.Forms.ToolStripSeparator separator1;
private System.Windows.Forms.ToolStripSeparator separator2;
}
}

View file

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder;
namespace CodeImp.DoomBuilder.ColorPicker
{
public partial class ToolsForm : Form
{
public ToolsForm() {
InitializeComponent();
General.Interface.AddButton(separator1);
General.Interface.AddButton(cpButton);
General.Interface.AddButton(separator2);
}
private void InvokeTaggedAction(object sender, EventArgs e) {
General.Interface.InvokeTaggedAction(sender, e);
}
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -415,7 +415,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
}
// This updates the VisualSectors and VisualThings that have their Changed property set
private void UpdateChangedObjects()
private void UpdateChangedObjects()
{
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
{

View file

@ -117,7 +117,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// This updates this virtual the sector and neightbours if needed
public void UpdateSectorGeometry(bool includeneighbours)
{
if(isupdating)
//mxd dbg
GZBuilder.GZGeneral.Trace("UpdateSectorGeometry isupdating=" + isupdating);
if(isupdating)
return;
isupdating = true;
@ -169,6 +172,27 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
isupdating = false;
}
//mxd. call this to update sector and things in it when Sector.Fields are changed
override public void UpdateSectorData() {
//update sector data
SectorData data = GetSectorData();
data.Update(true);
//update sector
Rebuild();
//update things in this sector
foreach (Thing t in General.Map.Map.Things) {
if (t.Sector == this.Sector) {
if (mode.VisualThingExists(t)) {
// Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing);
vt.Rebuild();
}
}
}
}
// This (re)builds the visual sector, calculating all geometry from scratch
public void Rebuild()

View file

@ -211,12 +211,18 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
ceiling.colorbelow = lightcolor.WithAlpha(255);
}
//mxd
public void Update(bool forced) {
updated = !forced;
Update();
}
// When no geometry has been changed and no effects have been added or removed,
// you can call this again to update existing effects. The effects will update
// the existing SectorLevels to match with any changes.
public void Update()
{
if(isupdating || updated) return;
if(isupdating || updated) return;
isupdating = true;
// Set floor/ceiling to their original setup