Add bouncing ball and acceleration sensor to examples/sensors
This commit is contained in:
parent
19194e36f4
commit
0b6929c522
48
android27/extra.go
Normal file
48
android27/extra.go
Normal 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
|
||||
}
|
||||
|
1748
android27/main.go
1748
android27/main.go
File diff suppressed because it is too large
Load Diff
48
android28/extra.go
Normal file
48
android28/extra.go
Normal 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
|
||||
}
|
||||
|
2024
android28/main.go
2024
android28/main.go
File diff suppressed because it is too large
Load Diff
48
android29/extra.go
Normal file
48
android29/extra.go
Normal 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
|
||||
}
|
||||
|
1932
android29/main.go
1932
android29/main.go
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user