Add bouncing ball and acceleration sensor to examples/sensors

This commit is contained in:
Greg 2020-06-16 22:26:54 -04:00
parent 19194e36f4
commit 0b6929c522
8 changed files with 3148 additions and 2879 deletions

48
android27/extra.go Normal file
View File

@ -0,0 +1,48 @@
package android27
/*
#cgo CFLAGS: -x objective-c -fno-objc-arc
#cgo LDFLAGS: -landroid -llog -lnativewindow -lm
#import <android/looper.h>
#import <android/sensor.h>
typedef struct {
float x;
float y;
float z;
int8_t status;
} ASensorVector2;
ASensorVector2
ASensorAcceleration(ASensorEvent* event) {
ASensorVector2 ret;
ret.x = event->acceleration.x;
ret.y = event->acceleration.y;
ret.z = event->acceleration.z;
ret.status = event->acceleration.status;
return ret;
}
ASensorEventQueue*
ASensorManager_createEventQueue2(ASensorManager* manager, ALooper* looper, int ident) {
return ASensorManager_createEventQueue(manager, looper, ident, 0, 0);
}
*/
import "C"
type ASensorVector C.ASensorVector2
func (x ASensorVector) X() Float { return (Float)(x.x) }
func (x ASensorVector) Y() Float { return (Float)(x.y) }
func (x ASensorVector) Z() Float { return (Float)(x.z) }
func (x *ASensorEvent) Acceleration() ASensorVector {
return (ASensorVector)(C.ASensorAcceleration(x))
}
func ASensorManagerCreateEventQueue(manager *ASensorManager, looper *ALooper, ident int) *ASensorEventQueue {
ret := (*ASensorEventQueue)(C.ASensorManager_createEventQueue2((*C.ASensorManager)(manager), (*C.ALooper)(looper), (C.int)(ident)))
return ret
}

File diff suppressed because it is too large Load Diff

48
android28/extra.go Normal file
View File

@ -0,0 +1,48 @@
package android28
/*
#cgo CFLAGS: -x objective-c -fno-objc-arc
#cgo LDFLAGS: -landroid -llog -lnativewindow -lm
#import <android/looper.h>
#import <android/sensor.h>
typedef struct {
float x;
float y;
float z;
int8_t status;
} ASensorVector2;
ASensorVector2
ASensorAcceleration(ASensorEvent* event) {
ASensorVector2 ret;
ret.x = event->acceleration.x;
ret.y = event->acceleration.y;
ret.z = event->acceleration.z;
ret.status = event->acceleration.status;
return ret;
}
ASensorEventQueue*
ASensorManager_createEventQueue2(ASensorManager* manager, ALooper* looper, int ident) {
return ASensorManager_createEventQueue(manager, looper, ident, 0, 0);
}
*/
import "C"
type ASensorVector C.ASensorVector2
func (x ASensorVector) X() Float { return (Float)(x.x) }
func (x ASensorVector) Y() Float { return (Float)(x.y) }
func (x ASensorVector) Z() Float { return (Float)(x.z) }
func (x *ASensorEvent) Acceleration() ASensorVector {
return (ASensorVector)(C.ASensorAcceleration(x))
}
func ASensorManagerCreateEventQueue(manager *ASensorManager, looper *ALooper, ident int) *ASensorEventQueue {
ret := (*ASensorEventQueue)(C.ASensorManager_createEventQueue2((*C.ASensorManager)(manager), (*C.ALooper)(looper), (C.int)(ident)))
return ret
}

File diff suppressed because it is too large Load Diff

48
android29/extra.go Normal file
View File

