This is WorldMapView.m in view mode; [Download] [Up]
// // $Id: WorldMapView.m,v 1.8 1997/10/31 04:52:16 nygard Exp $ // // // This file is a part of Empire, a game of exploration and conquest. // Copyright (C) 1996 Steve Nygard // // 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., 675 Mass Ave, Cambridge, MA 02139, USA. // // You may contact the author by: // e-mail: nygard@telusplanet.net // #import "Empire.h" RCSID ("$Id: WorldMapView.m,v 1.8 1997/10/31 04:52:16 nygard Exp $"); #import "WorldMapView.h" #import "Brain.h" #import "Map.h" #import "EmpireImageVendor.h" #import "Map.h" #import "MapView.h" // To pick up delegate protocol definition (no longer..) #import "EmpireProtocols.h" // To pick up delegate protocol definition #define GRIDSIZE 4.0 //====================================================================== // The World Map View provides a small view of the entire world. I'm // not sure what the normal map view would look like if it were scaled // down to this size. // // Much of the interface should be the same as MapView. // //====================================================================== @implementation WorldMapView - initWithFrame:(NSRect)frameRect { EmpireImageVendor *vendor = [EmpireImageVendor instance]; Player p; [super initWithFrame:frameRect]; [vendor attach:self]; for (p = p_neutral; p <= p_player3; p++) playerColors[p] = [vendor colorForPlayer:p]; terrainColors[0] = [[NSColor blackColor] retain]; terrainColors[1] = [[NSColor colorWithCalibratedRed:0 green:0 blue:153 / 255.0 alpha:1.0] retain]; terrainColors[2] = [[NSColor colorWithCalibratedRed:0 green:85 / 255.0 blue:0 alpha:1.0] retain]; terrainColors[3] = [playerColors[0] retain]; compressEvents = NO; return self; } //---------------------------------------------------------------------- - (void) dealloc { int l; [[EmpireImageVendor instance] detach:self]; for (l = 0; l < 4; l++) { SNRelease (terrainColors[l]); } if (map != nil) [map detach:self]; [super dealloc]; } //---------------------------------------------------------------------- - (BOOL) acceptsFirstResponder { return YES; } //---------------------------------------------------------------------- - (BOOL) acceptsFirstMouse:(NSEvent *)theEvent { return YES; } //---------------------------------------------------------------------- #define RCOUNT 16 // This builds up lists of RCOUNT rectangles for the different colors, // and then fills them as a group when full. This gets pretty good // performance. - (void) drawRect:(NSRect)rect { EMMapLocation location1, location2; int row, column; EMMapSize mapSize; NSPoint aPoint; MapToken **mapPtrs = [map mapPtrs]; int l; NSRect blackRects[RCOUNT]; NSRect playerRects[4][RCOUNT]; NSRect terrainRects[4][RCOUNT]; int blackCount; int playerCount[4]; int terrainCount[4]; if (map != nil) { mapSize = [map mapSize]; blackCount = 0; for (l = 0; l < 4; l++) playerCount[l] = terrainCount[l] = 0; aPoint.x = NSMinX (rect); aPoint.y = NSMinY (rect); location1 = [self getLocationForPoint:aPoint]; aPoint.x += NSWidth (rect); aPoint.y += NSHeight (rect); location2 = [self getLocationForPoint:aPoint]; for (row = location2.row; row <= location1.row; row++) { aPoint.y = GRIDSIZE * (float)(mapSize.height - 1 - row); for (column = location1.column; column <= location2.column; column++) { MapToken mapToken = mapPtrs[row][column]; Terrain terrain; Player player; BOOL explored; EMMapTokenComponents (mapToken, &terrain, &player, NULL, &explored); aPoint.x = GRIDSIZE * (float)column; if (explored == NO) { blackRects[blackCount++] = NSMakeRect(aPoint.x, aPoint.y, GRIDSIZE, GRIDSIZE); if (blackCount == RCOUNT) { PSsetgray (NSBlack); NSRectFillList (blackRects, blackCount); blackCount = 0; } } else if (player >= p_player1 && player <= p_player3) { playerRects[player][playerCount[player]++] = NSMakeRect (aPoint.x, aPoint.y, GRIDSIZE, GRIDSIZE); if (playerCount[player] == RCOUNT) { [playerColors[player] set]; NSRectFillList (playerRects[player], playerCount[player]); playerCount[player] = 0; } } else { terrainRects[terrain][terrainCount[terrain]++] = NSMakeRect (aPoint.x, aPoint.y, GRIDSIZE, GRIDSIZE); if (terrainCount[terrain] == RCOUNT) { [terrainColors[terrain] set]; NSRectFillList (terrainRects[terrain], terrainCount[terrain]); terrainCount[terrain] = 0; } } } } if (blackCount > 0) { PSsetgray (NSBlack); NSRectFillList (blackRects, blackCount); blackCount = 0; } for (l = 0; l < 4; l++) { if (playerCount[l] > 0) { [playerColors[l] set]; NSRectFillList (playerRects[l], playerCount[l]); playerCount[l] = 0; } if (terrainCount[l] > 0) { [terrainColors[l] set]; NSRectFillList (terrainRects[l], terrainCount[l]); terrainCount[l] = 0; } } } } //---------------------------------------------------------------------- - (Map *) map { return map; } //---------------------------------------------------------------------- - (void) setMap:(Map *)aMap { EMMapSize mapSize; if (aMap == nil) return; if (map != nil) { [map detach:self]; [map release]; } map = aMap; [map attach:self]; [map retain]; mapSize = [map mapSize]; [self setFrameSize:NSMakeSize (GRIDSIZE * (float)mapSize.width, GRIDSIZE * (float)mapSize.height)]; [self setNeedsDisplay:YES]; } //---------------------------------------------------------------------- - (void) setCompressEvents:(BOOL)flag { compressEvents = flag; } //---------------------------------------------------------------------- - (EMMapLocation) getLocationForPoint:(NSPoint)point { EMMapSize mapSize; EMMapLocation target; NSAssert (map != nil, @"Map was nil."); mapSize = [map mapSize]; target.row = mapSize.height - (int)(point.y / GRIDSIZE) - 1; target.column = point.x / GRIDSIZE; target.row = (target.row >= mapSize.height) ? mapSize.height - 1 : target.row; target.row = (target.row <= 0) ? 0 : target.row; target.column = (target.column >= mapSize.width) ? mapSize.width - 1 : target.column; target.column = (target.column < 0) ? 0 : target.column; return target; } //---------------------------------------------------------------------- - (NSRect) getRectForLocation:(EMMapLocation)target { EMMapSize mapSize; NSAssert (map != nil, @"Map was nil."); mapSize = [map mapSize]; return NSMakeRect (GRIDSIZE * (float)target.column, (mapSize.height - 1 - target.row) * GRIDSIZE, GRIDSIZE, GRIDSIZE); } //---------------------------------------------------------------------- - (NSRect) getRectAround3x3Location:(EMMapLocation)target { EMMapLocation location1, location2; EMMapSize mapSize; NSAssert (map != nil, @"Map was nil."); mapSize = [map mapSize]; location1.row = target.row - 1; location1.row = (location1.row < 0) ? 0 : location1.row; location1.row = (location1.row >= mapSize.height) ? mapSize.height - 1 : location1.row; location2.row = target.row + 1; location2.row = (location2.row < 0) ? 0 : location2.row; location2.row = (location2.row >= mapSize.height) ? mapSize.height - 1 : location2.row; location1.column = target.column - 1; location1.column = (location1.column < 0) ? 0 : location1.column; location1.column = (location1.column >= mapSize.width) ? mapSize.width - 1 : location1.column; location2.column = target.column + 1; location2.column = (location2.column < 0) ? 0 : location2.column; location2.column = (location2.column >= mapSize.width) ? mapSize.width - 1 : location2.column; return NSMakeRect ((float)location1.column * GRIDSIZE, (mapSize.height - 1 - location2.row) * GRIDSIZE, (float)(location2.column - location1.column + 1) * GRIDSIZE, (float)(location2.row - location1.row + 1) * GRIDSIZE); } //---------------------------------------------------------------------- - (void) scrollLocationToVisible:(EMMapLocation)target { NSRect aRect = [self getRectAround3x3Location:target]; [self scrollRectToVisible:aRect]; } //---------------------------------------------------------------------- - (void) centerLocation:(EMMapLocation)target ifNotVisible:(BOOL)notVisibleFlag { NSRect aRect; NSRect visibleRect; aRect = [self getRectAround3x3Location:target]; visibleRect = [self visibleRect]; aRect.origin.x = NSMinX (aRect) + (NSWidth (aRect) / 2) - (NSWidth (visibleRect) / 2); aRect.origin.y = NSMinY (aRect) + (NSHeight (aRect) / 2) - (NSHeight (visibleRect) / 2); aRect.size.width = NSWidth (visibleRect); aRect.size.height = NSHeight (visibleRect); aRect = NSIntersectionRect ([self bounds] , aRect); [self scrollRectToVisible:aRect]; } //---------------------------------------------------------------------- - (void) displayLocation:(EMMapLocation)target { EMMapSize mapSize; NSRect aRect; NSAssert (map != nil, @"Map was nil."); mapSize = [map mapSize]; NSAssert (target.row >= 0 && target.column >= 0 && target.row < mapSize.height && target.column < mapSize.width, @"Cell out of range."); aRect = [self getRectForLocation:target]; [self scrollRectToVisible:aRect]; [self setNeedsDisplayInRect:aRect]; [self displayIfNeeded]; } //---------------------------------------------------------------------- - (void) displayAround3x3Location:(EMMapLocation)target { EMMapSize mapSize; NSRect aRect; NSAssert (map != nil, @"Map was nil."); mapSize = [map mapSize]; NSAssert (target.row >= 0 && target.column >= 0 && target.row < mapSize.height && target.column < mapSize.width, @"Location out of range."); aRect = [self getRectAround3x3Location:target]; [self scrollRectToVisible:aRect]; [self setNeedsDisplayInRect:aRect]; [self displayIfNeeded]; } //---------------------------------------------------------------------- - (void) vendorImagesUpdated:(BOOL)player1:(BOOL)player2:(BOOL)player3:(BOOL)other { EmpireImageVendor *vendor = [EmpireImageVendor instance]; Player p; for (p = p_neutral; p <= p_player3; p++) playerColors[p] = [vendor colorForPlayer:p]; terrainColors[3] = playerColors[0]; [self setNeedsDisplay:YES]; } //====================================================================== // Map Observer //====================================================================== - (void) refreshMap { [self setNeedsDisplay:YES]; } //---------------------------------------------------------------------- - (void) refreshLocation:(EMMapLocation)target { [self displayLocation:target]; //[self displayIfNeeded]; } //---------------------------------------------------------------------- - (void) refresh3x3Location:(EMMapLocation)target { [self displayAround3x3Location:target]; } //---------------------------------------------------------------------- - (void) mouseDown:(NSEvent *)theEvent { NSPoint aPoint; EMMapLocation mapLocation; NSRect visibleRect; BOOL scrolled = NO; NSPoint mouseLocation; EMMapLocation lastLocation; BOOL periodicOn = NO; unsigned int originalModifierFlags = [theEvent modifierFlags]; unsigned int modifierFlags; lastLocation.row = -1; lastLocation.column = -1; if (delegate == nil) { [super mouseDown:theEvent]; return; } mouseLocation = [theEvent locationInWindow]; while ([theEvent type] != NSLeftMouseUp) { visibleRect = [self visibleRect]; switch ([theEvent type]) { case NSLeftMouseUp: break; case NSPeriodic: case NSLeftMouseDown: case NSLeftMouseDragged: if ([theEvent type] == NSPeriodic) { mouseLocation = [[self window] mouseLocationOutsideOfEventStream]; modifierFlags = originalModifierFlags; } else { mouseLocation = [theEvent locationInWindow]; modifierFlags = [theEvent modifierFlags]; } aPoint = [self convertPoint:mouseLocation fromView:nil]; mapLocation = [self getLocationForPoint:aPoint]; if (compressEvents == NO || mapLocation.row != lastLocation.row || mapLocation.column != lastLocation.column || [theEvent type] == NSPeriodic || (originalModifierFlags & NSControlKeyMask != 0)) { lastLocation = mapLocation; [delegate mouseDown:modifierFlags atLocation:mapLocation]; } //if (compressEvents == NO) { if (periodicOn == NO) { [NSEvent startPeriodicEventsAfterDelay:0.1 withPeriod:0.05]; periodicOn = YES; } } if (NSPointInRect(mouseLocation, visibleRect) == NO) { scrolled = YES; if (periodicOn == NO) { [NSEvent startPeriodicEventsAfterDelay:0.1 withPeriod:0.05]; periodicOn = YES; } } else if (compressEvents == YES) { [NSEvent stopPeriodicEvents]; periodicOn = NO; } break; default: break; } if (scrolled) scrolled = NO; theEvent = [[self window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSPeriodicMask)]; } [NSEvent stopPeriodicEvents]; // Mouse up event has been consumed by this point. [self mouseUp:theEvent]; } //---------------------------------------------------------------------- - (void) mouseUp:(NSEvent *)theEvent { NSPoint point; EMMapLocation mapLocation; if ([theEvent type] == NSLeftMouseUp && delegate != nil) { //NSLog (@"here."); point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; mapLocation = [self getLocationForPoint:point]; //NSLog (@"delegate: %@", delegate); [delegate mouseUp:[theEvent modifierFlags] atLocation:mapLocation]; } else { [super mouseUp:theEvent]; } } //---------------------------------------------------------------------- - (void) keyDown:(NSEvent *)theEvent { if (delegate != nil) { [delegate keyDown:theEvent]; } else { [super keyDown:theEvent]; } } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.