LCOV - code coverage report
Current view: top level - Core/Entities - OOVisualEffectEntity.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 36 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOVisualEffectEntity.m
       4             : 
       5             : 
       6             : Oolite
       7             : Copyright (C) 2004-2013 Giles C Williams and contributors
       8             : 
       9             : This program is free software; you can redistribute it and/or
      10             : modify it under the terms of the GNU General Public License
      11             : as published by the Free Software Foundation; either version 2
      12             : of the License, or (at your option) any later version.
      13             : 
      14             : This program is distributed in the hope that it will be useful,
      15             : but WITHOUT ANY WARRANTY; without even the impllied warranty of
      16             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             : GNU General Public License for more details.
      18             : 
      19             : You should have received a copy of the GNU General Public License
      20             : along with this program; if not, write to the Free Software
      21             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      22             : MA 02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : #import "OOVisualEffectEntity.h"
      27             : 
      28             : #import "OOMaths.h"
      29             : #import "Universe.h"
      30             : #import "OOShaderMaterial.h"
      31             : #import "OOOpenGLExtensionManager.h"
      32             : 
      33             : #import "ResourceManager.h"
      34             : #import "OOStringParsing.h"
      35             : #import "OOStringExpander.h"
      36             : #import "OOCollectionExtractors.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             : 
      52             : #import "OOFilteringEnumerator.h"
      53             : 
      54             : #import "MyOpenGLView.h"
      55             : 
      56             : @interface OOVisualEffectEntity (Private)
      57             : 
      58           0 : - (void) drawSubEntityImmediate:(bool)immediate translucent:(bool)translucent;
      59             : 
      60           0 : - (void) addSubEntity:(Entity<OOSubEntity> *) subent;
      61           0 : - (BOOL) setUpOneSubentity:(NSDictionary *) subentDict;
      62           0 : - (BOOL) setUpOneFlasher:(NSDictionary *) subentDict;
      63           0 : - (BOOL) setUpOneStandardSubentity:(NSDictionary *)subentDict;
      64             : 
      65             : @end
      66             : 
      67             : 
      68             : @implementation OOVisualEffectEntity
      69             : 
      70           0 : - (id) init
      71             : {
      72             :         return [self initWithKey:@"" definition:nil];
      73             : }
      74             : 
      75             : - (id)initWithKey:(NSString *)key definition:(NSDictionary *)dict
      76             : {
      77             :         OOJS_PROFILE_ENTER
      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             :         
      96             :         OOJS_PROFILE_EXIT
      97             : }
      98             : 
      99             : 
     100             : - (BOOL) setUpVisualEffectFromDictionary:(NSDictionary *) effectDict
     101             : {
     102             :         OOJS_PROFILE_ENTER
     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()
     121             :                                                 shaderBindingTarget:self];
     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             : 
     157             :         OOJS_PROFILE_EXIT
     158             : }
     159             : 
     160             : 
     161           0 : - (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           0 : - (BOOL) isEffect
     179             : {
     180             :         return YES;
     181             : }
     182             : 
     183             : 
     184           0 : - (BOOL) isVisualEffect
     185             : {
     186             :         return YES;
     187             : }
     188             : 
     189             : 
     190           0 : - (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           0 : - (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           0 : - (BOOL) setUpOneFlasher:(NSDictionary *) subentDict
     291             : {
     292             :         OOFlasherEntity *flasher = [OOFlasherEntity flasherWithDictionary:subentDict];
     293             :         [flasher setPosition:[subentDict oo_hpvectorForKey:@"position"]];
     294             :         [self addSubEntity:flasher];
     295             :         return YES;
     296             : }
     297             : 
     298             : 
     299           0 : - (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           0 : - (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           0 : - (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             :         }
     398             :         OOGLPushModelView();
     399             :         // HPVect: camera position
     400             :         OOGLTranslateModelView(HPVectorToVector(position));
     401             :         OOGLMultModelView(rotMatrix);
     402             :         [self drawImmediate:immediate translucent:translucent];
     403             : 
     404             :         OOGLPopModelView();
     405             : }
     406             : 
     407             : 
     408           0 : - (void) rescaleBy:(GLfloat)factor 
     409             : {
     410             :         if ([self mesh] != nil) {
     411             :                 [self setMesh:[[self mesh] meshRescaledBy:factor]];
     412             :         }
     413             :         
     414             :         // rescale subentities
     415             :         Entity<OOSubEntity>       *se = nil;
     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           0 : - (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
     468             :         Entity<OOSubEntity>       *se = nil;
     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
     499             :         Entity<OOSubEntity>       *se = nil;
     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
     530             :         Entity<OOSubEntity>       *se = nil;
     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           0 : - (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             : 
     618           0 : static GLfloat default_color[4] =       { 0.0, 0.0, 0.0, 0.0};
     619           0 : static 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           0 : - (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             :         }
     656             :         OOGLPushModelView();
     657             :         OOGLScaleModelView(make_vector(scaleX,scaleY,scaleZ));
     658             : 
     659             :         if ([self mesh] != nil)
     660             :         {
     661             :                 [super drawImmediate:immediate translucent:translucent];
     662             :         }
     663             :         OOGLPopModelView();
     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           0 : - (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           0 : - (NSComparisonResult) compareBeaconCodeWith:(Entity<OOBeaconEntity> *) other
     761             : {
     762             :         return [[self beaconCode] compare:[other beaconCode] options: NSCaseInsensitiveSearch];
     763             : }
     764             : 
     765             : 
     766           0 : - (NSString *) beaconCode
     767             : {
     768             :         return _beaconCode;
     769             : }
     770             : 
     771             : 
     772           0 : - (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           0 : - (NSString *) beaconLabel
     793             : {
     794             :         return _beaconLabel;
     795             : }
     796             : 
     797             : 
     798           0 : - (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           0 : - (BOOL) isBeacon
     811             : {
     812             :         return [self beaconCode] != nil;
     813             : }
     814             : 
     815             : 
     816           0 : - (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           0 : - (Entity <OOBeaconEntity> *) prevBeacon
     841             : {
     842             :         return [_prevBeacon weakRefUnderlyingObject];
     843             : }
     844             : 
     845             : 
     846           0 : - (Entity <OOBeaconEntity> *) nextBeacon
     847             : {
     848             :         return [_nextBeacon weakRefUnderlyingObject];
     849             : }
     850             : 
     851             : 
     852           0 : - (void) setPrevBeacon:(Entity <OOBeaconEntity> *)beaconShip
     853             : {
     854             :         if (beaconShip != [self prevBeacon])
     855             :         {
     856             :                 [_prevBeacon release];
     857             :                 _prevBeacon = [beaconShip weakRetain];
     858             :         }
     859             : }
     860             : 
     861             : 
     862           0 : - (void) setNextBeacon:(Entity <OOBeaconEntity> *)beaconShip
     863             : {
     864             :         if (beaconShip != [self nextBeacon])
     865             :         {
     866             :                 [_nextBeacon release];
     867             :                 _nextBeacon = [beaconShip weakRetain];
     868             :         }
     869             : }
     870             : 
     871             : 
     872           0 : - (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           0 : - (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

Generated by: LCOV version 1.14