Compare commits

..

4 Commits

Author SHA1 Message Date
Bertrand Jung
49779c712b
Merge 1dd96726c4 into 6db3b11b36 2024-08-25 05:31:06 +02:00
Hajime Hoshi
6db3b11b36 internal/shader: refactoring 2024-08-25 12:29:24 +09:00
Hajime Hoshi
3547d999b1 internal/graphicsdriver/opengl/gl: bug fix: crash when log length is 0 2024-08-25 11:45:54 +09:00
Hajime Hoshi
dd63eef65e textinput: support every environment even without IME
Closes #3072
2024-08-24 01:06:52 +09:00
7 changed files with 109 additions and 59 deletions

View File

@ -0,0 +1,58 @@
// Copyright 2023 The Ebitengine 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.
//go:build (!darwin && !js && !windows) || ios
package textinput
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/internal/ui"
)
type textInput struct {
rs []rune
lastTick uint64
}
var theTextInput textInput
func (t *textInput) Start(x, y int) (chan State, func()) {
// AppendInputChars is updated only when the tick is updated.
// If the tick is not updated, return nil immediately.
tick := ui.Get().Tick()
if t.lastTick == tick {
return nil, nil
}
defer func() {
t.lastTick = tick
}()
s := newSession()
// This is a pseudo implementation with AppendInputChars without IME.
// This is tentative and should be replaced with IME in the future.
t.rs = ebiten.AppendInputChars(t.rs[:0])
if len(t.rs) == 0 {
return nil, nil
}
s.ch <- State{
Text: string(t.rs),
Committed: true,
}
// Keep the channel as end() resets s.ch.
ch := s.ch
s.end()
return ch, nil
}

View File

@ -1,25 +0,0 @@
// Copyright 2023 The Ebitengine 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.
//go:build (!darwin && !js && !windows) || ios
package textinput
type textInput struct{}
var theTextInput textInput
func (t *textInput) Start(x, y int) (chan State, func()) {
return nil, nil
}

View File

