Extract sprite from dc6 from D2Shared (#234)

Remove processing of dc6 file type from sprite creation.  Use dc6 loader from D2Shared.
This commit is contained in:
nicholas-eden 2019-11-24 14:58:23 -08:00 committed by Tim Sarbin
parent 64c90312f7
commit 19257abddb
15 changed files with 85 additions and 106 deletions

View File

@ -1,6 +1,7 @@
package d2scene
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image/color"
"math"
"os"
@ -70,7 +71,8 @@ func (v *CharacterSelect) Load() []func() {
v.soundManager.PlayBGM(d2resource.BGMTitle)
return []func(){
func() {
v.background = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.CharacterSelectionBackground), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.CharacterSelectionBackground), d2datadict.Palettes[d2enum.Sky])
v.background = d2render.CreateSpriteFromDC6(dc6)
v.background.MoveTo(0, 0)
},
func() {
@ -130,11 +132,13 @@ func (v *CharacterSelect) Load() []func() {
v.deleteCharConfirmLabel.MoveTo(400, 185)
},
func() {
v.selectionBox = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.CharacterSelectionSelectBox), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.CharacterSelectionSelectBox), d2datadict.Palettes[d2enum.Sky])
v.selectionBox = d2render.CreateSpriteFromDC6(dc6)
v.selectionBox.MoveTo(37, 86)
},
func() {
v.okCancelBox = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.PopUpOkCancel), d2datadict.Palettes[d2enum.Fechar])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.PopUpOkCancel), d2datadict.Palettes[d2enum.Fechar])
v.okCancelBox = d2render.CreateSpriteFromDC6(dc6)
v.okCancelBox.MoveTo(270, 175)
},
func() {

View File

@ -2,6 +2,7 @@ package d2scene
import (
"bufio"
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image/color"
"log"
"os"
@ -83,7 +84,8 @@ func (v *Credits) LoadContributors() []string {
func (v *Credits) Load() []func() {
return []func(){
func() {
v.creditsBackground = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.CreditsBackground), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.CreditsBackground), d2datadict.Palettes[d2enum.Sky])
v.creditsBackground = d2render.CreateSpriteFromDC6(dc6)
v.creditsBackground.MoveTo(0, 0)
},
func() {

View File

@ -1,6 +1,7 @@
package d2scene
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image/color"
"github.com/OpenDiablo2/D2Shared/d2helper"
@ -51,14 +52,16 @@ func CreateGame(
func (v *Game) Load() []func() {
return []func(){
func() {
v.pentSpinLeft = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.PentSpin), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.PentSpin), d2datadict.Palettes[d2enum.Sky])
v.pentSpinLeft = d2render.CreateSpriteFromDC6(dc6)
v.pentSpinLeft.Animate = true
v.pentSpinLeft.AnimateBackwards = true
v.pentSpinLeft.SpecialFrameTime = 475
v.pentSpinLeft.MoveTo(100, 300)
},
func() {
v.pentSpinRight = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.PentSpin), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.PentSpin), d2datadict.Palettes[d2enum.Sky])
v.pentSpinRight = d2render.CreateSpriteFromDC6(dc6)
v.pentSpinRight.Animate = true
v.pentSpinRight.SpecialFrameTime = 475
v.pentSpinRight.MoveTo(650, 300)

View File

@ -2,6 +2,7 @@ package d2scene
import (
"fmt"
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image/color"
"log"
"os"
@ -109,31 +110,37 @@ func (v *MainMenu) Load() []func() {
v.openDiabloLabel.MoveTo(400, 580)
},
func() {
v.background = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.GameSelectScreen), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.GameSelectScreen), d2datadict.Palettes[d2enum.Sky])
v.background = d2render.CreateSpriteFromDC6(dc6)
v.background.MoveTo(0, 0)
},
func() {
v.trademarkBackground = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.TrademarkScreen), d2datadict.Palettes[d2enum.Sky])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.TrademarkScreen), d2datadict.Palettes[d2enum.Sky])
v.trademarkBackground = d2render.CreateSpriteFromDC6(dc6)
v.trademarkBackground.MoveTo(0, 0)
},
func() {
v.diabloLogoLeft = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.Diablo2LogoFireLeft), d2datadict.Palettes[d2enum.Units])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.Diablo2LogoFireLeft), d2datadict.Palettes[d2enum.Units])
v.diabloLogoLeft = d2render.CreateSpriteFromDC6(dc6)
v.diabloLogoLeft.Blend = true
v.diabloLogoLeft.Animate = true
v.diabloLogoLeft.MoveTo(400, 120)
},
func() {
v.diabloLogoRight = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.Diablo2LogoFireRight), d2datadict.Palettes[d2enum.Units])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.Diablo2LogoFireRight), d2datadict.Palettes[d2enum.Units])
v.diabloLogoRight = d2render.CreateSpriteFromDC6(dc6)
v.diabloLogoRight.Blend = true
v.diabloLogoRight.Animate = true
v.diabloLogoRight.MoveTo(400, 120)
},
func() {
v.diabloLogoLeftBack = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.Diablo2LogoBlackLeft), d2datadict.Palettes[d2enum.Units])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.Diablo2LogoBlackLeft), d2datadict.Palettes[d2enum.Units])
v.diabloLogoLeftBack = d2render.CreateSpriteFromDC6(dc6)
v.diabloLogoLeftBack.MoveTo(400, 120)
},
func() {
v.diabloLogoRightBack = d2render.CreateSprite(v.fileProvider.LoadFile(d2resource.Diablo2LogoBlackRight), d2datadict.Palettes[d2enum.Units])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(d2resource.Diablo2LogoBlackRight), d2datadict.Palettes[d2enum.Units])
v.diabloLogoRightBack = d2render.CreateSpriteFromDC6(dc6)
v.diabloLogoRightBack.MoveTo(400, 120)
},
func() {

View File

@ -1,6 +1,7 @@
package d2scene
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image"
"image/color"
@ -79,7 +80,8 @@ func CreateSelectHeroClass(
}
func (v *SelectHeroClass) loadSprite(path string, palette d2enum.PaletteType) d2render.Sprite {
return d2render.CreateSprite(v.fileProvider.LoadFile(path), d2datadict.Palettes[palette])
dc6, _ := d2dc6.LoadDC6(v.fileProvider.LoadFile(path), d2datadict.Palettes[palette])
return d2render.CreateSpriteFromDC6(dc6)
}
func (v *SelectHeroClass) Load() []func() {

View File

@ -1,6 +1,7 @@
package d2core
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"log"
"math"
"path"
@ -152,8 +153,8 @@ func (v Engine) IsLoading() bool {
// LoadSprite loads a sprite from the game's data files
func (v Engine) LoadSprite(fileName string, palette d2enum.PaletteType) d2render.Sprite {
data := v.LoadFile(fileName)
sprite := d2render.CreateSprite(data, d2datadict.Palettes[palette])
dc6, _ := d2dc6.LoadDC6(v.LoadFile(fileName), d2datadict.Palettes[palette])
sprite := d2render.CreateSpriteFromDC6(dc6)
return sprite
}

View File

@ -5,6 +5,7 @@ import (
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"github.com/OpenDiablo2/OpenDiablo2/d2render"
"github.com/hajimehoshi/ebiten"
)
@ -21,13 +22,14 @@ type Scrollbar struct {
}
func CreateScrollbar(fileProvider d2interface.FileProvider, x, y, height int) Scrollbar {
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(d2resource.Scrollbar), d2datadict.Palettes[d2enum.Sky])
result := Scrollbar{
visible: true,
enabled: true,
x: x,
y: y,
height: height,
scrollbarSprite: d2render.CreateSprite(fileProvider.LoadFile(d2resource.Scrollbar), d2datadict.Palettes[d2enum.Sky]),
scrollbarSprite: d2render.CreateSpriteFromDC6(dc6),
}
return result
}

View File

@ -1,6 +1,7 @@
package d2ui
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image"
"image/color"
@ -123,7 +124,8 @@ func CreateButton(buttonType ButtonType, fileProvider d2interface.FileProvider,
result.buttonLayout = buttonLayout
font := GetFont(buttonLayout.FontPath, d2enum.Units, fileProvider)
buttonSprite := d2render.CreateSprite(fileProvider.LoadFile(buttonLayout.ResourceName), d2datadict.Palettes[buttonLayout.PaletteName])
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(buttonLayout.ResourceName), d2datadict.Palettes[buttonLayout.PaletteName])
buttonSprite := d2render.CreateSpriteFromDC6(dc6)
totalButtonTypes := buttonSprite.GetTotalFrames() / (buttonLayout.XSegments * buttonLayout.YSegments)
for i := 0; i < buttonLayout.XSegments; i++ {
w, _ := buttonSprite.GetFrameSize(i)

View File

@ -5,6 +5,7 @@ import (
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"github.com/OpenDiablo2/OpenDiablo2/d2render"
"github.com/hajimehoshi/ebiten"
)
@ -28,7 +29,8 @@ func CreateCheckbox(fileProvider d2interface.FileProvider, checkState bool) Chec
height: 0,
enabled: true,
}
checkboxSprite := d2render.CreateSprite(fileProvider.LoadFile(d2resource.Checkbox), d2datadict.Palettes[d2enum.Fechar])
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(d2resource.Checkbox), d2datadict.Palettes[d2enum.Fechar])
checkboxSprite := d2render.CreateSpriteFromDC6(dc6)
result.width, result.height = checkboxSprite.GetFrameSize(0)
checkboxSprite.MoveTo(0, 0)

View File

@ -1,6 +1,7 @@
package d2ui
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"image/color"
"strings"
@ -54,7 +55,8 @@ func CreateFont(font string, palette d2enum.PaletteType, fileProvider d2interfac
metrics: make(map[uint16]FontSize),
}
// bug: performance issue when using CJK fonts, because ten thousand frames will be rendered PER font
result.fontSprite = d2render.CreateSprite(fileProvider.LoadFile(font+".dc6"), d2datadict.Palettes[palette])
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(font+".dc6"), d2datadict.Palettes[palette])
result.fontSprite = d2render.CreateSpriteFromDC6(dc6)
woo := "Woo!\x01"
fontData := fileProvider.LoadFile(font + ".tbl")
if string(fontData[0:5]) != woo {

View File

@ -1,6 +1,7 @@
package d2ui
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
@ -34,10 +35,11 @@ type Manager struct {
// CreateManager creates a new instance of a UI manager
func CreateManager(fileProvider d2interface.FileProvider, soundManager d2audio.Manager) *Manager {
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(d2resource.CursorDefault), d2datadict.Palettes[d2enum.Units])
result := &Manager{
pressedIndex: -1,
widgets: make([]Widget, 0),
cursorSprite: d2render.CreateSprite(fileProvider.LoadFile(d2resource.CursorDefault), d2datadict.Palettes[d2enum.Units]),
cursorSprite: d2render.CreateSpriteFromDC6(dc6),
clickSfx: soundManager.LoadSoundEffect(d2resource.SFXButtonClick),
waitForLeftMouseUp: false,
}

View File

@ -1,6 +1,7 @@
package d2ui
import (
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"strings"
"time"
@ -27,8 +28,9 @@ type TextBox struct {
}
func CreateTextbox(fileProvider d2interface.FileProvider) TextBox {
dc6, _ := d2dc6.LoadDC6(fileProvider.LoadFile(d2resource.TextBox2), d2datadict.Palettes[d2enum.Units])
result := TextBox{
bgSprite: d2render.CreateSprite(fileProvider.LoadFile(d2resource.TextBox2), d2datadict.Palettes[d2enum.Units]),
bgSprite: d2render.CreateSpriteFromDC6(dc6),
textLabel: CreateLabel(fileProvider, d2resource.FontFormal11, d2enum.Units),
lineBar: CreateLabel(fileProvider, d2resource.FontFormal11, d2enum.Units),
enabled: true,

View File

@ -1,16 +1,14 @@
package d2render
import (
"encoding/binary"
"image/color"
"log"
"sync"
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
"github.com/OpenDiablo2/D2Shared/d2helper"
"github.com/OpenDiablo2/OpenDiablo2/d2corehelper"
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
"github.com/hajimehoshi/ebiten"
)
@ -46,8 +44,7 @@ type SpriteFrame struct {
Image *ebiten.Image
}
// CreateSprite creates an instance of a sprite
func CreateSprite(data []byte, palette d2datadict.PaletteRec) Sprite {
func CreateSpriteFromDC6(dc6 d2dc6.DC6File) Sprite {
result := Sprite{
X: 50,
Y: 50,
@ -55,96 +52,39 @@ func CreateSprite(data []byte, palette d2datadict.PaletteRec) Sprite {
Direction: 0,
Blend: false,
ColorMod: nil,
Directions: binary.LittleEndian.Uint32(data[16:20]),
FramesPerDirection: binary.LittleEndian.Uint32(data[20:24]),
Directions: dc6.Directions,
FramesPerDirection: dc6.FramesPerDirection,
Animate: false,
LastFrameTime: d2helper.Now(),
SpecialFrameTime: -1,
StopOnLastFrame: false,
valid: false,
valid: true,
AnimateBackwards: false,
}
dataPointer := uint32(24)
totalFrames := result.Directions * result.FramesPerDirection
framePointers := make([]uint32, totalFrames)
for i := uint32(0); i < totalFrames; i++ {
framePointers[i] = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
}
result.Frames = make([]SpriteFrame, totalFrames)
wg := sync.WaitGroup{}
wg.Add(int(totalFrames))
for i := uint32(0); i < totalFrames; i++ {
go func(i uint32) {
defer wg.Done()
dataPointer := framePointers[i]
result.Frames[i] = SpriteFrame{}
result.Frames[i].Flip = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].Width = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].Height = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].OffsetX = d2helper.BytesToInt32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].OffsetY = d2helper.BytesToInt32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].Unknown = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].NextBlock = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].Length = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
dataPointer += 4
result.Frames[i].ImageData = make([]int16, result.Frames[i].Width*result.Frames[i].Height)
for fi := range result.Frames[i].ImageData {
result.Frames[i].ImageData[fi] = -1
}
x := uint32(0)
y := result.Frames[i].Height - 1
for {
b := data[dataPointer]
dataPointer++
if b == 0x80 {
if y == 0 {
break
}
y--
x = 0
} else if (b & 0x80) > 0 {
transparentPixels := b & 0x7F
for ti := byte(0); ti < transparentPixels; ti++ {
result.Frames[i].ImageData[x+(y*result.Frames[i].Width)+uint32(ti)] = -1
}
x += uint32(transparentPixels)
} else {
for bi := 0; bi < int(b); bi++ {
result.Frames[i].ImageData[x+(y*result.Frames[i].Width)+uint32(bi)] = int16(data[dataPointer])
dataPointer++
}
x += uint32(b)
}
result.Frames = make([]SpriteFrame, len(dc6.Frames))
wg := sync.WaitGroup{}
wg.Add(len(dc6.Frames))
for i, f := range dc6.Frames {
go func(i int, frame *d2dc6.DC6Frame) {
defer wg.Done()
result.Frames[i] = SpriteFrame{
Flip: frame.Flipped,
Width: frame.Width,
Height: frame.Height,
OffsetX: frame.OffsetX,
OffsetY: frame.OffsetY,
Unknown: frame.Unknown,
NextBlock: frame.NextBlock,
Length: frame.Length,
ImageData: frame.ImageData(),
//FrameData: frame.FrameData, // TODO: Is the field needed?
Image: frame.Image(),
}
var img = make([]byte, int(result.Frames[i].Width)*int(result.Frames[i].Height)*4)
for ii := uint32(0); ii < result.Frames[i].Width*result.Frames[i].Height; ii++ {
if result.Frames[i].ImageData[ii] < 1 { // TODO: Is this == -1 or < 1?
continue
}
img[ii*4] = palette.Colors[result.Frames[i].ImageData[ii]].R
img[(ii*4)+1] = palette.Colors[result.Frames[i].ImageData[ii]].G
img[(ii*4)+2] = palette.Colors[result.Frames[i].ImageData[ii]].B
img[(ii*4)+3] = 0xFF
}
newImage, _ := ebiten.NewImage(int(result.Frames[i].Width), int(result.Frames[i].Height), ebiten.FilterNearest)
newImage.ReplacePixels(img)
result.Frames[i].Image = newImage
img = nil
}(i)
}(i, f)
}
wg.Wait()
result.valid = true
return result
}
func (v Sprite) IsValid() bool {

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/OpenDiablo2/OpenDiablo2
go 1.12
require (
github.com/OpenDiablo2/D2Shared v0.0.0-20191124053203-a445d5d8cbe0
github.com/OpenDiablo2/D2Shared v0.0.0-20191124224548-cf6a3b59eadb
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/hajimehoshi/ebiten v1.11.0-alpha.0.20191121152720-3df198f68eea

8
go.sum
View File

@ -4,6 +4,10 @@ github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0 h1:tDnuU0igiBiQFjs
github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0/go.mod h1:h/5OEGj4G+fpYxluLjSMZbFY011ZxAntO98nCl8mrCs=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124053203-a445d5d8cbe0 h1:AvMIpYAhSC3xpDwAHHXUt8LN75oeH3sHrzXys/DgJU4=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124053203-a445d5d8cbe0/go.mod h1:zRNOUiglwakbufN8EsNWqLLDHsZoQDA6/dI2GIu2nnU=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124133124-e4652c013e40 h1:NjjCVr+4GCH9NWyfCcwYI5QrYiW3DiOhPxlvEqY2h/g=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124133124-e4652c013e40/go.mod h1:zRNOUiglwakbufN8EsNWqLLDHsZoQDA6/dI2GIu2nnU=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124224548-cf6a3b59eadb h1:4W+jWE86ZuDgHTg/RhWEcUoK7UpRJC/hEnlQ9/SEep4=
github.com/OpenDiablo2/D2Shared v0.0.0-20191124224548-cf6a3b59eadb/go.mod h1:fG8OQsAulB/t/RC9QeUjYAAEXZWY5kHvgWXmMgLhRwI=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
@ -12,6 +16,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-restruct/restruct v0.0.0-20191018101351-5fb876c952c9 h1:f25lTFrAliLucJ3G6a9PcgyaGXA6omEF+682jgfC+7U=
github.com/go-restruct/restruct v0.0.0-20191018101351-5fb876c952c9/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
@ -33,6 +39,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=