forked from Mirrors/openclonk
289 lines
7.0 KiB
Plaintext
289 lines
7.0 KiB
Plaintext
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 2009-2015, The OpenClonk Team and contributors
|
|
*
|
|
* Distributed under the terms of the ISC license; see accompanying file
|
|
* "COPYING" for details.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
|
* See accompanying file "TRADEMARK" for details.
|
|
*
|
|
* To redistribute this file separately, substitute the full license texts
|
|
* for the above references.
|
|
*/
|
|
|
|
#include <C4Include.h>
|
|
#include <C4Application.h>
|
|
#include <C4Viewport.h>
|
|
#include <C4ViewportWindow.h>
|
|
#include <C4FullScreen.h>
|
|
#include <C4Landscape.h>
|
|
|
|
#include <epoxy/gl.h>
|
|
|
|
#import "C4WindowController.h"
|
|
#import "C4DrawGLMac.h"
|
|
#import "C4EditorWindowController.h"
|
|
#import "C4AppDelegate.h"
|
|
#import "AppKit/NSOpenGL.h"
|
|
|
|
static SInt32 osVersion()
|
|
{
|
|
SInt32 ver;
|
|
Gestalt(gestaltSystemVersion, &ver);
|
|
return ver;
|
|
}
|
|
|
|
bool lionAndBeyond() {return osVersion() >= 0x1070;}
|
|
|
|
#ifdef USE_COCOA
|
|
|
|
// Turns out, it is necessary to derive a NSWindow class after all - or else the screen-filling window won't be able to become the key window
|
|
|
|
@interface ClonkScreenfillingWindow: NSWindow
|
|
{}
|
|
- (BOOL) canBecomeKeyWindow;
|
|
@end
|
|
|
|
@implementation ClonkScreenfillingWindow
|
|
- (BOOL) canBecomeKeyWindow;
|
|
{
|
|
return YES; // a resounding one
|
|
}
|
|
@end
|
|
|
|
@implementation C4WindowController
|
|
|
|
@synthesize stdWindow, openGLView, scrollView;
|
|
|
|
- (void) awakeFromNib
|
|
{
|
|
[super awakeFromNib];
|
|
if (!Application.isEditor)
|
|
C4AppDelegate.instance.gameWindowController = self;
|
|
}
|
|
|
|
- (void) fadeOut:(CGDisplayFadeReservationToken*)token
|
|
{
|
|
if (CGAcquireDisplayFadeReservation(15, token) == 0)
|
|
CGDisplayFade(*token, 0.2, 0.0, 1.0, 0, 0, 0, YES);
|
|
}
|
|
|
|
- (void) fadeIn:(CGDisplayFadeReservationToken)token
|
|
{
|
|
CGDisplayFade(token, 0.2, 1.0, 0.0, 0, 0, 0, YES);
|
|
CGReleaseDisplayFadeReservation(token);
|
|
}
|
|
|
|
- (BOOL) isFullScreen {
|
|
return fullscreenWindow != nil;
|
|
}
|
|
|
|
- (BOOL) isFullScreenConsideringLionFullScreen
|
|
{
|
|
return
|
|
[self isFullScreen] ||
|
|
(lionAndBeyond() && (self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask);
|
|
}
|
|
|
|
- (void) setFullscreen:(BOOL)fullscreen
|
|
{
|
|
if (fullscreen != [self isFullScreen])
|
|
{
|
|
// fade out
|
|
#ifndef _DEBUG
|
|
CGDisplayFadeReservationToken token;
|
|
[self fadeOut:&token];
|
|
#endif
|
|
if (![self isFullScreen])
|
|
{
|
|
NSRect fullscreenRect = NSScreen.mainScreen.frame;
|
|
fullscreenWindow = [[ClonkScreenfillingWindow alloc] initWithContentRect:fullscreenRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
|
|
[fullscreenWindow setLevel:NSMainMenuWindowLevel+1];
|
|
[fullscreenWindow setOpaque:YES];
|
|
[fullscreenWindow setHidesOnDeactivate:YES];
|
|
[fullscreenWindow setContentView:openGLView];
|
|
[fullscreenWindow setReleasedWhenClosed:YES];
|
|
[fullscreenWindow setDelegate:self];
|
|
[self.window orderOut:self];
|
|
[fullscreenWindow setInitialFirstResponder:openGLView];
|
|
[fullscreenWindow makeKeyAndOrderFront:self];
|
|
//[openGLView setContextSurfaceBackingSizeToOwnDimensions];
|
|
[openGLView enableEvents];
|
|
// hide cursor completely
|
|
[NSCursor hide];
|
|
}
|
|
else
|
|
{
|
|
// unhide and rely on cursor rects again
|
|
[NSCursor unhide];
|
|
|
|
[fullscreenWindow close];
|
|
fullscreenWindow = nil;
|
|
[self.window setContentView:openGLView];
|
|
[self.window orderFront:self];
|
|
[openGLView setFrame:[self.window.contentView frame]];
|
|
[openGLView enableEvents];
|
|
[self.window makeKeyAndOrderFront:self];
|
|
}
|
|
[openGLView display];
|
|
#ifndef _DEBUG
|
|
// fade in again
|
|
[self fadeIn:token];
|
|
#endif
|
|
}
|
|
}
|
|
|
|
- (BOOL) windowShouldClose:(id)sender
|
|
{
|
|
if (sender == self.window && self.stdWindow)
|
|
{
|
|
[self.openGLView showCursor];
|
|
self.stdWindow->Close();
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (C4Viewport*) viewport
|
|
{
|
|
for (C4Viewport* v = ::Viewports.GetFirstViewport(); v; v = v->GetNext())
|
|
if (v->GetWindow() == stdWindow || (!v->GetWindow() && stdWindow == &FullScreen))
|
|
return v;
|
|
return NULL;
|
|
}
|
|
|
|
- (IBAction) scroll:(id)sender
|
|
{
|
|
C4Viewport* viewport = self.viewport;
|
|
if (viewport)
|
|
{
|
|
viewport->ViewPositionByScrollBars();
|
|
viewport->Execute();
|
|
}
|
|
}
|
|
|
|
- (void) windowDidResize:(NSNotification *)notification
|
|
{
|
|
if (Application.isEditor)
|
|
{
|
|
C4Viewport* viewport = self.viewport;
|
|
if (viewport && Application.isEditor)
|
|
{
|
|
viewport->ScrollBarsByViewPosition();
|
|
}
|
|
}
|
|
}
|
|
|
|
- (BOOL) isLiveResizing
|
|
{
|
|
return self.window.inLiveResize;
|
|
}
|
|
|
|
- (NSRect) windowWillUseStandardFrame:(NSWindow*) window defaultFrame:(NSRect) newFrame
|
|
{
|
|
return NSMakeRect(newFrame.origin.x, newFrame.origin.y, preferredContentSize.width, preferredContentSize.height);
|
|
}
|
|
|
|
- (NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
|
|
{
|
|
if (stdWindow == &::FullScreen)
|
|
return NSMakeSize(
|
|
CGDisplayPixelsWide(C4OpenGLView.displayID),
|
|
CGDisplayPixelsHigh(C4OpenGLView.displayID)
|
|
);
|
|
else
|
|
return proposedSize;
|
|
}
|
|
|
|
- (void) windowWillExitFullScreen:(NSNotification *)notification
|
|
{
|
|
if (!Application.isEditor)
|
|
{
|
|
CGAssociateMouseAndMouseCursorPosition(TRUE);
|
|
}
|
|
}
|
|
|
|
- (void) setContentSize:(NSSize)size
|
|
{
|
|
[self.window setContentSize:size];
|
|
preferredContentSize = size;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface NSScroller (ClonkZoom)
|
|
- (void) setToLandscapeCoordinate:(float)lc
|
|
size:(int) s
|
|
viewportSize:(int) vs
|
|
zoom: (float) z;
|
|
- (float) landscapeCoordinateForSize:(int) s
|
|
viewportSize:(int) vs
|
|
zoom:(float) z;
|
|
@end
|
|
@implementation NSScroller (ClonkZoom)
|
|
- (void) setToLandscapeCoordinate:(float)lc
|
|
size:(int) s
|
|
viewportSize:(int) vs
|
|
zoom: (float) z
|
|
{
|
|
self.doubleValue = (double)lc/((double)s - (double)vs/z);
|
|
self.knobProportion = (CGFloat)std::min(1.0, (double)vs/(s*z));
|
|
}
|
|
|
|
- (float) landscapeCoordinateForSize:(int) s
|
|
viewportSize:(int) vs
|
|
zoom:(float) z
|
|
{
|
|
return self.doubleValue * ((double)s - (double)vs/z);
|
|
}
|
|
@end
|
|
|
|
// C4ViewportWindow
|
|
|
|
bool C4Viewport::ScrollBarsByViewPosition()
|
|
{
|
|
if (PlayerLock) return false;
|
|
NSScrollView* scrollView = pWindow->objectiveCObject<C4WindowController>().scrollView;
|
|
[scrollView.horizontalScroller setToLandscapeCoordinate:GetViewX() size:GBackWdt viewportSize:ViewWdt zoom:GetZoom()];
|
|
[scrollView.verticalScroller setToLandscapeCoordinate:GetViewY() size:GBackHgt viewportSize:ViewHgt zoom:GetZoom()];
|
|
return true;
|
|
}
|
|
|
|
bool C4Viewport::ViewPositionByScrollBars()
|
|
{
|
|
NSScrollView* scrollView = pWindow->objectiveCObject<C4WindowController>().scrollView;
|
|
SetViewX([scrollView.horizontalScroller landscapeCoordinateForSize:GBackWdt viewportSize:ViewWdt zoom:GetZoom()]);
|
|
SetViewY([scrollView.verticalScroller landscapeCoordinateForSize:GBackHgt viewportSize:ViewHgt zoom:GetZoom()]);
|
|
return true;
|
|
}
|
|
|
|
bool C4Viewport::TogglePlayerLock()
|
|
{
|
|
NSScrollView* scrollView = pWindow->objectiveCObject<C4WindowController>().scrollView;
|
|
if (PlayerLock)
|
|
{
|
|
PlayerLock = false;
|
|
if (scrollView)
|
|
{
|
|
[scrollView.verticalScroller setEnabled:YES];
|
|
[scrollView.horizontalScroller setEnabled:YES];
|
|
[scrollView setAutohidesScrollers:NO];
|
|
}
|
|
ScrollBarsByViewPosition();
|
|
}
|
|
else
|
|
{
|
|
PlayerLock = true;
|
|
if (scrollView)
|
|
{
|
|
[scrollView.verticalScroller setEnabled:NO];
|
|
[scrollView.horizontalScroller setEnabled:NO];
|
|
[scrollView setAutohidesScrollers:YES];
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endif
|