Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOVisualEffectEntity.m
Go to the documentation of this file.
1/*
2
3OOVisualEffectEntity.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the impllied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
27
28#import "OOMaths.h"
29#import "Universe.h"
30#import "OOShaderMaterial.h"
32
33#import "ResourceManager.h"
34#import "OOStringParsing.h"
35#import "OOStringExpander.h"
37#import "OOConstToString.h"
38#import "OOConstToJSString.h"
39
40#import "OOMesh.h"
41
42#import "OOColor.h"
43#import "OOPolygonSprite.h"
44
45#import "OOFlasherEntity.h"
46
47#import "OODebugGLDrawing.h"
48#import "OODebugFlags.h"
49
50#import "OOJSScript.h"
51
53
54#import "MyOpenGLView.h"
55
56@interface OOVisualEffectEntity (Private)
57
58- (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent;
59
60- (void) addSubEntity:(Entity<OOSubEntity> *) subent;
61- (BOOL) setUpOneSubentity:(NSDictionary *) subentDict;
62- (BOOL) setUpOneFlasher:(NSDictionary *) subentDict;
63- (BOOL) setUpOneStandardSubentity:(NSDictionary *)subentDict;
64
65@end
66
67
68@implementation OOVisualEffectEntity
69
70- (id) init
71{
72 return [self initWithKey:@"" definition:nil];
73}
74
75- (id)initWithKey:(NSString *)key definition:(NSDictionary *)dict
76{
78
79 NSParameterAssert(dict != nil);
80
81 self = [super init];
82 if (self == nil) return nil;
83
84 _effectKey = [key retain];
85
86 if (![self setUpVisualEffectFromDictionary:dict])
87 {
88 [self release];
89 self = nil;
90 }
91
92 _haveExecutedSpawnAction = NO;
93
94 return self;
95
97}
98
99
100- (BOOL) setUpVisualEffectFromDictionary:(NSDictionary *) effectDict
101{
103
104 effectinfoDictionary = [effectDict copy];
105 if (effectinfoDictionary == nil) effectinfoDictionary = [[NSDictionary alloc] init];
106
107 orientation = kIdentityQuaternion;
108 rotMatrix = kIdentityMatrix;
109
110 collision_radius = 0.0;
111
112 NSString *modelName = [effectDict oo_stringForKey:@"model"];
113 if (modelName != nil)
114 {
115 OOMesh *mesh = [OOMesh meshWithName:modelName
116 cacheKey:_effectKey
117 materialDictionary:[effectDict oo_dictionaryForKey:@"materials"]
118 shadersDictionary:[effectDict oo_dictionaryForKey:@"shaders"]
119 smooth:[effectDict oo_boolForKey:@"smooth" defaultValue:NO]
120 shaderMacros:OODefaultShipShaderMacros()
122 if (mesh == nil) return NO;
123 [self setMesh:mesh];
124 }
125
126 isImmuneToBreakPatternHide = [effectDict oo_boolForKey:@"is_break_pattern"];
127 scaleX = 1.0;
128 scaleY = 1.0;
129 scaleZ = 1.0;
130
131 [self clearSubEntities];
132 [self setUpSubEntities];
133
134 [self setScannerDisplayColor1:nil];
135 [self setScannerDisplayColor2:nil];
136
137 scanClass = CLASS_VISUAL_EFFECT;
138
139 [self setStatus:STATUS_EFFECT];
140
141 _hullHeatLevel = 60.0 / 256.0;
142 _shaderFloat1 = 0.0;
143 _shaderFloat2 = 0.0;
144 _shaderInt1 = 0;
145 _shaderInt2 = 0;
146 _shaderVector1 = kZeroVector;
147 _shaderVector2 = kZeroVector;
148
149 [self setBeaconCode:[effectDict oo_stringForKey:@"beacon"]];
150 [self setBeaconLabel:[effectDict oo_stringForKey:@"beacon_label" defaultValue:[self beaconCode]]];
151
152 scriptInfo = [[effectDict oo_dictionaryForKey:@"script_info" defaultValue:nil] retain];
153 [self setScript:[effectDict oo_stringForKey:@"script"]];
154
155 return YES;
156
158}
159
160
161- (void) dealloc
162{
163 [self clearSubEntities];
164 DESTROY(_effectKey);
165 DESTROY(effectinfoDictionary);
166 DESTROY(scanner_display_color1);
167 DESTROY(scanner_display_color2);
168 DESTROY(scriptInfo);
169 DESTROY(script);
170 DESTROY(_beaconCode);
171 DESTROY(_beaconLabel);
172 DESTROY(_beaconDrawable);
173
174 [super dealloc];
175}
176
177
178- (BOOL) isEffect
179{
180 return YES;
181}
182
183
184- (BOOL) isVisualEffect
185{
186 return YES;
187}
188
189
190- (BOOL) canCollide
191{
192 return NO;
193}
194
195
196- (OOMesh *)mesh
197{
198 return (OOMesh *)[self drawable];
199}
200
201
202- (void)setMesh:(OOMesh *)mesh
203{
204 if (mesh != [self mesh])
205 {
206 [self setDrawable:mesh];
207 }
208}
209
210
211- (NSString *)effectKey
212{
213 return _effectKey;
214}
215
216
217- (GLfloat)frustumRadius
218{
219 return [self scaleMax] * _profileRadius;
220}
221
222
223- (void) clearSubEntities
224{
225 [subEntities makeObjectsPerformSelector:@selector(setOwner:) withObject:nil]; // Ensure backlinks are broken
226 [subEntities release];
227 subEntities = nil;
228
229 // reset size & mass!
230 if ([self mesh])
231 {
232 collision_radius = [self findCollisionRadius];
233 }
234 else
235 {
236 collision_radius = 0.0;
237 }
238 _profileRadius = collision_radius;
239}
240
241
242- (BOOL)setUpSubEntities
243{
244 unsigned int i;
245 _profileRadius = collision_radius;
246 NSArray *subs = [effectinfoDictionary oo_arrayForKey:@"subentities"];
247
248 for (i = 0; i < [subs count]; i++)
249 {
250 [self setUpOneSubentity:[subs oo_dictionaryAtIndex:i]];
251 }
252
253 [self setNoDrawDistance];
254
255 return YES;
256}
257
258
259- (void) removeSubEntity:(Entity<OOSubEntity> *)sub
260{
261 [sub setOwner:nil];
262 [subEntities removeObject:sub];
263}
264
265
266- (void) setNoDrawDistance
267{
268 GLfloat r = _profileRadius * [self scaleMax];
269 no_draw_distance = r * r * NO_DRAW_DISTANCE_FACTOR * NO_DRAW_DISTANCE_FACTOR * 2.0;
270
271}
272
273
274- (BOOL) setUpOneSubentity:(NSDictionary *) subentDict
275{
276 NSString *type = [subentDict oo_stringForKey:@"type"];
277 if ([type isEqualToString:@"flasher"])
278 {
279 return [self setUpOneFlasher:subentDict];
280 }
281 else
282 {
283 return [self setUpOneStandardSubentity:subentDict];
284 }
285
286
287}
288
289
290- (BOOL) setUpOneFlasher:(NSDictionary *) subentDict
291{
293 [flasher setPosition:[subentDict oo_hpvectorForKey:@"position"]];
294 [self addSubEntity:flasher];
295 return YES;
296}
297
298
299- (BOOL) setUpOneStandardSubentity:(NSDictionary *)subentDict
300{
301 OOVisualEffectEntity *subentity = nil;
302 NSString *subentKey = nil;
303 HPVector subPosition;
304 Quaternion subOrientation;
305
306 subentKey = [subentDict oo_stringForKey:@"subentity_key"];
307 if (subentKey == nil) {
308 OOLog(@"setup.visualeffect.badEntry.subentities",@"Failed to set up entity - no subentKey in %@",subentDict);
309 return NO;
310 }
311
312 subentity = [UNIVERSE newVisualEffectWithName:subentKey];
313 if (subentity == nil) {
314 OOLog(@"setup.visualeffect.badEntry.subentities",@"Failed to set up entity %@",subentKey);
315 return NO;
316 }
317
318 subPosition = [subentDict oo_hpvectorForKey:@"position"];
319 subOrientation = [subentDict oo_quaternionForKey:@"orientation"];
320
321 [subentity setPosition:subPosition];
322 [subentity setOrientation:subOrientation];
323
324 [self addSubEntity:subentity];
325
326 [subentity release];
327
328 return YES;
329}
330
331
332- (void) addSubEntity:(Entity<OOSubEntity> *)sub
333{
334 if (sub == nil) return;
335
336 if (subEntities == nil) subEntities = [[NSMutableArray alloc] init];
337 sub->isSubEntity = YES;
338 // Order matters - need consistent state in setOwner:. -- Ahruman 2008-04-20
339 [subEntities addObject:sub];
340 [sub setOwner:self];
341
342 double distance = HPmagnitude([sub position]) + [sub findCollisionRadius];
343 if (distance > _profileRadius)
344 {
345 _profileRadius = distance;
346 }
347}
348
349
350- (NSArray *)subEntities
351{
352 return [[subEntities copy] autorelease];
353}
354
355
356- (NSUInteger) subEntityCount
357{
358 return [subEntities count];
359}
360
361
362- (NSEnumerator *) visualEffectSubEntityEnumerator
363{
364 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isVisualEffect)];
365}
366
367
368- (BOOL) hasSubEntity:(Entity<OOSubEntity> *)sub
369{
370 return [subEntities containsObject:sub];
371}
372
373
374- (NSEnumerator *)subEntityEnumerator
375{
376 return [[self subEntities] objectEnumerator];
377}
378
379
380- (NSEnumerator *)effectSubEntityEnumerator
381{
382 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isVisualEffect)];
383}
384
385
386- (NSEnumerator *)flasherEnumerator
387{
388 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isFlasher)];
389}
390
391
392- (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent
393{
394 if (cam_zero_distance > no_draw_distance) // this test provides an opportunity to do simple LoD culling
395 {
396 return; // TOO FAR AWAY
397 }
399 // HPVect: camera position
400 OOGLTranslateModelView(HPVectorToVector(position));
401 OOGLMultModelView(rotMatrix);
402 [self drawImmediate:immediate translucent:translucent];
403
405}
406
407
408- (void) rescaleBy:(GLfloat)factor
409{
410 if ([self mesh] != nil) {
411 [self setMesh:[[self mesh] meshRescaledBy:factor]];
412 }
413
414 // rescale subentities
416 foreach (se, [self subEntities])
417 {
418 [se setPosition:HPvector_multiply_scalar([se position], factor)];
419 [se rescaleBy:factor];
420 }
421
422 collision_radius *= factor;
423 _profileRadius *= factor;
424}
425
426
427- (void) rescaleBy:(GLfloat)factor writeToCache:(BOOL)writeToCache
428{
429 /* Do nothing; this is only needed because of OOEntityWithDrawable
430 implementation requirements */
431}
432
433
434- (GLfloat) scaleMax
435{
436 GLfloat scale = 1.0;
437 if (scaleX > scaleY)
438 {
439 if (scaleX > scaleZ)
440 {
441 scale *= scaleX;
442 }
443 else
444 {
445 scale *= scaleZ;
446 }
447 }
448 else if (scaleY > scaleZ)
449 {
450 scale *= scaleY;
451 }
452 else
453 {
454 scale *= scaleZ;
455 }
456 return scale;
457}
458
459- (GLfloat) scaleX
460{
461 return scaleX;
462}
463
464
465- (void) setScaleX:(GLfloat)factor
466{
467 // rescale subentities
469 GLfloat flasher_factor = pow(factor/scaleX,1.0/3.0);
470 foreach (se, [self subEntities])
471 {
472 HPVector move = [se position];
473 move.x *= factor/scaleX;
474 [se setPosition:move];
475 if ([se isVisualEffect])
476 {
477 [(OOVisualEffectEntity*)se setScaleX:factor];
478 }
479 else
480 {
481 [se rescaleBy:flasher_factor];
482 }
483 }
484
485 scaleX = factor;
486 [self setNoDrawDistance];
487}
488
489
490- (GLfloat) scaleY
491{
492 return scaleY;
493}
494
495
496- (void) setScaleY:(GLfloat)factor
497{
498 // rescale subentities
500 GLfloat flasher_factor = pow(factor/scaleY,1.0/3.0);
501 foreach (se, [self subEntities])
502 {
503 HPVector move = [se position];
504 move.y *= factor/scaleY;
505 [se setPosition:move];
506 if ([se isVisualEffect])
507 {
508 [(OOVisualEffectEntity*)se setScaleY:factor];
509 }
510 else
511 {
512 [se rescaleBy:flasher_factor];
513 }
514 }
515
516 scaleY = factor;
517 [self setNoDrawDistance];
518}
519
520
521- (GLfloat) scaleZ
522{
523 return scaleZ;
524}
525
526
527- (void) setScaleZ:(GLfloat)factor
528{
529 // rescale subentities
531 GLfloat flasher_factor = pow(factor/scaleZ,1.0/3.0);
532 foreach (se, [self subEntities])
533 {
534 HPVector move = [se position];
535 move.z *= factor/scaleZ;
536 [se setPosition:move];
537 if ([se isVisualEffect])
538 {
539 [(OOVisualEffectEntity*)se setScaleZ:factor];
540 }
541 else
542 {
543 [se rescaleBy:flasher_factor];
544 }
545 }
546
547 scaleZ = factor;
548 [self setNoDrawDistance];
549}
550
551
552- (GLfloat) collisionRadius
553{
554 return [self scaleMax] * collision_radius;
555}
556
557
558- (void) orientationChanged
559{
560 [super orientationChanged];
561
562 _v_forward = vector_forward_from_quaternion(orientation);
563 _v_up = vector_up_from_quaternion(orientation);
564 _v_right = vector_right_from_quaternion(orientation);
565}
566
567
568// exposed to shaders
569- (Vector) forwardVector
570{
571 return _v_forward;
572}
573
574
575// exposed to shaders
576- (Vector) upVector
577{
578 return _v_up;
579}
580
581
582// exposed to shaders
583- (Vector) rightVector
584{
585 return _v_right;
586}
587
588
589- (OOColor *)scannerDisplayColor1
590{
591 return [[scanner_display_color1 retain] autorelease];
592}
593
594
595- (OOColor *)scannerDisplayColor2
596{
597 return [[scanner_display_color2 retain] autorelease];
598}
599
600
601- (void)setScannerDisplayColor1:(OOColor *)color
602{
603 DESTROY(scanner_display_color1);
604
605 if (color == nil) color = [OOColor colorWithDescription:[effectinfoDictionary objectForKey:@"scanner_display_color1"]];
606 scanner_display_color1 = [color retain];
607}
608
609
610- (void)setScannerDisplayColor2:(OOColor *)color
611{
612 DESTROY(scanner_display_color2);
613
614 if (color == nil) color = [OOColor colorWithDescription:[effectinfoDictionary objectForKey:@"scanner_display_color2"]];
615 scanner_display_color2 = [color retain];
616}
617
618static GLfloat default_color[4] = { 0.0, 0.0, 0.0, 0.0};
619static GLfloat scripted_color[4] = { 0.0, 0.0, 0.0, 0.0};
620
621- (GLfloat *) scannerDisplayColorForShip:(BOOL)flash :(OOColor *)scannerDisplayColor1 :(OOColor *)scannerDisplayColor2
622{
623
624 if (scannerDisplayColor1 || scannerDisplayColor2)
625 {
626 if (scannerDisplayColor1 && !scannerDisplayColor2)
627 {
628 [scannerDisplayColor1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
629 }
630
631 if (!scannerDisplayColor1 && scannerDisplayColor2)
632 {
633 [scannerDisplayColor2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
634 }
635
636 if (scannerDisplayColor1 && scannerDisplayColor2)
637 {
638 if (flash)
639 [scannerDisplayColor1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
640 else
641 [scannerDisplayColor2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
642 }
643
644 return scripted_color;
645 }
646
647 return default_color; // transparent black if not specified
648}
649
650- (void) drawImmediate:(bool)immediate translucent:(bool)translucent
651{
652 if (no_draw_distance < cam_zero_distance)
653 {
654 return; // too far away to draw
655 }
657 OOGLScaleModelView(make_vector(scaleX,scaleY,scaleZ));
658
659 if ([self mesh] != nil)
660 {
661 [super drawImmediate:immediate translucent:translucent];
662 }
664
665 // Draw subentities.
666 if (!immediate) // TODO: is this relevant any longer?
667 {
668 Entity<OOSubEntity> *subEntity = nil;
669 foreach (subEntity, [self subEntities])
670 {
671 [subEntity drawSubEntityImmediate:immediate translucent:translucent];
672 }
673 }
674}
675
676
677- (void) update:(OOTimeDelta)delta_t
678{
679 [super update:delta_t];
680
681 if (!_haveExecutedSpawnAction) {
682 [self doScriptEvent:OOJSID("effectSpawned")];
683 _haveExecutedSpawnAction = YES;
684 }
685
686 Entity *se = nil;
687 foreach (se, [self subEntities])
688 {
689 [se update:delta_t];
690 }
691}
692
693
694- (BOOL) isBreakPattern
695{
696 return isImmuneToBreakPatternHide;
697}
698
699
700- (void) setIsBreakPattern:(BOOL)bp
701{
702 isImmuneToBreakPatternHide = bp;
703}
704
705
706- (NSDictionary *)effectInfoDictionary
707{
708 return effectinfoDictionary;
709}
710
711
712/* scripting */
713
714- (void) setScript:(NSString *)script_name
715{
716 NSMutableDictionary *properties = nil;
717
718 properties = [NSMutableDictionary dictionary];
719 [properties setObject:self forKey:@"visualEffect"];
720
721 [script autorelease];
722 script = [OOScript jsScriptFromFileNamed:script_name properties:properties];
723 // does not support legacy scripting
724 if (script == nil) {
725 script = [OOScript jsScriptFromFileNamed:@"oolite-default-effect-script.js" properties:properties];
726 }
727 [script retain];
728}
729
730
731- (OOJSScript *)script
732{
733 return script;
734}
735
736
737- (NSDictionary *)scriptInfo
738{
739 return (scriptInfo != nil) ? scriptInfo : (NSDictionary *)[NSDictionary dictionary];
740}
741
742// unlikely to need events with arguments
743- (void) doScriptEvent:(jsid)message
744{
745 JSContext *context = OOJSAcquireContext();
746 [script callMethod:message inContext:context withArguments:NULL count:0 result:NULL];
747 OOJSRelinquishContext(context);
748}
749
750
751- (void) remove
752{
753 [self doScriptEvent:OOJSID("effectRemoved")];
754 [UNIVERSE removeEntity:(Entity*)self];
755}
756
757
758/* beacons */
759
760- (NSComparisonResult) compareBeaconCodeWith:(Entity<OOBeaconEntity> *) other
761{
762 return [[self beaconCode] compare:[other beaconCode] options: NSCaseInsensitiveSearch];
763}
764
765
766- (NSString *) beaconCode
767{
768 return _beaconCode;
769}
770
771
772- (void) setBeaconCode:(NSString *)bcode
773{
774 if ([bcode length] == 0) bcode = nil;
775
776 if (_beaconCode != bcode)
777 {
778 [_beaconCode release];
779 _beaconCode = [bcode copy];
780
781 DESTROY(_beaconDrawable);
782 }
783 // if not blanking code and label is currently blank, default label to code
784 if (bcode != nil && (_beaconLabel == nil || [_beaconLabel length] == 0))
785 {
786 [self setBeaconLabel:bcode];
787 }
788
789}
790
791
792- (NSString *) beaconLabel
793{
794 return _beaconLabel;
795}
796
797
798- (void) setBeaconLabel:(NSString *)blabel
799{
800 if ([blabel length] == 0) blabel = nil;
801
802 if (_beaconLabel != blabel)
803 {
804 [_beaconLabel release];
805 _beaconLabel = [OOExpand(blabel) retain];
806 }
807}
808
809
810- (BOOL) isBeacon
811{
812 return [self beaconCode] != nil;
813}
814
815
816- (id <OOHUDBeaconIcon>) beaconDrawable
817{
818 if (_beaconDrawable == nil)
819 {
820 NSString *beaconCode = [self beaconCode];
821 NSUInteger length = [beaconCode length];
822
823 if (length > 1)
824 {
825 NSArray *iconData = [[UNIVERSE descriptions] oo_arrayForKey:beaconCode];
826 if (iconData != nil) _beaconDrawable = [[OOPolygonSprite alloc] initWithDataArray:iconData outlineWidth:0.5 name:beaconCode];
827 }
828
829 if (_beaconDrawable == nil)
830 {
831 if (length > 0) _beaconDrawable = [[beaconCode substringToIndex:1] retain];
832 else _beaconDrawable = @"";
833 }
834 }
835
836 return _beaconDrawable;
837}
838
839
840- (Entity <OOBeaconEntity> *) prevBeacon
841{
842 return [_prevBeacon weakRefUnderlyingObject];
843}
844
845
846- (Entity <OOBeaconEntity> *) nextBeacon
847{
848 return [_nextBeacon weakRefUnderlyingObject];
849}
850
851
852- (void) setPrevBeacon:(Entity <OOBeaconEntity> *)beaconShip
853{
854 if (beaconShip != [self prevBeacon])
855 {
856 [_prevBeacon release];
857 _prevBeacon = [beaconShip weakRetain];
858 }
859}
860
861
862- (void) setNextBeacon:(Entity <OOBeaconEntity> *)beaconShip
863{
864 if (beaconShip != [self nextBeacon])
865 {
866 [_nextBeacon release];
867 _nextBeacon = [beaconShip weakRetain];
868 }
869}
870
871
872- (BOOL) isJammingScanning
873{
874 return NO;
875}
876
877
878/* Shader bindable uniforms */
879
880// no automatic change of this, but simplifies use of default shader
881- (GLfloat)hullHeatLevel
882{
883 return _hullHeatLevel;
884}
885
886
887- (void)setHullHeatLevel:(GLfloat)value
888{
889 _hullHeatLevel = OOClamp_0_1_f(value);
890}
891
892
893- (GLfloat) shaderFloat1
894{
895 return _shaderFloat1;
896}
897
898
899- (void)setShaderFloat1:(GLfloat)value
900{
901 _shaderFloat1 = value;
902}
903
904
905- (GLfloat) shaderFloat2
906{
907 return _shaderFloat2;
908}
909
910
911- (void)setShaderFloat2:(GLfloat)value
912{
913 _shaderFloat2 = value;
914}
915
916
917- (int) shaderInt1
918{
919 return _shaderInt1;
920}
921
922
923- (void)setShaderInt1:(int)value
924{
925 _shaderInt1 = value;
926}
927
928
929- (int) shaderInt2
930{
931 return _shaderInt2;
932}
933
934
935- (void)setShaderInt2:(int)value
936{
937 _shaderInt2 = value;
938}
939
940
941- (Vector) shaderVector1
942{
943 return _shaderVector1;
944}
945
946
947- (void)setShaderVector1:(Vector)value
948{
949 _shaderVector1 = value;
950}
951
952
953- (Vector) shaderVector2
954{
955 return _shaderVector2;
956}
957
958
959- (void)setShaderVector2:(Vector)value
960{
961 _shaderVector2 = value;
962}
963
964
965@end
966
967@implementation OOVisualEffectEntity (SubEntityRelationship)
968
969// a slightly misnamed test now things other than ships can have subents
970- (BOOL) isShipWithSubEntityShip:(Entity *)other
971{
972 assert ([self isVisualEffect]);
973
974 if (![other isVisualEffect]) return NO;
975 if (![other isSubEntity]) return NO;
976 if ([other owner] != self) return NO;
977
978#ifndef NDEBUG
979 // Sanity check; this should always be true.
980 if (![self hasSubEntity:(OOVisualEffectEntity *)other])
981 {
982 OOLogERR(@"visualeffect.subentity.sanityCheck.failed", @"%@ thinks it's a subentity of %@, but the supposed parent does not agree. %@", [other shortDescription], [self shortDescription], @"This is an internal error, please report it.");
983 [other setOwner:nil];
984 return NO;
985 }
986#endif
987
988 return YES;
989}
990
991@end
#define NO_DRAW_DISTANCE_FACTOR
Definition Entity.h:46
#define DESTROY(x)
Definition OOCocoa.h:77
#define OOJS_PROFILE_EXIT
#define OOJS_PROFILE_ENTER
OOINLINE JSContext * OOJSAcquireContext(void)
OOINLINE void OOJSRelinquishContext(JSContext *context)
#define OOLogERR(class, format,...)
Definition OOLogging.h:112
#define OOLog(class, format,...)
Definition OOLogging.h:88
const OOMatrix kIdentityMatrix
Definition OOMatrix.m:31
void OOGLScaleModelView(Vector scale)
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLPopModelView(void)
return nil
Vector vector_up_from_quaternion(Quaternion quat)
Vector vector_right_from_quaternion(Quaternion quat)
Vector vector_forward_from_quaternion(Quaternion quat)
const Quaternion kIdentityQuaternion
double OOTimeDelta
Definition OOTypes.h:224
const Vector kZeroVector
Definition OOVector.m:28
static GLfloat scripted_color[4]
static GLfloat default_color[4]
unsigned isSubEntity
Definition Entity.h:95
void setOrientation:(Quaternion quat)
Definition Entity.m:725
void update:(OOTimeDelta delta_t)
Definition Entity.m:929
void setOwner:(Entity *ent)
Definition Entity.m:576
void drawSubEntityImmediate:translucent:(bool immediate, [translucent] bool translucent)
HPVector position
Definition Entity.h:112
void setPosition:(HPVector posn)
Definition Entity.m:647
OOColor * colorWithDescription:(id description)
Definition OOColor.m:127
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
Definition OOColor.m:368
instancetype flasherWithDictionary:(NSDictionary *dictionary)
instancetype meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:(NSString *name,[cacheKey] NSString *cacheKey,[materialDictionary] NSDictionary *materialDict,[shadersDictionary] NSDictionary *shadersDict,[smooth] BOOL smooth,[shaderMacros] NSDictionary *macros,[shaderBindingTarget] id< OOWeakReferenceSupport > object)
Definition OOMesh.m:233
id jsScriptFromFileNamed:properties:(NSString *fileName,[properties] NSDictionary *properties)
Definition OOScript.m:192
id initWithKey:definition:(NSString *key,[definition] NSDictionary *dict)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque