package main import ( "log" "strconv" "strings" "time" "github.com/g3n/engine/app" "github.com/g3n/engine/camera" "github.com/g3n/engine/core" "github.com/g3n/engine/geometry" "github.com/g3n/engine/gls" "github.com/g3n/engine/graphic" "github.com/g3n/engine/gui" "github.com/g3n/engine/light" "github.com/g3n/engine/material" "github.com/g3n/engine/math32" "github.com/g3n/engine/renderer" "github.com/g3n/engine/util/helper" "github.com/g3n/engine/window" ) var ( scene *core.Node tableConnections *gui.Table ) func main() { // Create application and scene a := app.App(1920, 1080, "Leaky Pool") scene = core.NewNode() // Set the scene to be managed by the gui manager gui.Manager().Set(scene) // Create perspective camera cam := camera.New(1) cam.SetPosition(0, 0, 80) scene.Add(cam) // Set up orbit control for the camera camera.NewOrbitControl(cam) // Set up callback to update viewport and camera aspect ratio when the window is resized onResize := func(evname string, ev interface{}) { // Get framebuffer size and update viewport accordingly width, height := a.GetSize() a.Gls().Viewport(0, 0, int32(width), int32(height)) // Update the camera's aspect ratio cam.SetAspect(float32(width) / float32(height)) } a.Subscribe(window.OnWindowSize, onResize) onResize("", nil) // Create a blue torus and add it to the scene geom := geometry.NewTorus(1, .4, 12, 32, math32.Pi*2) mat := material.NewStandard(math32.NewColor("DarkBlue")) mesh := graphic.NewMesh(geom, mat) scene.Add(mesh) // Create and add lights to the scene scene.Add(light.NewAmbient(&math32.Color{1.0, 1.0, 1.0}, 0.8)) pointLight := light.NewPoint(&math32.Color{1, 1, 1}, 5.0) pointLight.SetPosition(1, 0, 2) scene.Add(pointLight) // Create and add an axis helper to the scene scene.Add(helper.NewAxes(0.5)) // Set background color to gray //a.Gls().ClearColor(0.5, 0.5, 0.5, 1.0) a.Gls().ClearColor(0, 0, 0, 1.0) /////// //GUI// /////// // Connections Table var err error tableConnections, err = gui.NewTable(200, 200, []gui.TableColumn{ {Id: "1", Header: "Local Port", Width: 75, Expand: 0}, {Id: "2", Header: "Status", Width: 125, Expand: 0}, }) if err != nil { log.Fatalf("failed to create tableConnections: %v", err) } tableConnections.SetBorders(1, 1, 1, 1) tableConnections.SetPosition(0, 35) tableConnections.SetMargins(10, 10, 10, 10) editSend := gui.NewEdit(150, "data to transmit...") editSend.SetPosition(tableConnections.Position().X+tableConnections.Width()+10, tableConnections.Position().Y+15) scene.Add(editSend) buttonSendRelease := gui.NewButton("Send and Release") buttonSendRelease.SetPosition(editSend.Position().X+editSend.Width()+10, editSend.Position().Y-2) buttonSendRelease.Subscribe(gui.OnClick, func(name string, ev interface{}) { // Get the selected connection in the table // Get the editSend text // Call the "client program" function to convert to integer and transmit, then release /* if len(tableConnections.SelectedRows()) != 1 { return } row := tableConnections.Rows(0, -1)[tableConnections.SelectedRows()[0]] if row["2"] != "Leased Out" { return } var conn *net.TCPConn for i := range dials { if dials[i].Connection == nil { continue } if row["1"] != strings.Split(dials[i].Connection.LocalAddr().String(), ":")[1] { continue } conn = dials[i].Connection break } if conn == nil { log.Printf("could not match selected table entry to dialed connection") return } */ clientProgram(editSend.Text()) }) scene.Add(buttonSendRelease) labelServer := gui.NewLabel("Server: ") labelServer.SetPosition(10, 8) scene.Add(labelServer) editServer := gui.NewEdit(150, "10.69.71.106:6699") editServer.SetText("10.69.71.106:6699") editServer.SetPosition(labelServer.Position().X+labelServer.Width()+10, 10) scene.Add(editServer) labelPoolSize := gui.NewLabel("Pool Size: ") labelPoolSize.SetPosition(editServer.Position().X+editServer.Width()+10, 8) scene.Add(labelPoolSize) editPoolSize := gui.NewEdit(30, "10") editPoolSize.SetText("10") editPoolSize.SetPosition(labelPoolSize.Position().X+labelPoolSize.Width()+10, 10) scene.Add(editPoolSize) buttonPoolSize := gui.NewButton("Set") buttonPoolSize.SetPosition(editPoolSize.Position().X+editPoolSize.Width()+10, 8) buttonPoolSize.Subscribe(gui.OnClick, func(name string, ev interface{}) { poolSize, err := strconv.Atoi(editPoolSize.Text()) if err != nil { log.Printf("failed to convert poolSize '%d' to integer: %v", poolSize, err) return } setConnPoolSize(poolSize) }) scene.Add(buttonPoolSize) buttonStartPool := gui.NewButton("Start Pool") buttonStartPool.SetPosition(buttonPoolSize.Position().X+buttonPoolSize.Width()+10, 8) buttonStartPool.Subscribe(gui.OnClick, func(name string, ev interface{}) { go connPoolWatchdog(editServer.Text()) // goroutine that keeps the pool full of healthy TCP connections buttonStartPool.Label.SetText("Stop Pool") // stop not implemented - need to restart program }) scene.Add(buttonStartPool) scene.Add(tableConnections) // Run the application a.Run(func(renderer *renderer.Renderer, deltaTime time.Duration) { a.Gls().Clear(gls.DEPTH_BUFFER_BIT | gls.STENCIL_BUFFER_BIT | gls.COLOR_BUFFER_BIT) renderer.Render(scene, cam) }) } // updates the scene based on the status of the dial // Disconnected, Connected, Leased Out // Disconnected: // Connected: dials[i].Mat.SetColor(math32.NewColor("LimeGreen")) // Leased Out: func updateSceneConnections() { rows := make([]map[string]interface{}, 0, len(dials)) for i := range dials { row := make(map[string]interface{}) if dials[i].Connection != nil { row["1"] = strings.Split(dials[i].Connection.LocalAddr().String(), ":")[1] } else { row["1"] = "N/A" } row["2"] = dials[i].Status switch dials[i].Status { case "Disconnected": dials[i].Mat.SetColor(math32.NewColor("Grey")) case "Connected": dials[i].Mat.SetColor(math32.NewColor("LimeGreen")) case "Leased Out": dials[i].Mat.SetColor(math32.NewColor("Blue")) default: log.Printf("connection has unknown status! Should be one of Disconnected, Connected or Leased Out") } rows = append(rows, row) } tableConnections.SetRows(rows) }