Add cocoa.textureFactory

This commit is contained in:
Hajime Hoshi 2013-12-07 02:20:48 +09:00
parent 24a735dd0b
commit e55060c239
10 changed files with 213 additions and 85 deletions

View File

@ -79,7 +79,6 @@ func New() *Sprites {
func (game *Sprites) OnScreenSizeUpdated(e ui.ScreenSizeUpdatedEvent) {
go func() {
e := e
game.screenSizeUpdatedCh <- e
}()
}

View File

@ -57,7 +57,11 @@ func main() {
const fps = 60
const title = "Ebiten Demo"
var u ui.UI = cocoa.New(screenWidth, screenHeight, screenScale, title)
type UI interface {
ui.UI
//graphics.TextureFactory
}
var u UI = cocoa.New(screenWidth, screenHeight, screenScale, title)
// TODO: Get a map or something
u.LoadResources(game.InitTextures)
inputStateUpdated := u.InputStateUpdated()
@ -72,10 +76,9 @@ func main() {
case e, ok := <-inputStateUpdated:
// TODO: Use Adaptor?
if ok {
type Handler interface {
if game2, ok := game.(interface {
OnInputStateUpdated(ui.InputStateUpdatedEvent)
}
if game2, ok := game.(Handler); ok {
}); ok {
game2.OnInputStateUpdated(e)
}
} else {
@ -83,10 +86,9 @@ func main() {
}
case e, ok := <-screenSizeUpdated:
if ok {
type Handler interface {
if game2, ok := game.(interface {
OnScreenSizeUpdated(ui.ScreenSizeUpdatedEvent)
}
if game2, ok := game.(Handler); ok {
}); ok {
game2.OnScreenSizeUpdated(e)
}
} else {

View File

@ -3,6 +3,7 @@ package opengl
import (
"github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/matrix"
"image"
)
type Device struct {
@ -18,8 +19,8 @@ func NewDevice(screenWidth, screenHeight, screenScale int) *Device {
}
}
func (device *Device) Update(draw func(graphics.Canvas)) {
context := device.context
func (d *Device) Update(draw func(graphics.Canvas)) {
context := d.context
context.Init()
context.ResetOffscreen()
context.Clear()
@ -30,7 +31,7 @@ func (device *Device) Update(draw func(graphics.Canvas)) {
context.setMainFramebufferOffscreen()
context.Clear()
scale := float64(device.screenScale)
scale := float64(d.screenScale)
geometryMatrix := matrix.IdentityGeometry()
geometryMatrix.Scale(scale, scale)
context.DrawRenderTarget(context.screenId,
@ -38,6 +39,10 @@ func (device *Device) Update(draw func(graphics.Canvas)) {
context.flush()
}
func (device *Device) TextureFactory() graphics.TextureFactory {
return device.context
func (d *Device) CreateRenderTarget(tag string, width, height int) (graphics.RenderTargetId, error) {
return d.context.CreateRenderTarget(tag, width, height)
}
func (d *Device) CreateTextureFromImage(tag string, img image.Image) (graphics.TextureId, error) {
return d.context.CreateTextureFromImage(tag, img)
}

View File

@ -21,6 +21,13 @@ type TextureFactoryEvents interface {
RenderTargetCreated() <-chan RenderTargetCreatedEvent
}
// TODO: Rename this later
type TextureFactory2 interface {
CreateRenderTarget(tag string, width, height int)
CreateTexture(tag string, img image.Image)
TextureFactoryEvents
}
type TextureFactory interface {
CreateRenderTarget(tag string, width, height int) (RenderTargetId, error)
CreateTextureFromImage(tag string, img image.Image) (TextureId, error)

View File

@ -3,13 +3,9 @@ package cocoa
// #cgo CFLAGS: -x objective-c
// #cgo LDFLAGS: -framework Cocoa -framework OpenGL
//
// #include <stdlib.h>
// #include "input.h"
//
// void StartApplication(void);
// void* CreateGLContext(void* sharedGLContext);
// void SetCurrentGLContext(void* glContext);
// void* CreateWindow(size_t width, size_t height, const char* title, void* sharedGLContext);
// void PollEvents(void);
// void BeginDrawing(void* window);
// void EndDrawing(void* window);
@ -19,18 +15,19 @@ import (
"github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/graphics/opengl"
"github.com/hajimehoshi/go-ebiten/ui"
"image"
"unsafe"
)
type UI struct {
screenWidth int
screenHeight int
screenScale int
graphicsDevice *opengl.Device
window unsafe.Pointer
initialEventSent bool
screenSizeUpdated chan ui.ScreenSizeUpdatedEvent // initialized lazily
inputStateUpdated chan ui.InputStateUpdatedEvent // initialized lazily
screenWidth int
screenHeight int
screenScale int
graphicsDevice *opengl.Device
window unsafe.Pointer
initialEventSent bool
textureFactory *textureFactory
uiEvents
}
var currentUI *UI
@ -46,22 +43,22 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
initialEventSent: false,
}
cTitle := C.CString(title)
defer C.free(unsafe.Pointer(cTitle))
C.StartApplication()
context := C.CreateGLContext(unsafe.Pointer(nil))
C.SetCurrentGLContext(context)
u.graphicsDevice = opengl.NewDevice(
u.screenWidth,
u.screenHeight,
u.screenScale)
u.textureFactory = runTextureFactory()
u.textureFactory.UseContext(func() {
u.graphicsDevice = opengl.NewDevice(
u.screenWidth,
u.screenHeight,
u.screenScale)
})
u.window = u.textureFactory.CreateWindow(
u.screenWidth*u.screenScale,
u.screenHeight*u.screenScale,
title)
u.window = C.CreateWindow(C.size_t(u.screenWidth*u.screenScale),
C.size_t(u.screenHeight*u.screenScale),
cTitle,
context)
currentUI = u
return u
@ -71,19 +68,20 @@ func (u *UI) PollEvents() {
C.PollEvents()
if !u.initialEventSent {
e := ui.ScreenSizeUpdatedEvent{u.screenWidth, u.screenHeight}
u.notifyScreenSizeUpdated(e)
u.uiEvents.notifyScreenSizeUpdated(e)
u.initialEventSent = true
}
}
func (u *UI) LoadTextures(map[int]string) {
// TODO: Implement
func (u *UI) CreateRenderTarget(tag string, width, height int) {
}
func (u *UI) CreateTexture(tag string, img image.Image) {
}
func (u *UI) LoadResources(f func(graphics.TextureFactory)) {
C.BeginDrawing(u.window)
// This should be executed on the shared-context context
f(u.graphicsDevice)
C.EndDrawing(u.window)
}
func (u *UI) Draw(f func(graphics.Canvas)) {
@ -92,45 +90,11 @@ func (u *UI) Draw(f func(graphics.Canvas)) {
C.EndDrawing(u.window)
}
func (u *UI) ScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent {
if u.screenSizeUpdated != nil {
return u.screenSizeUpdated
}
u.screenSizeUpdated = make(chan ui.ScreenSizeUpdatedEvent)
return u.screenSizeUpdated
}
func (u *UI) notifyScreenSizeUpdated(e ui.ScreenSizeUpdatedEvent) {
if u.screenSizeUpdated == nil {
return
}
go func() {
u.screenSizeUpdated <- e
}()
}
func (u *UI) InputStateUpdated() <-chan ui.InputStateUpdatedEvent {
if u.inputStateUpdated != nil {
return u.inputStateUpdated
}
u.inputStateUpdated = make(chan ui.InputStateUpdatedEvent)
return u.inputStateUpdated
}
func (u *UI) notifyInputStateUpdated(e ui.InputStateUpdatedEvent) {
if u.inputStateUpdated == nil {
return
}
go func() {
u.inputStateUpdated <- e
}()
}
//export ebiten_ScreenSizeUpdated
func ebiten_ScreenSizeUpdated(width, height int) {
u := currentUI
e := ui.ScreenSizeUpdatedEvent{width, height}
u.notifyScreenSizeUpdated(e)
u.uiEvents.notifyScreenSizeUpdated(e)
}
//export ebiten_InputUpdated
@ -139,7 +103,7 @@ func ebiten_InputUpdated(inputType C.InputType, cx, cy C.int) {
if inputType == C.InputTypeMouseUp {
e := ui.InputStateUpdatedEvent{-1, -1}
u.notifyInputStateUpdated(e)
u.uiEvents.notifyInputStateUpdated(e)
return
}
@ -157,5 +121,5 @@ func ebiten_InputUpdated(inputType C.InputType, cx, cy C.int) {
y = u.screenHeight - 1
}
e := ui.InputStateUpdatedEvent{x, y}
u.notifyInputStateUpdated(e)
u.uiEvents.notifyInputStateUpdated(e)
}

View File

@ -32,10 +32,6 @@ void* CreateGLContext(void* sharedGLContext) {
return glContext;
}
void SetCurrentGLContext(void* glContext) {
[(NSOpenGLContext*)glContext makeCurrentContext];
}
void* CreateWindow(size_t width, size_t height, const char* title, void* sharedGLContext) {
NSOpenGLContext* glContext = CreateGLContext(sharedGLContext);
[glContext makeCurrentContext];
@ -66,7 +62,13 @@ void PollEvents(void) {
}
}
void UseGLContext(void* glContext) {
// TODO: CGLLock
[(NSOpenGLContext*)glContext makeCurrentContext];
}
void BeginDrawing(void* window) {
// TODO: CGLLock
[[(EbitenWindow*)window glContext] makeCurrentContext];
glClear(GL_COLOR_BUFFER_BIT);
}

View File

@ -0,0 +1,62 @@
package cocoa
// #include <stdlib.h>
//
// void* CreateGLContext(void* sharedGLContext);
// void* CreateWindow(size_t width, size_t height, const char* title, void* sharedGLContext);
// void UseGLContext(void* glContext);
//
import "C"
import (
//"github.com/hajimehoshi/go-ebiten/graphics"
"unsafe"
)
type textureFactory struct {
sharedContext unsafe.Pointer
funcs chan func()
funcsDone chan struct{}
textureFactoryEvents
}
func runTextureFactory() *textureFactory {
t := &textureFactory{
funcs: make(chan func()),
funcsDone: make(chan struct{}),
}
ch := make(chan struct{})
go func() {
t.sharedContext = C.CreateGLContext(unsafe.Pointer(nil))
close(ch)
t.loop()
}()
<-ch
return t
}
func (t *textureFactory) loop() {
for {
select {
case f := <-t.funcs:
C.UseGLContext(t.sharedContext)
f()
t.funcsDone <- struct{}{}
// TODO: Unuse
}
}
}
func (t *textureFactory) UseContext(f func()) {
t.funcs <- f
<-t.funcsDone
}
func (t *textureFactory) CreateWindow(width, height int, title string) unsafe.Pointer {
cTitle := C.CString(title)
defer C.free(unsafe.Pointer(cTitle))
return C.CreateWindow(C.size_t(width),
C.size_t(height),
cTitle,
t.sharedContext)
}

View File

@ -0,0 +1,44 @@
package cocoa
import (
"github.com/hajimehoshi/go-ebiten/graphics"
)
type textureFactoryEvents struct {
textureCreated chan graphics.TextureCreatedEvent
renderTargetCreated chan graphics.RenderTargetCreatedEvent
}
func (t *textureFactoryEvents) TextureCreated() <-chan graphics.TextureCreatedEvent {
if t.textureCreated != nil {
return t.textureCreated
}
t.textureCreated = make(chan graphics.TextureCreatedEvent)
return t.textureCreated
}
func (t *textureFactoryEvents) notifyTextureCreated(e graphics.TextureCreatedEvent) {
if t.textureCreated == nil {
return
}
go func() {
t.textureCreated <- e
}()
}
func (t *textureFactoryEvents) RenderTargetCreated() <-chan graphics.RenderTargetCreatedEvent {
if t.renderTargetCreated != nil {
return t.renderTargetCreated
}
t.renderTargetCreated = make(chan graphics.RenderTargetCreatedEvent)
return t.renderTargetCreated
}
func (t *textureFactoryEvents) notifyRenderTargetCreated(e graphics.RenderTargetCreatedEvent) {
if t.renderTargetCreated == nil {
return
}
go func() {
t.renderTargetCreated <- e
}()
}

44
ui/cocoa/ui_events.go Normal file
View File

@ -0,0 +1,44 @@
package cocoa
import (
"github.com/hajimehoshi/go-ebiten/ui"
)
type uiEvents struct {
screenSizeUpdated chan ui.ScreenSizeUpdatedEvent // initialized lazily
inputStateUpdated chan ui.InputStateUpdatedEvent // initialized lazily
}
func (u *uiEvents) ScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent {
if u.screenSizeUpdated != nil {
return u.screenSizeUpdated
}
u.screenSizeUpdated = make(chan ui.ScreenSizeUpdatedEvent)
return u.screenSizeUpdated
}
func (u *uiEvents) notifyScreenSizeUpdated(e ui.ScreenSizeUpdatedEvent) {
if u.screenSizeUpdated == nil {
return
}
go func() {
u.screenSizeUpdated <- e
}()
}
func (u *uiEvents) InputStateUpdated() <-chan ui.InputStateUpdatedEvent {
if u.inputStateUpdated != nil {
return u.inputStateUpdated
}
u.inputStateUpdated = make(chan ui.InputStateUpdatedEvent)
return u.inputStateUpdated
}
func (u *uiEvents) notifyInputStateUpdated(e ui.InputStateUpdatedEvent) {
if u.inputStateUpdated == nil {
return
}
go func() {
u.inputStateUpdated <- e
}()
}

View File

@ -22,7 +22,6 @@ type UIEvents interface {
type UI interface {
PollEvents()
LoadResources(func(graphics.TextureFactory))
LoadTextures(map[int]string)
Draw(func(graphics.Canvas))
UIEvents
}