3
void KageStage::initNodeTool() {
7
selectedShapes.clear();
8
_mouseLocationShapeIndex = _NO_SELECTION;
13
bool KageStage::isSelectedNode(unsigned int p_index) {
15
unsigned int nsize = selectedNodes.size();
20
for (unsigned int i = 0; i < nsize; ++i) {
21
if (selectedNodes[i] == p_index) {
28
void KageStage::addSelectedNode(unsigned int p_index) {
29
if (p_index == _NO_SELECTION) return;
30
if (isSelectedNode(p_index) == false) {
31
selectedNodes.push_back(p_index);
36
void KageStage::updateNodeX(double p_value, bool p_stackDo) {
38
std::cout << " KageStage::updateNodeX " << selectedNodes.size() << " " << p_value << std::endl;
40
if (selectedNodes.size() == 0) {
44
double l_propXdiff = 0;
45
vector<VectorData> v = win->getFrameData().getVectorData();
46
cout << " nodeIndexX " << nodeIndexX << " " << isSelectedNode(nodeIndexX) << endl;
47
//calculate xDIFF from selected base Node
48
for (unsigned int l_selectedNode = 0; l_selectedNode < selectedNodes.size(); ++l_selectedNode) {
49
if (selectedNodes[l_selectedNode] == nodeIndexX) {
50
l_propXdiff = p_value - v[selectedNodes[l_selectedNode]].points[2].x;
54
cout << " l_propXdiff " << l_propXdiff << endl;
55
for (unsigned int l_selectedNode = 0; l_selectedNode < selectedNodes.size(); ++l_selectedNode) {
56
// l_propXdiff = p_value - v[selectedNodes[l_selectedNode]].points[2].x;
57
if (v[selectedNodes[l_selectedNode]].vectorType == VectorData::TYPE_CURVE_CUBIC) {
58
v[selectedNodes[l_selectedNode]].points[1].x += l_propXdiff;
59
v[selectedNodes[l_selectedNode]].points[2].x += l_propXdiff;
61
if (v[selectedNodes[l_selectedNode]+1].getPoints().size() != 0) {
62
v[selectedNodes[l_selectedNode]+1].points[0].x += l_propXdiff;
64
//this part of code is trying to resolve this problematic code
65
// above code is problematic if for last Node; this will use shape's first Node's point 0 instead
66
std::cout << " KageStage::updateNodeX points.size is zero" << std::endl;
67
for (unsigned int i = selectedNodes[l_selectedNode]-1; i >= 0; --i) {
68
if (v[i].vectorType == VectorData::TYPE_MOVE) {
69
std::cout << " KageStage::updateNodeX got MOVE" << std::endl;
70
if (i+1 != selectedNodes[l_selectedNode]) {
71
std::cout << " KageStage::updateNodeX moving control point :) " << std::endl;
72
v[i ].points[0].x += l_propXdiff; // for Node MOVE
73
v[i+1].points[0].x += l_propXdiff; // for Node Curve's control point being used by Node MOVE
79
} else if (v[selectedNodes[l_selectedNode]].vectorType == VectorData::TYPE_IMAGE) {
80
//TODO:handle X for images
92
void KageStage::updateNodeY(double p_value) {
94
std::cout << " KageStage::updateNodeY " << selectedNodes.size() << " " << p_value << std::endl;
96
if (selectedNodes.size() == 0) {
100
double l_propYdiff = 0;
101
vector<VectorData> v = win->getFrameData().getVectorData();
103
//calculate yDIFF from selected base Node
104
for (unsigned int l_selectedNode = 0; l_selectedNode < selectedNodes.size(); ++l_selectedNode) {
105
if (selectedNodes[l_selectedNode] == nodeIndexY) {
106
l_propYdiff = p_value - v[selectedNodes[l_selectedNode]].points[2].y;
110
for (unsigned int l_selectedNode = 0; l_selectedNode < selectedNodes.size(); ++l_selectedNode) {
111
// l_propYdiff = p_value - v[selectedNodes[l_selectedNode]].points[2].y;
112
if (v[selectedNodes[l_selectedNode]].vectorType == VectorData::TYPE_CURVE_CUBIC) {
113
v[selectedNodes[l_selectedNode]].points[1].y += l_propYdiff;
114
v[selectedNodes[l_selectedNode]].points[2].y += l_propYdiff;
116
if (v[selectedNodes[l_selectedNode]+1].getPoints().size() != 0) {
117
v[selectedNodes[l_selectedNode]+1].points[0].y += l_propYdiff;
119
for (unsigned int i = selectedNodes[l_selectedNode]-1; i >= 0; --i) {
120
if (v[i].vectorType == VectorData::TYPE_MOVE) {
121
if (i+1 != selectedNodes[l_selectedNode]) {
122
v[i ].points[0].y += l_propYdiff;
123
v[i+1].points[0].y += l_propYdiff;
129
} else if (v[selectedNodes[l_selectedNode]].vectorType == VectorData::TYPE_IMAGE) {
130
//TODO:handle Y for images
134
win->setFrameData(v);
144
void KageStage::handleNodes() {
145
handleNodes_selection();
146
handleNodes_relocation();
147
handleNodes_rendering();
149
void KageStage::handleNodes_selection() {
150
if (mouseDown == true && _isModifyingShape == false) {
154
vector<VectorData> v = win->getFrameData().getVectorData();
155
unsigned int vsize = v.size();
156
mouseOnNodeHover = UINT_MAX;
157
unsigned int typeMovesIndex = _NO_SELECTION;
158
bool l_shapeGotClose = false;
159
for (unsigned int l_selectedShape = 0; l_selectedShape < selectedShapes.size(); ++l_selectedShape) {
160
for (unsigned int i = selectedShapes[l_selectedShape]; i < vsize; ++i) {
161
switch (v[i].vectorType) {
162
case VectorData::TYPE_CLOSE_PATH:
163
l_shapeGotClose = true;
165
case VectorData::TYPE_FILL:
166
l_shapeGotClose = false;
168
case VectorData::TYPE_ENDFILL:
169
if (l_shapeGotClose == false && typeMovesIndex != _NO_SELECTION) {
170
//check if mouse is on Move' location
172
v[typeMovesIndex].points[0].x + origin.x,
173
v[typeMovesIndex].points[0].y + origin.y) == true) {
174
mouseOnNodeHover = typeMovesIndex;
175
if (mouseDown == true) {
176
if (mouseOnNode == _NO_SELECTION) {
177
mouseOnNode = typeMovesIndex;
179
if (isSelectedNode(typeMovesIndex) == false && keyShiftDown == false) {
180
selectedNodes.clear();
182
addSelectedNode(typeMovesIndex);
183
if (mouseOnNodeIndex == _NO_SELECTION) {
184
mouseOnNodeIndex = 3;
186
mouseOnNodeOffset.x = _mouseLocation.x - v[typeMovesIndex].points[0].x - origin.x;
187
mouseOnNodeOffset.y = _mouseLocation.y - v[typeMovesIndex].points[0].y - origin.y;
193
case VectorData::TYPE_STROKE:
195
case VectorData::TYPE_MOVE:
197
case VectorData::TYPE_LINE:
199
case VectorData::TYPE_CURVE_QUADRATIC:
200
case VectorData::TYPE_CURVE_CUBIC:
203
v[i].points[2].x + origin.x,
204
v[i].points[2].y + origin.y) == true) {
205
mouseOnNodeHover = i;
206
if (mouseDown == true) {
207
if (mouseOnNode == _NO_SELECTION) {
210
if (isSelectedNode(i) == false && keyShiftDown == false) {
211
selectedNodes.clear();
214
if (mouseOnNodeIndex == _NO_SELECTION) {
215
mouseOnNodeIndex = 3;
217
mouseOnNodeOffset.x = _mouseLocation.x - v[i].points[2].x - origin.x;
218
mouseOnNodeOffset.y = _mouseLocation.y - v[i].points[2].y - origin.y;
222
//check control points
224
v[i].points[0].x + origin.x,
225
v[i].points[0].y + origin.y) == true) {
226
if (mouseDown == true) {
227
if (mouseOnNode == _NO_SELECTION) {
230
if (keyShiftDown == false) { selectedNodes.clear(); }
232
v[i-1].vectorType == VectorData::TYPE_LINE
233
|| v[i-1].vectorType == VectorData::TYPE_CURVE_QUADRATIC
234
|| v[i-1].vectorType == VectorData::TYPE_CURVE_CUBIC)) {
235
addSelectedNode(i-1);
237
if (mouseOnNodeIndex == _NO_SELECTION) {
238
mouseOnNodeIndex = 1;
244
v[i].points[1].x + origin.x,
245
v[i].points[1].y + origin.y) == true) {
246
if (mouseDown == true) {
247
if (mouseOnNode == _NO_SELECTION) {
250
if (keyShiftDown == false) { selectedNodes.clear(); }
252
if (mouseOnNodeIndex == _NO_SELECTION) {
253
mouseOnNodeIndex = 2;
258
case VectorData::TYPE_TEXT:
259
case VectorData::TYPE_IMAGE:
260
case VectorData::TYPE_INIT:
261
typeMovesIndex = _NO_SELECTION;
268
void KageStage::handleNodes_relocation() {
269
if (selectedShapes.size() == 0) {
273
vector<VectorData> v = win->getFrameData().getVectorData();
274
bool l_editingNode = false;
277
unsigned int typeMovesIndex = _NO_SELECTION;
278
unsigned int typeEndsPointSize;
279
unsigned int typeCubicCurvesIndex = _NO_SELECTION;
280
bool l_useEndPoint = false;
281
unsigned int vsize = v.size();
282
bool l_shapeGotClose = false;
283
PointData g_typeMovesXY;
284
for (unsigned int l_selectedShape = 0; l_selectedShape < selectedShapes.size(); ++l_selectedShape) {
285
for (unsigned int i = selectedShapes[l_selectedShape]; i < vsize; ++i) {
286
switch (v[i].vectorType) {
287
case VectorData::TYPE_CLOSE_PATH:
288
l_shapeGotClose = true;
289
if (typeMovesIndex != UINT_MAX) {
290
typeEndsPointSize = v[i-1].points.size()-1;
291
if (v[typeMovesIndex].points[0].x != v[typeMovesIndex].points[typeEndsPointSize].x
292
|| v[typeMovesIndex].points[0].y != v[typeMovesIndex].points[typeEndsPointSize].y) {
293
v[typeMovesIndex].points[0].x = v[i-1].points[typeEndsPointSize].x;
294
v[typeMovesIndex].points[0].y = v[i-1].points[typeEndsPointSize].y;
296
typeMovesIndex = UINT_MAX;
298
l_useEndPoint = true;
300
case VectorData::TYPE_FILL:
301
l_shapeGotClose = false;
303
case VectorData::TYPE_ENDFILL:
304
///make sure last point before end fill is in-sync with MOVE(shape's start point)
305
if (typeMovesIndex != UINT_MAX && mouseDown == true && mouseOnNode == i-1) {
306
if (l_useEndPoint == true) {
307
typeEndsPointSize = v[i-1].points.size()-1;
308
if (v[typeMovesIndex].points[0].x != v[typeMovesIndex].points[typeEndsPointSize].x
309
|| v[typeMovesIndex].points[0].y != v[typeMovesIndex].points[typeEndsPointSize].y) {
310
v[typeMovesIndex].points[0].x = v[i-1].points[typeEndsPointSize].x;
311
v[typeMovesIndex].points[0].y = v[i-1].points[typeEndsPointSize].y;
315
if (l_shapeGotClose == false && mouseDown == true && mouseOnNode == typeMovesIndex && mouseOnNodeIndex == 3) {
316
l_editingNode = true;
317
l_x = ((draw1.x - origin.x - mouseOnNodeOffset.x) - v[typeMovesIndex].points[0].x);
318
l_y = ((draw1.y - origin.y - mouseOnNodeOffset.y) - v[typeMovesIndex].points[0].y);
319
if (keyControlDown == true) {
320
if (keyShiftDown == true) {
321
l_x = 0; //restraint on X axis
323
l_y = 0; //restraint on Y axis
326
for (unsigned int j = 0; j < selectedNodes.size(); ++j) {
327
unsigned int k = selectedNodes[j];
328
//move control A of selected node's next curve
329
if (k+1 < v.size()-1 && v[k+1].vectorType == VectorData::TYPE_CURVE_CUBIC) {
330
v[k+1].points[0].x += l_x;
331
v[k+1].points[0].y += l_y;
332
} else if (k+2 < vsize && v[k+2].vectorType == VectorData::TYPE_ENDFILL) {
333
v[typeMovesIndex+1].points[0].x += l_x;
334
v[typeMovesIndex+1].points[0].y += l_y;
336
//move anchor of selected node
337
if (k != typeMovesIndex) {
338
v[k].points[2].x += l_x;
339
v[k].points[2].y += l_y;
342
v[typeMovesIndex].points[0].x += l_x;
343
v[typeMovesIndex].points[0].y += l_y;
347
case VectorData::TYPE_STROKE:
349
case VectorData::TYPE_MOVE:
350
///register i for later use in ENDFILL
353
case VectorData::TYPE_LINE:
354
if (mouseDown == true && mouseOnNode == i) {
355
v[i].points[0].x = draw1.x - origin.x;
356
v[i].points[0].y = draw1.y - origin.y;
358
l_x = v[i].points[0].x + origin.x;
359
l_y = v[i].points[0].y + origin.y;
361
if (isMouseOnNode(l_x, l_y) == true) {
362
if (mouseDown == true) {
363
v[i].points[0].x = draw1.x - origin.x;
364
v[i].points[0].y = draw1.y - origin.y;
366
l_x = v[i].points[0].x + origin.x;
367
l_y = v[i].points[0].y + origin.y;
371
case VectorData::TYPE_CURVE_QUADRATIC:
372
case VectorData::TYPE_CURVE_CUBIC:
373
///register i for later use in ENDFILL <-- note from newer handling of Poly
374
if (typeCubicCurvesIndex == _NO_SELECTION) {
375
typeCubicCurvesIndex = i;
379
if (mouseDown == true && mouseOnNode == i && mouseOnNodeIndex == 3) {
380
l_editingNode = true;
381
l_x = ((draw1.x - origin.x - mouseOnNodeOffset.x) - v[i].points[2].x);
382
l_y = ((draw1.y - origin.y - mouseOnNodeOffset.y) - v[i].points[2].y);
383
if (keyControlDown == true) {
384
if (keyShiftDown == true) {
385
l_x = 0; //restraint on X axis
387
l_y = 0; //restraint on Y axis
390
for (unsigned int j = 0; j < selectedNodes.size(); ++j) {
391
unsigned int k = selectedNodes[j];
392
//move control B of selected node's current curve
393
v[k].points[1].x += l_x;
394
v[k].points[1].y += l_y;
395
//move control A of selected node's next curve
396
if (k+1 < v.size()-1 && v[k+1].vectorType == VectorData::TYPE_CURVE_CUBIC) {
397
v[k+1].points[0].x += l_x;
398
v[k+1].points[0].y += l_y;
399
} else if (k+2 < vsize && v[k+2].vectorType == VectorData::TYPE_ENDFILL) {
400
v[typeMovesIndex+1].points[0].x += l_x;
401
v[typeMovesIndex+1].points[0].y += l_y;
403
//move anchor of selected node
405
v[k].points[2].x += l_x;
406
v[k].points[2].y += l_y;
410
v[i].points[2].x += l_x;
411
v[i].points[2].y += l_y;
414
//relocate control points
415
if (mouseDown == true && mouseOnNode == i && mouseOnNodeIndex == 1) {
416
l_editingNode = true;
417
v[i].points[0].x = draw1.x - origin.x;
418
v[i].points[0].y = draw1.y - origin.y;
421
if (mouseDown == true && mouseOnNode == i && mouseOnNodeIndex == 2) {
422
l_editingNode = true;
423
v[i].points[1].x = draw1.x - origin.x;
424
v[i].points[1].y = draw1.y - origin.y;
427
case VectorData::TYPE_TEXT:
428
case VectorData::TYPE_IMAGE:
429
case VectorData::TYPE_INIT:
436
if (l_editingNode == true) {
437
win->setFrameData(v);
439
// cout << " \t l_editingNode " << l_editingNode << endl;
440
_isModifyingShape = l_editingNode;
442
void KageStage::handleNodes_rendering() {
443
if (selectedShapes.size() == 0) {
447
vector<VectorData> v = win->getFrameData().getVectorData();
450
bool l_shapeGotClose = false;
451
unsigned int vsize = v.size();
452
unsigned int typeMovesIndex = _NO_SELECTION;
453
for (unsigned int l_selectedShape = 0; l_selectedShape < selectedShapes.size(); ++l_selectedShape) {
454
for (unsigned int i = selectedShapes[l_selectedShape]; i < vsize; ++i) {
455
switch (v[i].vectorType) {
456
case VectorData::TYPE_CLOSE_PATH:
457
l_shapeGotClose = true;
459
case VectorData::TYPE_FILL:
460
l_shapeGotClose = false;
462
case VectorData::TYPE_ENDFILL:
464
if (l_shapeGotClose == false && typeMovesIndex != UINT_MAX) {
467
v[typeMovesIndex].points[0].x + origin.x,
468
v[typeMovesIndex].points[0].y + origin.y
471
l_x = v[typeMovesIndex].points[0].x + origin.x;
472
l_y = v[typeMovesIndex].points[0].y + origin.y;
473
if (mouseOnNodeHover == typeMovesIndex) {
474
renderNode(l_x, l_y, 1);
476
if (selectedNodes.size() == 0) {
477
renderNode(l_x, l_y, 0);
479
bool l_selectedNode = false;
480
for (unsigned int j = 0; j < selectedNodes.size(); ++j) {
481
if (selectedNodes[j] == i) {
482
l_selectedNode = true;
486
if (l_selectedNode == true) {
487
renderNode(l_x, l_y, 2);
489
renderNode(l_x, l_y, 0);
495
case VectorData::TYPE_STROKE:
497
case VectorData::TYPE_MOVE:
500
case VectorData::TYPE_LINE:
501
if (isMouseOnNode(l_x, l_y) == true) {
502
renderNode(l_x, l_y, 1);
504
renderNode(l_x, l_y, 0);
507
case VectorData::TYPE_CURVE_QUADRATIC:
508
case VectorData::TYPE_CURVE_CUBIC:
509
//draw lines to anchor
511
v[i-1].points[v[i-1].points.size()-1].x + origin.x,
512
v[i-1].points[v[i-1].points.size()-1].y + origin.y
515
v[i].points[0].x + origin.x,
516
v[i].points[0].y + origin.y
518
cr->set_source_rgba(0.0,0.7,0.7,1.0);
519
cr->set_line_width(1.0);
520
cr->set_line_cap(Cairo::LINE_CAP_ROUND);
524
v[i].points[1].x + origin.x,
525
v[i].points[1].y + origin.y
528
v[i].points[2].x + origin.x,
529
v[i].points[2].y + origin.y
531
cr->set_source_rgba(0.0,0.7,0.7,1.0);
532
cr->set_line_width(1.0);
533
cr->set_line_cap(Cairo::LINE_CAP_ROUND);
538
v[i].points[2].x + origin.x,
539
v[i].points[2].y + origin.y
542
l_x = v[i].points[2].x + origin.x;
543
l_y = v[i].points[2].y + origin.y;
544
if (mouseOnNodeHover == i) {
545
renderNode(l_x, l_y, 1);
547
if (selectedNodes.size() == 0) {
548
renderNode(l_x, l_y, 0);
550
bool l_selectedNode = false;
551
for (unsigned int j = 0; j < selectedNodes.size(); ++j) {
552
if (selectedNodes[j] == i) {
553
l_selectedNode = true;
557
if (l_selectedNode == true) {
558
renderNode(l_x, l_y, 2);
560
renderNode(l_x, l_y, 0);
565
//draw control points
566
if (mouseDown == true && mouseOnNode == i && mouseOnNodeIndex == 1) {
567
renderNodeControl(v[i].points[0].x + origin.x, v[i].points[0].y + origin.y, true);
569
renderNodeControl(v[i].points[0].x + origin.x, v[i].points[0].y + origin.y, false);
572
if (mouseDown == true && mouseOnNode == i && mouseOnNodeIndex == 2) {
573
renderNodeControl(v[i].points[1].x + origin.x, v[i].points[1].y + origin.y, true);
575
renderNodeControl(v[i].points[1].x + origin.x, v[i].points[1].y + origin.y, false);
578
case VectorData::TYPE_TEXT:
579
case VectorData::TYPE_IMAGE:
580
case VectorData::TYPE_INIT:
581
if (i != selectedShapes[l_selectedShape]) {
590
void KageStage::handleNodesMouseDown() {
591
// handleNodesMouseUp();
593
void KageStage::handleNodesMouseUp() {
594
_nodeToMouseDistance = 1080;
595
vector<VectorData> v = win->getFrameData().getVectorData();
600
mouseOnNode = _NO_SELECTION;
601
if (keyShiftDown == false) {
602
selectedShapes.clear();
604
selectedNodes.clear();
605
unsigned int vsize = v.size();
606
unsigned int l_vStartIndex = 0;
607
if (_mouseLocationShapeIndex != _NO_SELECTION) {
608
l_vStartIndex = _mouseLocationShapeIndex;
610
for (unsigned int i = l_vStartIndex; i < vsize; ++i) {
611
if (v[i].vectorType == VectorData::TYPE_CURVE_CUBIC) {
612
if (handleNodes_getNearestShape(v[i].points[0].x + origin.x, v[i].points[0].y + origin.y, i, v)) {
613
selectedNodes.push_back(i-1); //visualization-wise, the control-point is for the previous Node -- it is its right control-point
615
if (handleNodes_getNearestShape(v[i].points[1].x + origin.x, v[i].points[1].y + origin.y, i, v)) {
616
selectedNodes.push_back(i);
618
if (handleNodes_getNearestShape(v[i].points[2].x + origin.x, v[i].points[2].y + origin.y, i, v)) {
619
selectedNodes.push_back(i);
623
if (selectedShape != UINT_MAX) {
624
addSelectedShape(selectedShape);
625
if (KageStage::toolMode == MODE_SELECT) {
626
win->propStageSetVisible(false);
627
win->propFillStrokeSetVisible(true);
628
win->propShapePropertiesSetVisible(true);
631
if (selectedNodes.size() > 0) {
632
if (KageStage::toolMode == MODE_NODE) {
633
double l_nodeX = DBL_MAX;
634
double l_nodeY = DBL_MAX;
635
for (unsigned int i = 0; i < selectedNodes.size(); ++i) {
636
if (v[selectedNodes[i]].getPoints().size() == 3) {
637
if (v[selectedNodes[i]].points[2].x < l_nodeX) {
638
l_nodeX = v[selectedNodes[i]].points[2].x;
640
if (v[selectedNodes[i]].points[2].y < l_nodeY) {
641
l_nodeY = v[selectedNodes[i]].points[2].y;
645
if (l_nodeX == DBL_MAX) { l_nodeX = 0; }
647
if (l_nodeY == DBL_MAX) { l_nodeY = 0; }
650
win->propStageSetVisible(false);
651
win->propNodeXYSetVisible(true);
657
bool KageStage::handleNodes_getNearestShape(double p_x, double p_y, unsigned int p_index, vector<VectorData> p_v) {
658
double l_vXdiff, l_vYdiff;
661
if (p_x >= draw1.x) {
662
l_vXdiff = p_x - draw1.x;
664
l_vXdiff = draw1.x - p_x;
666
if (p_y >= draw1.y) {
667
l_vYdiff = p_y - draw1.y;
669
l_vYdiff = draw1.y - p_y;
672
l_distance = sqrt((l_vXdiff * l_vXdiff) + (l_vYdiff * l_vYdiff));
673
if (l_distance <= _nodeToMouseDistance
674
&& isMouseOnNode(p_x, p_y, 100) == true) {
675
_nodeToMouseDistance = l_distance;
676
selectedShape = getSelectedShapeViaNode(p_index, p_v);
677
// addSelectedShape(selectedShape);
684
unsigned int KageStage::getSelectedShapeViaNode(unsigned int p_index, vector<VectorData> p_v) {
685
if (p_index >= p_v.size()) {
689
unsigned int l_tmp = selectedShape;
699
for (unsigned int i = p_index; i >= 0; --i) {
700
switch (p_v[i].vectorType) {
701
case VectorData::TYPE_FILL:
702
fillColor = p_v[i].fillColor.clone();
704
case VectorData::TYPE_ENDFILL:
706
case VectorData::TYPE_STROKE:
707
stroke = p_v[i].stroke.clone();
710
case VectorData::TYPE_MOVE: {
711
if (propX > p_v[i].points[0].x) {
712
propX = p_v[i].points[0].x;
716
if (propY > p_v[i].points[0].y) {
717
propY = p_v[i].points[0].y;
723
case VectorData::TYPE_LINE:
724
case VectorData::TYPE_CURVE_QUADRATIC:
726
case VectorData::TYPE_CURVE_CUBIC: {
727
if (propX > p_v[i].points[0].x) {
728
propX = p_v[i].points[0].x;
732
if (propX > p_v[i].points[1].x) {
733
propX = p_v[i].points[1].x;
737
if (propX > p_v[i].points[2].x) {
738
propX = p_v[i].points[2].x;
742
if (propY > p_v[i].points[0].y) {
743
propY = p_v[i].points[0].y;
747
if (propY > p_v[i].points[1].y) {
748
propY = p_v[i].points[1].y;
752
if (propY > p_v[i].points[2].y) {
753
propY = p_v[i].points[2].y;
759
case VectorData::TYPE_TEXT:
760
case VectorData::TYPE_IMAGE:
762
case VectorData::TYPE_INIT: {
763
unsigned int vsize = p_v.size();
764
for (unsigned int j = i; j < vsize; ++j) {
765
if (p_v[j].vectorType == VectorData::TYPE_ENDFILL) {
767
} else if (p_v[j].vectorType == VectorData::TYPE_MOVE) {
768
if (propX < p_v[j].points[0].x
769
&& propWidth < (p_v[j].points[0].x - propX)) {
770
propWidth = p_v[j].points[0].x - propX;
771
cout << "\npropWidth " << propWidth << " _zoomValueShapeProperty " << _zoomValueShapeProperty << endl;
772
propWidth = propWidth * _zoomValueShapeProperty;
774
if (propY < p_v[j].points[0].y
775
&& propHeight < (p_v[j].points[0].y - propY)) {
776
propHeight = p_v[j].points[0].y - propY;
777
propHeight = propHeight * _zoomValueShapeProperty;
779
} else if (p_v[j].vectorType == VectorData::TYPE_CURVE_CUBIC) {
780
for (int k = 0; k < 3; ++k) {
781
if (propX < p_v[j].points[k].x
782
&& propWidth < (p_v[j].points[k].x - propX)) {
783
propWidth = p_v[j].points[k].x - propX;
784
cout << "\npropWidth " << propWidth << " _zoomValueShapeProperty " << _zoomValueShapeProperty << endl;
785
propWidth = propWidth * _zoomValueShapeProperty;
787
if (propY < p_v[j].points[k].y
788
&& propHeight < (p_v[j].points[k].y - propY)) {
789
propHeight = p_v[j].points[k].y - propY;
790
propHeight = propHeight * _zoomValueShapeProperty;
805
void KageStage::renderNode(double p_x, double p_y, unsigned int p_state) {
806
cr->move_to(p_x-5, p_y);
807
cr->line_to(p_x , p_y-5);
808
cr->line_to(p_x+5, p_y );
809
cr->line_to(p_x , p_y+5);
812
cr->set_source_rgba(1.00, 0.00, 0.00, 1.00);
813
} else if (p_state == 0) {
814
cr->set_source_rgba(0.75, 0.75, 0.75, 1.00);
815
} else if (p_state == 2) {
816
cr->set_source_rgba(0.00, 0.00, 1.00, 1.00);
820
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
821
cr->set_line_width(0.5);
822
cr->set_line_cap(Cairo::LINE_CAP_ROUND);
826
void KageStage::renderNodeControl(double p_x, double p_y, bool p_selected) {
827
cr->set_line_width(1.0);
828
cr->arc(p_x, p_y, 3, 0, 2 * M_PI);
830
if (p_selected == true) {
831
cr->set_source_rgba(1.0,0.0,0.0,1.0);
834
cr->set_source_rgba(1.0,1.0,1.0,1.0);
838
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
842
bool KageStage::isSelectionBoxNormalized() {
843
if (selectionBox1.x <= selectionBox2.x && selectionBox1.y <= selectionBox2.y) {
848
void KageStage::normalizeSelectionBox() {
849
if (isSelectionBoxNormalized() == true) {
856
if (selectionBox1.x < selectionBox2.x) {
857
l_x1 = selectionBox1.x;
858
l_x2 = selectionBox2.x;
860
l_x1 = selectionBox2.x;
861
l_x2 = selectionBox1.x;
863
if (selectionBox1.y < selectionBox2.y) {
864
l_y1 = selectionBox1.y;
865
l_y2 = selectionBox2.y;
867
l_y1 = selectionBox2.y;
868
l_y2 = selectionBox1.y;
871
selectionBox1.x = l_x1;
872
selectionBox1.y = l_y1;
873
selectionBox2.x = l_x2;
874
selectionBox2.y = l_y2;
876
bool KageStage::isNodeOnSelectionBox(double p_nodeX, double p_nodeY) {
877
normalizeSelectionBox();
879
if (selectionBox1.x <= p_nodeX && selectionBox2.x >= p_nodeX
880
&& selectionBox1.y <= p_nodeY && selectionBox2.y >= p_nodeY) {
885
bool KageStage::isMouseOnNode(double p_x, double p_y, unsigned int p_buffer) {
886
if (p_x-p_buffer <= draw1.x && p_x+p_buffer >= draw1.x
887
&& p_y-p_buffer <= draw1.y && p_y+p_buffer >= draw1.y) {
893
bool KageStage::deselectSelectedNodes() {
895
std::cout << " KageStage::deselectSelectedNodes " << selectedNodes.size() << std::endl;
897
if (selectedNodes.size() == 0) {
902
win->propStageSetVisible(true);
903
win->propNodeXYSetVisible(false);
908
bool KageStage::deleteSelectedNodes() {
909
if (win->isLayerLocked() == true) {
912
bool l_return = false;
914
if (selectedNodes.size() == 0) {
919
std::cout << " KageStage::deleteSelectedNodes " << selectedNodes.size() << endl;
921
sort(selectedNodes.begin(), selectedNodes.end(), greater <unsigned int>());
923
for (unsigned int l_selectedNode = 0; l_selectedNode < selectedNodes.size(); ++l_selectedNode) {
925
std::cout << " KageStage::deleteSelectedNodes " << l_selectedNode << " " << selectedNodes.size() << endl;
926
l_return = deleteSelectedNode(selectedNodes[l_selectedNode]);
929
selectedNodes.clear();
931
if (l_return == true) {
937
bool KageStage::deleteSelectedNode(unsigned int p_index) {
938
if (win->isLayerLocked() == true) {
941
vector<VectorData> v = win->getFrameData().getVectorData();
943
selectedShape = getSelectedShapeViaNode(p_index, v);
945
//avoid deletion of selectedNode as non-Curve/Line; ex: selectedNode is Move
946
if (selectedShape == _NO_SELECTION
947
|| (v[p_index].vectorType != VectorData::TYPE_CURVE_CUBIC
948
&& v[p_index].vectorType != VectorData::TYPE_CURVE_QUADRATIC
949
&& v[p_index].vectorType != VectorData::TYPE_LINE)) {
953
unsigned int l_sequence = 0;
954
bool l_closepath = false;
956
if (v[selectedShape + 0].vectorType == VectorData::TYPE_INIT ) ++l_sequence;
957
if (v[selectedShape + 1].vectorType == VectorData::TYPE_FILL ) ++l_sequence;
958
if (v[selectedShape + 2].vectorType == VectorData::TYPE_STROKE ) ++l_sequence;
959
if (v[selectedShape + 3].vectorType == VectorData::TYPE_MOVE ) ++l_sequence;
960
if (v[selectedShape + 4].vectorType == VectorData::TYPE_CURVE_CUBIC
961
|| v[selectedShape + 4].vectorType == VectorData::TYPE_CURVE_QUADRATIC
962
|| v[selectedShape + 4].vectorType == VectorData::TYPE_LINE) {
965
if (v[selectedShape + 5].vectorType == VectorData::TYPE_CLOSE_PATH ) {
968
if (v[selectedShape + 6].vectorType == VectorData::TYPE_ENDFILL) {
971
} else if (v[selectedShape + 5].vectorType == VectorData::TYPE_ENDFILL) {
976
if (l_sequence == 6 && l_closepath == false) {
977
v.erase (v.begin() + selectedShape,
978
v.begin() + selectedShape + l_sequence);
980
cout << " DELETE A " << endl;
981
// selectedShapes.erase(selectedShapes.begin() + l_selectedShape);
982
} else if (l_sequence == 7 && l_closepath == true) {
983
v.erase (v.begin() + selectedShape,
984
v.begin() + selectedShape + l_sequence);
986
cout << " DELETE B " << endl;
987
// selectedShapes.erase(selectedShapes.begin() + l_selectedShape);
989
if (v[p_index-1].vectorType != VectorData::TYPE_MOVE &&
990
(v[p_index+1].vectorType == VectorData::TYPE_ENDFILL ||
991
v[p_index+1].vectorType == VectorData::TYPE_CLOSE_PATH)) {
992
for (unsigned int i = p_index; i > 0; --i) {
993
if (v[i].vectorType == VectorData::TYPE_MOVE) {
994
v[i+1].points[0].x = v[p_index].points[0].x;
995
v[i+1].points[0].y = v[p_index].points[0].y;
996
v[i].points[0].x = v[p_index-1].points[2].x;
997
v[i].points[0].y = v[p_index-1].points[2].y;
1002
v[p_index+1].points[0].x = v[p_index].points[0].x;
1003
v[p_index+1].points[0].y = v[p_index].points[0].y;
1005
cout << " DELETE C " << endl;
1007
v.erase (v.begin() + p_index);
1010
win->setFrameData(v);
1015
bool KageStage::toggleLineSelectedNodes() {
1016
vector<VectorData> v = win->getFrameData().getVectorData();
1018
unsigned int nsize = selectedNodes.size();
1020
bool l_gotit = false;
1021
unsigned int l_currentNode;
1022
unsigned int l_nextNode;
1023
for (unsigned int i = 0; i < nsize; ++i) {
1024
l_currentNode = selectedNodes[i];
1025
l_nextNode = l_currentNode+1;
1026
if (l_currentNode < v.size()
1027
&& isSelectedNode(l_nextNode) == true) {
1028
if ( (v[l_nextNode ].vectorType == VectorData::TYPE_CURVE_CUBIC || v[l_nextNode ].vectorType == VectorData::TYPE_CURVE_QUADRATIC)
1029
&& (v[l_currentNode].vectorType == VectorData::TYPE_CURVE_CUBIC || v[l_currentNode].vectorType == VectorData::TYPE_CURVE_QUADRATIC)) {
1030
v[l_nextNode].points[0].x = (v[l_currentNode].points[2].x + v[l_nextNode].points[2].x) / 2;
1031
v[l_nextNode].points[0].y = (v[l_currentNode].points[2].y + v[l_nextNode].points[2].y) / 2;
1033
v[l_nextNode].points[1].x = v[l_nextNode].points[0].x;
1034
v[l_nextNode].points[1].y = v[l_nextNode].points[0].y;
1037
} else if (v[l_nextNode].vectorType == VectorData::TYPE_CLOSE_PATH) {
1038
//The user just selected the very end of an enclosed shape and the very first node
1039
//so, search for very first curve/line if also currently selected
1040
for (unsigned int l_firstNode = l_currentNode-1; l_firstNode > 0; --l_firstNode) {
1041
if (v[l_firstNode].vectorType == VectorData::TYPE_MOVE) {
1043
if (isSelectedNode(l_firstNode) == true) {
1044
if ( (v[l_firstNode ].vectorType == VectorData::TYPE_CURVE_CUBIC || v[l_firstNode ].vectorType == VectorData::TYPE_CURVE_QUADRATIC)
1045
&& (v[l_currentNode].vectorType == VectorData::TYPE_CURVE_CUBIC || v[l_currentNode].vectorType == VectorData::TYPE_CURVE_QUADRATIC)) {
1046
v[l_firstNode].points[0].x = (v[l_currentNode].points[2].x + v[l_firstNode].points[2].x) / 2;
1047
v[l_firstNode].points[0].y = (v[l_currentNode].points[2].y + v[l_firstNode].points[2].y) / 2;
1049
v[l_firstNode].points[1].x = v[l_firstNode].points[0].x;
1050
v[l_firstNode].points[1].y = v[l_firstNode].points[0].y;
1060
if (l_gotit == true) {
1061
win->setFrameData(v);
1069
void KageStage::updateNodeXY() {
1070
unsigned int nsize = selectedNodes.size();
1074
nodeIndexX = UINT_MAX;
1075
nodeIndexY = UINT_MAX;
1079
vector<VectorData> v = win->getFrameData().getVectorData();
1080
unsigned int vsize = v.size();
1081
for (unsigned int i = 0; i < nsize; ++i) {
1082
for (unsigned int j = i; j < vsize; ++j) {
1083
if (isSelectedNode(j) == true) {
1084
if ( v[j].vectorType == VectorData::TYPE_CURVE_QUADRATIC
1085
|| v[j].vectorType == VectorData::TYPE_CURVE_CUBIC) {
1086
if (v[j].points[2].x < nodeX) {
1087
nodeX = v[j].points[2].x;
1090
if (v[j].points[2].y < nodeY) {
1091
nodeY = v[j].points[2].y;
1094
} else if (v[j].vectorType == VectorData::TYPE_INIT
1095
&& j != selectedShapes[i]) {
1101
if (nodeX == DBL_MAX) {
1103
nodeIndexX = UINT_MAX;
1105
if (nodeY == DBL_MAX) {
1107
nodeIndexY = UINT_MAX;
1110
win->propNodeXYSetVisible(true);