github.com/coming-chat/gomobile@v0.0.0-20220601074111-56995f7d7aba/example/basic/main.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin || linux || windows
     6  // +build darwin linux windows
     7  
     8  // An app that draws a green triangle on a red background.
     9  //
    10  // In order to build this program as an Android APK, using the gomobile tool.
    11  //
    12  // See http://godoc.org/golang.org/x/mobile/cmd/gomobile to install gomobile.
    13  //
    14  // Get the basic example and use gomobile to build or install it on your device.
    15  //
    16  //	$ go get -d golang.org/x/mobile/example/basic
    17  //	$ gomobile build golang.org/x/mobile/example/basic # will build an APK
    18  //
    19  //	# plug your Android device to your computer or start an Android emulator.
    20  //	# if you have adb installed on your machine, use gomobile install to
    21  //	# build and deploy the APK to an Android target.
    22  //	$ gomobile install golang.org/x/mobile/example/basic
    23  //
    24  // Switch to your device or emulator to start the Basic application from
    25  // the launcher.
    26  // You can also run the application on your desktop by running the command
    27  // below. (Note: It currently doesn't work on Windows.)
    28  //
    29  //	$ go install golang.org/x/mobile/example/basic && basic
    30  package main
    31  
    32  import (
    33  	"encoding/binary"
    34  	"log"
    35  
    36  	"golang.org/x/mobile/app"
    37  	"golang.org/x/mobile/event/lifecycle"
    38  	"golang.org/x/mobile/event/paint"
    39  	"golang.org/x/mobile/event/size"
    40  	"golang.org/x/mobile/event/touch"
    41  	"golang.org/x/mobile/exp/app/debug"
    42  	"golang.org/x/mobile/exp/f32"
    43  	"golang.org/x/mobile/exp/gl/glutil"
    44  	"golang.org/x/mobile/gl"
    45  )
    46  
    47  var (
    48  	images   *glutil.Images
    49  	fps      *debug.FPS
    50  	program  gl.Program
    51  	position gl.Attrib
    52  	offset   gl.Uniform
    53  	color    gl.Uniform
    54  	buf      gl.Buffer
    55  
    56  	green  float32
    57  	touchX float32
    58  	touchY float32
    59  )
    60  
    61  func main() {
    62  	app.Main(func(a app.App) {
    63  		var glctx gl.Context
    64  		var sz size.Event
    65  		for e := range a.Events() {
    66  			switch e := a.Filter(e).(type) {
    67  			case lifecycle.Event:
    68  				switch e.Crosses(lifecycle.StageVisible) {
    69  				case lifecycle.CrossOn:
    70  					glctx, _ = e.DrawContext.(gl.Context)
    71  					onStart(glctx)
    72  					a.Send(paint.Event{})
    73  				case lifecycle.CrossOff:
    74  					onStop(glctx)
    75  					glctx = nil
    76  				}
    77  			case size.Event:
    78  				sz = e
    79  				touchX = float32(sz.WidthPx / 2)
    80  				touchY = float32(sz.HeightPx / 2)
    81  			case paint.Event:
    82  				if glctx == nil || e.External {
    83  					// As we are actively painting as fast as
    84  					// we can (usually 60 FPS), skip any paint
    85  					// events sent by the system.
    86  					continue
    87  				}
    88  
    89  				onPaint(glctx, sz)
    90  				a.Publish()
    91  				// Drive the animation by preparing to paint the next frame
    92  				// after this one is shown.
    93  				a.Send(paint.Event{})
    94  			case touch.Event:
    95  				touchX = e.X
    96  				touchY = e.Y
    97  			}
    98  		}
    99  	})
   100  }
   101  
   102  func onStart(glctx gl.Context) {
   103  	var err error
   104  	program, err = glutil.CreateProgram(glctx, vertexShader, fragmentShader)
   105  	if err != nil {
   106  		log.Printf("error creating GL program: %v", err)
   107  		return
   108  	}
   109  
   110  	buf = glctx.CreateBuffer()
   111  	glctx.BindBuffer(gl.ARRAY_BUFFER, buf)
   112  	glctx.BufferData(gl.ARRAY_BUFFER, triangleData, gl.STATIC_DRAW)
   113  
   114  	position = glctx.GetAttribLocation(program, "position")
   115  	color = glctx.GetUniformLocation(program, "color")
   116  	offset = glctx.GetUniformLocation(program, "offset")
   117  
   118  	images = glutil.NewImages(glctx)
   119  	fps = debug.NewFPS(images)
   120  }
   121  
   122  func onStop(glctx gl.Context) {
   123  	glctx.DeleteProgram(program)
   124  	glctx.DeleteBuffer(buf)
   125  	fps.Release()
   126  	images.Release()
   127  }
   128  
   129  func onPaint(glctx gl.Context, sz size.Event) {
   130  	glctx.ClearColor(1, 0, 0, 1)
   131  	glctx.Clear(gl.COLOR_BUFFER_BIT)
   132  
   133  	glctx.UseProgram(program)
   134  
   135  	green += 0.01
   136  	if green > 1 {
   137  		green = 0
   138  	}
   139  	glctx.Uniform4f(color, 0, green, 0, 1)
   140  
   141  	glctx.Uniform2f(offset, touchX/float32(sz.WidthPx), touchY/float32(sz.HeightPx))
   142  
   143  	glctx.BindBuffer(gl.ARRAY_BUFFER, buf)
   144  	glctx.EnableVertexAttribArray(position)
   145  	glctx.VertexAttribPointer(position, coordsPerVertex, gl.FLOAT, false, 0, 0)
   146  	glctx.DrawArrays(gl.TRIANGLES, 0, vertexCount)
   147  	glctx.DisableVertexAttribArray(position)
   148  
   149  	fps.Draw(sz)
   150  }
   151  
   152  var triangleData = f32.Bytes(binary.LittleEndian,
   153  	0.0, 0.4, 0.0, // top left
   154  	0.0, 0.0, 0.0, // bottom left
   155  	0.4, 0.0, 0.0, // bottom right
   156  )
   157  
   158  const (
   159  	coordsPerVertex = 3
   160  	vertexCount     = 3
   161  )
   162  
   163  const vertexShader = `#version 100
   164  uniform vec2 offset;
   165  
   166  attribute vec4 position;
   167  void main() {
   168  	// offset comes in with x/y values between 0 and 1.
   169  	// position bounds are -1 to 1.
   170  	vec4 offset4 = vec4(2.0*offset.x-1.0, 1.0-2.0*offset.y, 0, 0);
   171  	gl_Position = position + offset4;
   172  }`
   173  
   174  const fragmentShader = `#version 100
   175  precision mediump float;
   176  uniform vec4 color;
   177  void main() {
   178  	gl_FragColor = color;
   179  }`