func appMain(a app.App) { inst = a for e := range a.Events() { switch e := a.Filter(e).(type) { case lifecycle.Event: onLifecycleEvent(&e) case size.Event: onSizeEvent(&e) case paint.Event: onPaintEvent(&e) case touch.Event: onTouchEvent(&e) case key.Event: onKeyEvent(&e) } } }
// ServerMain performs the main routine for the demo server. func ServerMain(a app.App) { background := context.Background() remotePt = make(chan rexdemo.RemotePoint, 1) demo = NewDemo() go RunDiscovery(background, demo) var glctx gl.Context var sz size.Event for e := range a.Events() { select { case pt := <-remotePt: touchX = float32(pt.X * float64(sz.WidthPx)) touchY = float32(pt.Y * float64(sz.HeightPx)) default: } switch e := a.Filter(e).(type) { case lifecycle.Event: switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: glctx, _ = e.DrawContext.(gl.Context) onStart(glctx) a.Send(paint.Event{}) case lifecycle.CrossOff: onStop(glctx) glctx = nil } case size.Event: sz = e touchX = float32(sz.WidthPx / 2) touchY = float32(sz.HeightPx / 2) case paint.Event: if glctx == nil || e.External { // As we are actively painting as fast as // we can (usually 60 FPS), skip any paint // events sent by the system. continue } onPaint(glctx, sz) a.Publish() // Drive the animation by preparing to paint the next frame // after this one is shown. a.Send(paint.Event{}) case touch.Event: touchX = e.X touchY = e.Y } } }
// main is the entry point of the application. This is function gets registered // as the main function of the application. func (m *Module) main(a app.App) { var images *glutil.Images var glctx gl.Context sz := size.Event{} m.Render.InitApp(a) ticker := time.NewTicker(time.Second) for { select { case <-ticker.C: a.Send(paint.Event{}) case <-m.Network.Updated(): m.loaded = true case e := <-a.Events(): switch e := a.Filter(e).(type) { case lifecycle.Event: glctx, _ = e.DrawContext.(gl.Context) if glctx != nil { glctx = e.DrawContext.(gl.Context) if images != nil { images.Release() } images = glutil.NewImages(glctx) } case size.Event: sz = e case paint.Event: m.draw(glctx, sz, images) a.Publish() } } } }
// ServerMain performs the main routine for the demo server. func ServerMain(a app.App) { background := context.Background() remotePt = make(chan rexdemo.RemotePoint, 1) demo = NewDemo() // initialize the room server and launch the discovery server. bestAddr := room.BestAddr() if bestAddr != "" { log.Printf("[WARN] Unable to locate a good address for binding") } config := &room.ServerConfig{ Room: rexdemo.Room, Bus: room.NewBus(background, demo), Addr: bestAddr, } server, err := StartServer(config) if err != nil { log.Printf("[FATAL] Unable to initialize server: %v", err) os.Exit(1) } go func() { err = server.Wait() if err != nil { log.Printf("[FATAL] Server terminated: %v", err) return } }() go RunDiscovery(background, server) var glctx gl.Context var sz size.Event for e := range a.Events() { select { case pt := <-remotePt: touchX = float32(pt.X * float64(sz.WidthPx)) touchY = float32(pt.Y * float64(sz.HeightPx)) default: } switch e := a.Filter(e).(type) { case lifecycle.Event: switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: glctx, _ = e.DrawContext.(gl.Context) onStart(glctx) a.Send(paint.Event{}) case lifecycle.CrossOff: onStop(glctx) glctx = nil } case size.Event: sz = e touchX = float32(sz.WidthPx / 2) touchY = float32(sz.HeightPx / 2) case paint.Event: if glctx == nil || e.External { // As we are actively painting as fast as // we can (usually 60 FPS), skip any paint // events sent by the system. continue } onPaint(glctx, sz) a.Publish() // Drive the animation by preparing to paint the next frame // after this one is shown. a.Send(paint.Event{}) case touch.Event: touchX = e.X touchY = e.Y } } }
func repaint(a app.App) { a.Send(paint.Event{}) // keep animating }
func (gn *Engine) Run(a app.App) { if gn.chatty { log.Println("Starting gn Run.") log.Print("runtime.GOOS = ", runtime.GOOS) log.Print("runtime.GOARCH = ", runtime.GOARCH) } // TODO(monopole): Send these into App somehow, so // the select below can be collapse to just a switch // on app events. var chMasterCommand <-chan ifc.MasterCommand var chPauseDuration <-chan float32 var chGravity <-chan float32 var chIncomingBall <-chan *model.Ball var chQuit <-chan bool holdCount := 0 chWaiting, chIsReady := gn.enterWaitState() var sz size.Event for { if false && gn.chatty { log.Printf(" ") log.Printf(" ") log.Printf("Re-entering select.") } select { case ready := <-chIsReady: log.Printf("Got ready signal = %v", ready) if ready { chWaiting, chIsReady = nil, nil relay := gn.nm.GetRelay() chMasterCommand = relay.ChMasterCommand() chPauseDuration = relay.ChPauseDuration() chGravity = relay.ChGravity() chIncomingBall = relay.ChIncomingBall() chQuit = relay.ChQuit() gn.scn.Start() if gn.chatty { log.Printf("Started screen.") } gn.createBall() gn.isAlive = true if gn.chatty { log.Printf("Seem to be alive now.") } a.Send(paint.Event{}) } else { if gn.chatty { log.Printf("Unable to get ready - exiting.") } if gn.stopMeansReallyStop() { return } chWaiting, chIsReady = gn.enterWaitState() } case mc := <-chMasterCommand: switch mc.Name { case "kick": gn.kick() gn.freeze() case "left": gn.left() case "right": gn.right() case "random": gn.random() case "destroy": gn.balls = []*model.Ball{} default: log.Print("Don't understand command %v", mc) } case <-chQuit: gn.stop() if gn.stopMeansReallyStop() { return } chWaiting, chIsReady = gn.enterWaitState() case pd := <-chPauseDuration: gn.pauseDuration = pd case g := <-chGravity: gn.gravity = g case b := <-chIncomingBall: nx := b.GetPos().X if nx == config.MagicX { // Ball came in from center of top nx = gn.scn.Width() / 2.0 } else if nx >= 0 && nx <= fuzzyZero { // Ball came in from left. nx = 0 } else { // Ball came in from right. nx = gn.scn.Width() } // Assume Y component normalized before teleport. ny := b.GetPos().Y * gn.scn.Height() b.SetPos(nx, ny) // TODO: Adjust velocity per refraction-like rules? gn.balls = append(gn.balls, b) case dc := <-gn.nm.ChDoorCommand(): gn.handleDoor(dc) case event := <-a.Events(): switch e := a.Filter(event).(type) { case lifecycle.Event: switch e.Crosses(lifecycle.StageVisible) { case lifecycle.CrossOn: if chWaiting == nil { log.Panic("Lifecycle trouble") return } if err := gn.scn.SetDrawContext(e.DrawContext); err != nil { log.Panic(err) } log.Print("Passing cycleOn") chWaiting <- readyCycleOn log.Print("Passed cycleOn") case lifecycle.CrossOff: gn.scn.Stop() gn.stop() if gn.stopMeansReallyStop() { return } chWaiting, chIsReady = gn.enterWaitState() } case paint.Event: if gn.isAlive { gn.moveBalls() gn.scn.Paint(gn.balls) a.Publish() } a.Send(paint.Event{}) case key.Event: // Aspirationally use keys if gn.chatty { log.Printf("Key event! %T = %v", e.Code, e.Code) } switch e.Code { case key.CodeQ, key.CodeEscape: gn.stop() if gn.stopMeansReallyStop() { return } chWaiting, chIsReady = gn.enterWaitState() } case touch.Event: if gn.chatty { log.Println("Touch event") } switch e.Type { case touch.TypeBegin: holdCount = 1 gn.beginX = e.X gn.beginY = e.Y if e.X < magicButtonSideLength && e.Y < magicButtonSideLength { if gn.chatty { log.Printf("Touched shutdown spot.\n") } gn.stop() if gn.stopMeansReallyStop() { return } chWaiting, chIsReady = gn.enterWaitState() } case touch.TypeMove: holdCount++ case touch.TypeEnd: if gn.chatty { log.Printf("holdcount = %d", holdCount) } if holdCount > 0 && holdCount <= maxHoldCount { // If they hold on too long, ignore it. dx := float64(e.X - gn.beginX) dy := float64(e.Y - gn.beginY) mag := math.Sqrt(dx*dx + dy*dy) if mag >= minDragLength { ndx := float32(dx/mag) * gn.scn.Width() / gn.pauseDuration ndy := float32(dy/mag) * gn.scn.Height() / gn.pauseDuration b := model.NewBall(nil, model.Vec{gn.beginX, gn.beginY}, model.Vec{ndx, ndy}) if gn.chatty { log.Printf("Sending impulse: %s", b.String()) } gn.applyImpulse(b) } else { if gn.chatty { log.Printf("Mag only %.4f", mag) } } } holdCount = 0 } case size.Event: // TODO: Adjust velocity on resizes - balls should take the // same amount of time to traverse the screen regardless of // the size. sz = e gn.scn.ReSize(float32(sz.WidthPx), float32(sz.HeightPx)) gn.resetImpulseLimit() if gn.chatty && debugShowResizes { log.Printf( "Resize new w=%.2f, new h=%.2f, maxDsqImpulse = %f.2", gn.scn.Width(), gn.scn.Height(), gn.maxDistSqForImpulse) } if chWaiting != nil { if gn.chatty { log.Printf("passing readyResize") } chWaiting <- readyResize if gn.chatty { log.Printf("passed readyResize") } } } } } }