1 /*  NAME:
2         E3Main.c
3 
4     DESCRIPTION:
5         Implementation of Quesa API calls.
6 
7     COPYRIGHT:
8         Copyright (c) 1999-2005, Quesa Developers. All rights reserved.
9 
10         For the current release of Quesa, please see:
11 
12             <http://www.quesa.org/>
13 
14         Redistribution and use in source and binary forms, with or without
15         modification, are permitted provided that the following conditions
16         are met:
17 
18             o Redistributions of source code must retain the above copyright
19               notice, this list of conditions and the following disclaimer.
20 
21             o Redistributions in binary form must reproduce the above
22               copyright notice, this list of conditions and the following
23               disclaimer in the documentation and/or other materials provided
24               with the distribution.
25 
26             o Neither the name of Quesa nor the names of its contributors
27               may be used to endorse or promote products derived from this
28               software without specific prior written permission.
29 
30         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31         "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32         LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33         A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34         OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35         SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
36         TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37         PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
38         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39         NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40         SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41     ___________________________________________________________________________
42 */
43 //=============================================================================
44 //      Include files
45 //-----------------------------------------------------------------------------
46 #include <new>
47 
48 #include "E3Prefix.h"
49 #include "E3Version.h"
50 #include "E3View.h"
51 #include "E3Camera.h"
52 #include "E3Geometry.h"
53 #include "E3DrawContext.h"
54 #include "E3Renderer.h"
55 #include "E3Group.h"
56 #include "E3Set.h"
57 #include "E3Light.h"
58 #include "E3Style.h"
59 #include "E3String.h"
60 #include "E3Transform.h"
61 #include "E3Main.h"
62 #include "E3Memory.h"
63 #include "E3Storage.h"
64 #include "E3Pick.h"
65 #include "E3IO.h"
66 #include "E3Shader.h"
67 #include "E3Texture.h"
68 #include "E3CustomElements.h"
69 #include "E3IOFileFormat.h"
70 #include "E3StackCrawl.h"
71 
72 #if QUESA_OS_MACINTOSH
73 // Viewer supported only on Carbon/Classic now
74 #include "E3Viewer.h"
75 #endif
76 
77 
78 
79 
80 
81 //=============================================================================
82 //      Internal types
83 //-----------------------------------------------------------------------------
84 
85 
86 
87 
88 //=============================================================================
89 //      Internal functions
90 //-----------------------------------------------------------------------------
91 //      E3ShapeInfo::E3ShapeInfo : Constructor for class info of root class.
92 //-----------------------------------------------------------------------------
93 
E3ShapeInfo(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)94 E3ShapeInfo::E3ShapeInfo	(
95 				TQ3XMetaHandler	newClassMetaHandler,
96 				E3ClassInfo*	newParent // nil for root class of course
97 			 	)
98 		: E3SharedInfo ( newClassMetaHandler, newParent )
99 	{
100 	// Fill in the method data of the class
101 
102 	// There are (currently) no new methods in shape class
103 	} ;
104 
105 
106 //=============================================================================
107 //      e3shape_new_class_info : Method to construct a class info record.
108 //-----------------------------------------------------------------------------
109 static E3ClassInfo*
e3shape_new_class_info(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)110 e3shape_new_class_info (
111 				TQ3XMetaHandler	newClassMetaHandler,
112 				E3ClassInfo*	newParent
113 			 	)
114 	{
115 	return new ( std::nothrow ) E3ShapeInfo ( newClassMetaHandler, newParent ) ;
116 	}
117 
118 
119 
120 
121 
122 //=============================================================================
123 //      e3shape_metahandler : Shape metahandler.
124 //-----------------------------------------------------------------------------
125 static TQ3XFunctionPointer
e3shape_metahandler(TQ3XMethodType methodType)126 e3shape_metahandler(TQ3XMethodType methodType)
127 {	TQ3XFunctionPointer		theMethod = NULL;
128 
129 
130 
131 	// Return our methods
132 	switch (methodType) {
133 		case kQ3XMethodTypeNewObjectClass:
134 			theMethod = (TQ3XFunctionPointer) e3shape_new_class_info;
135 			break;
136 
137 		}
138 
139 	return(theMethod);
140 }
141 
142 
143 
144 
145 
146 //=============================================================================
147 //      E3SharedInfo::E3SharedInfo : Constructor for class info of root class.
148 //-----------------------------------------------------------------------------
149 #pragma mark -
E3SharedInfo(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)150 E3SharedInfo::E3SharedInfo	(
151 				TQ3XMetaHandler	newClassMetaHandler,
152 				E3ClassInfo*	newParent // nil for root class of course
153 			 	)
154 		: E3Root ( newClassMetaHandler, newParent )
155 	{
156 	// Fill in the method data of the class
157 
158 //	disposeMethod = (TQ3XObjectDisposeMethod) Find_Method ( kQ3XMethodTypeObjectDispose , kQ3True ) ;
159 //	newMethod = (TQ3XObjectNewMethod) Find_Method ( kQ3XMethodTypeObjectNew , kQ3False ) ; // N.B. False, not inherited
160 //	deleteMethod = (TQ3XObjectDeleteMethod) Find_Method ( kQ3XMethodTypeObjectDelete , kQ3False ) ; // N.B. False, not inherited
161 //	duplicateMethod = (TQ3XObjectDuplicateMethod) Find_Method ( kQ3XMethodTypeObjectDuplicate , kQ3False ) ; // N.B. False, not inherited
162 	} ;
163 
164 
165 //=============================================================================
166 //      e3shared_new_class_info : Method to construct a class info record.
167 //-----------------------------------------------------------------------------
168 static E3ClassInfo*
e3shared_new_class_info(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)169 e3shared_new_class_info (
170 				TQ3XMetaHandler	newClassMetaHandler,
171 				E3ClassInfo*	newParent
172 			 	)
173 	{
174 	return new ( std::nothrow ) E3SharedInfo ( newClassMetaHandler, newParent ) ;
175 	}
176 
177 
178 
179 
180 
181 //=============================================================================
182 //      e3shared_new : Shared new method.
183 //-----------------------------------------------------------------------------
184 TQ3Status
e3shared_new(E3Shared * theObject,void * privateData,void * paramData)185 e3shared_new ( E3Shared* theObject, void *privateData, void *paramData )
186 	{
187 #pragma unused(privateData)
188 #pragma unused(paramData)
189 
190 
191 
192 	// Initialise our instance data
193 	theObject->refCount  = 1 ;
194 	theObject->editIndex = 1 ;
195 
196 	return kQ3Success ;
197 	}
198 
199 
200 
201 
202 
203 //=============================================================================
204 //      e3shared_dispose : Shared dispose method.
205 //-----------------------------------------------------------------------------
206 void
e3shared_dispose(E3Shared * theObject)207 e3shared_dispose ( E3Shared* theObject )
208 	{
209 	// Find the instance data
210 	if ( theObject == NULL )
211 		return ;
212 
213 
214 
215 	// Decrement the reference count
216 	Q3_ASSERT(theObject->refCount >= 1);
217 	theObject->refCount--;
218 
219 
220 
221 	// If the reference count falls to 0, dispose of the object
222 	if ( theObject->refCount == 0 )
223 		theObject->DestroyInstance () ;
224 	}
225 
226 
227 
228 
229 
230 //=============================================================================
231 //      e3shared_duplicate : Shared duplicate method.
232 //-----------------------------------------------------------------------------
233 TQ3Status
e3shared_duplicate(TQ3Object fromObject,const void * fromPrivateData,TQ3Object toObject,void * toPrivateData)234 e3shared_duplicate(TQ3Object fromObject,     const void *fromPrivateData,
235 						 TQ3Object toObject, void *toPrivateData)
236 {	E3Shared		*instanceData = (E3Shared *) toObject ;
237 #pragma unused(fromObject)
238 #pragma unused(toPrivateData)
239 
240 
241 
242 	// Validate our parameters
243 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(fromObject),      kQ3Failure);
244 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(fromPrivateData), kQ3Failure);
245 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(toObject),        kQ3Failure);
246 	Q3_REQUIRE_OR_RESULT(Q3_VALID_PTR(toPrivateData),   kQ3Failure);
247 
248 
249 
250 	// Initialise the instance data of the new object
251 	instanceData->refCount  = 1;
252 	instanceData->editIndex = 1;
253 
254 	return(kQ3Success);
255 }
256 
257 
258 
259 
260 
261 //=============================================================================
262 //      e3shared_write : Default write method.
263 //-----------------------------------------------------------------------------
264 static TQ3Status
e3shared_write(TQ3ViewObject theView,TQ3ObjectType objectType,TQ3Object theObject,const void * objectData)265 e3shared_write ( TQ3ViewObject theView, TQ3ObjectType objectType, TQ3Object theObject, const void *objectData )
266 	{
267 	// Submit the object
268 	return E3FileFormat_Method_SubmitObject ( theView, theObject, objectType, objectData ) ;
269 	}
270 
271 
272 
273 
274 
275 //=============================================================================
276 //      e3shared_metahandler : Shared metahandler.
277 //-----------------------------------------------------------------------------
278 static TQ3XFunctionPointer
e3shared_metahandler(TQ3XMethodType methodType)279 e3shared_metahandler(TQ3XMethodType methodType)
280 {	TQ3XFunctionPointer		theMethod = NULL;
281 
282 
283 
284 	// Return our methods
285 	switch (methodType) {
286 		case kQ3XMethodTypeNewObjectClass:
287 			theMethod = (TQ3XFunctionPointer) e3shared_new_class_info;
288 			break;
289 
290 		case kQ3XMethodTypeObjectNew:
291 			theMethod = (TQ3XFunctionPointer) e3shared_new;
292 			break;
293 
294 		case kQ3XMethodTypeObjectDispose:
295 			theMethod = (TQ3XFunctionPointer) e3shared_dispose;
296 			break;
297 
298 		case kQ3XMethodTypeObjectDuplicate:
299 			theMethod = (TQ3XFunctionPointer) e3shared_duplicate;
300 			break;
301 
302 		case kQ3XMethodTypeObjectSubmitWrite:
303 			theMethod = (TQ3XFunctionPointer) e3shared_write;
304 			break;
305 		}
306 
307 	return(theMethod);
308 }
309 
310 
311 
312 
313 
314 //=============================================================================
315 //      E3Root::E3Root : Constructor for class info of root class.
316 //-----------------------------------------------------------------------------
317 #pragma mark -
318 
E3Root(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)319 E3Root::E3Root	(
320 				TQ3XMetaHandler	newClassMetaHandler,
321 				E3ClassInfo*	newParent // nil for root class of course
322 			 	)
323 	: E3ClassInfo ( newClassMetaHandler , newParent ) ,
324 	// Fill in the method data of the class
325 	disposeMethod		( (TQ3XObjectDisposeMethod)		Find_Method ( kQ3XMethodTypeObjectDispose , kQ3True ) ) ,
326 	newMethod			( (TQ3XObjectNewMethod)			Find_Method ( kQ3XMethodTypeObjectNew , kQ3False ) ) , // N.B. False, not inherited
327 	deleteMethod		( (TQ3XObjectDeleteMethod)		Find_Method ( kQ3XMethodTypeObjectDelete , kQ3False ) ) , // N.B. False, not inherited
328 	duplicateMethod		( (TQ3XObjectDuplicateMethod)	Find_Method ( kQ3XMethodTypeObjectDuplicate , kQ3False ) ) , // N.B. False, not inherited
329 	submitRenderMethod	( (TQ3XObjectSubmitMethod)		Find_Method ( kQ3XMethodTypeObjectSubmitRender , kQ3True ) ) ,
330 	submitPickMethod	( (TQ3XObjectSubmitMethod)		Find_Method ( kQ3XMethodTypeObjectSubmitPick , kQ3True ) ) ,
331 	submitBoundsMethod	( (TQ3XObjectSubmitMethod)		Find_Method ( kQ3XMethodTypeObjectSubmitBounds , kQ3True ) ) ,
332 	submitWriteMethod	( (TQ3XObjectSubmitMethod)		Find_Method ( kQ3XMethodTypeObjectSubmitWrite , kQ3True ) )
333 	{
334 	if ( disposeMethod == NULL )
335 		SetAbstract () ;
336 	} ;
337 
338 
339 //=============================================================================
340 //      e3root_new_class_info : Method to construct a class info record for the root class.
341 // This is necessary because applications can register their own object classes based on ours
342 //-----------------------------------------------------------------------------
343 static E3ClassInfo*
e3root_new_class_info(TQ3XMetaHandler newClassMetaHandler,E3ClassInfo * newParent)344 e3root_new_class_info (
345 				TQ3XMetaHandler	newClassMetaHandler,
346 				E3ClassInfo*	newParent // nil for root class of course
347 			 	)
348 	{
349 	return new ( std::nothrow ) E3Root ( newClassMetaHandler, newParent ) ;
350 	}
351 
352 
353 
354 
355 
356 //=============================================================================
357 //      e3root_new : Root object new method.
358 //-----------------------------------------------------------------------------
359 
360 TQ3Status
e3root_new(TQ3Object theObject,void * privateData,void * paramData)361 e3root_new( TQ3Object theObject, void *privateData, void *paramData )
362 {
363 #pragma unused( paramData )
364 #pragma unused( privateData )
365 
366 
367 #if Q3_DEBUG
368 	E3GlobalsPtr	theGlobals = E3Globals_Get();
369 	static TQ3Boolean	sIsMakingListHead = kQ3False;
370 
371 	if (sIsMakingListHead == kQ3True)
372 	{
373 		theObject->next = theObject;
374 		theObject->prev = theObject;
375 		theObject->stackCrawl = NULL;
376 	}
377 	else
378 	{
379 		// initialize instance data
380 		if (theGlobals->isLeakChecking == kQ3True)
381 		{
382 			// make sure the list has a header
383 			if (theGlobals->listHead == NULL)
384 			{
385 				sIsMakingListHead = kQ3True;	// prevent infinite recursion
386 				theGlobals->listHead = E3ClassTree::CreateInstance ( kQ3ObjectTypeRoot,
387 					kQ3False, NULL ) ;
388 				sIsMakingListHead = kQ3False;
389 				Q3_REQUIRE_OR_RESULT( theGlobals->listHead != NULL, kQ3Failure );
390 			}
391 			Q3_ASSERT( theGlobals->listHead->GetClass ()->GetType () == kQ3ObjectTypeRoot ) ;
392 
393 			// insert the new node between the list header and last normal node
394 			theObject->next = theGlobals->listHead;
395 			theObject->prev = PREVLINK( theGlobals->listHead );
396 			NEXTLINK( PREVLINK( theGlobals->listHead ) ) = theObject;
397 			PREVLINK( theGlobals->listHead ) = theObject;
398 
399 			// Record a stack crawl if possible
400 			theObject->stackCrawl = E3StackCrawl_New();
401 		}
402 		else
403 		{
404 			theObject->next = NULL;
405 			theObject->prev = NULL;
406 			theObject->stackCrawl = NULL;
407 		}
408 	}
409 #endif
410 
411 	theObject->theSet = NULL;
412 
413 	return kQ3Success;
414 }
415 
416 
417 
418 
419 
420 //=============================================================================
421 //      e3root_duplicate : Root object duplicate method.
422 //-----------------------------------------------------------------------------
423 TQ3Status
e3root_duplicate(TQ3Object fromObject,const void * fromPrivateData,TQ3Object toObject,void * toPrivateData)424 e3root_duplicate(TQ3Object fromObject,     const void *fromPrivateData,
425 						 TQ3Object toObject, void *toPrivateData)
426 {
427 #pragma unused( fromObject, fromPrivateData )
428 	TQ3Status	q3status;
429 
430 	q3status = e3root_new( toObject, toPrivateData, NULL );
431 
432 	if (q3status == kQ3Success)
433 	{
434 		OpaqueTQ3Object*	fromInstanceData = (OpaqueTQ3Object*) fromPrivateData;
435 		OpaqueTQ3Object*	toInstanceData = (OpaqueTQ3Object*) toPrivateData;
436 
437 
438 		if (fromInstanceData->theSet != NULL)
439 		{
440 			toInstanceData->theSet = Q3Object_Duplicate( fromInstanceData->theSet );
441 			if (toInstanceData->theSet == NULL)
442 			{
443 				q3status = kQ3Failure;
444 			}
445 		}
446 	}
447 
448 	return q3status;
449 }
450 
451 
452 
453 
454 
455 //=============================================================================
456 //      e3root_delete : Root delete method.
457 //-----------------------------------------------------------------------------
458 void
e3root_delete(TQ3Object theObject,void * privateData)459 e3root_delete( TQ3Object theObject, void *privateData )
460 {
461 	OpaqueTQ3Object	*instanceData = (OpaqueTQ3Object *) privateData;
462 
463 	Q3_ASSERT(privateData == theObject);
464 //	Q3_ASSERT(privateData == theObject->FindLeafInstanceData () ) ;
465 
466 	Q3Object_CleanDispose( &instanceData->theSet );
467 
468 #if Q3_DEBUG
469 	if ( instanceData->prev != NULL )
470 	{
471 		NEXTLINK( instanceData->prev ) = instanceData->next;
472 		PREVLINK( instanceData->next ) = instanceData->prev;
473 	}
474 
475 	instanceData->prev = NULL;
476 	instanceData->next = NULL;
477 
478 	E3StackCrawl_Dispose( instanceData->stackCrawl );
479 #endif
480 }
481 
482 
483 
484 
485 
486 //=============================================================================
487 //      e3root_dispose : Root object dispose method.
488 //-----------------------------------------------------------------------------
489 static void
e3root_dispose(TQ3Object theObject)490 e3root_dispose(TQ3Object theObject)
491 	{
492 	// Dispose of the object
493 	theObject->DestroyInstance () ;
494 	}
495 
496 
497 
498 
499 
500 //=============================================================================
501 //      e3root_metahandler : Root object metahandler.
502 //-----------------------------------------------------------------------------
503 static TQ3XFunctionPointer
e3root_metahandler(TQ3XMethodType methodType)504 e3root_metahandler(TQ3XMethodType methodType)
505 {	TQ3XFunctionPointer		theMethod = NULL;
506 
507 
508 
509 	// Return our methods
510 	switch (methodType) {
511 		case kQ3XMethodTypeObjectClassVersion:
512 			theMethod = (TQ3XFunctionPointer) kQ3PackedVersion;
513 			break;
514 
515 		case kQ3XMethodTypeNewObjectClass:
516 			theMethod = (TQ3XFunctionPointer) e3root_new_class_info;
517 			break;
518 
519 		case kQ3XMethodTypeObjectDispose:
520 			theMethod = (TQ3XFunctionPointer) e3root_dispose;
521 			break;
522 
523 		case kQ3XMethodTypeObjectNew:
524 			theMethod = (TQ3XFunctionPointer) e3root_new;
525 			break;
526 
527 		case kQ3XMethodTypeObjectDelete:
528 			theMethod = (TQ3XFunctionPointer) e3root_delete;
529 			break;
530 
531 		case kQ3XMethodTypeObjectDuplicate:
532 			theMethod = (TQ3XFunctionPointer) e3root_duplicate;
533 			break;
534 		}
535 
536 	return(theMethod);
537 }
538 
539 
540 
541 
542 
543 //=============================================================================
544 //      e3main_registercoreclasses : Register the core object classes.
545 //-----------------------------------------------------------------------------
546 #pragma mark -
547 static TQ3Status
e3main_registercoreclasses(void)548 e3main_registercoreclasses(void)
549 	{
550 	// Register the classes
551 	TQ3Status qd3dStatus = E3ClassTree::RegisterClass (
552 											kQ3ObjectTypeQuesa,
553 											OpaqueTQ3Object::eClassType,
554 											kQ3ClassNameRoot,
555 											e3root_metahandler,
556 											sizeof ( OpaqueTQ3Object )
557 											);
558 
559 	if (qd3dStatus == kQ3Success)
560 		qd3dStatus = Q3_REGISTER_CLASS (		kQ3ClassNameShared,
561 												e3shared_metahandler,
562 												E3Shared ) ;
563 
564 	if (qd3dStatus == kQ3Success)
565 		qd3dStatus = Q3_REGISTER_CLASS (		kQ3ClassNameShape,
566 												e3shape_metahandler,
567 												E3Shape ) ;
568 
569 	return qd3dStatus ;
570 	}
571 
572 
573 
574 
575 //=============================================================================
576 //      e3main_unregistercoreclasses : Unregister the core object classes.
577 //-----------------------------------------------------------------------------
578 static TQ3Status
e3main_unregistercoreclasses(void)579 e3main_unregistercoreclasses(void)
580 	{
581 	// Unregister the classes. Unregistering the root class will
582 	// unregister everything else anchored underneath it.
583 	return E3ClassTree::UnregisterClass ( kQ3ObjectTypeRoot, kQ3True ) ;
584 	}
585 
586 
587 
588 
589 
590 //=============================================================================
591 //      Public functions
592 //-----------------------------------------------------------------------------
593 //      E3Initialize : Initialise Quesa.
594 //-----------------------------------------------------------------------------
595 #pragma mark -
596 TQ3Status
E3Initialize(void)597 E3Initialize(void)
598 {	E3GlobalsPtr	theGlobals = E3Globals_Get();
599 	TQ3Status		qd3dStatus = kQ3Success;
600 
601 
602 	// If we've not initialised Quesa yet, do so now
603 	if (!theGlobals->systemInitialised)
604 		{
605 		// Initialise the platform
606 		qd3dStatus = E3System_Initialise();
607 
608 
609 
610 		// Initialise Quesa
611 		if (qd3dStatus == kQ3Success)
612 			qd3dStatus = e3main_registercoreclasses();
613 
614 		if (qd3dStatus == kQ3Success)
615 			qd3dStatus = E3Memory_RegisterClass();
616 
617 		if (qd3dStatus == kQ3Success)
618 			qd3dStatus = E3String_RegisterClass();
619 
620 		if (qd3dStatus == kQ3Success)
621 			qd3dStatus = E3Transform_RegisterClass();
622 
623 		if (qd3dStatus == kQ3Success)
624 			qd3dStatus = E3Group_RegisterClass();
625 
626 		if (qd3dStatus == kQ3Success)
627 			qd3dStatus = E3Set_RegisterClass();
628 
629 		if (qd3dStatus == kQ3Success)
630 			qd3dStatus = E3Light_RegisterClass();
631 
632 		if (qd3dStatus == kQ3Success)
633 			qd3dStatus = E3Style_RegisterClass();
634 
635 		if (qd3dStatus == kQ3Success)
636 			qd3dStatus = E3View_RegisterClass();
637 
638 		if (qd3dStatus == kQ3Success)
639 			qd3dStatus = E3DrawContext_RegisterClass();
640 
641 		if (qd3dStatus == kQ3Success)
642 			qd3dStatus = E3Camera::RegisterClass();
643 
644 		if (qd3dStatus == kQ3Success)
645 			qd3dStatus = E3Geometry_RegisterClass();
646 
647 		if (qd3dStatus == kQ3Success)
648 			qd3dStatus = E3Shader_RegisterClass();
649 
650 		if (qd3dStatus == kQ3Success)
651 			qd3dStatus = E3Texture_RegisterClass();
652 
653 		if (qd3dStatus == kQ3Success)
654 			qd3dStatus = E3Renderer_RegisterClass();
655 
656 		if (qd3dStatus == kQ3Success)
657 			qd3dStatus = E3Storage_RegisterClass();
658 
659 		if (qd3dStatus == kQ3Success)
660 			qd3dStatus = E3File_RegisterClass();
661 
662 		if (qd3dStatus == kQ3Success)
663 			qd3dStatus = E3Pick_RegisterClass();
664 
665 		if (qd3dStatus == kQ3Success)
666 			qd3dStatus = E3CustomElements_RegisterClass();
667 
668 		#if QUESA_OS_MACINTOSH
669 		// Viewer  supported only on Carbon/Classic
670 		if (qd3dStatus == kQ3Success)
671 			qd3dStatus = E3Viewer_RegisterClass();
672 		#endif
673 
674 
675 
676 		// Load our plug-ins
677 		if (qd3dStatus == kQ3Success)
678 			E3System_LoadPlugins();
679 
680 
681 
682 		// Set our flag
683 		if (qd3dStatus == kQ3Success)
684 			theGlobals->systemInitialised = kQ3True;
685 		}
686 
687 
688 	// Or post a notice
689 	else
690 		E3ErrorManager_PostNotice(kQ3NoticeSystemAlreadyInitialized);
691 
692 
693 
694 	// If all went well, increment the reference count
695 	if (qd3dStatus == kQ3Success)
696 		theGlobals->systemRefCount++;
697 
698 	return(qd3dStatus);
699 }
700 
701 
702 
703 
704 
705 //=============================================================================
706 //      E3Exit : Terminate Quesa.
707 //-----------------------------------------------------------------------------
708 TQ3Status
E3Exit(void)709 E3Exit(void)
710 {	E3GlobalsPtr	theGlobals = E3Globals_Get();
711 	TQ3Status		qd3dStatus;
712 
713 
714 
715 	// Make sure we've been initialised
716 	if (!theGlobals->systemInitialised)
717 		return(kQ3Failure);
718 
719 
720 
721 	// Decrement the instance count
722 	Q3_ASSERT(theGlobals->systemRefCount > 0);
723 	theGlobals->systemRefCount--;
724 
725 
726 
727 	// If this was the last instance, terminate Quesa
728 	if (theGlobals->systemRefCount == 0)
729 		{
730 		// Dump some stats
731 #if QUESA_DUMP_STATS_ON_EXIT
732 		E3ClassTree::Dump () ;
733 #endif
734 
735 #if QUESA_ALLOW_QD3D_EXTENSIONS && Q3_DEBUG
736 		if ( Q3Memory_IsRecording() && (Q3Memory_CountRecords() > 0) )
737 		{
738 			E3ErrorManager_PostError( kQ3ErrorMemoryLeak, kQ3False );
739 			Q3Memory_DumpRecording( "Quesa-leaks.txt", "Q3Exit" );
740 			Q3Memory_ForgetRecording();
741 		}
742 #endif
743 
744 
745 
746 		// Reset leak-checking globals to initial state
747 #if Q3_DEBUG
748 		Q3Object_CleanDispose(&theGlobals->listHead );
749 		theGlobals->isLeakChecking = kQ3False;
750 #endif
751 
752 
753 
754 		// Unload our plug-ins
755 		E3System_UnloadPlugins();
756 
757 
758 
759 		// Terminate Quesa
760 		#if QUESA_OS_MACINTOSH
761 		// Viewer  supported only on Carbon/Classic
762 		qd3dStatus = E3Viewer_UnregisterClass();
763 		#endif
764 		qd3dStatus = E3CustomElements_UnregisterClass();
765 		qd3dStatus = E3Pick_UnregisterClass();
766 		qd3dStatus = E3File_UnregisterClass();
767 		qd3dStatus = E3Storage_UnregisterClass();
768 		qd3dStatus = E3Renderer_UnregisterClass();
769 		qd3dStatus = E3Texture_UnregisterClass();
770 		qd3dStatus = E3Shader_UnregisterClass();
771 		qd3dStatus = E3Geometry_UnregisterClass();
772 		qd3dStatus = E3Camera::UnregisterClass();
773 		qd3dStatus = E3DrawContext_UnregisterClass();
774 		qd3dStatus = E3View_UnregisterClass();
775 		qd3dStatus = E3Style_UnregisterClass();
776 		qd3dStatus = E3Light_UnregisterClass();
777 		qd3dStatus = E3Set_UnregisterClass();
778 		qd3dStatus = E3Group_UnregisterClass();
779 		qd3dStatus = E3Transform_UnregisterClass();
780 		qd3dStatus = E3String_UnregisterClass();
781 		qd3dStatus = E3Memory_UnregisterClass();
782 		qd3dStatus = e3main_unregistercoreclasses();
783 		E3ClassTree::Destroy () ;
784 
785 
786 
787 		// Terminate the platform
788 		E3System_Terminate();
789 
790 
791 
792 		// Set our flag
793 		theGlobals->systemInitialised = kQ3False;
794 		}
795 
796 	return(kQ3Success);
797 }
798 
799 
800 
801 
802 
803 //=============================================================================
804 //      E3IsInitialized : Test to see if Quesa has been initialised.
805 //-----------------------------------------------------------------------------
806 TQ3Boolean
E3IsInitialized(void)807 E3IsInitialized(void)
808 {	E3GlobalsPtr	theGlobals = E3Globals_Get();
809 
810 
811 
812 	// Return as we've initialised Quesa
813 	return(theGlobals->systemInitialised);
814 }
815 
816 
817 
818 
819 
820 //=============================================================================
821 //      E3GetVersion : Return the build version.
822 //-----------------------------------------------------------------------------
823 //		Note :	kQ3MajorVersion and kQ3MinorVersion are each in BCD format.
824 //				For example, 12 is represented as 0x12.
825 //
826 //				May be called outside of a Q3Initialize/Q3Exit block.
827 //-----------------------------------------------------------------------------
828 TQ3Status
E3GetVersion(TQ3Uns32 * majorRevision,TQ3Uns32 * minorRevision)829 E3GetVersion(TQ3Uns32 *majorRevision, TQ3Uns32 *minorRevision)
830 {
831 
832 
833 	// Return the build version
834 	*majorRevision = 10 * (kQ3MajorVersion >> 4) + (kQ3MajorVersion & 0x0f);
835 	if (kQ3MinorVersion & 0x0f)
836 		*minorRevision = 10 * (kQ3MinorVersion >> 4) + (kQ3MinorVersion & 0x0f);
837 	else // single-digit minor version
838 		*minorRevision = (kQ3MinorVersion >> 4);
839 
840 	return(kQ3Success);
841 }
842 
843 
844 
845 
846 
847 //=============================================================================
848 //      E3GetReleaseVersion : Return the build version in 'vers' format.
849 //-----------------------------------------------------------------------------
850 //		Note :	We return the version number in the format of the first four
851 //				bytes of a 'vers' resource. For example, "1.23a56" is
852 //				represented as 0x01234056.
853 //
854 //				For more information, see the description of the 'vers'
855 //				resource in "Inside Macintosh: Macintosh Toolbox Essential",
856 //				p. 7-69.
857 //
858 //				May be called outside of a Q3Initialize/Q3Exit block.
859 //-----------------------------------------------------------------------------
860 TQ3Status
E3GetReleaseVersion(TQ3Uns32 * releaseRevision)861 E3GetReleaseVersion(TQ3Uns32 *releaseRevision)
862 {
863 
864 
865 	// Return the release version
866 	*releaseRevision = kQ3PackedVersion;
867 
868 	return(kQ3Success);
869 }
870 
871 
872 
873 
874 
875 //=============================================================================
876 //      E3ObjectHierarchy_GetTypeFromString : Find the type for a class.
877 //-----------------------------------------------------------------------------
878 //		Note : Given a class name, returns the type of the class.
879 //-----------------------------------------------------------------------------
880 #pragma mark -
881 TQ3Status
E3ObjectHierarchy_GetTypeFromString(const TQ3ObjectClassNameString objectClassString,TQ3ObjectType * objectClassType)882 E3ObjectHierarchy_GetTypeFromString(const TQ3ObjectClassNameString objectClassString, TQ3ObjectType *objectClassType)
883 	{
884 	// Initialise a return value
885 	*objectClassType = kQ3ObjectTypeInvalid ;
886 
887 
888 
889 	// Find the class
890 	E3ClassInfoPtr theClass = E3ClassTree::GetClass ( objectClassString ) ;
891 	if ( theClass == NULL )
892 		return kQ3Failure ;
893 
894 
895 
896 	// Return the type
897 	*objectClassType = theClass->GetType () ;
898 	return kQ3Success ;
899 	}
900 
901 
902 
903 
904 
905 //=============================================================================
906 //      E3ObjectHierarchy_GetStringFromType : Find the name for a class.
907 //-----------------------------------------------------------------------------
908 //		Note : Given a class type, returns the name of the class.
909 //-----------------------------------------------------------------------------
910 TQ3Status
E3ObjectHierarchy_GetStringFromType(TQ3ObjectType objectClassType,TQ3ObjectClassNameString objectClassString)911 E3ObjectHierarchy_GetStringFromType(TQ3ObjectType objectClassType, TQ3ObjectClassNameString objectClassString)
912 	{
913 	// Initialise a return value
914 	strcpy ( objectClassString, "" ) ;
915 
916 
917 
918 	// Find the class
919 	E3ClassInfoPtr theClass = E3ClassTree::GetClass ( objectClassType ) ;
920 	if ( theClass == NULL )
921 		return kQ3Failure ;
922 
923 
924 
925 	// Return the name
926 	strcpy ( objectClassString, theClass->GetName () ) ;
927 	return kQ3Success ;
928 	}
929 
930 
931 
932 
933 
934 //=============================================================================
935 //      E3ObjectHierarchy_IsTypeRegistered : Test if a class is registered.
936 //-----------------------------------------------------------------------------
937 TQ3Boolean
E3ObjectHierarchy_IsTypeRegistered(TQ3ObjectType objectClassType)938 E3ObjectHierarchy_IsTypeRegistered(TQ3ObjectType objectClassType)
939 	{
940 	// Find the class
941 	E3ClassInfoPtr theClass = E3ClassTree::GetClass ( objectClassType ) ;
942 
943 	return theClass != NULL ? kQ3True : kQ3False ;
944 	}
945 
946 
947 
948 
949 
950 //=============================================================================
951 //      E3ObjectHierarchy_IsNameRegistered : Test if a class is registered.
952 //-----------------------------------------------------------------------------
953 TQ3Boolean
E3ObjectHierarchy_IsNameRegistered(const char * objectClassName)954 E3ObjectHierarchy_IsNameRegistered(const char *objectClassName)
955 	{
956 	// Find the class
957 	E3ClassInfoPtr theClass = E3ClassTree::GetClass ( objectClassName ) ;
958 
959 	return theClass != NULL ? kQ3True : kQ3False ;
960 	}
961 
962 
963 
964 
965 
966 //=============================================================================
967 //      E3ObjectHierarchy_GetSubClassData : Get the sub-classes of a class.
968 //-----------------------------------------------------------------------------
969 //		Note :	Fills in subClassData with the number and class types of all of
970 //				the subclasses immediately below the specified class.
971 //-----------------------------------------------------------------------------
972 TQ3Status
E3ObjectHierarchy_GetSubClassData(TQ3ObjectType objectClassType,TQ3SubClassData * subClassData)973 E3ObjectHierarchy_GetSubClassData(TQ3ObjectType objectClassType, TQ3SubClassData *subClassData)
974 	{
975 	// Initialise a return value
976 	subClassData->numClasses = 0;
977 	subClassData->classTypes = NULL;
978 
979 
980 
981 	// Find the class
982 	E3ClassInfoPtr theClass = E3ClassTree::GetClass ( objectClassType ) ;
983 	if ( theClass == NULL )
984 		return kQ3Failure ;
985 
986 
987 
988 	// Allocate the array for the child classes
989 	Q3Memory_Clear(subClassData, sizeof(TQ3SubClassData));
990 
991 	TQ3Uns32 numChildren = theClass->GetNumChildren () ;
992 	if (numChildren != 0)
993 		{
994 		subClassData->classTypes = (TQ3ObjectType *) Q3Memory_Allocate(sizeof(TQ3ObjectType) * numChildren);
995 		if (subClassData->classTypes == NULL)
996 			return(kQ3Failure);
997 
998 		subClassData->numClasses = numChildren;
999 		}
1000 
1001 
1002 
1003 	// Collect the child classes
1004 	for ( TQ3Uns32 n = 0 ; n < numChildren ; ++n )
1005 		{
1006 		// Get the child
1007 		E3ClassInfoPtr theChild = theClass->GetChild ( n ) ;
1008 		Q3_ASSERT_VALID_PTR(theChild);
1009 
1010 
1011 		// Grab the type
1012 		subClassData->classTypes [ n ] = theChild->GetType () ;
1013 		}
1014 
1015 	return kQ3Success ;
1016 	}
1017 
1018 
1019 
1020 
1021 
1022 //=============================================================================
1023 //      E3ObjectHierarchy_EmptySubClassData : Dispose of the sub-class data.
1024 //-----------------------------------------------------------------------------
1025 TQ3Status
E3ObjectHierarchy_EmptySubClassData(TQ3SubClassData * subClassData)1026 E3ObjectHierarchy_EmptySubClassData(TQ3SubClassData *subClassData)
1027 {
1028 
1029 
1030 	// Dispose of the data
1031 	Q3Memory_Free(&subClassData->classTypes);
1032 
1033 
1034 
1035 	// Reset the structure
1036 	subClassData->numClasses = 0;
1037 	subClassData->classTypes = NULL;
1038 
1039 	return(kQ3Success);
1040 }
1041 
1042 
1043 
1044 
1045 
1046 //=============================================================================
1047 //      E3Object_Dispose : Dispose of an object.
1048 //-----------------------------------------------------------------------------
1049 #pragma mark -
1050 TQ3Status
Dispose(void)1051 OpaqueTQ3Object::Dispose ( void )
1052 	{
1053 
1054 	// Dispose of the object
1055 	 ( (E3Root*) GetClass () )->disposeMethod ( this ) ;
1056 
1057 	return kQ3Success ;
1058 	}
1059 
1060 
1061 
1062 
1063 
1064 //=============================================================================
1065 //      E3Object_CleanDispose : Dispose of an object.
1066 //-----------------------------------------------------------------------------
1067 TQ3Status
E3Object_CleanDispose(TQ3Object * theObject)1068 E3Object_CleanDispose(TQ3Object *theObject)
1069 {	TQ3Status		qd3dStatus;
1070 
1071 
1072 
1073 	// If we have an object, dispose of it and clear the pointer
1074 	if (theObject != NULL && *theObject != NULL)
1075 		{
1076 		qd3dStatus = Q3Object_Dispose(*theObject);
1077 		*theObject = NULL;
1078 		}
1079 	else
1080 		qd3dStatus = kQ3Success;
1081 
1082 	return(qd3dStatus);
1083 }
1084 
1085 
1086 
1087 
1088 
1089 //=============================================================================
1090 //      E3Object_Duplicate : Duplicate an object.
1091 //-----------------------------------------------------------------------------
1092 //		Note :	Draw context and view objects can not be duplicated, since
1093 //				these refer to resources created by the application that belong
1094 //				to the window system.
1095 //
1096 //				If the new object is a shared object, its reference count is
1097 //				set to 1.
1098 //-----------------------------------------------------------------------------
1099 TQ3Object
E3Object_Duplicate(TQ3Object theObject)1100 E3Object_Duplicate(TQ3Object theObject)
1101 	{
1102 	// Reject draw context and view objects
1103 	//
1104 	// Note - the current Quesa implementation does not support
1105 	// duplicating file storage objects, as opposed to memory storage objects.
1106 	//
1107 	// When this is functionality is added, the kQ3SharedTypeStorage
1108 	// test should be removed.
1109 	//
1110 	// If this causes your app problems, please contact Jose Cruanyes
1111 	// or James Walker to discuss a fix.
1112 	if ( E3View_IsOfMyClass ( theObject ) // Can't access E3View here as it isn't in a header file (yet)
1113 	|| Q3_OBJECT_IS_CLASS ( theObject, E3DrawContext )
1114 	|| ( Q3_OBJECT_IS_CLASS ( theObject, E3Storage ) && ! Q3_OBJECT_IS_CLASS ( theObject, E3MemoryStorage ) ) )
1115 		{
1116 		E3ErrorManager_PostError(kQ3ErrorInvalidObjectType, kQ3False);
1117 		return(NULL);
1118 		}
1119 
1120 
1121 
1122 	// Duplicate the object
1123 	return theObject->DuplicateInstance () ;
1124 	}
1125 
1126 
1127 
1128 
1129 
1130 //=============================================================================
1131 //      E3Object_Submit : Submit an object to a view.
1132 //-----------------------------------------------------------------------------
1133 TQ3Status
E3Object_Submit(TQ3Object theObject,TQ3ViewObject theView)1134 E3Object_Submit(TQ3Object theObject, TQ3ViewObject theView)
1135 {	TQ3Status		qd3dStatus;
1136 
1137 
1138 
1139 	// Submit the object
1140 	qd3dStatus = E3View_SubmitRetained(theView, theObject);
1141 	return(qd3dStatus);
1142 }
1143 
1144 
1145 
1146 
1147 
1148 //=============================================================================
1149 //      E3Object_IsDrawable : Determine if an object is drawable.
1150 //-----------------------------------------------------------------------------
1151 //		Note :	There is no is-drawable method as such, instead we interpret
1152 //				the 'address' of the method as a TQ3Boolean.
1153 //-----------------------------------------------------------------------------
1154 TQ3Boolean
E3Object_IsDrawable(TQ3Object theObject)1155 E3Object_IsDrawable(TQ3Object theObject)
1156 	{
1157 	// Get the 'method'
1158 	TQ3Boolean isDrawable = (TQ3Boolean) ( NULL != theObject->GetClass ()->GetMethod (
1159 									kQ3XMethodTypeObjectIsDrawable ) ) ;
1160 
1161 	return isDrawable ;
1162 	}
1163 
1164 
1165 
1166 
1167 
1168 //=============================================================================
1169 //      E3Object_IsWritable : Determine if an object is writeable.
1170 //-----------------------------------------------------------------------------
1171 //		Note : We return as the object has a kQ3XMethodTypeObjectWrite method.
1172 //-----------------------------------------------------------------------------
1173 TQ3Boolean
E3Object_IsWritable(TQ3Object theObject,TQ3FileObject theFile)1174 E3Object_IsWritable(TQ3Object theObject, TQ3FileObject theFile)
1175 	{
1176 #pragma unused(theFile)
1177 
1178 
1179 
1180 	// Get the method
1181 	TQ3XObjectWriteMethod writeMethod = (TQ3XObjectWriteMethod) theObject->GetClass ()->GetMethod ( kQ3XMethodTypeObjectWrite ) ;
1182 
1183 
1184 
1185 	// Return as the method exists or not
1186 	return (TQ3Boolean) ( writeMethod != NULL ) ;
1187 	}
1188 
1189 
1190 
1191 
1192 
1193 //=============================================================================
1194 //      E3Object_GetType : Get the fundamental type of an object.
1195 //-----------------------------------------------------------------------------
1196 //		Note :	To determine the fundamental type, we walk up the object's
1197 //				parents until we come to the level below the root object.
1198 //
1199 //				NB - we can not filter the result, since some undocumented QD3D
1200 //				objects are registered off the root object.
1201 //-----------------------------------------------------------------------------
1202 TQ3ObjectType
E3Object_GetType(TQ3Object theObject)1203 E3Object_GetType(TQ3Object theObject)
1204 	{
1205 	// Get the type of the object below the root object
1206 	return theObject->GetObjectType ( kQ3ObjectTypeRoot ) ;
1207 	}
1208 
1209 
1210 
1211 
1212 
1213 //=============================================================================
1214 //      E3Object_IsType : Is an object an instance of a particular type?
1215 //-----------------------------------------------------------------------------
1216 TQ3Boolean
E3Object_IsType(TQ3Object theObject,TQ3ObjectType theType)1217 E3Object_IsType(TQ3Object theObject, TQ3ObjectType theType)
1218 	{
1219 	// Return as the object is an instance of the type
1220 	return theObject->GetClass ()->IsType ( theType ) ;
1221 	}
1222 
1223 
1224 
1225 
1226 
1227 //=============================================================================
1228 //      E3Object_AddElement : Add an element to an object
1229 //-----------------------------------------------------------------------------
1230 TQ3Status
AddElement(TQ3ElementType theType,const void * theData)1231 OpaqueTQ3Object::AddElement ( TQ3ElementType theType, const void *theData )
1232 	{
1233 	// Translate public type to internal type for set elements
1234 	if ( theType == kQ3ElementTypeSet )
1235 		theType = kQ3ObjectTypeSetElement;
1236 
1237 
1238 
1239 	// If we've actually been passed a set, use it directly
1240 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1241 		return Q3Set_Add ( (TQ3SetObject) this, theType, theData ) ;
1242 
1243 	// otherwise use the set within the instance data
1244 	if ( theSet == NULL )
1245 		{
1246 		theSet = Q3Set_New () ;
1247 
1248 		if ( theSet == NULL )
1249 			return kQ3Failure ;
1250 		}
1251 
1252 	TQ3Status qd3dStatus = Q3Set_Add ( theSet, theType, theData ) ;
1253 
1254 
1255 	if ( ( qd3dStatus != kQ3Failure ) && Q3_OBJECT_IS_CLASS ( this, E3Shared ) )
1256 		( (E3Shared*) this )->Edited () ;
1257 
1258 	return qd3dStatus ;
1259 	}
1260 
1261 
1262 
1263 
1264 
1265 //=============================================================================
1266 //      E3Object_GetElement : Get element data from an object.
1267 //-----------------------------------------------------------------------------
1268 TQ3Status
GetElement(TQ3ElementType theType,void * theData)1269 OpaqueTQ3Object::GetElement ( TQ3ElementType theType, void *theData )
1270 	{
1271 	// Translate public type to internal type for set elements
1272 	if (theType == kQ3ElementTypeSet)
1273 		theType = kQ3ObjectTypeSetElement;
1274 
1275 
1276 
1277 	// If we've actually been passed a set, use it directly
1278 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1279 		return Q3Set_Get ( (TQ3SetObject) this, theType, theData ) ;
1280 
1281 	// otherwise use the set within the instance data
1282 
1283 	if ( theSet == NULL )
1284 		return kQ3Failure ;
1285 
1286 	return Q3Set_Get ( theSet, theType, (void*)theData ) ;
1287 	}
1288 
1289 
1290 
1291 
1292 
1293 //=============================================================================
1294 //      E3Object_ContainsElement : Test whether an object contains an element.
1295 //-----------------------------------------------------------------------------
1296 TQ3Boolean
ContainsElement(TQ3ElementType theType)1297 OpaqueTQ3Object::ContainsElement ( TQ3ElementType theType )
1298 	{
1299 	// Translate public type to internal type for set elements
1300 	if ( theType == kQ3ElementTypeSet )
1301 		theType = kQ3ObjectTypeSetElement ;
1302 
1303 
1304 
1305 	// If we've actually been passed a set, use it directly
1306 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1307 		return Q3Set_Contains ( (TQ3SetObject) this, theType ) ;
1308 
1309 	// otherwise use the set within the instance data
1310 
1311 	if ( theSet != NULL )
1312 		return Q3Set_Contains ( theSet, theType ) ;
1313 
1314 
1315 
1316 	return kQ3False ;
1317 	}
1318 
1319 
1320 
1321 
1322 
1323 //=============================================================================
1324 //      E3Object_GetNextElementType : Get the next element type in an object.
1325 //-----------------------------------------------------------------------------
1326 TQ3Status
GetNextElementType(TQ3ElementType * theType)1327 OpaqueTQ3Object::GetNextElementType ( TQ3ElementType *theType )
1328 	{
1329 	TQ3Status qd3dStatus = kQ3Failure ;
1330 
1331 
1332 
1333 	// Translate public type to internal type for set elements
1334 	if ( *theType == kQ3ElementTypeSet )
1335 		*theType = kQ3ObjectTypeSetElement ;
1336 
1337 
1338 
1339 	// If we've actually been passed a set, use it directly
1340 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1341 		qd3dStatus = Q3Set_GetNextElementType ( (TQ3SetObject) this, theType ) ;
1342 	else	// otherwise use the set within the instance data
1343 		{
1344 		if ( theSet == NULL )
1345 			{
1346 			*theType = kQ3ElementTypeNone ;
1347 			return kQ3Success ;
1348 			}
1349 
1350 		qd3dStatus = Q3Set_GetNextElementType ( theSet, theType ) ;
1351 		}
1352 
1353 
1354 
1355 	if ( *theType == kQ3ObjectTypeSetElement )
1356 		*theType = kQ3ElementTypeSet ;
1357 
1358 
1359 	return qd3dStatus ;
1360 	}
1361 
1362 
1363 
1364 
1365 
1366 //=============================================================================
1367 //      E3Object_EmptyElements : Remove all elements from an object.
1368 //-----------------------------------------------------------------------------
1369 TQ3Status
EmptyElements(void)1370 OpaqueTQ3Object::EmptyElements ( void )
1371 	{
1372 	// If we've actually been passed a set, use it directly
1373 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1374 		return Q3Set_Empty ( (TQ3SetObject) this ) ;
1375 
1376 	// otherwise use the set within the instance data
1377 	if ( theSet == NULL )
1378 		return kQ3Success ;
1379 
1380 	TQ3Status qd3dStatus = Q3Set_Empty ( theSet ) ;
1381 
1382 
1383 	if ( ( qd3dStatus != kQ3Failure ) && Q3_OBJECT_IS_CLASS ( this, E3Shared ) )
1384 		( (E3Shared*) this )->Edited () ;
1385 
1386 
1387 	return qd3dStatus ;
1388 	}
1389 
1390 
1391 
1392 
1393 
1394 //=============================================================================
1395 //      E3Object_ClearElement : Remove a specific type of element from an object.
1396 //-----------------------------------------------------------------------------
1397 TQ3Status
ClearElement(TQ3ElementType theType)1398 OpaqueTQ3Object::ClearElement ( TQ3ElementType theType )
1399 	{
1400 	// Translate public type to internal type for set elements
1401 	if (theType == kQ3ElementTypeSet)
1402 		theType = kQ3ObjectTypeSetElement;
1403 
1404 
1405 
1406 	// If we've actually been passed a set, use it directly
1407 	if ( Q3_OBJECT_IS_CLASS ( this, E3Set ) )
1408 		return Q3Set_Clear ( (TQ3SetObject) this, theType ) ;
1409 
1410 	// otherwise use the set within the instance data
1411 	if ( theSet == NULL )
1412 		return kQ3Success ;
1413 
1414 	TQ3Status qd3dStatus = Q3Set_Clear ( theSet, theType ) ;
1415 
1416 
1417 	if ( ( qd3dStatus != kQ3Failure ) && Q3_OBJECT_IS_CLASS ( this, E3Shared ) )
1418 		( (E3Shared*) this )->Edited () ;
1419 
1420 
1421 	return qd3dStatus ;
1422 	}
1423 
1424 
1425 
1426 
1427 
1428 //=============================================================================
1429 //      E3Object_GetSet : Get the set of an object.
1430 //-----------------------------------------------------------------------------
1431 TQ3Status
GetSet(TQ3SetObject * set)1432 OpaqueTQ3Object::GetSet ( TQ3SetObject *set )
1433 	{
1434 	E3Shared_Acquire ( set, theSet ) ;
1435 
1436 	return kQ3Success ;
1437 	}
1438 
1439 
1440 
1441 
1442 
1443 //=============================================================================
1444 //      E3Object_SetSet : Set the set of an object.
1445 //-----------------------------------------------------------------------------
1446 TQ3Status
SetSet(TQ3SetObject set)1447 OpaqueTQ3Object::SetSet ( TQ3SetObject set )
1448 	{
1449 	E3Shared_Replace ( &theSet, set ) ;
1450 
1451 	return kQ3Success ;
1452 	}
1453 
1454 
1455 
1456 
1457 
1458 //=============================================================================
1459 //      E3Shared_IsOfMyClass : Check if object pointer is valid and of type shared
1460 //-----------------------------------------------------------------------------
1461 //		Replaces Q3Object_IsType ( object, kQ3ObjectTypeShared )
1462 //		but call is smaller and does not call E3System_Bottleneck
1463 //		as this is (always?) done in the calling code as well
1464 //-----------------------------------------------------------------------------
1465 #pragma mark -
1466 TQ3Boolean
E3Shared_IsOfMyClass(TQ3Object object)1467 E3Shared_IsOfMyClass ( TQ3Object object )
1468 	{
1469 	if ( object == NULL )
1470 		return kQ3False ;
1471 
1472 	if ( object->IsObjectValid () )
1473 		return Q3_OBJECT_IS_CLASS ( object, E3Shared ) ;
1474 
1475 	return kQ3False ;
1476 	}
1477 
1478 
1479 
1480 
1481 
1482 //=============================================================================
1483 //      E3Shared_GetType : Get the type of a shared object.
1484 //-----------------------------------------------------------------------------
1485 TQ3ObjectType
E3Shared_GetType(TQ3SharedObject sharedObject)1486 E3Shared_GetType(TQ3SharedObject sharedObject)
1487 	{
1488 	// Return the type
1489 	return sharedObject->GetObjectType ( kQ3ObjectTypeShared ) ;
1490 	}
1491 
1492 
1493 
1494 
1495 
1496 //=============================================================================
1497 //      E3Shared_GetReference : Get a reference to a shared object.
1498 //-----------------------------------------------------------------------------
1499 //		Note :	We increase the reference count of the shared object by 1.
1500 //
1501 //				Note that other Quesa code assumes acquiring a new reference
1502 //				to an object can not fail, provided the object is in fact a
1503 //				shared object.
1504 //
1505 //				If acquiring a new reference could ever fail, routines like
1506 //				E3Shared_Replace will need to be updated.
1507 //-----------------------------------------------------------------------------
1508 E3Shared*
GetReference(void)1509 E3Shared::GetReference ( void )
1510 	{
1511 	// Increment the reference count and return the object. Note that we
1512 	// return the object passed in: this is OK since we're not declared
1513 	// to return a different object.
1514 	refCount++;
1515 	Q3_ASSERT(refCount >= 2);
1516 
1517 	return this ;
1518 	}
1519 
1520 
1521 
1522 
1523 
1524 //=============================================================================
1525 //      E3Shared_IsReferenced : Is a reference shared?
1526 //-----------------------------------------------------------------------------
1527 //		Note :	We return kQ3True if there is more than one reference to the
1528 //				object, and kQ3False if there is one reference to the object.
1529 //-----------------------------------------------------------------------------
1530 TQ3Boolean
IsReferenced(void)1531 E3Shared::IsReferenced ( void )
1532 	{
1533 	// Return as the reference count is greater than 1
1534 	return ( (TQ3Boolean) ( refCount > 1 ) ) ;
1535 	}
1536 
1537 
1538 
1539 
1540 
1541 //=============================================================================
1542 //      E3Shared_GetReferenceCount : Return the reference count.
1543 //-----------------------------------------------------------------------------
1544 TQ3Uns32
GetReferenceCount(void)1545 E3Shared::GetReferenceCount ( void )
1546 	{
1547 	// Return the reference count
1548 	return refCount ;
1549 	}
1550 
1551 
1552 
1553 
1554 
1555 //=============================================================================
1556 //      E3Shared_GetEditIndex : Return the edit index of a shared object.
1557 //-----------------------------------------------------------------------------
1558 TQ3Uns32
GetEditIndex(void)1559 E3Shared::GetEditIndex ( void )
1560 	{
1561 	// Return the edit index
1562 	return editIndex ;
1563 	}
1564 
1565 
1566 
1567 
1568 
1569 //=============================================================================
1570 //      E3Shared_Edited : Increase the edit index of an object.
1571 //-----------------------------------------------------------------------------
1572 TQ3Status
Edited(void)1573 E3Shared::Edited ( void )
1574 	{
1575 	// Increment the edit index
1576 	++editIndex ;
1577 	return kQ3Success ;
1578 	}
1579 
1580 
1581 
1582 
1583 
1584 //=============================================================================
1585 //      E3Shape_IsOfMyClass : Check if object pointer is valid and of type shape
1586 //-----------------------------------------------------------------------------
1587 //		Replaces Q3Object_IsType ( object, kQ3SharedTypeShape )
1588 //		but call is smaller and does not call E3System_Bottleneck
1589 //		as this is (always?) done in the calling code as well
1590 //-----------------------------------------------------------------------------
1591 #pragma mark -
1592 TQ3Boolean
E3Shape_IsOfMyClass(TQ3Object object)1593 E3Shape_IsOfMyClass ( TQ3Object object )
1594 	{
1595 	if ( object == NULL )
1596 		return kQ3False ;
1597 
1598 	if ( object->IsObjectValid () )
1599 		return Q3_OBJECT_IS_CLASS ( object, E3Shape ) ;
1600 
1601 	return kQ3False ;
1602 	}
1603 
1604 
1605 
1606 
1607 
1608 //=============================================================================
1609 //      E3Shape_GetType : Get the type of a shape object.
1610 //-----------------------------------------------------------------------------
1611 TQ3ObjectType
E3Shape_GetType(TQ3ShapeObject theShape)1612 E3Shape_GetType(TQ3ShapeObject theShape)
1613 	{
1614 	// Return the type
1615 	return theShape->GetObjectType ( kQ3SharedTypeShape ) ;
1616 	}
1617 
1618 
1619 
1620 
1621 
1622 //=============================================================================
1623 //      E3Shape_GetSet : Get the set for a shape.
1624 //-----------------------------------------------------------------------------
1625 TQ3Status
E3Shape_GetSet(TQ3ShapeObject theShape,TQ3SetObject * theSet)1626 E3Shape_GetSet(TQ3ShapeObject theShape, TQ3SetObject *theSet)
1627 	{
1628 	*theSet = NULL ;
1629 	return theShape->GetElement ( kQ3ElementTypeSet, theSet ) ;
1630 	}
1631 
1632 
1633 
1634 
1635 
1636 //=============================================================================
1637 //      E3Shape_SetSet : Set the set for a shape.
1638 //-----------------------------------------------------------------------------
1639 TQ3Status
E3Shape_SetSet(TQ3ShapeObject theShape,TQ3SetObject theSet)1640 E3Shape_SetSet(TQ3ShapeObject theShape, TQ3SetObject theSet)
1641 	{
1642 	if ( theSet == NULL )
1643 		return theShape->ClearElement ( kQ3ElementTypeSet ) ;
1644 
1645 	return theShape->AddElement ( kQ3ElementTypeSet, &theSet ) ;
1646 	}
1647 
1648 
1649 
1650 
1651 
1652 //=============================================================================
1653 //      E3Shape_SubmitElements : Submit custom elements of a shape.
1654 //-----------------------------------------------------------------------------
1655 //		This will be called by E3FFW_3DMF_TraverseObject to submit
1656 //		any custom elements that might be attached to the shape.
1657 //-----------------------------------------------------------------------------
1658 TQ3Status
SubmitElements(TQ3ViewObject inView)1659 OpaqueTQ3Object::SubmitElements ( TQ3ViewObject inView )
1660 	{
1661 	// Use the shape's set, if any.
1662 	if ( theSet == NULL )
1663 		return kQ3Success ;
1664 
1665 	return ( (E3Set*) theSet )->SubmitElements ( inView ) ;
1666 	}
1667 
1668 
1669 
1670 
1671 
1672 //=============================================================================
1673 //      E3Bitmap_Empty : Dispose of the memory allocated for a bitmap.
1674 //-----------------------------------------------------------------------------
1675 #pragma mark -
1676 TQ3Status
E3Bitmap_Empty(TQ3Bitmap * theBitmap)1677 E3Bitmap_Empty(TQ3Bitmap *theBitmap)
1678 {
1679 
1680 
1681 	// Dispose of the bitmap's image
1682 	Q3Memory_Free(&theBitmap->image);
1683 
1684 	return(kQ3Success);
1685 }
1686 
1687 
1688 
1689 
1690 
1691 //=============================================================================
1692 //      E3Bitmap_GetImageSize : Get the amount of memory required for a bitmap.
1693 //-----------------------------------------------------------------------------
1694 TQ3Uns32
E3Bitmap_GetImageSize(TQ3Uns32 theWidth,TQ3Uns32 theHeight)1695 E3Bitmap_GetImageSize(TQ3Uns32 theWidth, TQ3Uns32 theHeight)
1696 {	TQ3Uns32		imageSize;
1697 
1698 
1699 
1700 	// Bitmaps are 1 bit deep, so every 8 pixels requires 1 byte
1701 	imageSize  = ((theWidth - 1) / 8) + 1;
1702 	imageSize *= theHeight;
1703 
1704 	return(imageSize);
1705 }
1706 
1707 
1708 
1709 
1710 
1711 //=============================================================================
1712 //      E3Bitmap_GetBit : Get a bit from a bitmap.
1713 //-----------------------------------------------------------------------------
1714 TQ3Boolean
E3Bitmap_GetBit(const TQ3Bitmap * theBitmap,TQ3Uns32 x,TQ3Uns32 y)1715 E3Bitmap_GetBit(const TQ3Bitmap *theBitmap, TQ3Uns32 x, TQ3Uns32 y)
1716 {	TQ3Uns8			*bytePtr, theByte, bitShift;
1717 	TQ3Boolean		theState;
1718 
1719 
1720 
1721 	// Locate the byte we need
1722 	bytePtr  = theBitmap->image + (y * theBitmap->rowBytes);
1723 	bytePtr += (x / 8);
1724 	theByte  = *bytePtr;
1725 
1726 
1727 
1728 	// Locate the bit we need
1729 	bitShift = (TQ3Uns8) (x % 8);
1730 	if (theBitmap->bitOrder == kQ3EndianBig)
1731 		theState = ((theByte >> (7 - bitShift)) & 0x01) != 0 ? kQ3True : kQ3False;
1732 	else
1733 		theState = ((theByte >>  (   bitShift)) & 0x01) != 0 ? kQ3True : kQ3False;
1734 
1735 	return(theState);
1736 }
1737 
1738 
1739 
1740 
1741 
1742 //=============================================================================
1743 //      E3Bitmap_SetBit : Set a bit within a bitmap.
1744 //-----------------------------------------------------------------------------
1745 TQ3Status
E3Bitmap_SetBit(TQ3Bitmap * theBitmap,TQ3Uns32 x,TQ3Uns32 y,TQ3Boolean theState)1746 E3Bitmap_SetBit(TQ3Bitmap *theBitmap, TQ3Uns32 x, TQ3Uns32 y, TQ3Boolean theState)
1747 {	TQ3Uns8		*bytePtr, theByte, bitShift, byteMask;
1748 
1749 
1750 
1751 	// Locate the byte we need
1752 	bytePtr  = theBitmap->image + (y * theBitmap->rowBytes);
1753 	bytePtr += (x / 8);
1754 
1755 
1756 
1757 	// Prepare the mask
1758 	bitShift = (TQ3Uns8) (x % 8);
1759 
1760 	if (theBitmap->bitOrder == kQ3EndianBig)
1761 		byteMask = (1 << (7 - bitShift));
1762 	else
1763 		byteMask = (1 << (    bitShift));
1764 
1765 
1766 
1767 	// Update the byte
1768 	theByte = *bytePtr;
1769 
1770 	if (theState)
1771 		theByte |=  byteMask;
1772 	else
1773 		theByte &= ~byteMask;
1774 
1775 	*bytePtr = theByte;
1776 
1777 	return(kQ3Success);
1778 }
1779 
1780 
1781 
1782 
1783 
1784 
1785