ezrec / tcell_ebiten

tcell Screen driver for Ebiten
MIT License
1 stars 0 forks source link

v1: API Proposal #30

Open ezrec opened 3 weeks ago

ezrec commented 3 weeks ago

tcell_ebiten

import "github.com/ezrec/tcell_ebiten"

Package tcell_ebiten provides an github.com/hajimehoshi/ebiten/v2 to github.com/gdamore/tcell/v2 translation layer.

Index

type ETCell

ETCell is the ebiten to tcell manager. An empty ETCell is valid, and ready to use. An ETCell should not be copied.

When creating a new ETCell, use the following patterns to manage how the ETCell display resolutions.

  1. Game.Layout() resolution follows outside size; Screen.Size() is layout size divided by font size.
  1. Game.Layout() fixed at 640x480 => Screen.Size() is layout size divided by font size.
  1. Screen.Size() fixed at 80x25 => Game.Layout() resolution is Screen.Size() times font size.
  1. Screen.Size() fixed at 80x25 => Game.Layout() resolution fixed at 640x480, drawing offset to 100,200
type ETCell struct {
    // contains filtered or unexported fields
}

func (*ETCell) Game

func (et *ETCell) Game() ebiten.Game

Game returns the ebiten.Game interface for this ETCell

func (*ETCell) Screen

func (et *ETCell) Screen() tcell.Screen

Screen returns the tcell.Screen interface for this ETCell.

func (*ETCell) SetFontBold

func (et *ETCell) SetFontBold(font_source any) *ETCell

SetFontBold sets the bold font to be used, if not the same as the normal font.

func (*ETCell) SetFontItalic

func (et *ETCell) SetFontItalic(font_source any) *ETCell

SetFontItalic sets the italic font to be used, if not the same as the normal font.

func (*ETCell) SetFontNormal

func (et *ETCell) SetFontNormal(font_source any) *ETCell

SetFontNormal sets the normal font to be used. It can use any of the following: - golang.org/x/image/font.Face - github.com/hajimehoshi/ebiten/v2/text/v2.Face - io.Reader (assumed to be a TTF font file)

func (*ETCell) SetGameDrawOffset

func (et *ETCell) SetGameDrawOffset(x int, y int) *ETCell

SetGameDrawOffset sets an offset with which to draw the text grid.

func (*ETCell) SetGameDrawScaling

func (et *ETCell) SetGameDrawScaling(x, y float64) *ETCell

SetGameDrawScaling scales the text grid (after offsetting). Default is x = 1.0, y = 1.0

func (*ETCell) SetGameLayout

func (et *ETCell) SetGameLayout(width int, height int) *ETCell

SetGameLayout forces a fixed Game.Layout() screen resolution.

func (*ETCell) SetGameLayoutHighDPI

func (et *ETCell) SetGameLayoutHighDPI(enabled bool) *ETCell

SetGameLayoutHighDPI sets the scaling of the text area to match the monitor's pixel resolution, instead of Ebiten's "native" scaling.

func (*ETCell) SetGameUpdateInputCapture

func (et *ETCell) SetGameUpdateInputCapture(area image.Rectangle) *ETCell

SetInputGameCapture sets the ebiten layout area where all mouse and key events are captured. If area is Empty (default), the entire ebiten game area's events are captured.

func (*ETCell) SetGameUpdateKeyCapture

func (et *ETCell) SetGameUpdateKeyCapture(area image.Rectangle) *ETCell

SetKeyCapture sets the ebiten layout area where key events are captured. If area is Empty (default), the entire ebiten game area's events are captured.

func (*ETCell) SetGameUpdateMouseCapture

func (et *ETCell) SetGameUpdateMouseCapture(area image.Rectangle) *ETCell

SetMouseGameCapture sets the ebiten layout area where mouse events are captured. If area is Empty (default), the entire ebiten game area's events are captured.

func (*ETCell) SetScreenBeepHandler

func (et *ETCell) SetScreenBeepHandler(on_beep func()) *ETCell

SetBeepHandler sets the action that will be called when tcell.Screen.Beep() is called. Default is no action.

func (*ETCell) SetScreenCursorColor

func (et *ETCell) SetScreenCursorColor(color tcell.Color) *ETCell

SetCursorColor changes the color of the text 'hardware' cursor.

func (*ETCell) SetScreenSize

func (et *ETCell) SetScreenSize(cols int, rows int) *ETCell

SetScreenSize forces a fixed Screen.Size() text grid layout.

ezrec commented 3 weeks ago

@memmaker - can you take a look at this proposed API?

It should allow quite a bit more flexibility than the current one, and can handle a future where ebiten.Layout and tcell.Screen have interfaces that can't be mutually embeddable.

memmaker commented 3 weeks ago

Some suggestions:

If you implement HiDPI right, you won't have to expose any toggle to Enable or Disable it.

At least I know of no applications for low-res graphics on a HiDPI display.

I'd just make sure that the device scaling is taken into account in all cases, since it will be just 1.0 for normal displays.

I also found the need to emulate the fallback behaviour for glyphs as implemented in terminals: Using a secondary font for some pre-configured glyphs instead of substituting the glyphs when they are not available.

ezrec commented 3 weeks ago

If you implement HiDPI right, you won't have to expose any toggle to Enable or Disable it.

I believe you are correct - I'll have it in HDPI mode always.

I also found the need to emulate the fallback behaviour for glyphs as implemented in terminals: Using a secondary font for some pre-configured glyphs instead of substituting the glyphs when they are not available.

The ebiten/v2/text/v2.MultiFont wrapper can get you what you want now, I believe.

Thinking about that problem more, it might be useful to have a tcell_ebiten/font.MonoFace, which could have 'factory structs' to make font faces that can handle these scenarios.

type FontStyle int
const (
  FontStyleNormal = FontStyle(iota)
  FontStyleBold
  FontStyleItalic
)

type FontFace interface {
    Size() (width, height int)  // Character cell size, in pixels.
    Descender() int             // Descender metric of the font (used for 'bar' cursor placement).
    Glyph(character rune, style FontStyle) (glyph *ebiten.Image, is_substitute bool)
}

// Implements FontFace
type MonoFace struct {
   // private fields
}

// Takes any of the following types:
// - image_font.Face
// - ebiten_text.Face
type NewMonoFace(source any) MonoFace

// Apply a rune mapping to a font. 
// implements FontFace
type FontFaceWithRuneMapping struct {
    FontFace
    RuneMapping map[rune]rune
}

// Have a font be the 'backup' for another font, if it doesn't have the right runes.
// implements FontFace
type FontFaceWithBackup struct {
  FontFace
  Backup FontFace
}

// Have alternate fonts for bold or italic styles.
// implements FontFace
type FontFaceWithStyle struct {
    FontFace  // Normal font.
    Bold FontFace
    Italic FontFace
}