OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4ConsoleQtShapes.h
Go to the documentation of this file.
1 /*
2 * OpenClonk, http://www.openclonk.org
3 *
4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5 * Copyright (c) 2013, The OpenClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16 
17 /* Editable shapes in the viewports (like e.g. AI guard range rectangles) */
18 
19 #ifndef INC_C4ConsoleQtShapes
20 #define INC_C4ConsoleQtShapes
21 #ifdef WITH_QT_EDITOR
22 
23 #include "editor/C4ConsoleGUI.h" // for glew.h
24 #include "editor/C4ConsoleQt.h"
25 #include "script/C4Value.h"
26 
27 // Shape base class
28 class C4ConsoleQtShape : public QObject
29 {
30  Q_OBJECT
31 protected:
32  C4Value rel_obj; // Object relative to which shape is defined
33  C4Value properties;
34  bool is_relative;
35  int32_t dragging_border, selected_border;
36  uint32_t border_color;
37  const class C4PropertyDelegateShape *parent_delegate;
38  class C4ConsoleQtShapes *shape_list;
39 
40 protected:
41  // Return shape color, or dragged border color if index is the border currently being dragged
42  uint32_t GetBorderColor(int32_t border_index, bool dragging_border_is_bitmask, uint32_t default_color = 0u) const;
43 public:
44  C4ConsoleQtShape(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
45 
46  virtual bool 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) = 0;
47  virtual void Draw(class C4TargetFacet &cgo, float line_width) = 0;
48 
49  // Coordinate transform: Add object
50  int32_t AbsX(int32_t rel_x=0) const;
51  int32_t AbsY(int32_t rel_y=0) const;
52 
53  // Start/stop dragging
54  virtual bool StartDragging(int32_t *border, int32_t x, int32_t y, bool shift_down, bool ctrl_down) { dragging_border = *border; return true; }
55  virtual void StopDragging();
56  virtual void Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor) = 0;
57  bool IsDragging() const { return dragging_border != -1; }
58 
59  virtual void SetValue(const C4Value &val) = 0;
60  virtual C4Value GetValue() const = 0; // Return current shape as C4Value to be stored back to property
61 
62  const class C4PropertyDelegateShape *GetParentDelegate() const { return parent_delegate; }
63  const C4PropList *GetProperties() const { return properties.getPropList(); }
64 
65  virtual bool IsSelectionAllowed(int32_t border) const { return false; }
66  bool Select(int32_t border);
67  void ResetSelection();
68  virtual bool GetSelectedData(const C4Value &shape_val, const class C4PropertyPath &shape_property_path, C4PropList **shape_item_editorprops, C4PropList **shape_item_value, C4String **shape_item_name, class C4PropertyPath *shape_item_target_path) const
69  {
70  return false;
71  }
72 
73  // Specialization
74  virtual class C4ConsoleQtGraph *GetGraphShape() { return nullptr; }
75 
76 signals:
77  void ShapeDragged();
78  void BorderSelectionChanged();
79 };
80 
81 // Rectangular shape
82 class C4ConsoleQtRect : public C4ConsoleQtShape
83 {
84 private:
85  int32_t left, top, right, bottom;
86  bool store_as_proplist;
87  bool properties_lowercase;
88 public:
89  C4ConsoleQtRect(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
90 
91  bool 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) override;
92  void Draw(class C4TargetFacet &cgo, float line_width) override;
93  void Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor) override;
94 
95  void SetValue(const C4Value &val) override;
96  C4Value GetValue() const override;
97 };
98 
99 // Circular shape
100 class C4ConsoleQtCircle : public C4ConsoleQtShape
101 {
102 private:
103  int32_t radius;
104  int32_t cx, cy;
105  bool can_move_center;
106 public:
107  C4ConsoleQtCircle(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
108 
109  bool 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) override;
110  void Draw(class C4TargetFacet &cgo, float line_width) override;
111  void Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor) override;
112 
113  void SetValue(const C4Value &val) override;
114  C4Value GetValue() const override;
115 };
116 
117 // Single position shape
118 class C4ConsoleQtPoint : public C4ConsoleQtShape
119 {
120 private:
121  int32_t cx, cy;
122 public:
123  C4ConsoleQtPoint(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
124 
125  bool 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) override;
126  void Draw(class C4TargetFacet &cgo, float line_width) override;
127  void Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor) override;
128 
129  void SetValue(const C4Value &val) override;
130  C4Value GetValue() const override;
131 };
132 
133 // Vertices and edges
134 class C4ConsoleQtGraph : public C4ConsoleQtShape
135 {
136  Q_OBJECT
137 protected:
138  struct Vertex
139  {
140  int32_t x, y;
141  uint32_t color; // 0 = default color
142 
143  Vertex() : x(0), y(0), color(0u) {}
144  };
145 
146  struct Edge
147  {
148  int32_t vertex_indices[2]; // index into vertices array
149  uint32_t color; // 0 = default color
150  uint32_t line_thickness;
151 
152  Edge() : color(0u), line_thickness(1) { vertex_indices[0] = vertex_indices[1] = -1; }
153  bool connects_to(int32_t vertex_index) const;
154  bool connects_to(int32_t vertex_index, int32_t *idx) const;
155  };
156 
157  // Actual vertex and edge data
158  struct GraphData
159  {
160  std::vector<Vertex> vertices;
161  std::vector<Edge> edges;
162 
163  // Convert elements to/from C4Value
164  C4ValueArray *GetVerticesValue() const;
165  C4ValueArray *GetEdgesValue() const;
166  void SetVerticesValue(const C4ValueArray *vvertices);
167  void SetEdgesValue(const C4ValueArray *vedges);
168 
169  int32_t GetEdgeCountForVertex(int32_t vertex_index) const;
170 
171  // Graph modification. Called from C4ConsoleQtGraph::EditGraph only, which propagates the change to the value via the queue
172  void SetVertexPos(int32_t vertex_index, int32_t new_x, int32_t new_y);
173  void EditEdge(int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex_index);
174  void InsertEdgeBefore(int32_t insert_edge_index, int32_t vertex1, int32_t vertex2);
175  void InsertVertexBefore(int32_t insert_vertex_index, int32_t x, int32_t y);
176  void RemoveEdge(int32_t edge_index);
177  void RemoveVertex(int32_t vertex_index);
178 
179  // Graph modification on internal C4Value script data. Called from C4ConsoleQtGraph::EditGraphValue.
180  static void EditGraphValue_SetVertexPos(C4ValueArray *vvertices, int32_t vertex_index, int32_t new_x, int32_t new_y);
181  static void EditGraphValue_EditEdge(C4ValueArray *vvertices, C4ValueArray *vedges, int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex_index);
182  static void EditGraphValue_InsertEdgeBefore(C4ValueArray *vvertices, C4ValueArray *vedges, int32_t insert_edge_index, int32_t vertex1, int32_t vertex2);
183  static void EditGraphValue_InsertVertexBefore(C4ValueArray *vvertices, C4ValueArray *vedges, int32_t insert_vertex_index, int32_t x, int32_t y);
184  static void EditGraphValue_RemoveEdge(C4ValueArray *vvertices, C4ValueArray *vedges, int32_t edge_index);
185  static void EditGraphValue_RemoveVertex(C4ValueArray *vvertices, C4ValueArray *vedges, int32_t vertex_index);
186  static bool EditGraphValue_EdgeConnectsTo(C4PropList *edge, int32_t vertex_index);
187  } graph;
188 
189  bool allow_vertex_selection = false; // If vertices on the graph can be selected
190  bool allow_edge_selection = false; // If edges on the graph can be selected
191  bool horizontal_fix = false; // If edges are locked horizontally
192  bool vertical_fix = false; // If edges are locked vertically
193  bool structure_fix = false; // If edge+vertex insertion/deletion is blocked
194  bool draw_arrows = false; // If directions on edges are to be signified with arrowheads
195 
196  C4Value vertex_delegate, edge_delegate;
197 
198  // Drag snap to other vertices
199  int32_t drag_snap_offset_x = 0, drag_snap_offset_y = 0;
200  bool drag_snapped = false;
201  int32_t drag_snap_vertex = -1, drag_source_vertex_index = -1;
202 
203  // Resolve border_index to vertices/edges: Use negative indices for edges and zero/positive indices for vertices
204  static bool IsVertexDrag(int32_t border) { return border >= 0; }
205  static bool IsEdgeDrag(int32_t border) { return border < -1; }
206  static int32_t DragBorderToVertex(int32_t border) { return border; }
207  static int32_t DragBorderToEdge(int32_t border) { return -2 - border; }
208  static int32_t VertexToDragBorder(int32_t vertex) { return vertex; }
209  static int32_t EdgeToDragBorder(int32_t edge) { return -edge - 2; }
210 
211  void DrawEdge(class C4TargetFacet &cgo, const Vertex &v0, const Vertex &v2, uint32_t clr, float line_width, float edge_width, bool highlight);
212 public:
213  C4ConsoleQtGraph(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
214 
215  bool 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) override;
216  void Draw(class C4TargetFacet &cgo, float line_width) override;
217  void Drag(int32_t x, int32_t y, int32_t dx, int32_t dy, int32_t hit_range, Qt::CursorShape *drag_cursor) override;
218  bool StartDragging(int32_t *border, int32_t x, int32_t y, bool shift_down, bool ctrl_down) override;
219  void StopDragging() override;
220 
221  void SetValue(const C4Value &val) override;
222  C4Value GetValue() const override;
223 
224  bool IsSelectionAllowed(int32_t border) const override;
225  bool GetSelectedData(const C4Value &shape_val, const class C4PropertyPath &shape_property_path, C4PropList **shape_item_editorprops, C4PropList **shape_item_value, C4String **shape_item_name, class C4PropertyPath *shape_item_target_path) const override;
226 
227  void EditGraph(bool signal_change, C4ControlEditGraph::Action action, int32_t index, int32_t x, int32_t y);
228  static void EditGraphValue(C4Value &val, C4ControlEditGraph::Action action, int32_t index, int32_t x, int32_t y);
229 
230  class C4ConsoleQtGraph *GetGraphShape() override { return this; }
231 
232 protected:
233  void EditEdge(int32_t edge_index, int32_t change_vertex_index, int32_t new_vertex);
234  int32_t AddVertex(int32_t new_x, int32_t new_y);
235  int32_t AddEdge(int32_t connect_vertex_index_1, int32_t connect_vertex_index_2);
236  void InsertVertexBefore(int32_t insert_vertex_index, int32_t x, int32_t y);
237  void InsertEdgeBefore(int32_t insert_edge_index, int32_t connect_vertex_index_1, int32_t connect_vertex_index_2);
238  virtual int32_t InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y);
239  virtual int32_t InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y);
240  virtual void RemoveEdge(int32_t edge_index);
241  virtual void RemoveVertex(int32_t vertex_index, bool create_skip_connection);
242 
243  virtual bool IsPolyline() const { return false; }
244 
245  // Check if given vertex/edge can be modified under given shift state
246  virtual bool IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor, bool shift_down, bool ctrl_down);
247  virtual bool IsEdgeHit(int32_t edge_index, Qt::CursorShape *drag_cursor, bool shift_down, bool ctrl_down);
248 
249 signals:
250  void GraphEdit(C4ControlEditGraph::Action action, int32_t index, int32_t x, int32_t y);
251 };
252 
253 // Specialization of graph: One line of connected vertices
254 class C4ConsoleQtPolyline : public C4ConsoleQtGraph
255 {
256 private:
257  bool start_from_object = false;
258 public:
259  C4ConsoleQtPolyline(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list);
260 
261  void Draw(class C4TargetFacet &cgo, float line_width) override;
262  void SetValue(const C4Value &val) override;
263  C4Value GetValue() const override;
264 
265 protected:
266  int32_t InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y) override;
267  int32_t InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y) override;
268  void RemoveEdge(int32_t edge_index) override;
269 
270  bool IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor, bool shift_down, bool ctrl_down) override;
271  bool IsPolyline() const override { return true; }
272 };
273 
274 // Specialization of graph: One closed line of connected vertices
275 class C4ConsoleQtPolygon : public C4ConsoleQtPolyline
276 {
277 public:
278  C4ConsoleQtPolygon(class C4Object *for_obj, C4PropList *props, const class C4PropertyDelegateShape *parent_delegate, class C4ConsoleQtShapes *shape_list)
279  : C4ConsoleQtPolyline(for_obj, props, parent_delegate, shape_list) {}
280 
281  void SetValue(const C4Value &val) override;
282 
283 protected:
284  int32_t InsertVertexOnEdge(int32_t split_edge_index, int32_t x, int32_t y) override;
285  int32_t InsertVertexOnVertex(int32_t target_vertex_index, int32_t x, int32_t y) override;
286  void RemoveEdge(int32_t edge_index) override;
287 
288  bool IsVertexHit(int32_t vertex_index, Qt::CursorShape *drag_cursor, bool shift_down, bool ctrl_down) override;
289 };
290 
291 /* List of all current editable Qt shapes */
292 class C4ConsoleQtShapes
293 {
294  typedef std::list<std::unique_ptr<C4ConsoleQtShape> > ShapeList;
295  ShapeList shapes;
296  C4ConsoleQtShape *dragging_shape, *selected_shape;
297  Qt::CursorShape drag_cursor;
298  float drag_x, drag_y;
299 public:
300  C4ConsoleQtShapes() : dragging_shape(nullptr), selected_shape(nullptr), drag_x(0), drag_y(0), drag_cursor(Qt::CursorShape::ArrowCursor) { }
301 
302  C4ConsoleQtShape *CreateShape(class C4Object *for_obj, C4PropList *props, const C4Value &val, const class C4PropertyDelegateShape *parent_delegate);
303  void AddShape(C4ConsoleQtShape *shape);
304  void RemoveShape(C4ConsoleQtShape *shape);
305  void ClearShapes();
306 
307  // Mouse callbacks from viewports to execute shape dragging
308  bool MouseDown(float x, float y, float hit_range, bool shift_down, bool ctrl_down); // return true if a shape was hit
309  void MouseMove(float x, float y, bool left_down, float hit_range, bool shift_down, bool ctrl_down); // move move: Execute shape dragging
310  void MouseUp(float x, float y, bool shift_down, bool ctrl_down);
311 
312  void Draw(C4TargetFacet &cgo);
313 
314  // Dragging info
315  bool HasDragCursor() const { return drag_cursor != Qt::CursorShape::ArrowCursor; }
316  Qt::CursorShape GetDragCursor() const { return drag_cursor; }
317  bool IsDragging() const { return !!dragging_shape; }
318 
319  // Selected shapes
320  void SetSelectedShape(C4ConsoleQtShape *new_selection, int32_t selected_border);
321  C4ConsoleQtShape *GetSelectedShape() const { return selected_shape; }
322  bool GetSelectedShapeData(const C4Value &shape_val, const class C4PropertyPath &shape_property_path, C4PropList **shape_item_editorprops, C4PropList **shape_item_value, C4String **shape_item_name, class C4PropertyPath *shape_item_target_path) const;
323 };
324 
325 /* Shape holder class: Handles adding/removal of shape to shapes list */
326 class C4ConsoleQtShapeHolder
327 {
328  C4ConsoleQtShape *shape;
329  bool last_visit;
330  C4Value last_value;
331 
332  static bool last_visit_flag;
333 
334 public:
335  C4ConsoleQtShapeHolder() : shape(nullptr) {}
336  ~C4ConsoleQtShapeHolder() { Clear(); }
337 
338  void Clear();
339  void Set(C4ConsoleQtShape *new_shape);
340  C4ConsoleQtShape *Get() const { return shape; }
341 
342  // Check counter to determine unused shapes
343  void visit() { last_visit = last_visit_flag; }
344  bool was_visited() const { return last_visit == last_visit_flag; }
345  static void begin_visit() { last_visit_flag = !last_visit_flag; }
346 
347  // Remember pointer to last proplist or array set in value to reflect scripted updates
348  const C4Value &GetLastValue() const { return last_value; }
349  void SetLastValue(const C4Value &new_val) { last_value = new_val; }
350 };
351 
352 
353 #endif // WITH_QT_EDITOR
354 #endif // INC_C4ConsoleQtShapes
void MouseMove(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, class C4Viewport *pVP)
Definition: C4Gui.h:2829
C4PropList * getPropList() const
Definition: C4Value.h:116