@ -0,0 +1,48 @@
package android29
/*
#cgo CFLAGS: -x objective-c -fno-objc-arc
#cgo LDFLAGS: -landroid -llog -lnativewindow -lm
#import <android/looper.h>
#import <android/sensor.h>
typedef struct {
float x;
float y;
float z;
int8_t status;
} ASensorVector2;
ASensorVector2
ASensorAcceleration(ASensorEvent* event) {
ASensorVector2 ret;
ret.x = event->acceleration.x;
ret.y = event->acceleration.y;
ret.z = event->acceleration.z;
ret.status = event->acceleration.status;
return ret;
}
ASensorEventQueue*
ASensorManager_createEventQueue2(ASensorManager* manager, ALooper* looper, int ident) {
return ASensorManager_createEventQueue(manager, looper, ident, 0, 0);
}
*/
import "C"
type ASensorVector C.ASensorVector2
func (x ASensorVector) X() Float { return (Float)(x.x) }
func (x ASensorVector) Y() Float { return (Float)(x.y) }
func (x ASensorVector) Z() Float { return (Float)(x.z) }
func (x *ASensorEvent) Acceleration() ASensorVector {
return (ASensorVector)(C.ASensorAcceleration(x))
}
func ASensorManagerCreateEventQueue(manager *ASensorManager, looper *ALooper, ident int) *ASensorEventQueue {
ret := (*ASensorEventQueue)(C.ASensorManager_createEventQueue2((*C.ASensorManager)(manager), (*C.ALooper)(looper), (C.int)(ident)))
return ret
}

File diff suppressed because it is too large Load Diff

View File

