Initial addition of "Visual Effect" entities.

- effectdata.plist defines them
 - VisualEffect JS representation
 - System.addVisualEffect()
 - System.breakPattern and Station.breakPattern properties to allow override of usual break pattern
 - No appearance on scanner yet
src/Core/Entities/OOVisualEffectEntity and src/Core/Scripting/OOJSVisualEffectEntity will need adding to XCode project, please.


git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@5212 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Chris Morris 2012-08-19 17:09:51 +00:00
parent 0e617730dd
commit 44f1494b13
29 changed files with 1303 additions and 42 deletions

View File

@ -185,7 +185,8 @@ OOLITE_ENTITY_FILES = \
ShipEntityLoadRestore.m \
OOLaserShotEntity.m \
OOQuiriumCascadeEntity.m \
OORingEffectEntity.m
OORingEffectEntity.m \
OOVisualEffectEntity.m
OOLITE_GRAPHICS_DRAWABLE_FILES = \
OODrawable.m \
@ -292,6 +293,7 @@ OOLITE_SCRIPTING_FILES = \
OOJSSystem.m \
OOJSSystemInfo.m \
OOJSTimer.m \
OOJSVisualEffect.m \
OOJSVector.m \
OOJSWorldScripts.m \
OOLegacyScriptWhitelist.m \

View File

@ -132,6 +132,9 @@
display.mode.switch.failed = $error;
display.mode.unknown = $error;
display.initGL = no;
effectData.load.begin = yes;
effectData.load.done = no;
$linkedListError = $error;

View File

@ -99,7 +99,8 @@ enum OOScanClass
collisionTestFilter: 1,
throw_sparks: 1,
isImmuneToBreakPatternHide: 1,
isExplicitlyNotMainStation: 1;
isExplicitlyNotMainStation: 1,
isVisualEffect: 1;
OOScanClass scanClass;
@ -168,6 +169,7 @@ enum OOScanClass
- (BOOL) isSky;
- (BOOL) isWormhole;
- (BOOL) isEffect;
- (BOOL) isVisualEffect;
- (BOOL) validForAddToUniverse;
- (void) addToLinkedLists;

View File

