Files
DarkRP2D/external/Box2D-2.3.1/Contributions/Platforms/iPhone/Classes/Box2DView.mm
Julian Nießner d175d433a8 Added Box2D
2018-05-06 12:43:20 +02:00

300 lines
7.8 KiB
Plaintext

//
// Box2DView.mm
// Box2D OpenGL View
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import "Box2DView.h"
#define USE_DEPTH_BUFFER 0
#define kAccelerometerFrequency 30
#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10
Settings settings;
// A class extension to declare private methods
@interface Box2DView ()
@property (nonatomic, retain) EAGLContext *context;
@property (nonatomic, assign) NSTimer *animationTimer;
- (BOOL) createFramebuffer;
- (void) destroyFramebuffer;
@end
@implementation Box2DView
@synthesize context;
@synthesize animationTimer;
@synthesize animationInterval;
@synthesize delegate=_delegate;
// You must implement this method
+ (Class)layerClass {
return [CAEAGLLayer class];
}
//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
animationInterval = 1.0 / 60.0;
sceneScale=10.0f;
positionOffset=CGPointMake(0, 0);
lastWorldTouch=CGPointMake(0, 0);
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
//[self setMultipleTouchEnabled:YES];
}
return self;
}
-(void) selectTestEntry:(int) testIndex
{
// Destroy existing scene
delete test;
entry = g_testEntries + testIndex;
test = entry->createFcn();
doubleClickValidCountdown=0;
sceneScale=10.0f;
positionOffset=CGPointMake(0, 0);
lastWorldTouch=CGPointMake(0, 0);
}
- (void)drawView {
if (doubleClickValidCountdown>0) doubleClickValidCountdown--;
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-sceneScale, sceneScale, -sceneScale*1.5f, sceneScale*1.5f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(positionOffset.x, positionOffset.y,0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
test->Step(&settings);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (void)layoutSubviews {
[EAGLContext setCurrentContext:context];
[self destroyFramebuffer];
[self createFramebuffer];
[self drawView];
}
- (BOOL)createFramebuffer {
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (USE_DEPTH_BUFFER) {
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
return YES;
}
- (void)destroyFramebuffer {
glDeleteFramebuffersOES(1, &viewFramebuffer);
viewFramebuffer = 0;
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
viewRenderbuffer = 0;
if(depthRenderbuffer) {
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
depthRenderbuffer = 0;
}
}
- (void)startAnimation {
self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
}
- (void)stopAnimation {
self.animationTimer = nil;
}
- (void)setAnimationTimer:(NSTimer *)newTimer {
[animationTimer invalidate];
animationTimer = newTimer;
}
- (void)setAnimationInterval:(NSTimeInterval)interval {
animationInterval = interval;
if (animationTimer) {
[self stopAnimation];
[self startAnimation];
}
}
- (void)dealloc {
[self stopAnimation];
if ([EAGLContext currentContext] == context) {
[EAGLContext setCurrentContext:nil];
}
[context release];
[super dealloc];
}
-(CGPoint) screenSpaceToWorldSpace:(CGPoint) screenLocation
{
screenLocation.x-=160;
screenLocation.y-=240;
screenLocation.x/=160;
screenLocation.y/=160;
screenLocation.x*=sceneScale;
screenLocation.y*=-sceneScale;
screenLocation.x-=positionOffset.x;
screenLocation.y-=positionOffset.y;
return screenLocation;
}
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
if (doubleClickValidCountdown>0)
{
[_delegate leaveTest];
return;
}
doubleClickValidCountdown=FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK;
panning=false;
for (UITouch *touch in touches)
{
CGPoint touchLocation=[touch locationInView:self];
CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
//printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
lastScreenTouch=touchLocation;
lastWorldTouch=worldPosition;
b2Vec2 p = b2Vec2(lastWorldTouch.x,lastWorldTouch.y);
test->MouseDown(p);
//test->ShiftMouseDown(p);
if (!test->m_mouseJoint) panning=true;
}
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
for (UITouch *touch in touches)
{
CGPoint touchLocation=[touch locationInView:self];
CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
//printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
CGPoint screenDistanceMoved=CGPointMake(touchLocation.x-lastScreenTouch.x,touchLocation.y-lastScreenTouch.y);
if (panning)
{
screenDistanceMoved.x/=160;
screenDistanceMoved.y/=160;
screenDistanceMoved.x*=sceneScale;
screenDistanceMoved.y*=-sceneScale;
positionOffset.x+=screenDistanceMoved.x;
positionOffset.y+=screenDistanceMoved.y;
}
lastScreenTouch=touchLocation;
lastWorldTouch=worldPosition;
test->MouseMove(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
}
}
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
test->MouseUp(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
}
- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
// Only run for valid values
if (acceleration.y!=0 && acceleration.x!=0)
{
if (test) test->SetGravity(acceleration.x,acceleration.y);
}
}
@end