@ -3,20 +3,31 @@
package main
import (
"fmt"
"image/color"
"log"
"time"
"gioui.org/app"
"gioui.org/f32"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget/material"
"gioui.org/font/gofont"
)
type vector struct {
x, y, z float64
}
var (
labchan chan string
senschan chan vector
)
type (
@ -26,6 +37,7 @@ type (
func main() {
labchan = make(chan string)
senschan = make(chan vector)
log.Print("Staring event loop")
go eventloop()
app.Main()
@ -43,6 +55,7 @@ func eventloop() {
w := app.NewWindow(
app.Size(unit.Dp(400), unit.Dp(400)),
app.Title("Hello"))
th := material.NewTheme(gofont.Collection())
var ops op.Ops
@ -61,10 +74,80 @@ func eventloop() {
go func() {
labchan <- "Starting"
}()
var accel vector
accel.y = 1
lablist := func(gtx C) D {
return list.Layout(gtx, len(labels), func(gtx C, i int) D {
return labels[i].Layout(gtx)
})
}
vecview := func(gtx C) D {
f := layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceEvenly}
return f.Layout(gtx,
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("x = %f", accel.x)).Layout(gtx)
}),
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("y = %f", accel.y)).Layout(gtx)
}),
layout.Rigid(func(gtx C) D {
return material.Body1(th, fmt.Sprintf("z = %f", accel.z)).Layout(gtx)
}),
)
}
var cx, cy, cvx, cvy, cs float32 // circle position
cx = 200
cy = 200
cs = 50 // circle size (radius)
circle := func(gtx C, width, height float32) D {
// clip circle position and bounce off of the edges
if (cx < cs) { cx = cs; cvx = (-0.5) * cvx }
if (cy < cs) { cy = cs; cvy = (-0.5) * cvy }
if (cx > width - cs) { cx = width - cs; cvx = (-0.5) * cvx }
if (cy > height - cs) { cy = height - cs; cvy = (-0.5) * cvy }
blue := color.RGBA{0x3f, 0x51, 0xb5, 0x80}
r1 := f32.Rectangle{f32.Point{cx - cs, cy - cs}, f32.Point{cx + cs, cy + cs}}
clip.Rect{ Rect: r1, NE: cs, NW: cs, SE: cs, SW: cs}.Op(gtx.Ops).Add(gtx.Ops)
paint.ColorOp{Color: blue}.Add(gtx.Ops)
paint.PaintOp{Rect: r1}.Add(gtx.Ops)
var ret D
ret.Size.X = int(cs * 2)
ret.Size.Y = int(cs * 2)
return ret
}
ticker := time.NewTicker(time.Second / 60)
var t, told int64
t = time.Now().UnixNano()
for {
select {
case <- ticker.C:
told = t
t = time.Now().UnixNano()
elapsed := float32((t - told) / 1000000)
cvx = cvx - float32(accel.x/1000) * elapsed
cvy = cvy + float32(accel.y/1000) * elapsed
cx = cx + cvx * elapsed
cy = cy + cvy * elapsed
w.Invalidate()
case x := <-labchan:
labels = append(labels, material.Body1(th, x))
case x := <-senschan:
accel = x
case e := <-w.Events():
switch e := e.(type) {
case system.DestroyEvent:
@ -73,11 +156,16 @@ func eventloop() {
gtx := layout.NewContext(&ops, e)
resetSysinset(e.Insets)
sysinset.Layout(gtx, func(gtx C) D {
return margin.Layout(gtx, func(gtx C) D {
return list.Layout(gtx, len(labels), func(gtx C, i int) D {
return labels[i].Layout(gtx)
})
ret := margin.Layout(gtx, func(gtx C) D {
f1 := layout.Flex{Axis: layout.Vertical}
ret := f1.Layout(gtx,
layout.Rigid(vecview),
layout.Flexed(1, lablist),
)
circle(gtx, float32(ret.Size.X), float32(ret.Size.Y))
return ret
})
return ret
})
e.Frame(gtx.Ops)
}

View File

@ -3,9 +3,9 @@ package main
import (
"fmt"
"log"
"os"
"runtime"
"unsafe"
"gioui.org/app"
ndk "git.wow.st/gmp/android-go/android27"
)
@ -13,55 +13,74 @@ var (
tag *ndk.Char
)
func mkHomeDir() {
msg := ndk.CharWithGoString("getting datadir")
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
msg.Free()
godir, _ := app.DataDir()
labchan <- fmt.Sprintf("DataDir is %s", godir)
msg = ndk.CharWithGoString("ok. calling mkdir")
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
msg.Free()
if _, err := os.Stat(godir); !os.IsNotExist(err) {
labchan <- "already exists"
return
}
if err := os.MkdirAll(godir, 0700); err != nil {
fmt.Sprintf("Error creating directory: %s", err)
labchan <- fmt.Sprintf("Error creating directory: %s", err)
} else {
labchan <- "created"
}
}
func apiLevel() {
msg := ndk.CharWithGoString("hello log world")
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
msg.Free()
apilevel := ndk.AndroidGetDeviceApiLevel()
message := fmt.Sprintf("API level is %d", apilevel)
labchan <- message
msg = ndk.CharWithGoString(message)
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
msg.Free()
}
func getSensors() {
pkg := ndk.CharWithGoString("st.wow.git.jni")
sm := ndk.ASensorManagerGetInstanceForPackage(pkg)
func sensorLoop() {
// the Android Looper is thread-local
runtime.LockOSThread()
pkg := ndk.CharWithGoString("st.wow.git.sensors")
manager := ndk.ASensorManagerGetInstanceForPackage(pkg)
pkg.Free()
sens := ndk.ASensorManagerGetDefaultSensor(sm, ndk.ASENSOR_TYPE_ACCELEROMETER)
sens := ndk.ASensorManagerGetDefaultSensor(manager, ndk.ASENSOR_TYPE_ACCELEROMETER)
stp := ndk.ASensorGetStringType(sens)
labchan <- "sensor" + stp.String()
var looper *ndk.ALooper
var queue *ndk.ASensorEventQueue
looper_id := 1
var rate ndk.Int32_t = 60
setup := func() {
looper = ndk.ALooperForThread()
if (looper == nil) {
labchan <- "no looper for thread"
looper = ndk.ALooperPrepare(ndk.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
}
queue = ndk.ASensorManagerCreateEventQueue(manager, looper, looper_id)
ndk.ASensorEventQueueEnableSensor(queue, sens)
ndk.ASensorEventQueueSetEventRate(queue, sens, 1000000/rate) // microseconds
}
setup()
labchan <- "polling accelerometer"
for {
var zero ndk.Int
id := (int)(ndk.ALooperPollOnce(-1, &zero, &zero, (*unsafe.Pointer)(unsafe.Pointer(nil)))) // poll forever
if (id == ndk.ALOOPER_POLL_ERROR) { // set up a new looper
labchan <- "getting a new looper"
setup()
continue
}
if (id == looper_id) {
var event ndk.ASensorEvent
if (ndk.ASensorEventQueueGetEvents(queue, &event, 1) != 1) {
continue
}
accel := (&event).Acceleration()
senschan <- vector{float64(accel.X()), float64(accel.Y()), float64(accel.Z())}
}
}
}
func init() {
tag = ndk.CharWithGoString("gio")
log.Print("Android starting")
go apiLevel()
go mkHomeDir()
go getSensors()
go sensorLoop()
}