]> Shamusworld >> Repos - architektonas/blob - src/object.cpp
Beginning to make the Layer widget functional.
[architektonas] / src / object.cpp
1 //
2 // object.cpp: Base class for all CAD objects
3 //
4 // Part of the Architektonas Project
5 // (C) 2011 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // WHO  WHEN        WHAT
11 // ---  ----------  ------------------------------------------------------------
12 // JLH  03/22/2011  Created this file
13 // JLH  04/01/2011  Added constructor to allow derived objects to have empty
14 //                  constructor bodies, added state querying
15 // JLH  04/02/2001  Added static methods for global states (fixed angle, etc)
16 //
17
18 #include "object.h"
19 #include <stdlib.h>
20 #include <math.h>
21
22 // Initialize static variables
23 bool Object::fixedAngle = false;
24 bool Object::fixedLength = false;
25 QFont * Object::font = 0;
26 int Object::viewportHeight = 0;
27 bool Object::deleteActive = false;
28 bool Object::dimensionActive = false;
29 bool Object::snapToGrid = true;
30 //snapToPoints all well here?
31 bool Object::ignoreClicks = false;
32 bool Object::dontMove = false;
33 bool Object::selectionInProgress = false;
34 QRectF Object::selection;
35 double Object::gridSpacing;
36 int Object::currentLayer = 0;
37
38
39 Object::Object(): position(Vector(0, 0)), parent(0), type(OTObject),
40         state(OSInactive), layer(0), oldState(OSInactive), needUpdate(false)
41         //, attachedDimension(0)
42 {
43 }
44
45
46 Object::Object(Vector v,  Object * passedInParent/*= 0*/): position(v),
47         parent(passedInParent), state(OSInactive), layer(0), oldState(OSInactive),
48         needUpdate(false)//, attachedDimension(0)
49 {
50 }
51
52
53 Object::~Object()
54 {
55 printf("Object: Destroyed!\n");
56         for(uint i=0; i<connected.size(); i++)
57                 connected[i].object->DisconnectAll(this);
58 }
59
60
61 /*virtual*/ void Object::Draw(Painter *)
62 {
63 }
64
65
66 /*virtual*/ Vector Object::Center(void)
67 {
68         return Vector();
69 }
70
71
72 /*virtual*/ bool Object::Collided(Vector)
73 {
74         return false;
75 }
76
77
78 /*virtual*/ void Object::PointerMoved(Vector)
79 {
80 }
81
82
83 /*virtual*/ void Object::PointerReleased(void)
84 {
85 }
86
87
88 /*virtual*/ bool Object::NeedsUpdate(void)
89 {
90         return needUpdate;
91 }
92
93
94 /*virtual*/ bool Object::HitTest(Point)
95 {
96         return false;
97 }
98
99
100 // This is intended to be overridden by the Container class, for object morphing
101 /*virtual*/ void Object::Transmute(Object *, Object *)
102 {
103 }
104
105
106 /*virtual*/ Object * Object::GetParent(void)
107 {
108         return parent;
109 }
110
111
112 /*virtual*/ void Object::Add(Object *)
113 {
114 }
115
116
117 // This returns a pointer to the point passed in, if it coincides. Otherwise returns NULL.
118 /*virtual*/ Vector * Object::GetPointAt(Vector)
119 {
120         return 0;
121 }
122
123
124 // This is meant for writing object data to a file.
125 /*virtual*/ void Object::Enumerate(FILE *)
126 {
127 }
128
129
130 /*virtual*/ Object * Object::Copy(void)
131 {
132         return new Object(position, parent);
133 }
134
135
136 // This returns a point on the object at 'parameter', which is between 0 and 1.
137 // Default is to return the object's position.
138 /*virtual*/ Vector Object::GetPointAtParameter(double)
139 {
140         return position;
141 }
142
143
144 // Since these functions are pretty much non-object specific, we can implement
145 // them here. :-)
146 /*virtual*/ void Object::Connect(Object * obj, double parameter)
147 {
148         connected.push_back(Connection(obj, parameter));
149 }
150
151
152 /*virtual*/ void Object::Disconnect(Object * obj, double parameter)
153 {
154 #if 0
155         for(uint i=0; i<connected.size(); i++)
156         {
157                 if (connected[i].object == obj && connected[i].t == parameter)
158                 {
159                         connected.erase(connected.begin() + i);
160                         return;
161                 }
162         }
163 #else
164         std::vector<Connection>::iterator i;
165
166         for(i=connected.begin(); i!=connected.end(); i++)
167         {
168                 if (((*i).object == obj) && ((*i).t == parameter))
169                 {
170                         connected.erase(i);
171                         return;
172                 }
173         }
174 #endif
175 }
176
177
178 /*virtual*/ void Object::DisconnectAll(Object * obj)
179 {
180 #if 0
181         // According the std::vector docs, only items at position i and beyond are
182         // invalidated, everything before i is still valid. So we use that here.
183         for(uint i=0; i<connected.size();)
184         {
185                 // If we found our object, erase it from the vector but don't advance
186                 // the iterator. Otherwise, advance the iterator. :-)
187                 if (connected[i].object == obj)
188                         connected.erase(connected.begin() + i);
189                 else
190                         i++;
191         }
192 #else
193         std::vector<Connection>::iterator i;
194
195         for(i=connected.begin(); i!=connected.end(); )
196         {
197                 if ((*i).object == obj)
198                         connected.erase(i);
199                 else
200                         i++;
201         }
202 #endif
203 }
204
205
206 /*virtual*/ QRectF Object::Extents(void)
207 {
208         // Generic object returns an empty rect...
209         return QRectF();
210 }
211
212
213 #if 0
214 /*virtual*/ ObjectType Object::Type(void)
215 {
216         return OTObject;
217 }
218 #endif
219
220
221 /*virtual*/ void Object::Translate(Vector amount)
222 {
223         position += amount;
224 }
225
226
227 /*virtual*/ void Object::Rotate(Vector, double)
228 {
229 }
230
231
232 /*virtual*/ void Object::Scale(Vector, double)
233 {
234 }
235
236
237 ObjectState Object::GetState(void)
238 {
239         return state;
240 }
241
242
243 void Object::Reparent(Object * newParent)
244 {
245         parent = newParent;
246 }
247
248
249 /*Dimension * Object::GetAttachedDimension(void)
250 {
251         return attachedDimension;
252 }*/
253
254
255 // Class methods...
256
257 void Object::SetFixedAngle(bool state/*= true*/)
258 {
259         fixedAngle = state;
260 }
261
262
263 void Object::SetFixedLength(bool state/*= true*/)
264 {
265         fixedLength = state;
266 }
267
268
269 void Object::SetFont(QFont * f)
270 {
271         font = f;
272 }
273
274
275 void Object::SetViewportHeight(int height)
276 {
277         viewportHeight = height;
278 }
279
280
281 void Object::SetDeleteActive(bool state/*= true*/)
282 {
283         deleteActive = state;
284 }
285
286
287 void Object::SetDimensionActive(bool state/*= true*/)
288 {
289         dimensionActive = state;
290 }
291
292
293 void Object::SetSnapMode(bool state/*= true*/)
294 {
295         snapToGrid = state;
296 }
297
298
299 //
300 // This looks strange, but it's really quite simple: We want a point that's
301 // more than half-way to the next grid point to snap there while conversely we
302 // want a point that's less than half-way to to the next grid point then snap
303 // to the one before it. So we add half of the grid spacing to the point, then
304 // divide by it so that we can remove the fractional part, then multiply it
305 // back to get back to the correct answer.
306 //
307 Vector Object::SnapPointToGrid(Vector point)
308 {
309         point += gridSpacing / 2.0;             // *This* adds to Z!!!
310         point /= gridSpacing;
311         point.x = floor(point.x);//need to fix this for negative numbers...
312         point.y = floor(point.y);
313         point.z = 0;                                    // Make *sure* Z doesn't go anywhere!!!
314         point *= gridSpacing;
315         return point;
316 }
317
318