1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-18 02:16:23 -05:00

Use our own DrawEffects enum for draw effects (#564)

* Add PushEffect, handle effects in renderer

* Set effects instead of blend

* Stop using PushCompositeMode, use PushEffect

* Remove remaining composite mode things
This commit is contained in:
Ziemas 2020-07-09 03:57:35 +02:00 committed by GitHub
parent a10a53be26
commit e2e8a303c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 87 additions and 172 deletions

View File

@ -1,47 +0,0 @@
package d2enum
// CompositeMode defines the composite mode
type CompositeMode int
const (
// CompositeModeSourceOver applies a composite based on:
// c_out = c_src + c_dst × (1 - α_src) (Regular alpha blending)
CompositeModeSourceOver CompositeMode = iota + 1
// CompositeModeClear applies a composite based on: c_out = 0
CompositeModeClear
// CompositeModeCopy applies a composite based on: c_out = c_src
CompositeModeCopy
// CompositeModeDestination applies a composite based on: c_out = c_dst
CompositeModeDestination
// CompositeModeDestinationOver applies a composite based on: c_out = c_src × (1 - α_dst) + c_dst
CompositeModeDestinationOver
// CompositeModeSourceIn applies a composite based on: c_out = c_src × α_dst
CompositeModeSourceIn
// CompositeModeDestinationIn applies a composite based on: c_out = c_dst × α_src
CompositeModeDestinationIn
// CompositeModeSourceOut applies a composite based on: c_out = c_src × (1 - α_dst)
CompositeModeSourceOut
// CompositeModeDestinationOut applies a composite based on: c_out = c_dst × (1 - α_src)
CompositeModeDestinationOut
// CompositeModeSourceAtop applies a composite based on: c_out = c_src × α_dst + c_dst × (1 - α_src)
CompositeModeSourceAtop
// CompositeModeDestinationAtop applies a composite based on: c_out = c_src × (1 - α_dst) + c_dst × α_src
CompositeModeDestinationAtop
// CompositeModeXor applies a composite based on: c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
CompositeModeXor
// CompositeModeLighter applies a composite based on:
// c_out = c_src + c_dst Sum of source and destination (a.k.a. 'plus' or 'additive')
CompositeModeLighter
)

View File

@ -3,6 +3,8 @@ package d2interface
import ( import (
"image" "image"
"image/color" "image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
) )
// Animation is an animation // Animation is an animation
@ -35,5 +37,5 @@ type Animation interface {
SetColorMod(colorMod color.Color) SetColorMod(colorMod color.Color)
GetPlayedCount() int GetPlayedCount() int
ResetPlayedCount() ResetPlayedCount()
SetBlend(blend bool) SetEffect(effect d2enum.DrawEffect)
} }

View File

