mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-13 05:57:00 -04:00
Added color utilities; implemented more of Graph related classes
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@76 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <gfx/gfx.hpp>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Color utility functions
|
||||||
|
|
||||||
|
Color lerp(const Color& a, const Color& b, double t) {
|
||||||
|
return Color(a.Red() + (b.Red() - a.Red() ) * t,
|
||||||
|
a.Green() + (b.Green() - a.Green()) * t,
|
||||||
|
a.Blue() + (b.Blue() - a.Blue() ) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hsl2rgbp(double t1, double t2, double t3) {
|
||||||
|
// adjust t3 to [0...1)
|
||||||
|
if (t3 < 0.0) t3 += 1;
|
||||||
|
else if (t3 > 1.0) t3 -= 1;
|
||||||
|
// determine color
|
||||||
|
if (6.0 * t3 < 1) return (int)(255 * (t1 + (t2-t1) * 6.0 * t3) );
|
||||||
|
if (2.0 * t3 < 1) return (int)(255 * (t2) );
|
||||||
|
if (3.0 * t3 < 2) return (int)(255 * (t1 + (t2-t1) * 6.0 * (2.0/3.0 - t3)) );
|
||||||
|
else return (int)(255 * (t1) );
|
||||||
|
}
|
||||||
|
Color hsl2rgb(double h, double s, double l) {
|
||||||
|
double t2 = l < 0.5 ? l * (1.0 + s) :
|
||||||
|
l * (1.0 - s) + s;
|
||||||
|
double t1 = 2.0 * l - t2;
|
||||||
|
return Color(
|
||||||
|
hsl2rgbp(t1, t2, h + 1.0/3.0),
|
||||||
|
hsl2rgbp(t1, t2, h) ,
|
||||||
|
hsl2rgbp(t1, t2, h - 1.0/3.0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Color darken(const Color& c) {
|
||||||
|
return Color(
|
||||||
|
c.Red() * 8 / 10,
|
||||||
|
c.Green() * 8 / 10,
|
||||||
|
c.Blue() * 8 / 10
|
||||||
|
);
|
||||||
|
}
|
||||||
+7
-1
@@ -144,7 +144,7 @@ class ContourMask {
|
|||||||
UInt *lefts, *rights;
|
UInt *lefts, *rights;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Utility
|
// ----------------------------------------------------------------------------- : Color utility functions
|
||||||
|
|
||||||
inline int bot(int x) { return max(0, x); } ///< bottom range check for color values
|
inline int bot(int x) { return max(0, x); } ///< bottom range check for color values
|
||||||
inline int top(int x) { return min(255, x); } ///< top range check for color values
|
inline int top(int x) { return min(255, x); } ///< top range check for color values
|
||||||
@@ -153,5 +153,11 @@ inline int col(int x) { return top(bot(x)); } ///< top and bottom range check fo
|
|||||||
/// Linear interpolation between colors
|
/// Linear interpolation between colors
|
||||||
Color lerp(const Color& a, const Color& b, double t);
|
Color lerp(const Color& a, const Color& b, double t);
|
||||||
|
|
||||||
|
/// convert HSL to RGB, h,s,l must be in range [0...1)
|
||||||
|
Color hsl2rgb(double h, double s, double l);
|
||||||
|
|
||||||
|
/// A darker version of a color
|
||||||
|
Color darken(const Color& c);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : EOF
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <gui/control/gallery_list.hpp>
|
#include <gui/control/gallery_list.hpp>
|
||||||
|
#include <gfx/gfx.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Events
|
// ----------------------------------------------------------------------------- : Events
|
||||||
|
|
||||||
@@ -111,14 +112,6 @@ void GalleryList::onKeyDown(wxKeyEvent& ev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linear interpolation between colors
|
|
||||||
// MOVE ME, declared in gfx.hpp
|
|
||||||
Color lerp(const Color& a, const Color& b, double t) {
|
|
||||||
return Color(a.Red() + (b.Red() - a.Red() ) * t,
|
|
||||||
a.Green() + (b.Green() - a.Green()) * t,
|
|
||||||
a.Blue() + (b.Blue() - a.Blue() ) * t);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxSize GalleryList::DoGetBestSize() const {
|
wxSize GalleryList::DoGetBestSize() const {
|
||||||
wxSize ws = GetSize(), cs = GetClientSize();
|
wxSize ws = GetSize(), cs = GetClientSize();
|
||||||
const int w = item_size.GetWidth() + 2 * MARGIN;
|
const int w = item_size.GetWidth() + 2 * MARGIN;
|
||||||
|
|||||||
+119
-2
@@ -7,19 +7,136 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <gui/control/graph.hpp>
|
#include <gui/control/graph.hpp>
|
||||||
|
#include <gfx/gfx.hpp>
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Graph
|
DECLARE_TYPEOF_COLLECTION(GraphAxisP);
|
||||||
|
DECLARE_TYPEOF_COLLECTION(GraphElementP);
|
||||||
|
DECLARE_TYPEOF_COLLECTION(GraphGroup);
|
||||||
|
typedef map<String,UInt> map_String_UInt;
|
||||||
|
DECLARE_TYPEOF(map_String_UInt);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : GraphData
|
||||||
|
|
||||||
|
GraphElement::GraphElement(const String& v1) {
|
||||||
|
values.push_back(v1);
|
||||||
|
}
|
||||||
|
GraphElement::GraphElement(const String& v1, const String& v2) {
|
||||||
|
values.push_back(v1);
|
||||||
|
values.push_back(v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphData::GraphData(const GraphDataPre& d)
|
||||||
|
: axes(d.axes)
|
||||||
|
{
|
||||||
|
// total size
|
||||||
|
size = (UInt)d.elements.size();
|
||||||
|
// find groups on each axis
|
||||||
|
size_t value_count = 1;
|
||||||
|
size_t i = 0;
|
||||||
|
FOR_EACH(a, axes) {
|
||||||
|
map<String,UInt> counts; // note: default constructor for UInt() does initialize to 0
|
||||||
|
FOR_EACH_CONST(e, d.elements) {
|
||||||
|
counts[e->values[i]] += 1;
|
||||||
|
}
|
||||||
|
// TODO: allow some ordering in the groups, and allow colors to be passed
|
||||||
|
FOR_EACH(c, counts) {
|
||||||
|
a->groups.push_back(GraphGroup(c.first, c.second));
|
||||||
|
a->max = max(a->max, c.second);
|
||||||
|
}
|
||||||
|
// find some nice colors for the groups
|
||||||
|
if (a->auto_color) {
|
||||||
|
double hue = 0.6; // start hue
|
||||||
|
bool first = true;
|
||||||
|
FOR_EACH(g, a->groups) {
|
||||||
|
double amount = double(g.size) / size; // amount this group takes
|
||||||
|
if (!first) hue += amount/2;
|
||||||
|
g.color = hsl2rgb(hue, 1.0, 0.5);
|
||||||
|
hue += amount / 2;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value_count *= a->groups.size();
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// count elements in each position
|
||||||
|
values.clear();
|
||||||
|
values.resize(value_count, 0);
|
||||||
|
FOR_EACH_CONST(e, d.elements) {
|
||||||
|
// find index j in elements
|
||||||
|
size_t i = 0, j = 0;
|
||||||
|
FOR_EACH(a, axes) {
|
||||||
|
String v = e->values[i];
|
||||||
|
size_t k = 0, l = 0;
|
||||||
|
FOR_EACH(g, a->groups) {
|
||||||
|
if (v == g.name) {
|
||||||
|
k = l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
l += 1;
|
||||||
|
}
|
||||||
|
j = j * a->groups.size() + k;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
values[j] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Graph1D
|
||||||
|
|
||||||
|
bool Graph1D::findItem(const RealPoint& pos, vector<int>& out) const {
|
||||||
|
int i = findItem(pos);
|
||||||
|
if (i == -1) return false;
|
||||||
|
else {
|
||||||
|
out.clear();
|
||||||
|
out.insert(out.begin(), data->axes.size(), -1);
|
||||||
|
out.at(axis) = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Bar Graph
|
||||||
|
|
||||||
|
void BarGraph::draw(RotatedDC& dc) const {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
int BarGraph::findItem(const RealPoint& pos) const {
|
||||||
|
return -1; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Pie Graph
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Graph Legend
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : GraphControl
|
// ----------------------------------------------------------------------------- : GraphControl
|
||||||
|
|
||||||
GraphControl::GraphControl(Window* parent, int id)
|
GraphControl::GraphControl(Window* parent, int id)
|
||||||
: wxControl(parent, id)
|
: wxControl(parent, id)
|
||||||
{}
|
{
|
||||||
|
graph = new_shared1<BarGraph>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphControl::setData(const GraphDataPre& data) {
|
||||||
|
setData(new_shared1<GraphData>(data));
|
||||||
|
}
|
||||||
|
void GraphControl::setData(const GraphDataP& data) {
|
||||||
|
if (graph) {
|
||||||
|
graph->setData(data);
|
||||||
|
current_item.clear(); // TODO : preserver selection
|
||||||
|
Refresh(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphControl::onPaint(wxPaintEvent&) {
|
void GraphControl::onPaint(wxPaintEvent&) {
|
||||||
wxBufferedPaintDC dc(this);
|
wxBufferedPaintDC dc(this);
|
||||||
|
wxSize cs = GetClientSize();
|
||||||
|
RotatedDC rdc(dc, 0, RealRect(RealPoint(0,0),cs), 1, false);
|
||||||
|
rdc.SetPen(*wxTRANSPARENT_PEN);
|
||||||
|
rdc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||||
|
rdc.DrawRectangle(rdc.getInternalRect());
|
||||||
|
if (graph) graph->draw(rdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphControl::onSize(wxSizeEvent&) {
|
void GraphControl::onSize(wxSizeEvent&) {
|
||||||
|
|||||||
@@ -23,25 +23,39 @@ DECLARE_POINTER_TYPE(Graph);
|
|||||||
/** A group is rendered as a single bar or pie slice */
|
/** A group is rendered as a single bar or pie slice */
|
||||||
class GraphGroup {
|
class GraphGroup {
|
||||||
public:
|
public:
|
||||||
|
GraphGroup(const String& name, UInt size, const Color& color = *wxBLACK)
|
||||||
|
: name(name), color(color), size(size)
|
||||||
|
{}
|
||||||
|
|
||||||
String name; ///< Name of this position
|
String name; ///< Name of this position
|
||||||
Color color; ///< Associated color
|
Color color; ///< Associated color
|
||||||
int size; ///< Number of elements in this group
|
UInt size; ///< Number of elements in this group
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An axis in a graph, consists of a list of groups
|
/// An axis in a graph, consists of a list of groups
|
||||||
/** The sum of groups.sum = sum of all elements in the data */
|
/** The sum of groups.sum = sum of all elements in the data */
|
||||||
class GraphAxis {
|
class GraphAxis {
|
||||||
public:
|
public:
|
||||||
|
GraphAxis(const String& name, bool auto_color = true)
|
||||||
|
: name(name)
|
||||||
|
, auto_color(auto_color)
|
||||||
|
, max(0)
|
||||||
|
{}
|
||||||
|
|
||||||
String name; ///< Name/label of this axis
|
String name; ///< Name/label of this axis
|
||||||
bool auto_color; ///< Automatically assign colors to the groups on this axis
|
bool auto_color; ///< Automatically assign colors to the groups on this axis
|
||||||
vector<GraphGroup> groups; ///< Groups along this axis
|
vector<GraphGroup> groups; ///< Groups along this axis
|
||||||
int max; ///< Maximum size of the groups
|
UInt max; ///< Maximum size of the groups
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single data point of a graph
|
/// A single data point of a graph
|
||||||
class GraphElement {
|
class GraphElement {
|
||||||
public:
|
public:
|
||||||
vector<String> axis_groups; ///< Group name for each axis
|
GraphElement() {}
|
||||||
|
GraphElement(const String& v1);
|
||||||
|
GraphElement(const String& v1, const String& v2);
|
||||||
|
|
||||||
|
vector<String> values; ///< Group name for each axis
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data to be displayed in a graph, not processed yet
|
/// Data to be displayed in a graph, not processed yet
|
||||||
@@ -54,11 +68,11 @@ class GraphDataPre {
|
|||||||
/// Data to be displayed in a graph
|
/// Data to be displayed in a graph
|
||||||
class GraphData {
|
class GraphData {
|
||||||
public:
|
public:
|
||||||
GraphData(GraphDataPre);
|
GraphData(const GraphDataPre&);
|
||||||
|
|
||||||
vector<GraphAxisP> axes; ///< The axes in the data
|
vector<GraphAxisP> axes; ///< The axes in the data
|
||||||
vector<int> values; ///< Multi dimensional (dim = axes.size()) array of values
|
vector<UInt> values; ///< Multi dimensional (dim = axes.size()) array of values
|
||||||
int size; ///< Total number of elements
|
UInt size; ///< Total number of elements
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -69,7 +83,7 @@ class GraphData {
|
|||||||
class Graph {
|
class Graph {
|
||||||
public:
|
public:
|
||||||
/// Draw this graph, filling the internalRect() of the dc.
|
/// Draw this graph, filling the internalRect() of the dc.
|
||||||
virtual void draw(RotatedDC& dc) = 0;
|
virtual void draw(RotatedDC& dc) const = 0;
|
||||||
/// Find the item at the given position, position is normalized to [0..1)
|
/// Find the item at the given position, position is normalized to [0..1)
|
||||||
virtual bool findItem(const RealPoint& pos, vector<int>& out) const { return false; }
|
virtual bool findItem(const RealPoint& pos, vector<int>& out) const { return false; }
|
||||||
/// Change the data
|
/// Change the data
|
||||||
@@ -84,7 +98,7 @@ class Graph {
|
|||||||
class Graph1D : public Graph {
|
class Graph1D : public Graph {
|
||||||
public:
|
public:
|
||||||
inline Graph1D(size_t axis) : axis(axis) {}
|
inline Graph1D(size_t axis) : axis(axis) {}
|
||||||
virtual bool findItem(const RealPoint& pos, vector<int>& out) const { return false; }
|
virtual bool findItem(const RealPoint& pos, vector<int>& out) const;
|
||||||
protected:
|
protected:
|
||||||
size_t axis;
|
size_t axis;
|
||||||
/// Find an item, return the position along the axis, or -1 if not found
|
/// Find an item, return the position along the axis, or -1 if not found
|
||||||
|
|||||||
@@ -1240,6 +1240,33 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\gfx\blend_image.cpp">
|
RelativePath=".\gfx\blend_image.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\gfx\color.cpp">
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Debug Unicode|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Release Unicode|Win32">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\gfx\combine_image.cpp">
|
RelativePath=".\gfx\combine_image.cpp">
|
||||||
<FileConfiguration
|
<FileConfiguration
|
||||||
|
|||||||
Reference in New Issue
Block a user