diff --git a/example/main.go b/example/main.go index 3197f7c63..8a990d9e9 100644 --- a/example/main.go +++ b/example/main.go @@ -12,6 +12,7 @@ import ( "github.com/hajimehoshi/go-ebiten/ui/cocoa" "os" "runtime" + "time" ) func main() { @@ -47,10 +48,18 @@ func main() { const screenScale = 2 const title = "Ebiten Demo" ui := cocoa.New(screenWidth, screenHeight, screenScale, title) - ui.Start(game) - ui.InitTextures(game) + ui.Start() + ui.InitTextures(game.InitTextures) + + frameTime := time.Duration(int64(time.Second) / int64(ebiten.FPS)) + tick := time.Tick(frameTime) for { - ui.WaitEvents() + ui.PollEvents() + select { + case <-tick: + ui.Update(game.Update) + default: + } ui.Draw(game.Draw) } } diff --git a/ui/cocoa/cocoa.go b/ui/cocoa/cocoa.go index 42cb244cc..c57df4f86 100644 --- a/ui/cocoa/cocoa.go +++ b/ui/cocoa/cocoa.go @@ -1,13 +1,13 @@ package cocoa // #cgo CFLAGS: -x objective-c -// #cgo LDFLAGS: -framework Cocoa -framework OpenGL -framework QuartzCore -// +// #cgo LDFLAGS: -framework Cocoa -framework OpenGL +// // #include // #include "input.h" // // void Start(size_t width, size_t height, size_t scale, const char* title); -// void WaitEvents(void); +// void PollEvents(void); // void BeginDrawing(void); // void EndDrawing(void); // @@ -18,7 +18,6 @@ import ( "github.com/hajimehoshi/go-ebiten/graphics/opengl" "runtime" "sync" - "time" "unsafe" ) @@ -45,16 +44,13 @@ func (context *GameContext) InputState() ebiten.InputState { } type UI struct { - 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 + screenWidth int + screenHeight int + screenScale int + title string + graphicsDevice *opengl.Device + lock sync.Mutex + gameContext *GameContext } var currentUI *UI @@ -64,13 +60,10 @@ 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 struct{}), - updated: make(chan struct{}), - input: make(chan ebiten.InputState), + screenWidth: screenWidth, + screenHeight: screenHeight, + screenScale: screenScale, + title: title, gameContext: &GameContext{ screenWidth: screenWidth, screenHeight: screenHeight, @@ -81,24 +74,7 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI { return ui } -func (ui *UI) gameMainLoop(game ebiten.Game) { - frameTime := time.Duration(int64(time.Second) / int64(ebiten.FPS)) - tick := time.Tick(frameTime) - for { - select { - case ui.gameContext.inputState = <-ui.input: - case <-tick: - game.Update(ui.gameContext) - case ui.updating <- struct{}{}: - //ui.DrawGame(game) - <-ui.updated - } - } -} - -func (ui *UI) Start(game ebiten.Game) { - go ui.gameMainLoop(game) - +func (ui *UI) Start() { cTitle := C.CString(ui.title) defer C.free(unsafe.Pointer(cTitle)) @@ -106,19 +82,23 @@ func (ui *UI) Start(game ebiten.Game) { C.size_t(ui.screenHeight), C.size_t(ui.screenScale), cTitle) - C.WaitEvents() + C.PollEvents() } -func (ui *UI) WaitEvents() { - C.WaitEvents() +func (ui *UI) PollEvents() { + C.PollEvents() } -func (ui *UI) InitTextures(game ebiten.Game) { +func (ui *UI) InitTextures(f func(graphics.TextureFactory)) { C.BeginDrawing() - game.InitTextures(ui.graphicsDevice.TextureFactory()) + f(ui.graphicsDevice.TextureFactory()) C.EndDrawing() } +func (ui *UI) Update(f func(ebiten.GameContext)) { + f(ui.gameContext) +} + func (ui *UI) Draw(f func(graphics.Context)) { C.BeginDrawing() ui.graphicsDevice.Update(f) @@ -136,14 +116,10 @@ func ebiten_EbitenOpenGLView_Initialized() { currentUI.screenScale) } -//export ebiten_EbitenOpenGLView_Updating -func ebiten_EbitenOpenGLView_Updating() { -} - //export ebiten_EbitenOpenGLView_InputUpdated func ebiten_EbitenOpenGLView_InputUpdated(inputType C.InputType, cx, cy C.int) { if inputType == C.InputTypeMouseUp { - currentUI.input <- ebiten.InputState{-1, -1} + currentUI.gameContext.inputState = ebiten.InputState{-1, -1} return } @@ -160,5 +136,5 @@ func ebiten_EbitenOpenGLView_InputUpdated(inputType C.InputType, cx, cy C.int) { } else if currentUI.screenHeight <= y { y = currentUI.screenHeight - 1 } - currentUI.input <- ebiten.InputState{x, y} + currentUI.gameContext.inputState = ebiten.InputState{x, y} } diff --git a/ui/cocoa/ebiten_content_view.c b/ui/cocoa/ebiten_content_view.c new file mode 100644 index 000000000..215523ce1 --- /dev/null +++ b/ui/cocoa/ebiten_content_view.c @@ -0,0 +1,40 @@ +// -*- objc -*- + +#include "ebiten_content_view.h" +#include "input.h" + +void ebiten_EbitenOpenGLView_InputUpdated(InputType inputType, int x, int y); + +@implementation EbitenContentView { +} + +- (BOOL)isFlipped { + return YES; +} + +- (void)mouseDown:(NSEvent*)theEvent { + NSPoint location = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + int x = location.x; + int y = location.y; + ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseDown, x, y); +} + +- (void)mouseUp:(NSEvent*)theEvent { + (void)theEvent; + NSPoint location = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + int x = location.x; + int y = location.y; + ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseUp, x, y); +} + +- (void)mouseDragged:(NSEvent*)theEvent { + NSPoint location = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + int x = location.x; + int y = location.y; + ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseDragged, x, y); +} + +@end diff --git a/ui/cocoa/ebiten_opengl_view.h b/ui/cocoa/ebiten_content_view.h similarity index 64% rename from ui/cocoa/ebiten_opengl_view.h rename to ui/cocoa/ebiten_content_view.h index d395bdcfd..bd4e69cea 100644 --- a/ui/cocoa/ebiten_opengl_view.h +++ b/ui/cocoa/ebiten_content_view.h @@ -6,9 +6,7 @@ #import #import -@interface EbitenOpenGLView : NSOpenGLView - -//- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime; +@interface EbitenContentView : NSView @end diff --git a/ui/cocoa/ebiten_opengl_view.c b/ui/cocoa/ebiten_opengl_view.c deleted file mode 100644 index 801313639..000000000 --- a/ui/cocoa/ebiten_opengl_view.c +++ /dev/null @@ -1,115 +0,0 @@ -// -*- objc -*- - -#include "ebiten_opengl_view.h" -#include "input.h" - -void ebiten_EbitenOpenGLView_Initialized(void); -void ebiten_EbitenOpenGLView_Updating(void); -void ebiten_EbitenOpenGLView_InputUpdated(InputType inputType, int x, int y); - -// Reference: -// http://developer.apple.com/library/mac/#qa/qa1385/_index.html -// http://www.alecjacobson.com/weblog/?p=2185 - -// TODO: Use NSViewController? - -/*static CVReturn -EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink, - CVTimeStamp const* now, - CVTimeStamp const* outputTime, - CVOptionFlags flagsIn, - CVOptionFlags* flagsOut, - void* displayLinkContext) { - (void)displayLink; - (void)now; - (void)flagsIn; - (void)flagsOut; - @autoreleasepool { - EbitenOpenGLView* view = (__bridge EbitenOpenGLView*)displayLinkContext; - return [view getFrameForTime:outputTime]; - } - }*/ - -@implementation EbitenOpenGLView { - /*@private - CVDisplayLinkRef displayLink_;*/ -} - -/*- (void)dealloc { - CVDisplayLinkRelease(self->displayLink_); -#if !__has_feature(objc_arc) - [super dealloc]; -#endif -}*/ - -/*- (void)prepareOpenGL { - [super prepareOpenGL]; - ebiten_EbitenOpenGLView_Initialized(); - }*/ - -/*- (void)prepareOpenGL { - [super prepareOpenGL]; - NSOpenGLContext* openGLContext = [self openGLContext]; - assert(openGLContext != nil); - GLint swapInterval = 1; - [openGLContext setValues:&swapInterval - forParameter:NSOpenGLCPSwapInterval]; - CVDisplayLinkCreateWithActiveCGDisplays(&self->displayLink_); - CVDisplayLinkSetOutputCallback(self->displayLink_, - &EbitenDisplayLinkCallback, - (__bridge void*)self); - CGLContextObj cglContext = (CGLContextObj)[openGLContext CGLContextObj]; - CGLPixelFormatObj cglPixelFormat = - (CGLPixelFormatObj)[[self pixelFormat] CGLPixelFormatObj]; - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self->displayLink_, - cglContext, - cglPixelFormat); - CVDisplayLinkStart(self->displayLink_); - - ebiten_EbitenOpenGLView_Initialized(); - }*/ - -/*- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime { - (void)outputTime; - NSOpenGLContext* context = [self openGLContext]; - assert(context != nil); - [context makeCurrentContext]; - { - CGLLockContext((CGLContextObj)[context CGLContextObj]); - ebiten_EbitenOpenGLView_Updating(); - [context flushBuffer]; - CGLUnlockContext((CGLContextObj)[context CGLContextObj]); - } - return kCVReturnSuccess; - }*/ - -- (BOOL)isFlipped { - return YES; -} - -- (void)mouseDown:(NSEvent*)theEvent { - NSPoint location = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - int x = location.x; - int y = location.y; - ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseDown, x, y); -} - -- (void)mouseUp:(NSEvent*)theEvent { - (void)theEvent; - NSPoint location = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - int x = location.x; - int y = location.y; - ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseUp, x, y); -} - -- (void)mouseDragged:(NSEvent*)theEvent { - NSPoint location = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - int x = location.x; - int y = location.y; - ebiten_EbitenOpenGLView_InputUpdated(InputTypeMouseDragged, x, y); -} - -@end diff --git a/ui/cocoa/ebiten_window.c b/ui/cocoa/ebiten_window.c index 2fbac108a..dc3aa2ba7 100644 --- a/ui/cocoa/ebiten_window.c +++ b/ui/cocoa/ebiten_window.c @@ -4,7 +4,7 @@ #include -#import "ebiten_opengl_view.h" +#import "ebiten_content_view.h" void ebiten_EbitenOpenGLView_Initialized(void); @@ -38,14 +38,10 @@ void ebiten_EbitenOpenGLView_Initialized(void); [self setDocumentEdited:YES]; NSRect rect = NSMakeRect(0, 0, size.width, size.height); - NSView* contentView = [[NSView alloc] initWithFrame:rect]; + NSView* contentView = [[EbitenContentView alloc] initWithFrame:rect]; [self setContentView:contentView]; return self; - - /*EbitenOpenGLView* contentView = - [[EbitenOpenGLView alloc] initWithFrame:rect - pixelFormat:format];*/ } - (NSOpenGLContext*)glContext { diff --git a/ui/cocoa/mainloop.c b/ui/cocoa/mainloop.c index 6b55efd0b..66398e032 100644 --- a/ui/cocoa/mainloop.c +++ b/ui/cocoa/mainloop.c @@ -23,7 +23,7 @@ void Start(size_t width, size_t height, size_t scale, const char* title) { currentWindow = window; } -void WaitEvents(void) { +void PollEvents(void) { for (;;) { NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast]