1
0
mirror of https://github.com/thes3m/XNI synced 2024-12-26 13:26:06 +01:00

Game components handling updated to enable change of order during update. Various leaks removed.

git-svn-id: http://xni.googlecode.com/svn/XNI@52 ac433895-eea3-a490-d80a-17149a75e588
This commit is contained in:
Matej Jan 2011-01-15 02:05:37 +00:00
parent 1ca44f0f04
commit 7cd74d182f
31 changed files with 450 additions and 62 deletions

View File

@ -11,6 +11,7 @@
#import "Retronator.Xni.Framework.classes.h"
#import "Retronator.Xni.Framework.Content.classes.h"
#import "Retronator.Xni.Framework.Content.Pipeline.classes.h"
@interface ContentManager : NSObject {
NSString *rootDirectory;
@ -29,8 +30,12 @@
@property (nonatomic, readonly) id<IServiceProvider> serviceProvider;
- (id) load:(NSString*)assetName;
- (id) load:(NSString *)assetName processor:(ContentProcessor*)processor;
- (id) load:(NSString *)assetName importer:(ContentImporter*)importer processor:(ContentProcessor*)processor;
- (id) load:(NSString*)assetName fromFile:(NSString*)filePath;
- (id) load:(NSString *)assetName fromFile:(NSString*)filePath processor:(ContentProcessor*)processor;
- (id) load:(NSString *)assetName fromFile:(NSString*)filePath importer:(ContentImporter*)importer processor:(ContentProcessor*)processor;
- (void) unload;

View File

@ -40,7 +40,14 @@
}
- (id) load:(NSString *)assetName{
return [self load:assetName importer:nil processor:nil];
}
- (id) load:(NSString *)assetName processor:(ContentProcessor *)processor {
return [self load:assetName importer:nil processor:processor];
}
- (id) load:(NSString *)assetName importer:(ContentImporter *)importer processor:(ContentProcessor *)processor {
// Check if we have already loaded this asset.
id existing = [loadedAssets objectForKey:assetName];
if (existing) {
@ -56,7 +63,7 @@
for (int i = 0; i < count; i++) {
NSString *file = [files objectAtIndex:i];
if ([[file stringByDeletingPathExtension] isEqual:assetName]) {
return [self load:assetName fromFile:file];
return [self load:assetName fromFile:file importer:importer processor:processor];
}
}
@ -65,7 +72,14 @@
}
- (id) load:(NSString *)assetName fromFile:(NSString *)filePath {
return [self load:assetName fromFile:filePath importer:nil processor:nil];
}
- (id) load:(NSString *)assetName fromFile:(NSString *)filePath processor:(ContentProcessor *)processor {
return [self load:assetName fromFile:filePath importer:nil processor:processor];
}
- (id) load:(NSString *)assetName fromFile:(NSString *)filePath importer:(ContentImporter *)importer processor:(ContentProcessor *)processor {
// Check if we have already loaded this file.
id existing = [loadedFiles objectForKey:filePath];
if (existing) {
@ -76,6 +90,8 @@
NSString *fileName = [filePath stringByDeletingPathExtension];
NSString *extension = [filePath pathExtension];
NSString *absolutePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension inDirectory:rootDirectory];
// Bug in NSBundle - we are returned an object that doesn't have an object count 0, so we release it ourselves to avoid a leak.
[absolutePath autorelease];
if (!absolutePath) {
@ -94,38 +110,54 @@
[extension isEqualToString:@"gif"] || [extension isEqualToString:@"tif"] || [extension isEqualToString:@"tiff"] ||
[extension isEqualToString:@"ico"] || [extension isEqualToString:@"bmp"]) {
// Texture content
TextureImporter *textureImporter = [[[TextureImporter alloc] init] autorelease];
TextureContent *textureContent = [textureImporter importFile:absolutePath];
input = [[ContentReader alloc] initWithContentManager:self Content:textureContent];
if (!importer) {
importer = [[[TextureImporter alloc] init] autorelease];
}
} else if ([extension isEqualToString:@"x"]) {
// Direct x model content
XImporter *xImporter = [[[XImporter alloc] init] autorelease];
NodeContent *root = [xImporter importFile:absolutePath];
ModelProcessor *modelProcessor = [[[ModelProcessor alloc] init] autorelease];
ModelContent *modelContent = [modelProcessor process:root];
input = [[ContentReader alloc] initWithContentManager:self Content:modelContent];
if (!importer) {
importer = [[[XImporter alloc] init] autorelease];
}
if (!processor) {
processor = [[[ModelProcessor alloc] init] autorelease];
}
} else if ([extension isEqualToString:@"wav"]) {
// Wave audio content
WavImporter *wavImporter = [[[WavImporter alloc] init] autorelease];
AudioContent *audioContent = [wavImporter importFile:absolutePath];
SoundEffectProcessor *soundEffectProcessor = [[[SoundEffectProcessor alloc] init] autorelease];
SoundEffectContent *soundEffectContent = [soundEffectProcessor process:audioContent];
input = [[ContentReader alloc] initWithContentManager:self Content:soundEffectContent];
if (!importer) {
importer = [[[WavImporter alloc] init] autorelease];
}
if (!processor) {
processor = [[[SoundEffectProcessor alloc] init] autorelease];
}
} else if ([extension isEqualToString:@"mp3"]) {
// Wave audio content
WavImporter *wavImporter = [[[WavImporter alloc] init] autorelease];
AudioContent *audioContent = [wavImporter importFile:absolutePath];
SongProcessor *songProcessor = [[[SongProcessor alloc] init] autorelease];
SongContent *songContent = [songProcessor process:audioContent];
input = [[ContentReader alloc] initWithContentManager:self Content:songContent];
} else {
// Mp3 audio content
if (!importer) {
importer = [[[WavImporter alloc] init] autorelease];
}
if (!processor) {
processor = [[[SongProcessor alloc] init] autorelease];
}
}
// Make sure we have a valid importer.
if (!importer) {
[NSException raise:@"InvalidArgumentException" format:@"Files with extension %@ are not supported", extension];
}
// Import content.
id content = [importer importFile:absolutePath];
// Process content if we have a processor.
if (processor) {
content = [processor process:content];
}
// Create a reader for converting into realtime data.
input = [[ContentReader alloc] initWithContentManager:self Content:content];
[pool release];
// And another pool for the conversion process.
// Create another pool for the conversion process.
pool = [[NSAutoreleasePool alloc] init];
ContentTypeReader *reader = [readerManager getTypeReaderFor:[input.content class]];
@ -153,6 +185,7 @@
- (void) dealloc
{
[loadedAssets release];
[loadedFiles release];
[readerManager release];
[super dealloc];
}

View File

@ -42,7 +42,7 @@
ExternalReference *externalReference = (ExternalReference*)source;
// We should load the item with content manager.
result = [contentManager load:externalReference.name fromFile:externalReference.filename];
result = [[contentManager load:externalReference.name fromFile:externalReference.filename] autorelease]; // TODO: Be sure to remove this release when content manager is coded correctly.
} else {
// Get the correct reader for item.
ContentTypeReader *typeReader = [contentManager.readerManager getTypeReaderFor:[source class]];

View File

@ -21,6 +21,7 @@
ModelBoneReader *modelBoneReader;
VertexDeclarationReader *vertexDeclarationReader;
SoundEffectReader *soundEffectReader;
SpriteFontReader *spriteFontReader;
}
- (ContentTypeReader*) getTypeReaderFor:(Class)targetType;

View File

@ -28,6 +28,7 @@
modelBoneReader = [[ModelBoneReader alloc] init];
vertexDeclarationReader = [[VertexDeclarationReader alloc] init];
soundEffectReader = [[SoundEffectReader alloc] init];
spriteFontReader = [[SpriteFontReader alloc] init];
}
return self;
}
@ -54,6 +55,8 @@
return vertexDeclarationReader;
} else if (targetType == [SoundEffectContent class]) {
return soundEffectReader;
} else if (targetType == [SpriteFontContent class]) {
return spriteFontReader;
} else {
return nil;
}
@ -63,6 +66,15 @@
{
[texture2DReader release];
[modelReader release];
[modelMeshReader release];
[modelMeshPartReader release];
[basicEffectReader release];
[indexBufferReader release];
[vertexBufferReader release];
[modelBoneReader release];
[vertexDeclarationReader release];
[soundEffectReader release];
[spriteFontReader release];
[super dealloc];
}

