Created new repository.
This commit is contained in:
commit
6151f28ef3
37
audio.go
Normal file
37
audio.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define ALLEGRO_KCM_AUDIO_SRC
|
||||||
|
|
||||||
|
#include <allegro5/allegro_audio.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type Recorder struct {
|
||||||
|
recorder *C.ALLEGRO_AUDIO_RECORDER
|
||||||
|
Frequency int
|
||||||
|
Depth int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRecorder(fragments, samples, frequency, depth int) *Recorder {
|
||||||
|
var depthC C.ALLEGRO_AUDIO_DEPTH
|
||||||
|
switch depth {
|
||||||
|
case 16:
|
||||||
|
depthC = C.ALLEGRO_AUDIO_DEPTH_INT16
|
||||||
|
default:
|
||||||
|
depthC = C.ALLEGRO_AUDIO_DEPTH_UINT8
|
||||||
|
}
|
||||||
|
var rec = C.al_create_audio_recorder(C.size_t(fragments), C.uint(samples), C.uint(frequency), depthC, C.ALLEGRO_CHANNEL_CONF_1)
|
||||||
|
if rec == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &Recorder{rec, frequency, depth}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Recorder) Start() {
|
||||||
|
C.al_start_audio_recorder(r.recorder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Recorder) Destroy() {
|
||||||
|
C.al_destroy_audio_recorder(r.recorder)
|
||||||
|
}
|
260
bitmap.go
Normal file
260
bitmap.go
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"image"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bitmap represents an in memory bitmap
|
||||||
|
type Bitmap struct {
|
||||||
|
bitmap *C.ALLEGRO_BITMAP
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
subs []*Bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
type DrawOptions struct {
|
||||||
|
Center bool
|
||||||
|
Scale *Scale
|
||||||
|
Tint *Color
|
||||||
|
Rotation *Rotation
|
||||||
|
}
|
||||||
|
|
||||||
|
type Scale struct {
|
||||||
|
Horizontal float32
|
||||||
|
Vertical float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewScale(hor, ver float32) *Scale {
|
||||||
|
return &Scale{hor, ver}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUniformScale(s float32) *Scale {
|
||||||
|
return &Scale{s, s}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rotation struct {
|
||||||
|
Angle float32
|
||||||
|
Center bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBitmap(width, height int, mut func(m FlagMutation), flags []NewBitmapFlag) (*Bitmap, error) {
|
||||||
|
var newBmpFlags = CaptureNewBitmapFlags()
|
||||||
|
defer newBmpFlags.Revert()
|
||||||
|
newBmpFlags.Mutate(func(m FlagMutation) {
|
||||||
|
if mut != nil {
|
||||||
|
mut(m)
|
||||||
|
}
|
||||||
|
for _, f := range flags {
|
||||||
|
m.Set(f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b := C.al_create_bitmap(C.int(width), C.int(height))
|
||||||
|
if b == nil {
|
||||||
|
return nil, errors.New("error creating bitmap")
|
||||||
|
}
|
||||||
|
return &Bitmap{b, width, height, nil}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBitmap creates a new bitmap of given width and height and optional flags
|
||||||
|
func NewBitmap(width, height int, flags ...NewBitmapFlag) (*Bitmap, error) {
|
||||||
|
return newBitmap(width, height, nil, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVideoBitmap creates a new video bitmap of given width and height and optional flags
|
||||||
|
func NewVideoBitmap(width, height int, flags ...NewBitmapFlag) (*Bitmap, error) {
|
||||||
|
return newBitmap(width, height, func(m FlagMutation) {
|
||||||
|
m.Unset(NewBitmapFlagMemoryBitmap)
|
||||||
|
m.Set(NewBitmapFlagVideoBitmap)
|
||||||
|
}, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMemoryBitmap creates a new video bitmap of given width and height and optional flags
|
||||||
|
func NewMemoryBitmap(width, height int, flags ...NewBitmapFlag) (*Bitmap, error) {
|
||||||
|
return newBitmap(width, height, func(m FlagMutation) {
|
||||||
|
m.Unset(NewBitmapFlagVideoBitmap)
|
||||||
|
m.Set(NewBitmapFlagMemoryBitmap)
|
||||||
|
}, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBitmapFromImage creates a new bitmap starting from a Go native image (image.Image)
|
||||||
|
func NewBitmapFromImage(src image.Image, video bool) (*Bitmap, error) {
|
||||||
|
var newBmpFlags = CaptureNewBitmapFlags()
|
||||||
|
defer newBmpFlags.Revert()
|
||||||
|
newBmpFlags.Mutate(func(m FlagMutation) {
|
||||||
|
m.Unset(NewBitmapFlagVideoBitmap)
|
||||||
|
m.Set(NewBitmapFlagMemoryBitmap)
|
||||||
|
m.Set(NewBitmapFlagMinLinear)
|
||||||
|
})
|
||||||
|
var bnd = src.Bounds()
|
||||||
|
width, height := bnd.Dx(), bnd.Dy()
|
||||||
|
var b = C.al_create_bitmap(C.int(width), C.int(height))
|
||||||
|
if b == nil {
|
||||||
|
return nil, errors.New("error creating memory bitmap")
|
||||||
|
}
|
||||||
|
region := C.al_lock_bitmap(b, C.ALLEGRO_PIXEL_FORMAT_ABGR_8888, C.ALLEGRO_LOCK_WRITEONLY)
|
||||||
|
if region == nil {
|
||||||
|
C.al_destroy_bitmap(b)
|
||||||
|
return nil, errors.New("unable to lock bitmap")
|
||||||
|
}
|
||||||
|
dst := (*[1 << 30]uint8)(region.data)
|
||||||
|
left, top := bnd.Min.X, bnd.Min.Y
|
||||||
|
for y := 0; y < height; y++ {
|
||||||
|
row := dst[y*int(region.pitch):]
|
||||||
|
for x := 0; x < width; x++ {
|
||||||
|
r, g, b, a := src.At(left+x, top+y).RGBA()
|
||||||
|
row[x*4] = uint8(r >> 8)
|
||||||
|
row[x*4+1] = uint8(g >> 8)
|
||||||
|
row[x*4+2] = uint8(b >> 8)
|
||||||
|
row[x*4+3] = uint8(a >> 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.al_unlock_bitmap(b)
|
||||||
|
if video {
|
||||||
|
newBmpFlags.Mutate(func(m FlagMutation) {
|
||||||
|
m.Unset(NewBitmapFlagMemoryBitmap)
|
||||||
|
m.Set(NewBitmapFlagVideoBitmap)
|
||||||
|
m.Set(NewBitmapFlagMinLinear)
|
||||||
|
})
|
||||||
|
C.al_convert_bitmap(b)
|
||||||
|
}
|
||||||
|
return &Bitmap{b, width, height, nil}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBitmap tries to load the image at the specified path as a bitmap
|
||||||
|
func LoadBitmap(path string) (*Bitmap, error) {
|
||||||
|
p := C.CString(path)
|
||||||
|
defer C.free(unsafe.Pointer(p))
|
||||||
|
b := C.al_load_bitmap(p)
|
||||||
|
if b == nil {
|
||||||
|
return nil, errors.New("error loading bitmap")
|
||||||
|
}
|
||||||
|
width := int(C.al_get_bitmap_width(b))
|
||||||
|
height := int(C.al_get_bitmap_height(b))
|
||||||
|
return &Bitmap{b, width, height, nil}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the bitmap at the given location
|
||||||
|
func (b *Bitmap) Draw(left, top float32) {
|
||||||
|
C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) DrawOptions(left, top float32, options DrawOptions) {
|
||||||
|
width := float32(b.width)
|
||||||
|
height := float32(b.height)
|
||||||
|
|
||||||
|
scale := options.Scale != nil
|
||||||
|
if scale {
|
||||||
|
width *= options.Scale.Horizontal
|
||||||
|
height *= options.Scale.Vertical
|
||||||
|
}
|
||||||
|
if options.Center {
|
||||||
|
left -= width * 0.5
|
||||||
|
top -= height * 0.5
|
||||||
|
}
|
||||||
|
rotated := options.Rotation != nil
|
||||||
|
var centerX C.float
|
||||||
|
var centerY C.float
|
||||||
|
if rotated && options.Rotation.Center {
|
||||||
|
centerX = C.float(b.width) * 0.5
|
||||||
|
centerY = C.float(b.height) * 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
if scale {
|
||||||
|
if options.Tint == nil { // scaled
|
||||||
|
if rotated { // scaled & rotated
|
||||||
|
C.al_draw_scaled_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal), C.float(options.Scale.Vertical), C.float(options.Rotation.Angle), 0)
|
||||||
|
} else { // scaled
|
||||||
|
C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
|
||||||
|
}
|
||||||
|
} else { // tinted & scaled
|
||||||
|
if rotated { // scaled, tinted & rotated
|
||||||
|
C.al_draw_tinted_scaled_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal), C.float(options.Scale.Vertical), C.float(options.Rotation.Angle), 0)
|
||||||
|
} else { // tinted, scaled
|
||||||
|
C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if options.Tint == nil {
|
||||||
|
if rotated { // rotated
|
||||||
|
C.al_draw_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0)
|
||||||
|
} else {
|
||||||
|
C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0)
|
||||||
|
}
|
||||||
|
} else { // tinted
|
||||||
|
if rotated { // tinted & rotated
|
||||||
|
C.al_draw_tinted_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0)
|
||||||
|
} else {
|
||||||
|
C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub creates a sub-bitmap of the original bitmap
|
||||||
|
func (b *Bitmap) Sub(x, y, w, h int) *Bitmap {
|
||||||
|
var sub = C.al_create_sub_bitmap(b.bitmap, C.int(x), C.int(y), C.int(w), C.int(h))
|
||||||
|
if sub == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var bmp = &Bitmap{sub, w, h, nil}
|
||||||
|
b.subs = append(b.subs, bmp)
|
||||||
|
return bmp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subs returns the slice of sub-bitmaps
|
||||||
|
func (b *Bitmap) Subs() []*Bitmap {
|
||||||
|
return b.subs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) Width() int {
|
||||||
|
return b.width
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) Height() int {
|
||||||
|
return b.height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) IsVideo() bool {
|
||||||
|
return C.al_get_bitmap_flags(b.bitmap)&C.ALLEGRO_VIDEO_BITMAP == C.ALLEGRO_VIDEO_BITMAP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) Image() image.Image {
|
||||||
|
im := image.NewRGBA(image.Rect(0, 0, b.width, b.height))
|
||||||
|
region := C.al_lock_bitmap(b.bitmap, C.ALLEGRO_PIXEL_FORMAT_ABGR_8888, C.ALLEGRO_LOCK_READONLY)
|
||||||
|
if region == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer C.al_unlock_bitmap(b.bitmap)
|
||||||
|
src := (*[1 << 30]uint8)(region.data)
|
||||||
|
dst := im.Pix
|
||||||
|
var srcOff, dstOff int
|
||||||
|
for y := 0; y < b.height; y++ {
|
||||||
|
copy(dst[dstOff:], src[srcOff:srcOff+b.width*4])
|
||||||
|
srcOff += int(region.pitch)
|
||||||
|
dstOff += im.Stride
|
||||||
|
}
|
||||||
|
return im
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bitmap) SetAsTarget() {
|
||||||
|
C.al_set_target_bitmap(b.bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy destroys the bitmap
|
||||||
|
func (b *Bitmap) Destroy() {
|
||||||
|
var bmp = b.bitmap
|
||||||
|
if bmp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.bitmap = nil
|
||||||
|
for _, sub := range b.subs {
|
||||||
|
sub.Destroy()
|
||||||
|
}
|
||||||
|
C.al_destroy_bitmap(bmp)
|
||||||
|
}
|
6
c.go
Normal file
6
c.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package allg5
|
||||||
|
|
||||||
|
// #cgo pkg-config: allegro-5 allegro_audio-5 allegro_font-5 allegro_image-5 allegro_primitives-5 allegro_ttf-5
|
||||||
|
import "C"
|
6
c_windows.go
Normal file
6
c_windows.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// +build windows,!static
|
||||||
|
|
||||||
|
package allg5
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lallegro -lallegro_audio -lallegro_font -lallegro_image -lallegro_primitives -lallegro_ttf
|
||||||
|
import "C"
|
6
c_windows_static.go
Normal file
6
c_windows_static.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// +build windows,static
|
||||||
|
|
||||||
|
package allg5
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lallegro_monolith-static -static -ljpeg -ldumb -lFLAC -lfreetype -lvorbisfile -lvorbis -logg -lphysfs -lpng16 -lzlib -luuid -lkernel32 -lwinmm -lpsapi -lopengl32 -lglu32 -luser32 -lcomdlg32 -lgdi32 -lshell32 -lole32 -ladvapi32 -lws2_32 -lshlwapi -lstdc++ -lwebp
|
||||||
|
import "C"
|
36
color.go
Normal file
36
color.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
import "image/color"
|
||||||
|
|
||||||
|
var _ color.Color = &Color{}
|
||||||
|
|
||||||
|
type Color struct {
|
||||||
|
color C.ALLEGRO_COLOR
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewColor(r, g, b byte) Color {
|
||||||
|
return Color{C.al_map_rgb(C.uchar(r), C.uchar(g), C.uchar(b))}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewColorAlpha(r, g, b, a byte) Color {
|
||||||
|
return Color{C.al_map_rgba(C.uchar(r), C.uchar(g), C.uchar(b), C.uchar(a))}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewColorGo(c color.Color) Color {
|
||||||
|
r, g, b, a := c.RGBA()
|
||||||
|
return Color{C.al_premul_rgba(C.uchar(r>>8), C.uchar(g>>8), C.uchar(b>>8), C.uchar(a>>8))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGBA implements the color.Color interface.
|
||||||
|
func (c Color) RGBA() (r, g, b, a uint32) {
|
||||||
|
var cr, cg, cb, ca C.uchar
|
||||||
|
C.al_unmap_rgba(c.color, &cr, &cg, &cb, &ca)
|
||||||
|
a = uint32(ca)
|
||||||
|
r = uint32(cr) * a
|
||||||
|
g = uint32(cg) * a
|
||||||
|
b = uint32(cb) * a
|
||||||
|
a *= a
|
||||||
|
return
|
||||||
|
}
|
129
display.go
Normal file
129
display.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Display represents a display
|
||||||
|
type Display struct {
|
||||||
|
display *C.ALLEGRO_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) {
|
||||||
|
C.al_set_display_icon(d.display, i.bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
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}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNewWindowTitle(title string) {
|
||||||
|
t := C.CString(title)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
C.al_set_new_window_title(t)
|
||||||
|
}
|
265
event.go
Normal file
265
event.go
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define ALLEGRO_KCM_AUDIO_SRC
|
||||||
|
|
||||||
|
#include <allegro5/allegro.h>
|
||||||
|
#include <allegro5/allegro_audio.h>
|
||||||
|
|
||||||
|
#define USER_EVENT_TYPE ALLEGRO_GET_EVENT_TYPE('u', 's', 'e', 'r')
|
||||||
|
|
||||||
|
void init_user_event(ALLEGRO_EVENT* e)
|
||||||
|
{
|
||||||
|
e->user.type = USER_EVENT_TYPE;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventQueue struct {
|
||||||
|
queue *C.ALLEGRO_EVENT_QUEUE
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event interface {
|
||||||
|
Stamp() float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventBase struct {
|
||||||
|
stamp float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eb EventBase) Stamp() float64 {
|
||||||
|
return eb.stamp
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplayCloseEvent struct {
|
||||||
|
EventBase
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplayResizeEvent struct {
|
||||||
|
EventBase
|
||||||
|
X, Y int
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplayOrientation int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DisplayOrientation0Degrees DisplayOrientation = iota
|
||||||
|
DisplayOrientation90Degrees
|
||||||
|
DisplayOrientation180Degrees
|
||||||
|
DisplayOrientation270Degrees
|
||||||
|
DisplayOrientationFaceUp
|
||||||
|
DisplayOrientationFaceDown
|
||||||
|
)
|
||||||
|
|
||||||
|
func toDisplayOrientation(o C.int) DisplayOrientation {
|
||||||
|
switch o {
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES:
|
||||||
|
return DisplayOrientation0Degrees
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES:
|
||||||
|
return DisplayOrientation90Degrees
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES:
|
||||||
|
return DisplayOrientation180Degrees
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES:
|
||||||
|
return DisplayOrientation270Degrees
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_FACE_UP:
|
||||||
|
return DisplayOrientationFaceUp
|
||||||
|
case C.ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN:
|
||||||
|
return DisplayOrientationFaceDown
|
||||||
|
default:
|
||||||
|
panic("not supported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisplayOrientationEvent struct {
|
||||||
|
EventBase
|
||||||
|
Orientation DisplayOrientation
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyEvent struct {
|
||||||
|
EventBase
|
||||||
|
KeyCode Key
|
||||||
|
Display *Display
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyCharEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
UnicodeCharacter rune
|
||||||
|
Modifiers KeyMod
|
||||||
|
Repeat bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyDownEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyUpEvent struct {
|
||||||
|
KeyEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseButtonDownEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
Button MouseButton
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseButtonUpEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
Button MouseButton
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseEnterEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseEvent struct {
|
||||||
|
EventBase
|
||||||
|
X, Y int
|
||||||
|
Z, W int
|
||||||
|
Display *Display
|
||||||
|
}
|
||||||
|
type MouseLeaveEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
type MouseMoveEvent struct {
|
||||||
|
MouseEvent
|
||||||
|
DeltaX, DeltaY int
|
||||||
|
DeltaZ, DeltaW int
|
||||||
|
Pressure float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecorderFragmentEvent struct {
|
||||||
|
EventBase
|
||||||
|
Buffer unsafe.Pointer
|
||||||
|
Samples int
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserEvent struct {
|
||||||
|
EventBase
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserEventSource struct {
|
||||||
|
source *C.ALLEGRO_EVENT_SOURCE
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEventQueue() (*EventQueue, error) {
|
||||||
|
q := C.al_create_event_queue()
|
||||||
|
if q == nil {
|
||||||
|
return nil, errors.New("unable to create event queue")
|
||||||
|
}
|
||||||
|
return &EventQueue{q}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) register(source *C.ALLEGRO_EVENT_SOURCE) {
|
||||||
|
C.al_register_event_source(eq.queue, source)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterDisplay(d *Display) {
|
||||||
|
eq.register(C.al_get_display_event_source(d.display))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterMouse() {
|
||||||
|
eq.register(C.al_get_mouse_event_source())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterKeyboard() {
|
||||||
|
eq.register(C.al_get_keyboard_event_source())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterRecorder(rec *Recorder) {
|
||||||
|
eq.register(C.al_get_audio_recorder_event_source(rec.recorder))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) RegisterUserEvents(source *UserEventSource) {
|
||||||
|
eq.register(source.source)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) mapEvent(e *C.ALLEGRO_EVENT) Event {
|
||||||
|
any := (*C.ALLEGRO_ANY_EVENT)(unsafe.Pointer(e))
|
||||||
|
eb := EventBase{float64(any.timestamp)}
|
||||||
|
switch any._type {
|
||||||
|
case C.ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT:
|
||||||
|
recorder := (*C.ALLEGRO_AUDIO_RECORDER_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &RecorderFragmentEvent{eb, unsafe.Pointer(recorder.buffer), int(recorder.samples)}
|
||||||
|
case C.ALLEGRO_EVENT_DISPLAY_CLOSE:
|
||||||
|
return &DisplayCloseEvent{eb}
|
||||||
|
case C.ALLEGRO_EVENT_DISPLAY_ORIENTATION:
|
||||||
|
display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &DisplayOrientationEvent{eb, toDisplayOrientation(display.orientation)}
|
||||||
|
case C.ALLEGRO_EVENT_DISPLAY_RESIZE:
|
||||||
|
display := (*C.ALLEGRO_DISPLAY_EVENT)(unsafe.Pointer(e))
|
||||||
|
C.al_acknowledge_resize(display.source)
|
||||||
|
return &DisplayResizeEvent{eb, int(display.x), int(display.y), int(display.width), int(display.height)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_AXES:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseMoveEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, int(mouse.dx), int(mouse.dy), int(mouse.dz), int(mouse.dw), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseButtonDownEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, MouseButton(mouse.button), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseEnterEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_BUTTON_UP:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseButtonUpEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}, MouseButton(mouse.button), float32(mouse.pressure)}
|
||||||
|
case C.ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY:
|
||||||
|
mouse := (*C.ALLEGRO_MOUSE_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &MouseLeaveEvent{MouseEvent{eb, int(mouse.x), int(mouse.y), int(mouse.z), int(mouse.w), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_DOWN:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyDownEvent{KeyEvent{eb, Key(key.keycode), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_UP:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyUpEvent{KeyEvent{eb, Key(key.keycode), nil}}
|
||||||
|
case C.ALLEGRO_EVENT_KEY_CHAR:
|
||||||
|
key := (*C.ALLEGRO_KEYBOARD_EVENT)(unsafe.Pointer(e))
|
||||||
|
return &KeyCharEvent{KeyEvent{eb, Key(key.keycode), nil}, rune(key.unichar), KeyMod(key.modifiers), bool(key.repeat)}
|
||||||
|
case C.USER_EVENT_TYPE:
|
||||||
|
return &UserEvent{eb}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) Get() Event {
|
||||||
|
var event C.ALLEGRO_EVENT
|
||||||
|
if !bool(C.al_get_next_event(eq.queue, &event)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return eq.mapEvent(&event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) GetWait() Event {
|
||||||
|
var event C.ALLEGRO_EVENT
|
||||||
|
C.al_wait_for_event(eq.queue, &event)
|
||||||
|
return eq.mapEvent(&event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (eq *EventQueue) Destroy() {
|
||||||
|
C.al_destroy_event_queue(eq.queue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserEventSource() *UserEventSource {
|
||||||
|
s := (*C.ALLEGRO_EVENT_SOURCE)(C.malloc(C.sizeof_ALLEGRO_EVENT_SOURCE))
|
||||||
|
source := &UserEventSource{s}
|
||||||
|
C.al_init_user_event_source(s)
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserEventSource) Destroy() {
|
||||||
|
C.al_destroy_user_event_source(s.source)
|
||||||
|
C.free(unsafe.Pointer(s.source))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserEventSource) EmitEvent() bool {
|
||||||
|
e := (*C.ALLEGRO_EVENT)(C.malloc(C.sizeof_ALLEGRO_EVENT))
|
||||||
|
C.init_user_event(e)
|
||||||
|
return bool(C.al_emit_user_event(s.source, e, nil))
|
||||||
|
}
|
23
flagmut.go
Normal file
23
flagmut.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <stdlib.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type FlagMutation interface {
|
||||||
|
Set(f NewBitmapFlag)
|
||||||
|
Unset(f NewBitmapFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
type flagMut struct {
|
||||||
|
flg C.int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *flagMut) Set(f NewBitmapFlag) {
|
||||||
|
m.flg |= C.int(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *flagMut) Unset(f NewBitmapFlag) {
|
||||||
|
if m.flg&C.int(f) == C.int(f) {
|
||||||
|
m.flg ^= C.int(f)
|
||||||
|
}
|
||||||
|
}
|
107
font.go
Normal file
107
font.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_font.h>
|
||||||
|
// #include <allegro5/allegro_ttf.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Font struct {
|
||||||
|
font *C.ALLEGRO_FONT
|
||||||
|
hght float32
|
||||||
|
asc float32
|
||||||
|
desc float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type HorizontalAlignment int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AlignLeft HorizontalAlignment = iota
|
||||||
|
AlignCenter
|
||||||
|
AlignRight
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadTTFFont(path string, size int) (*Font, error) {
|
||||||
|
p := C.CString(path)
|
||||||
|
defer C.free(unsafe.Pointer(p))
|
||||||
|
|
||||||
|
f := C.al_load_ttf_font(p, C.int(size), 0)
|
||||||
|
if f == nil {
|
||||||
|
return nil, fmt.Errorf("unable to load ttf font '%s'", path)
|
||||||
|
}
|
||||||
|
return &Font{f, 0, 0, 0}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) drawFlags(a HorizontalAlignment) C.int {
|
||||||
|
switch a {
|
||||||
|
case AlignLeft:
|
||||||
|
return C.ALLEGRO_ALIGN_LEFT
|
||||||
|
case AlignCenter:
|
||||||
|
return C.ALLEGRO_ALIGN_CENTRE
|
||||||
|
case AlignRight:
|
||||||
|
return C.ALLEGRO_ALIGN_RIGHT
|
||||||
|
}
|
||||||
|
return C.ALLEGRO_ALIGN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) Draw(left, top float32, color Color, align HorizontalAlignment, text string) {
|
||||||
|
t := C.CString(text)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
|
||||||
|
flags := f.drawFlags(align)
|
||||||
|
C.al_draw_text(f.font, color.color, C.float(left), C.float(top), flags, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ascent returns the ascent of the font
|
||||||
|
func (f *Font) Ascent() float32 {
|
||||||
|
if f.asc == 0 {
|
||||||
|
f.asc = float32(C.al_get_font_ascent(f.font))
|
||||||
|
}
|
||||||
|
return f.asc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descent returns the descent of the font.
|
||||||
|
func (f *Font) Descent() float32 {
|
||||||
|
if f.desc == 0 {
|
||||||
|
f.desc = float32(C.al_get_font_descent(f.font))
|
||||||
|
}
|
||||||
|
return f.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height returns the height of the font
|
||||||
|
func (f *Font) Height() float32 {
|
||||||
|
if f.hght == 0 {
|
||||||
|
f.hght = f.Ascent() + f.Descent()
|
||||||
|
}
|
||||||
|
return f.hght
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextDimensions returns the bounding box of the rendered text.
|
||||||
|
func (f *Font) TextDimensions(text string) (x, y, w, h float32) {
|
||||||
|
t := C.CString(text)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
|
||||||
|
var bbx, bby, bbw, bbh C.int
|
||||||
|
C.al_get_text_dimensions(f.font, t, &bbx, &bby, &bbw, &bbh)
|
||||||
|
x = float32(bbx)
|
||||||
|
y = float32(bby)
|
||||||
|
w = float32(bbw)
|
||||||
|
h = float32(bbh)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextWidth returns the width of the rendered text.
|
||||||
|
func (f *Font) TextWidth(text string) float32 {
|
||||||
|
t := C.CString(text)
|
||||||
|
defer C.free(unsafe.Pointer(t))
|
||||||
|
|
||||||
|
return float32(C.al_get_text_width(f.font, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) Destroy() {
|
||||||
|
C.al_destroy_font(f.font)
|
||||||
|
}
|
26
graphics.go
Normal file
26
graphics.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// BitmapFlag is extra information provided for creating a bitmap
|
||||||
|
type BitmapFlag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BitmapFlagLinearScaleDown enables linear scaling when scaling down. Gives better results when combined with BitmapFlagMipMap
|
||||||
|
BitmapFlagLinearScaleDown BitmapFlag = C.ALLEGRO_MIN_LINEAR
|
||||||
|
// BitmapFlagLinearScaleUp enables linear scaling when scaling up.
|
||||||
|
BitmapFlagLinearScaleUp = C.ALLEGRO_MAG_LINEAR
|
||||||
|
// BitmapFlagMipMap enables mipmaps for drawing a scaled down version. Bitmap must square and its sides must be a power of two.
|
||||||
|
BitmapFlagMipMap = C.ALLEGRO_MIPMAP
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClearToColor clears the target bitmap to the color
|
||||||
|
func ClearToColor(c Color) {
|
||||||
|
C.al_clear_to_color(c.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNewBitmapFlags sets the default bitmap flags for a newly created bitmap
|
||||||
|
func SetNewBitmapFlags(flags BitmapFlag) {
|
||||||
|
C.al_set_new_bitmap_flags(C.int(flags))
|
||||||
|
}
|
188
keyboard.go
Normal file
188
keyboard.go
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type Key int
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyA Key = 1
|
||||||
|
KeyB = 2
|
||||||
|
KeyC = 3
|
||||||
|
KeyD = 4
|
||||||
|
KeyE = 5
|
||||||
|
KeyF = 6
|
||||||
|
KeyG = 7
|
||||||
|
KeyH = 8
|
||||||
|
KeyI = 9
|
||||||
|
KeyJ = 10
|
||||||
|
KeyK = 11
|
||||||
|
KeyL = 12
|
||||||
|
KeyM = 13
|
||||||
|
KeyN = 14
|
||||||
|
KeyO = 15
|
||||||
|
KeyP = 16
|
||||||
|
KeyQ = 17
|
||||||
|
KeyR = 18
|
||||||
|
KeyS = 19
|
||||||
|
KeyT = 20
|
||||||
|
KeyU = 21
|
||||||
|
KeyV = 22
|
||||||
|
KeyW = 23
|
||||||
|
KeyX = 24
|
||||||
|
KeyY = 25
|
||||||
|
KeyZ = 26
|
||||||
|
Key0 = 27
|
||||||
|
Key1 = 28
|
||||||
|
Key2 = 29
|
||||||
|
Key3 = 30
|
||||||
|
Key4 = 31
|
||||||
|
Key5 = 32
|
||||||
|
Key6 = 33
|
||||||
|
Key7 = 34
|
||||||
|
Key8 = 35
|
||||||
|
Key9 = 36
|
||||||
|
KeyPad0 = 37
|
||||||
|
KeyPad1 = 38
|
||||||
|
KeyPad2 = 39
|
||||||
|
KeyPad3 = 40
|
||||||
|
KeyPad4 = 41
|
||||||
|
KeyPad5 = 42
|
||||||
|
KeyPad6 = 43
|
||||||
|
KeyPad7 = 44
|
||||||
|
KeyPad8 = 45
|
||||||
|
KeyPad9 = 46
|
||||||
|
KeyF1 = 47
|
||||||
|
KeyF2 = 48
|
||||||
|
KeyF3 = 49
|
||||||
|
KeyF4 = 50
|
||||||
|
KeyF5 = 51
|
||||||
|
KeyF6 = 52
|
||||||
|
KeyF7 = 53
|
||||||
|
KeyF8 = 54
|
||||||
|
KeyF9 = 55
|
||||||
|
KeyF10 = 56
|
||||||
|
KeyF11 = 57
|
||||||
|
KeyF12 = 58
|
||||||
|
KeyEscape = 59
|
||||||
|
KeyTilde = 60
|
||||||
|
KeyMinus = 61
|
||||||
|
KeyEquals = 62
|
||||||
|
KeyBackspace = 63
|
||||||
|
KeyTab = 64
|
||||||
|
KeyOpenBrace = 65
|
||||||
|
KeyCloseBrace = 66
|
||||||
|
KeyEnter = 67
|
||||||
|
KeySemicolon = 68
|
||||||
|
KeyQuote = 69
|
||||||
|
KeyBackslash = 70
|
||||||
|
KeyBackslash2 = 71 /* DirectInput calls this DIK_OEM_102: "< > | on UK/Germany keyboards" */
|
||||||
|
KeyComma = 72
|
||||||
|
KeyFullstop = 73
|
||||||
|
KeySlash = 74
|
||||||
|
KeySpace = 75
|
||||||
|
KeyInsert = 76
|
||||||
|
KeyDelete = 77
|
||||||
|
KeyHome = 78
|
||||||
|
KeyEnd = 79
|
||||||
|
KeyPageUp = 80
|
||||||
|
KeyPageDown = 81
|
||||||
|
KeyLeft = 82
|
||||||
|
KeyRight = 83
|
||||||
|
KeyUp = 84
|
||||||
|
KeyDown = 85
|
||||||
|
KeyPadSlash = 86
|
||||||
|
KeyPadAsterisk = 87
|
||||||
|
KeyPadMinus = 88
|
||||||
|
KeyPadPlus = 89
|
||||||
|
KeyPadDelete = 90
|
||||||
|
KeyPadEnter = 91
|
||||||
|
KeyPrintScreen = 92
|
||||||
|
KeyPause = 93
|
||||||
|
KeyAbntC1 = 94
|
||||||
|
KeyYen = 95
|
||||||
|
KeyKana = 96
|
||||||
|
KeyConvert = 97
|
||||||
|
KeyNoConvert = 98
|
||||||
|
KeyAt = 99
|
||||||
|
KeyCircumflex = 100
|
||||||
|
KeyColon2 = 101
|
||||||
|
KeyKanji = 102
|
||||||
|
KeyPadEquals = 103 /* MacOS X */
|
||||||
|
KeyBackQuote = 104 /* MacOS X */
|
||||||
|
KeySemicolon2 = 105 /* MacOS X -- TODO: ask lillo what this should be */
|
||||||
|
KeyCommand = 106 /* MacOS X */
|
||||||
|
KeyBack = 107 /* Android back key */
|
||||||
|
KeyVolumeUp = 108
|
||||||
|
KeyVolumeDown = 109
|
||||||
|
KeySearch = 110
|
||||||
|
KeyDPadCenter = 111
|
||||||
|
KeyButtonX = 112
|
||||||
|
KeyButtonY = 113
|
||||||
|
KeyDPadUp = 114
|
||||||
|
KeyDPadDown = 115
|
||||||
|
KeyDPadLeft = 116
|
||||||
|
KeyDPadRight = 117
|
||||||
|
KeySelect = 118
|
||||||
|
KeyStart = 119
|
||||||
|
KeyButtonL1 = 120
|
||||||
|
KeyButtonR1 = 121
|
||||||
|
KeyButtonL2 = 122
|
||||||
|
KeyButtonR2 = 123
|
||||||
|
KeyButtonA = 124
|
||||||
|
KeyButtonB = 125
|
||||||
|
KeyThumbL = 126
|
||||||
|
KeyThumbR = 127
|
||||||
|
KeyUnknown = 128
|
||||||
|
KeyModifiers = 215
|
||||||
|
KeyLShift = 215
|
||||||
|
KeyRShift = 216
|
||||||
|
KeyLCtrl = 217
|
||||||
|
KeyRCtrl = 218
|
||||||
|
KeyAlt = 219
|
||||||
|
KeyAltGr = 220
|
||||||
|
KeyLWin = 221
|
||||||
|
KeyRWin = 222
|
||||||
|
KeyMenu = 223
|
||||||
|
KeyScrollLock = 224
|
||||||
|
KeyNumLock = 225
|
||||||
|
KeyCapsLock = 226
|
||||||
|
)
|
||||||
|
|
||||||
|
type KeyMod uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyModShift KeyMod = 0x00001
|
||||||
|
KeyModCtrl = 0x00002
|
||||||
|
KeyModAlt = 0x00004
|
||||||
|
KeyModLWin = 0x00008
|
||||||
|
KeyModRWin = 0x00010
|
||||||
|
KeyModMenu = 0x00020
|
||||||
|
KeyModAltGr = 0x00040
|
||||||
|
KeyModCommand = 0x00080
|
||||||
|
KeyModScrollLock = 0x00100
|
||||||
|
KeyModNumlock = 0x00200
|
||||||
|
KeyModCapsLock = 0x00400
|
||||||
|
KeyModInaltseq = 0x00800
|
||||||
|
KeyModAccent1 = 0x01000
|
||||||
|
KeyModAccent2 = 0x02000
|
||||||
|
KeyModAccent3 = 0x04000
|
||||||
|
KeyModAccent4 = 0x08000
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsKeyDown(k Key) bool {
|
||||||
|
var state C.ALLEGRO_KEYBOARD_STATE
|
||||||
|
C.al_get_keyboard_state(&state)
|
||||||
|
return bool(C.al_key_down(&state, C.int(k)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAnyKeyDown(keys ...Key) bool {
|
||||||
|
var state C.ALLEGRO_KEYBOARD_STATE
|
||||||
|
C.al_get_keyboard_state(&state)
|
||||||
|
for _, k := range keys {
|
||||||
|
if bool(C.al_key_down(&state, C.int(k))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
34
monitor.go
Normal file
34
monitor.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type Monitor struct {
|
||||||
|
X1, Y1 int
|
||||||
|
X2, Y2 int
|
||||||
|
}
|
||||||
|
|
||||||
|
func monitor(m *C.ALLEGRO_MONITOR_INFO) Monitor {
|
||||||
|
return Monitor{int(m.x1), int(m.y1), int(m.x2), int(m.y2)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultMonitor() Monitor {
|
||||||
|
var m C.ALLEGRO_MONITOR_INFO
|
||||||
|
C.al_get_monitor_info(C.ALLEGRO_DEFAULT_DISPLAY_ADAPTER, &m)
|
||||||
|
return monitor(&m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Monitors() []Monitor {
|
||||||
|
var n = NumberOfVideoAdapters()
|
||||||
|
var mons []Monitor
|
||||||
|
var m C.ALLEGRO_MONITOR_INFO
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
C.al_get_monitor_info(C.int(i), &m)
|
||||||
|
mons = append(mons, monitor(&m))
|
||||||
|
}
|
||||||
|
return mons
|
||||||
|
}
|
||||||
|
|
||||||
|
func NumberOfVideoAdapters() int {
|
||||||
|
return int(C.al_get_num_video_adapters())
|
||||||
|
}
|
54
mouse.go
Normal file
54
mouse.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type MouseButton uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
MouseButtonLeft MouseButton = 1
|
||||||
|
MouseButtonRight = 2
|
||||||
|
MouseButtonMiddle = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type MouseCursor uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
MouseCursorNone MouseCursor = 0
|
||||||
|
MouseCursorDefault = 1
|
||||||
|
MouseCursorArrow = 2
|
||||||
|
MouseCursorBusy = 3
|
||||||
|
MouseCursorQuestion = 4
|
||||||
|
MouseCursorEdit = 5
|
||||||
|
MouseCursorMove = 6
|
||||||
|
MouseCursorResizeN = 7
|
||||||
|
MouseCursorResizeW = 8
|
||||||
|
MouseCursorResizeS = 9
|
||||||
|
MouseCursorResizeE = 10
|
||||||
|
MouseCursorResizeNW = 11
|
||||||
|
MouseCursorResizeSW = 12
|
||||||
|
MouseCursorResizeSE = 13
|
||||||
|
MouseCursorResizeNE = 14
|
||||||
|
MouseCursorProgress = 15
|
||||||
|
MouseCursorPrecision = 16
|
||||||
|
MouseCursorLink = 17
|
||||||
|
MouseCursorAltSelect = 18
|
||||||
|
MouseCursorUnavailable = 19
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsMouseButtonDown(b MouseButton) bool {
|
||||||
|
var state C.ALLEGRO_MOUSE_STATE
|
||||||
|
C.al_get_mouse_state(&state)
|
||||||
|
return bool(C.al_mouse_button_down(&state, C.int(b)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAnyMouseButtonDown(buttons ...MouseButton) bool {
|
||||||
|
var state C.ALLEGRO_MOUSE_STATE
|
||||||
|
C.al_get_mouse_state(&state)
|
||||||
|
for _, b := range buttons {
|
||||||
|
if bool(C.al_mouse_button_down(&state, C.int(b))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
31
newbitmapflag.go
Normal file
31
newbitmapflag.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type NewBitmapFlag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
NewBitmapFlagMemoryBitmap = NewBitmapFlag(C.ALLEGRO_MEMORY_BITMAP)
|
||||||
|
NewBitmapFlagVideoBitmap = NewBitmapFlag(C.ALLEGRO_VIDEO_BITMAP)
|
||||||
|
NewBitmapFlagMinLinear = NewBitmapFlag(C.ALLEGRO_MIN_LINEAR)
|
||||||
|
)
|
||||||
|
|
||||||
|
type NewBitmapFlagsCapture struct {
|
||||||
|
cap C.int
|
||||||
|
}
|
||||||
|
|
||||||
|
func CaptureNewBitmapFlags() *NewBitmapFlagsCapture {
|
||||||
|
var cap = C.al_get_new_bitmap_flags()
|
||||||
|
return &NewBitmapFlagsCapture{cap}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *NewBitmapFlagsCapture) Mutate(mut func(FlagMutation)) {
|
||||||
|
var m = &flagMut{c.cap}
|
||||||
|
mut(m)
|
||||||
|
C.al_set_new_bitmap_flags(m.flg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *NewBitmapFlagsCapture) Revert() {
|
||||||
|
C.al_set_new_bitmap_flags(c.cap)
|
||||||
|
}
|
12
platform_windows.go
Normal file
12
platform_windows.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_windows.h>
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func (d *Display) WindowHandle() unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(C.al_get_win_window_handle(d.display))
|
||||||
|
}
|
30
primitives.go
Normal file
30
primitives.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
// #include <allegro5/allegro.h>
|
||||||
|
// #include <allegro5/allegro_primitives.h>
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func DrawFilledRectangle(x1, y1, x2, y2 float32, c Color) {
|
||||||
|
C.al_draw_filled_rectangle(C.float(x1), C.float(y1), C.float(x2), C.float(y2), c.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawFilledTriangle(x1, y1, x2, y2, x3, y3 float32, c Color) {
|
||||||
|
C.al_draw_filled_triangle(C.float(x1), C.float(y1), C.float(x2), C.float(y2), C.float(x3), C.float(y3), c.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawLine(x1, y1, x2, y2 float32, c Color, thickness float32) {
|
||||||
|
C.al_draw_line(C.float(x1), C.float(y1), C.float(x2), C.float(y2), c.color, C.float(thickness))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawPolyline(vertices []float32, c Color, thickness float32) {
|
||||||
|
C.al_draw_polyline((*C.float)(unsafe.Pointer(&vertices[0])), 8, C.int(len(vertices)>>1), C.ALLEGRO_LINE_JOIN_ROUND, C.ALLEGRO_LINE_CAP_ROUND, c.color, C.float(thickness), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawRectangle(x1, y1, x2, y2 float32, c Color, thickness float32) {
|
||||||
|
C.al_draw_rectangle(C.float(x1), C.float(y1), C.float(x2), C.float(y2), c.color, C.float(thickness))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DrawTriangle(x1, y1, x2, y2, x3, y3 float32, c Color, thickness float32) {
|
||||||
|
C.al_draw_triangle(C.float(x1), C.float(y1), C.float(x2), C.float(y2), C.float(x3), C.float(y3), c.color, C.float(thickness))
|
||||||
|
}
|
66
system.go
Normal file
66
system.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package allg5
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define ALLEGRO_KCM_AUDIO_SRC
|
||||||
|
|
||||||
|
#include <allegro5/allegro.h>
|
||||||
|
#include <allegro5/allegro_audio.h>
|
||||||
|
#include <allegro5/allegro_font.h>
|
||||||
|
#include <allegro5/allegro_image.h>
|
||||||
|
#include <allegro5/allegro_primitives.h>
|
||||||
|
#include <allegro5/allegro_ttf.h>
|
||||||
|
|
||||||
|
bool init() {
|
||||||
|
return al_init();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
}
|
||||||
|
|
||||||
|
type InitConfig struct {
|
||||||
|
Audio bool
|
||||||
|
Font bool
|
||||||
|
Image bool
|
||||||
|
Primitives bool
|
||||||
|
Keyboard bool
|
||||||
|
Mouse bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var InitAll = InitConfig{true, true, true, true, true, true}
|
||||||
|
|
||||||
|
// Init initializes the Allegro system
|
||||||
|
func Init(config InitConfig) error {
|
||||||
|
if !bool(C.init()) {
|
||||||
|
return errors.New("failed to initialize Allegro")
|
||||||
|
}
|
||||||
|
if config.Audio && !bool(C.al_install_audio()) {
|
||||||
|
return errors.New("failed to initialize audio addon")
|
||||||
|
}
|
||||||
|
if config.Font && !bool(C.al_init_font_addon()) {
|
||||||
|
return errors.New("failed to initialize font addon")
|
||||||
|
}
|
||||||
|
if config.Font && !bool(C.al_init_ttf_addon()) {
|
||||||
|
return errors.New("failed to initialize ttf addon")
|
||||||
|
}
|
||||||
|
if config.Image && !bool(C.al_init_image_addon()) {
|
||||||
|
return errors.New("failed to initialize image addon")
|
||||||
|
}
|
||||||
|
if config.Primitives && !bool(C.al_init_primitives_addon()) {
|
||||||
|
return errors.New("failed to initialize primitives addon")
|
||||||
|
}
|
||||||
|
if config.Keyboard && !bool(C.al_install_keyboard()) {
|
||||||
|
return errors.New("failed to install keyboard")
|
||||||
|
}
|
||||||
|
if config.Mouse && !bool(C.al_install_mouse()) {
|
||||||
|
return errors.New("failed to install mouse")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user