@ -18,7 +18,7 @@ type Surface interface {
Pop() Pop()
PopN(n int) PopN(n int)
PushColor(color color.Color) PushColor(color color.Color)
PushCompositeMode(mode d2enum.CompositeMode) PushEffect(effect d2enum.DrawEffect)
PushFilter(filter d2enum.Filter) PushFilter(filter d2enum.Filter)
PushTranslation(x, y int) PushTranslation(x, y int)
PushBrightness(brightness float64) PushBrightness(brightness float64)

View File

@ -40,12 +40,12 @@ type animationDirection struct {
// animation has directionality, play modes, and frame counting // animation has directionality, play modes, and frame counting
type animation struct { type animation struct {
directions []animationDirection directions []animationDirection
effect d2enum.DrawEffect
colorMod color.Color colorMod color.Color
frameIndex int frameIndex int
directionIndex int directionIndex int
lastFrameTime float64 lastFrameTime float64
playedCount int playedCount int
compositeMode d2enum.CompositeMode
playMode playMode playMode playMode
playLength float64 playLength float64
subStartingFrame int subStartingFrame int
@ -120,7 +120,7 @@ func (a *animation) Render(target d2iface.Surface) error {
target.PushTranslation(frame.offsetX, frame.offsetY) target.PushTranslation(frame.offsetX, frame.offsetY)
defer target.Pop() defer target.Pop()
target.PushCompositeMode(a.compositeMode) target.PushEffect(a.effect)
defer target.Pop() defer target.Pop()
target.PushColor(a.colorMod) target.PushColor(a.colorMod)
@ -148,7 +148,7 @@ func (a *animation) RenderSection(sfc d2iface.Surface, bound image.Rectangle) er
frame := direction.frames[a.frameIndex] frame := direction.frames[a.frameIndex]
sfc.PushTranslation(frame.offsetX, frame.offsetY) sfc.PushTranslation(frame.offsetX, frame.offsetY)
sfc.PushCompositeMode(a.compositeMode) sfc.PushEffect(a.effect)
sfc.PushColor(a.colorMod) sfc.PushColor(a.colorMod)
defer sfc.PopN(3) defer sfc.PopN(3)
@ -305,11 +305,6 @@ func (a *animation) ResetPlayedCount() {
a.playedCount = 0 a.playedCount = 0
} }
// SetBlend sets the Animation alpha blending status func (a *animation) SetEffect(e d2enum.DrawEffect) {
func (a *animation) SetBlend(blend bool) { a.effect = e
if blend {
a.compositeMode = d2enum.CompositeModeLighter
} else {
a.compositeMode = d2enum.CompositeModeSourceOver
}
} }

View File

@ -53,7 +53,7 @@ func (am *animationManager) LoadAnimation(
return nil, err return nil, err
} }
animation, err = CreateDC6Animation(am.renderer, animationPath, palette) animation, err = CreateDC6Animation(am.renderer, animationPath, palette, d2enum.DrawEffectNone)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -18,7 +18,7 @@ type DC6Animation struct {
// CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette // CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette
func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string, func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string,
palette d2iface.Palette) (d2iface.Animation, error) { palette d2iface.Palette, effect d2enum.DrawEffect) (d2iface.Animation, error) {
dc6, err := loadDC6(dc6Path) dc6, err := loadDC6(dc6Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -29,6 +29,7 @@ func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string,
playLength: defaultPlayLength, playLength: defaultPlayLength,
playLoop: true, playLoop: true,
originAtBottom: true, originAtBottom: true,
effect: effect,
} }
anim := DC6Animation{ anim := DC6Animation{

View File

@ -15,7 +15,6 @@ import (
type DCCAnimation struct { type DCCAnimation struct {
animation animation
dccPath string dccPath string
effect d2enum.DrawEffect
palette d2iface.Palette palette d2iface.Palette
renderer d2iface.Renderer renderer d2iface.Renderer
} }
@ -32,6 +31,7 @@ func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2ifa
playLength: defaultPlayLength, playLength: defaultPlayLength,
playLoop: true, playLoop: true,
directions: make([]animationDirection, dcc.NumberOfDirections), directions: make([]animationDirection, dcc.NumberOfDirections),
effect: effect,
} }
DCC := DCCAnimation{ DCC := DCCAnimation{
@ -39,17 +39,8 @@ func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2ifa
dccPath: dccPath, dccPath: dccPath,
palette: palette, palette: palette,
renderer: renderer, renderer: renderer,
effect: effect,
} }
// Really the renderer should take DrawEffects and do the right thing
if effect == d2enum.DrawEffectModulate {
DCC.SetBlend(true)
}
// Transparency is now no longer handled, it should be done by using PL2 palette and
// picking the appropriate transform for the transparency level
err = DCC.SetDirection(0) err = DCC.SetDirection(0)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -98,7 +98,6 @@ func (f *Font) GetTextMetrics(text string) (width, height int) {
// RenderText prints a text using its configured style on a Surface (multi-lines are left-aligned, use label otherwise) // RenderText prints a text using its configured style on a Surface (multi-lines are left-aligned, use label otherwise)
func (f *Font) RenderText(text string, target d2interface.Surface) error { func (f *Font) RenderText(text string, target d2interface.Surface) error {
f.sheet.SetColorMod(f.color) f.sheet.SetColorMod(f.color)
f.sheet.SetBlend(false)
lines := strings.Split(text, "\n") lines := strings.Split(text, "\n")

View File

@ -1,6 +1,7 @@
package d2gui package d2gui
import ( import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
) )
@ -53,7 +54,6 @@ func createAnimatedSprite(imagePath, palettePath string, direction AnimationDire
} else { } else {
sprite.animation.PlayBackward() sprite.animation.PlayBackward()
} }
sprite.animation.SetBlend(false)
sprite.SetVisible(true) sprite.SetVisible(true)
return sprite, nil return sprite, nil
@ -84,3 +84,7 @@ func (s *Sprite) advance(elapsed float64) error {
func (s *Sprite) getSize() (int, int) { func (s *Sprite) getSize() (int, int) {
return s.animation.GetCurrentFrameSize() return s.animation.GetCurrentFrameSize()
} }
func (s *Sprite) SetEffect(e d2enum.DrawEffect) {
s.animation.SetEffect(e)
}

View File

@ -5,6 +5,7 @@ import (
"math" "math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
) )
@ -27,7 +28,7 @@ func CreateMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error)
animation.SetSubLoop(record.Animation.SubStartingFrame, record.Animation.SubEndingFrame) animation.SetSubLoop(record.Animation.SubStartingFrame, record.Animation.SubEndingFrame)
} }
animation.SetBlend(true) animation.SetEffect(d2enum.DrawEffectModulate)
//animation.SetPlaySpeed(float64(record.Animation.AnimationSpeed)) //animation.SetPlaySpeed(float64(record.Animation.AnimationSpeed))
animation.SetPlayLoop(record.Animation.LoopAnimation) animation.SetPlayLoop(record.Animation.LoopAnimation)
animation.PlayForward() animation.PlayForward()

View File

@ -1,72 +0,0 @@
package ebiten
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/hajimehoshi/ebiten"
)
func d2ToEbitenCompositeMode(comp d2enum.CompositeMode) ebiten.CompositeMode {
switch comp {
case d2enum.CompositeModeSourceOver:
return ebiten.CompositeModeSourceOver
case d2enum.CompositeModeClear:
return ebiten.CompositeModeClear
case d2enum.CompositeModeCopy:
return ebiten.CompositeModeCopy
case d2enum.CompositeModeDestination:
return ebiten.CompositeModeDestination
case d2enum.CompositeModeDestinationOver:
return ebiten.CompositeModeDestinationOver
case d2enum.CompositeModeSourceIn:
return ebiten.CompositeModeSourceIn
case d2enum.CompositeModeDestinationIn:
return ebiten.CompositeModeDestinationIn
case d2enum.CompositeModeSourceOut:
return ebiten.CompositeModeSourceOut
case d2enum.CompositeModeDestinationOut:
return ebiten.CompositeModeDestinationOut
case d2enum.CompositeModeSourceAtop:
return ebiten.CompositeModeSourceAtop
case d2enum.CompositeModeDestinationAtop:
return ebiten.CompositeModeDestinationAtop
case d2enum.CompositeModeXor:
return ebiten.CompositeModeXor
case d2enum.CompositeModeLighter:
return ebiten.CompositeModeLighter
}
return ebiten.CompositeModeSourceOver
}
func ebitenToD2CompositeMode(comp ebiten.CompositeMode) d2enum.CompositeMode {
switch comp {
case ebiten.CompositeModeSourceOver:
return d2enum.CompositeModeSourceOver
case ebiten.CompositeModeClear:
return d2enum.CompositeModeClear
case ebiten.CompositeModeCopy:
return d2enum.CompositeModeCopy
case ebiten.CompositeModeDestination:
return d2enum.CompositeModeDestination
case ebiten.CompositeModeDestinationOver:
return d2enum.CompositeModeDestinationOver
case ebiten.CompositeModeSourceIn:
return d2enum.CompositeModeSourceIn
case ebiten.CompositeModeDestinationIn:
return d2enum.CompositeModeDestinationIn
case ebiten.CompositeModeSourceOut:
return d2enum.CompositeModeSourceOut
case ebiten.CompositeModeDestinationOut:
return d2enum.CompositeModeDestinationOut
case ebiten.CompositeModeSourceAtop:
return d2enum.CompositeModeSourceAtop
case ebiten.CompositeModeDestinationAtop:
return d2enum.CompositeModeDestinationAtop
case ebiten.CompositeModeXor:
return d2enum.CompositeModeXor
case ebiten.CompositeModeLighter:
return d2enum.CompositeModeLighter
}
return d2enum.CompositeModeSourceOver
}

