hostile-takeover/game/iphone/wiview.mm

352 lines
9.3 KiB
Plaintext

//
// wiview.mm
// wi
//
// Created by Scott Ludwig on 4/21/08.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "game/iphone/wiview.h"
#import "game/iphone/spritemgradapter.h"
#import "game/iphone/iphoneanimsprite.h"
#import "game/iphone/selectionsprite.h"
#import "game/iphone/webviewcontroller.h"
#include "game/iphone/input.h"
#include "mpshared/misc.h"
@implementation WiView
- (id)initWithFrame:(struct CGRect)rect
{
self = [super initWithFrame: rect];
if (self == nil) {
return nil;
}
#if 0 // iOS <= 7
rect_ = CGRectMake(0, 0, rect.size.height, rect.size.width);
#else
// As of iOS 8 screen coordinates are interface oriented not device oriented.
rect_ = CGRectMake(0, 0, rect.size.width, rect.size.height);
#endif
[self setMultipleTouchEnabled: YES];
atouch_[0] = NULL;
atouch_[1] = NULL;
havePalette_ = false;
pb_ = NULL;
memset(&rcClip1_, 0, sizeof(rcClip1_));
memset(&rcClip2_, 0, sizeof(rcClip2_));
pcrit_ = new base::CriticalSection();
psprm_ = new wi::SpriteManagerAdapter(self);
cpspr_ = 0;
fSpriteDirty_ = false;
game_thread_ = NULL;
return self;
}
- (void)dealloc
{
if (pb_ != NULL) {
free(pb_);
}
delete psprm_;
delete pcrit_;
[super dealloc];
}
- (void)setGameThread:(base::Thread *)thread
{
game_thread_ = thread;
}
- (void)checkTracking:(UIEvent *)event
{
// This is just in case - if we lose an up, this detects it and resets
// things. So far touchesCancelled appears to be working as advertised.
int cTouchesTracking = 0;
for (int i = 0; i < 2; i++) {
if (atouch_[i] != NULL) {
cTouchesTracking++;
}
}
int cTouchesFound = 0;
NSSet *allTouches = [event allTouches];
for (UITouch *touch in allTouches) {
for (int i = 0; i < 2; i++) {
if (touch == atouch_[i]) {
cTouchesFound++;
}
}
}
// If it's whacked, post an up and set the slot to NULL.
if (cTouchesFound != cTouchesTracking) {
for (int i = 0; i < 2; i++) {
if (atouch_[i] != NULL) {
atouch_[i] = NULL;
base::Message msg;
msg.id = (i == 0) ? kidmMouseUp : kidmMouseUp2;
msg.x = aptLast_[i].x;
msg.y = aptLast_[i].y;
msg.ff = 0;
msg.ms = wi::HostGetMillisecondCount();
if (game_thread_ != NULL) {
game_thread_->Post(&msg);
}
}
}
}
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// Sometimes we won't get an up. Handle this case.
[self checkTracking:event];
// Keep track of touches. According to the documentation, the touch *
// pointer value is constant throughout the life of the touch, so it
// can be used as sort of an id.
// Only process touches for this view. WebView and ChatView are
// handled as children, and events in their toolbar area somehow
// get sent here. However this parent only wants touches for its
// own view, not for the whole window.
for (UITouch *touch in touches) {
if (touch.view != self) {
continue;
}
for (int i = 0; i < 2; i++) {
if (atouch_[i] == NULL) {
atouch_[i] = touch;
CGPoint point = [touch locationInView: nil];
base::Message msg;
msg.id = (i == 0) ? kidmMouseDown : kidmMouseDown2;
msg.x = (int)point.x;
msg.y = (int)point.y;
msg.ff = 0;
msg.ms = wi::HostGetMillisecondCount();
if (game_thread_ != NULL) {
game_thread_->Post(&msg);
}
aptLast_[i].x = (int)point.x;
aptLast_[i].y = (int)point.y;
break;
}
}
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
for (UITouch *touch in touches) {
if (touch.view != self) {
continue;
}
for (int i = 0; i < 2; i++) {
if (atouch_[i] == touch) {
CGPoint point = [touch locationInView: nil];
base::Message msg;
msg.id = (i == 0) ? kidmMouseMove : kidmMouseMove2;
msg.x = (int)point.x;
msg.y = (int)point.y;
msg.ff = 0;
msg.ms = wi::HostGetMillisecondCount();
if (game_thread_ != NULL) {
game_thread_->Post(&msg,
(i == 0) ? kidmMouseMove2 : kidmMouseMove);
}
aptLast_[i].x = (int)point.x;
aptLast_[i].y = (int)point.y;
break;
}
}
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
for (UITouch *touch in touches) {
if (touch.view != self) {
continue;
}
for (int i = 0; i < 2; i++) {
if (atouch_[i] == touch) {
atouch_[i] = NULL;
CGPoint point = [touch locationInView: nil];
base::Message msg;
msg.id = (i == 0) ? kidmMouseUp : kidmMouseUp2;
msg.x = (int)point.x;
msg.y = (int)point.y;
msg.ff = 0;
msg.ms = wi::HostGetMillisecondCount();
if (game_thread_ != NULL) {
game_thread_->Post(&msg);
}
aptLast_[i].x = (int)point.x;
aptLast_[i].y = (int)point.y;
break;
}
}
}
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
for (int i = 0; i < 2; i++) {
if (atouch_[i] != NULL) {
atouch_[i] = NULL;
base::Message msg;
msg.id = (i == 0) ? kidmMouseUp : kidmMouseUp2;
msg.x = aptLast_[i].x;
msg.y = aptLast_[i].y;
msg.ff = 0;
msg.ms = wi::HostGetMillisecondCount();
if (game_thread_ != NULL) {
game_thread_->Post(&msg);
}
}
}
}
- (void)getSurfaceProperties:(wi::SurfaceProperties *)pprops
{
pprops->cxWidth = (int)rect_.size.width;
pprops->cyHeight = (int)rect_.size.height;
pprops->cbxPitch = 2;
pprops->cbyPitch = (int)rect_.size.width * 2;
pprops->ffFormat = wi::kfDirect565;
}
- (wi::SpriteManager *)getSpriteManager
{
return psprm_;
}
- (void)setClipRects:(wi::Rect *)prc1 prc2:(wi::Rect *)prc2
{
rcClip1_ = *prc1;
rcClip2_ = *prc2;
}
- (wi::AnimSprite *)createAnimSprite
{
return new wi::IPhoneAnimSprite(psprm_);
}
- (wi::SelectionSprite *)createSelectionSprite
{
return new wi::IPhoneSelectionSprite(psprm_);
}
- (void)addSprite:(wi::Sprite *)pspr
{
base::CritScope cs(pcrit_);
// If already added, just recreate the layer
bool fFound = false;
for (int i = 0; i < cpspr_; i++) {
if (pspr == apspr_[i]) {
fFound = true;
}
}
if (!fFound && cpspr_ < ARRAYSIZE(apspr_) - 1) {
apspr_[cpspr_] = pspr;
cpspr_++;
}
fSpriteDirty_ = true;
}
- (void)removeSprite:(wi::Sprite *)pspr
{
base::CritScope cs(pcrit_);
bool fFound = false;
for (int i = 0; i < cpspr_; i++) {
if (pspr == apspr_[i]) {
cpspr_--;
if (i < ARRAYSIZE(apspr_) - 1) {
memmove(&apspr_[i], &apspr_[i + 1],
(ARRAYSIZE(apspr_) - 1 - i) * ELEMENTSIZE(apspr_));
}
fFound = true;
break;
}
}
fSpriteDirty_ = true;
}
- (void)updateSprite:(wi::Sprite *)pspr
{
fSpriteDirty_ = true;
}
- (void)drawSprites:(CGContextRef)ctx
{
base::CritScope cs(pcrit_);
if (cpspr_ == 0) {
return;
}
// Save context before setting clip rects
CGContextSaveGState(ctx);
// First clip to the playfield up to just before the left edge of the
// minimap, then the area above the minimap.
#if 0
CGRect arcClip[2];
arcClip[0].origin.x = rcClip1_.left;
arcClip[0].origin.y = (int)rect_.size.width - rcClip1_.top -
rcClip1_.Height();
arcClip[0].size.width = rcClip1_.Width();
arcClip[0].size.height = rcClip1_.Height();
arcClip[1].origin.x = rcClip2_.left;
arcClip[1].origin.y = (int)rect_.size.width - rcClip2_.top -
rcClip2_.Height();
arcClip[1].size.width = rcClip2_.Width();
arcClip[1].size.height = rcClip2_.Height();
#else
CGRect arcClip[2];
arcClip[0].origin.x = rcClip1_.left;
arcClip[0].origin.y = rect_.size.height - rcClip1_.bottom;
arcClip[0].size.width = rcClip1_.Width();
arcClip[0].size.height = rcClip1_.Height();
arcClip[1].origin.x = rcClip2_.left;
arcClip[1].origin.y = rect_.size.height - rcClip2_.bottom;
arcClip[1].size.width = rcClip2_.Width();
arcClip[1].size.height = rcClip2_.Height();
#endif
CGContextClipToRects(ctx, arcClip, 2);
// Draw sprites
wi::Size siz;
siz.cx = (int)rect_.size.width;
siz.cy = (int)rect_.size.height;
for (int i = 0; i < cpspr_; i++) {
apspr_[i]->Draw(ctx, &siz);
}
// Restore context
CGContextRestoreGState(ctx);
}
- (void)setFormMgrs:(wi::FormMgr *)pfrmmSimUI input:(wi::FormMgr *)pfrmmInput
{
}
- (void)resetScrollOffset
{
}
@end