View File

@ -112,6 +112,7 @@
- (void) dealloc
{
//if (extRef) ExtAudioFileDispose(extRef);
[format release];
[fileUrl release];
[super dealloc];
}

View File

@ -4,4 +4,5 @@
@class ModelReader, ModelMeshReader, ModelMeshPartReader;
@class BasicEffectReader, IndexBufferReader, VertexBufferReader;
@class ModelBoneReader, VertexDeclarationReader;
@class SoundEffectReader;
@class SoundEffectReader;
@class SpriteFontReader;

View File

@ -16,4 +16,6 @@
#import "ModelBoneReader.h"
#import "VertexDeclarationReader.h"
#import "SoundEffectReader.h"
#import "SoundEffectReader.h"
#import "SpriteFontReader.h"

View File

@ -0,0 +1,17 @@
//
// SpriteFontReader.h
// XNI
//
// Created by Matej Jan on 20.12.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ContentTypeReader.h"
@interface SpriteFontReader : ContentTypeReader {
}
@end

View File

@ -0,0 +1,32 @@
//
// SpriteFontReader.m
// XNI
//
// Created by Matej Jan on 20.12.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import "SpriteFontReader.h"
#import "Retronator.Xni.Framework.Graphics.h"
#import "Retronator.Xni.Framework.Content.h"
#import "Retronator.Xni.Framework.Content.Pipeline.Processors.h"
#import "SpriteFontContent+Internal.h"
#import "SpriteFont+Internal.h"
@implementation SpriteFontReader
- (id) readFromInput:(ContentReader *)input into:(id)existingInstance {
SpriteFontContent *content = input.content;
Texture2D *texture = [input readObjectFrom:content.texture];
SpriteFont *result = [[(SpriteFont*)[SpriteFont alloc] initWithTexture:texture
characterMap:content.characterMap
lineSpacing:content.lineSpacing] autorelease];
return result;
}
@end

