Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hswidget/PaletteSelectWidget: refactor #312

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions hswidget/dc6widget/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
gim "github.com/ozankasikci/go-image-merge"

"github.com/OpenDiablo2/HellSpawner/hscommon/hsutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)

const (
Expand Down Expand Up @@ -62,6 +63,7 @@ type widgetState struct {
// cache - will not be saved
rgb []*image.RGBA
textures []*giu.Texture
palette *[256]d2interface.Color

IsForward bool
ticker *time.Ticker
Expand All @@ -71,6 +73,7 @@ func (w *widgetState) Dispose() {
w.viewerState.Dispose()
w.Mode = dc6WidgetViewer
w.textures = nil
w.palette = nil
}

type viewerState struct {
Expand Down Expand Up @@ -146,11 +149,17 @@ func (p *widget) initState() {

go p.runPlayer(newState)

p.buildImages(newState)

p.setState(newState)
}

func (p *widget) buildImages(state *widgetState) {
totalFrames := int(p.dc6.Directions * p.dc6.FramesPerDirection)
newState.rgb = make([]*image.RGBA, totalFrames)
state.rgb = make([]*image.RGBA, totalFrames)

for frameIndex := 0; frameIndex < int(p.dc6.Directions*p.dc6.FramesPerDirection); frameIndex++ {
newState.rgb[frameIndex] = image.NewRGBA(image.Rect(0, 0, int(p.dc6.Frames[frameIndex].Width), int(p.dc6.Frames[frameIndex].Height)))
state.rgb[frameIndex] = image.NewRGBA(image.Rect(0, 0, int(p.dc6.Frames[frameIndex].Width), int(p.dc6.Frames[frameIndex].Height)))
decodedFrame := p.dc6.DecodeFrame(frameIndex)

for y := 0; y < int(p.dc6.Frames[frameIndex].Height); y++ {
Expand All @@ -166,14 +175,14 @@ func (p *widget) initState() {

var r, g, b uint8

if p.palette != nil {
col := p.palette[val]
if state.palette != nil {
col := state.palette[val]
r, g, b = col.R(), col.G(), col.B()
} else {
r, g, b = val, val, val
}

newState.rgb[frameIndex].Set(
state.rgb[frameIndex].Set(
x, y,
color.RGBA{
R: r,
Expand All @@ -186,14 +195,12 @@ func (p *widget) initState() {
}
}

p.setState(newState)

go func() {
textures := make([]*giu.Texture, totalFrames)

for frameIndex := 0; frameIndex < totalFrames; frameIndex++ {
frameIndex := frameIndex
p.textureLoader.CreateTextureFromARGB(newState.rgb[frameIndex], func(t *giu.Texture) {
p.textureLoader.CreateTextureFromARGB(state.rgb[frameIndex], func(t *giu.Texture) {
textures[frameIndex] = t
})
}
Expand Down
8 changes: 6 additions & 2 deletions hswidget/dc6widget/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ type widget struct {
id string
dc6 *d2dc6.DC6
textureLoader hscommon.TextureLoader
palette *[256]d2interface.Color
}

// Create creates new widget
Expand All @@ -43,7 +42,6 @@ func Create(state []byte, palette *[256]d2interface.Color, textureLoader hscommo
id: id,
dc6: dc6,
textureLoader: textureLoader,
palette: palette,
}

if giu.Context.GetState(result.getStateID()) == nil && state != nil {
Expand All @@ -62,6 +60,12 @@ func Create(state []byte, palette *[256]d2interface.Color, textureLoader hscommo
result.setState(s)
}

if s := result.getState(); s.palette != palette {
s.palette = palette
fmt.Println("updating palette")
result.buildImages(s)
}

return result
}

Expand Down
36 changes: 21 additions & 15 deletions hswidget/dccwidget/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ianling/giu"

"github.com/OpenDiablo2/HellSpawner/hscommon/hsutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)

const miliseconds = 1000
Expand Down Expand Up @@ -38,7 +39,7 @@ func (a animationPlayMode) String() string {

const defaultTickTime = 100

type widgetState struct {
type DCCWidgetState struct {
Controls struct {
Direction int32
Frame int32
Expand All @@ -56,24 +57,25 @@ type widgetState struct {

isForward bool // determines a direction of animation
ticker *time.Ticker
palette *[256]d2interface.Color
}

// Dispose cleans viewers state
func (s *widgetState) Dispose() {
func (s *DCCWidgetState) Dispose() {
s.textures = nil
}

func (p *widget) getStateID() string {
return fmt.Sprintf("widget_%s", p.id)
func (p *DCCWidget) getStateID() string {
return fmt.Sprintf("DCCWidget_%s", p.id)
}

func (p *widget) getState() *widgetState {
var state *widgetState
func (p *DCCWidget) getState() *DCCWidgetState {
var state *DCCWidgetState

s := giu.Context.GetState(p.getStateID())

if s != nil {
state = s.(*widgetState)
state = s.(*DCCWidgetState)
} else {
p.initState()
state = p.getState()
Expand All @@ -82,9 +84,9 @@ func (p *widget) getState() *widgetState {
return state
}

func (p *widget) initState() {
func (p *DCCWidget) initState() {
// Prevent multiple invocation to LoadImage.
state := &widgetState{
state := &DCCWidgetState{
IsPlaying: false,
Repeat: false,
TickTime: defaultTickTime,
Expand All @@ -97,6 +99,10 @@ func (p *widget) initState() {

go p.runPlayer(state)

p.buildImages(state)
}

func (p *DCCWidget) buildImages(state *DCCWidgetState) {
totalFrames := p.dcc.NumberOfDirections * p.dcc.FramesPerDirection
state.images = make([]*image.RGBA, totalFrames)

Expand All @@ -121,7 +127,7 @@ func (p *widget) initState() {

val := pixels[idx]

RGBAColor := p.makeImagePixel(val)
RGBAColor := p.makeImagePixel(val, state.palette)
state.images[absoluteFrameIdx].Set(x, y, RGBAColor)
}
}
Expand All @@ -144,11 +150,11 @@ func (p *widget) initState() {
}()
}

func (p *widget) setState(s giu.Disposable) {
func (p *DCCWidget) setState(s giu.Disposable) {
giu.Context.SetState(p.getStateID(), s)
}

func (p *widget) makeImagePixel(val byte) color.RGBA {
func (p *DCCWidget) makeImagePixel(val byte, palette *[256]d2interface.Color) color.RGBA {
alpha := maxAlpha

if val == 0 {
Expand All @@ -157,8 +163,8 @@ func (p *widget) makeImagePixel(val byte) color.RGBA {

var r, g, b uint8

if p.palette != nil {
col := p.palette[val]
if palette != nil {
col := palette[val]
r, g, b = col.R(), col.G(), col.B()
} else {
r, g, b = val, val, val
Expand All @@ -174,7 +180,7 @@ func (p *widget) makeImagePixel(val byte) color.RGBA {
return RGBAColor
}

func (p *widget) runPlayer(state *widgetState) {
func (p *DCCWidget) runPlayer(state *DCCWidgetState) {
for range state.ticker.C {
if !state.IsPlaying {
continue
Expand Down
38 changes: 23 additions & 15 deletions hswidget/dccwidget/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,24 @@ const (
imageW, imageH = 32, 32
)

type widget struct {
type DCCWidget struct {
id string
dcc *d2dcc.DCC
palette *[256]d2interface.Color
textureLoader hscommon.TextureLoader
}

// Create creates a new dcc widget
func Create(tl hscommon.TextureLoader, state []byte, palette *[256]d2interface.Color, id string, dcc *d2dcc.DCC) giu.Widget {
result := &widget{
// Create creates a new dcc DCCWidget
func Create(tl hscommon.TextureLoader, state []byte, id string, dcc *d2dcc.DCC) *DCCWidget {
result := &DCCWidget{
id: id,
dcc: dcc,
palette: palette,
textureLoader: tl,
}

if giu.Context.GetState(result.getStateID()) == nil && state != nil {
s := result.getState()
if err := json.Unmarshal(state, s); err != nil {
log.Printf("error decoding dcc widget state: %v", err)
log.Printf("error decoding dcc DCCWidget state: %v", err)
}

// update ticker
Expand All @@ -62,8 +60,18 @@ func Create(tl hscommon.TextureLoader, state []byte, palette *[256]d2interface.C
return result
}

// Build build a widget
func (p *widget) Build() {
// Palette allows to set palette to show image
func (p *DCCWidget) Palette(palette *[256]d2interface.Color) *DCCWidget {
if s := p.getState(); s.palette != palette {
s.palette = palette
p.buildImages(s)
}

return p
}

// Build builds a DCCWidget
func (p *DCCWidget) Build() {
viewerState := p.getState()

imageScale := uint32(viewerState.Controls.Scale)
Expand All @@ -81,15 +89,15 @@ func (p *widget) Build() {
log.Print(err)
}

var widget *giu.ImageWidget
var DCCWidget *giu.ImageWidget
if viewerState.textures == nil || len(viewerState.textures) <= int(frameIdx) || viewerState.textures[frameIdx] == nil {
widget = giu.Image(nil).Size(imageW, imageH)
DCCWidget = giu.Image(nil).Size(imageW, imageH)
} else {
bw := p.dcc.Directions[dirIdx].Box.Width
bh := p.dcc.Directions[dirIdx].Box.Height
w := float32(uint32(bw) * imageScale)
h := float32(uint32(bh) * imageScale)
widget = giu.Image(viewerState.textures[textureIdx]).Size(w, h)
DCCWidget = giu.Image(viewerState.textures[textureIdx]).Size(w, h)
}

giu.Layout{
Expand Down Expand Up @@ -120,11 +128,11 @@ func (p *widget) Build() {
giu.Separator(),
p.makePlayerLayout(viewerState),
giu.Separator(),
widget,
DCCWidget,
}.Build()
}

func (p *widget) makePlayerLayout(state *widgetState) giu.Layout {
func (p *DCCWidget) makePlayerLayout(state *DCCWidgetState) giu.Layout {
playModeList := make([]string, 0)
for i := playModeForward; i <= playModePingPong; i++ {
playModeList = append(playModeList, i.String())
Expand Down Expand Up @@ -153,7 +161,7 @@ func (p *widget) makePlayerLayout(state *widgetState) giu.Layout {
}
}

func (p *widget) exportGif(state *widgetState) error {
func (p *DCCWidget) exportGif(state *DCCWidgetState) error {
fpd := int32(p.dcc.FramesPerDirection)
firstFrame := state.Controls.Direction * fpd
images := state.images[firstFrame : firstFrame+fpd]
Expand Down
13 changes: 8 additions & 5 deletions hswidget/dt1widget/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/ianling/giu"

"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)

type controls struct {
Expand All @@ -26,18 +27,20 @@ type widgetState struct {

tileGroups [][]*d2dt1.Tile
textures [][]map[string]*giu.Texture
palette *[256]d2interface.Color
}

// Dispose clears viewers state
func (s *widgetState) Dispose() {
s.textures = nil
s.palette = nil
}

func (p *widget) getStateID() string {
return fmt.Sprintf("widget_%s", p.id)
func (p *DT1Widget) getStateID() string {
return fmt.Sprintf("DT1Widget_%s", p.id)
}

func (p *widget) getState() *widgetState {
func (p *DT1Widget) getState() *widgetState {
var state *widgetState

s := giu.Context.GetState(p.getStateID())
Expand All @@ -53,11 +56,11 @@ func (p *widget) getState() *widgetState {
return state
}

func (p *widget) setState(s giu.Disposable) {
func (p *DT1Widget) setState(s giu.Disposable) {
giu.Context.SetState(p.getStateID(), s)
}

func (p *widget) initState() {
func (p *DT1Widget) initState() {
state := &widgetState{
controls: &controls{
ShowGrid: true,
Expand Down
2 changes: 1 addition & 1 deletion hswidget/dt1widget/sub_tile_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func getFlagFromPos(x, y int) int {
return subtileLookup[y][x]
}

func (p *widget) getSubTileFieldToEdit(idx int) *bool {
func (p *DT1Widget) getSubTileFieldToEdit(idx int) *bool {
state := p.getState()

tileIdx := state.TileGroup
Expand Down
Loading