View File

@ -67,7 +67,7 @@ func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surfa
surface.(*ebitenSurface).image, surface.(*ebitenSurface).image,
surfaceState{ surfaceState{
filter: ebiten.FilterNearest, filter: ebiten.FilterNearest,
mode: ebiten.CompositeModeSourceOver, effect: d2enum.DrawEffectNone,
}, },
) )

View File

@ -32,7 +32,7 @@ type ebitenSurface struct {
} }
func createEbitenSurface(img *ebiten.Image, currentState ...surfaceState) *ebitenSurface { func createEbitenSurface(img *ebiten.Image, currentState ...surfaceState) *ebitenSurface {
state := surfaceState{} state := surfaceState{effect: d2enum.DrawEffectNone}
if len(currentState) > 0 { if len(currentState) > 0 {
state = currentState[0] state = currentState[0]
} }
@ -50,9 +50,9 @@ func (s *ebitenSurface) PushTranslation(x, y int) {
s.stateCurrent.y += y s.stateCurrent.y += y
} }
func (s *ebitenSurface) PushCompositeMode(mode d2enum.CompositeMode) { func (s *ebitenSurface) PushEffect(effect d2enum.DrawEffect) {
s.stateStack = append(s.stateStack, s.stateCurrent) s.stateStack = append(s.stateStack, s.stateCurrent)
s.stateCurrent.mode = d2ToEbitenCompositeMode(mode) s.stateCurrent.effect = effect
} }
func (s *ebitenSurface) PushFilter(filter d2enum.Filter) { func (s *ebitenSurface) PushFilter(filter d2enum.Filter) {
@ -87,7 +87,7 @@ func (s *ebitenSurface) PopN(n int) {
} }
func (s *ebitenSurface) Render(sfc d2interface.Surface) error { func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
opts := &ebiten.DrawImageOptions{CompositeMode: s.stateCurrent.mode} opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y)) opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
opts.Filter = s.stateCurrent.filter opts.Filter = s.stateCurrent.filter
@ -99,6 +99,25 @@ func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness) opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness)
} }
// Are these correct? who even knows
switch s.stateCurrent.effect {
case d2enum.DrawEffectPctTransparency25:
opts.ColorM.Translate(0, 0, 0, -0.25)
case d2enum.DrawEffectPctTransparency50:
opts.ColorM.Translate(0, 0, 0, -0.50)
case d2enum.DrawEffectPctTransparency75:
opts.ColorM.Translate(0, 0, 0, -0.75)
case d2enum.DrawEffectModulate:
opts.CompositeMode = ebiten.CompositeModeLighter
// TODO: idk what to do when ebiten doesn't exactly match, pick closest?
case d2enum.DrawEffectBurn:
case d2enum.DrawEffectNormal:
case d2enum.DrawEffectMod2XTrans:
case d2enum.DrawEffectMod2X:
case d2enum.DrawEffectNone:
opts.CompositeMode = ebiten.CompositeModeSourceOver
}
var img = sfc.(*ebitenSurface).image var img = sfc.(*ebitenSurface).image
return s.image.DrawImage(img, opts) return s.image.DrawImage(img, opts)
@ -106,7 +125,7 @@ func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
// Renders the section of the animation frame enclosed by bounds // Renders the section of the animation frame enclosed by bounds
func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error { func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
opts := &ebiten.DrawImageOptions{CompositeMode: s.stateCurrent.mode} opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y)) opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
opts.Filter = s.stateCurrent.filter opts.Filter = s.stateCurrent.filter
@ -118,6 +137,25 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness) opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness)
} }
// Are these correct? who even knows
switch s.stateCurrent.effect {
case d2enum.DrawEffectPctTransparency25:
opts.ColorM.Translate(0, 0, 0, -0.25)
case d2enum.DrawEffectPctTransparency50:
opts.ColorM.Translate(0, 0, 0, -0.50)
case d2enum.DrawEffectPctTransparency75:
opts.ColorM.Translate(0, 0, 0, -0.75)
case d2enum.DrawEffectModulate:
opts.CompositeMode = ebiten.CompositeModeLighter
// TODO: idk what to do when ebiten doesn't exactly match, pick closest?
case d2enum.DrawEffectBurn:
case d2enum.DrawEffectNormal:
case d2enum.DrawEffectMod2XTrans:
case d2enum.DrawEffectMod2X:
case d2enum.DrawEffectNone:
opts.CompositeMode = ebiten.CompositeModeSourceOver
}
var img = sfc.(*ebitenSurface).image var img = sfc.(*ebitenSurface).image
return s.image.DrawImage(img.SubImage(bound).(*ebiten.Image), opts) return s.image.DrawImage(img.SubImage(bound).(*ebiten.Image), opts)