View File

@ -45,9 +45,10 @@
GameComponentCollection *components;
NSMutableArray *enabledComponents;
NSMutableArray *visibleComponents;
NSMutableSet *enabledChangedComponents;
NSMutableArray *componentsList;
NSMutableSet *initializedComponents;
// Services
GameServiceContainer *services;

View File

@ -51,7 +51,12 @@ static NSArray *drawOrderSort;
enabledComponents = [[NSMutableArray alloc] init];
visibleComponents = [[NSMutableArray alloc] init];
enabledChangedComponents = [[NSMutableSet alloc] init];
// A temporary array for operations on components.
// First it is used for constructing a list of components, that need to be initialized.
// In run it is used to make a copy of enabled/visible components for enumerating over them.
componentsList = [[NSMutableArray alloc] init];
initializedComponents = [[NSMutableSet alloc] init];
[components.componentAdded subscribeDelegate:
[Delegate delegateWithTarget:self Method:@selector(componentAddedTo:eventArgs:)]];
@ -170,23 +175,13 @@ static NSArray *drawOrderSort;
// Update input.
[[TouchPanel getInstance] update];
// Update the game.
[self updateWithGameTime:gameTime];
// Update enabled components.
for (id<IUpdatable> updatable in enabledChangedComponents) {
if (updatable.enabled) {
[self addEnabledComponent: updatable];
} else {
[enabledComponents removeObject:updatable];
}
}
[enabledChangedComponents removeAllObjects];
// Update audio.
[SoundEffect update];
// Draw to display.
if ([self beginDraw]) {
[self drawWithGameTime:gameTime];
@ -235,9 +230,12 @@ static NSArray *drawOrderSort;
// Here we only handle the components.
- (void) initialize {
for (id<IGameComponent> component in components) {
while ([componentsList count] > 0) {
id<IGameComponent> component = [componentsList objectAtIndex:0];
[component initialize];
}
[initializedComponents addObject:component];
[componentsList removeObjectAtIndex:0];
}
initializeDone = YES;
[self loadContent];
@ -248,9 +246,11 @@ static NSArray *drawOrderSort;
- (void) beginRun {}
- (void) updateWithGameTime:(GameTime*)theGameTime {
for (id<IUpdatable> updatable in enabledComponents) {
[componentsList addObjectsFromArray:enabledComponents];
for (id<IUpdatable> updatable in componentsList) {
[updatable updateWithGameTime:theGameTime];
}
[componentsList removeAllObjects];
}
- (BOOL) beginDraw {
@ -258,9 +258,11 @@ static NSArray *drawOrderSort;
}
- (void) drawWithGameTime:(GameTime*)theGameTime {
for (id<IDrawable> drawable in visibleComponents) {
[componentsList addObjectsFromArray:visibleComponents];
for (id<IDrawable> drawable in componentsList) {
[drawable drawWithGameTime:theGameTime];
}
[componentsList removeAllObjects];
}
- (void) endDraw {
@ -288,8 +290,13 @@ static NSArray *drawOrderSort;
- (void) componentAddedTo:(GameComponentCollection*)sender eventArgs:(GameComponentCollectionEventArgs*)e {
// Initialize component if it's being added after main initialize has been called.
if (initializeDone) {
[e.gameComponent initialize];
}
if (![initializedComponents containsObject:e.gameComponent]) {
[e.gameComponent initialize];
[initializedComponents addObject:e.gameComponent];
}
} else {
[componentsList addObject:e.gameComponent];
}
// Process updatable component.
if ([e.gameComponent conformsToProtocol:@protocol(IUpdatable)]) {
@ -303,7 +310,7 @@ static NSArray *drawOrderSort;
[Delegate delegateWithTarget:self Method:@selector(componentUpdateOrderChanged:eventArgs:)]];
}
// Process updatable component.
// Process drawable component.
if ([e.gameComponent conformsToProtocol:@protocol(IDrawable)]) {
id<IDrawable> drawable = (id<IDrawable>)e.gameComponent;
if (drawable.visible) {
@ -317,6 +324,10 @@ static NSArray *drawOrderSort;
}
- (void) componentRemovedFrom:(GameComponentCollection*)sender eventArgs:(GameComponentCollectionEventArgs*)e {
if (!initializeDone) {
[componentsList removeObject:e.gameComponent];
}
// Process updatable component.
if ([e.gameComponent conformsToProtocol:@protocol(IUpdatable)]) {
id<IUpdatable> updatable = (id<IUpdatable>)e.gameComponent;
@ -329,7 +340,7 @@ static NSArray *drawOrderSort;
[Delegate delegateWithTarget:self Method:@selector(componentUpdateOrderChanged:eventArgs:)]];
}
// Process updatable component.
// Process drawable component.
if ([e.gameComponent conformsToProtocol:@protocol(IDrawable)]) {
id<IDrawable> drawable = (id<IDrawable>)e.gameComponent;
if (drawable.visible) {
@ -343,7 +354,11 @@ static NSArray *drawOrderSort;
}
- (void) componentEnabledChanged:(id<IUpdatable>)sender eventArgs:(EventArgs*)e {
[enabledChangedComponents addObject:sender];
if (sender.enabled) {
[self addEnabledComponent: sender];
} else {
[enabledComponents removeObject:sender];
}
}
- (void) componentUpdateOrderChanged:(id<IUpdatable>)sender eventArgs:(EventArgs*)e {
@ -355,7 +370,7 @@ static NSArray *drawOrderSort;
[self addVisibleComponent:sender];
} else {
[visibleComponents removeObject:sender];
}
}
}
- (void) componentDrawOrderChanged:(id<IDrawable>)sender eventArgs:(EventArgs*)e {
@ -376,7 +391,8 @@ static NSArray *drawOrderSort;
[self unloadContent];
[gameTime release];
[enabledChangedComponents release];
[initializedComponents release];
[componentsList release];
[enabledComponents release];
[visibleComponents release];
[components release];

View File

@ -19,6 +19,9 @@
@property (nonatomic, readonly) Event *componentAdded;
@property (nonatomic, readonly) Event *componentRemoved;
@property (nonatomic, readonly) int count;
- (id<IGameComponent>)itemAt:(int)index;
- (void) addComponent:(id<IGameComponent>)component;
- (void) removeComponent:(id<IGameComponent>)component;

View File

@ -24,6 +24,14 @@
@synthesize componentAdded;
@synthesize componentRemoved;
- (int) count {
return [components count];
}
- (id<IGameComponent>)itemAt:(int)index {
return [components objectAtIndex:index];
}
- (void) addComponent:(id<IGameComponent>)component {
[components addObject:component];
[componentAdded raiseWithSender:self

View File

@ -27,5 +27,14 @@
@synthesize enabled;
@synthesize specularColor;
- (void) dealloc
{
[diffuseColor release];
[specularColor release];
[direction release];
[super dealloc];
}
@end

View File

@ -71,6 +71,7 @@
// Create sampler states and texture collections and handle changes.
samplerStates = [[SamplerStateCollection alloc] init];
textures = [[TextureCollection alloc] init];
[samplerStates.samplerStateChanged subscribeDelegate:[Delegate delegateWithTarget:self
Method:@selector(applySamplerState:eventArgs:)]];
[textures.textureChanged subscribeDelegate:[Delegate delegateWithTarget:self

View File

@ -80,6 +80,7 @@
- (void) dealloc
{
[absoluteBones release];
[bones release];
[meshes release];
[root release];

View File

@ -13,6 +13,7 @@
#define ReadOnlyCollection ModelBoneCollection
#define T ModelBone*
#define Initialization bones = [[NSMutableDictionary alloc] init]; for (ModelBone* bone in collection) {if (bone.name) [bones setObject:bone forKey:bone.name];}
#define Disposing [bones release];
#include "ReadOnlyCollection.m.h"

View File

@ -13,6 +13,7 @@
#define ReadOnlyCollection ModelMeshCollection
#define T ModelMesh*
#define Initialization meshes = [[NSMutableDictionary alloc] init]; for (ModelMesh* mesh in collection) {[meshes setObject:mesh forKey:mesh.name];}
#define Disposing [meshes release];
#include "ReadOnlyCollection.m.h"

View File

@ -17,3 +17,5 @@
@class GraphicsDevice, ReachGraphicsDevice, HiDefGraphicsDevice;
@class SpriteBatch;
@class SpriteFont;

View File

@ -53,4 +53,6 @@
#import "ReachGraphicsDevice.h"
#import "HiDefGraphicsDevice.h"
#import "SpriteBatch.h"
#import "SpriteBatch.h"
#import "SpriteFont.h"

View File

@ -65,6 +65,12 @@
- (void) draw:(Texture2D*)texture to:(Vector2*)position fromRectangle:(Rectangle*)sourceRectangle tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scale:(Vector2*)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color;
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scaleUniform:(float)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scale:(Vector2*)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth;
- (void) end;
@end

View File

@ -10,6 +10,8 @@
#import "Retronator.Xni.Framework.Graphics.h"
#import "SpriteBatch.h"
#import "SpriteFont+Internal.h"
typedef struct {
float x;
float y;
@ -45,8 +47,6 @@ typedef struct {
@end
static Matrix *identity;
static NSArray *textureSort;
static NSArray *frontToBackSort;
static NSArray *backToFrontSort;
@ -144,7 +144,6 @@ static VertexPositionColorTextureStruct vertices[4];
}
+ (void) initialize {
identity = [[Matrix identity] retain];
NSSortDescriptor *textureSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"textureId" ascending:YES] autorelease];
NSSortDescriptor *depthAscendingSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"layerDepth" ascending:YES] autorelease];
NSSortDescriptor *depthDescendingSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"layerDepth" ascending:NO] autorelease];
@ -292,6 +291,41 @@ static VertexPositionColorTextureStruct vertices[4];
[self draw:sprite];
}
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color {
[self drawStringWithSpriteFont:spriteFont text:text to:position tintWithColor:color rotation:0 origin:[Vector2 zero] scale:[Vector2 one] effects:SpriteEffectsNone layerDepth:0];
}
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scaleUniform:(float)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth {
[self drawStringWithSpriteFont:spriteFont text:text to:position tintWithColor:color rotation:rotation origin:origin scale:[Vector2 vectorWithX:scale y:scale] effects:effects layerDepth:layerDepth];
}
- (void) drawStringWithSpriteFont:(SpriteFont*)spriteFont text:(NSString*)text to:(Vector2*)position tintWithColor:(Color*)color
rotation:(float)rotation origin:(Vector2*)origin scale:(Vector2*)scale effects:(SpriteEffects)effects layerDepth:(float)layerDepth {
Vector2 *currentOrigin = [Vector2 vectorWithX:origin.x y:origin.y-spriteFont.lineSpacing];
Vector2 *characterOrigin = [Vector2 zero];
for (int i = 0; i < [text length]; i++) {
unichar character = [text characterAtIndex:i];
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) {
// This is a control character for a new line.
currentOrigin.x = origin.x;
currentOrigin.y -= spriteFont.lineSpacing;
} else {
// Draw this character
Rectangle *sourceRectangle = [spriteFont sourceRectangleForCharacter:character];
characterOrigin.x = currentOrigin.x;
characterOrigin.y = currentOrigin.y + sourceRectangle.height;
[self draw:spriteFont.texture to:position fromRectangle:sourceRectangle tintWithColor:color
rotation:rotation origin:characterOrigin scale:scale effects:effects layerDepth:layerDepth];
currentOrigin.x -= sourceRectangle.width + spriteFont.spacing;
}
}
}
- (void) draw:(XniSprite *)sprite {
[sprites addObject:sprite];
@ -430,6 +464,8 @@ static VertexPositionColorTextureStruct vertices[4];
- (void) dealloc
{
[self.graphicsDevice.deviceReset unsubscribeDelegate:[Delegate delegateWithTarget:self Method:@selector(setProjection)]];
[basicEffect release];
[sprites release];
[vertexArray release];
[super dealloc];

View File

@ -0,0 +1,21 @@
//
// SpriteFont+Internal.h
// XNI
//
// Created by Matej Jan on 20.12.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SpriteFont.h"
@interface SpriteFont (Internal)
- (id) initWithTexture:(Texture2D*)theTexture characterMap:(NSDictionary*)theCharacterMap lineSpacing:(int)theLineSpacing;
@property (nonatomic, readonly) Texture2D *texture;
- (Rectangle*) sourceRectangleForCharacter:(unichar)character;
@end

View File

@ -0,0 +1,32 @@
//
// SpriteFont.h
// XNI
//
// Created by Matej Jan on 20.12.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Retronator.Xni.Framework.classes.h"
#import "Retronator.Xni.Framework.Graphics.classes.h"
@interface SpriteFont : NSObject {
NSSet *characters;
NSNumber *defaultCharacter;
int lineSpacing;
float spacing;
@private
Texture2D *texture;
NSDictionary *characterMap;
}
@property (nonatomic, readonly) NSSet *characters;
@property (nonatomic, retain) NSNumber *defaultCharacter;
@property (nonatomic) int lineSpacing;
@property (nonatomic) float spacing;
- (Vector2*) measureString:(NSString*)text;
@end

View File

@ -0,0 +1,88 @@
//
// SpriteFont.m
// XNI
//
// Created by Matej Jan on 20.12.10.
// Copyright 2010 Retronator. All rights reserved.
//
#import "SpriteFont.h"
#import "SpriteFont+Internal.h"
#import "Retronator.Xni.Framework.h"
@implementation SpriteFont
- (id) initWithTexture:(Texture2D*)theTexture characterMap:(NSDictionary *)theCharacterMap lineSpacing:(int)theLineSpacing
{
self = [super init];
if (self != nil) {
texture = [theTexture retain];
characterMap = [theCharacterMap retain];
characters = [[NSSet alloc] initWithArray:[characterMap allKeys]];
lineSpacing = theLineSpacing;
}
return self;
}
@synthesize characters, defaultCharacter, lineSpacing, spacing;
- (Texture2D *) texture {
return texture;
}
- (Vector2 *) measureString:(NSString *)text {
Vector2 *size = [Vector2 zero];
Vector2 *currentPosition = [Vector2 vectorWithX:0 y:lineSpacing];
for (int i = 0; i < [text length]; i++) {
unichar character = [text characterAtIndex:i];
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) {
// This is a control character for a new line.
currentPosition.x = 0;
currentPosition.y += lineSpacing;
} else {
// Draw this character
Rectangle *sourceRectangle = [self sourceRectangleForCharacter:character];
currentPosition.x += sourceRectangle.width + spacing;
if (currentPosition.x > size.x) {
size.x = currentPosition.x;
}
if (currentPosition.y > size.y) {
size.y = currentPosition.y;
}
}
}
return size;
}
- (Rectangle *) sourceRectangleForCharacter:(unichar)character {
Rectangle *result = [characterMap objectForKey:[NSNumber numberWithChar:character]];
if (!result && defaultCharacter) {
result = [characterMap objectForKey:defaultCharacter];
}
if (!result) {
[NSException raise:@"ArgumentException" format:@"The character %C with charcode %i is not supported by this sprite font.", character, (int)character];
}
return result;
}
- (void) dealloc
{
[characters release];
[defaultCharacter release];
[texture release];
[characterMap release];
[super dealloc];
}
@end

View File

@ -389,12 +389,12 @@
// CONSTANTS
+ (id) zero {
MatrixStruct MatrixStruct = MatrixMake(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return [Matrix matrixWithStruct:&MatrixStruct];
MatrixStruct matrixStruct = MatrixMake(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return [Matrix matrixWithStruct:&matrixStruct];
}
+ (id) identity {
MatrixStruct MatrixStruct = MatrixMake(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
return [Matrix matrixWithStruct:&MatrixStruct];
MatrixStruct matrixStruct = MatrixMake(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
return [Matrix matrixWithStruct:&matrixStruct];
}
@end

View File

@ -32,6 +32,9 @@
- (Rectangle*) set:(Rectangle*)value;
- (BOOL) containsX:(int)x y:(int)y;
- (BOOL) containsPoint:(XniPoint*)point;
- (BOOL) equals:(Rectangle*)rectangle;
+ (Rectangle*) empty;

View File

@ -8,6 +8,7 @@
#import "Rectangle.h"
#import "Retronator.Xni.Framework.h"
@implementation Rectangle
@ -71,6 +72,15 @@
return self;
}
- (BOOL) containsX:(int)x y:(int)y {
return x >= data.x && x <= data.x + data.width && y >= data.y && y <= data.y + data.height;
}
- (BOOL) containsPoint:(XniPoint*)point {
return [self containsX:point.x y:point.y];
}
- (id) copyWithZone:(NSZone *)zone {
return [[Rectangle allocWithZone:zone] initWithRectangleStruct:&data];
}

View File

@ -37,6 +37,9 @@
- (void) dealloc
{
#ifdef Disposing
Disposing
#endif
[collection release];
[super dealloc];
}

View File

@ -312,6 +312,16 @@
B5EC5A4F1252C2DF001E7DFC /* GestureSample.h in Headers */ = {isa = PBXBuildFile; fileRef = B5EC5A4D1252C2DF001E7DFC /* GestureSample.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5EC5A501252C2DF001E7DFC /* GestureSample.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EC5A4E1252C2DF001E7DFC /* GestureSample.m */; };
B5EC5A931252C710001E7DFC /* Retronator.Xni.Framework.Input.h in Headers */ = {isa = PBXBuildFile; fileRef = B5EC5A921252C710001E7DFC /* Retronator.Xni.Framework.Input.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5ED4C9D12BF82FE00A58E29 /* SpriteFont.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4C9B12BF82FE00A58E29 /* SpriteFont.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5ED4C9E12BF82FE00A58E29 /* SpriteFont.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ED4C9C12BF82FE00A58E29 /* SpriteFont.m */; };
B5ED4CC012BF895B00A58E29 /* FontTextureProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4CBE12BF895B00A58E29 /* FontTextureProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5ED4CC112BF895B00A58E29 /* FontTextureProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ED4CBF12BF895B00A58E29 /* FontTextureProcessor.m */; };
B5ED4CC912BF898900A58E29 /* SpriteFontContent.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4CC712BF898900A58E29 /* SpriteFontContent.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5ED4CCA12BF898900A58E29 /* SpriteFontContent.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ED4CC812BF898900A58E29 /* SpriteFontContent.m */; };
B5ED4CD012BF8A1600A58E29 /* SpriteFontContent+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4CCF12BF8A1600A58E29 /* SpriteFontContent+Internal.h */; };
B5ED4CEF12BF8D9100A58E29 /* SpriteFontReader.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4CED12BF8D9100A58E29 /* SpriteFontReader.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5ED4CF012BF8D9100A58E29 /* SpriteFontReader.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ED4CEE12BF8D9100A58E29 /* SpriteFontReader.m */; };
B5ED4D2512BF92A100A58E29 /* SpriteFont+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = B5ED4D2412BF92A100A58E29 /* SpriteFont+Internal.h */; };
B5EFD744129B2A7800FDC150 /* ModelMeshContentCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = B5EFD742129B2A7800FDC150 /* ModelMeshContentCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
B5EFD745129B2A7800FDC150 /* ModelMeshContentCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EFD743129B2A7800FDC150 /* ModelMeshContentCollection.m */; };
B5EFD748129B2A8900FDC150 /* ModelMeshPartContentCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = B5EFD746129B2A8900FDC150 /* ModelMeshPartContentCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -687,6 +697,16 @@
B5EC5A4D1252C2DF001E7DFC /* GestureSample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GestureSample.h; sourceTree = "<group>"; };
B5EC5A4E1252C2DF001E7DFC /* GestureSample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GestureSample.m; sourceTree = "<group>"; };
B5EC5A921252C710001E7DFC /* Retronator.Xni.Framework.Input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Retronator.Xni.Framework.Input.h; sourceTree = "<group>"; };
B5ED4C9B12BF82FE00A58E29 /* SpriteFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteFont.h; sourceTree = "<group>"; };
B5ED4C9C12BF82FE00A58E29 /* SpriteFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpriteFont.m; sourceTree = "<group>"; };
B5ED4CBE12BF895B00A58E29 /* FontTextureProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontTextureProcessor.h; sourceTree = "<group>"; };
B5ED4CBF12BF895B00A58E29 /* FontTextureProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FontTextureProcessor.m; sourceTree = "<group>"; };
B5ED4CC712BF898900A58E29 /* SpriteFontContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteFontContent.h; sourceTree = "<group>"; };
B5ED4CC812BF898900A58E29 /* SpriteFontContent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpriteFontContent.m; sourceTree = "<group>"; };
B5ED4CCF12BF8A1600A58E29 /* SpriteFontContent+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SpriteFontContent+Internal.h"; sourceTree = "<group>"; };
B5ED4CED12BF8D9100A58E29 /* SpriteFontReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpriteFontReader.h; sourceTree = "<group>"; };
B5ED4CEE12BF8D9100A58E29 /* SpriteFontReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpriteFontReader.m; sourceTree = "<group>"; };
B5ED4D2412BF92A100A58E29 /* SpriteFont+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SpriteFont+Internal.h"; sourceTree = "<group>"; };
B5EFD742129B2A7800FDC150 /* ModelMeshContentCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelMeshContentCollection.h; sourceTree = "<group>"; };
B5EFD743129B2A7800FDC150 /* ModelMeshContentCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModelMeshContentCollection.m; sourceTree = "<group>"; };
B5EFD746129B2A8900FDC150 /* ModelMeshPartContentCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModelMeshPartContentCollection.h; sourceTree = "<group>"; };
@ -992,6 +1012,8 @@
B554FA0C12A4362B00F20A0D /* VertexDeclarationReader.m */,
B50FE48612B885BC003D4F1A /* SoundEffectReader.h */,
B50FE48712B885BC003D4F1A /* SoundEffectReader.m */,
B5ED4CED12BF8D9100A58E29 /* SpriteFontReader.h */,
B5ED4CEE12BF8D9100A58E29 /* SpriteFontReader.m */,
);
path = Content;
sourceTree = "<group>";
@ -1102,6 +1124,9 @@
B5DDE8C611FF2A23000DB38B /* HiDefGraphicsDevice.m */,
B5E78B481242925600DDD99A /* SpriteBatch.h */,
B5E78B491242925600DDD99A /* SpriteBatch.m */,
B5ED4C9B12BF82FE00A58E29 /* SpriteFont.h */,
B5ED4D2412BF92A100A58E29 /* SpriteFont+Internal.h */,
B5ED4C9C12BF82FE00A58E29 /* SpriteFont.m */,
);
path = Graphics;
sourceTree = "<group>";
@ -1219,6 +1244,8 @@
B5E7ECBC129AE6560015B663 /* Retronator.Xni.Framework.Content.Pipeline.Processors.h */,
B5E7ECAC129AE5B40015B663 /* TextureProcessor.h */,
B5E7ECAD129AE5B40015B663 /* TextureProcessor.m */,
B5ED4CBE12BF895B00A58E29 /* FontTextureProcessor.h */,
B5ED4CBF12BF895B00A58E29 /* FontTextureProcessor.m */,
B5E7ECB0129AE5C50015B663 /* ModelProcessor.h */,
B5E7ECB1129AE5C50015B663 /* ModelProcessor.m */,
B5E7ECB4129AE5D40015B663 /* MaterialProcessor.h */,
@ -1254,6 +1281,9 @@
B51ADC8212B83F62004E2DB0 /* SoundEffectContent.m */,
B51ADC7912B83EE9004E2DB0 /* SongContent.h */,
B51ADC7A12B83EE9004E2DB0 /* SongContent.m */,
B5ED4CC712BF898900A58E29 /* SpriteFontContent.h */,
B5ED4CCF12BF8A1600A58E29 /* SpriteFontContent+Internal.h */,
B5ED4CC812BF898900A58E29 /* SpriteFontContent.m */,
);
path = Processors;
sourceTree = "<group>";
@ -1516,6 +1546,12 @@
B50FE48812B885BC003D4F1A /* SoundEffectReader.h in Headers */,
B50FE50712B88F64003D4F1A /* SoundEffectInstance+Internal.h in Headers */,
B50FE76212B8B11C003D4F1A /* SoundEffect+Internal.h in Headers */,
B5ED4C9D12BF82FE00A58E29 /* SpriteFont.h in Headers */,
B5ED4CC012BF895B00A58E29 /* FontTextureProcessor.h in Headers */,
B5ED4CC912BF898900A58E29 /* SpriteFontContent.h in Headers */,
B5ED4CD012BF8A1600A58E29 /* SpriteFontContent+Internal.h in Headers */,
B5ED4CEF12BF8D9100A58E29 /* SpriteFontReader.h in Headers */,
B5ED4D2512BF92A100A58E29 /* SpriteFont+Internal.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1758,6 +1794,10 @@
B51ADCD012B84FD8004E2DB0 /* WavImporter.m in Sources */,
B51ADCD412B84FE1004E2DB0 /* Mp3Importer.m in Sources */,
B50FE48912B885BC003D4F1A /* SoundEffectReader.m in Sources */,
B5ED4C9E12BF82FE00A58E29 /* SpriteFont.m in Sources */,
B5ED4CC112BF895B00A58E29 /* FontTextureProcessor.m in Sources */,
B5ED4CCA12BF898900A58E29 /* SpriteFontContent.m in Sources */,
B5ED4CF012BF8D9100A58E29 /* SpriteFontReader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};