@ -592,6 +592,9 @@ func (c *defaultContext) GetInteger(pname uint32) int {
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
bufSize := c.GetProgrami(program, INFO_LOG_LENGTH)
if bufSize == 0 {
return ""
}
infoLog := make([]byte, bufSize)
C.glowGetProgramInfoLog(c.gpGetProgramInfoLog, C.GLuint(program), C.GLsizei(bufSize), nil, (*C.GLchar)(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
@ -605,6 +608,9 @@ func (c *defaultContext) GetProgrami(program uint32, pname uint32) int {
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
bufSize := c.GetShaderi(shader, INFO_LOG_LENGTH)
if bufSize == 0 {
return ""
}
infoLog := make([]byte, bufSize)
C.glowGetShaderInfoLog(c.gpGetShaderInfoLog, C.GLuint(shader), C.GLsizei(bufSize), nil, (*C.GLchar)(unsafe.Pointer(&infoLog[0])))
return string(infoLog)

View File

@ -300,6 +300,9 @@ func (c *defaultContext) GetInteger(pname uint32) int {
func (c *defaultContext) GetProgramInfoLog(program uint32) string {
bufSize := c.GetProgrami(program, INFO_LOG_LENGTH)
if bufSize == 0 {
return ""
}
infoLog := make([]byte, bufSize)
purego.SyscallN(c.gpGetProgramInfoLog, uintptr(program), uintptr(bufSize), 0, uintptr(unsafe.Pointer(&infoLog[0])))
return string(infoLog)
@ -313,6 +316,9 @@ func (c *defaultContext) GetProgrami(program uint32, pname uint32) int {
func (c *defaultContext) GetShaderInfoLog(shader uint32) string {
bufSize := c.GetShaderi(shader, INFO_LOG_LENGTH)
if bufSize == 0 {
return ""
}
infoLog := make([]byte, bufSize)
purego.SyscallN(c.gpGetShaderInfoLog, uintptr(shader), uintptr(bufSize), 0, uintptr(unsafe.Pointer(&infoLog[0])))
return string(infoLog)

View File

@ -55,9 +55,7 @@ type compileState struct {
ir shaderir.Program
funcs []function
vertexOutParams []shaderir.Type
fragmentInParams []shaderir.Type
funcs []function
global block
@ -292,18 +290,14 @@ func (cs *compileState) parse(f *ast.File) {
// Parse function names so that any other function call the others.
// The function data is provisional and will be updated soon.
var vertexOutParams []shaderir.Type
var fragmentInParams []shaderir.Type
for _, d := range f.Decls {
fd, ok := d.(*ast.FuncDecl)
if !ok {
continue
}
n := fd.Name.Name
if n == cs.vertexEntry {
continue
}
if n == cs.fragmentEntry {
continue
}
for _, f := range cs.funcs {
if f.name == n {
@ -321,6 +315,15 @@ func (cs *compileState) parse(f *ast.File) {
outT = append(outT, v.typ)
}
if n == cs.vertexEntry {
vertexOutParams = outT
continue
}
if n == cs.fragmentEntry {
fragmentInParams = inT
continue
}
cs.funcs = append(cs.funcs, function{
name: n,
ir: shaderir.Func{
@ -333,6 +336,26 @@ func (cs *compileState) parse(f *ast.File) {
})
}
// Check varying variables.
// In testings, there might not be vertex and fragment entry points.
if len(vertexOutParams) > 0 && len(fragmentInParams) > 0 {
if len(vertexOutParams) != len(fragmentInParams) {
cs.addError(0, "the number of vertex entry point's returning values and the number of fragment entry point's params must be the same")
}
for i, t := range vertexOutParams {
if !t.Equal(&fragmentInParams[i]) {
cs.addError(0, "vertex entry point's returning value types and fragment entry point's param types must match")
}
}
}
// Set varying veraibles.
if len(vertexOutParams) > 0 {
// TODO: Check that these params are not arrays or structs
// The 0th argument is a special variable for position and is not included in varying variables.
cs.ir.Varyings = append(cs.ir.Varyings, vertexOutParams[1:]...)
}
// Parse functions.
for _, d := range f.Decls {
if f, ok := d.(*ast.FuncDecl); ok {
@ -348,29 +371,6 @@ func (cs *compileState) parse(f *ast.File) {
return
}
// Parse varying veraibles.
// In testings, there might not be vertex and fragment entry points.
if cs.ir.VertexFunc.Block != nil && cs.ir.FragmentFunc.Block != nil {
if len(cs.fragmentInParams) != len(cs.vertexOutParams) {
cs.addError(0, "the number of vertex entry point's returning values and the number of fragment entry point's params must be the same")
}
for i, t := range cs.vertexOutParams {
if !t.Equal(&cs.fragmentInParams[i]) {
cs.addError(0, "vertex entry point's returning value types and fragment entry point's param types must match")
}
}
}
if cs.ir.VertexFunc.Block != nil {
// TODO: Check that these params are not arrays or structs
// The 0th argument is a special variable for position and is not included in varying variables.
cs.ir.Varyings = append(cs.ir.Varyings, cs.vertexOutParams[1:]...)
}
if len(cs.errs) > 0 {
return
}
for _, f := range cs.funcs {
cs.ir.Funcs = append(cs.ir.Funcs, f.ir)
}
@ -483,10 +483,8 @@ func (cs *compileState) parseDecl(b *block, fname string, d ast.Decl) ([]shaderi
switch d.Name.Name {
case cs.vertexEntry:
cs.ir.VertexFunc.Block = f.ir.Block
cs.vertexOutParams = f.ir.OutParams
case cs.fragmentEntry:
cs.ir.FragmentFunc.Block = f.ir.Block
cs.fragmentInParams = f.ir.InParams
default:
// The function is already registered for their names.
for i := range cs.funcs {

View File

@ -153,6 +153,8 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
if err := ui.error(); err != nil {
return err
}
ui.tick.Add(1)
}
// Update window icons during a frame, since an icon might be *ebiten.Image and

View File

@ -79,6 +79,7 @@ type UserInterface struct {
graphicsLibrary atomic.Int32
running atomic.Bool
terminated atomic.Bool
tick atomic.Uint64
whiteImage *Image
@ -230,3 +231,7 @@ func (u *UserInterface) isTerminated() bool {
func (u *UserInterface) setTerminated() {
u.terminated.Store(true)
}
func (u *UserInterface) Tick() uint64 {
return u.tick.Load()
}