mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
Stop using [NSApp run]
This commit is contained in:
parent
2bc4d6bf14
commit
170ed689fa
@ -9,9 +9,7 @@ import (
|
||||
"github.com/hajimehoshi/go-ebiten/example/game/rotating"
|
||||
"github.com/hajimehoshi/go-ebiten/example/game/sprites"
|
||||
"github.com/hajimehoshi/go-ebiten/example/game/testpattern"
|
||||
"github.com/hajimehoshi/go-ebiten/ui"
|
||||
"github.com/hajimehoshi/go-ebiten/ui/cocoa"
|
||||
// "github.com/hajimehoshi/go-ebiten/ui/glut"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
@ -23,10 +21,6 @@ func main() {
|
||||
if 2 <= len(os.Args) {
|
||||
gameName = os.Args[1]
|
||||
}
|
||||
uiName := "cocoa"
|
||||
if 3 <= len(os.Args) {
|
||||
uiName = os.Args[2]
|
||||
}
|
||||
|
||||
var game ebiten.Game
|
||||
switch gameName {
|
||||
@ -52,12 +46,11 @@ func main() {
|
||||
const screenHeight = 240
|
||||
const screenScale = 2
|
||||
const title = "Ebiten Demo"
|
||||
var u ui.UI
|
||||
switch uiName {
|
||||
default:
|
||||
fallthrough
|
||||
case "cocoa":
|
||||
u = cocoa.New(screenWidth, screenHeight, screenScale, title)
|
||||
ui := cocoa.New(screenWidth, screenHeight, screenScale, title)
|
||||
ui.Start(game)
|
||||
ui.InitTextures(game)
|
||||
for {
|
||||
ui.WaitEvents()
|
||||
ui.Draw(game.Draw)
|
||||
}
|
||||
u.Run(game)
|
||||
}
|
||||
|
@ -6,13 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type Device struct {
|
||||
context *Context
|
||||
context *Context
|
||||
}
|
||||
|
||||
func NewDevice(screenWidth, screenHeight, screenScale int) *Device {
|
||||
graphicsContext := newContext(screenWidth, screenHeight, screenScale)
|
||||
context := newContext(screenWidth, screenHeight, screenScale)
|
||||
return &Device{
|
||||
context: graphicsContext,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,24 @@
|
||||
package cocoa
|
||||
|
||||
// #cgo CFLAGS: -x objective-c -fobjc-arc
|
||||
// #cgo CFLAGS: -x objective-c
|
||||
// #cgo LDFLAGS: -framework Cocoa -framework OpenGL -framework QuartzCore
|
||||
//
|
||||
//
|
||||
// #include <stdlib.h>
|
||||
// #include "input.h"
|
||||
//
|
||||
// void Run(size_t width, size_t height, size_t scale, const char* title);
|
||||
// void Start(size_t width, size_t height, size_t scale, const char* title);
|
||||
// void WaitEvents(void);
|
||||
// void BeginDrawing(void);
|
||||
// void EndDrawing(void);
|
||||
//
|
||||
import "C"
|
||||
import (
|
||||
"github.com/hajimehoshi/go-ebiten"
|
||||
"github.com/hajimehoshi/go-ebiten/graphics"
|
||||
"github.com/hajimehoshi/go-ebiten/graphics/opengl"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@ -41,16 +45,16 @@ func (context *GameContext) InputState() ebiten.InputState {
|
||||
}
|
||||
|
||||
type UI struct {
|
||||
screenWidth int
|
||||
screenHeight int
|
||||
screenScale int
|
||||
title string
|
||||
updating chan ebiten.Game
|
||||
updated chan ebiten.Game
|
||||
input chan ebiten.InputState
|
||||
graphicsDevice *opengl.Device
|
||||
funcsExecutedOnMainThread []func() // TODO: map?
|
||||
lock sync.Mutex
|
||||
screenWidth int
|
||||
screenHeight int
|
||||
screenScale int
|
||||
title string
|
||||
updating chan struct{}
|
||||
updated chan struct{}
|
||||
input chan ebiten.InputState
|
||||
graphicsDevice *opengl.Device
|
||||
lock sync.Mutex
|
||||
gameContext *GameContext
|
||||
}
|
||||
|
||||
var currentUI *UI
|
||||
@ -60,14 +64,18 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
|
||||
panic("UI can't be duplicated.")
|
||||
}
|
||||
ui := &UI{
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
screenScale: screenScale,
|
||||
title: title,
|
||||
updating: make(chan ebiten.Game),
|
||||
updated: make(chan ebiten.Game),
|
||||
input: make(chan ebiten.InputState),
|
||||
funcsExecutedOnMainThread: []func(){},
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
screenScale: screenScale,
|
||||
title: title,
|
||||
updating: make(chan struct{}),
|
||||
updated: make(chan struct{}),
|
||||
input: make(chan ebiten.InputState),
|
||||
gameContext: &GameContext{
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
inputState: ebiten.InputState{-1, -1},
|
||||
},
|
||||
}
|
||||
currentUI = ui
|
||||
return ui
|
||||
@ -76,50 +84,45 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
|
||||
func (ui *UI) gameMainLoop(game ebiten.Game) {
|
||||
frameTime := time.Duration(int64(time.Second) / int64(ebiten.FPS))
|
||||
tick := time.Tick(frameTime)
|
||||
gameContext := &GameContext{
|
||||
screenWidth: ui.screenWidth,
|
||||
screenHeight: ui.screenHeight,
|
||||
inputState: ebiten.InputState{-1, -1},
|
||||
}
|
||||
ui.InitializeGame(game)
|
||||
for {
|
||||
select {
|
||||
case gameContext.inputState = <-ui.input:
|
||||
case ui.gameContext.inputState = <-ui.input:
|
||||
case <-tick:
|
||||
game.Update(gameContext)
|
||||
case ui.updating <- game:
|
||||
game = <-ui.updated
|
||||
game.Update(ui.gameContext)
|
||||
case ui.updating <- struct{}{}:
|
||||
//ui.DrawGame(game)
|
||||
<-ui.updated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ui *UI) Run(game ebiten.Game) {
|
||||
func (ui *UI) Start(game ebiten.Game) {
|
||||
go ui.gameMainLoop(game)
|
||||
runtime.LockOSThread()
|
||||
|
||||
cTitle := C.CString(ui.title)
|
||||
defer C.free(unsafe.Pointer(cTitle))
|
||||
|
||||
C.Run(C.size_t(ui.screenWidth),
|
||||
C.Start(C.size_t(ui.screenWidth),
|
||||
C.size_t(ui.screenHeight),
|
||||
C.size_t(ui.screenScale),
|
||||
cTitle)
|
||||
C.WaitEvents()
|
||||
}
|
||||
|
||||
func (ui *UI) InitializeGame(game ebiten.Game) {
|
||||
ui.lock.Lock()
|
||||
defer ui.lock.Unlock()
|
||||
ui.funcsExecutedOnMainThread = append(ui.funcsExecutedOnMainThread, func() {
|
||||
game.InitTextures(ui.graphicsDevice.TextureFactory())
|
||||
})
|
||||
func (ui *UI) WaitEvents() {
|
||||
C.WaitEvents()
|
||||
}
|
||||
|
||||
func (ui *UI) DrawGame(game ebiten.Game) {
|
||||
ui.lock.Lock()
|
||||
defer ui.lock.Unlock()
|
||||
ui.funcsExecutedOnMainThread = append(ui.funcsExecutedOnMainThread, func() {
|
||||
ui.graphicsDevice.Update(game.Draw)
|
||||
})
|
||||
func (ui *UI) InitTextures(game ebiten.Game) {
|
||||
C.BeginDrawing()
|
||||
game.InitTextures(ui.graphicsDevice.TextureFactory())
|
||||
C.EndDrawing()
|
||||
}
|
||||
|
||||
func (ui *UI) Draw(f func(graphics.Context)) {
|
||||
C.BeginDrawing()
|
||||
ui.graphicsDevice.Update(f)
|
||||
C.EndDrawing()
|
||||
}
|
||||
|
||||
//export ebiten_EbitenOpenGLView_Initialized
|
||||
@ -127,7 +130,6 @@ func ebiten_EbitenOpenGLView_Initialized() {
|
||||
if currentUI.graphicsDevice != nil {
|
||||
panic("The graphics device is already initialized")
|
||||
}
|
||||
|
||||
currentUI.graphicsDevice = opengl.NewDevice(
|
||||
currentUI.screenWidth,
|
||||
currentUI.screenHeight,
|
||||
@ -136,16 +138,6 @@ func ebiten_EbitenOpenGLView_Initialized() {
|
||||
|
||||
//export ebiten_EbitenOpenGLView_Updating
|
||||
func ebiten_EbitenOpenGLView_Updating() {
|
||||
currentUI.lock.Lock()
|
||||
defer currentUI.lock.Unlock()
|
||||
for _, f := range currentUI.funcsExecutedOnMainThread {
|
||||
f()
|
||||
}
|
||||
currentUI.funcsExecutedOnMainThread = currentUI.funcsExecutedOnMainThread[0:0]
|
||||
|
||||
game := <-currentUI.updating
|
||||
currentUI.graphicsDevice.Update(game.Draw)
|
||||
currentUI.updated <- game
|
||||
}
|
||||
|
||||
//export ebiten_EbitenOpenGLView_InputUpdated
|
||||
|
@ -13,7 +13,7 @@ void ebiten_EbitenOpenGLView_InputUpdated(InputType inputType, int x, int y);
|
||||
|
||||
// TODO: Use NSViewController?
|
||||
|
||||
static CVReturn
|
||||
/*static CVReturn
|
||||
EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
CVTimeStamp const* now,
|
||||
CVTimeStamp const* outputTime,
|
||||
@ -28,19 +28,26 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
EbitenOpenGLView* view = (__bridge EbitenOpenGLView*)displayLinkContext;
|
||||
return [view getFrameForTime:outputTime];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@implementation EbitenOpenGLView {
|
||||
@private
|
||||
CVDisplayLinkRef displayLink_;
|
||||
/*@private
|
||||
CVDisplayLinkRef displayLink_;*/
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
/*- (void)dealloc {
|
||||
CVDisplayLinkRelease(self->displayLink_);
|
||||
// Do not call [super dealloc] because of ARC.
|
||||
}
|
||||
#if !__has_feature(objc_arc)
|
||||
[super dealloc];
|
||||
#endif
|
||||
}*/
|
||||
|
||||
- (void)prepareOpenGL {
|
||||
/*- (void)prepareOpenGL {
|
||||
[super prepareOpenGL];
|
||||
ebiten_EbitenOpenGLView_Initialized();
|
||||
}*/
|
||||
|
||||
/*- (void)prepareOpenGL {
|
||||
[super prepareOpenGL];
|
||||
NSOpenGLContext* openGLContext = [self openGLContext];
|
||||
assert(openGLContext != nil);
|
||||
@ -60,9 +67,9 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
CVDisplayLinkStart(self->displayLink_);
|
||||
|
||||
ebiten_EbitenOpenGLView_Initialized();
|
||||
}
|
||||
}*/
|
||||
|
||||
- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime {
|
||||
/*- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime {
|
||||
(void)outputTime;
|
||||
NSOpenGLContext* context = [self openGLContext];
|
||||
assert(context != nil);
|
||||
@ -74,7 +81,7 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
CGLUnlockContext((CGLContextObj)[context CGLContextObj]);
|
||||
}
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
}*/
|
||||
|
||||
- (BOOL)isFlipped {
|
||||
return YES;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
@interface EbitenOpenGLView : NSOpenGLView
|
||||
|
||||
- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime;
|
||||
//- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -2,9 +2,16 @@
|
||||
|
||||
#import "ebiten_window.h"
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#import "ebiten_opengl_view.h"
|
||||
|
||||
void ebiten_EbitenOpenGLView_Initialized(void);
|
||||
|
||||
@implementation EbitenWindow
|
||||
{
|
||||
NSOpenGLContext* glContext_;
|
||||
}
|
||||
|
||||
- (id)initWithSize:(NSSize)size {
|
||||
NSUInteger style = (NSTitledWindowMask | NSClosableWindowMask |
|
||||
@ -31,6 +38,20 @@
|
||||
[self setDocumentEdited:YES];
|
||||
|
||||
NSRect rect = NSMakeRect(0, 0, size.width, size.height);
|
||||
NSView* contentView = [[NSView alloc] initWithFrame:rect];
|
||||
[self setContentView:contentView];
|
||||
|
||||
return self;
|
||||
|
||||
/*EbitenOpenGLView* contentView =
|
||||
[[EbitenOpenGLView alloc] initWithFrame:rect
|
||||
pixelFormat:format];*/
|
||||
}
|
||||
|
||||
- (NSOpenGLContext*)glContext {
|
||||
if (self->glContext_ != nil)
|
||||
return self->glContext_;
|
||||
|
||||
NSOpenGLPixelFormatAttribute attributes[] = {
|
||||
NSOpenGLPFAWindow,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
@ -40,11 +61,15 @@
|
||||
};
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes:attributes];
|
||||
EbitenOpenGLView* glView =
|
||||
[[EbitenOpenGLView alloc] initWithFrame:rect
|
||||
pixelFormat:format];
|
||||
[self setContentView:glView];
|
||||
return self;
|
||||
self->glContext_ = [[NSOpenGLContext alloc] initWithFormat:format
|
||||
shareContext:nil];
|
||||
[self->glContext_ setView:[self contentView]];
|
||||
[self->glContext_ makeCurrentContext];
|
||||
ebiten_EbitenOpenGLView_Initialized();
|
||||
|
||||
[format release];
|
||||
|
||||
return self->glContext_;
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender {
|
||||
@ -60,6 +85,7 @@
|
||||
modalDelegate:self
|
||||
didEndSelector:selector
|
||||
contextInfo:nil];
|
||||
[alert release];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
@ -74,5 +100,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
- (void)beginDrawing {
|
||||
[[self glContext] makeCurrentContext];
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
- (void)endDrawing {
|
||||
[[self glContext] flushBuffer];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -12,6 +12,8 @@
|
||||
returnCode:(NSInteger)returnCode
|
||||
contextInfo:(void*)contextInfo;
|
||||
- (BOOL)windowShouldClose:(id)sender;
|
||||
- (void)beginDrawing;
|
||||
- (void)endDrawing;
|
||||
|
||||
@end
|
||||
|
||||
|
45
ui/cocoa/mainloop.c
Normal file
45
ui/cocoa/mainloop.c
Normal file
@ -0,0 +1,45 @@
|
||||
// -*- objc -*-
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#import "ebiten_controller.h"
|
||||
#import "ebiten_window.h"
|
||||
|
||||
static EbitenWindow* currentWindow = 0;
|
||||
|
||||
void Start(size_t width, size_t height, size_t scale, const char* title) {
|
||||
NSSize size = NSMakeSize(width * scale, height * scale);
|
||||
EbitenWindow* window = [[EbitenWindow alloc]
|
||||
initWithSize:size];
|
||||
[window setTitle: [[NSString alloc] initWithUTF8String:title]];
|
||||
EbitenController* controller = [[EbitenController alloc]
|
||||
initWithWindow:window];
|
||||
NSApplication* app = [NSApplication sharedApplication];
|
||||
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
[app setDelegate:controller];
|
||||
[app finishLaunching];
|
||||
[app activateIgnoringOtherApps:YES];
|
||||
|
||||
currentWindow = window;
|
||||
}
|
||||
|
||||
void WaitEvents(void) {
|
||||
for (;;) {
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
if (event == nil) {
|
||||
break;
|
||||
}
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
}
|
||||
|
||||
void BeginDrawing(void) {
|
||||
[currentWindow beginDrawing];
|
||||
}
|
||||
|
||||
void EndDrawing(void) {
|
||||
[currentWindow endDrawing];
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// -*- objc -*-
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#import "ebiten_controller.h"
|
||||
#import "ebiten_window.h"
|
||||
|
||||
void Run(size_t width, size_t height, size_t scale, const char* title) {
|
||||
@autoreleasepool {
|
||||
NSSize size = NSMakeSize(width * scale, height * scale);
|
||||
EbitenWindow* window = [[EbitenWindow alloc]
|
||||
initWithSize:size];
|
||||
[window setTitle: [[NSString alloc] initWithUTF8String:title]];
|
||||
EbitenController* controller = [[EbitenController alloc]
|
||||
initWithWindow:window];
|
||||
NSApplication* app = [NSApplication sharedApplication];
|
||||
[app setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
[app setDelegate:controller];
|
||||
[app finishLaunching];
|
||||
[app activateIgnoringOtherApps:YES];
|
||||
[app run];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user