mirror of https://github.com/liamg/aminal.git
simplified cursor rendering
This commit is contained in:
parent
54c2aed4a5
commit
e673e72ad9
83
gui/gui.go
83
gui/gui.go
|
@ -5,7 +5,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/liamg/glfont"
|
"gitlab.com/liamg/raft/glfont"
|
||||||
|
|
||||||
"github.com/go-gl/gl/all-core/gl"
|
"github.com/go-gl/gl/all-core/gl"
|
||||||
"github.com/go-gl/glfw/v3.2/glfw"
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||||||
|
@ -16,30 +16,28 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type GUI struct {
|
type GUI struct {
|
||||||
window *glfw.Window
|
window *glfw.Window
|
||||||
logger *zap.SugaredLogger
|
logger *zap.SugaredLogger
|
||||||
config *config.Config
|
config *config.Config
|
||||||
terminal *terminal.Terminal
|
terminal *terminal.Terminal
|
||||||
width int //window width in pixels
|
width int //window width in pixels
|
||||||
height int //window height in pixels
|
height int //window height in pixels
|
||||||
font *glfont.Font
|
font *glfont.Font
|
||||||
fontScale int32
|
fontScale int32
|
||||||
renderer Renderer
|
renderer Renderer
|
||||||
colourAttr uint32
|
colourAttr uint32
|
||||||
renderState *RenderState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI {
|
func New(config *config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI {
|
||||||
|
|
||||||
//logger.
|
//logger.
|
||||||
return &GUI{
|
return &GUI{
|
||||||
config: config,
|
config: config,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
width: 600,
|
width: 600,
|
||||||
height: 300,
|
height: 300,
|
||||||
terminal: terminal,
|
terminal: terminal,
|
||||||
fontScale: 15.0,
|
fontScale: 15.0,
|
||||||
renderState: NewRenderState(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +71,6 @@ func (gui *GUI) resize(w *glfw.Window, width int, height int) {
|
||||||
gui.logger.Errorf("Failed to resize terminal to %d cols, %d rows: %s", cols, rows, err)
|
gui.logger.Errorf("Failed to resize terminal to %d cols, %d rows: %s", cols, rows, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.logger.Debugf("Resetting render state...")
|
|
||||||
gui.renderState.Reset()
|
|
||||||
|
|
||||||
gui.logger.Debugf("Setting viewport size...")
|
gui.logger.Debugf("Setting viewport size...")
|
||||||
gl.Viewport(0, 0, int32(gui.width), int32(gui.height))
|
gl.Viewport(0, 0, int32(gui.width), int32(gui.height))
|
||||||
|
|
||||||
|
@ -192,9 +187,6 @@ func (gui *GUI) Render() error {
|
||||||
|
|
||||||
defaultCell := buffer.NewBackgroundCell(gui.config.ColourScheme.Background)
|
defaultCell := buffer.NewBackgroundCell(gui.config.ColourScheme.Background)
|
||||||
|
|
||||||
var lastCursorX uint
|
|
||||||
var lastCursorY uint
|
|
||||||
|
|
||||||
for !gui.window.ShouldClose() {
|
for !gui.window.ShouldClose() {
|
||||||
|
|
||||||
dirty := false
|
dirty := false
|
||||||
|
@ -210,29 +202,16 @@ func (gui *GUI) Render() error {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.UseProgram(program)
|
|
||||||
|
|
||||||
if dirty || gui.terminal.CheckDirty() {
|
if dirty || gui.terminal.CheckDirty() {
|
||||||
|
|
||||||
|
gl.UseProgram(program)
|
||||||
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
|
||||||
|
|
||||||
if gui.terminal.Modes().ShowCursor {
|
|
||||||
cx := uint(gui.terminal.GetLogicalCursorX())
|
|
||||||
cy := uint(gui.terminal.GetLogicalCursorY())
|
|
||||||
cy = cy + uint(gui.terminal.GetScrollOffset())
|
|
||||||
|
|
||||||
if lastCursorX != cx || lastCursorY != cy {
|
|
||||||
gui.renderState.SetDirty(lastCursorX, lastCursorY)
|
|
||||||
dirty = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := gui.terminal.GetVisibleLines()
|
lines := gui.terminal.GetVisibleLines()
|
||||||
lineCount := gui.terminal.ActiveBuffer().ViewHeight()
|
lineCount := gui.terminal.ActiveBuffer().ViewHeight()
|
||||||
colCount := gui.terminal.ActiveBuffer().ViewWidth()
|
colCount := gui.terminal.ActiveBuffer().ViewWidth()
|
||||||
for y := 0; y < int(lineCount); y++ {
|
for x := 0; x < int(colCount); x++ {
|
||||||
|
for y := 0; y < int(lineCount); y++ {
|
||||||
for x := 0; x < int(colCount); x++ {
|
|
||||||
|
|
||||||
cell := defaultCell
|
cell := defaultCell
|
||||||
|
|
||||||
|
@ -246,7 +225,27 @@ func (gui *GUI) Render() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.renderer.DrawCell(cell, uint(x), uint(y))
|
gui.renderer.DrawCellBg(cell, uint(x), uint(y))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for x := 0; x < int(colCount); x++ {
|
||||||
|
for y := 0; y < int(lineCount); y++ {
|
||||||
|
|
||||||
|
cell := defaultCell
|
||||||
|
|
||||||
|
if y < len(lines) {
|
||||||
|
cells := lines[y].Cells()
|
||||||
|
if x < len(cells) {
|
||||||
|
cell = cells[x]
|
||||||
|
if cell.Rune() == 0 {
|
||||||
|
cell = defaultCell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.renderer.DrawCellText(cell, uint(x), uint(y))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,15 @@ import (
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/go-gl/gl/all-core/gl"
|
"github.com/go-gl/gl/all-core/gl"
|
||||||
"github.com/liamg/glfont"
|
|
||||||
"gitlab.com/liamg/raft/buffer"
|
"gitlab.com/liamg/raft/buffer"
|
||||||
"gitlab.com/liamg/raft/config"
|
"gitlab.com/liamg/raft/config"
|
||||||
|
"gitlab.com/liamg/raft/glfont"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
SetArea(areaX int, areaY int, areaWidth int, areaHeight int)
|
SetArea(areaX int, areaY int, areaWidth int, areaHeight int)
|
||||||
DrawCell(cell buffer.Cell, col uint, row uint)
|
DrawCellBg(cell buffer.Cell, col uint, row uint)
|
||||||
|
DrawCellText(cell buffer.Cell, col uint, row uint)
|
||||||
DrawCursor(col uint, row uint, colour config.Colour)
|
DrawCursor(col uint, row uint, colour config.Colour)
|
||||||
GetTermSize() (uint, uint)
|
GetTermSize() (uint, uint)
|
||||||
}
|
}
|
||||||
|
@ -89,6 +90,12 @@ func (r *OpenGLRenderer) newRectangle(x float32, y float32, colourAttr uint32) *
|
||||||
return rect
|
return rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rect *rectangle) Draw() {
|
||||||
|
gl.UseProgram(rect.prog)
|
||||||
|
gl.BindVertexArray(rect.vao)
|
||||||
|
gl.DrawArrays(gl.TRIANGLES, 0, 6)
|
||||||
|
}
|
||||||
|
|
||||||
func (rect *rectangle) setColour(colour [3]float32) {
|
func (rect *rectangle) setColour(colour [3]float32) {
|
||||||
if rect.colour == colour {
|
if rect.colour == colour {
|
||||||
return
|
return
|
||||||
|
@ -199,55 +206,44 @@ func (r *OpenGLRenderer) generateRectangle(col uint, line uint) *rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) DrawCursor(col uint, row uint, colour config.Colour) {
|
func (r *OpenGLRenderer) DrawCursor(col uint, row uint, colour config.Colour) {
|
||||||
|
rect := r.getRectangle(col, row)
|
||||||
rect, ok := r.rectangles[[2]uint{col, row}]
|
|
||||||
if !ok { // probably trying to draw during resize - perhaps add a mutex?
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
solid := true
|
|
||||||
|
|
||||||
mode := uint32(gl.LINE_LOOP) // gl.TRIANGES for solid cursor
|
|
||||||
points := int32(4)
|
|
||||||
|
|
||||||
if solid {
|
|
||||||
mode = gl.TRIANGLES
|
|
||||||
points = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.UseProgram(r.program)
|
|
||||||
rect.setColour(colour)
|
rect.setColour(colour)
|
||||||
gl.BindVertexArray(rect.vao)
|
rect.Draw()
|
||||||
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
|
|
||||||
gl.DrawArrays(mode, 0, points)
|
|
||||||
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col uint, row uint) {
|
func (r *OpenGLRenderer) DrawCellBg(cell buffer.Cell, col uint, row uint) {
|
||||||
|
|
||||||
var fg [3]float32
|
|
||||||
var bg [3]float32
|
var bg [3]float32
|
||||||
|
|
||||||
if cell.Attr().Reverse {
|
if cell.Attr().Reverse {
|
||||||
fg = cell.Bg()
|
|
||||||
bg = cell.Fg()
|
bg = cell.Fg()
|
||||||
} else {
|
} else {
|
||||||
fg = cell.Fg()
|
|
||||||
bg = cell.Bg()
|
bg = cell.Bg()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bg != r.config.ColourScheme.Background {
|
||||||
|
rect := r.getRectangle(col, row)
|
||||||
|
rect.setColour(bg)
|
||||||
|
rect.Draw()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *OpenGLRenderer) DrawCellText(cell buffer.Cell, col uint, row uint) {
|
||||||
|
|
||||||
|
var fg [3]float32
|
||||||
|
|
||||||
|
if cell.Attr().Reverse {
|
||||||
|
fg = cell.Bg()
|
||||||
|
} else {
|
||||||
|
fg = cell.Fg()
|
||||||
|
}
|
||||||
|
|
||||||
pos, ok := r.cellPositions[[2]uint{col, row}]
|
pos, ok := r.cellPositions[[2]uint{col, row}]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row))
|
panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row))
|
||||||
}
|
}
|
||||||
|
|
||||||
rect := r.getRectangle(col, row)
|
|
||||||
rect.setColour(bg)
|
|
||||||
|
|
||||||
gl.UseProgram(r.program)
|
|
||||||
gl.BindVertexArray(rect.vao)
|
|
||||||
gl.DrawArrays(gl.TRIANGLES, 0, 6)
|
|
||||||
|
|
||||||
var alpha float32 = 1
|
var alpha float32 = 1
|
||||||
if cell.Attr().Dim {
|
if cell.Attr().Dim {
|
||||||
alpha = 0.5
|
alpha = 0.5
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
package gui
|
|
||||||
|
|
||||||
type RenderState struct {
|
|
||||||
cells map[[2]uint]RenderedCell
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRenderState() *RenderState {
|
|
||||||
return &RenderState{
|
|
||||||
cells: map[[2]uint]RenderedCell{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type RenderedCell struct {
|
|
||||||
bg [3]float32
|
|
||||||
fg [3]float32
|
|
||||||
contents rune
|
|
||||||
dirty bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RenderState) Reset() {
|
|
||||||
rs.cells = map[[2]uint]RenderedCell{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RenderState) SetDirty(x uint, y uint) {
|
|
||||||
rs.cells[[2]uint{x, y}] = RenderedCell{
|
|
||||||
bg: [3]float32{0, 0, 0},
|
|
||||||
fg: [3]float32{0, 0, 0},
|
|
||||||
contents: 0,
|
|
||||||
dirty: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rs *RenderState) RequiresRender(x uint, y uint, bg [3]float32, fg [3]float32, contents rune, empty bool) bool {
|
|
||||||
|
|
||||||
state, found := rs.cells[[2]uint{x, y}]
|
|
||||||
if !found {
|
|
||||||
if empty {
|
|
||||||
//return false
|
|
||||||
}
|
|
||||||
rs.cells[[2]uint{x, y}] = RenderedCell{
|
|
||||||
bg: bg,
|
|
||||||
fg: fg,
|
|
||||||
contents: contents,
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.bg != bg || state.fg != fg || state.contents != contents || state.dirty {
|
|
||||||
rs.cells[[2]uint{x, y}] = RenderedCell{
|
|
||||||
bg: bg,
|
|
||||||
fg: fg,
|
|
||||||
contents: contents,
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
Loading…
Reference in New Issue