Render to surface, not ebiten texture (#268)
* Render to surface, not ebiten texture * Fix debug text
This commit is contained in:
parent
0c2b7cfd8d
commit
49b9a190f2
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2dcc"
|
||||
"github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2corehelper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
@ -192,18 +192,15 @@ func (a *Animation) Advance(elapsed float64) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *Animation) Render(target *ebiten.Image, offsetX, offsetY int) error {
|
||||
func (a *Animation) Render(target *d2surface.Surface) error {
|
||||
direction := a.directions[a.directionIndex]
|
||||
frame := direction.frames[a.frameIndex]
|
||||
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(frame.offsetX+offsetX), float64(frame.offsetY+offsetY))
|
||||
opts.CompositeMode = a.compositeMode
|
||||
if a.colorMod != nil {
|
||||
opts.ColorM = d2corehelper.ColorToColorM(a.colorMod)
|
||||
}
|
||||
|
||||
return target.DrawImage(frame.image, opts)
|
||||
target.PushTranslation(frame.offsetX, frame.offsetY)
|
||||
target.PushCompositeMode(a.compositeMode)
|
||||
target.PushColor(a.colorMod)
|
||||
defer target.PopN(3)
|
||||
return target.Render(frame.image)
|
||||
}
|
||||
|
||||
func (a *Animation) GetFrameSize(frameIndex int) (int, int, error) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2data"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2dcc"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type Composite struct {
|
||||
|
@ -45,7 +45,7 @@ func (c *Composite) Advance(elapsed float64) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Composite) Render(target *ebiten.Image, offsetX, offsetY int) error {
|
||||
func (c *Composite) Render(target *d2surface.Surface) error {
|
||||
if c.mode == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func (c *Composite) Render(target *ebiten.Image, offsetX, offsetY int) error {
|
|||
for _, layerIndex := range c.mode.drawOrder[c.mode.frameIndex] {
|
||||
layer := c.mode.layers[layerIndex]
|
||||
if layer != nil {
|
||||
if err := layer.Render(target, offsetX, offsetY); err != nil {
|
||||
if err := layer.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common"
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
dh "github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
|
@ -15,6 +13,7 @@ import (
|
|||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2corecommon/d2coreinterface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
@ -195,7 +194,7 @@ func (v *CharacterSelect) onExitButtonClicked() {
|
|||
func (v *CharacterSelect) Unload() {
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Render(screen *ebiten.Image) {
|
||||
func (v *CharacterSelect) Render(screen *d2surface.Surface) {
|
||||
v.background.RenderSegmented(screen, 4, 3, 0)
|
||||
v.d2HeroTitle.Render(screen)
|
||||
actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
|
||||
|
@ -210,10 +209,12 @@ func (v *CharacterSelect) Render(screen *ebiten.Image) {
|
|||
v.characterNameLabel[i].Render(screen)
|
||||
v.characterStatsLabel[i].Render(screen)
|
||||
v.characterExpLabel[i].Render(screen)
|
||||
v.characterImage[i].Render(screen, v.characterNameLabel[i].X-40, v.characterNameLabel[i].Y+50)
|
||||
screen.PushTranslation(v.characterNameLabel[i].X-40, v.characterNameLabel[i].Y+50)
|
||||
v.characterImage[i].Render(screen)
|
||||
screen.Pop()
|
||||
}
|
||||
if v.showDeleteConfirmation {
|
||||
ebitenutil.DrawRect(screen, 0.0, 0.0, 800.0, 600.0, color.RGBA{0, 0, 0, 128})
|
||||
screen.DrawRect(800, 600, color.RGBA{0, 0, 0, 128})
|
||||
v.okCancelBox.RenderSegmented(screen, 2, 1, 0)
|
||||
v.deleteCharConfirmLabel.Render(screen)
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common"
|
||||
dh "github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type labelItem struct {
|
||||
|
@ -107,7 +107,7 @@ func (v *Credits) Unload() {
|
|||
}
|
||||
|
||||
// Render renders the credits scene
|
||||
func (v *Credits) Render(screen *ebiten.Image) {
|
||||
func (v *Credits) Render(screen *d2surface.Surface) {
|
||||
v.creditsBackground.RenderSegmented(screen, 4, 3, 0)
|
||||
for _, label := range v.labels {
|
||||
if label.Available {
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"github.com/OpenDiablo2/OpenDiablo2/d2player"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
|
@ -87,8 +87,8 @@ func (v *Game) Load() []func() {
|
|||
func (v *Game) Unload() {
|
||||
}
|
||||
|
||||
func (v Game) Render(screen *ebiten.Image) {
|
||||
screen.Fill(color.Black)
|
||||
func (v Game) Render(screen *d2surface.Surface) {
|
||||
screen.Clear(color.Black)
|
||||
v.mapEngine.Render(screen)
|
||||
v.gameControls.Render(screen)
|
||||
}
|
||||
|
|
|
@ -18,9 +18,8 @@ import (
|
|||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
// MainMenu represents the main menu
|
||||
|
@ -223,7 +222,7 @@ func (v *MainMenu) Unload() {
|
|||
}
|
||||
|
||||
// Render renders the main menu
|
||||
func (v *MainMenu) Render(screen *ebiten.Image) {
|
||||
func (v *MainMenu) Render(screen *d2surface.Surface) {
|
||||
if v.ShowTrademarkScreen {
|
||||
v.trademarkBackground.RenderSegmented(screen, 4, 3, 0)
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package d2scene
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
|
@ -12,9 +11,9 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
"github.com/hajimehoshi/ebiten/inpututil"
|
||||
)
|
||||
|
||||
|
@ -160,7 +159,7 @@ func (v *MapEngineTest) Unload() {
|
|||
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
||||
func (v *MapEngineTest) Render(screen *d2surface.Surface) {
|
||||
v.mapEngine.Render(screen)
|
||||
screenX := v.uiManager.CursorX
|
||||
screenY := v.uiManager.CursorY
|
||||
|
@ -173,14 +172,6 @@ func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
|||
}
|
||||
|
||||
tileRect := curRegion.GetTileRect()
|
||||
line := fmt.Sprintf("%d, %d (Tile %d.%d, %d.%d)",
|
||||
screenX,
|
||||
screenY,
|
||||
int(math.Floor(worldX))-tileRect.Left,
|
||||
subtileX,
|
||||
int(math.Floor(worldY))-tileRect.Top,
|
||||
subtileY,
|
||||
)
|
||||
|
||||
levelFilesToPick := make([]string, 0)
|
||||
fileIndex := v.fileIndex
|
||||
|
@ -199,12 +190,20 @@ func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
|||
v.fileIndex = fileIndex
|
||||
}
|
||||
v.filesCount = len(levelFilesToPick)
|
||||
ebitenutil.DebugPrintAt(screen, line, 5, 5)
|
||||
ebitenutil.DebugPrintAt(screen, "Map: "+curRegion.GetLevelType().Name, 5, 17)
|
||||
ebitenutil.DebugPrintAt(screen, fmt.Sprintf("%v: %v/%v [%v, %v]", regionPath, fileIndex+1, v.filesCount, v.currentRegion, v.levelPreset), 5, 29)
|
||||
ebitenutil.DebugPrintAt(screen, "N - next region, P - previous region", 5, 41)
|
||||
ebitenutil.DebugPrintAt(screen, "Shift+N - next preset, Shift+P - previous preset", 5, 53)
|
||||
ebitenutil.DebugPrintAt(screen, "Ctrl+N - next file, Ctrl+P - previous file", 5, 65)
|
||||
|
||||
screen.PushTranslation(5, 5)
|
||||
screen.DrawText("%d, %d (Tile %d.%d, %d.%d)", screenX, screenY, int(math.Floor(worldX))-tileRect.Left, subtileX, int(math.Floor(worldY))-tileRect.Top, subtileY)
|
||||
screen.PushTranslation(0, 16)
|
||||
screen.DrawText("Map: " + curRegion.GetLevelType().Name)
|
||||
screen.PushTranslation(0, 16)
|
||||
screen.DrawText("%v: %v/%v [%v, %v]", regionPath, fileIndex+1, v.filesCount, v.currentRegion, v.levelPreset)
|
||||
screen.PushTranslation(0, 16)
|
||||
screen.DrawText("N - next region, P - previous region")
|
||||
screen.PushTranslation(0, 16)
|
||||
screen.DrawText("Shift+N - next preset, Shift+P - previous preset")
|
||||
screen.PushTranslation(0, 16)
|
||||
screen.DrawText("Ctrl+N - next file, Ctrl+P - previous file")
|
||||
screen.PopN(6)
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) Update(tickTime float64) {
|
||||
|
|
|
@ -16,8 +16,8 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common"
|
||||
dh "github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type HeroRenderInfo struct {
|
||||
|
@ -444,7 +444,7 @@ func (v SelectHeroClass) onOkButtonClicked() {
|
|||
v.sceneProvider.SetNextScene(CreateGame(v.sceneProvider, v.uiManager, v.soundManager, gameState))
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) Render(screen *ebiten.Image) {
|
||||
func (v *SelectHeroClass) Render(screen *d2surface.Surface) {
|
||||
v.bgImage.RenderSegmented(screen, 4, 3, 0)
|
||||
v.headingLabel.Render(screen)
|
||||
if v.selectedHero != d2enum.HeroNone {
|
||||
|
@ -560,7 +560,7 @@ func (v *SelectHeroClass) updateHeroSelectionHover(hero d2enum.Hero, canSelect b
|
|||
|
||||
}
|
||||
|
||||
func (v *SelectHeroClass) renderHero(screen *ebiten.Image, hero d2enum.Hero) {
|
||||
func (v *SelectHeroClass) renderHero(screen *d2surface.Surface, hero d2enum.Hero) {
|
||||
renderInfo := v.heroRenderInfo[hero]
|
||||
switch renderInfo.Stance {
|
||||
case d2enum.HeroStanceIdle:
|
||||
|
@ -647,7 +647,7 @@ func setSpriteToFirstFrame(sprite *d2render.Sprite) {
|
|||
}
|
||||
}
|
||||
|
||||
func drawSprite(sprite *d2render.Sprite, target *ebiten.Image) {
|
||||
func drawSprite(sprite *d2render.Sprite, target *d2surface.Surface) {
|
||||
if sprite != nil {
|
||||
sprite.Render(target)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import (
|
|||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
"github.com/hajimehoshi/ebiten/inpututil"
|
||||
)
|
||||
|
||||
|
@ -176,30 +175,41 @@ func (v *Engine) Update() {
|
|||
}
|
||||
|
||||
// Draw draws the game
|
||||
func (v Engine) Draw(screen *ebiten.Image) {
|
||||
func (v Engine) Draw(target *d2surface.Surface) {
|
||||
if v.loadingProgress < 1.0 {
|
||||
v.LoadingSprite.SetCurrentFrame(int(d2helper.Max(0, d2helper.Min(uint32(v.LoadingSprite.GetFrameCount()-1), uint32(float64(v.LoadingSprite.GetFrameCount()-1)*v.loadingProgress)))))
|
||||
v.LoadingSprite.Render(screen)
|
||||
v.LoadingSprite.Render(target)
|
||||
} else {
|
||||
if v.CurrentScene == nil {
|
||||
log.Fatal("no scene loaded")
|
||||
}
|
||||
v.CurrentScene.Render(screen)
|
||||
v.UIManager.Render(screen)
|
||||
v.CurrentScene.Render(target)
|
||||
v.UIManager.Render(target)
|
||||
}
|
||||
if v.showFPS {
|
||||
ebitenutil.DebugPrintAt(screen, "vsync:"+strconv.FormatBool(ebiten.IsVsyncEnabled())+"\nFPS:"+strconv.Itoa(int(ebiten.CurrentFPS())), 5, 565)
|
||||
target.PushTranslation(5, 565)
|
||||
target.DrawText("vsync:" + strconv.FormatBool(ebiten.IsVsyncEnabled()) + "\nFPS:" + strconv.Itoa(int(ebiten.CurrentFPS())))
|
||||
target.Pop()
|
||||
|
||||
cx, cy := ebiten.CursorPosition()
|
||||
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
ebitenutil.DebugPrintAt(screen, "Alloc "+strconv.FormatInt(int64(m.Alloc)/1024/1024, 10), 680, 0)
|
||||
ebitenutil.DebugPrintAt(screen, "Pause "+strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10), 680, 10)
|
||||
ebitenutil.DebugPrintAt(screen, "HeapSys "+strconv.FormatInt(int64(m.HeapSys/1024/1024), 10), 680, 20)
|
||||
ebitenutil.DebugPrintAt(screen, "NumGC "+strconv.FormatInt(int64(m.NumGC), 10), 680, 30)
|
||||
cx, cy := ebiten.CursorPosition()
|
||||
ebitenutil.DebugPrintAt(screen, "Coords "+strconv.FormatInt(int64(cx), 10)+","+strconv.FormatInt(int64(cy), 10), 680, 40)
|
||||
|
||||
target.PushTranslation(680, 0)
|
||||
target.DrawText("Alloc " + strconv.FormatInt(int64(m.Alloc)/1024/1024, 10))
|
||||
target.PushTranslation(0, 16)
|
||||
target.DrawText("Pause " + strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10))
|
||||
target.PushTranslation(0, 16)
|
||||
target.DrawText("HeapSys " + strconv.FormatInt(int64(m.HeapSys/1024/1024), 10))
|
||||
target.PushTranslation(0, 16)
|
||||
target.DrawText("NumGC " + strconv.FormatInt(int64(m.NumGC), 10))
|
||||
target.PushTranslation(0, 16)
|
||||
target.DrawText("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
|
||||
target.PopN(5)
|
||||
}
|
||||
|
||||
d2term.Render(d2surface.CreateSurface(screen))
|
||||
d2term.Render(target)
|
||||
}
|
||||
|
||||
// SetNextScene tells the engine what scene to load on the next update cycle
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type Hero struct {
|
||||
|
@ -52,8 +52,8 @@ func (v *Hero) Advance(tickTime float64) {
|
|||
v.AnimatedEntity.Advance(tickTime)
|
||||
}
|
||||
|
||||
func (v *Hero) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
v.AnimatedEntity.Render(target, offsetX, offsetY)
|
||||
func (v *Hero) Render(target *d2surface.Surface) {
|
||||
v.AnimatedEntity.Render(target)
|
||||
}
|
||||
|
||||
func (v *Hero) GetPosition() (float64, float64) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type NPC struct {
|
||||
|
@ -44,8 +44,8 @@ func (v *NPC) SetPaths(paths []d2common.Path) {
|
|||
v.HasPaths = len(paths) > 0
|
||||
}
|
||||
|
||||
func (v *NPC) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
v.AnimatedEntity.Render(target, offsetX, offsetY)
|
||||
func (v *NPC) Render(target *d2surface.Surface) {
|
||||
v.AnimatedEntity.Render(target)
|
||||
}
|
||||
|
||||
func (v *NPC) GetPosition() (float64, float64) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package d2coreinterface
|
||||
|
||||
import "github.com/hajimehoshi/ebiten"
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
|
||||
// Drawable represents an instance that can be drawn
|
||||
type Drawable interface {
|
||||
Render(target *ebiten.Image)
|
||||
Render(target *d2surface.Surface)
|
||||
GetSize() (width, height int)
|
||||
SetPosition(x, y int)
|
||||
GetPosition() (x, y int)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package d2coreinterface
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
|
||||
// Scene defines the function necessary for scene management
|
||||
type Scene interface {
|
||||
Load() []func()
|
||||
Unload()
|
||||
Render(screen *ebiten.Image)
|
||||
Render(target *d2surface.Surface)
|
||||
Update(tickTime float64)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -67,8 +68,8 @@ func (g *GameControls) Load() {
|
|||
}
|
||||
|
||||
// TODO: consider caching the panels to single image that is reused.
|
||||
func (g *GameControls) Render(target *ebiten.Image) {
|
||||
width, height := target.Size()
|
||||
func (g *GameControls) Render(target *d2surface.Surface) {
|
||||
width, height := target.GetSize()
|
||||
offset := int(0)
|
||||
|
||||
// Left globe holder
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2asset"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
// AnimatedEntity represents an entity on the map that can be animated
|
||||
|
@ -70,14 +70,13 @@ func (v AnimatedEntity) Wait() bool {
|
|||
}
|
||||
|
||||
// Render draws this animated entity onto the target
|
||||
func (v *AnimatedEntity) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
localX := (v.subcellX - v.subcellY) * 16
|
||||
localY := ((v.subcellX + v.subcellY) * 8) - 5
|
||||
v.composite.Render(
|
||||
target,
|
||||
int(v.offsetX)+offsetX+int(localX),
|
||||
int(v.offsetY)+offsetY+int(localY),
|
||||
func (v *AnimatedEntity) Render(target *d2surface.Surface) {
|
||||
target.PushTranslation(
|
||||
int(v.offsetX)+int((v.subcellX-v.subcellY)*16),
|
||||
int(v.offsetY)+int(((v.subcellX+v.subcellY)*8)-5),
|
||||
)
|
||||
defer target.Pop()
|
||||
v.composite.Render(target)
|
||||
}
|
||||
|
||||
func (v AnimatedEntity) GetDirection() int {
|
||||
|
|
|
@ -3,17 +3,16 @@ package d2mapengine
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type MapEntity interface {
|
||||
Render(target *ebiten.Image, screenX, screenY int)
|
||||
GetPosition() (float64, float64)
|
||||
Render(target *d2surface.Surface)
|
||||
Advance(tickTime float64)
|
||||
GetPosition() (float64, float64)
|
||||
}
|
||||
|
||||
type MapEngine struct {
|
||||
|
@ -134,7 +133,7 @@ func (me *MapEngine) Advance(tickTime float64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (me *MapEngine) Render(target *ebiten.Image) {
|
||||
func (me *MapEngine) Render(target *d2surface.Surface) {
|
||||
for _, region := range me.regions {
|
||||
if region.isVisbile(me.viewport) {
|
||||
region.renderPass1(me.viewport, target)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package d2mapengine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
|
@ -9,7 +8,6 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common"
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
||||
|
@ -20,8 +18,8 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2corehelper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type MapRegion struct {
|
||||
|
@ -234,7 +232,7 @@ func (mr *MapRegion) getTileWorldPosition(tileX, tileY int) (float64, float64) {
|
|||
return float64(tileX + mr.tileRect.Left), float64(tileY + mr.tileRect.Top)
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderPass1(viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderPass1(viewport *Viewport, target *d2surface.Surface) {
|
||||
for tileY := range mr.ds1.Tiles {
|
||||
for tileX, tile := range mr.ds1.Tiles[tileY] {
|
||||
worldX, worldY := mr.getTileWorldPosition(tileX, tileY)
|
||||
|
@ -247,7 +245,7 @@ func (mr *MapRegion) renderPass1(viewport *Viewport, target *ebiten.Image) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderPass2(entities []MapEntity, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderPass2(entities []MapEntity, viewport *Viewport, target *d2surface.Surface) {
|
||||
for tileY := range mr.ds1.Tiles {
|
||||
for tileX, tile := range mr.ds1.Tiles[tileY] {
|
||||
worldX, worldY := mr.getTileWorldPosition(tileX, tileY)
|
||||
|
@ -258,8 +256,9 @@ func (mr *MapRegion) renderPass2(entities []MapEntity, viewport *Viewport, targe
|
|||
for _, entity := range entities {
|
||||
entWorldX, entWorldY := entity.GetPosition()
|
||||
if entWorldX == worldX && entWorldY == worldY {
|
||||
screenX, screenY := viewport.GetTranslationScreen()
|
||||
entity.Render(target, screenX, screenY)
|
||||
target.PushTranslation(viewport.GetTranslationScreen())
|
||||
entity.Render(target)
|
||||
target.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,7 +268,7 @@ func (mr *MapRegion) renderPass2(entities []MapEntity, viewport *Viewport, targe
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderPass3(viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderPass3(viewport *Viewport, target *d2surface.Surface) {
|
||||
for tileY := range mr.ds1.Tiles {
|
||||
for tileX, tile := range mr.ds1.Tiles[tileY] {
|
||||
worldX, worldY := mr.getTileWorldPosition(tileX, tileY)
|
||||
|
@ -282,7 +281,7 @@ func (mr *MapRegion) renderPass3(viewport *Viewport, target *ebiten.Image) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderTilePass1(tile d2ds1.TileRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderTilePass1(tile d2ds1.TileRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
for _, wall := range tile.Walls {
|
||||
if !wall.Hidden && wall.Prop1 != 0 && wall.Type.LowerWall() {
|
||||
mr.renderWall(wall, viewport, target)
|
||||
|
@ -302,7 +301,7 @@ func (mr *MapRegion) renderTilePass1(tile d2ds1.TileRecord, viewport *Viewport,
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderTilePass2(tile d2ds1.TileRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderTilePass2(tile d2ds1.TileRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
for _, wall := range tile.Walls {
|
||||
if !wall.Hidden && wall.Type.UpperWall() {
|
||||
mr.renderWall(wall, viewport, target)
|
||||
|
@ -310,7 +309,7 @@ func (mr *MapRegion) renderTilePass2(tile d2ds1.TileRecord, viewport *Viewport,
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderTilePass3(tile d2ds1.TileRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderTilePass3(tile d2ds1.TileRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
for _, wall := range tile.Walls {
|
||||
if wall.Type == d2enum.Roof {
|
||||
mr.renderWall(wall, viewport, target)
|
||||
|
@ -318,7 +317,7 @@ func (mr *MapRegion) renderTilePass3(tile d2ds1.TileRecord, viewport *Viewport,
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderFloor(tile d2ds1.FloorShadowRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderFloor(tile d2ds1.FloorShadowRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
var img *ebiten.Image
|
||||
if !tile.Animated {
|
||||
img = mr.getImageCacheRecord(tile.Style, tile.Sequence, 0, tile.RandomIndex)
|
||||
|
@ -331,14 +330,15 @@ func (mr *MapRegion) renderFloor(tile d2ds1.FloorShadowRecord, viewport *Viewpor
|
|||
}
|
||||
|
||||
viewport.PushTranslationOrtho(-80, float64(tile.YAdjust))
|
||||
screenX, screenY := viewport.GetTranslationScreen()
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(screenX), float64(screenY))
|
||||
target.DrawImage(img, opts)
|
||||
viewport.PopTranslation()
|
||||
defer viewport.PopTranslation()
|
||||
|
||||
target.PushTranslation(viewport.GetTranslationScreen())
|
||||
defer target.Pop()
|
||||
|
||||
target.Render(img)
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderWall(tile d2ds1.WallRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderWall(tile d2ds1.WallRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
img := mr.getImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex)
|
||||
if img == nil {
|
||||
log.Printf("Render called on uncached wall {%v,%v,%v}", tile.Style, tile.Sequence, tile.Type)
|
||||
|
@ -346,14 +346,15 @@ func (mr *MapRegion) renderWall(tile d2ds1.WallRecord, viewport *Viewport, targe
|
|||
}
|
||||
|
||||
viewport.PushTranslationOrtho(-80, float64(tile.YAdjust))
|
||||
screenX, screenY := viewport.GetTranslationScreen()
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(screenX), float64(screenY))
|
||||
target.DrawImage(img, opts)
|
||||
viewport.PopTranslation()
|
||||
defer viewport.PopTranslation()
|
||||
|
||||
target.PushTranslation(viewport.GetTranslationScreen())
|
||||
defer target.Pop()
|
||||
|
||||
target.Render(img)
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderShadow(tile d2ds1.FloorShadowRecord, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderShadow(tile d2ds1.FloorShadowRecord, viewport *Viewport, target *d2surface.Surface) {
|
||||
img := mr.getImageCacheRecord(tile.Style, tile.Sequence, 13, tile.RandomIndex)
|
||||
if img == nil {
|
||||
log.Printf("Render called on uncached shadow {%v,%v}", tile.Style, tile.Sequence)
|
||||
|
@ -361,15 +362,16 @@ func (mr *MapRegion) renderShadow(tile d2ds1.FloorShadowRecord, viewport *Viewpo
|
|||
}
|
||||
|
||||
viewport.PushTranslationOrtho(-80, float64(tile.YAdjust))
|
||||
screenX, screenY := viewport.GetTranslationScreen()
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(screenX), float64(screenY))
|
||||
opts.ColorM = d2corehelper.ColorToColorM(color.RGBA{255, 255, 255, 160})
|
||||
target.DrawImage(img, opts)
|
||||
viewport.PopTranslation()
|
||||
defer viewport.PopTranslation()
|
||||
|
||||
target.PushTranslation(viewport.GetTranslationScreen())
|
||||
target.PushColor(color.RGBA{255, 255, 255, 160})
|
||||
defer target.PopN(2)
|
||||
|
||||
target.Render(img)
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderDebug(debugVisLevel int, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderDebug(debugVisLevel int, viewport *Viewport, target *d2surface.Surface) {
|
||||
for tileY := range mr.ds1.Tiles {
|
||||
for tileX := range mr.ds1.Tiles[tileY] {
|
||||
worldX, worldY := mr.getTileWorldPosition(tileX, tileY)
|
||||
|
@ -380,7 +382,7 @@ func (mr *MapRegion) renderDebug(debugVisLevel int, viewport *Viewport, target *
|
|||
}
|
||||
}
|
||||
|
||||
func (mr *MapRegion) renderTileDebug(x, y int, debugVisLevel int, viewport *Viewport, target *ebiten.Image) {
|
||||
func (mr *MapRegion) renderTileDebug(x, y int, debugVisLevel int, viewport *Viewport, target *d2surface.Surface) {
|
||||
if debugVisLevel > 0 {
|
||||
subtileColor := color.RGBA{80, 80, 255, 100}
|
||||
tileColor := color.RGBA{255, 255, 255, 255}
|
||||
|
@ -389,22 +391,34 @@ func (mr *MapRegion) renderTileDebug(x, y int, debugVisLevel int, viewport *View
|
|||
screenX2, screenY2 := viewport.WorldToScreen(float64(x+1), float64(y))
|
||||
screenX3, screenY3 := viewport.WorldToScreen(float64(x), float64(y+1))
|
||||
|
||||
ebitenutil.DrawLine(target, float64(screenX1), float64(screenY1), float64(screenX2), float64(screenY2), tileColor)
|
||||
ebitenutil.DrawLine(target, float64(screenX1), float64(screenY1), float64(screenX3), float64(screenY3), tileColor)
|
||||
ebitenutil.DebugPrintAt(target, fmt.Sprintf("%v,%v", x, y), screenX1-10, screenY1+10)
|
||||
target.PushTranslation(screenX1, screenY1)
|
||||
defer target.Pop()
|
||||
|
||||
target.DrawLine(screenX2-screenX1, screenY2-screenY1, tileColor)
|
||||
target.DrawLine(screenX3-screenX1, screenY3-screenY1, tileColor)
|
||||
target.PushTranslation(-10, 10)
|
||||
target.DrawText("%v, %v", x, y)
|
||||
target.Pop()
|
||||
|
||||
if debugVisLevel > 1 {
|
||||
for i := 1; i <= 4; i++ {
|
||||
x := i * 16
|
||||
y := i * 8
|
||||
|
||||
ebitenutil.DrawLine(target, float64(screenX1-x), float64(screenY1+y), float64(screenX1-x+80), float64(screenY1+y+40), subtileColor)
|
||||
ebitenutil.DrawLine(target, float64(screenX1+x), float64(screenY1+y), float64(screenX1+x-80), float64(screenY1+y+40), subtileColor)
|
||||
target.PushTranslation(-x, y)
|
||||
target.DrawLine(80, 40, subtileColor)
|
||||
target.Pop()
|
||||
|
||||
target.PushTranslation(x, y)
|
||||
target.DrawLine(-80, 40, subtileColor)
|
||||
target.Pop()
|
||||
}
|
||||
|
||||
tile := mr.ds1.Tiles[y][x]
|
||||
for i := range tile.Floors {
|
||||
ebitenutil.DebugPrintAt(target, fmt.Sprintf("f: %v-%v", tile.Floors[i].Style, tile.Floors[i].Sequence), screenX1-20, screenY1+10+(i+1)*14)
|
||||
for i, floor := range tile.Floors {
|
||||
target.PushTranslation(-20, 10+(i+1)*14)
|
||||
target.DrawText("f: %v-%v", floor.Style, floor.Sequence)
|
||||
target.Pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package d2surface
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2corehelper"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
)
|
||||
|
||||
type surfaceState struct {
|
||||
x int
|
||||
y int
|
||||
mode ebiten.CompositeMode
|
||||
x int
|
||||
y int
|
||||
mode ebiten.CompositeMode
|
||||
filter ebiten.Filter
|
||||
color color.Color
|
||||
}
|
||||
|
||||
type Surface struct {
|
||||
|
@ -23,7 +27,8 @@ func CreateSurface(image *ebiten.Image) *Surface {
|
|||
return &Surface{
|
||||
image: image,
|
||||
stateCurrent: surfaceState{
|
||||
mode: ebiten.CompositeModeSourceOver,
|
||||
filter: ebiten.FilterNearest,
|
||||
mode: ebiten.CompositeModeSourceOver,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +44,16 @@ func (s *Surface) PushCompositeMode(mode ebiten.CompositeMode) {
|
|||
s.stateCurrent.mode = mode
|
||||
}
|
||||
|
||||
func (s *Surface) PushFilter(filter ebiten.Filter) {
|
||||
s.stateStack = append(s.stateStack, s.stateCurrent)
|
||||
s.stateCurrent.filter = filter
|
||||
}
|
||||
|
||||
func (s *Surface) PushColor(color color.Color) {
|
||||
s.stateStack = append(s.stateStack, s.stateCurrent)
|
||||
s.stateCurrent.color = color
|
||||
}
|
||||
|
||||
func (s *Surface) Pop() {
|
||||
count := len(s.stateStack)
|
||||
if count == 0 {
|
||||
|
@ -49,14 +64,36 @@ func (s *Surface) Pop() {
|
|||
s.stateStack = s.stateStack[:count-1]
|
||||
}
|
||||
|
||||
func (s *Surface) PopN(n int) {
|
||||
for i := 0; i < n; i++ {
|
||||
s.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Surface) Render(image *ebiten.Image) error {
|
||||
opts := &ebiten.DrawImageOptions{CompositeMode: s.stateCurrent.mode}
|
||||
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
|
||||
opts.Filter = s.stateCurrent.filter
|
||||
if s.stateCurrent.color != nil {
|
||||
opts.ColorM = d2corehelper.ColorToColorM(s.stateCurrent.color)
|
||||
}
|
||||
|
||||
return s.image.DrawImage(image, opts)
|
||||
}
|
||||
|
||||
func (s *Surface) DrawText(text string) {
|
||||
ebitenutil.DebugPrintAt(s.image, text, s.stateCurrent.x, s.stateCurrent.y)
|
||||
func (s *Surface) DrawText(format string, params ...interface{}) {
|
||||
ebitenutil.DebugPrintAt(s.image, fmt.Sprintf(format, params...), s.stateCurrent.x, s.stateCurrent.y)
|
||||
}
|
||||
|
||||
func (s *Surface) DrawLine(x, y int, color color.Color) {
|
||||
ebitenutil.DrawLine(
|
||||
s.image,
|
||||
float64(s.stateCurrent.x),
|
||||
float64(s.stateCurrent.y),
|
||||
float64(s.stateCurrent.x+x),
|
||||
float64(s.stateCurrent.y+y),
|
||||
color,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *Surface) DrawRect(width, height int, color color.Color) {
|
||||
|
@ -70,6 +107,14 @@ func (s *Surface) DrawRect(width, height int, color color.Color) {
|
|||
)
|
||||
}
|
||||
|
||||
func (s *Surface) Clear(color color.Color) error {
|
||||
return s.image.Fill(color)
|
||||
}
|
||||
|
||||
func (s *Surface) GetSize() (int, int) {
|
||||
return s.image.Size()
|
||||
}
|
||||
|
||||
func (s *Surface) GetDepth() int {
|
||||
return len(s.stateStack)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package d2ui
|
|||
import (
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -72,7 +73,7 @@ func (v Scrollbar) GetLastDirChange() int {
|
|||
return v.lastDirChange
|
||||
}
|
||||
|
||||
func (v *Scrollbar) Render(target *ebiten.Image) {
|
||||
func (v *Scrollbar) Render(target *d2surface.Surface) {
|
||||
if !v.visible || v.maxOffset == 0 {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2corehelper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
@ -127,33 +127,38 @@ func CreateButton(buttonType ButtonType, text string) Button {
|
|||
}
|
||||
|
||||
result.normalImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
normalSurface := d2surface.CreateSurface(result.normalImage)
|
||||
_, fontHeight := font.GetTextMetrics(text)
|
||||
textY := int((result.height/2)-(int(fontHeight)/2)) + buttonLayout.TextOffset
|
||||
|
||||
buttonSprite.SetPosition(0, 0)
|
||||
buttonSprite.SetBlend(true)
|
||||
buttonSprite.RenderSegmented(result.normalImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, result.normalImage)
|
||||
buttonSprite.RenderSegmented(normalSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, normalSurface)
|
||||
if buttonLayout.AllowFrameChange {
|
||||
if totalButtonTypes > 1 {
|
||||
result.pressedImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.RenderSegmented(result.pressedImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+1)
|
||||
font.Render(-2, textY+2, text, color.RGBA{100, 100, 100, 255}, result.pressedImage)
|
||||
pressedSurface := d2surface.CreateSurface(result.pressedImage)
|
||||
buttonSprite.RenderSegmented(pressedSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+1)
|
||||
font.Render(-2, textY+2, text, color.RGBA{100, 100, 100, 255}, pressedSurface)
|
||||
}
|
||||
if totalButtonTypes > 2 {
|
||||
result.toggledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.RenderSegmented(result.toggledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+2)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, result.toggledImage)
|
||||
toggledSurface := d2surface.CreateSurface(result.toggledImage)
|
||||
buttonSprite.RenderSegmented(toggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+2)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, toggledSurface)
|
||||
}
|
||||
if totalButtonTypes > 3 {
|
||||
result.pressedToggledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.RenderSegmented(result.pressedToggledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+3)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, result.pressedToggledImage)
|
||||
pressedToggledSurface := d2surface.CreateSurface(result.pressedToggledImage)
|
||||
buttonSprite.RenderSegmented(pressedToggledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+3)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, pressedToggledSurface)
|
||||
}
|
||||
if buttonLayout.DisabledFrame != -1 {
|
||||
result.disabledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.RenderSegmented(result.disabledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.DisabledFrame)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, result.disabledImage)
|
||||
disabledSurface := d2surface.CreateSurface(result.disabledImage)
|
||||
buttonSprite.RenderSegmented(disabledSurface, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.DisabledFrame)
|
||||
font.Render(0, textY, text, color.RGBA{100, 100, 100, 255}, disabledSurface)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -173,25 +178,24 @@ func (v *Button) Activate() {
|
|||
}
|
||||
|
||||
// Render renders the button
|
||||
func (v Button) Render(target *ebiten.Image) {
|
||||
opts := &ebiten.DrawImageOptions{
|
||||
CompositeMode: ebiten.CompositeModeSourceAtop,
|
||||
Filter: ebiten.FilterNearest,
|
||||
}
|
||||
opts.GeoM.Translate(float64(v.x), float64(v.y))
|
||||
func (v Button) Render(target *d2surface.Surface) {
|
||||
target.PushCompositeMode(ebiten.CompositeModeSourceAtop)
|
||||
target.PushFilter(ebiten.FilterNearest)
|
||||
target.PushTranslation(v.x, v.y)
|
||||
defer target.PopN(3)
|
||||
|
||||
if !v.enabled {
|
||||
//opts.CompositeMode = ebiten.CompositeModeLighter
|
||||
opts.ColorM = d2corehelper.ColorToColorM(color.RGBA{128, 128, 128, 195})
|
||||
target.DrawImage(v.disabledImage, opts)
|
||||
target.PushColor(color.RGBA{128, 128, 128, 195})
|
||||
defer target.Pop()
|
||||
target.Render(v.disabledImage)
|
||||
} else if v.toggled && v.pressed {
|
||||
target.DrawImage(v.pressedToggledImage, opts)
|
||||
target.Render(v.pressedToggledImage)
|
||||
} else if v.pressed {
|
||||
target.DrawImage(v.pressedImage, opts)
|
||||
target.Render(v.pressedImage)
|
||||
} else if v.toggled {
|
||||
target.DrawImage(v.toggledImage, opts)
|
||||
target.Render(v.toggledImage)
|
||||
} else {
|
||||
target.DrawImage(v.normalImage, opts)
|
||||
target.Render(v.normalImage)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package d2ui
|
|||
import (
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -30,23 +31,25 @@ func CreateCheckbox(checkState bool) Checkbox {
|
|||
checkboxSprite.SetPosition(0, 0)
|
||||
|
||||
result.Image, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
checkboxSprite.RenderSegmented(result.Image, 1, 1, 0)
|
||||
surface := d2surface.CreateSurface(result.Image)
|
||||
checkboxSprite.RenderSegmented(surface, 1, 1, 0)
|
||||
|
||||
result.checkedImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
checkboxSprite.RenderSegmented(result.checkedImage, 1, 1, 1)
|
||||
checkedSurface := d2surface.CreateSurface(result.checkedImage)
|
||||
checkboxSprite.RenderSegmented(checkedSurface, 1, 1, 1)
|
||||
return result
|
||||
}
|
||||
|
||||
func (v Checkbox) Render(target *ebiten.Image) {
|
||||
opts := &ebiten.DrawImageOptions{
|
||||
CompositeMode: ebiten.CompositeModeSourceAtop,
|
||||
Filter: ebiten.FilterNearest,
|
||||
}
|
||||
opts.GeoM.Translate(float64(v.x), float64(v.y))
|
||||
if v.checkState == false {
|
||||
target.DrawImage(v.Image, opts)
|
||||
func (v Checkbox) Render(target *d2surface.Surface) {
|
||||
target.PushCompositeMode(ebiten.CompositeModeSourceAtop)
|
||||
target.PushTranslation(v.x, v.y)
|
||||
target.PushFilter(ebiten.FilterNearest)
|
||||
defer target.PopN(3)
|
||||
|
||||
if v.checkState {
|
||||
target.Render(v.checkedImage)
|
||||
} else {
|
||||
target.DrawImage(v.checkedImage, opts)
|
||||
target.Render(v.Image)
|
||||
}
|
||||
}
|
||||
func (v Checkbox) GetEnabled() bool {
|
||||
|
|
|
@ -8,8 +8,7 @@ import (
|
|||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
|
||||
"encoding/binary"
|
||||
|
||||
|
@ -106,7 +105,7 @@ func (v *Font) GetTextMetrics(text string) (width, height int) {
|
|||
}
|
||||
|
||||
// Render draws the font on the target surface
|
||||
func (v *Font) Render(x, y int, text string, color color.Color, target *ebiten.Image) {
|
||||
func (v *Font) Render(x, y int, text string, color color.Color, target *d2surface.Surface) {
|
||||
v.fontSprite.SetColorMod(color)
|
||||
v.fontSprite.SetBlend(false)
|
||||
|
||||
|
@ -115,7 +114,7 @@ func (v *Font) Render(x, y int, text string, color color.Color, target *ebiten.I
|
|||
maxCharHeight = d2helper.Max(maxCharHeight, uint32(m.Height))
|
||||
}
|
||||
|
||||
targetWidth, _ := target.Size()
|
||||
targetWidth, _ := target.GetSize()
|
||||
lines := strings.Split(text, "\n")
|
||||
for lineIdx, line := range lines {
|
||||
lineWidth, _ := v.GetTextMetrics(line)
|
||||
|
|
|
@ -3,6 +3,7 @@ package d2ui
|
|||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -42,23 +43,25 @@ func CreateLabel(fontPath, palettePath string) Label {
|
|||
}
|
||||
|
||||
// Render draws the label on the screen
|
||||
func (v *Label) Render(target *ebiten.Image) {
|
||||
func (v *Label) Render(target *d2surface.Surface) {
|
||||
if len(v.text) == 0 {
|
||||
return
|
||||
}
|
||||
v.cacheImage()
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
|
||||
x, y := v.X, v.Y
|
||||
if v.Alignment == LabelAlignCenter {
|
||||
opts.GeoM.Translate(float64(v.X-int(v.Width/2)), float64(v.Y))
|
||||
x, y = v.X-int(v.Width/2), v.Y
|
||||
} else if v.Alignment == LabelAlignRight {
|
||||
opts.GeoM.Translate(float64(v.X-int(v.Width)), float64(v.Y))
|
||||
} else {
|
||||
opts.GeoM.Translate(float64(v.X), float64(v.Y))
|
||||
x, y = v.X-int(v.Width), v.Y
|
||||
}
|
||||
opts.CompositeMode = ebiten.CompositeModeSourceAtop
|
||||
opts.Filter = ebiten.FilterNearest
|
||||
target.DrawImage(v.imageData, opts)
|
||||
|
||||
target.PushFilter(ebiten.FilterNearest)
|
||||
target.PushCompositeMode(ebiten.CompositeModeSourceAtop)
|
||||
target.PushTranslation(x, y)
|
||||
defer target.PopN(3)
|
||||
|
||||
target.Render(v.imageData)
|
||||
}
|
||||
|
||||
// SetPosition moves the label to the specified location
|
||||
|
@ -79,7 +82,8 @@ func (v *Label) cacheImage() {
|
|||
v.Width = width
|
||||
v.Height = height
|
||||
v.imageData, _ = ebiten.NewImage(int(width), int(height), ebiten.FilterNearest)
|
||||
v.font.Render(0, 0, v.text, v.Color, v.imageData)
|
||||
surface := d2surface.CreateSurface(v.imageData)
|
||||
v.font.Render(0, 0, v.text, v.Color, surface)
|
||||
}
|
||||
|
||||
// SetText sets the label's text
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -58,17 +59,16 @@ func (v *Manager) WaitForMouseRelease() {
|
|||
}
|
||||
|
||||
// Render renders all of the UI elements
|
||||
func (v *Manager) Render(screen *ebiten.Image) {
|
||||
func (v *Manager) Render(target *d2surface.Surface) {
|
||||
for _, widget := range v.widgets {
|
||||
if !widget.GetVisible() {
|
||||
continue
|
||||
if widget.GetVisible() {
|
||||
widget.Render(target)
|
||||
}
|
||||
widget.Render(screen)
|
||||
}
|
||||
|
||||
cx, cy := ebiten.CursorPosition()
|
||||
v.cursorSprite.SetPosition(cx, cy)
|
||||
v.cursorSprite.Render(screen)
|
||||
v.cursorSprite.Render(target)
|
||||
}
|
||||
|
||||
// Update updates all of the UI elements
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
@ -51,7 +52,7 @@ func repeatingKeyPressed(key ebiten.Key) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (v TextBox) Render(target *ebiten.Image) {
|
||||
func (v TextBox) Render(target *d2surface.Surface) {
|
||||
if !v.visible {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import (
|
|||
|
||||
"github.com/OpenDiablo2/D2Shared/d2helper"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2asset"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
)
|
||||
|
||||
type Sprite struct {
|
||||
|
@ -34,21 +33,19 @@ func MustLoadSprite(animationPath, palettePath string) *Sprite {
|
|||
return sprite
|
||||
}
|
||||
|
||||
func (s *Sprite) Render(target *ebiten.Image) error {
|
||||
func (s *Sprite) Render(target *d2surface.Surface) error {
|
||||
if err := s.advance(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, frameHeight := s.animation.GetCurrentFrameSize()
|
||||
|
||||
if err := s.animation.Render(target, s.x, s.y-frameHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
target.PushTranslation(s.x, s.y-frameHeight)
|
||||
defer target.Pop()
|
||||
return s.animation.Render(target)
|
||||
}
|
||||
|
||||
func (s *Sprite) RenderSegmented(target *ebiten.Image, segmentsX, segmentsY, frameOffset int) error {
|
||||
func (s *Sprite) RenderSegmented(target *d2surface.Surface, segmentsX, segmentsY, frameOffset int) error {
|
||||
if err := s.advance(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -62,7 +59,10 @@ func (s *Sprite) RenderSegmented(target *ebiten.Image, segmentsX, segmentsY, fra
|
|||
return err
|
||||
}
|
||||
|
||||
if err := s.animation.Render(target, s.x+currentX, s.y+currentY); err != nil {
|
||||
target.PushTranslation(s.x+currentX, s.y+currentY)
|
||||
err := s.animation.Render(target)
|
||||
target.Pop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
11
main.go
11
main.go
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2surface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2term"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
|
@ -67,9 +68,13 @@ func main() {
|
|||
|
||||
func update(screen *ebiten.Image) error {
|
||||
d2Engine.Update()
|
||||
if ebiten.IsDrawingSkipped() {
|
||||
return nil
|
||||
if !ebiten.IsDrawingSkipped() {
|
||||
surface := d2surface.CreateSurface(screen)
|
||||
d2Engine.Draw(surface)
|
||||
if surface.GetDepth() > 0 {
|
||||
panic("detected surface stack leak")
|
||||
}
|
||||
}
|
||||
d2Engine.Draw(screen)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue