31 C4ConsoleQtShape::C4ConsoleQtShape(
C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
32 : is_relative(true), dragging_border(-1), selected_border(-1), border_color(0xffff0000), parent_delegate(parent_delegate), shape_list(shape_list)
34 rel_obj.SetPropList(for_obj);
43 uint32_t C4ConsoleQtShape::GetBorderColor(int32_t border_index,
bool dragging_border_is_bitmask, uint32_t default_color)
const
47 if ((dragging_border == border_index) || (dragging_border_is_bitmask && (dragging_border & border_index)))
49 return default_color ? default_color : border_color;
52 int32_t C4ConsoleQtShape::AbsX(int32_t rel_x)
const
57 if (obj) rel_x += obj->
GetX();
62 int32_t C4ConsoleQtShape::AbsY(int32_t rel_y)
const
67 if (obj) rel_y += obj->
GetY();
72 void C4ConsoleQtShape::StopDragging()
79 bool C4ConsoleQtShape::Select(int32_t border)
81 selected_border = border;
82 emit BorderSelectionChanged();
86 void C4ConsoleQtShape::ResetSelection()
89 emit BorderSelectionChanged();
95 C4ConsoleQtRect::C4ConsoleQtRect(
C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
96 : C4ConsoleQtShape(for_obj, props, parent_delegate, shape_list),
left(0),
top(0),
right(10),
bottom(10), store_as_proplist(false), properties_lowercase(false)
105 properties_lowercase = store_as_proplist =
true;
107 store_as_proplist =
true;
112 bool C4ConsoleQtRect::IsHit(int32_t x, int32_t y, int32_t hit_range, Qt::CursorShape *drag_cursor, int32_t *drag_border,
bool shift_down,
bool ctrl_down)
115 int32_t
left = AbsX(this->left),
top = AbsY(this->
top);
118 int32_t dleft = Abs<int32_t>(
left - x);
119 int32_t dtop = Abs<int32_t>(
top - y);
120 int32_t dright = Abs<int32_t>(
right - x);
121 int32_t dbottom = Abs<int32_t>(
bottom - y);
123 if (x <
left - hit_range || y < top - hit_range || x >
right + hit_range || y >
bottom + hit_range)
126 bool hit_left = (dleft <= hit_range && dleft < dright);
127 bool hit_top = (dtop <= hit_range && dtop < dbottom);
128 bool hit_right = (!hit_left && dright <= hit_range);
129 bool hit_bottom = (!hit_top && dbottom <= hit_range);
132 if (idrag_border) *drag_border = idrag_border;
133 if (hit_left || hit_right)
134 if (hit_top || hit_bottom)
135 *drag_cursor = (hit_left == hit_top) ? Qt::SizeFDiagCursor : Qt::SizeBDiagCursor;
137 *drag_cursor = Qt::SizeHorCursor;
138 else if (hit_top || hit_bottom)
139 *drag_cursor = Qt::SizeVerCursor;
140 return !!idrag_border;
143 void C4ConsoleQtRect::Draw(
class C4TargetFacet &cgo,
float line_width)
145 float left = float(AbsX(this->left)) + cgo.
X - cgo.
TargetX;
146 float top = float(AbsY(this->top)) + cgo.
Y - cgo.
TargetY;
147 float right = float(AbsX(this->right)) + cgo.
X - cgo.
TargetX;
155 void C4ConsoleQtRect::Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor)
165 void C4ConsoleQtRect::SetValue(
const C4Value &val)
168 if (store_as_proplist)
182 if (varr && varr->
GetSize() >= 4)
192 C4Value C4ConsoleQtRect::GetValue()
const
195 if (store_as_proplist)
218 C4ConsoleQtCircle::C4ConsoleQtCircle(
class C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
219 : C4ConsoleQtShape(for_obj, props, parent_delegate, shape_list), radius(10), cx(0), cy(0), can_move_center(false)
227 bool C4ConsoleQtCircle::IsHit(int32_t x, int32_t y, int32_t hit_range, Qt::CursorShape *drag_cursor, int32_t *drag_border,
bool shift_down,
bool ctrl_down)
232 int32_t r = x*x + y*y;
234 if (Inside<int32_t>(r, (radius - hit_range)*(radius - hit_range), (radius + hit_range)*(radius + hit_range)))
237 if (x * 58 / 100 / (y+!y))
238 *drag_cursor = Qt::CursorShape::SizeHorCursor;
239 else if (y * 58 / 100 / (x+!x))
240 *drag_cursor = Qt::CursorShape::SizeVerCursor;
242 *drag_cursor = Qt::CursorShape::SizeFDiagCursor;
244 *drag_cursor = Qt::CursorShape::SizeBDiagCursor;
249 if (can_move_center && r <= hit_range*hit_range)
251 *drag_cursor = Qt::CursorShape::SizeAllCursor;
258 void C4ConsoleQtCircle::Draw(
class C4TargetFacet &cgo,
float line_width)
267 void C4ConsoleQtCircle::C4ConsoleQtCircle::Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor)
269 if (dragging_border == 0)
273 radius = int32_t(sqrt(
double(x*x + y*y)));
275 else if (dragging_border == 1)
282 void C4ConsoleQtCircle::SetValue(
const C4Value &val)
289 if (aval && aval->
GetSize() == 3)
302 C4Value C4ConsoleQtCircle::GetValue()
const
322 C4ConsoleQtPoint::C4ConsoleQtPoint(
class C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
323 : C4ConsoleQtShape(for_obj, props, parent_delegate, shape_list), cx(0), cy(0)
332 bool C4ConsoleQtPoint::IsHit(int32_t x, int32_t y, int32_t hit_range, Qt::CursorShape *drag_cursor, int32_t *drag_border,
bool shift_down,
bool ctrl_down)
337 int32_t r = x*x + y*y;
339 if (r <= hit_range*hit_range*6)
341 if (horizontal_fix && vertical_fix) *drag_cursor = Qt::CursorShape::ForbiddenCursor;
342 if (horizontal_fix && !vertical_fix) *drag_cursor = Qt::CursorShape::SizeVerCursor;
343 if (!horizontal_fix && vertical_fix) *drag_cursor = Qt::CursorShape::SizeHorCursor;
344 if (!horizontal_fix && !vertical_fix) *drag_cursor = Qt::CursorShape::SizeAllCursor;
351 void C4ConsoleQtPoint::Draw(
class C4TargetFacet &cgo,
float line_width)
354 uint32_t clr = GetBorderColor(0,
false);
355 float d = line_width * 3;
356 float dc = sqrtf(2) * d;
357 int32_t x = AbsX(cx) + cgo.
X - cgo.
TargetX;
358 int32_t y = AbsY(cy) + cgo.
Y - cgo.
TargetY;
359 if (horizontal_fix && !vertical_fix)
365 else if (!horizontal_fix && vertical_fix)
382 void C4ConsoleQtPoint::Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor)
384 if (!horizontal_fix) cx += dx;
385 if (!vertical_fix) cy += dy;
388 void C4ConsoleQtPoint::SetValue(
const C4Value &val)
392 if (aval && aval->
GetSize() == 2)
399 C4Value C4ConsoleQtPoint::GetValue()
const
411 bool C4ConsoleQtGraph::Edge::connects_to(int32_t vertex_index)
const
414 return vertex_indices[0] == vertex_index || vertex_indices[1] == vertex_index;
417 bool C4ConsoleQtGraph::Edge::connects_to(int32_t vertex_index, int32_t *idx)
const
421 if (vertex_indices[0] == vertex_index)
425 else if (vertex_indices[1] == vertex_index)
437 void C4ConsoleQtGraph::GraphData::SetVerticesValue(
const C4ValueArray *vvertices)
442 vertices.reserve(vvertices->
GetSize());
443 for (int32_t i = 0; i < vvertices->
GetSize(); ++i)
447 if (!vvertex)
continue;
451 vertices.push_back(vtx);
456 void C4ConsoleQtGraph::GraphData::SetEdgesValue(
const C4ValueArray *vedges)
461 edges.reserve(vedges->
GetSize());
462 for (int32_t i = 0; i < vedges->
GetSize(); ++i)
471 if (vedgevertices && vedgevertices->
GetSize() >= 2)
477 if (edge.vertex_indices[0] < 0 || edge.vertex_indices[1] < 0)
continue;
478 if (edge.vertex_indices[0] >= vertices.size() || edge.vertex_indices[1] >= vertices.size())
continue;
482 edges.push_back(edge);
488 C4ValueArray *C4ConsoleQtGraph::GraphData::GetVerticesValue()
const
492 vvertices->
SetSize(vertices.size());
494 for (
const Vertex &vtx : vertices)
506 C4ValueArray *C4ConsoleQtGraph::GraphData::GetEdgesValue()
const
511 for (
const Edge &edge : edges)
526 void C4ConsoleQtGraph::GraphData::SetVertexPos(int32_t vertex_index, int32_t new_x, int32_t new_y)
529 if (vertex_index < 0 || vertex_index >= vertices.size())
return;
531 vertices[vertex_index].x = new_x;
532 vertices[vertex_index].y = new_y;
535 void C4ConsoleQtGraph::GraphData::EditEdge(int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex_index)
538 if (edge_index < 0 || edge_index >= edges.size())
return;
539 if (new_vertex_index < 0 || new_vertex_index >= vertices.size())
return;
540 if (change_vertex_index < 0 || change_vertex_index > 1)
return;
542 Edge &edge = edges[edge_index];
543 int32_t other_vertex_index = edge.vertex_indices[!change_vertex_index];
544 if (new_vertex_index == other_vertex_index)
return;
546 for (Edge &check_edge : edges)
548 if (&check_edge != &edge)
550 if (check_edge.connects_to(new_vertex_index) && check_edge.connects_to(other_vertex_index))
return;
554 edge.vertex_indices[change_vertex_index] = new_vertex_index;
557 void C4ConsoleQtGraph::GraphData::InsertEdgeBefore(int32_t insert_edge_index, int32_t vertex1, int32_t vertex2)
560 if (insert_edge_index < 0 || insert_edge_index > edges.size())
return;
561 if (vertex1 < 0 || vertex1 >= vertices.size())
return;
562 if (vertex2 < 0 || vertex2 >= vertices.size())
return;
564 for (Edge &check_edge : edges)
566 if (check_edge.connects_to(vertex1) && check_edge.connects_to(vertex2))
return;
570 new_edge.vertex_indices[0] = vertex1;
571 new_edge.vertex_indices[1] = vertex2;
572 edges.insert(edges.begin() + insert_edge_index, new_edge);
575 void C4ConsoleQtGraph::GraphData::InsertVertexBefore(int32_t insert_vertex_index, int32_t x, int32_t y)
578 if (insert_vertex_index < 0 || insert_vertex_index > vertices.size())
return;
583 vertices.insert(vertices.begin() + insert_vertex_index, new_vertex);
585 for (Edge &edge : edges)
587 for (int32_t &vertex_index : edge.vertex_indices)
589 if (vertex_index >= insert_vertex_index)
597 void C4ConsoleQtGraph::GraphData::RemoveEdge(int32_t edge_index)
600 if (edge_index < 0 || edge_index >= edges.size())
return;
602 edges.erase(edges.begin() + edge_index);
605 void C4ConsoleQtGraph::GraphData::RemoveVertex(int32_t remove_vertex_index)
608 if (remove_vertex_index < 0 || remove_vertex_index >= vertices.size())
return;
610 if (vertices.size() == 1)
return;
611 assert(remove_vertex_index >= 0 && remove_vertex_index < vertices.size() && vertices.size() >= 2);
613 auto rm_check = [remove_vertex_index](
const Edge &edge) {
return edge.connects_to(remove_vertex_index); };
614 edges.erase(std::remove_if(edges.begin(), edges.end(), rm_check), edges.end());
616 vertices.erase(vertices.begin() + remove_vertex_index);
618 for (Edge &edge : edges)
620 for (int32_t &vi : edge.vertex_indices)
622 if (vi > remove_vertex_index)
630 int32_t C4ConsoleQtGraph::GraphData::GetEdgeCountForVertex(int32_t vertex_index)
const
633 auto count_check = [vertex_index](
const Edge &edge) {
return edge.connects_to(vertex_index); };
634 return std::count_if(edges.begin(), edges.end(), count_check);
637 void C4ConsoleQtGraph::GraphData::EditGraphValue_SetVertexPos(
C4ValueArray *vvertices, int32_t vertex_index, int32_t new_x, int32_t new_y)
640 if (vertex_index < 0 || vertex_index >= vvertices->
GetSize())
return;
643 if (!vvertex || vvertex->
IsFrozen())
return;
648 void C4ConsoleQtGraph::GraphData::EditGraphValue_EditEdge(
C4ValueArray *vvertices,
C4ValueArray *vedges, int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex_index)
651 if (edge_index < 0 || edge_index >= vedges->
GetSize())
return;
652 if (new_vertex_index < 0 || new_vertex_index >= vvertices->
GetSize())
return;
653 if (change_vertex_index < 0 || change_vertex_index > 1)
return;
657 if (!edge_vertices || edge_vertices->
IsFrozen())
return;
659 int32_t other_vertex_index = edge_vertices->
GetItem(!change_vertex_index).
getInt();
660 if (new_vertex_index == other_vertex_index)
return;
662 for (int32_t i = 0; i < vedges->
GetSize(); ++i)
673 edge_vertices->
SetItem(change_vertex_index,
C4VInt(new_vertex_index));
676 void C4ConsoleQtGraph::GraphData::EditGraphValue_InsertEdgeBefore(
C4ValueArray *vvertices,
C4ValueArray *vedges, int32_t insert_edge_index, int32_t vertex1, int32_t vertex2)
679 if (insert_edge_index < 0 || insert_edge_index > vedges->
GetSize())
return;
680 if (vertex1 < 0 || vertex1 >= vvertices->
GetSize())
return;
682 for (int32_t i = 0; i < vedges->
GetSize(); ++i)
697 for (int32_t i = vedges->
GetSize() - 1; i > insert_edge_index; --i)
704 void C4ConsoleQtGraph::GraphData::EditGraphValue_InsertVertexBefore(
C4ValueArray *vvertices,
C4ValueArray *vedges, int32_t insert_vertex_index, int32_t x, int32_t y)
707 if (insert_vertex_index < 0 || insert_vertex_index > vvertices->
GetSize())
return;
714 for (int32_t i = vvertices->
GetSize() - 1; i > insert_vertex_index; --i)
722 for (int32_t i = 0; i < vedges->
GetSize(); ++i)
728 if (edge_vertices && edge_vertices->
GetSize() >= 2)
730 for (int32_t j = 0; j < 2; ++j)
733 if (vertex_index >= insert_vertex_index)
744 void C4ConsoleQtGraph::GraphData::EditGraphValue_RemoveEdge(
C4ValueArray *vvertices,
C4ValueArray *vedges, int32_t edge_index)
747 if (edge_index < 0 || edge_index >= vedges->
GetSize())
return;
749 for (int32_t i = edge_index; i < vedges->
GetSize() - 1; ++i)
756 void C4ConsoleQtGraph::GraphData::EditGraphValue_RemoveVertex(
C4ValueArray *vvertices,
C4ValueArray *vedges, int32_t remove_vertex_index)
759 if (remove_vertex_index < 0 || remove_vertex_index >= vvertices->
GetSize())
return;
761 if (vvertices->
GetSize() == 1)
return;
763 for (int32_t i = remove_vertex_index; i < vvertices->
GetSize() - 1; ++i)
771 for (int32_t edge_index = vedges->
GetSize(); edge_index >= 0; --edge_index)
778 if (edge_vertices && edge_vertices->
GetSize() >= 2)
780 for (int32_t j = 0; j < 2; ++j)
783 if (v == remove_vertex_index)
785 EditGraphValue_RemoveEdge(vvertices, vedges, edge_index);
788 else if (v > remove_vertex_index)
799 bool C4ConsoleQtGraph::GraphData::EditGraphValue_EdgeConnectsTo(
C4PropList *edge, int32_t vertex_index)
802 if (!edge)
return false;
804 if (!edge_vertices || edge_vertices->
GetSize() < 2)
return false;
809 C4ConsoleQtGraph::C4ConsoleQtGraph(
C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
810 : C4ConsoleQtShape(for_obj, props, parent_delegate, shape_list)
817 allow_vertex_selection = !!vertex_delegate.getPropList();
818 allow_edge_selection = !!edge_delegate.getPropList();
826 bool C4ConsoleQtGraph::IsHit(int32_t x, int32_t y, int32_t hit_range, Qt::CursorShape *drag_cursor, int32_t *drag_border,
bool shift_down,
bool ctrl_down)
829 int32_t i = 0, best_hit_range = hit_range*hit_range * 6*6;
830 bool has_hit =
false;
831 for (
const Vertex &vtx : graph.vertices)
833 int32_t dx = x - AbsX(vtx.x);
834 int32_t dy = y - AbsY(vtx.y);
835 int32_t r = dx*dx + dy*dy;
837 if (r <= best_hit_range)
839 if (IsVertexHit(i, drag_cursor, shift_down, ctrl_down))
841 *drag_border = VertexToDragBorder(i);
849 if (!has_hit && (allow_edge_selection || shift_down || ctrl_down))
851 best_hit_range = hit_range*hit_range;
853 for (
const Edge &edge : graph.edges)
856 assert(edge.vertex_indices[0] >= 0 && edge.vertex_indices[1] >= 0);
857 assert(edge.vertex_indices[0] < graph.vertices.size() && edge.vertex_indices[1] < graph.vertices.size());
858 const Vertex &v0 = graph.vertices[edge.vertex_indices[0]];
859 const Vertex &v1 = graph.vertices[edge.vertex_indices[1]];
861 int32_t dx0 = x - AbsX(v0.x);
862 int32_t dy0 = y - AbsY(v0.y);
863 int32_t dx1 = v1.x - v0.x;
864 int32_t dy1 = v1.y - v0.y;
866 int32_t d = dx0 * dx1 + dy0 * dy1;
867 if (d > 0 && d < dx1 * dx1 + dy1 * dy1)
870 d = dx1 * dy0 - dy1 * dx0;
871 d = d * d / (dx1 * dx1 + dy1 * dy1);
873 if (d <= best_hit_range)
875 if (IsEdgeHit(i, drag_cursor, shift_down, ctrl_down))
876 *drag_border = EdgeToDragBorder(i);
885 if (has_hit && (shift_down || ctrl_down) && structure_fix)
887 *drag_cursor = Qt::CursorShape::ForbiddenCursor;
889 else if (*drag_cursor == Qt::CursorShape::SizeAllCursor)
892 if (horizontal_fix && vertical_fix)
894 *drag_cursor = Qt::CursorShape::PointingHandCursor;
896 else if (horizontal_fix)
898 *drag_cursor = Qt::CursorShape::SizeVerCursor;
900 else if (vertical_fix)
902 *drag_cursor = Qt::CursorShape::SizeHorCursor;
908 bool C4ConsoleQtGraph::IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor,
bool shift_down,
bool ctrl_down)
910 if (shift_down && !ctrl_down)
913 *drag_cursor = Qt::CursorShape::DragCopyCursor;
915 else if (ctrl_down && !shift_down)
918 if (graph.vertices.size() == 1)
920 *drag_cursor = Qt::CursorShape::ForbiddenCursor;
924 *drag_cursor = Qt::CursorShape::DragMoveCursor;
930 *drag_cursor = Qt::CursorShape::SizeAllCursor;
935 bool C4ConsoleQtGraph::IsEdgeHit(int32_t edge_index, Qt::CursorShape *drag_cursor,
bool shift_down,
bool ctrl_down)
937 if (shift_down && !ctrl_down)
940 *drag_cursor = Qt::CursorShape::DragCopyCursor;
942 else if (ctrl_down && !shift_down)
945 *drag_cursor = Qt::CursorShape::DragMoveCursor;
947 else if (allow_edge_selection)
950 *drag_cursor = Qt::CursorShape::PointingHandCursor;
960 void C4ConsoleQtGraph::DrawEdge(
class C4TargetFacet &cgo,
const Vertex &v0,
const Vertex &v1, uint32_t clr,
float line_width,
float edge_width,
bool highlight)
962 float vx0 = AbsX(v0.x) + cgo.
X - cgo.
TargetX;
963 float vy0 = AbsY(v0.y) + cgo.
Y - cgo.
TargetY;
964 float vx1 = AbsX(v1.x) + cgo.
X - cgo.
TargetX;
965 float vy1 = AbsY(v1.y) + cgo.
Y - cgo.
TargetY;
966 float dx = v1.x - v0.x, dy = v1.y - v0.y;
967 float d = sqrt(dx*dx + dy*dy);
971 float ddx = dy / d * edge_width;
972 float ddy = dx / d * edge_width;
982 float d_vtx = std::min<float>(d, line_width * 3 * sqrtf(2));
983 float arrx = vx1 - dx / d * d_vtx;
984 float arry = vy1 - dy / d * d_vtx;
985 float arrowhead_size = std::max<float>(2.0, std::min<float>(d / 2, 8.0)) * edge_width;
986 float ddx1 = (-dy / 2 - dx);
987 float ddy1 = (+dx / 2 - dy);
988 float d1 = sqrt(ddx1*ddx1 + ddy1*ddy1);
989 float ddx2 = (+dy / 2 - dx);
990 float ddy2 = (-dx / 2 - dy);
991 float d2 = sqrt(ddx2*ddx2 + ddy2*ddy2);
992 pDraw->
DrawLineDw(cgo.
Surface, arrx, arry, arrx + ddx1 * arrowhead_size / d1, arry + ddy1 * arrowhead_size / d1, clr, edge_width);
993 pDraw->
DrawLineDw(cgo.
Surface, arrx, arry, arrx + ddx2 * arrowhead_size / d2, arry + ddy2 * arrowhead_size / d2, clr, edge_width);
997 void C4ConsoleQtGraph::Draw(
class C4TargetFacet &cgo,
float line_width)
1001 for (
const Edge &edge : graph.edges)
1003 uint32_t clr = GetBorderColor(EdgeToDragBorder(i),
false, edge.color);
1004 assert(edge.vertex_indices[0] >= 0 && edge.vertex_indices[1] >= 0);
1005 assert(edge.vertex_indices[0] < graph.vertices.size() && edge.vertex_indices[1] < graph.vertices.size());
1006 const Vertex &v0 = graph.vertices[edge.vertex_indices[0]];
1007 const Vertex &v1 = graph.vertices[edge.vertex_indices[1]];
1008 float edge_width = line_width * edge.line_thickness;
1009 bool highlight = (IsEdgeDrag(selected_border) && DragBorderToEdge(selected_border) == i);
1010 DrawEdge(cgo, v0, v1, clr, line_width, edge_width, highlight);
1015 for (
const Vertex &vtx : graph.vertices)
1017 uint32_t clr = GetBorderColor(VertexToDragBorder(i),
false, vtx.color);
1018 float d = line_width * 3;
1019 float dc = sqrtf(2) * d;
1020 int32_t x = AbsX(vtx.x) + cgo.
X - cgo.
TargetX;
1021 int32_t y = AbsY(vtx.y) + cgo.
Y - cgo.
TargetY;
1025 if (IsVertexDrag(selected_border) && DragBorderToVertex(selected_border) == i)
1035 bool C4ConsoleQtGraph::StartDragging(int32_t *border, int32_t x, int32_t y,
bool shift_down,
bool ctrl_down)
1037 assert(*border != -1);
1038 drag_snap_offset_x = drag_snap_offset_y = 0;
1039 drag_snapped =
false;
1040 drag_snap_vertex = -1;
1041 drag_source_vertex_index = -1;
1042 if (shift_down && !ctrl_down && !structure_fix)
1045 if (IsEdgeDrag(*border))
1048 *border = dragging_border = VertexToDragBorder(InsertVertexOnEdge(DragBorderToEdge(*border), x - AbsX(), y - AbsY()));
1053 drag_source_vertex_index = DragBorderToVertex(*border);
1054 *border = dragging_border = VertexToDragBorder(InsertVertexOnVertex(drag_source_vertex_index, x - AbsX(), y - AbsY()));
1059 else if (ctrl_down && !shift_down && !structure_fix)
1062 if (IsEdgeDrag(*border))
1065 RemoveEdge(DragBorderToEdge(*border));
1071 if (graph.vertices.size() > 1) RemoveVertex(DragBorderToVertex(*border),
true);
1074 emit ShapeDragged();
1079 else if (!shift_down && !ctrl_down)
1082 if (IsVertexDrag(*border))
1084 return C4ConsoleQtShape::StartDragging(border, x, y, shift_down, ctrl_down);
1099 void C4ConsoleQtGraph::Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor)
1102 if (IsVertexDrag(dragging_border) && DragBorderToVertex(dragging_border) < graph.vertices.size())
1104 int32_t dragged_vertex_index = DragBorderToVertex(dragging_border);
1105 Vertex &dragged_vertex = graph.vertices[dragged_vertex_index];
1107 dx -= drag_snap_offset_x;
1108 dy -= drag_snap_offset_y;
1109 if (!horizontal_fix) dragged_vertex.x += dx;
1110 if (!vertical_fix) dragged_vertex.y += dy;
1112 if (!IsPolyline() && !structure_fix)
1115 drag_snap_vertex = -1;
1116 int32_t best_hit_range_sq = hit_range * hit_range * 4;
1117 for (Vertex &check_vertex : graph.vertices)
1119 if (i != dragged_vertex_index && i != drag_source_vertex_index)
1121 int32_t cdx = check_vertex.x - dragged_vertex.x - dx;
1122 int32_t cdy = check_vertex.y - dragged_vertex.y - dy;
1123 int32_t cdsq = cdx*cdx + cdy*cdy;
1124 if (cdsq <= best_hit_range_sq)
1126 drag_snap_vertex = i;
1127 best_hit_range_sq = cdsq;
1133 drag_snapped = (drag_snap_vertex >= 0);
1136 drag_snap_offset_x = graph.vertices[drag_snap_vertex].x - dragged_vertex.x;
1137 drag_snap_offset_y = graph.vertices[drag_snap_vertex].y - dragged_vertex.y;
1138 dragged_vertex.x += drag_snap_offset_x;
1139 dragged_vertex.y += drag_snap_offset_y;
1140 *drag_cursor = Qt::CursorShape::DragMoveCursor;
1144 drag_snap_offset_x = drag_snap_offset_y = 0;
1145 *drag_cursor = Qt::CursorShape::SizeAllCursor;
1149 EditGraph(
true, C4ControlEditGraph::Action::CEG_SetVertexPos, dragged_vertex_index, dragged_vertex.x, dragged_vertex.y);
1153 void C4ConsoleQtGraph::StopDragging()
1156 if (IsVertexDrag(dragging_border))
1158 int32_t dragged_vertex = DragBorderToVertex(dragging_border);
1161 if (dragged_vertex && dragged_vertex != drag_snap_vertex)
1165 std::set<int32_t> vertices_connected_to_snap_vertex;
1167 for (Edge &edge : graph.edges)
1169 if (edge.connects_to(drag_snap_vertex, &idx))
1171 vertices_connected_to_snap_vertex.insert(edge.vertex_indices[!idx]);
1175 vertices_connected_to_snap_vertex.insert(drag_snap_vertex);
1178 for (Edge &edge : graph.edges)
1180 if (edge.connects_to(dragged_vertex, &idx))
1182 if (!vertices_connected_to_snap_vertex.count(edge.vertex_indices[!idx]))
1184 EditEdge(i_edge, idx, drag_snap_vertex);
1190 RemoveVertex(dragged_vertex,
false);
1195 EditGraph(
true, C4ControlEditGraph::Action::CEG_SetVertexPos, dragged_vertex, graph.vertices[dragged_vertex].x, graph.vertices[dragged_vertex].y);
1197 drag_snapped =
false;
1199 C4ConsoleQtShape::StopDragging();
1202 void C4ConsoleQtGraph::SetValue(
const C4Value &val)
1215 C4Value C4ConsoleQtGraph::GetValue()
const
1226 void C4ConsoleQtGraph::EditEdge(int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex)
1228 EditGraph(
true, C4ControlEditGraph::Action::CEG_EditEdge, edge_index, change_vertex_index, new_vertex);
1231 int32_t C4ConsoleQtGraph::AddVertex(int32_t new_x, int32_t new_y)
1233 EditGraph(
true, C4ControlEditGraph::Action::CEG_InsertVertex, graph.vertices.size(), new_x, new_y);
1234 return graph.vertices.size() - 1;
1237 int32_t C4ConsoleQtGraph::AddEdge(int32_t connect_vertex_index_1, int32_t connect_vertex_index_2)
1239 EditGraph(
true, C4ControlEditGraph::Action::CEG_InsertEdge, graph.edges.size(), connect_vertex_index_1, connect_vertex_index_2);
1240 return graph.edges.size() - 1;
1243 int32_t C4ConsoleQtGraph::InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y)
1245 assert(split_edge_index >= 0 && split_edge_index < graph.edges.size());
1247 int32_t new_vertex_index = AddVertex(x, y);
1248 AddEdge(new_vertex_index, graph.edges[split_edge_index].vertex_indices[1]);
1249 EditEdge(split_edge_index, 1, new_vertex_index);
1251 return new_vertex_index;
1254 int32_t C4ConsoleQtGraph::InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y)
1256 assert(target_vertex_index >= 0 && target_vertex_index < graph.vertices.size());
1258 int32_t new_vertex_index = AddVertex(x, y);
1260 AddEdge(target_vertex_index, new_vertex_index);
1262 return new_vertex_index;
1265 void C4ConsoleQtGraph::RemoveEdge(int32_t edge_index)
1267 assert(edge_index >= 0 && edge_index < graph.edges.size());
1269 Edge removed_edge = graph.edges[edge_index];
1270 EditGraph(
true, C4ControlEditGraph::Action::CEG_RemoveEdge, edge_index, 0, 0);
1272 if (!graph.GetEdgeCountForVertex(removed_edge.vertex_indices[0]))
1274 RemoveVertex(removed_edge.vertex_indices[0],
false);
1276 if (removed_edge.vertex_indices[1] > removed_edge.vertex_indices[0]) --removed_edge.vertex_indices[1];
1278 if (!graph.GetEdgeCountForVertex(removed_edge.vertex_indices[1]))
1281 RemoveVertex(removed_edge.vertex_indices[1],
false);
1285 void C4ConsoleQtGraph::RemoveVertex(int32_t remove_vertex_index,
bool create_skip_connection)
1287 assert(remove_vertex_index >= 0 && remove_vertex_index < graph.vertices.size());
1289 if (create_skip_connection && graph.GetEdgeCountForVertex(remove_vertex_index) == 2)
1291 Edge *combine_edge =
nullptr;
1293 for (Edge &edge : graph.edges)
1295 int32_t connect_idx;
1296 if (edge.connects_to(remove_vertex_index, &connect_idx))
1300 combine_edge = &edge;
1305 int32_t v = combine_edge->vertex_indices[combine_edge->vertex_indices[0] == remove_vertex_index];
1306 EditEdge(i, connect_idx, v);
1315 EditGraph(
true, C4ControlEditGraph::Action::CEG_RemoveVertex, remove_vertex_index, 0, 0);
1318 void C4ConsoleQtGraph::InsertVertexBefore(int32_t insert_vertex_index, int32_t x, int32_t y)
1321 EditGraph(
true, C4ControlEditGraph::Action::CEG_InsertVertex, insert_vertex_index, x, y);
1324 void C4ConsoleQtGraph::InsertEdgeBefore(int32_t insert_edge_index, int32_t connect_vertex_index_1, int32_t connect_vertex_index_2)
1327 EditGraph(
true, C4ControlEditGraph::Action::CEG_InsertEdge, insert_edge_index, connect_vertex_index_1, connect_vertex_index_2);
1330 bool C4ConsoleQtGraph::IsSelectionAllowed(int32_t border)
const
1333 if (IsVertexDrag(border))
return allow_vertex_selection;
1334 if (IsEdgeDrag(border))
return allow_edge_selection;
1343 int32_t selected_item = -1;
1345 if (IsVertexDrag(selected_border))
1347 selected_item = DragBorderToVertex(selected_border);
1348 delegate = vertex_delegate.getPropList();
1350 if (!shape_val_proplist)
return false;
1354 else if (IsEdgeDrag(selected_border))
1356 selected_item = DragBorderToEdge(selected_border);
1357 delegate = edge_delegate.getPropList();
1359 if (!shape_val_proplist)
return false;
1363 if (!delegate)
return false;
1365 if (!vitems || vitems->
GetSize() <= selected_item)
return false;
1367 if (!*shape_item_value)
return false;
1369 *shape_item_target_path =
C4PropertyPath(item_array_path, selected_item);
1373 if (!*shape_item_editorprops)
return false;
1383 case C4ControlEditGraph::Action::CEG_None:
1387 case C4ControlEditGraph::Action::CEG_SetVertexPos:
1388 graph.SetVertexPos(index, x, y);
1390 case C4ControlEditGraph::Action::CEG_EditEdge:
1391 graph.EditEdge(index, x, y);
1393 case C4ControlEditGraph::Action::CEG_InsertVertex:
1394 graph.InsertVertexBefore(index, x, y);
1396 case C4ControlEditGraph::Action::CEG_InsertEdge:
1397 graph.InsertEdgeBefore(index, x, y);
1399 case C4ControlEditGraph::Action::CEG_RemoveVertex:
1400 graph.RemoveVertex(index);
1402 case C4ControlEditGraph::Action::CEG_RemoveEdge:
1403 graph.RemoveEdge(index);
1410 emit GraphEdit(action, index, x, y);
1425 if (!vvertices || !vedges || vvertices->
IsFrozen() || vedges->
IsFrozen())
return;
1430 if (!vvertices || vvertices->
IsFrozen())
return;
1435 case C4ControlEditGraph::Action::CEG_None:
1439 case C4ControlEditGraph::Action::CEG_SetVertexPos:
1441 GraphData::EditGraphValue_SetVertexPos(vvertices, index, x, y);
1444 case C4ControlEditGraph::Action::CEG_EditEdge:
1448 GraphData::EditGraphValue_EditEdge(vvertices, vedges, index, x, y);
1452 case C4ControlEditGraph::Action::CEG_InsertVertex:
1454 GraphData::EditGraphValue_InsertVertexBefore(vvertices, vedges, index, x, y);
1457 case C4ControlEditGraph::Action::CEG_InsertEdge:
1461 GraphData::EditGraphValue_InsertEdgeBefore(vvertices, vedges, index, x, y);
1465 case C4ControlEditGraph::Action::CEG_RemoveVertex:
1467 GraphData::EditGraphValue_RemoveVertex(vvertices, vedges, index);
1470 case C4ControlEditGraph::Action::CEG_RemoveEdge:
1474 GraphData::EditGraphValue_RemoveEdge(vvertices, vedges, index);
1484 C4ConsoleQtPolyline::C4ConsoleQtPolyline(
class C4Object *for_obj,
C4PropList *props,
const class C4PropertyDelegateShape *parent_delegate,
class C4ConsoleQtShapes *shape_list)
1485 : C4ConsoleQtGraph(for_obj, props, parent_delegate, shape_list)
1493 void C4ConsoleQtPolyline::Draw(
class C4TargetFacet &cgo,
float line_width)
1496 if (start_from_object && graph.vertices.size())
1498 C4ConsoleQtGraph::Vertex v0;
1505 v0.x += obj->
GetX();
1506 v0.y += obj->
GetY();
1509 DrawEdge(cgo, v0, graph.vertices[0], border_color, line_width, line_width,
false);
1512 C4ConsoleQtGraph::Draw(cgo, line_width);
1515 void C4ConsoleQtPolyline::SetValue(
const C4Value &val)
1518 graph.SetVerticesValue(val.
getArray());
1520 graph.edges.clear();
1521 if (graph.vertices.size() >= 2)
1523 graph.edges.reserve(graph.vertices.size());
1524 for (int32_t i = 0; i < graph.vertices.size() - 1; ++i)
1527 edge.vertex_indices[0] = i;
1528 edge.vertex_indices[1] = i + 1;
1529 graph.edges.push_back(edge);
1534 C4Value C4ConsoleQtPolyline::GetValue()
const
1537 return C4VArray(graph.GetVerticesValue());
1540 int32_t C4ConsoleQtPolyline::InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y)
1543 InsertVertexBefore(split_edge_index + 1, x, y);
1544 InsertEdgeBefore(split_edge_index, split_edge_index, split_edge_index + 1);
1545 EditEdge(split_edge_index + 1, 0, split_edge_index + 1);
1546 return split_edge_index + 1;
1549 int32_t C4ConsoleQtPolyline::InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y)
1552 if (!target_vertex_index)
1554 InsertVertexBefore(0, x, y);
1555 InsertEdgeBefore(0, 0, 1);
1556 return target_vertex_index;
1558 else if (target_vertex_index == graph.vertices.size() - 1)
1560 InsertVertexBefore(target_vertex_index + 1, x, y);
1561 InsertEdgeBefore(target_vertex_index, target_vertex_index, target_vertex_index + 1);
1562 return target_vertex_index + 1;
1571 void C4ConsoleQtPolyline::RemoveEdge(int32_t edge_index)
1574 int32_t before_vertices = edge_index + 1;
1575 int32_t after_vertices = graph.edges.size() - edge_index;
1576 if (before_vertices > after_vertices)
1579 for (int32_t i = 0; i < after_vertices; ++i)
1581 RemoveVertex(graph.vertices.size()-1,
false);
1587 for (int32_t i = 0; i < before_vertices; ++i)
1589 RemoveVertex(0,
false);
1594 bool C4ConsoleQtPolyline::IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor,
bool shift_down,
bool ctrl_down)
1598 if (shift_down && !ctrl_down && vertex_index && vertex_index != graph.vertices.size()-1)
1602 return C4ConsoleQtGraph::IsVertexHit(vertex_index, drag_cursor, shift_down, ctrl_down);
1608 void C4ConsoleQtPolygon::SetValue(
const C4Value &val)
1611 C4ConsoleQtPolyline::SetValue(val);
1613 if (graph.vertices.size() > 2)
1616 edge.vertex_indices[0] = graph.vertices.size() - 1;
1617 edge.vertex_indices[1] = 0;
1618 graph.edges.push_back(edge);
1622 int32_t C4ConsoleQtPolygon::InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y)
1625 int32_t rval = C4ConsoleQtPolyline::InsertVertexOnEdge(split_edge_index, x, y);
1627 if (graph.vertices.size() == 3)
1634 int32_t C4ConsoleQtPolygon::InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y)
1641 void C4ConsoleQtPolygon::RemoveEdge(int32_t edge_index)
1644 Edge edge = graph.edges[edge_index];
1645 int32_t vertex_index = edge.vertex_indices[1];
1646 RemoveVertex(vertex_index,
true);
1647 if (graph.vertices.size() > 1)
1649 RemoveVertex(vertex_index ? edge.vertex_indices[0] : graph.vertices.size() - 1,
true);
1653 bool C4ConsoleQtPolygon::IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor,
bool shift_down,
bool ctrl_down)
1656 if (shift_down && !ctrl_down)
1661 return C4ConsoleQtGraph::IsVertexHit(vertex_index, drag_cursor, shift_down, ctrl_down);
1667 C4ConsoleQtShape *C4ConsoleQtShapes::CreateShape(
class C4Object *for_obj,
C4PropList *props,
const C4Value &val,
const class C4PropertyDelegateShape *parent_delegate)
1670 if (!
type)
return nullptr;
1671 C4ConsoleQtShape *shape =
nullptr;
1672 if (
type->GetData() ==
"rect") shape =
new C4ConsoleQtRect(for_obj, props, parent_delegate,
this);
1673 else if (
type->GetData() ==
"circle") shape =
new C4ConsoleQtCircle(for_obj, props, parent_delegate,
this);
1674 else if (
type->GetData() ==
"point") shape =
new C4ConsoleQtPoint(for_obj, props, parent_delegate,
this);
1675 else if (
type->GetData() ==
"graph") shape =
new C4ConsoleQtGraph(for_obj, props, parent_delegate,
this);
1676 else if (
type->GetData() ==
"polyline") shape =
new C4ConsoleQtPolyline(for_obj, props, parent_delegate,
this);
1677 else if (
type->GetData() ==
"polygon") shape =
new C4ConsoleQtPolygon(for_obj, props, parent_delegate,
this);
1678 shape->SetValue(val);
1682 void C4ConsoleQtShapes::AddShape(C4ConsoleQtShape *shape)
1684 if (shape) shapes.emplace_back(shape);
1687 void C4ConsoleQtShapes::RemoveShape(C4ConsoleQtShape *shape)
1690 shapes.remove_if([shape](
auto &it) {
return it.get() == shape; });
1691 if (dragging_shape == shape) dragging_shape =
nullptr;
1692 if (selected_shape == shape) selected_shape =
nullptr;
1695 void C4ConsoleQtShapes::ClearShapes()
1698 dragging_shape = selected_shape =
nullptr;
1699 drag_cursor = Qt::CursorShape::ArrowCursor;
1706 float line_width = std::max<float>(1.0f, 1.0f / cgo.
Zoom);
1707 for (
auto &shape : shapes) shape->Draw(cgo, line_width);
1710 bool C4ConsoleQtShapes::MouseDown(
float x,
float y,
float hit_range,
bool shift_down,
bool ctrl_down)
1713 int32_t hit_range_int = std::max(int32_t(hit_range + 0.5f), 1);
1715 if (dragging_shape) MouseUp(x, y, shift_down, ctrl_down);
1716 int32_t drag_border=-1;
1717 for (
auto &shape : shapes)
1719 if (shape->IsHit(x, y, hit_range_int, &drag_cursor, &drag_border, shift_down, ctrl_down))
1721 dragging_shape = shape.get();
1722 if (dragging_shape->StartDragging(&drag_border, int32_t(x), int32_t(y), shift_down, ctrl_down))
1730 dragging_shape =
nullptr;
1733 if (drag_border != -1)
1735 if (shape->IsSelectionAllowed(drag_border))
1737 SetSelectedShape(&*shape, drag_border);
1749 int32_t hit_range_int = std::max(int32_t(hit_range + 0.5f), 1);
1751 if (dragging_shape && left_down)
1753 int32_t dx = int32_t(round(x - drag_x)),
1754 dy = int32_t(round(y - drag_y));
1759 dragging_shape->Drag(drag_x, drag_y, dx, dy, hit_range_int, &drag_cursor);
1762 else if (!left_down)
1765 drag_cursor = Qt::CursorShape::ArrowCursor;
1767 for (
auto &shape : shapes)
if (shape->IsHit(x, y, hit_range_int, &drag_cursor, &ignored, shift_down, ctrl_down))
break;
1772 drag_cursor = Qt::CursorShape::ArrowCursor;
1776 void C4ConsoleQtShapes::MouseUp(
float x,
float y,
bool shift_down,
bool ctrl_down)
1781 dragging_shape->StopDragging();
1782 dragging_shape =
nullptr;
1783 drag_cursor = Qt::CursorShape::ArrowCursor;
1787 void C4ConsoleQtShapes::SetSelectedShape(C4ConsoleQtShape *new_selection, int32_t selected_border)
1790 if (selected_shape) selected_shape->ResetSelection();
1791 selected_shape = new_selection;
1794 if (!selected_shape->Select(selected_border))
1797 if (selected_shape == new_selection) selected_shape =
nullptr;
1804 if (!selected_shape)
return false;
1805 return selected_shape->GetSelectedData(shape_val, shape_property_path, shape_item_editorprops, shape_item_value, shape_item_name, shape_item_target_path);
1811 bool C4ConsoleQtShapeHolder::last_visit_flag =
false;
1813 void C4ConsoleQtShapeHolder::Clear()
1822 void C4ConsoleQtShapeHolder::Set(C4ConsoleQtShape *new_shape)
1824 if (shape == new_shape)
return;
C4Value C4VArray(C4ValueArray *pArray)
C4Value C4VInt(int32_t i)
C4Value C4VPropList(C4PropList *p)
void DrawCircleDw(C4Surface *sfcTarget, float cx, float cy, float r, DWORD dwClr, float width=1.0f)
void DrawLineDw(C4Surface *sfcTarget, float x1, float y1, float x2, float y2, DWORD dwClr, float width=1.0f)
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
int32_t GetPropertyBool(C4PropertyName n, bool default_val=false) const
C4ValueArray * GetPropertyArray(C4PropertyName n) const
bool HasProperty(C4String *k) const
C4PropList * GetPropertyPropList(C4PropertyName k) const
C4String * GetPropertyStr(C4PropertyName k) const
static C4PropList * New(C4PropList *prototype=nullptr)
bool GetProperty(C4PropertyName k, C4Value *pResult) const
void SetProperty(C4PropertyName k, const C4Value &to)
const char * GetCStr() const
const C4Value & GetItem(int32_t iElem) const
void SetSize(int32_t inSize)
void SetItem(int32_t iElemNr, const C4Value &Value)
C4ValueArray * getArray() const
C4PropList * getPropList() const
void MouseMove(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, class C4Viewport *pVP)