View File

@ -3,14 +3,15 @@ package ebiten
import ( import (
"image/color" "image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
) )
type surfaceState struct { type surfaceState struct {
x int x int
y int y int
mode ebiten.CompositeMode filter ebiten.Filter
filter ebiten.Filter color color.Color
color color.Color
brightness float64 brightness float64
effect d2enum.DrawEffect
} }

View File

@ -137,7 +137,7 @@ func CreateButton(renderer d2interface.Renderer, buttonType ButtonType, text str
xOffset := result.width / 2 xOffset := result.width / 2
buttonSprite.SetPosition(0, 0) buttonSprite.SetPosition(0, 0)
buttonSprite.SetBlend(true) buttonSprite.SetEffect(d2enum.DrawEffectModulate)
buttonSprite.RenderSegmented(result.normalSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame) buttonSprite.RenderSegmented(result.normalSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
lbl.SetPosition(xOffset, textY) lbl.SetPosition(xOffset, textY)
@ -190,10 +190,9 @@ func (v *Button) Activate() {
// Render renders the button // Render renders the button
func (v *Button) Render(target d2interface.Surface) { func (v *Button) Render(target d2interface.Surface) {
target.PushCompositeMode(d2enum.CompositeModeSourceAtop)
target.PushFilter(d2enum.FilterNearest) target.PushFilter(d2enum.FilterNearest)
target.PushTranslation(v.x, v.y) target.PushTranslation(v.x, v.y)
defer target.PopN(3) defer target.PopN(2)
if !v.enabled { if !v.enabled {
target.PushColor(color.RGBA{R: 128, G: 128, B: 128, A: 195}) target.PushColor(color.RGBA{R: 128, G: 128, B: 128, A: 195})

View File

@ -43,10 +43,9 @@ func CreateCheckbox(renderer d2interface.Renderer, checkState bool) Checkbox {
} }
func (v *Checkbox) Render(target d2interface.Surface) { func (v *Checkbox) Render(target d2interface.Surface) {
target.PushCompositeMode(d2enum.CompositeModeSourceAtop)
target.PushTranslation(v.x, v.y) target.PushTranslation(v.x, v.y)
target.PushFilter(d2enum.FilterNearest) target.PushFilter(d2enum.FilterNearest)
defer target.PopN(3) defer target.PopN(2)
if v.checkState { if v.checkState {
_ = target.Render(v.checkedImage) _ = target.Render(v.checkedImage)

View File

@ -5,6 +5,7 @@ import (
"image" "image"
"image/color" "image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2common"
@ -179,11 +180,10 @@ func (s *Sprite) SetColorMod(color color.Color) {
s.animation.SetColorMod(color) s.animation.SetColorMod(color)
} }
// SetBlend sets the animation alpha blending status
func (s *Sprite) SetBlend(blend bool) {
s.animation.SetBlend(blend)
}
func (s *Sprite) Advance(elapsed float64) error { func (s *Sprite) Advance(elapsed float64) error {
return s.animation.Advance(elapsed) return s.animation.Advance(elapsed)
} }
func (s *Sprite) SetEffect(e d2enum.DrawEffect) {
s.animation.SetEffect(e)
}

View File

@ -182,14 +182,14 @@ func (v *MainMenu) createLabels(loading d2screen.LoadingState) {
func (v *MainMenu) createLogos(loading d2screen.LoadingState) { func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits) animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
v.diabloLogoLeft, _ = d2ui.LoadSprite(animation) v.diabloLogoLeft, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeft.SetBlend(true) v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate)
v.diabloLogoLeft.PlayForward() v.diabloLogoLeft.PlayForward()
v.diabloLogoLeft.SetPosition(400, 120) v.diabloLogoLeft.SetPosition(400, 120)
loading.Progress(0.6) loading.Progress(0.6)
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits) animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
v.diabloLogoRight, _ = d2ui.LoadSprite(animation) v.diabloLogoRight, _ = d2ui.LoadSprite(animation)
v.diabloLogoRight.SetBlend(true) v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate)
v.diabloLogoRight.PlayForward() v.diabloLogoRight.PlayForward()
v.diabloLogoRight.SetPosition(400, 120) v.diabloLogoRight.SetPosition(400, 120)

View File

@ -602,7 +602,8 @@ func advanceSprite(sprite *d2ui.Sprite, elapsed float64) {
} }
} }
func loadSprite(animationPath string, position image.Point, playLength int, playLoop, blend bool) *d2ui.Sprite { func loadSprite(animationPath string, position image.Point, playLength int, playLoop,
blend bool) *d2ui.Sprite {
if animationPath == "" { if animationPath == "" {
return nil return nil
} }
@ -615,7 +616,10 @@ func loadSprite(animationPath string, position image.Point, playLength int, play
animation.PlayForward() animation.PlayForward()
animation.SetPlayLoop(playLoop) animation.SetPlayLoop(playLoop)
animation.SetBlend(blend)
if blend {
animation.SetEffect(d2enum.DrawEffectModulate)
}
if playLength != 0 { if playLength != 0 {
animation.SetPlayLengthMs(playLength) animation.SetPlayLengthMs(playLength)

View File

@ -412,7 +412,7 @@ func (g *GameControls) Render(target d2interface.Surface) {
// Stamina status bar // Stamina status bar
target.PushTranslation(273, 572) target.PushTranslation(273, 572)
target.PushCompositeMode(d2enum.CompositeModeLighter) target.PushEffect(d2enum.DrawEffectModulate)
staminaPercent := float64(g.hero.Stats.Stamina) / float64(g.hero.Stats.MaxStamina) staminaPercent := float64(g.hero.Stats.Stamina) / float64(g.hero.Stats.MaxStamina)
target.DrawRect(int(staminaPercent*staminaBarWidth), 19, color.RGBA{R: 175, G: 136, B: 72, A: 200}) target.DrawRect(int(staminaPercent*staminaBarWidth), 19, color.RGBA{R: 175, G: 136, B: 72, A: 200})
target.PopN(2) target.PopN(2)