allg5/display.go

171 lines
3.9 KiB
Go

package allg5
// #include <allegro5/allegro.h>
import "C"
import (
"errors"
"sort"
"unsafe"
)
// Display represents a display.
type Display struct {
display *C.ALLEGRO_DISPLAY
}
// DisplayMode contains information about a fullscreen display mode.
type DisplayMode struct {
Width int
Height int
Format PixelFormat
RefreshRate int
}
// DisplayMode returns all available fullscreen display modes.
func DisplayModes() []DisplayMode {
n := int(C.al_get_num_display_modes())
var modes []DisplayMode
var mode C.ALLEGRO_DISPLAY_MODE
for i := 0; i < n; i++ {
C.al_get_display_mode(C.int(i), &mode)
modes = append(modes, DisplayMode{
Width: int(mode.width),
Height: int(mode.height),
Format: PixelFormat(mode.format),
RefreshRate: int(mode.refresh_rate),
})
}
weight := func(m DisplayMode) int { return (m.Width*m.Height)*10000 + (m.RefreshRate * 100) + int(m.Format) }
sort.Slice(modes, func(i, j int) bool { return weight(modes[i]) < weight(modes[j]) })
return modes
}
// NewDisplayOptions sets options for creating a new display.
type NewDisplayOptions struct {
Fullscreen bool
Resizable bool
Windowed bool
Maximized bool
Frameless bool
Vsync bool
Shaders bool
OpenGL bool
}
// NewDisplay creates a display.
func NewDisplay(width, height int, options NewDisplayOptions) (*Display, error) {
var flags C.int = C.ALLEGRO_WINDOWED
if options.Fullscreen {
if options.Windowed {
flags |= C.ALLEGRO_FULLSCREEN_WINDOW
} else {
flags = C.ALLEGRO_FULLSCREEN
}
} else if options.Frameless {
flags |= C.ALLEGRO_FRAMELESS
}
if options.Resizable {
flags |= C.ALLEGRO_RESIZABLE
}
if options.Maximized {
flags |= C.ALLEGRO_MAXIMIZED
}
if options.Vsync {
C.al_set_new_display_option(C.ALLEGRO_VSYNC, 1, C.ALLEGRO_SUGGEST)
}
if options.OpenGL {
flags |= C.ALLEGRO_OPENGL
}
if options.Shaders {
flags |= C.ALLEGRO_PROGRAMMABLE_PIPELINE
}
C.al_set_new_display_flags(flags)
d := C.al_create_display(C.int(width), C.int(height))
if d == nil {
return nil, errors.New("error creating display")
}
return &Display{d}, nil
}
// Flip flips the buffer to the display
func (d *Display) Flip() {
C.al_flip_display()
}
func (d *Display) Width() int {
return int(C.al_get_display_width(d.display))
}
func (d *Display) Height() int {
return int(C.al_get_display_height(d.display))
}
func (d *Display) Position() (int, int) {
var x, y C.int
C.al_get_window_position(d.display, &x, &y)
return int(x), int(y)
}
func (d *Display) Resize(w, h int) {
C.al_resize_display(d.display, C.int(w), C.int(h))
}
func (d *Display) SetAsTarget() {
C.al_set_target_backbuffer(d.display)
}
func (d *Display) SetIcon(i ...*Bitmap) {
if len(i) == 0 {
return
}
if len(i) == 1 {
C.al_set_display_icon(d.display, i[0].bitmap)
return
}
icons := make([]*C.ALLEGRO_BITMAP, len(i))
for j := range icons {
icons[j] = i[j].bitmap
}
C.al_set_display_icons(d.display, C.int(len(icons)), &(icons[0]))
}
func (d *Display) SetMouseCursor(c MouseCursor) {
C.al_set_system_mouse_cursor(d.display, C.ALLEGRO_SYSTEM_MOUSE_CURSOR(c))
}
func (d *Display) SetMousePosition(x, y int) {
C.al_set_mouse_xy(d.display, C.int(x), C.int(y))
}
func (d *Display) SetPosition(x, y int) {
C.al_set_window_position(d.display, C.int(x), C.int(y))
}
func (d *Display) SetWindowTitle(title string) {
t := C.CString(title)
defer C.free(unsafe.Pointer(t))
C.al_set_window_title(d.display, t)
}
func (d *Display) Target() *Bitmap {
return &Bitmap{C.al_get_backbuffer(d.display), d.Width(), d.Height(), nil, nil}
}
// Destroy destroys the display
func (d *Display) Destroy() {
C.al_destroy_display(d.display)
}
func CurrentTarget() *Bitmap {
var bmp = C.al_get_target_bitmap()
return &Bitmap{bmp, int(C.al_get_bitmap_width(bmp)), int(C.al_get_bitmap_height(bmp)), nil, nil}
}
func SetNewWindowTitle(title string) {
t := C.CString(title)
defer C.free(unsafe.Pointer(t))
C.al_set_new_window_title(t)
}