1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-16 04:25:23 +00:00
OpenDiablo2/d2core/d2render/ebiten/ebiten_renderer.go

148 lines
3.9 KiB
Go
Raw Normal View History

package ebiten
import (
"image"
2020-07-23 16:56:50 +00:00
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
2020-07-08 13:16:16 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
2020-07-08 13:16:16 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
)
const (
2020-08-06 02:04:36 +00:00
screenWidth = 800
screenHeight = 600
defaultSaturation = 1.0
defaultBrightness = 1.0
defaultSkewX = 0.0
defaultSkewY = 0.0
defaultScaleX = 1.0
defaultScaleY = 1.0
)
// Renderer is an implementation of a renderer
2020-06-19 06:19:27 +00:00
type Renderer struct {
renderCallback func(surface d2interface.Surface) error
2020-06-19 06:19:27 +00:00
}
// Update updates the screen with the given *ebiten.Image
2020-06-19 06:19:27 +00:00
func (r *Renderer) Update(screen *ebiten.Image) error {
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
err := r.renderCallback(createEbitenSurface(r, screen))
2020-06-19 06:19:27 +00:00
if err != nil {
return err
}
2020-06-19 06:19:27 +00:00
return nil
}
// Layout returns the renderer screen width and height
func (r *Renderer) Layout(_, _ int) (width, height int) {
return screenWidth, screenHeight
2020-06-19 06:19:27 +00:00
}
// CreateRenderer creates an ebiten renderer instance
func CreateRenderer() (*Renderer, error) {
result := &Renderer{}
2020-07-08 13:16:16 +00:00
config := d2config.Config
ebiten.SetCursorMode(ebiten.CursorModeHidden)
2020-07-08 13:16:16 +00:00
ebiten.SetFullscreen(config.FullScreen)
ebiten.SetRunnableOnUnfocused(config.RunInBackground)
ebiten.SetVsyncEnabled(config.VsyncEnabled)
ebiten.SetMaxTPS(config.TicksPerSecond)
return result, nil
}
// GetRendererName returns the name of the renderer
func (*Renderer) GetRendererName() string {
return "Ebiten"
}
// SetWindowIcon sets the icon for the window, visible in the chrome of the window
func (*Renderer) SetWindowIcon(fileName string) {
_, iconImage, err := ebitenutil.NewImageFromFile(fileName, ebiten.FilterLinear)
if err == nil {
ebiten.SetWindowIcon([]image.Image{iconImage})
}
}
// IsDrawingSkipped returns a bool for whether or not the drawing has been skipped
func (r *Renderer) IsDrawingSkipped() bool {
return ebiten.IsDrawingSkipped()
}
// Run initializes the renderer
func (r *Renderer) Run(f func(surface d2interface.Surface) error, width, height int, title string) error {
2020-06-19 06:19:27 +00:00
r.renderCallback = f
2020-06-19 06:19:27 +00:00
ebiten.SetWindowTitle(title)
ebiten.SetWindowResizable(true)
ebiten.SetWindowSize(width, height)
2020-06-19 06:19:27 +00:00
return ebiten.RunGame(r)
}
// CreateSurface creates a renderer surface from an existing surface
func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surface, error) {
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
img := surface.(*ebitenSurface).image
sfcState := surfaceState{
filter: ebiten.FilterNearest,
effect: d2enum.DrawEffectNone,
saturation: defaultSaturation,
brightness: defaultBrightness,
skewX: defaultSkewX,
skewY: defaultSkewY,
scaleX: defaultScaleX,
scaleY: defaultScaleY,
}
result := createEbitenSurface(r, img, sfcState)
2020-02-09 19:12:04 +00:00
return result, nil
}
// NewSurface creates a new surface
func (r *Renderer) NewSurface(width, height int, filter d2enum.Filter) (d2interface.Surface, error) {
ebitenFilter := d2ToEbitenFilter(filter)
img, err := ebiten.NewImage(width, height, ebitenFilter)
if err != nil {
2020-02-09 19:12:04 +00:00
return nil, err
}
Decouple asset manager from renderer (#730) * improve AssetManager implementation Notable changes are: * removed the individual managers inside of d2asset, only one asset manager * AssetManager now has caches for the types of files it loads * created a type for TextDictionary (the txt file structs) * fixed a file path bug in d2loader Source * fixed a asset stream bug in d2loader Asset * d2loader.Loader now needs a d2config.Config on creation (for resolving locale files) * updated the mpq file in d2asset test data, added test case for "sub-directory" * added a Data method to d2asset.Asset. The data is cached on first full read. * renamed ArchiveDataStream to DataStream in d2interface * moved palette utility func out of d2asset and into d2util * bugfix for MacOS mpq loader issue * lint fixes, added data caching to filesystem asset * adding comment for mpq asset close * Decouple d2asset from d2render Notable changes in d2common: * d2dcc.Load now fully decodes the dcc and stores the directions/frames in the dcc struct * un-exported dcc.decodeDirection, it is only used in d2dcc * removed font interface from d2interface, we only have one font implementation * added `Renderer` method to d2interface.Surface, animations use this to bind to a renderer and create surfaces as they need * added `BindRenderer` method to animation interface Notable changes in d2common/d2asset: * **d2asset.NewAssetManager only needs to be passed a d2config.Config**, it is decoupled from d2render * exported Animation * Animation implementation binds to the renderer to create surfaces only on the first time it is rendered * font, dcc, dc6 initialization logic moved out of asset_manager.go * for dc6 and dcc animations, the process of decoding and creating render surfaces has been broken into different methods * the d2asset.Font struct now stores font table data for initialization purposes Notable changes in d2core/d2render: * Surfaces store a renderer reference, this allows animations to bind to the renderer and create a surface just-in-time **These last changes should have been a separate PR, sorry.** Notable changes in d2core/d2ui: * ui.NewSprite now handles creating an animation internally, only needs image and palette path as arguments Notable Changes in d2game: Because of the change in d2ui, all instances of this code pattern... ```golang animation, err := screen.asset.LoadAnimation(imgPath, palettePath) sprite, err := screen.ui.NewSprite(animation) ``` ... becomes this ... ```golang sprite, err := screen.ui.NewSprite(imgPath, palettePath) ```
2020-09-14 21:31:45 +00:00
return createEbitenSurface(r, img), nil
}
// IsFullScreen returns a boolean for whether or not the renderer is currently set to fullscreen
2020-02-09 19:12:04 +00:00
func (r *Renderer) IsFullScreen() bool {
return ebiten.IsFullscreen()
}
// SetFullScreen sets the renderer to fullscreen, given a boolean
2020-02-09 19:12:04 +00:00
func (r *Renderer) SetFullScreen(fullScreen bool) {
ebiten.SetFullscreen(fullScreen)
}
// SetVSyncEnabled enables vsync, given a boolean
2020-02-09 19:12:04 +00:00
func (r *Renderer) SetVSyncEnabled(vsync bool) {
ebiten.SetVsyncEnabled(vsync)
}
// GetVSyncEnabled returns a boolean for whether or not vsync is enabled
2020-02-09 19:12:04 +00:00
func (r *Renderer) GetVSyncEnabled() bool {
return ebiten.IsVsyncEnabled()
}
// GetCursorPos returns the current cursor position x,y coordinates
func (r *Renderer) GetCursorPos() (x, y int) {
2020-02-09 19:12:04 +00:00
return ebiten.CursorPosition()
}
// CurrentFPS returns the current frames per second of the renderer
func (r *Renderer) CurrentFPS() float64 {
return ebiten.CurrentFPS()
}