| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- package giu
- import (
- "fmt"
- "image"
- "image/color"
- "image/draw"
- "image/png"
- "log"
- "os"
- "path/filepath"
- "github.com/AllenDang/imgui-go"
- "github.com/pkg/browser"
- )
- // LoadImage loads image from file and returns *image.RGBA.
- func LoadImage(imgPath string) (*image.RGBA, error) {
- imgFile, err := os.Open(filepath.Clean(imgPath))
- if err != nil {
- return nil, fmt.Errorf("LoadImage: error opening image file %s: %w", imgPath, err)
- }
- defer func() {
- // nolint:govet // we want to reuse this err variable here
- if err := imgFile.Close(); err != nil {
- panic(fmt.Sprintf("error closing image file: %s", imgPath))
- }
- }()
- img, err := png.Decode(imgFile)
- if err != nil {
- return nil, fmt.Errorf("LoadImage: error decoding png image: %w", err)
- }
- return ImageToRgba(img), nil
- }
- // ImageToRgba converts image.Image to *image.RGBA.
- func ImageToRgba(img image.Image) *image.RGBA {
- switch trueImg := img.(type) {
- case *image.RGBA:
- return trueImg
- default:
- rgba := image.NewRGBA(trueImg.Bounds())
- draw.Draw(rgba, trueImg.Bounds(), trueImg, image.Pt(0, 0), draw.Src)
- return rgba
- }
- }
- // ToVec4Color converts rgba color to imgui.Vec4.
- func ToVec4Color(col color.Color) imgui.Vec4 {
- const mask = 0xffff
- r, g, b, a := col.RGBA()
- return imgui.Vec4{
- X: float32(r) / mask,
- Y: float32(g) / mask,
- Z: float32(b) / mask,
- W: float32(a) / mask,
- }
- }
- // ToVec2 converts image.Point to imgui.Vec2.
- func ToVec2(pt image.Point) imgui.Vec2 {
- return imgui.Vec2{
- X: float32(pt.X),
- Y: float32(pt.Y),
- }
- }
- // Vec4ToRGBA converts imgui's Vec4 to golang rgba color.
- func Vec4ToRGBA(vec4 imgui.Vec4) color.RGBA {
- return color.RGBA{
- R: uint8(vec4.X * 255),
- G: uint8(vec4.Y * 255),
- B: uint8(vec4.Z * 255),
- A: uint8(vec4.W * 255),
- }
- }
- // Update updates giu app
- // it is done by default after each frame.
- // However because frames stops rendering, when no user
- // action is done, it may be necessary to
- // Update ui manually at some point.
- func Update() {
- if Context.isAlive {
- Context.platform.Update()
- }
- }
- // GetCursorScreenPos returns imgui drawing cursor on the screen.
- func GetCursorScreenPos() image.Point {
- pos := imgui.CursorScreenPos()
- return image.Pt(int(pos.X), int(pos.Y))
- }
- // SetCursorScreenPos sets imgui drawing cursor on the screen.
- func SetCursorScreenPos(pos image.Point) {
- imgui.SetCursorScreenPos(imgui.Vec2{X: float32(pos.X), Y: float32(pos.Y)})
- }
- // GetCursorPos gets imgui drawing cursor inside of current window.
- func GetCursorPos() image.Point {
- pos := imgui.CursorPos()
- return image.Pt(int(pos.X), int(pos.Y))
- }
- // SetCursorPos sets imgui drawing cursor inside of current window.
- func SetCursorPos(pos image.Point) {
- imgui.SetCursorPos(imgui.Vec2{X: float32(pos.X), Y: float32(pos.Y)})
- }
- // GetMousePos returns mouse position.
- func GetMousePos() image.Point {
- pos := imgui.MousePos()
- return image.Pt(int(pos.X), int(pos.Y))
- }
- // GetAvailableRegion returns region available for rendering.
- // it is always WindowSize-WindowPadding*2.
- func GetAvailableRegion() (width, height float32) {
- region := imgui.ContentRegionAvail()
- return region.X, region.Y
- }
- // CalcTextSize calls CalcTextSizeV(text, false, -1).
- func CalcTextSize(text string) (width, height float32) {
- return CalcTextSizeV(text, false, -1)
- }
- // CalcTextSizeV calculates text dimensions.
- func CalcTextSizeV(text string, hideAfterDoubleHash bool, wrapWidth float32) (w, h float32) {
- size := imgui.CalcTextSize(text, hideAfterDoubleHash, wrapWidth)
- return size.X, size.Y
- }
- // SetNextWindowSize sets size of the next window.
- func SetNextWindowSize(width, height float32) {
- imgui.SetNextWindowSize(imgui.Vec2{X: width, Y: height})
- }
- // ExecCondition represents imgui.Condition.
- type ExecCondition imgui.Condition
- // imgui conditions.
- const (
- ConditionAlways ExecCondition = ExecCondition(imgui.ConditionAlways)
- ConditionOnce ExecCondition = ExecCondition(imgui.ConditionOnce)
- ConditionFirstUseEver ExecCondition = ExecCondition(imgui.ConditionFirstUseEver)
- ConditionAppearing ExecCondition = ExecCondition(imgui.ConditionAppearing)
- )
- // SetNextWindowPos sets position of next window.
- func SetNextWindowPos(x, y float32) {
- imgui.SetNextWindowPos(imgui.Vec2{X: x, Y: y})
- }
- // SetNextWindowSizeV does similar to SetNextWIndowSize but allows to specify imgui.Condition.
- func SetNextWindowSizeV(width, height float32, condition ExecCondition) {
- imgui.SetNextWindowSizeV(
- imgui.Vec2{
- X: width,
- Y: height,
- },
- imgui.Condition(condition),
- )
- }
- // SetItemDefaultFocus set the item focused by default.
- func SetItemDefaultFocus() {
- imgui.SetItemDefaultFocus()
- }
- // SetKeyboardFocusHere sets keyboard focus at *NEXT* widget.
- func SetKeyboardFocusHere() {
- SetKeyboardFocusHereV(0)
- }
- // SetKeyboardFocusHereV sets keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
- func SetKeyboardFocusHereV(i int) {
- imgui.SetKeyboardFocusHereV(i)
- }
- // PushClipRect pushes a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering.
- func PushClipRect(clipRectMin, clipRectMax image.Point, intersectWithClipRect bool) {
- imgui.PushClipRect(ToVec2(clipRectMin), ToVec2(clipRectMax), intersectWithClipRect)
- }
- // PopClipRect should be called to end PushClipRect.
- func PopClipRect() {
- imgui.PopClipRect()
- }
- // Assert checks if cond. If not cond, it alls golang panic.
- func Assert(cond bool, t, method, msg string, args ...any) {
- if !cond {
- fatal(t, method, msg, args...)
- }
- }
- func fatal(widgetName, method, message string, args ...any) {
- if widgetName != "" {
- widgetName = fmt.Sprintf("(*%s)", widgetName)
- }
- log.Panicf("giu: %s.%s: %s", widgetName, method, fmt.Sprintf(message, args...))
- }
- // OpenURL opens `url` in default browser.
- func OpenURL(url string) {
- if err := browser.OpenURL(url); err != nil {
- log.Printf("Error opening %s: %v", url, err)
- }
- }
|