16 #define GL_SILENCE_DEPRECATION
39 @implementation C4OpenGLView
43 - (BOOL) isOpaque {
return YES;}
46 - (id) initWithFrame:(NSRect)frameRect
48 self = [
super initWithFrame:frameRect];
50 [[NSNotificationCenter defaultCenter]
52 selector:@selector(_surfaceNeedsUpdate:)
53 name:NSViewGlobalFrameDidChangeNotification
66 [[
self window] makeFirstResponder:self];
67 [[
self window] setAcceptsMouseMovedEvents:YES];
69 [
self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
72 - (BOOL) acceptsFirstResponder {
return YES;}
74 - (void) resetCursorRects
76 [
super resetCursorRects];
77 if ([
self shouldHideMouseCursor])
79 static NSCursor* cursor;
82 cursor = [[NSCursor alloc] initWithImage:[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] hotSpot:NSMakePoint(0, 0)];
84 [
self addCursorRect:self.bounds cursor:cursor];
88 - (void) _surfaceNeedsUpdate:(NSNotification*)notification
95 NSOpenGLContext* ctx = [
self context];
97 if ([ctx view] !=
self) {
100 [ctx makeCurrentContext];
108 - (void) viewDidMoveToWindow
110 [
super viewDidMoveToWindow];
111 if ([
self window] == nil)
112 [context clearDrawable];
115 - (void) drawRect:(NSRect)rect
123 if ([NSApp respondsToSelector:
@selector(occlusionState)])
126 if (([NSApp occlusionState] & NSApplicationOcclusionStateVisible) == 0)
131 if ([
self.controller isFullScreenConsideringLionFullScreen] && ![NSApp isActive])
133 if ([
self.window isMiniaturized] || ![
self.window isVisible])
136 C4Window* stdWindow =
self.controller.stdWindow;
141 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
146 int32_t mouseButtonFromEvent(NSEvent* event,
DWORD* modifierFlags)
148 *modifierFlags = [event modifierFlags];
149 if ([event modifierFlags] & NSEventModifierFlagCommand)
152 *modifierFlags |= NSEventModifierFlagControl;
156 case NSEventTypeLeftMouseDown:
158 case NSEventTypeLeftMouseUp:
160 case NSEventTypeRightMouseDown:
162 case NSEventTypeRightMouseUp:
164 case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
166 case NSEventTypeOtherMouseDown:
168 case NSEventTypeOtherMouseUp:
170 case NSEventTypeScrollWheel:
178 - (BOOL) shouldHideMouseCursor
185 if ([
self shouldHideMouseCursor])
191 if ([
self shouldHideMouseCursor])
195 - (void) mouseEvent:(NSEvent*)event
198 int32_t button = mouseButtonFromEvent(event, &flags);
201 CGPoint mouse = [
self convertPoint:[
self.window mouseLocationOutsideOfEventStream] fromView:nil];
204 mouse.x *= ActualFullscreenX/
self.frame.size.width;
205 mouse.y *= ActualFullscreenY/
self.frame.size.height;
207 mouse.x = fmin(fmax(mouse.x, 0), actualSizeX);
208 mouse.y = fmin(fmax(mouse.y, 0), actualSizeY);
210 int y = actualSizeY - mouse.y;
212 C4Viewport* viewport =
self.controller.viewport;
215 DWORD keyMask = flags;
216 if ([event
type] == NSEventTypeScrollWheel)
221 if ([event deltaY] > 0)
222 keyMask |= (+32) << 16;
224 keyMask |= (-32) << 16;
254 - (void) magnifyWithEvent:(NSEvent *)event
256 if (
Game.
IsRunning && (event.modifierFlags & NSEventModifierFlagOption) == 0)
258 C4Viewport* viewport =
self.controller.viewport;
261 viewport->
SetZoom(viewport->
GetZoom()+[event magnification],
true);
267 [
self.window toggleFullScreen:self];
269 [
self.controller setFullscreen:[event magnification] > 0];
274 - (void) swipeWithEvent:(NSEvent*)event
277 if (event.deltaX > 0)
283 - (void)insertText:(
id)insertString
287 NSString* str = [insertString isKindOfClass:[NSAttributedString class]] ? [(NSAttributedString*)insertString string] : (NSString*)insertString;
288 const char* cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
293 - (void)doCommandBySelector:(
SEL)selector
298 - (void)keyEvent:(NSEvent*)event withKeyEventType:(
C4KeyEventType)type
301 [event keyCode]+CocoaKeycodeOffset,
303 [event modifierFlags] & NSEventModifierFlagOption,
304 ([event modifierFlags] & NSEventModifierFlagControl) || ([event modifierFlags] & NSEventModifierFlagCommand),
305 [event modifierFlags] & NSEventModifierFlagShift,
309 C4Window* stdWindow =
self.controller.stdWindow;
319 - (void)keyDown:(NSEvent*)event
321 [
self interpretKeyEvents:[NSArray arrayWithObject:event]];
322 [
self keyEvent:event withKeyEventType:KEYEV_Down];
325 - (void)keyUp:(NSEvent*)event
327 [
self keyEvent:event withKeyEventType:KEYEV_Up];
330 - (void)flagsChanged:(NSEvent*)event
336 if (key == K_SHIFT_L || key == K_SHIFT_R)
337 modifier = NSEventModifierFlagShift;
338 if (key == K_CONTROL_L || key == K_CONTROL_R)
339 modifier = NSEventModifierFlagControl;
340 if (key == K_COMMAND_L || key == K_COMMAND_R)
341 modifier = NSEventModifierFlagCommand;
342 if (key == K_ALT_L || key == K_ALT_R)
343 modifier = NSEventModifierFlagOption;
347 int modifierMask = [event modifierFlags];
348 if (modifierMask & modifier)
349 [
self keyEvent:event withKeyEventType:KEYEV_Down];
351 [
self keyEvent:event withKeyEventType:KEYEV_Up];
355 - (NSDragOperation) draggingEntered:(
id<NSDraggingInfo>)sender
357 return NSDragOperationCopy;
360 - (NSDragOperation) draggingUpdated:(
id<NSDraggingInfo>)sender
362 return NSDragOperationCopy;
365 - (BOOL) prepareForDragOperation:(
id<NSDraggingInfo>)sender
370 - (BOOL) performDragOperation:(
id<NSDraggingInfo>)sender
372 NSPasteboard* pasteboard = [sender draggingPasteboard];
373 if ([[pasteboard types] containsObject:NSFilenamesPboardType])
375 NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
376 C4Viewport* viewport =
self.controller.viewport;
379 for (NSString* fileName in files)
381 auto loc = NSMakePoint([sender draggingLocation].x,
self.bounds.size.height - [sender draggingLocation].y);
382 viewport->
DropFile([fileName cStringUsingEncoding:NSUTF8StringEncoding], loc.x, loc.y);
389 - (
void )concludeDragOperation:(
id<NSDraggingInfo>)sender
395 - (void) scrollWheel:(NSEvent *)event
398 C4Viewport* viewport =
self.controller.viewport;
401 NSScrollView* scrollView =
self.controller.scrollView;
403 [scrollView.horizontalScroller setDoubleValue:scrollView.horizontalScroller.doubleValue+p.x];
404 [scrollView.verticalScroller setDoubleValue:scrollView.verticalScroller.doubleValue+p.y];
412 [
self mouseEvent:event];
416 - (void) mouseDown: (NSEvent *)event {[
self mouseEvent:event];}
417 - (void) rightMouseDown: (NSEvent *)event {[
self mouseEvent:event];}
418 - (void) rightMouseUp: (NSEvent *)event {[
self mouseEvent:event];}
419 - (void) otherMouseDown: (NSEvent *)event {[
self mouseEvent:event];}
420 - (void) otherMouseUp: (NSEvent *)event {[
self mouseEvent:event];}
421 - (void) mouseUp: (NSEvent *)event {[
self mouseEvent:event];}
422 - (void) mouseMoved: (NSEvent *)event {[
self mouseEvent:event];}
423 - (void) mouseDragged: (NSEvent *)event {[
self mouseEvent:event];}
424 - (void) rightMouseDragged:(NSEvent *)event {[
self mouseEvent:event];}
431 + (CGDirectDisplayID) displayID
433 return (CGDirectDisplayID)[[[[[NSApp keyWindow] screen] deviceDescription] valueForKey:@"NSScreenNumber"] intValue];
436 + (void) enumerateMultiSamples:(
std::vector<
int>&)samples
438 CGDirectDisplayID displayID =
self.displayID;
439 CGOpenGLDisplayMask displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
440 int numRenderers = 0;
441 CGLRendererInfoObj obj = NULL;
444 CGLQueryRendererInfo(displayMask, &obj, &numRenderers);
445 CGLDescribeRenderer(obj, 0, kCGLRPSampleModes, &sampleModes);
446 CGLDestroyRendererInfo(obj);
448 if (sampleModes & kCGLMultisampleBit)
450 samples.push_back(1);
451 samples.push_back(2);
452 samples.push_back(4);
456 + (void) setSurfaceBackingSizeOf:(NSOpenGLContext*) context width:(
int)wdt height:(
int)hgt
461 GLint dim[2] = {wdt, hgt};
462 CGLContextObj ctx = (CGLContextObj)context.CGLContextObj;
463 CGLSetParameter(ctx, kCGLCPSurfaceBackingSize, dim);
464 CGLEnable (ctx, kCGLCESurfaceBackingSize);
468 - (void) setContextSurfaceBackingSizeToOwnDimensions
470 [C4OpenGLView setSurfaceBackingSizeOf:self.context width:self.frame.size.width height:self.frame.size.height];
473 static NSOpenGLContext* MainContext;
475 + (NSOpenGLContext*) mainContext
480 + (NSOpenGLContext*) createContext:(
CStdGLCtx*) pMainCtx
482 std::vector<NSOpenGLPixelFormatAttribute> attribs;
483 attribs.push_back(NSOpenGLPFAOpenGLProfile);
484 attribs.push_back(NSOpenGLProfileVersion3_2Core);
485 attribs.push_back(NSOpenGLPFADepthSize);
486 attribs.push_back(16);
489 std::vector<int> samples;
490 [
self enumerateMultiSamples:samples];
491 if (!samples.empty())
493 attribs.push_back(NSOpenGLPFAMultisample);
494 attribs.push_back(NSOpenGLPFASampleBuffers);
495 attribs.push_back(1);
496 attribs.push_back(NSOpenGLPFASamples);
500 attribs.push_back(NSOpenGLPFANoRecovery);
503 attribs.push_back(0);
504 NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
505 NSOpenGLContext* result = [[NSOpenGLContext alloc] initWithFormat:format shareContext:pMainCtx ? pMainCtx->objectiveCObject<NSOpenGLContext>() : nil];
507 MainContext = result;
511 - (IBAction) increaseZoom:(
id)sender
522 - (IBAction) decreaseZoom:(
id)sender
535 @implementation C4EditorOpenGLView
537 - (void) copy:(
id) sender
542 - (void) delete:(
id) sender
547 - (IBAction) grabContents:(
id) sender
552 - (IBAction) resetZoom:(
id) sender
554 self.controller.viewport->SetZoom(1,
true);
559 #pragma mark CStdGLCtx: Initialization
566 setObjectiveCObject(nil);
578 [C4OpenGLView enumerateMultiSamples:samples];
584 if (!
pGL)
return false;
589 NSOpenGLContext* ctx = [C4OpenGLView createContext:pGL->pMainCtx];
590 setObjectiveCObject(ctx);
592 if (!
Select(
true))
return pGL->
Error(
" gl: Unable to select context");
595 if (controller && controller.openGLView)
597 [controller.openGLView setContext:ctx];
598 [ctx setView:controller.openGLView];
605 #pragma mark CStdGLCtx: Select/Deselect
609 [objectiveCObject<NSOpenGLContext>() makeCurrentContext];
615 if (verbose)
pGL->
Error(
" gl: UpdateClipper failed");
639 int ActualFullscreenX = 0, ActualFullscreenY = 0;
C4Application Application
C4MouseControl MouseControl
const int32_t C4MC_Button_None
const int32_t C4MC_Button_RightDown
const int32_t C4MC_Button_MiddleUp
const int32_t C4MC_Button_RightUp
const int32_t C4MC_Button_MiddleDown
const int32_t C4MC_Button_RightDouble
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Button_LeftDown
const int32_t C4MC_Button_LeftDouble
const int32_t C4MC_Button_Wheel
int32_t ValidPlr(int32_t plr)
C4ConfigGraphics Graphics
bool LeftButtonDown(DWORD dwKeyState)
bool KeyDown(C4KeyCode KeyCode, DWORD dwKeyState)
bool RightButtonDown(DWORD dwKeyState)
bool RightButtonUp(DWORD dwKeyState)
bool LeftButtonUp(DWORD dwKeyState)
bool Move(float iX, float iY, float zoom, DWORD dwKeyState)
bool KeyUp(C4KeyCode KeyCode, DWORD dwKeyState)
virtual bool CharIn(const char *c)
bool DoKeyboardInput(C4KeyCode vk_code, C4KeyEventType event_type, bool alt, bool ctrl, bool shift, bool repeated, class C4GUI::Dialog *for_dialog=nullptr, bool fPlrCtrlOnly=false, int32_t strength=-1)
int32_t GetHeight() const
bool IsViewport(C4Viewport *pViewport)
bool ViewPositionByScrollBars()
void DropFile(const char *filename, float x, float y)
void SetZoom(float zoom_value)
virtual void EnumerateMultiSamples(std::vector< int > &samples, int min_expected=0) const
virtual void PerformUpdate()
virtual bool Init(C4Window *pWindow, C4AbstractApp *pApp)
virtual bool Select(bool verbose=false)
virtual void Clear(bool multisample_change=false)
static std::list< CStdGLCtx * > contexts
std::list< CStdGLCtx * >::iterator this_context
bool Error(const char *szMsg) override
bool UpdateClipper() override
IBAction simulateKeyPressed:(C4KeyCode key)
void MouseMove(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, class C4Viewport *pVP)