diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/lltoolplacer.cpp | 380 |
1 files changed, 375 insertions, 5 deletions
diff --git a/linden/indra/newview/lltoolplacer.cpp b/linden/indra/newview/lltoolplacer.cpp index ee5d08f..d26bdab 100644 --- a/linden/indra/newview/lltoolplacer.cpp +++ b/linden/indra/newview/lltoolplacer.cpp | |||
@@ -50,9 +50,22 @@ | |||
50 | #include "llviewerregion.h" | 50 | #include "llviewerregion.h" |
51 | #include "llviewerwindow.h" | 51 | #include "llviewerwindow.h" |
52 | #include "llworld.h" | 52 | #include "llworld.h" |
53 | #include "viewer.h" | ||
54 | #include "llui.h" | 53 | #include "llui.h" |
55 | 54 | ||
55 | //Headers added for functions moved from viewer.cpp | ||
56 | #include "llvograss.h" | ||
57 | #include "llvotree.h" | ||
58 | #include "llvolumemessage.h" | ||
59 | #include "llhudmanager.h" | ||
60 | #include "llagent.h" | ||
61 | #include "audioengine.h" | ||
62 | #include "llhudeffecttrail.h" | ||
63 | #include "llviewerobjectlist.h" | ||
64 | #include "llviewercamera.h" | ||
65 | #include "llviewerstats.h" | ||
66 | |||
67 | const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f); | ||
68 | |||
56 | //static | 69 | //static |
57 | LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE; | 70 | LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE; |
58 | 71 | ||
@@ -61,9 +74,366 @@ LLToolPlacer::LLToolPlacer() | |||
61 | { | 74 | { |
62 | } | 75 | } |
63 | 76 | ||
77 | BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face, | ||
78 | BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region ) | ||
79 | { | ||
80 | F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f; | ||
81 | |||
82 | // Viewer-side pick to find the right sim to create the object on. | ||
83 | // First find the surface the object will be created on. | ||
84 | gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE); | ||
85 | |||
86 | // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok | ||
87 | // representations (if any) are NOT the same as their viewer representation. | ||
88 | *hit_obj = gObjectList.findObject( gLastHitNonFloraObjectID ); | ||
89 | *hit_face = gLastHitNonFloraObjectFace; | ||
90 | *b_hit_land = !(*hit_obj) && !gLastHitNonFloraPosGlobal.isExactlyZero(); | ||
91 | LLVector3d land_pos_global = gLastHitNonFloraPosGlobal; | ||
92 | |||
93 | // Make sure there's a surface to place the new object on. | ||
94 | BOOL bypass_sim_raycast = FALSE; | ||
95 | LLVector3d surface_pos_global; | ||
96 | if (*b_hit_land) | ||
97 | { | ||
98 | surface_pos_global = land_pos_global; | ||
99 | bypass_sim_raycast = TRUE; | ||
100 | } | ||
101 | else | ||
102 | if (*hit_obj) | ||
103 | { | ||
104 | surface_pos_global = (*hit_obj)->getPositionGlobal(); | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | return FALSE; | ||
109 | } | ||
110 | |||
111 | // Make sure the surface isn't too far away. | ||
112 | LLVector3d ray_start_global = gAgent.getCameraPositionGlobal(); | ||
113 | F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared()); | ||
114 | if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) ) | ||
115 | { | ||
116 | return FALSE; | ||
117 | } | ||
118 | |||
119 | // Find the sim where the surface lives. | ||
120 | LLViewerRegion *regionp = gWorldp->getRegionFromPosGlobal(surface_pos_global); | ||
121 | if (!regionp) | ||
122 | { | ||
123 | llwarns << "Trying to add object outside of all known regions!" << llendl; | ||
124 | return FALSE; | ||
125 | } | ||
126 | |||
127 | // Find the simulator-side ray that will be used to place the object accurately | ||
128 | LLVector3d mouse_direction; | ||
129 | mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) ); | ||
130 | |||
131 | *region = regionp; | ||
132 | *ray_start_region = regionp->getPosRegionFromGlobal( ray_start_global ); | ||
133 | F32 near_clip = gCamera->getNear() + 0.01f; // Include an epsilon to avoid rounding issues. | ||
134 | *ray_start_region += gCamera->getAtAxis() * near_clip; | ||
135 | |||
136 | if( bypass_sim_raycast ) | ||
137 | { | ||
138 | // Hack to work around Havok's inability to ray cast onto height fields | ||
139 | *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global ); // ray end is the viewer's intersection point | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | LLVector3d ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction; // add an epsilon to the sim version of the ray to avoid rounding problems. | ||
144 | *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global ); | ||
145 | } | ||
146 | |||
147 | return TRUE; | ||
148 | } | ||
149 | |||
150 | |||
151 | BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) | ||
152 | { | ||
153 | LLVector3 ray_start_region; | ||
154 | LLVector3 ray_end_region; | ||
155 | LLViewerRegion* regionp = NULL; | ||
156 | BOOL b_hit_land = FALSE; | ||
157 | S32 hit_face = -1; | ||
158 | LLViewerObject* hit_obj = NULL; | ||
159 | U8 state = 0; | ||
160 | BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp ); | ||
161 | if( !success ) | ||
162 | { | ||
163 | return FALSE; | ||
164 | } | ||
165 | |||
166 | if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) ) | ||
167 | { | ||
168 | // Can't create objects on avatars or attachments | ||
169 | return FALSE; | ||
170 | } | ||
171 | |||
172 | if (NULL == regionp) | ||
173 | { | ||
174 | llwarns << "regionp was NULL; aborting function." << llendl; | ||
175 | return FALSE; | ||
176 | } | ||
177 | |||
178 | if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX) | ||
179 | { | ||
180 | LLFirstUse::useSandbox(); | ||
181 | } | ||
182 | |||
183 | // Set params for new object based on its PCode. | ||
184 | LLQuaternion rotation; | ||
185 | LLVector3 scale = DEFAULT_OBJECT_SCALE; | ||
186 | U8 material = LL_MCODE_WOOD; | ||
187 | BOOL create_selected = FALSE; | ||
188 | LLVolumeParams volume_params; | ||
189 | |||
190 | switch (pcode) | ||
191 | { | ||
192 | case LL_PCODE_LEGACY_GRASS: | ||
193 | // Randomize size of grass patch | ||
194 | scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f)); | ||
195 | state = rand() % LLVOGrass::sMaxGrassSpecies; | ||
196 | break; | ||
197 | |||
198 | |||
199 | case LL_PCODE_LEGACY_TREE: | ||
200 | case LL_PCODE_TREE_NEW: | ||
201 | state = rand() % LLVOTree::sMaxTreeSpecies; | ||
202 | break; | ||
203 | |||
204 | case LL_PCODE_SPHERE: | ||
205 | case LL_PCODE_CONE: | ||
206 | case LL_PCODE_CUBE: | ||
207 | case LL_PCODE_CYLINDER: | ||
208 | case LL_PCODE_TORUS: | ||
209 | case LLViewerObject::LL_VO_SQUARE_TORUS: | ||
210 | case LLViewerObject::LL_VO_TRIANGLE_TORUS: | ||
211 | default: | ||
212 | create_selected = TRUE; | ||
213 | break; | ||
214 | } | ||
215 | |||
216 | // Play creation sound | ||
217 | if (gAudiop) | ||
218 | { | ||
219 | F32 volume = gSavedSettings.getF32("AudioLevelUI"); | ||
220 | gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume); | ||
221 | } | ||
222 | |||
223 | gMessageSystem->newMessageFast(_PREHASH_ObjectAdd); | ||
224 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | ||
225 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
226 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
227 | gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); | ||
228 | gMessageSystem->nextBlockFast(_PREHASH_ObjectData); | ||
229 | gMessageSystem->addU8Fast(_PREHASH_Material, material); | ||
230 | |||
231 | U32 flags = 0; // not selected | ||
232 | if (use_physics) | ||
233 | { | ||
234 | flags |= FLAGS_USE_PHYSICS; | ||
235 | } | ||
236 | if (create_selected) | ||
237 | { | ||
238 | flags |= FLAGS_CREATE_SELECTED; | ||
239 | } | ||
240 | gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags ); | ||
241 | |||
242 | LLPCode volume_pcode; // ...PCODE_VOLUME, or the original on error | ||
243 | switch (pcode) | ||
244 | { | ||
245 | case LL_PCODE_SPHERE: | ||
246 | rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); | ||
247 | |||
248 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); | ||
249 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
250 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
251 | volume_params.setRatio ( 1, 1 ); | ||
252 | volume_params.setShear ( 0, 0 ); | ||
253 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
254 | volume_pcode = LL_PCODE_VOLUME; | ||
255 | break; | ||
256 | |||
257 | case LL_PCODE_TORUS: | ||
258 | rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); | ||
259 | |||
260 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE ); | ||
261 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
262 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
263 | volume_params.setRatio ( 1.f, 0.25f ); // "top size" | ||
264 | volume_params.setShear ( 0, 0 ); | ||
265 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
266 | volume_pcode = LL_PCODE_VOLUME; | ||
267 | break; | ||
268 | |||
269 | case LLViewerObject::LL_VO_SQUARE_TORUS: | ||
270 | rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); | ||
271 | |||
272 | volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE ); | ||
273 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
274 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
275 | volume_params.setRatio ( 1.f, 0.25f ); // "top size" | ||
276 | volume_params.setShear ( 0, 0 ); | ||
277 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
278 | volume_pcode = LL_PCODE_VOLUME; | ||
279 | break; | ||
280 | |||
281 | case LLViewerObject::LL_VO_TRIANGLE_TORUS: | ||
282 | rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); | ||
283 | |||
284 | volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE ); | ||
285 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
286 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
287 | volume_params.setRatio ( 1.f, 0.25f ); // "top size" | ||
288 | volume_params.setShear ( 0, 0 ); | ||
289 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
290 | volume_pcode = LL_PCODE_VOLUME; | ||
291 | break; | ||
292 | |||
293 | case LL_PCODE_SPHERE_HEMI: | ||
294 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); | ||
295 | //volume_params.setBeginAndEndS( 0.5f, 1.f ); | ||
296 | volume_params.setBeginAndEndT( 0.f, 0.5f ); | ||
297 | volume_params.setRatio ( 1, 1 ); | ||
298 | volume_params.setShear ( 0, 0 ); | ||
299 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
300 | volume_pcode = LL_PCODE_VOLUME; | ||
301 | break; | ||
302 | |||
303 | case LL_PCODE_CUBE: | ||
304 | volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); | ||
305 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
306 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
307 | volume_params.setRatio ( 1, 1 ); | ||
308 | volume_params.setShear ( 0, 0 ); | ||
309 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
310 | volume_pcode = LL_PCODE_VOLUME; | ||
311 | break; | ||
312 | |||
313 | case LL_PCODE_PRISM: | ||
314 | volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); | ||
315 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
316 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
317 | volume_params.setRatio ( 0, 1 ); | ||
318 | volume_params.setShear ( -0.5f, 0 ); | ||
319 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
320 | volume_pcode = LL_PCODE_VOLUME; | ||
321 | break; | ||
322 | |||
323 | case LL_PCODE_PYRAMID: | ||
324 | volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); | ||
325 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
326 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
327 | volume_params.setRatio ( 0, 0 ); | ||
328 | volume_params.setShear ( 0, 0 ); | ||
329 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
330 | volume_pcode = LL_PCODE_VOLUME; | ||
331 | break; | ||
332 | |||
333 | case LL_PCODE_TETRAHEDRON: | ||
334 | volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE ); | ||
335 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
336 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
337 | volume_params.setRatio ( 0, 0 ); | ||
338 | volume_params.setShear ( 0, 0 ); | ||
339 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
340 | volume_pcode = LL_PCODE_VOLUME; | ||
341 | break; | ||
342 | |||
343 | case LL_PCODE_CYLINDER: | ||
344 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); | ||
345 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
346 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
347 | volume_params.setRatio ( 1, 1 ); | ||
348 | volume_params.setShear ( 0, 0 ); | ||
349 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
350 | volume_pcode = LL_PCODE_VOLUME; | ||
351 | break; | ||
352 | |||
353 | case LL_PCODE_CYLINDER_HEMI: | ||
354 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); | ||
355 | volume_params.setBeginAndEndS( 0.25f, 0.75f ); | ||
356 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
357 | volume_params.setRatio ( 1, 1 ); | ||
358 | volume_params.setShear ( 0, 0 ); | ||
359 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
360 | volume_pcode = LL_PCODE_VOLUME; | ||
361 | break; | ||
362 | |||
363 | case LL_PCODE_CONE: | ||
364 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); | ||
365 | volume_params.setBeginAndEndS( 0.f, 1.f ); | ||
366 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
367 | volume_params.setRatio ( 0, 0 ); | ||
368 | volume_params.setShear ( 0, 0 ); | ||
369 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
370 | volume_pcode = LL_PCODE_VOLUME; | ||
371 | break; | ||
372 | |||
373 | case LL_PCODE_CONE_HEMI: | ||
374 | volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); | ||
375 | volume_params.setBeginAndEndS( 0.25f, 0.75f ); | ||
376 | volume_params.setBeginAndEndT( 0.f, 1.f ); | ||
377 | volume_params.setRatio ( 0, 0 ); | ||
378 | volume_params.setShear ( 0, 0 ); | ||
379 | LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); | ||
380 | volume_pcode = LL_PCODE_VOLUME; | ||
381 | break; | ||
382 | |||
383 | default: | ||
384 | LLVolumeMessage::packVolumeParams(0, gMessageSystem); | ||
385 | volume_pcode = pcode; | ||
386 | break; | ||
387 | } | ||
388 | gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode); | ||
389 | |||
390 | gMessageSystem->addVector3Fast(_PREHASH_Scale, scale ); | ||
391 | gMessageSystem->addQuatFast(_PREHASH_Rotation, rotation ); | ||
392 | gMessageSystem->addVector3Fast(_PREHASH_RayStart, ray_start_region ); | ||
393 | gMessageSystem->addVector3Fast(_PREHASH_RayEnd, ray_end_region ); | ||
394 | gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, (U8)b_hit_land ); | ||
395 | gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE ); | ||
396 | gMessageSystem->addU8Fast(_PREHASH_State, state); | ||
397 | |||
398 | // Limit raycast to a single object. | ||
399 | // Speeds up server raycast + avoid problems with server ray hitting objects | ||
400 | // that were clipped by the near plane or culled on the viewer. | ||
401 | LLUUID ray_target_id; | ||
402 | if( hit_obj ) | ||
403 | { | ||
404 | ray_target_id = hit_obj->getID(); | ||
405 | } | ||
406 | else | ||
407 | { | ||
408 | ray_target_id.setNull(); | ||
409 | } | ||
410 | gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, ray_target_id ); | ||
411 | |||
412 | // Pack in name value pairs | ||
413 | gMessageSystem->sendReliable(regionp->getHost()); | ||
414 | |||
415 | // Spawns a message, so must be after above send | ||
416 | if (create_selected) | ||
417 | { | ||
418 | gSelectMgr->deselectAll(); | ||
419 | gViewerWindow->getWindow()->incBusyCount(); | ||
420 | } | ||
421 | |||
422 | // VEFFECT: AddObject | ||
423 | LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); | ||
424 | effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject()); | ||
425 | effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region)); | ||
426 | effectp->setDuration(LL_HUD_DUR_SHORT); | ||
427 | effectp->setColor(LLColor4U(gAgent.getEffectColor())); | ||
428 | |||
429 | gViewerStats->incStat(LLViewerStats::ST_CREATE_COUNT); | ||
430 | |||
431 | return TRUE; | ||
432 | } | ||
433 | |||
64 | // Used by the placer tool to add copies of the current selection. | 434 | // Used by the placer tool to add copies of the current selection. |
65 | // Inspired by add_object(). JC | 435 | // Inspired by add_object(). JC |
66 | BOOL add_duplicate(S32 x, S32 y) | 436 | BOOL LLToolPlacer::addDuplicate(S32 x, S32 y) |
67 | { | 437 | { |
68 | LLVector3 ray_start_region; | 438 | LLVector3 ray_start_region; |
69 | LLVector3 ray_end_region; | 439 | LLVector3 ray_end_region; |
@@ -71,7 +441,7 @@ BOOL add_duplicate(S32 x, S32 y) | |||
71 | BOOL b_hit_land = FALSE; | 441 | BOOL b_hit_land = FALSE; |
72 | S32 hit_face = -1; | 442 | S32 hit_face = -1; |
73 | LLViewerObject* hit_obj = NULL; | 443 | LLViewerObject* hit_obj = NULL; |
74 | BOOL success = raycast_for_new_obj_pos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp ); | 444 | BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp ); |
75 | if( !success ) | 445 | if( !success ) |
76 | { | 446 | { |
77 | make_ui_sound("UISndInvalidOp"); | 447 | make_ui_sound("UISndInvalidOp"); |
@@ -123,11 +493,11 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask) | |||
123 | 493 | ||
124 | if (gSavedSettings.getBOOL("CreateToolCopySelection")) | 494 | if (gSavedSettings.getBOOL("CreateToolCopySelection")) |
125 | { | 495 | { |
126 | added = add_duplicate(x, y); | 496 | added = addDuplicate(x, y); |
127 | } | 497 | } |
128 | else | 498 | else |
129 | { | 499 | { |
130 | added = add_object( sObjectType, x, y, NO_PHYSICS ); | 500 | added = addObject( sObjectType, x, y, FALSE ); |
131 | } | 501 | } |
132 | 502 | ||
133 | // ...and go back to the default tool | 503 | // ...and go back to the default tool |