@ -190,6 +190,12 @@ static NSString * const kOOLogEntityUpdateError = @"entity.linkedList.update.
}
- (BOOL) isVisualEffect
{
return NO;
}
- (BOOL) validForAddToUniverse
{
OOUInteger mySessionID = [self sessionID];

View File

@ -154,6 +154,9 @@ MA 02110-1301, USA.
- (void) drawEntity:(BOOL)immediate :(BOOL)translucent
{
// check if has been hidden.
if (!isImmuneToBreakPatternHide) return;
OO_ENTER_OPENGL();
if (translucent || immediate)

View File

@ -28,6 +28,12 @@ MA 02110-1301, USA.
@class OODrawable;
// Methods that must be supported by subentities, regardless of type.
@protocol OOSubEntity
- (void) rescaleBy:(GLfloat)factor;
@end
@interface OOEntityWithDrawable: Entity
{

View File

@ -62,7 +62,6 @@ MA 02110-1301, USA.
[self setActive:[dictionary oo_boolForKey:@"initially_on" defaultValue:YES]];
}
return self;
}
@ -112,6 +111,7 @@ MA 02110-1301, USA.
[super update:delta_t];
_time += delta_t;
if (_frequency != 0)
{
float wave = sin(_frequency * M_PI * (_time + _phase));

View File

@ -135,7 +135,20 @@ static OOTexture *sBlobTexture = nil;
- (void) drawEntity:(BOOL)immediate :(BOOL)translucent
{
if (!translucent || [UNIVERSE breakPatternHide]) return;
if (!translucent) return;
if ([UNIVERSE breakPatternHide] && !isImmuneToBreakPatternHide)
{
Entity *father = [self owner];
while (father != nil && father != NO_TARGET)
{
if (![father isSubEntity]) break;
father = [father owner];
}
if (!father->isImmuneToBreakPatternHide)
{
return;
}
}
if (no_draw_distance <= cam_zero_distance) return;
OO_ENTER_OPENGL();

View File

@ -0,0 +1,86 @@
/*
OOVisualEffectEntity.h
Entity subclass representing a visual effect with a custom mesh
Oolite
Copyright (C) 2004-2012 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOEntityWithDrawable.h"
#import "OOPlanetEntity.h"
#import "OOJSPropID.h"
@class OOColor, OOMesh, OOScript, OOJSScript;
@interface OOVisualEffectEntity: OOEntityWithDrawable <OOSubEntity>
{
@public
@protected
NSMutableArray *subEntities;
NSDictionary *effectinfoDictionary;
GLfloat _profileRadius; // for frustum culling
// OOColor *scanner_display_color1;
// OOColor *scanner_display_color2;
@private
NSString *_effectKey;
}
- (id)initWithKey:(NSString *)key definition:(NSDictionary *) dict;
- (BOOL) setUpVisualEffectFromDictionary:(NSDictionary *) effectDict;
- (OOMesh *)mesh;
- (void)setMesh:(OOMesh *)mesh;
- (GLfloat)frustumRadius;
- (void) clearSubEntities;
- (BOOL)setUpSubEntities;
- (NSArray *)subEntities;
- (unsigned) subEntityCount;
- (BOOL) hasSubEntity:(Entity<OOSubEntity> *)sub;
- (NSEnumerator *)subEntityEnumerator;
- (NSEnumerator *)effectSubEntityEnumerator;
- (NSEnumerator *)flasherEnumerator;
// TODO: optional appearance on scanners
/*- (void)setScannerDisplayColor1:(OOColor *)color;
- (void)setScannerDisplayColor2:(OOColor *)color; */
// convenience for shaders
// FIXME: make this actually work
- (GLfloat)hullHeatLevel;
- (BOOL) isBreakPattern;
- (void) setIsBreakPattern:(BOOL)bp;
- (NSDictionary *)effectInfoDictionary;
@end

View File

@ -0,0 +1,438 @@
/*
OOVisualEffectEntity.m
Oolite
Copyright (C) 2004-2012 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the impllied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOVisualEffectEntity.h"
#import "OOMaths.h"
#import "Universe.h"
#import "OOShaderMaterial.h"
#import "OOOpenGLExtensionManager.h"
#import "ResourceManager.h"
#import "OOStringParsing.h"
#import "OOCollectionExtractors.h"
#import "OOConstToString.h"
#import "OOConstToJSString.h"
#import "OOMesh.h"
#import "Geometry.h"
#import "Octree.h"
#import "OOColor.h"
#import "OOPolygonSprite.h"
#import "OOFlasherEntity.h"
#import "OODebugGLDrawing.h"
#import "OODebugFlags.h"
#import "OOJSScript.h"
#import "OOFilteringEnumerator.h"
@interface OOVisualEffectEntity (Private)
- (void) drawSubEntity:(BOOL) immediate :(BOOL) translucent;
- (void) addSubEntity:(Entity<OOSubEntity> *) subent;
- (BOOL) setUpOneSubentity:(NSDictionary *) subentDict;
- (BOOL) setUpOneFlasher:(NSDictionary *) subentDict;
- (BOOL) setUpOneStandardSubentity:(NSDictionary *)subentDict;
@end
@implementation OOVisualEffectEntity
- (id) init
{
return [self initWithKey:@"" definition:nil];
}
- (id)initWithKey:(NSString *)key definition:(NSDictionary *)dict
{
OOJS_PROFILE_ENTER
NSParameterAssert(dict != nil);
self = [super init];
if (self == nil) return nil;
_effectKey = [key retain];
if (![self setUpVisualEffectFromDictionary:dict])
{
[self release];
self = nil;
}
collisionTestFilter = NO;
return self;
OOJS_PROFILE_EXIT
}
- (BOOL) setUpVisualEffectFromDictionary:(NSDictionary *) effectDict
{
OOJS_PROFILE_ENTER
effectinfoDictionary = [effectDict copy];
if (effectinfoDictionary == nil) effectinfoDictionary = [[NSDictionary alloc] init];
orientation = kIdentityQuaternion;
rotMatrix = kIdentityMatrix;
NSString *modelName = [effectDict oo_stringForKey:@"model"];
if (modelName != nil)
{
OOMesh *mesh = [OOMesh meshWithName:modelName
cacheKey:_effectKey
materialDictionary:[effectDict oo_dictionaryForKey:@"materials"]
shadersDictionary:[effectDict oo_dictionaryForKey:@"shaders"]
smooth:[effectDict oo_boolForKey:@"smooth" defaultValue:NO]
shaderMacros:OODefaultShipShaderMacros()
shaderBindingTarget:self];
if (mesh == nil) return NO;
[self setMesh:mesh];
}
isImmuneToBreakPatternHide = [effectDict oo_boolForKey:@"is_break_pattern"];
[self clearSubEntities];
[self setUpSubEntities];
// [self setScannerDisplayColor1:nil];
// [self setScannerDisplayColor2:nil];
scanClass = CLASS_NO_DRAW; // TODO: allow appearance on scanner?
[self setStatus:STATUS_EFFECT];
return YES;
OOJS_PROFILE_EXIT
}
- (void) dealloc
{
[self clearSubEntities];
DESTROY(_effectKey);
DESTROY(effectinfoDictionary);
// DESTROY(scanner_display_color1);
// DESTROY(scanner_display_color2);
[super dealloc];
}
- (BOOL) isEffect
{
return YES;
}
- (BOOL) isVisualEffect
{
return YES;
}
- (BOOL) canCollide
{
return NO;
}
- (OOMesh *)mesh
{
return (OOMesh *)[self drawable];
}
- (void)setMesh:(OOMesh *)mesh
{
if (mesh != [self mesh])
{
[self setDrawable:mesh];
}
}
- (GLfloat)frustumRadius
{
return _profileRadius;
}
- (void) clearSubEntities
{
[subEntities makeObjectsPerformSelector:@selector(setOwner:) withObject:nil]; // Ensure backlinks are broken
[subEntities release];
subEntities = nil;
// reset size & mass!
collision_radius = [self findCollisionRadius];
_profileRadius = collision_radius;
}
- (BOOL)setUpSubEntities
{
unsigned int i;
_profileRadius = collision_radius;
NSArray *subs = [effectinfoDictionary oo_arrayForKey:@"subentities"];
for (i = 0; i < [subs count]; i++)
{
[self setUpOneSubentity:[subs oo_dictionaryAtIndex:i]];
}
no_draw_distance = _profileRadius * _profileRadius * NO_DRAW_DISTANCE_FACTOR * NO_DRAW_DISTANCE_FACTOR * 2.0;
return YES;
}
- (BOOL) setUpOneSubentity:(NSDictionary *) subentDict
{
NSString *type = [subentDict oo_stringForKey:@"type"];
if ([type isEqualToString:@"flasher"])
{
return [self setUpOneFlasher:subentDict];
}
else
{
return [self setUpOneStandardSubentity:subentDict];
}
}
- (BOOL) setUpOneFlasher:(NSDictionary *) subentDict
{
OOFlasherEntity *flasher = [OOFlasherEntity flasherWithDictionary:subentDict];
[flasher setPosition:[subentDict oo_vectorForKey:@"position"]];
[self addSubEntity:flasher];
return YES;
}
- (BOOL) setUpOneStandardSubentity:(NSDictionary *)subentDict
{
OOVisualEffectEntity *subentity = nil;
NSString *subentKey = nil;
Vector subPosition;
Quaternion subOrientation;
subentKey = [subentDict oo_stringForKey:@"subentity_key"];
if (subentKey == nil) {
OOLog(@"setup.visualeffect.badEntry.subentities",@"Failed to set up entity - no subentKey in %@",subentDict);
return NO;
}
subentity = [UNIVERSE newVisualEffectWithName:subentKey];
if (subentity == nil) {
OOLog(@"setup.visualeffect.badEntry.subentities",@"Failed to set up entity %@",subentKey);
return NO;
}
subPosition = [subentDict oo_vectorForKey:@"position"];
subOrientation = [subentDict oo_quaternionForKey:@"orientation"];
[subentity setPosition:subPosition];
[subentity setOrientation:subOrientation];
[self addSubEntity:subentity];
[subentity release];
return YES;
}
- (void) addSubEntity:(Entity<OOSubEntity> *) sub {
if (sub == nil) return;
if (subEntities == nil) subEntities = [[NSMutableArray alloc] init];
sub->isSubEntity = YES;
// Order matters - need consistent state in setOwner:. -- Ahruman 2008-04-20
[subEntities addObject:sub];
[sub setOwner:self];
double distance = magnitude([sub position]) + [sub findCollisionRadius];
if (distance > _profileRadius)
{
_profileRadius = distance;
}
}
- (NSArray *)subEntities
{
return [[subEntities copy] autorelease];
}
- (unsigned) subEntityCount
{
return [subEntities count];
}
- (BOOL) hasSubEntity:(Entity<OOSubEntity> *)sub
{
return [subEntities containsObject:sub];
}
- (NSEnumerator *)subEntityEnumerator
{
return [[self subEntities] objectEnumerator];
}
- (NSEnumerator *)effectSubEntityEnumerator
{
return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isVisualEffect)];
}
- (NSEnumerator *)flasherEnumerator
{
return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isFlasher)];
}
- (void) drawSubEntity:(BOOL) immediate :(BOOL) translucent
{
if (cam_zero_distance > no_draw_distance) // this test provides an opportunity to do simple LoD culling
{
return; // TOO FAR AWAY
}
OOGL(glPushMatrix());
GLTranslateOOVector(position);
GLMultOOMatrix(rotMatrix);
[self drawEntity:immediate :translucent];
OOGL(glPopMatrix());
}
- (void) rescaleBy:(GLfloat)factor
{
[self setMesh:[[self mesh] meshRescaledBy:factor]];
// rescale subentities
Entity<OOSubEntity> *se = nil;
foreach (se, [self subEntities])
{
[se setPosition:vector_multiply_scalar([se position], factor)];
[se rescaleBy:factor];
}
}
/*- (void)setScannerDisplayColor1:(OOColor *)color
{
DESTROY(scanner_display_color1);
if (color == nil) color = [OOColor colorWithDescription:[effectinfoDictionary objectForKey:@"scanner_display_color1"]];
scanner_display_color1 = [color retain];
}
- (void)setScannerDisplayColor2:(OOColor *)color
{
DESTROY(scanner_display_color2);
if (color == nil) color = [OOColor colorWithDescription:[effectinfoDictionary objectForKey:@"scanner_display_color2"]];
scanner_display_color2 = [color retain];
}*/
- (void)drawEntity:(BOOL)immediate :(BOOL)translucent
{
if (no_draw_distance < cam_zero_distance)
{
return; // too far away to draw
}
[super drawEntity:immediate :translucent];
// Draw subentities.
if (!immediate) // TODO: is this relevant any longer?
{
OOVisualEffectEntity *subEntity = nil;
foreach (subEntity, [self subEntities])
{
[subEntity drawSubEntity:immediate :translucent];
}
}
}
- (void) update:(OOTimeDelta)delta_t
{
[super update:delta_t];
Entity *se = nil;
foreach (se, [self subEntities])
{
[se update:delta_t];
}
}
- (GLfloat)hullHeatLevel
{
return 60.0 / 256.0;
}
- (BOOL) isBreakPattern
{
return isImmuneToBreakPatternHide;
}
- (void) setIsBreakPattern:(BOOL)bp
{
isImmuneToBreakPatternHide = bp;
}
- (NSDictionary *)effectInfoDictionary
{
return effectinfoDictionary;
}
@end

View File

@ -2056,6 +2056,7 @@ static GLfloat sBaseMass = 0.0;
[self setDockTarget:[UNIVERSE station]];
// send world script events to let oxps know we're in a new system.
// all player.ship properties are still disabled at this stage.
[UNIVERSE setWitchspaceBreakPattern:YES];
[self doScriptEvent:OOJSID("shipWillExitWitchspace")];
[self doScriptEvent:OOJSID("shipExitedWitchspace")];
@ -5529,9 +5530,10 @@ static GLfloat sBaseMass = 0.0;
[self setShowDemoShips:NO];
[[UNIVERSE gameController] setMouseInteractionModeForFlight];
[UNIVERSE setDisplayText:NO];
[UNIVERSE setUpBreakPattern:position orientation:orientation forDocking:NO];
[UNIVERSE setWitchspaceBreakPattern:YES];
[self playExitWitchspace];
[self doScriptEvent:OOJSID("shipWillExitWitchspace")];
[UNIVERSE setUpBreakPattern:position orientation:orientation forDocking:NO];
}

View File

@ -185,15 +185,6 @@ typedef enum
} OOShipDamageType;
// Methods that must be supported by subentities, regardless of type.
@protocol OOSubEntity
- (void) rescaleBy:(GLfloat)factor;
@end
@interface ShipEntity: OOEntityWithDrawable <OOSubEntity>
{
@public

View File

@ -5254,11 +5254,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
// roll or roll factor
if ([result objectForKey:@"stickRollFactor"] != nil)
{
stick_roll = [result oo_floatForKey:@"stickRollFactor" defaultValue:0.0] * max_flight_roll;
stick_roll = [result oo_floatForKey:@"stickRollFactor"] * max_flight_roll;
}
else
{
stick_roll = [result oo_floatForKey:@"stickRoll" defaultValue:0.0];
stick_roll = [result oo_floatForKey:@"stickRoll"];
}
if (stick_roll > max_flight_roll)
{
@ -5272,11 +5272,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
// pitch or pitch factor
if ([result objectForKey:@"stickPitchFactor"] != nil)
{
stick_pitch = [result oo_floatForKey:@"stickPitchFactor" defaultValue:0.0] * max_flight_pitch;
stick_pitch = [result oo_floatForKey:@"stickPitchFactor"] * max_flight_pitch;
}
else
{
stick_pitch = [result oo_floatForKey:@"stickPitch" defaultValue:0.0];
stick_pitch = [result oo_floatForKey:@"stickPitch"];
}
if (stick_pitch > max_flight_pitch)
{
@ -5290,11 +5290,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
// yaw or yaw factor
if ([result objectForKey:@"stickYawFactor"] != nil)
{
stick_yaw = [result oo_floatForKey:@"stickYawFactor" defaultValue:0.0] * max_flight_yaw;
stick_yaw = [result oo_floatForKey:@"stickYawFactor"] * max_flight_yaw;
}
else
{
stick_yaw = [result oo_floatForKey:@"stickYaw" defaultValue:0.0];
stick_yaw = [result oo_floatForKey:@"stickYaw"];
}
if (stick_yaw > max_flight_yaw)
{
@ -5311,11 +5311,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
// desired speed
if ([result objectForKey:@"desiredSpeedFactor"] != nil)
{
desired_speed = [result oo_floatForKey:@"desiredSpeedFactor" defaultValue:0.0] * maxFlightSpeed;
desired_speed = [result oo_floatForKey:@"desiredSpeedFactor"] * maxFlightSpeed;
}
else
{
desired_speed = [result oo_floatForKey:@"desiredSpeed" defaultValue:0.0];
desired_speed = [result oo_floatForKey:@"desiredSpeed"];
}
if (desired_speed < 0.0)

View File

@ -100,7 +100,8 @@ typedef enum
requiresDockingClearance: 1,
interstellarUndockingAllowed: 1,
allowsFastDocking: 1,
allowsAutoDocking: 1;
allowsAutoDocking: 1,
hasBreakPattern: 1;
}
- (NSMutableArray *) localMarket;
@ -212,6 +213,10 @@ typedef enum
- (BOOL) suppressArrivalReports;
- (void) setSuppressArrivalReports:(BOOL)newValue;
- (BOOL) hasBreakPattern;
- (void) setHasBreakPattern:(BOOL)newValue;
@end

View File

@ -519,6 +519,8 @@ NSDictionary *OOMakeDockingInstructions(StationEntity *station, Vector coords, f
isStation = YES;
_shipsOnHold = [[OOWeakSet alloc] init];
}
hasBreakPattern = YES;
return self;
@ -2244,6 +2246,18 @@ NSDictionary *OOMakeDockingInstructions(StationEntity *station, Vector coords, f
}
- (BOOL) hasBreakPattern
{
return hasBreakPattern;
}
- (void) setHasBreakPattern:(BOOL)newValue
{
hasBreakPattern = !!newValue;
}
- (NSString *) descriptionComponents
{
return [NSString stringWithFormat:@"\"%@\" %@", name, [super descriptionComponents]];

View File

@ -980,7 +980,7 @@ static BOOL hostiles;
case CLASS_THARGOID:
foundHostiles = YES;
break;
case CLASS_ROCK:
case CLASS_CARGO:
case CLASS_MISSILE:

View File

@ -74,7 +74,7 @@ static NSString * const kCacheKeyCaches = @"caches";
enum
{
kEndianTagValue = 0x0123456789ABCDEFULL,
kFormatVersionValue = 202
kFormatVersionValue = 203
};

View File

@ -67,6 +67,7 @@ BOOL IsShipPredicate(Entity *entity, void *parameter); // Parameter: ignored
BOOL IsStationPredicate(Entity *entity, void *parameter); // Parameter: ignored. Tests isStation.
BOOL IsPlanetPredicate(Entity *entity, void *parameter); // Parameter: ignored. Tests isPlanet and planetType == STELLAR_TYPE_NORMAL_PLANET.
BOOL IsSunPredicate(Entity *entity, void *parameter); // Parameter: ignored. Tests isSun.
BOOL IsVisualEffectPredicate(Entity *entity, void *parameter); // Parameter: ignored. Tests isVisualEffect and !isSubentity.
// These predicates assume their parameter is a ShipEntity.
BOOL HasRolePredicate(Entity *ship, void *parameter); // Parameter: NSString

View File

@ -145,6 +145,12 @@ BOOL IsSunPredicate(Entity *entity, void *parameter)
}
BOOL IsVisualEffectPredicate(Entity *entity, void *parameter)
{
return [entity isVisualEffect] && ![entity isSubEntity];
}
BOOL HasRolePredicate(Entity *ship, void *parameter)
{
return [(ShipEntity *)ship hasRole:(NSString *)parameter];

View File

@ -35,6 +35,7 @@ SOFTWARE.
@interface OOShipRegistry: NSObject
{
NSDictionary *_shipData;
NSDictionary *_effectData;
NSArray *_demoShips;
NSArray *_playerShips;
NSDictionary *_probabilitySets;
@ -45,6 +46,7 @@ SOFTWARE.
+ (void) reload;
- (NSDictionary *) shipInfoForKey:(NSString *)key;
- (NSDictionary *) effectInfoForKey:(NSString *)key;
- (NSDictionary *) shipyardInfoForKey:(NSString *)key;
- (OOProbabilitySet *) probabilitySetForRole:(NSString *)role;

View File

@ -49,6 +49,7 @@ static void DumpStringAddrs(NSDictionary *dict, NSString *context);
static OOShipRegistry *sSingleton = nil;
static NSString * const kShipRegistryCacheName = @"ship registry";
static NSString * const kShipDataCacheKey = @"ship data";
static NSString * const kPlayerShipsCacheKey = @"player ships";
@ -56,6 +57,8 @@ static NSString * const kDemoShipsCacheKey = @"demo ships";
static NSString * const kConditionScriptsCacheKey = @"condition scripts";
static NSString * const kRoleWeightsCacheKey = @"role weights";
static NSString * const kDefaultDemoShip = @"coriolis-station";
static NSString * const kVisualEffectRegistryCacheName = @"visual effect registry";
static NSString * const kVisualEffectDataCacheKey = @"visual effect data";
@interface OOShipRegistry (OODataLoader)
@ -65,13 +68,13 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
- (void) loadCachedRoleProbabilitySets;
- (void) buildRoleProbabilitySets;
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData;
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData withKey:(NSString *)likeKey;
- (BOOL) loadAndMergeShipyard:(NSMutableDictionary *)ioData;
- (BOOL) stripPrivateKeys:(NSMutableDictionary *)ioData;
- (BOOL) makeShipEntriesMutable:(NSMutableDictionary *)ioData;
- (BOOL) loadAndApplyShipDataOverrides:(NSMutableDictionary *)ioData;
- (BOOL) canonicalizeAndTagSubentities:(NSMutableDictionary *)ioData;
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData;
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData shipMode:(BOOL)shipMode;
- (BOOL) sanitizeConditions:(NSMutableDictionary *)ioData;
#if PRELOAD
@ -145,6 +148,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
_shipData = [[cache objectForKey:kShipDataCacheKey inCache:kShipRegistryCacheName] retain];
_playerShips = [[cache objectForKey:kPlayerShipsCacheKey inCache:kShipRegistryCacheName] retain];
_effectData = [[cache objectForKey:kVisualEffectDataCacheKey inCache:kVisualEffectRegistryCacheName] retain];
if ([_shipData count] == 0) // Don't accept nil or empty
{
[self loadShipData];
@ -201,6 +205,12 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
}
- (NSDictionary *) effectInfoForKey:(NSString *)key
{
return [_effectData objectForKey:key];
}
- (NSDictionary *) shipyardInfoForKey:(NSString *)key
{
return [[self shipInfoForKey:key] objectForKey:@"_oo_shipyard"];
@ -287,7 +297,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
OOLog(@"shipData.load.done", @"Finished stripping private keys...");
// Resolve like_ship entries.
if (![self applyLikeShips:result]) return;
if (![self applyLikeShips:result withKey:@"like_ship"]) return;
OOLog(@"shipData.load.done", @"Finished resolving like_ships...");
// Clean up subentity declarations and tag subentities so they won't be pruned.
@ -295,7 +305,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
OOLog(@"shipData.load.done", @"Finished cleaning up subentities...");
// Clean out templates and invalid entries.
if (![self removeUnusableEntries:result]) return;
if (![self removeUnusableEntries:result shipMode:YES]) return;
OOLog(@"shipData.load.done", @"Finished removing invalid entries...");
// Add shipyard entries into shipdata entries.
@ -317,6 +327,39 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
OOLogOutdentIf(@"shipData.load.begin");
OOLog(@"shipData.load.done", @"Ship data loaded.");
[_effectData release];
_effectData = nil;
result = [[[ResourceManager dictionaryFromFilesNamed:@"effectdata.plist"
inFolder:@"Config"
mergeMode:MERGE_BASIC
cache:NO] mutableCopy] autorelease];
if (result == nil) return;
// Make each entry mutable to simplify later stages. Also removes any entries that aren't dictionaries.
if (![self makeShipEntriesMutable:result]) return;
OOLog(@"effectData.load.done", @"Finished initial cleanup...");
// Strip private keys (anything starting with _oo_).
if (![self stripPrivateKeys:result]) return;
OOLog(@"effectData.load.done", @"Finished stripping private keys...");
// Resolve like_ship entries.
if (![self applyLikeShips:result withKey:@"like_effect"]) return;
OOLog(@"effectData.load.done", @"Finished resolving like_effects...");
// Clean up subentity declarations and tag subentities so they won't be pruned.
if (![self canonicalizeAndTagSubentities:result]) return;
OOLog(@"effectData.load.done", @"Finished cleaning up subentities...");
// Clean out templates and invalid entries.
if (![self removeUnusableEntries:result shipMode:NO]) return;
OOLog(@"effectData.load.done", @"Finished removing invalid entries...");
_effectData = OODeepCopy(result);
[[OOCacheManager sharedCache] setObject:_effectData forKey:kVisualEffectDataCacheKey inCache:kVisualEffectRegistryCacheName];
}
@ -434,7 +477,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
resolved (either their like_ships do not exist, or they form reference
cycles) so we stop looping and report it.
*/
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData
- (BOOL) applyLikeShips:(NSMutableDictionary *)ioData withKey:(NSString *)likeKey
{
NSMutableSet *remainingLikeShips = nil;
NSEnumerator *enumerator = nil;
@ -450,7 +493,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
for (enumerator = [ioData keyEnumerator]; (key = [enumerator nextObject]); )
{
shipEntry = [ioData objectForKey:key];
if ([shipEntry oo_stringForKey:@"like_ship"] != nil)
if ([shipEntry oo_stringForKey:likeKey] != nil)
{
[remainingLikeShips addObject:key];
}
@ -463,7 +506,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
{
// Look up like_ship entry
shipEntry = [ioData objectForKey:key];
parentKey = [shipEntry objectForKey:@"like_ship"];
parentKey = [shipEntry objectForKey:likeKey];
if (![remainingLikeShips containsObject:parentKey])
{
// If parent is fully resolved, we can resolve this child.
@ -497,7 +540,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
if ([reportedBadShips count] != 0)
{
[reportedBadShips sortUsingSelector:@selector(caseInsensitiveCompare:)];
OOLogERR(@"shipData.merge.failed", @"one or more shipdata.plist entries have like_ship references that cannot be resolved: %@", [reportedBadShips componentsJoinedByString:@", "]);
OOLogERR(@"shipData.merge.failed", @"one or more shipdata.plist entries have %@ references that cannot be resolved: %@", likeKey, [reportedBadShips componentsJoinedByString:@", "]); // FIXME: distinguish shipdata and effectdata
}
break;
}
@ -813,7 +856,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
}
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData
- (BOOL) removeUnusableEntries:(NSMutableDictionary *)ioData shipMode:(BOOL)shipMode
{
NSEnumerator *shipKeyEnum = nil;
NSString *shipKey = nil;
@ -828,7 +871,7 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
remove = NO;
if ([shipEntry oo_boolForKey:@"is_template"] || [shipEntry oo_boolForKey:@"_oo_deferred_remove"]) remove = YES;
else if ([[shipEntry oo_stringForKey:@"roles"] length] == 0 && ![shipEntry oo_boolForKey:@"_oo_is_subentity"])
else if (shipMode && [[shipEntry oo_stringForKey:@"roles"] length] == 0 && ![shipEntry oo_boolForKey:@"_oo_is_subentity"] && ![shipEntry oo_boolForKey:@"_oo_is_effect"])
{
OOLogERR(@"shipData.load.error", @"the shipdata.plist entry \"%@\" specifies no %@.", shipKey, @"roles");
remove = YES;
@ -836,12 +879,12 @@ static NSString * const kDefaultDemoShip = @"coriolis-station";
else
{
modelName = [shipEntry oo_stringForKey:@"model"];
if ([modelName length] == 0)
if (shipMode && [modelName length] == 0)
{
OOLogERR(@"shipData.load.error", @"the shipdata.plist entry \"%@\" specifies no %@.", shipKey, @"model");
remove = YES;
}
else if ([ResourceManager pathForFileNamed:modelName inFolder:@"Models"] == nil)
else if (shipMode && [ResourceManager pathForFileNamed:modelName inFolder:@"Models"] == nil)
{
OOLogERR(@"shipData.load.error", @"the shipdata.plist entry \"%@\" specifies non-existent model \"%@\".", shipKey, modelName);
remove = YES;

View File

@ -31,6 +31,7 @@ MA 02110-1301, USA.
#import "OOJSDock.h"
#import "DockEntity.h"
#import "OOPlanetEntity.h"
#import "OOVisualEffectEntity.h"
@implementation Entity (OOJavaScriptExtensions)
@ -157,3 +158,13 @@ MA 02110-1301, USA.
}
@end
@implementation OOVisualEffectEntity (OOJavaScriptExtensions)
- (BOOL) isVisibleToScripts
{
return YES;
}
@end

View File

@ -71,6 +71,9 @@ enum
{
// Property IDs
kStation_alertCondition,
kStation_allowsAutoDocking,
kStation_allowsFastDocking,
kStation_breakPattern,
kStation_dockedContractors, // miners and scavengers.
kStation_dockedDefenders,
kStation_dockedPolice,
@ -80,8 +83,6 @@ enum
kStation_hasShipyard,
kStation_isMainStation, // Is [UNIVERSE station], boolean, read-only
kStation_requiresDockingClearance,
kStation_allowsFastDocking,
kStation_allowsAutoDocking,
kStation_suppressArrivalReports,
};
@ -92,6 +93,7 @@ static JSPropertySpec sStationProperties[] =
{ "alertCondition", kStation_alertCondition, OOJS_PROP_READWRITE_CB },
{ "allowsAutoDocking", kStation_allowsAutoDocking, OOJS_PROP_READWRITE_CB },
{ "allowsFastDocking", kStation_allowsFastDocking, OOJS_PROP_READWRITE_CB },
{ "breakPattern", kStation_breakPattern, OOJS_PROP_READWRITE_CB },
{ "dockedContractors", kStation_dockedContractors, OOJS_PROP_READONLY_CB },
{ "dockedDefenders", kStation_dockedDefenders, OOJS_PROP_READONLY_CB },
{ "dockedPolice", kStation_dockedPolice, OOJS_PROP_READONLY_CB },
@ -233,6 +235,10 @@ static JSBool StationGetProperty(JSContext *context, JSObject *this, jsid propID
*value = OOJSValueFromBOOL([entity suppressArrivalReports]);
return YES;
case kStation_breakPattern:
*value = OOJSValueFromBOOL([entity hasBreakPattern]);
return YES;
default:
OOJSReportBadPropertySelector(context, this, propID, sStationProperties);
return NO;
@ -304,6 +310,14 @@ static JSBool StationSetProperty(JSContext *context, JSObject *this, jsid propID
return YES;
}
break;
case kStation_breakPattern:
if (JS_ValueToBoolean(context, *value, &bValue))
{
[entity setHasBreakPattern:bValue];
return YES;
}
break;
default:
OOJSReportBadPropertySelector(context, this, propID, sStationProperties);

View File

@ -73,6 +73,7 @@ static JSBool SystemAddShips(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddGroup(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddShipsToRoute(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddGroupToRoute(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemLegacyAddShips(JSContext *context, uintN argc, jsval *vp);
static JSBool SystemLegacyAddSystemShips(JSContext *context, uintN argc, jsval *vp);
@ -106,6 +107,8 @@ enum
{
// Property IDs
kSystem_allShips, // ships in system, array of Ship, read-only
kSystem_allVisualEffects, // VEs in system, array of VEs, read-only
kSystem_breakPattern, // witchspace break pattern shown
kSystem_description, // description, string, read/write
kSystem_economy, // economy ID, integer, read/write
kSystem_economyDescription, // economy ID description, string, read-only
@ -133,6 +136,8 @@ static JSPropertySpec sSystemProperties[] =
{
// JS name ID flags
{ "allShips", kSystem_allShips, OOJS_PROP_READONLY_CB },
{ "allVisualEffects", kSystem_allVisualEffects, OOJS_PROP_READONLY_CB },
{ "breakPattern", kSystem_breakPattern, OOJS_PROP_READWRITE_CB },
{ "description", kSystem_description, OOJS_PROP_READWRITE_CB },
{ "economy", kSystem_economy, OOJS_PROP_READWRITE_CB },
{ "economyDescription", kSystem_economyDescription, OOJS_PROP_READONLY_CB },
@ -167,6 +172,7 @@ static JSFunctionSpec sSystemMethods[] =
{ "addPlanet", SystemAddPlanet, 1 },
{ "addShips", SystemAddShips, 3 },
{ "addShipsToRoute", SystemAddShipsToRoute, 2 },
{ "addVisualEffect", SystemAddVisualEffect, 2 },
{ "countEntitiesWithScanClass", SystemCountEntitiesWithScanClass, 1 },
{ "countShipsWithPrimaryRole", SystemCountShipsWithPrimaryRole, 1 },
{ "countShipsWithRole", SystemCountShipsWithRole, 1 },
@ -255,6 +261,13 @@ static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsid propID,
OOJS_END_FULL_NATIVE
handled = YES;
break;
case kSystem_allVisualEffects:
OOJS_BEGIN_FULL_NATIVE(context)
result = [UNIVERSE findVisualEffectsMatchingPredicate:JSEntityIsJavaScriptSearchablePredicate parameter:NULL inRange:-1 ofEntity:nil];
OOJS_END_FULL_NATIVE
handled = YES;
break;
case kSystem_info:
*value = GetJSSystemInfoForSystem(context, [player currentGalaxyID], [player currentSystemID]);
@ -270,6 +283,10 @@ static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsid propID,
case kSystem_pseudoRandom256:
*value = INT_TO_JSVAL([player systemPseudoRandom256]);
return YES;
case kSystem_breakPattern:
*value = OOJSValueFromBOOL([UNIVERSE witchspaceBreakPattern]);
return YES;
}
if (!handled)
@ -398,13 +415,29 @@ static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsid propID,
OOSystemID system;
NSString *stringValue = nil;
int32 iValue;
JSBool bValue;
player = OOPlayerForScripting();
galaxy = [player currentGalaxyID];
system = [player currentSystemID];
switch (JSID_TO_INT(propID))
{
case kSystem_breakPattern:
if (JS_ValueToBoolean(context, *value, &bValue))
{
[UNIVERSE setWitchspaceBreakPattern:bValue];
return YES;
}
break;
default:
{}// do nothing yet
}
if (system == -1) return YES; // Can't change anything in interstellar space.
if (system == -1) return YES; // Can't change anything else in interstellar space.
switch (JSID_TO_INT(propID))
{
@ -1071,7 +1104,9 @@ static JSBool SystemStaticSystemIDForName(JSContext *context, uintN argc, jsval
}
OOJS_BEGIN_FULL_NATIVE(context)
result = [UNIVERSE systemIDForSystemSeed:[UNIVERSE systemSeedForSystemName:name]];
OOJS_END_FULL_NATIVE
OOJS_RETURN_INT(result);
@ -1112,6 +1147,41 @@ static JSBool SystemStaticInfoForSystem(JSContext *context, uintN argc, jsval *v
}
static JSBool SystemAddVisualEffect(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
NSString *key = nil;
Vector where;
uintN consumed = 0;
if (argc > 0) key = OOStringFromJSValue(context, OOJS_ARGV[0]);
if (key == nil)
{
OOJSReportBadArguments(context, @"System", @"addVisualEffect", MIN(argc, 1U), &OOJS_ARGV[0], nil, @"string (key)");
return NO;
}
if (!VectorFromArgumentListNoError(context, argc - 1, OOJS_ARGV + 1, &where, &consumed))
{
OOJSReportBadArguments(context, @"System", @"addVisualEffect", MIN(argc - 1, 1U), &OOJS_ARGV[1], nil, @"vector");
return NO;
}
OOVisualEffectEntity *result = nil;
OOJS_BEGIN_FULL_NATIVE(context)
result = [UNIVERSE addVisualEffectAt:where withKey:key];
OOJS_END_FULL_NATIVE
OOJS_RETURN_OBJECT(result);
OOJS_NATIVE_EXIT
}
// *** Helper functions ***
// Shared implementation of addShips() and addGroup().

View File

@ -0,0 +1,33 @@
/*
OOJSVisualEffect.h
JavaScript proxy for OOVisualEffectEntities.
Oolite
Copyright (C) 2004-2012 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import <Foundation/Foundation.h>
#include <jsapi.h>
@class OOVisualEffectEntity;
void InitOOJSVisualEffect(JSContext *context, JSObject *global);

View File

@ -0,0 +1,389 @@
/*
OOJSVisualEffect.m
Oolite
Copyright (C) 2004-2012 Giles C Williams and contributors
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
*/
#import "OOVisualEffectEntity.h"
#import "OOJSVisualEffect.h"
#import "OOJSEntity.h"
#import "OOJavaScriptEngine.h"
#import "OOMesh.h"
#import "OOCollectionExtractors.h"
#import "ResourceManager.h"
static JSObject *sVisualEffectPrototype;
static BOOL JSVisualEffectGetVisualEffectEntity(JSContext *context, JSObject *stationObj, OOVisualEffectEntity **outEntity);
static JSBool VisualEffectGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
static JSBool VisualEffectSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
static JSBool VisualEffectRemove(JSContext *context, uintN argc, jsval *vp);
static JSBool VisualEffectGetShaders(JSContext *context, uintN argc, jsval *vp);
static JSBool VisualEffectSetShaders(JSContext *context, uintN argc, jsval *vp);
static JSBool VisualEffectGetMaterials(JSContext *context, uintN argc, jsval *vp);
static JSBool VisualEffectSetMaterials(JSContext *context, uintN argc, jsval *vp);
static JSBool VisualEffectSetMaterialsInternal(JSContext *context, uintN argc, jsval *vp, OOVisualEffectEntity *thisEnt, BOOL fromShaders);
static JSClass sVisualEffectClass =
{
"VisualEffect",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, // addProperty
JS_PropertyStub, // delProperty
VisualEffectGetProperty, // getProperty
VisualEffectSetProperty, // setProperty
JS_EnumerateStub, // enumerate
JS_ResolveStub, // resolve
JS_ConvertStub, // convert
OOJSObjectWrapperFinalize,// finalize
JSCLASS_NO_OPTIONAL_MEMBERS
};
enum
{
// Property IDs
kVisualEffect_isBreakPattern
};
static JSPropertySpec sVisualEffectProperties[] =
{
// JS name ID flags
{ "isBreakPatterns", kVisualEffect_isBreakPattern, OOJS_PROP_READWRITE_CB },
{ 0 }
};
static JSFunctionSpec sVisualEffectMethods[] =
{
// JS name Function min args
{ "remove", VisualEffectRemove, 0 },
{ "getMaterials", VisualEffectGetMaterials, 0 },
{ "getShaders", VisualEffectGetShaders, 0 },
{ "setMaterials", VisualEffectSetMaterials, 1 },
{ "setShaders", VisualEffectSetShaders, 2 },
{ 0 }
};
void InitOOJSVisualEffect(JSContext *context, JSObject *global)
{
sVisualEffectPrototype = JS_InitClass(context, global, JSEntityPrototype(), &sVisualEffectClass, OOJSUnconstructableConstruct, 0, sVisualEffectProperties, sVisualEffectMethods, NULL, NULL);
OOJSRegisterObjectConverter(&sVisualEffectClass, OOJSBasicPrivateObjectConverter);
OOJSRegisterSubclass(&sVisualEffectClass, JSEntityClass());
}
static BOOL JSVisualEffectGetVisualEffectEntity(JSContext *context, JSObject *visualEffectObj, OOVisualEffectEntity **outEntity)
{
OOJS_PROFILE_ENTER
BOOL result;
Entity *entity = nil;
if (outEntity == NULL) return NO;
*outEntity = nil;
result = OOJSEntityGetEntity(context, visualEffectObj, &entity);
if (!result) return NO;
if (![entity isKindOfClass:[OOVisualEffectEntity class]]) return NO;
*outEntity = (OOVisualEffectEntity *)entity;
return YES;
OOJS_PROFILE_EXIT
}
@implementation OOVisualEffectEntity (OOJavaScriptExtensions)
- (void)getJSClass:(JSClass **)outClass andPrototype:(JSObject **)outPrototype
{
*outClass = &sVisualEffectClass;
*outPrototype = sVisualEffectPrototype;
}
- (NSString *) oo_jsClassName
{
return @"VisualEffect";
}
@end
static JSBool VisualEffectGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
{
if (!JSID_IS_INT(propID)) return YES;
OOJS_NATIVE_ENTER(context)
OOVisualEffectEntity *entity = nil;
if (!JSVisualEffectGetVisualEffectEntity(context, this, &entity)) return NO;
if (entity == nil) { *value = JSVAL_VOID; return YES; }
switch (JSID_TO_INT(propID))
{
case kVisualEffect_isBreakPattern:
*value = OOJSValueFromBOOL([entity isBreakPattern]);
return YES;
default:
OOJSReportBadPropertySelector(context, this, propID, sVisualEffectProperties);
return NO;
}
OOJS_NATIVE_EXIT
}
static JSBool VisualEffectSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
{
if (!JSID_IS_INT(propID)) return YES;
OOJS_NATIVE_ENTER(context)
OOVisualEffectEntity *entity = nil;
JSBool bValue;
// int32 iValue;
if (!JSVisualEffectGetVisualEffectEntity(context, this, &entity)) return NO;
if (entity == nil) return YES;
switch (JSID_TO_INT(propID))
{
case kVisualEffect_isBreakPattern:
if (JS_ValueToBoolean(context, *value, &bValue))
{
[entity setIsBreakPattern:bValue];
return YES;
}
break;
default:
OOJSReportBadPropertySelector(context, this, propID, sVisualEffectProperties);
return NO;
}
OOJSReportBadPropertyValue(context, this, propID, sVisualEffectProperties, *value);
return NO;
OOJS_NATIVE_EXIT
}
// *** Methods ***
#define GET_THIS_EFFECT(THISENT) do { \
if (EXPECT_NOT(!JSVisualEffectGetVisualEffectEntity(context, OOJS_THIS, &THISENT))) return NO; /* Exception */ \
if (OOIsStaleEntity(THISENT)) OOJS_RETURN_VOID; \
} while (0)
static JSBool VisualEffectRemove(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
OOVisualEffectEntity *thisEnt = nil;
GET_THIS_EFFECT(thisEnt);
[UNIVERSE removeEntity:(Entity*)thisEnt];
OOJS_RETURN_VOID;
OOJS_NATIVE_EXIT
}
//getMaterials()
static JSBool VisualEffectGetMaterials(JSContext *context, uintN argc, jsval *vp)
{
OOJS_PROFILE_ENTER
NSObject *result = nil;
OOVisualEffectEntity *thisEnt = nil;
GET_THIS_EFFECT(thisEnt);
result = [[thisEnt mesh] materials];
if (result == nil) result = [NSDictionary dictionary];
OOJS_RETURN_OBJECT(result);
OOJS_PROFILE_EXIT
}
//getShaders()
static JSBool VisualEffectGetShaders(JSContext *context, uintN argc, jsval *vp)
{
OOJS_PROFILE_ENTER
NSObject *result = nil;
OOVisualEffectEntity *thisEnt = nil;
GET_THIS_EFFECT(thisEnt);
result = [[thisEnt mesh] shaders];
if (result == nil) result = [NSDictionary dictionary];
OOJS_RETURN_OBJECT(result);
OOJS_PROFILE_EXIT
}
// setMaterials(params: dict, [shaders: dict]) // sets materials dictionary. Optional parameter sets the shaders dictionary too.
static JSBool VisualEffectSetMaterials(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
OOVisualEffectEntity *thisEnt = nil;
if (argc < 1)
{
OOJSReportBadArguments(context, @"VisualEffect", @"setMaterials", 0, OOJS_ARGV, nil, @"parameter object");
return NO;
}
GET_THIS_EFFECT(thisEnt);
return VisualEffectSetMaterialsInternal(context, argc, vp, thisEnt, NO);
OOJS_NATIVE_EXIT
}
// setShaders(params: dict)
static JSBool VisualEffectSetShaders(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context)
OOVisualEffectEntity *thisEnt = nil;
GET_THIS_EFFECT(thisEnt);
if (argc < 1)
{
OOJSReportBadArguments(context, @"VisualEffect", @"setShaders", 0, OOJS_ARGV, nil, @"parameter object");
return NO;
}
if (JSVAL_IS_NULL(OOJS_ARGV[0]) || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JSVAL_IS_OBJECT(OOJS_ARGV[0])))
{
// EMMSTRAN: JS_ValueToObject() and normal error handling here.
OOJSReportWarning(context, @"VisualEffect.%@: expected %@ instead of '%@'.", @"setShaders", @"object", [NSString stringWithJavaScriptValue:OOJS_ARGV[0] inContext:context]);
OOJS_RETURN_BOOL(NO);
}
OOJS_ARGV[1] = OOJS_ARGV[0];
return VisualEffectSetMaterialsInternal(context, argc, vp, thisEnt, YES);
OOJS_NATIVE_EXIT
}
/* ** helper functions ** */
static JSBool VisualEffectSetMaterialsInternal(JSContext *context, uintN argc, jsval *vp, OOVisualEffectEntity *thisEnt, BOOL fromShaders)
{
OOJS_PROFILE_ENTER
JSObject *params = NULL;
NSDictionary *materials;
NSDictionary *shaders;
BOOL withShaders = NO;
BOOL success = NO;
GET_THIS_EFFECT(thisEnt);
if (JSVAL_IS_NULL(OOJS_ARGV[0]) || (!JSVAL_IS_NULL(OOJS_ARGV[0]) && !JSVAL_IS_OBJECT(OOJS_ARGV[0])))
{
OOJSReportWarning(context, @"VisualEffect.%@: expected %@ instead of '%@'.", @"setMaterials", @"object", [NSString stringWithJavaScriptValue:OOJS_ARGV[0] inContext:context]);
OOJS_RETURN_BOOL(NO);
}
if (argc > 1)
{
withShaders = YES;
if (JSVAL_IS_NULL(OOJS_ARGV[1]) || (!JSVAL_IS_NULL(OOJS_ARGV[1]) && !JSVAL_IS_OBJECT(OOJS_ARGV[1])))
{
OOJSReportWarning(context, @"VisualEffect.%@: expected %@ instead of '%@'.", @"setMaterials", @"object as second parameter", [NSString stringWithJavaScriptValue:OOJS_ARGV[1] inContext:context]);
withShaders = NO;
}
}
if (fromShaders)
{
materials = [[thisEnt mesh] materials];
params = JSVAL_TO_OBJECT(OOJS_ARGV[0]);
shaders = OOJSNativeObjectFromJSObject(context, params);
}
else
{
params = JSVAL_TO_OBJECT(OOJS_ARGV[0]);
materials = OOJSNativeObjectFromJSObject(context, params);
if (withShaders)
{
params = JSVAL_TO_OBJECT(OOJS_ARGV[1]);
shaders = OOJSNativeObjectFromJSObject(context, params);
}
else
{
shaders = [[thisEnt mesh] shaders];
}
}
OOJS_BEGIN_FULL_NATIVE(context)
NSDictionary *effectDict = [thisEnt effectInfoDictionary];
// First we test to see if we can create the mesh.
OOMesh *mesh = [OOMesh meshWithName:[effectDict oo_stringForKey:@"model"]
cacheKey:nil
materialDictionary:materials
shadersDictionary:shaders
smooth:[effectDict oo_boolForKey:@"smooth" defaultValue:NO]
shaderMacros:[[ResourceManager materialDefaults] oo_dictionaryForKey:@"ship-prefix-macros"]
shaderBindingTarget:thisEnt];
if (mesh != nil)
{
[thisEnt setMesh:mesh];
success = YES;
}
OOJS_END_FULL_NATIVE
OOJS_RETURN_BOOL(success);
OOJS_PROFILE_EXIT
}

View File

@ -46,6 +46,7 @@ MA 02110-1301, USA.
#import "OOJSShip.h"
#import "OOJSStation.h"
#import "OOJSDock.h"
#import "OOJSVisualEffect.h"
#import "OOJSPlayer.h"
#import "OOJSPlayerShip.h"
#import "OOJSManifest.h"
@ -346,6 +347,7 @@ static void ReportJSError(JSContext *context, const char *message, JSErrorReport
InitOOJSShip(gOOJSMainThreadContext, _globalObject);
InitOOJSStation(gOOJSMainThreadContext, _globalObject);
InitOOJSDock(gOOJSMainThreadContext, _globalObject);
InitOOJSVisualEffect(gOOJSMainThreadContext, _globalObject);
InitOOJSPlayer(gOOJSMainThreadContext, _globalObject);
InitOOJSPlayerShip(gOOJSMainThreadContext, _globalObject);
InitOOJSManifest(gOOJSMainThreadContext, _globalObject);

View File

@ -41,8 +41,9 @@ MA 02110-1301, USA.
#endif
@class GameController, CollisionRegion, MyOpenGLView, GuiDisplayGen,
Entity, ShipEntity, StationEntity, OOPlanetEntity, OOSunEntity,
PlayerEntity, OORoleSet, WormholeEntity, DockEntity, OOJSScript;
Entity, ShipEntity, StationEntity, OOPlanetEntity, OOSunEntity,
OOVisualEffectEntity, PlayerEntity, OORoleSet, WormholeEntity,
DockEntity, OOJSScript;
typedef BOOL (*EntityFilterPredicate)(Entity *entity, void *parameter);
@ -309,6 +310,7 @@ enum
BOOL _pauseMessage;
BOOL _autoCommLog;
BOOL _permanentCommLog;
BOOL _witchspaceBreakPattern;
}
- (id)initWithGameView:(MyOpenGLView *)gameView;
@ -360,6 +362,7 @@ enum
- (void) witchspaceShipWithPrimaryRole:(NSString *)role;
- (ShipEntity *) spawnShipWithRole:(NSString *) desc near:(Entity *) entity;
- (OOVisualEffectEntity *) addVisualEffectAt:(Vector)pos withKey:(NSString *)key;
- (ShipEntity *) addShipAt:(Vector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius;
- (NSArray *) addShipsAt:(Vector)pos withRole:(NSString *)role quantity:(unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup;
- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(unsigned)count routeFraction:(double)routeFraction asGroup:(BOOL)isGroup;
@ -371,6 +374,10 @@ enum
- (GLfloat) safeWitchspaceExitDistance;
- (void) setUpBreakPattern:(Vector)pos orientation:(Quaternion)q forDocking:(BOOL)forDocking;
- (BOOL) witchspaceBreakPattern;
- (void) setWitchspaceBreakPattern:(BOOL)newValue;
- (void) handleGameOver;
- (void) setupIntroFirstGo:(BOOL)justCobra;
@ -403,6 +410,7 @@ enum
- (NSString *) randomShipKeyForRoleRespectingConditions:(NSString *)role;
- (ShipEntity *) newShipWithRole:(NSString *)role OO_RETURNS_RETAINED; // Selects ship using role weights, applies auto_ai, respects conditions
- (ShipEntity *) newShipWithName:(NSString *)shipKey OO_RETURNS_RETAINED; // Does not apply auto_ai or respect conditions
- (OOVisualEffectEntity *) newVisualEffectWithName:(NSString *)effectKey OO_RETURNS_RETAINED;
- (DockEntity *) newDockWithName:(NSString *)shipKey OO_RETURNS_RETAINED; // Does not apply auto_ai or respect conditions
- (ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy OO_RETURNS_RETAINED; // If usePlayerProxy, non-carriers are instantiated as ProxyPlayerEntity.
@ -491,6 +499,10 @@ enum
parameter:(void *)parameter
inRange:(double)range
ofEntity:(Entity *)entity;
- (NSMutableArray *) findVisualEffectsMatchingPredicate:(EntityFilterPredicate)predicate
parameter:(void *)parameter
inRange:(double)range
ofEntity:(Entity *)entity;
- (id) nearestEntityMatchingPredicate:(EntityFilterPredicate)predicate
parameter:(void *)parameter
relativeToEntity:(Entity *)entity;

View File

@ -63,6 +63,7 @@ MA 02110-1301, USA.
#import "SkyEntity.h"
#import "DustEntity.h"
#import "OOPlanetEntity.h"
#import "OOVisualEffectEntity.h"
#import "OOSunEntity.h"
#import "WormholeEntity.h"
#import "OOBreakPatternEntity.h"
@ -584,6 +585,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
blue:0.0f
alpha:0.0f];
[self setWitchspaceBreakPattern:YES];
[player doScriptEvent:OOJSID("shipWillExitWitchspace")];
[player doScriptEvent:OOJSID("shipExitedWitchspace")];
[player setWormhole:nil];
@ -654,6 +656,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[dockedStation setPosition: pos];
}
[self setWitchspaceBreakPattern:YES];
[player doScriptEvent:OOJSID("shipWillExitWitchspace")];
[player doScriptEvent:OOJSID("shipExitedWitchspace")];
}
@ -1955,6 +1958,29 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
- (OOVisualEffectEntity *) addVisualEffectAt:(Vector)pos withKey:(NSString *)key
{
OOJS_PROFILE_ENTER
// minimise the time between creating ship & assigning position.
OOVisualEffectEntity *vis = [self newVisualEffectWithName:key]; // is retained
BOOL success = NO;
if (vis != nil)
{
[vis setPosition:pos];
[vis setOrientation:OORandomQuaternion()];
success = [self addEntity:vis]; // retained globally now
[vis release];
}
return success ? vis : (OOVisualEffectEntity *)nil;
OOJS_PROFILE_EXIT
}
- (ShipEntity *) addShipAt:(Vector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius
{
OOJS_PROFILE_ENTER
@ -2277,12 +2303,34 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[ring setVelocity:v];
[ring setLifetime:i*50.0];
[ring setScanClass: CLASS_NO_DRAW];
// FIXME: better would be to have break pattern timing not depend on
// these ring objects existing in the first place. - CIM
if (forDocking && ![[PLAYER dockedStation] hasBreakPattern])
{
ring->isImmuneToBreakPatternHide = NO;
}
else if (!forDocking && ![self witchspaceBreakPattern])
{
ring->isImmuneToBreakPatternHide = NO;
}
[self addEntity:ring];
breakPatternCounter++;
}
}
- (BOOL) witchspaceBreakPattern
{
return _witchspaceBreakPattern;
}
- (void) setWitchspaceBreakPattern:(BOOL)newValue
{
_witchspaceBreakPattern = !!newValue;
}
- (void) handleGameOver
{
// In unrestricted mode, reload last save game, if any. In strict mode, always restart as a fresh Jameson.
@ -2720,6 +2768,36 @@ static BOOL IsFriendlyStationPredicate(Entity *entity, void *parameter)
}
- (OOVisualEffectEntity *) newVisualEffectWithName:(NSString *)effectKey
{
OOJS_PROFILE_ENTER
NSDictionary *effectDict = nil;
OOVisualEffectEntity *effect = nil;
effectDict = [[OOShipRegistry sharedRegistry] effectInfoForKey:effectKey];
if (effectDict == nil) return nil;
NS_DURING
effect = [[OOVisualEffectEntity alloc] initWithKey:effectKey definition:effectDict];
NS_HANDLER
[effect release];
effect = nil;
if ([[localException name] isEqual:OOLITE_EXCEPTION_DATA_NOT_FOUND])
{
OOLog(kOOLogException, @"***** Oolite Exception : '%@' in [Universe newVisualEffectWithName: %@ ] *****", [localException reason], effectKey);
}
else [localException raise];
NS_ENDHANDLER
// MKW 20090327 - retain count is actually 2!
return effect; // retain count = 1
OOJS_PROFILE_EXIT
}
- (ShipEntity *) newShipWithName:(NSString *)shipKey usePlayerProxy:(BOOL)usePlayerProxy
{
OOJS_PROFILE_ENTER
@ -4948,6 +5026,34 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
}
- (NSMutableArray *) findVisualEffectsMatchingPredicate:(EntityFilterPredicate)predicate
parameter:(void *)parameter
inRange:(double)range
ofEntity:(Entity *)entity
{
if (predicate != NULL)
{
BinaryOperationPredicateParameter param =
{
IsVisualEffectPredicate, NULL,
predicate, parameter
};
return [self findEntitiesMatchingPredicate:ANDPredicate
parameter:&param
inRange:range
ofEntity:entity];
}
else
{
return [self findEntitiesMatchingPredicate:IsVisualEffectPredicate
parameter:NULL
inRange:range
ofEntity:entity];
}
}
- (id) nearestEntityMatchingPredicate:(EntityFilterPredicate)predicate
parameter:(void *)parameter
relativeToEntity:(Entity *)entity
@ -9841,6 +9947,7 @@ static void PreloadOneSound(NSString *soundName)
];
[pool release];
}
if (!sunGoneNova && !includedHermit)
{