mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
Implement ui.cocoa
This commit is contained in:
parent
54893c3031
commit
983aeec03b
@ -8,8 +8,8 @@ import (
|
||||
"github.com/hajimehoshi/go.ebiten/example/game/rects"
|
||||
"github.com/hajimehoshi/go.ebiten/example/game/rotating"
|
||||
"github.com/hajimehoshi/go.ebiten/example/game/sprites"
|
||||
_ "github.com/hajimehoshi/go.ebiten/ui/cocoa"
|
||||
"github.com/hajimehoshi/go.ebiten/ui/glut"
|
||||
"github.com/hajimehoshi/go.ebiten/ui/cocoa"
|
||||
_ "github.com/hajimehoshi/go.ebiten/ui/glut"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
@ -41,5 +41,5 @@ func main() {
|
||||
}
|
||||
|
||||
const screenScale = 2
|
||||
glut.Run(game, 256, 240, screenScale, "Ebiten Demo")
|
||||
cocoa.Run(game, 256, 240, screenScale, "Ebiten Demo")
|
||||
}
|
||||
|
@ -10,15 +10,112 @@ package cocoa
|
||||
import "C"
|
||||
import (
|
||||
"github.com/hajimehoshi/go.ebiten"
|
||||
_ "github.com/hajimehoshi/go.ebiten/graphics"
|
||||
_ "github.com/hajimehoshi/go.ebiten/graphics/opengl"
|
||||
// "github.com/hajimehoshi/go.ebiten/graphics"
|
||||
"github.com/hajimehoshi/go.ebiten/graphics/opengl"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type UI struct {
|
||||
game ebiten.Game
|
||||
screenWidth int
|
||||
screenHeight int
|
||||
screenScale int
|
||||
graphicsDevice *opengl.Device
|
||||
inited chan bool
|
||||
updating chan bool
|
||||
updated chan bool
|
||||
input chan ebiten.InputState
|
||||
}
|
||||
|
||||
var currentUI *UI
|
||||
|
||||
//export ebiten_EbitenOpenGLView_Initialized
|
||||
func ebiten_EbitenOpenGLView_Initialized() {
|
||||
if currentUI.graphicsDevice != nil {
|
||||
panic("The graphics device is already initialized")
|
||||
}
|
||||
|
||||
currentUI.graphicsDevice = opengl.NewDevice(
|
||||
currentUI.screenWidth,
|
||||
currentUI.screenHeight,
|
||||
currentUI.screenScale)
|
||||
currentUI.graphicsDevice.Init()
|
||||
|
||||
currentUI.game.Init(currentUI.graphicsDevice.TextureFactory())
|
||||
|
||||
currentUI.inited <- true
|
||||
}
|
||||
|
||||
//export ebiten_EbitenOpenGLView_Updating
|
||||
func ebiten_EbitenOpenGLView_Updating() {
|
||||
<-currentUI.updating
|
||||
currentUI.graphicsDevice.Update(currentUI.game.Draw)
|
||||
currentUI.updated <- true
|
||||
}
|
||||
|
||||
//export ebiten_EbitenOpenGLView_InputUpdated
|
||||
func ebiten_EbitenOpenGLView_InputUpdated(x, y C.int) {
|
||||
currentUI.input <- ebiten.InputState{int(x), int(y)}
|
||||
}
|
||||
|
||||
func Run(game ebiten.Game, screenWidth, screenHeight, screenScale int,
|
||||
title string) {
|
||||
cTitle := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(cTitle))
|
||||
|
||||
C.Run(C.size_t(screenWidth), C.size_t(screenHeight), C.size_t(screenScale), cTitle)
|
||||
currentUI = &UI{
|
||||
game: game,
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
screenScale: screenScale,
|
||||
inited: make(chan bool),
|
||||
updating: make(chan bool),
|
||||
updated: make(chan bool),
|
||||
input: make(chan ebiten.InputState),
|
||||
}
|
||||
|
||||
go func() {
|
||||
frameTime := time.Duration(
|
||||
int64(time.Second) / int64(ebiten.FPS))
|
||||
tick := time.Tick(frameTime)
|
||||
gameContext := &GameContext{
|
||||
screenWidth: screenWidth,
|
||||
screenHeight: screenHeight,
|
||||
inputState: ebiten.InputState{-1, -1},
|
||||
}
|
||||
<-currentUI.inited
|
||||
for {
|
||||
select {
|
||||
case gameContext.inputState = <-currentUI.input:
|
||||
case <-tick:
|
||||
game.Update(gameContext)
|
||||
case currentUI.updating <- true:
|
||||
<-currentUI.updated
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
C.Run(C.size_t(screenWidth),
|
||||
C.size_t(screenHeight),
|
||||
C.size_t(screenScale),
|
||||
cTitle)
|
||||
}
|
||||
|
||||
type GameContext struct {
|
||||
screenWidth int
|
||||
screenHeight int
|
||||
inputState ebiten.InputState
|
||||
}
|
||||
|
||||
func (context *GameContext) ScreenWidth() int {
|
||||
return context.screenWidth
|
||||
}
|
||||
|
||||
func (context *GameContext) ScreenHeight() int {
|
||||
return context.screenHeight
|
||||
}
|
||||
|
||||
func (context *GameContext) InputState() ebiten.InputState {
|
||||
return context.inputState
|
||||
}
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
#include "ebiten_opengl_view.h"
|
||||
|
||||
void ebiten_EbitenOpenGLView_Initialized(void);
|
||||
void ebiten_EbitenOpenGLView_Updating(void);
|
||||
void ebiten_EbitenOpenGLView_InputUpdated(int x, int y);
|
||||
|
||||
// Reference:
|
||||
// http://developer.apple.com/library/mac/#qa/qa1385/_index.html
|
||||
// http://www.alecjacobson.com/weblog/?p=2185
|
||||
@ -28,15 +32,9 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
@implementation EbitenOpenGLView {
|
||||
@private
|
||||
CVDisplayLinkRef displayLink_;
|
||||
updating* updating_;
|
||||
//ebiten::input* input_;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
if (self = [super init]) {
|
||||
self->updating_ = NULL;
|
||||
}
|
||||
return self;
|
||||
size_t screenWidth_;
|
||||
size_t screenHeight_;
|
||||
size_t screenScale_;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
@ -48,7 +46,7 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
[super prepareOpenGL];
|
||||
NSOpenGLContext* openGLContext = [self openGLContext];
|
||||
assert(openGLContext != nil);
|
||||
GLint const swapInterval = 1;
|
||||
GLint swapInterval = 1;
|
||||
[openGLContext setValues:&swapInterval
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&self->displayLink_);
|
||||
@ -62,40 +60,24 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
cglContext,
|
||||
cglPixelFormat);
|
||||
CVDisplayLinkStart(self->displayLink_);
|
||||
|
||||
ebiten_EbitenOpenGLView_Initialized();
|
||||
}
|
||||
|
||||
- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime {
|
||||
(void)outputTime;
|
||||
if (!self->updating_) {
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
NSOpenGLContext* context = [self openGLContext];
|
||||
assert(context != nil);
|
||||
[context makeCurrentContext];
|
||||
bool terminated = false;
|
||||
{
|
||||
CGLLockContext((CGLContextObj)[context CGLContextObj]);
|
||||
terminated = self->updating_();
|
||||
ebiten_EbitenOpenGLView_Updating();
|
||||
[context flushBuffer];
|
||||
CGLUnlockContext((CGLContextObj)[context CGLContextObj]);
|
||||
}
|
||||
if (terminated) {
|
||||
//CVDisplayLinkStop(self->displayLink_);
|
||||
[NSApp terminate:nil];
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
- (void)setUpdatingFunc:(updating*)func {
|
||||
self->updating_ = func;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - (void)setInput:(ebiten::input&)input {
|
||||
// self->input_ = &input;
|
||||
// }
|
||||
|
||||
- (BOOL)isFlipped {
|
||||
return YES;
|
||||
}
|
||||
@ -103,40 +85,50 @@ EbitenDisplayLinkCallback(CVDisplayLinkRef displayLink,
|
||||
- (void)mouseDown:(NSEvent*)theEvent {
|
||||
NSPoint location = [self convertPoint:[theEvent locationInWindow]
|
||||
fromView:nil];
|
||||
// TODO
|
||||
/*
|
||||
if (self->input_) {
|
||||
int x = location.x;
|
||||
int y = location.y;
|
||||
// TODO: Screen size
|
||||
self->input_->set_touches_real_location(0,
|
||||
static_cast<int>(x),
|
||||
static_cast<int>(y));
|
||||
self->input_->set_touched(0, true);
|
||||
}*/
|
||||
int x = location.x / self->screenScale_;
|
||||
int y = location.y / self->screenScale_;
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (self->screenWidth_<= x) {
|
||||
x = self->screenWidth_ - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
} else if (self->screenHeight_<= y) {
|
||||
y = self->screenHeight_ - 1;
|
||||
}
|
||||
ebiten_EbitenOpenGLView_InputUpdated(x, y);
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent*)theEvent {
|
||||
(void)theEvent;
|
||||
// TODO
|
||||
/*if (self->input_) {
|
||||
self->input_->set_touches_real_location(0, -1, -1);
|
||||
self->input_->set_touched(0, false);
|
||||
}*/
|
||||
ebiten_EbitenOpenGLView_InputUpdated(-1, -1);
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent*)theEvent {
|
||||
NSPoint location = [self convertPoint:[theEvent locationInWindow]
|
||||
fromView:nil];
|
||||
// TODO
|
||||
/*if (self->input_) {
|
||||
int x = location.x;
|
||||
int y = location.y;
|
||||
self->input_->set_touches_real_location(0,
|
||||
static_cast<int>(x),
|
||||
static_cast<int>(y));
|
||||
self->input_->set_touched(0, true);
|
||||
}*/
|
||||
int x = location.x / self->screenScale_;
|
||||
int y = location.y / self->screenScale_;
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (self->screenWidth_<= x) {
|
||||
x = self->screenWidth_ - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
} else if (self->screenHeight_<= y) {
|
||||
y = self->screenHeight_ - 1;
|
||||
}
|
||||
ebiten_EbitenOpenGLView_InputUpdated(x, y);
|
||||
}
|
||||
|
||||
- (void)setScreenWidth:(size_t)screenWidth
|
||||
screenHeight:(size_t)screenHeight
|
||||
screenScale:(size_t)screenScale {
|
||||
self->screenWidth_ = screenWidth;
|
||||
self->screenHeight_ = screenHeight;
|
||||
self->screenScale_ = screenScale;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -6,12 +6,12 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
typedef bool updating(void);
|
||||
|
||||
@interface EbitenOpenGLView : NSOpenGLView
|
||||
|
||||
- (CVReturn)getFrameForTime:(CVTimeStamp const*)outputTime;
|
||||
- (void)setUpdatingFunc:(updating*)updatingFunc;
|
||||
- (void)setScreenWidth:(size_t)screenWidth
|
||||
screenHeight:(size_t)screenHeight
|
||||
screenScale:(size_t)screenScale;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -6,12 +6,12 @@
|
||||
#import "ebiten_opengl_view.h"
|
||||
#import "ebiten_window.h"
|
||||
|
||||
static NSWindow* generateWindow(size_t width, size_t height) {
|
||||
static NSWindow* generateWindow(size_t width, size_t height, size_t scale, const char* title) {
|
||||
EbitenWindow* window = [[EbitenWindow alloc]
|
||||
initWithSize:NSMakeSize(width, height)];
|
||||
initWithSize:NSMakeSize(width * scale, height * scale)];
|
||||
assert(window != nil);
|
||||
|
||||
NSRect const rect = NSMakeRect(0, 0, width, height);
|
||||
NSRect const rect = NSMakeRect(0, 0, width * scale, height * scale);
|
||||
NSOpenGLPixelFormatAttribute const attributes[] = {
|
||||
NSOpenGLPFAWindow,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
@ -24,7 +24,11 @@ static NSWindow* generateWindow(size_t width, size_t height) {
|
||||
EbitenOpenGLView* glView =
|
||||
[[EbitenOpenGLView alloc] initWithFrame:rect
|
||||
pixelFormat:format];
|
||||
[glView setScreenWidth:width
|
||||
screenHeight:height
|
||||
screenScale:scale];
|
||||
[window setContentView:glView];
|
||||
[window setTitle: [[NSString alloc] initWithUTF8String:title]];
|
||||
//[window makeFirstResponder:glView];
|
||||
|
||||
return window;
|
||||
@ -32,7 +36,7 @@ static NSWindow* generateWindow(size_t width, size_t height) {
|
||||
|
||||
void Run(size_t width, size_t height, size_t scale, const char* title) {
|
||||
@autoreleasepool {
|
||||
NSWindow* window = generateWindow(width * scale, height * scale);
|
||||
NSWindow* window = generateWindow(width, height, scale, title);
|
||||
EbitenController* controller = [[EbitenController alloc]
|
||||
initWithWindow:window];
|
||||
NSApplication* app = [NSApplication sharedApplication];
|
||||
|
@ -78,13 +78,10 @@ func idle() {
|
||||
}
|
||||
|
||||
func new(screenWidth, screenHeight, screenScale int, title string) *GlutUI {
|
||||
graphicsDevice := opengl.NewDevice(
|
||||
screenWidth, screenHeight, screenScale)
|
||||
ui := &GlutUI{
|
||||
glutInputting: make(chan glutInputEvent, 10),
|
||||
graphicsDevice: graphicsDevice,
|
||||
updating: make(chan func(graphics.Context)),
|
||||
updated: make(chan bool),
|
||||
glutInputting: make(chan glutInputEvent, 10),
|
||||
updating: make(chan func(graphics.Context)),
|
||||
updated: make(chan bool),
|
||||
}
|
||||
|
||||
cargs := []*C.char{}
|
||||
@ -109,11 +106,6 @@ func new(screenWidth, screenHeight, screenScale int, title string) *GlutUI {
|
||||
defer C.free(unsafe.Pointer(cTitle))
|
||||
C.glutCreateWindow(cTitle)
|
||||
|
||||
// Set the callbacks
|
||||
C.setGlutFuncs()
|
||||
|
||||
graphicsDevice.Init()
|
||||
|
||||
return ui
|
||||
}
|
||||
|
||||
@ -121,6 +113,11 @@ func Run(game ebiten.Game, screenWidth, screenHeight, screenScale int, title str
|
||||
ui := new(screenWidth, screenHeight, screenScale, title)
|
||||
currentUI = ui
|
||||
|
||||
graphicsDevice := opengl.NewDevice(
|
||||
screenWidth, screenHeight, screenScale)
|
||||
ui.graphicsDevice = graphicsDevice
|
||||
graphicsDevice.Init()
|
||||
|
||||
game.Init(ui.graphicsDevice.TextureFactory())
|
||||
|
||||
input := make(chan ebiten.InputState)
|
||||
@ -170,6 +167,9 @@ func Run(game ebiten.Game, screenWidth, screenHeight, screenScale int, title str
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
// Set the callbacks
|
||||
C.setGlutFuncs()
|
||||
|
||||
C.glutMainLoop()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user