]> Shamusworld >> Repos - architektonas/blob - src/container.cpp
Added new About logo, beginnings of generic rotation tool.
[architektonas] / src / container.cpp
1 // container.cpp: Container object
2 //
3 // Part of the Architektonas Project
4 // (C) 2011 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/30/2011  Created this file
12 // JLH  06/02/2011  Added code to delete objects in this container when they go
13 //                  out of scope
14 //
15
16 #include "container.h"
17
18 #include <QtGui>
19
20
21 Container::Container(Vector p1, Object * p/*= NULL*/): Object(p1, p),
22         dragging(false), draggingHandle1(false), draggingHandle2(false)//, needUpdate(false)
23 {
24 }
25
26 Container::~Container()
27 {
28         // No memory leaks!
29         while (objects.size() > 0)
30         {
31                 delete objects[0];
32                 objects.erase(objects.begin());
33         }
34 }
35
36 /*virtual*/ void Container::Draw(QPainter * painter)
37 {
38         for(int i=0; i<(int)objects.size(); i++)
39                 objects[i]->Draw(painter);
40 }
41
42 /*virtual*/ Vector Container::Center(void)
43 {
44         return position;
45 }
46
47 /*
48  We need at least *three* handles for this object:
49  - one for moving
50  - one for resizing
51  - one for rotation
52
53 We need to think about the intuitive way (if there is any) to grab and
54 manipulate a complex object like this... Need to think, "What should happen when
55 I click here and drag there?"
56
57 Also: should put the snap logic into the Object base class (as a static method)...
58 */
59
60 /*virtual*/ bool Container::Collided(Vector point)
61 {
62         objectWasDragged = false;
63         Vector v1 = position - point;
64
65 #if 0
66         if (state == OSInactive)
67         {
68 //printf("Circle: pp = %lf, length = %lf, distance = %lf\n", parameterizedPoint, lineSegment.Magnitude(), distance);
69 //printf("      v1.Magnitude = %lf, v2.Magnitude = %lf\n", v1.Magnitude(), v2.Magnitude());
70 //printf("      point = %lf,%lf,%lf; p1 = %lf,%lf,%lf; p2 = %lf,%lf,%lf\n", point.x, point.y, point.z, position.x, position.y, position.z, endpoint.x, endpoint.y, endpoint.z);
71 //printf("      \n", );
72 //How to translate this into pixels from Document space???
73 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
74 //the caller knows about the zoom factor and all that good kinda crap
75                 if (v1.Magnitude() < 10.0)
76                 {
77                         oldState = state;
78                         state = OSSelected;
79                         oldPoint = position; //maybe "position"?
80                         draggingHandle1 = true;
81                         return true;
82                 }
83                 else if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
84                 {
85                         oldState = state;
86                         state = OSSelected;
87                         oldPoint = point;
88                         dragging = true;
89                         return true;
90                 }
91         }
92         else if (state == OSSelected)
93         {
94                 // Here we test for collision with handles as well! (SOON!)
95 /*
96 Like so:
97                 if (v1.Magnitude() < 2.0) // Handle #1
98                 else if (v2.Magnitude() < 2.0) // Handle #2
99 */
100                 if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
101                 {
102                         oldState = state;
103 //                      state = OSInactive;
104                         oldPoint = point;
105                         dragging = true;
106                         return true;
107                 }
108         }
109 #else
110         bool collision = false;
111
112         // NOTE that this deletes the object on mouse down instead of mouse up. Have to
113         // check to see how it feels to do it that way...
114         if (deleteActive)
115         {
116                 for(int i=0; i<(int)objects.size(); i++)
117                 {
118                         if (objects[i]->Collided(point))
119                         {
120                                 objects.erase(objects.begin() + i);     // Calls the destructor, (deletes the object, I presume... O_o)
121                                 break;
122                         }
123                 }
124         }
125         else
126         {
127                 for(int i=0; i<(int)objects.size(); i++)
128                 {
129                         if (objects[i]->Collided(point))
130                                 collision = true;
131                 }
132         }
133 #endif
134
135         // Do we decouple the state of the generic container from the objects inside??? Mebbe.
136         state = OSInactive;
137 //      return false;
138         return collision;
139 }
140
141 // The TLC is passing all mouse movement here, so we're doing the same here.
142 // Need to adjust all other objects to handle things correctly.
143 // One optimization that will need to be done eventually is to subdivide the screen
144 // into parts and keep subdividing until an acceptable number of objects lie within
145 // the slice. This way, the GUI will still be responsive and *not* have to test
146 // every object for collision.
147 /*virtual*/ void Container::PointerMoved(Vector point)
148 {
149 //      objectWasDragged = true;
150 //printf("CONTAINER: PointerMoved()\n");
151
152         for(int i=0; i<(int)objects.size(); i++)
153         {
154 //              if (objects[i]->GetState() == OSSelected)
155                         objects[i]->PointerMoved(point);
156         }
157
158         // Generic container doesn't need this???
159 //      needUpdate = false;
160 }
161
162 /*virtual*/ void Container::PointerReleased(void)
163 {
164         dragging = false;
165         draggingHandle1 = false;
166         draggingHandle2 = false;
167
168         // Here we check for just a click: If object was clicked and dragged, then
169         // revert to the old state (OSInactive). Otherwise, keep the new state that
170         // we set.
171 /*Maybe it would be better to just check for "object was dragged" state and not have to worry
172 about keeping track of old states...
173 */
174         if (objectWasDragged)
175                 state = oldState;
176 //Note that the preceeding is unnecessary for a generic container!
177
178         for(int i=0; i<(int)objects.size(); i++)
179                 objects[i]->PointerReleased();
180 }
181
182 /*virtual*/ bool Container::NeedsUpdate(void)
183 {
184         needUpdate = false;
185
186         for(int i=0; i<(int)objects.size(); i++)
187         {
188                 if (objects[i]->NeedsUpdate())
189                         needUpdate = true;
190         }
191
192         return needUpdate;
193 }
194
195 /*virtual*/ void Container::Add(Object * object)
196 {
197         objects.push_back(object);
198 }