-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMyGraphicControl.h
More file actions
176 lines (152 loc) · 4.67 KB
/
Copy pathMyGraphicControl.h
File metadata and controls
176 lines (152 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#ifndef __MY_GRAPHIC_CONTROL_H__
#define __MY_GRAPHIC_CONTROL_H__
#include "IControl.h"
#include <vector>
#include <algorithm>
class Point {
public:
unsigned int uid;
double x;
double y;
bool operator < (const Point& point) const { return (this->x < point.x); };
bool operator > (const Point& point) const { return (this->x > point.x); };
bool operator == (const Point& point) const { return (this->uid == point.uid); };
};
class MyGraphicControl : public IControl {
protected:
std::vector<Point> points;
Point selected;
bool isDragging;
unsigned int counter;
double convertToGraphicX(double value) {
double min = (double) this->mRECT.L;
double distance = (double) this->mRECT.W();
return value * distance + min;
};
double convertToPercentX(double value) {
double min = (double) this->mRECT.L;
double position = value - min;
double distance = (double) this->mRECT.W();
return position / distance;
};
double convertToGraphicY(double value) {
double min = (double) this->mRECT.T;
double distance = (double) this->mRECT.H();
// We use (1 - value) as the max value 1 is located on top of graphics and not bottom
return (1 - value) * distance + min;
};
double convertToPercentY(double value) {
double min = (double) this->mRECT.T;
double position = value - min;
double distance = (double) this->mRECT.H();
// We return the 1 - distance as the value 1 is located on top of graphics and not bottom
return 1 - position / distance;
};
public:
MyGraphicControl(IPlugBase *pPlug, IRECT pR) : IControl(pPlug, pR) {};
~MyGraphicControl() {};
bool IsDirty() { return true; };
bool Draw(IGraphics *pGraphics) {
IColor color(255, 50, 200, 20);
Point previous;
// Little trick, no "real" points got uid = 0, so we know it's
// not a real point, and we should avoid doing line with it...
previous.uid = 0;
for (std::vector<Point>::iterator it = points.begin(); it != points.end(); ++it) {
Point current = *it;
// We draw the point
pGraphics->DrawCircle(&color, convertToGraphicX(current.x), convertToGraphicY(current.y), 3, 0, true);
// The previous point is a valid point, we draw line also
if (previous.uid > 0) {
pGraphics->DrawLine(&color,
convertToGraphicX(previous.x), convertToGraphicY(previous.y),
convertToGraphicX(current.x), convertToGraphicY(current.y),
0, true);
}
// We update the previous point
previous = current;
}
/* TODO:
I didn't put it here, to make you think
But you need few more cases to handle:
- when there is no points on the graphic
- when there is a single point on the graphic
- what to draw BEFORE the first point
- what to draw AFTER the last point
*/
return true;
};
Point getPoint(double x, double y, double epsilon) {
for (std::vector<Point>::iterator it = points.begin(); it != points.end(); ++it) {
Point point = *it;
double xGraphic = convertToGraphicX(point.x);
double yGraphic = convertToGraphicY(point.y);
if (
// X check
(xGraphic - epsilon < x && xGraphic + epsilon > x) &&
// Y check
(yGraphic - epsilon < y && yGraphic + epsilon > y)
) {
return point;
}
}
// Nothing found, we return a "blank" point
Point none;
none.uid = 0;
return none;
};
void OnMouseDblClick(int x, int y, IMouseMod* pMouseMod) {
Point imHere = getPoint(x, y, 6);
// As we said, the uid = 0 means no point
if (imHere.uid == 0) {
Point newPoint;
newPoint.x = convertToPercentX(x);
newPoint.y = convertToPercentY(y);
newPoint.uid = counter++;
points.push_back(newPoint);
// And we sort it!
std::sort(points.begin(), points.end());
SetDirty();
} else {
// We delete the point
points.erase(std::remove(points.begin(), points.end(), imHere), points.end());
SetDirty();
}
};
void OnMouseUp(int x, int y, IMouseMod* pMouseMod) {
isDragging = false;
};
void OnMouseDown(int x, int y, IMouseMod* pMouseMod) {
Point imHere = getPoint(x, y, 6);
if (imHere.uid == 0) {
// We erase selected
Point none;
none.uid = 0;
selected = none;
// Not needed, but who knows.
isDragging = false;
SetDirty();
} else {
selected = imHere;
isDragging = true;
SetDirty();
}
};
void OnMouseDrag(int x, int y, int dX, int dY, IMouseMod* pMouseMod) {
if (selected.uid == 0 || isDragging == false) {
// Nothing to do
return;
}
// We search for our points
// As selected is not a pointer
// If we modify it, it will be meaningless...
std::vector<Point>::iterator it = std::find(points.begin(), points.end(), selected);
if (it != points.end()) {
(&(*it))->x = convertToPercentX(x);
(&(*it))->y = convertToPercentY(y);
}
// And we ask to render
SetDirty();
};
};
#endif