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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gioui.org/app"
|
"gioui.org/app"
|
||||||
|
"gioui.org/f32"
|
||||||
"gioui.org/io/system"
|
"gioui.org/io/system"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
|
"gioui.org/op/clip"
|
||||||
|
"gioui.org/op/paint"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
|
|
||||||
"gioui.org/font/gofont"
|
"gioui.org/font/gofont"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type vector struct {
|
||||||
|
x, y, z float64
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
labchan chan string
|
labchan chan string
|
||||||
|
senschan chan vector
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -26,6 +37,7 @@ type (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
labchan = make(chan string)
|
labchan = make(chan string)
|
||||||
|
senschan = make(chan vector)
|
||||||
log.Print("Staring event loop")
|
log.Print("Staring event loop")
|
||||||
go eventloop()
|
go eventloop()
|
||||||
app.Main()
|
app.Main()
|
||||||
|
@ -43,6 +55,7 @@ func eventloop() {
|
||||||
w := app.NewWindow(
|
w := app.NewWindow(
|
||||||
app.Size(unit.Dp(400), unit.Dp(400)),
|
app.Size(unit.Dp(400), unit.Dp(400)),
|
||||||
app.Title("Hello"))
|
app.Title("Hello"))
|
||||||
|
|
||||||
th := material.NewTheme(gofont.Collection())
|
th := material.NewTheme(gofont.Collection())
|
||||||
var ops op.Ops
|
var ops op.Ops
|
||||||
|
|
||||||
|
@ -61,10 +74,80 @@ func eventloop() {
|
||||||
go func() {
|
go func() {
|
||||||
labchan <- "Starting"
|
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 {
|
for {
|
||||||
select {
|
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:
|
case x := <-labchan:
|
||||||
labels = append(labels, material.Body1(th, x))
|
labels = append(labels, material.Body1(th, x))
|
||||||
|
|
||||||
|
case x := <-senschan:
|
||||||
|
accel = x
|
||||||
|
|
||||||
case e := <-w.Events():
|
case e := <-w.Events():
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
case system.DestroyEvent:
|
case system.DestroyEvent:
|
||||||
|
@ -73,11 +156,16 @@ func eventloop() {
|
||||||
gtx := layout.NewContext(&ops, e)
|
gtx := layout.NewContext(&ops, e)
|
||||||
resetSysinset(e.Insets)
|
resetSysinset(e.Insets)
|
||||||
sysinset.Layout(gtx, func(gtx C) D {
|
sysinset.Layout(gtx, func(gtx C) D {
|
||||||
return margin.Layout(gtx, func(gtx C) D {
|
ret := margin.Layout(gtx, func(gtx C) D {
|
||||||
return list.Layout(gtx, len(labels), func(gtx C, i int) D {
|
f1 := layout.Flex{Axis: layout.Vertical}
|
||||||
return labels[i].Layout(gtx)
|
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)
|
e.Frame(gtx.Ops)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"gioui.org/app"
|
|
||||||
ndk "git.wow.st/gmp/android-go/android27"
|
ndk "git.wow.st/gmp/android-go/android27"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,55 +13,74 @@ var (
|
||||||
tag *ndk.Char
|
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() {
|
func apiLevel() {
|
||||||
msg := ndk.CharWithGoString("hello log world")
|
msg := ndk.CharWithGoString("hello log world")
|
||||||
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
|
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
|
||||||
msg.Free()
|
msg.Free()
|
||||||
|
|
||||||
apilevel := ndk.AndroidGetDeviceApiLevel()
|
apilevel := ndk.AndroidGetDeviceApiLevel()
|
||||||
message := fmt.Sprintf("API level is %d", apilevel)
|
message := fmt.Sprintf("API level is %d", apilevel)
|
||||||
labchan <- message
|
labchan <- message
|
||||||
|
|
||||||
msg = ndk.CharWithGoString(message)
|
msg = ndk.CharWithGoString(message)
|
||||||
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
|
ndk.AndroidLogWrite(ndk.ANDROID_LOG_WARN, tag, msg)
|
||||||
msg.Free()
|
msg.Free()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSensors() {
|
func sensorLoop() {
|
||||||
pkg := ndk.CharWithGoString("st.wow.git.jni")
|
// the Android Looper is thread-local
|
||||||
sm := ndk.ASensorManagerGetInstanceForPackage(pkg)
|
runtime.LockOSThread()
|
||||||
|
|
||||||
|
pkg := ndk.CharWithGoString("st.wow.git.sensors")
|
||||||
|
manager := ndk.ASensorManagerGetInstanceForPackage(pkg)
|
||||||
pkg.Free()
|
pkg.Free()
|
||||||
sens := ndk.ASensorManagerGetDefaultSensor(sm, ndk.ASENSOR_TYPE_ACCELEROMETER)
|
|
||||||
|
sens := ndk.ASensorManagerGetDefaultSensor(manager, ndk.ASENSOR_TYPE_ACCELEROMETER)
|
||||||
stp := ndk.ASensorGetStringType(sens)
|
stp := ndk.ASensorGetStringType(sens)
|
||||||
labchan <- "sensor" + stp.String()
|
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() {
|
func init() {
|
||||||
tag = ndk.CharWithGoString("gio")
|
tag = ndk.CharWithGoString("gio")
|
||||||
log.Print("Android starting")
|
log.Print("Android starting")
|
||||||
go apiLevel()
|
go apiLevel()
|
||||||
go mkHomeDir()
|
go sensorLoop()
|
||||||
go getSensors()
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user