mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
internal/ui: add Image
This is a preparation for a refactoring. Image will be a proxy to pass a graphics driver to the lower layer.
This commit is contained in:
parent
3e44a20b22
commit
e78f34aa26
@ -63,7 +63,7 @@ func (c *gameForUI) Layout(outsideWidth, outsideHeight float64, deviceScaleFacto
|
|||||||
// The shader program for the screen is special and doesn't work well with an image on an atlas.
|
// The shader program for the screen is special and doesn't work well with an image on an atlas.
|
||||||
// An image on an atlas is surrounded by a transparent edge,
|
// An image on an atlas is surrounded by a transparent edge,
|
||||||
// and the shader program unexpectedly picks the pixel on the edges.
|
// and the shader program unexpectedly picks the pixel on the edges.
|
||||||
c.offscreen.mipmap.SetIndependent(true)
|
c.offscreen.image.SetIndependent(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ow, oh
|
return ow, oh
|
||||||
@ -74,7 +74,7 @@ func (c *gameForUI) Update() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *gameForUI) Draw(screenScale float64, offsetX, offsetY float64, needsClearingScreen bool, framebufferYDirection graphicsdriver.YDirection, clearScreenEveryFrame, filterEnabled bool) error {
|
func (c *gameForUI) Draw(screenScale float64, offsetX, offsetY float64, needsClearingScreen bool, framebufferYDirection graphicsdriver.YDirection, clearScreenEveryFrame, filterEnabled bool) error {
|
||||||
c.offscreen.mipmap.SetVolatile(clearScreenEveryFrame)
|
c.offscreen.image.SetVolatile(clearScreenEveryFrame)
|
||||||
|
|
||||||
// Even though updateCount == 0, the offscreen is cleared and Draw is called.
|
// Even though updateCount == 0, the offscreen is cleared and Draw is called.
|
||||||
// Draw should not update the game state and then the screen should not be updated without Update, but
|
// Draw should not update the game state and then the screen should not be updated without Update, but
|
||||||
|
43
image.go
43
image.go
@ -22,7 +22,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ type Image struct {
|
|||||||
// See strings.Builder for similar examples.
|
// See strings.Builder for similar examples.
|
||||||
addr *Image
|
addr *Image
|
||||||
|
|
||||||
mipmap *mipmap.Mipmap
|
image *ui.Image
|
||||||
|
|
||||||
bounds image.Rectangle
|
bounds image.Rectangle
|
||||||
original *Image
|
original *Image
|
||||||
@ -58,7 +57,7 @@ func (i *Image) Size() (width, height int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) isDisposed() bool {
|
func (i *Image) isDisposed() bool {
|
||||||
return i.mipmap == nil
|
return i.image == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) isSubImage() bool {
|
func (i *Image) isSubImage() bool {
|
||||||
@ -205,9 +204,9 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
|||||||
vs := graphics.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, 1, 1, 1, 1)
|
vs := graphics.QuadVertices(sx0, sy0, sx1, sy1, a, b, c, d, tx, ty, 1, 1, 1, 1)
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
srcs := [graphics.ShaderImageNum]*ui.Image{img.image}
|
||||||
|
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, graphicsdriver.AddressUnsafe, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, canSkipMipmap(options.GeoM, filter))
|
i.image.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, graphicsdriver.AddressUnsafe, dstRegion, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, canSkipMipmap(options.GeoM, filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertex represents a vertex passed to DrawTriangles.
|
// Vertex represents a vertex passed to DrawTriangles.
|
||||||
@ -369,9 +368,9 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
is := make([]uint16, len(indices))
|
is := make([]uint16, len(indices))
|
||||||
copy(is, indices)
|
copy(is, indices)
|
||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
srcs := [graphics.ShaderImageNum]*ui.Image{img.image}
|
||||||
|
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, address, dstRegion, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, options.FillRule == EvenOdd, false)
|
i.image.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, address, dstRegion, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, options.FillRule == EvenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||||
@ -469,7 +468,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
is := make([]uint16, len(indices))
|
is := make([]uint16, len(indices))
|
||||||
copy(is, indices)
|
copy(is, indices)
|
||||||
|
|
||||||
var imgs [graphics.ShaderImageNum]*mipmap.Mipmap
|
var imgs [graphics.ShaderImageNum]*ui.Image
|
||||||
var imgw, imgh int
|
var imgw, imgh int
|
||||||
for i, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
if img == nil {
|
if img == nil {
|
||||||
@ -486,7 +485,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
panic("ebiten: all the source images must be the same size with the rectangle")
|
panic("ebiten: all the source images must be the same size with the rectangle")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imgs[i] = img.mipmap
|
imgs[i] = img.image
|
||||||
}
|
}
|
||||||
|
|
||||||
var sx, sy float32
|
var sx, sy float32
|
||||||
@ -519,7 +518,7 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
us := shader.convertUniforms(options.Uniforms)
|
||||||
|
|
||||||
i.mipmap.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, options.FillRule == EvenOdd, false)
|
i.image.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, options.FillRule == EvenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectShaderOptions represents options for DrawRectShader.
|
// DrawRectShaderOptions represents options for DrawRectShader.
|
||||||
@ -584,7 +583,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
|
|
||||||
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
mode := graphicsdriver.CompositeMode(options.CompositeMode)
|
||||||
|
|
||||||
var imgs [graphics.ShaderImageNum]*mipmap.Mipmap
|
var imgs [graphics.ShaderImageNum]*ui.Image
|
||||||
for i, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
if img == nil {
|
if img == nil {
|
||||||
continue
|
continue
|
||||||
@ -595,7 +594,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
if w, h := img.Size(); width != w || height != h {
|
if w, h := img.Size(); width != w || height != h {
|
||||||
panic("ebiten: all the source images must be the same size with the rectangle")
|
panic("ebiten: all the source images must be the same size with the rectangle")
|
||||||
}
|
}
|
||||||
imgs[i] = img.mipmap
|
imgs[i] = img.image
|
||||||
}
|
}
|
||||||
|
|
||||||
var sx, sy float32
|
var sx, sy float32
|
||||||
@ -631,7 +630,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
}
|
}
|
||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
us := shader.convertUniforms(options.Uniforms)
|
||||||
i.mipmap.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, false, canSkipMipmap(options.GeoM, graphicsdriver.FilterNearest))
|
i.image.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, false, canSkipMipmap(options.GeoM, graphicsdriver.FilterNearest))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubImage returns an image representing the portion of the image p visible through r.
|
// SubImage returns an image representing the portion of the image p visible through r.
|
||||||
@ -663,7 +662,7 @@ func (i *Image) SubImage(r image.Rectangle) image.Image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
img := &Image{
|
img := &Image{
|
||||||
mipmap: i.mipmap,
|
image: i.image,
|
||||||
bounds: r,
|
bounds: r,
|
||||||
original: orig,
|
original: orig,
|
||||||
}
|
}
|
||||||
@ -729,7 +728,7 @@ func (i *Image) at(x, y int) (r, g, b, a uint8) {
|
|||||||
if !image.Pt(x, y).In(i.Bounds()) {
|
if !image.Pt(x, y).In(i.Bounds()) {
|
||||||
return 0, 0, 0, 0
|
return 0, 0, 0, 0
|
||||||
}
|
}
|
||||||
pix, err := i.mipmap.Pixels(x, y, 1, 1)
|
pix, err := i.image.Pixels(x, y, 1, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if panicOnErrorAtImageAt {
|
if panicOnErrorAtImageAt {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -765,7 +764,7 @@ func (i *Image) Set(x, y int, clr color.Color) {
|
|||||||
|
|
||||||
r, g, b, a := clr.RGBA()
|
r, g, b, a := clr.RGBA()
|
||||||
pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}
|
pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}
|
||||||
if err := i.mipmap.ReplacePixels(pix, x, y, 1, 1); err != nil {
|
if err := i.image.ReplacePixels(pix, x, y, 1, 1); err != nil {
|
||||||
ui.SetError(err)
|
ui.SetError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -788,8 +787,8 @@ func (i *Image) Dispose() {
|
|||||||
if i.isSubImage() {
|
if i.isSubImage() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i.mipmap.MarkDisposed()
|
i.image.MarkDisposed()
|
||||||
i.mipmap = nil
|
i.image = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplacePixels replaces the pixels of the image with p.
|
// ReplacePixels replaces the pixels of the image with p.
|
||||||
@ -817,7 +816,7 @@ func (i *Image) ReplacePixels(pixels []byte) {
|
|||||||
// Do not need to copy pixels here.
|
// Do not need to copy pixels here.
|
||||||
// * In internal/mipmap, pixels are copied when necessary.
|
// * In internal/mipmap, pixels are copied when necessary.
|
||||||
// * In internal/shareable, pixels are copied to make its paddings.
|
// * In internal/shareable, pixels are copied to make its paddings.
|
||||||
if err := i.mipmap.ReplacePixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy()); err != nil {
|
if err := i.image.ReplacePixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy()); err != nil {
|
||||||
ui.SetError(err)
|
ui.SetError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -842,7 +841,7 @@ func NewImage(width, height int) *Image {
|
|||||||
panic(fmt.Sprintf("ebiten: height at NewImage must be positive but %d", height))
|
panic(fmt.Sprintf("ebiten: height at NewImage must be positive but %d", height))
|
||||||
}
|
}
|
||||||
i := &Image{
|
i := &Image{
|
||||||
mipmap: mipmap.New(width, height),
|
image: ui.NewImage(width, height),
|
||||||
bounds: image.Rect(0, 0, width, height),
|
bounds: image.Rect(0, 0, width, height),
|
||||||
}
|
}
|
||||||
i.addr = i
|
i.addr = i
|
||||||
@ -873,7 +872,7 @@ func NewImageFromImage(source image.Image) *Image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i := &Image{
|
i := &Image{
|
||||||
mipmap: mipmap.New(width, height),
|
image: ui.NewImage(width, height),
|
||||||
bounds: image.Rect(0, 0, width, height),
|
bounds: image.Rect(0, 0, width, height),
|
||||||
}
|
}
|
||||||
i.addr = i
|
i.addr = i
|
||||||
@ -884,7 +883,7 @@ func NewImageFromImage(source image.Image) *Image {
|
|||||||
|
|
||||||
func newScreenFramebufferImage(width, height int) *Image {
|
func newScreenFramebufferImage(width, height int) *Image {
|
||||||
i := &Image{
|
i := &Image{
|
||||||
mipmap: mipmap.NewScreenFramebufferMipmap(width, height),
|
image: ui.NewScreenFramebufferImage(width, height),
|
||||||
bounds: image.Rect(0, 0, width, height),
|
bounds: image.Rect(0, 0, width, height),
|
||||||
screen: true,
|
screen: true,
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func takeScreenshot(screen *Image) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
blackbg := !IsScreenTransparent()
|
blackbg := !IsScreenTransparent()
|
||||||
if err := screen.mipmap.DumpScreenshot(newname, blackbg); err != nil {
|
if err := screen.image.DumpScreenshot(newname, blackbg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
internal/ui/image.go
Normal file
96
internal/ui/image.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2022 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
mipmap *mipmap.Mipmap
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewImage(width, height int) *Image {
|
||||||
|
return &Image{
|
||||||
|
mipmap: mipmap.New(width, height),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewScreenFramebufferImage(width, height int) *Image {
|
||||||
|
return &Image{
|
||||||
|
mipmap: mipmap.NewScreenFramebufferMipmap(width, height),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) MarkDisposed() {
|
||||||
|
i.mipmap.MarkDisposed()
|
||||||
|
i.mipmap = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
||||||
|
var srcMipmaps [graphics.ShaderImageNum]*mipmap.Mipmap
|
||||||
|
for i, src := range srcs {
|
||||||
|
if src == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
srcMipmaps[i] = src.mipmap
|
||||||
|
}
|
||||||
|
|
||||||
|
var s *mipmap.Shader
|
||||||
|
if shader != nil {
|
||||||
|
s = shader.shader
|
||||||
|
}
|
||||||
|
|
||||||
|
i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms, evenOdd, canSkipMipmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) ReplacePixels(pix []byte, x, y, width, height int) error {
|
||||||
|
return i.mipmap.ReplacePixels(pix, x, y, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) Pixels(x, y, width, height int) ([]byte, error) {
|
||||||
|
return i.mipmap.Pixels(x, y, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) DumpScreenshot(name string, blackbg bool) error {
|
||||||
|
return i.mipmap.DumpScreenshot(name, blackbg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) SetIndependent(independent bool) {
|
||||||
|
i.mipmap.SetIndependent(independent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) SetVolatile(volatile bool) {
|
||||||
|
i.mipmap.SetVolatile(volatile)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Shader struct {
|
||||||
|
shader *mipmap.Shader
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShader(program *shaderir.Program) *Shader {
|
||||||
|
return &Shader{
|
||||||
|
shader: mipmap.NewShader(program),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Shader) MarkDisposed() {
|
||||||
|
s.shader.MarkDisposed()
|
||||||
|
s.shader = nil
|
||||||
|
}
|
@ -23,9 +23,9 @@ import (
|
|||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shader"
|
"github.com/hajimehoshi/ebiten/v2/internal/shader"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var shaderSuffix string
|
var shaderSuffix string
|
||||||
@ -111,7 +111,7 @@ func imageSrc%[1]dAt(pos vec2) vec4 {
|
|||||||
//
|
//
|
||||||
// For the details about the shader, see https://ebiten.org/documents/shader.html.
|
// For the details about the shader, see https://ebiten.org/documents/shader.html.
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
shader *mipmap.Shader
|
shader *ui.Shader
|
||||||
uniformNames []string
|
uniformNames []string
|
||||||
uniformTypes []shaderir.Type
|
uniformTypes []shaderir.Type
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ func __vertex(position vec2, texCoord vec2, color vec4) (vec4, vec2, vec4) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Shader{
|
return &Shader{
|
||||||
shader: mipmap.NewShader(s),
|
shader: ui.NewShader(s),
|
||||||
uniformNames: s.UniformNames,
|
uniformNames: s.UniformNames,
|
||||||
uniformTypes: s.Uniforms,
|
uniformTypes: s.Uniforms,
|
||||||
}, nil
|
}, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user