Adding modding folder with a hacked build.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"github.com/inkyblackness/hacked/ui/opengl"
|
||||
|
||||
mgl "github.com/go-gl/mathgl/mgl32"
|
||||
)
|
||||
|
||||
// Context provides current render properties.
|
||||
type Context struct {
|
||||
OpenGL opengl.OpenGL
|
||||
|
||||
ViewMatrix *mgl.Mat4
|
||||
ProjectionMatrix mgl.Mat4
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/inkyblackness/imgui-go/v3"
|
||||
|
||||
"github.com/inkyblackness/hacked/editor/graphics"
|
||||
)
|
||||
|
||||
// FrameImage renders an image centered and fitted within the given size.
|
||||
func FrameImage(label string, frameCache *graphics.FrameCache, key graphics.FrameCacheKey, size imgui.Vec2) {
|
||||
textureID := TextureIDForBitmapFrame(key)
|
||||
|
||||
imgui.PushStyleColor(imgui.StyleColorChildBg, imgui.Vec4{X: 0, Y: 0, Z: 0, W: 1})
|
||||
imgui.PushStyleVarVec2(imgui.StyleVarWindowPadding, imgui.Vec2{X: 0, Y: 0})
|
||||
if imgui.BeginChildV(label, size, false,
|
||||
imgui.WindowFlagsNoNav|imgui.WindowFlagsNoInputs|imgui.WindowFlagsNoScrollWithMouse|
|
||||
imgui.WindowFlagsNoScrollbar) {
|
||||
texture := frameCache.Texture(key)
|
||||
if texture != nil {
|
||||
var uv imgui.Vec2
|
||||
uv.X, uv.Y = texture.UV()
|
||||
width, height := texture.Size()
|
||||
|
||||
scaleFactor := float32(math.Min(float64(size.X/width), float64(size.Y/height)))
|
||||
imageSize := imgui.Vec2{X: width * scaleFactor, Y: height * scaleFactor}
|
||||
|
||||
bufferSize := imgui.Vec2{X: (size.X - imageSize.X) / 2, Y: (size.Y - imageSize.Y) / 2}
|
||||
imgui.SetCursorPos(bufferSize)
|
||||
|
||||
imgui.ImageV(textureID, imageSize, imgui.Vec2{}, uv,
|
||||
imgui.Vec4{X: 1, Y: 1, Z: 1, W: 1}, imgui.Vec4{X: 0, Y: 0, Z: 0, W: 0})
|
||||
}
|
||||
}
|
||||
imgui.EndChild()
|
||||
imgui.PopStyleVar()
|
||||
imgui.PopStyleColor()
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
mgl "github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/inkyblackness/hacked/ui/opengl"
|
||||
)
|
||||
|
||||
var orientationViewVertexShaderSource = `
|
||||
#version 150
|
||||
precision mediump float;
|
||||
|
||||
in vec3 vertexPosition;
|
||||
|
||||
uniform mat4 modelMatrix;
|
||||
uniform mat4 viewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
out vec3 position;
|
||||
out float zCenter;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0);
|
||||
zCenter = (projectionMatrix * viewMatrix * modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).z;
|
||||
position = gl_Position.xyz;
|
||||
}
|
||||
`
|
||||
|
||||
var orientationViewFragmentShaderSource = `
|
||||
#version 150
|
||||
precision mediump float;
|
||||
|
||||
uniform vec4 foregroundColor;
|
||||
uniform vec4 backgroundColor;
|
||||
|
||||
in vec3 position;
|
||||
in float zCenter;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main(void) {
|
||||
if (position.z <= zCenter)
|
||||
{
|
||||
fragColor = foregroundColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
fragColor = backgroundColor;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// OrientationView is a control that displays how an object is oriented.
|
||||
// This is still not working properly. The orientation arrow is not properly rotated,
|
||||
// and I suspect the typical issue of three-angle rotation versus quaternion rotation.
|
||||
// Though I doubt the original engine used quaternions, it remains too confusing for me.
|
||||
type OrientationView struct {
|
||||
context Context
|
||||
|
||||
program uint32
|
||||
vao *opengl.VertexArrayObject
|
||||
vertexPositionBuffer uint32
|
||||
vertexPositionAttrib int32
|
||||
modelMatrixUniform opengl.Matrix4Uniform
|
||||
viewMatrixUniform opengl.Matrix4Uniform
|
||||
projectionMatrixUniform opengl.Matrix4Uniform
|
||||
foregroundColorUniform opengl.Vector4Uniform
|
||||
backgroundColorUniform opengl.Vector4Uniform
|
||||
|
||||
baseOrientation mgl.Mat4
|
||||
rotation mgl.Vec3
|
||||
xRingVerticesStart int
|
||||
yRingVerticesStart int
|
||||
zRingVerticesStart int
|
||||
vertices int
|
||||
}
|
||||
|
||||
// NewOrientationView returns a new instance.
|
||||
func NewOrientationView(context Context, baseOrientation mgl.Mat4, rotation mgl.Vec3) *OrientationView {
|
||||
gl := context.OpenGL
|
||||
program, programErr := opengl.LinkNewStandardProgram(gl, orientationViewVertexShaderSource, orientationViewFragmentShaderSource)
|
||||
|
||||
if programErr != nil {
|
||||
panic(opengl.NamedShaderError{Name: "OrientationViewShader", Nested: programErr})
|
||||
}
|
||||
|
||||
view := &OrientationView{
|
||||
context: context,
|
||||
program: program,
|
||||
|
||||
vao: opengl.NewVertexArrayObject(gl, program),
|
||||
vertexPositionBuffer: gl.GenBuffers(1)[0],
|
||||
vertexPositionAttrib: gl.GetAttribLocation(program, "vertexPosition"),
|
||||
modelMatrixUniform: opengl.Matrix4Uniform(gl.GetUniformLocation(program, "modelMatrix")),
|
||||
viewMatrixUniform: opengl.Matrix4Uniform(gl.GetUniformLocation(program, "viewMatrix")),
|
||||
projectionMatrixUniform: opengl.Matrix4Uniform(gl.GetUniformLocation(program, "projectionMatrix")),
|
||||
foregroundColorUniform: opengl.Vector4Uniform(gl.GetUniformLocation(program, "foregroundColor")),
|
||||
backgroundColorUniform: opengl.Vector4Uniform(gl.GetUniformLocation(program, "backgroundColor")),
|
||||
|
||||
baseOrientation: baseOrientation,
|
||||
rotation: rotation,
|
||||
}
|
||||
{
|
||||
gl.BindBuffer(opengl.ARRAY_BUFFER, view.vertexPositionBuffer)
|
||||
var vertices []float32
|
||||
radius := 0.5
|
||||
vertices = append(vertices, 0.0, 0.0, 0.0)
|
||||
vertices = append(vertices, 0.4, 0.0, 0.0)
|
||||
vertices = append(vertices, 0.0, 0.0, 0.0)
|
||||
vertices = append(vertices, 0.0, 0.4, 0.0)
|
||||
vertices = append(vertices, 0.0, 0.0, 0.0)
|
||||
vertices = append(vertices, 0.0, 0.0, 0.4)
|
||||
|
||||
view.xRingVerticesStart = len(vertices)
|
||||
for angle := 0.0; angle < float64(toRad(360.0)); angle += float64(toRad(4.0)) {
|
||||
vertices = append(vertices, 0.0, float32(radius*math.Cos(angle)), float32(radius*math.Sin(angle)))
|
||||
}
|
||||
vertices = append(vertices, 0.0, float32(radius*math.Cos(0)), float32(radius*math.Sin(0)))
|
||||
|
||||
view.yRingVerticesStart = len(vertices)
|
||||
for angle := 0.0; angle < float64(toRad(360.0)); angle += float64(toRad(4.0)) {
|
||||
vertices = append(vertices, float32(radius*math.Cos(angle)), 0.0, float32(radius*math.Sin(angle)))
|
||||
}
|
||||
vertices = append(vertices, float32(radius*math.Cos(0)), 0.0, float32(radius*math.Sin(0)))
|
||||
|
||||
view.zRingVerticesStart = len(vertices)
|
||||
for angle := 0.0; angle < float64(toRad(360.0)); angle += float64(toRad(4.0)) {
|
||||
vertices = append(vertices, float32(radius*math.Cos(angle)), float32(radius*math.Sin(angle)), 0.0)
|
||||
}
|
||||
vertices = append(vertices, float32(radius*math.Cos(0)), float32(radius*math.Sin(0)), 0.0)
|
||||
|
||||
view.vertices = len(vertices)
|
||||
gl.BufferData(opengl.ARRAY_BUFFER, len(vertices)*4, vertices, opengl.STATIC_DRAW)
|
||||
gl.BindBuffer(opengl.ARRAY_BUFFER, 0)
|
||||
}
|
||||
view.vao.WithSetter(func(gl opengl.OpenGL) {
|
||||
gl.EnableVertexAttribArray(uint32(view.vertexPositionAttrib))
|
||||
gl.BindBuffer(opengl.ARRAY_BUFFER, view.vertexPositionBuffer)
|
||||
gl.VertexAttribOffset(uint32(view.vertexPositionAttrib), 3, opengl.FLOAT, false, 0, 0)
|
||||
gl.BindBuffer(opengl.ARRAY_BUFFER, 0)
|
||||
})
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
// Dispose cleans up resources of the view.
|
||||
func (view *OrientationView) Dispose() {
|
||||
gl := view.context.OpenGL
|
||||
view.vao.Dispose()
|
||||
gl.DeleteBuffers([]uint32{view.vertexPositionBuffer})
|
||||
gl.DeleteProgram(view.program)
|
||||
}
|
||||
|
||||
func toRad(degree float32) float32 {
|
||||
return (degree * math.Pi * 2.0) / 360.0
|
||||
}
|
||||
|
||||
// Render renders the orientation view for given orientation.
|
||||
func (view *OrientationView) Render(orientation mgl.Vec3) {
|
||||
gl := view.context.OpenGL
|
||||
|
||||
view.vao.OnShader(func() {
|
||||
view.projectionMatrixUniform.Set(gl, &view.context.ProjectionMatrix)
|
||||
view.viewMatrixUniform.Set(gl, view.context.ViewMatrix)
|
||||
|
||||
view.renderRings(false)
|
||||
view.renderArrow(
|
||||
mgl.Ident4().
|
||||
Mul4(mgl.HomogRotate3D(toRad(orientation[0]), mgl.Vec3{view.rotation[0], 0.0, 0.0})).
|
||||
Mul4(mgl.HomogRotate3D(toRad(orientation[1]), mgl.Vec3{0.0, view.rotation[1], 0.0})).
|
||||
Mul4(mgl.HomogRotate3D(toRad(orientation[2]), mgl.Vec3{0.0, 0.0, view.rotation[2]})))
|
||||
view.renderRings(true)
|
||||
})
|
||||
}
|
||||
|
||||
func (view *OrientationView) renderRings(front bool) {
|
||||
foreground := func(color [4]float32) [4]float32 {
|
||||
if !front {
|
||||
return [4]float32{0.0, 0.0, 0.0, 0.0}
|
||||
}
|
||||
return color
|
||||
}
|
||||
background := func(color [4]float32) [4]float32 {
|
||||
if front {
|
||||
return [4]float32{0.0, 0.0, 0.0, 0.0}
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
// draw Z-rotation ring
|
||||
view.renderRing(view.zRingVerticesStart, view.vertices,
|
||||
foreground([4]float32{0.0, 0.0, 1.0, 1.0}), background([4]float32{0.0, 0.0, 0.8, 0.7}))
|
||||
|
||||
// draw Y-rotation ring
|
||||
view.renderRing(view.yRingVerticesStart, view.zRingVerticesStart,
|
||||
foreground([4]float32{0.0, 1.0, 0.0, 1.0}), background([4]float32{0.0, 0.8, 0.0, 0.7}))
|
||||
|
||||
// draw X-rotation ring
|
||||
view.renderRing(view.xRingVerticesStart, view.yRingVerticesStart,
|
||||
foreground([4]float32{1.0, 0.0, 0.0, 1.0}), background([4]float32{0.8, 0.0, 0.0, 0.7}))
|
||||
}
|
||||
|
||||
func (view *OrientationView) renderRing(start, end int, foregroundColor, backgroundColor [4]float32) {
|
||||
gl := view.context.OpenGL
|
||||
|
||||
modelMatrix := mgl.Ident4().Mul4(view.baseOrientation)
|
||||
view.foregroundColorUniform.Set(gl, &foregroundColor)
|
||||
view.backgroundColorUniform.Set(gl, &backgroundColor)
|
||||
view.modelMatrixUniform.Set(gl, &modelMatrix)
|
||||
gl.DrawArrays(opengl.LINES, int32(start)/3, int32(end-start)/3)
|
||||
}
|
||||
|
||||
func (view *OrientationView) renderArrow(rotation mgl.Mat4) {
|
||||
gl := view.context.OpenGL
|
||||
|
||||
modelMatrix := mgl.Ident4().Mul4(view.baseOrientation).Mul4(rotation)
|
||||
view.foregroundColorUniform.Set(gl, &[4]float32{0.0, 0.0, 1.0, 1.0})
|
||||
view.backgroundColorUniform.Set(gl, &[4]float32{0.0, 0.0, 0.6, 1.0})
|
||||
view.modelMatrixUniform.Set(gl, &modelMatrix)
|
||||
gl.DrawArrays(opengl.LINES, 4, 2)
|
||||
|
||||
modelMatrix = mgl.Ident4().Mul4(view.baseOrientation).Mul4(rotation)
|
||||
view.foregroundColorUniform.Set(gl, &[4]float32{0.0, 1.0, 0.0, 1.0})
|
||||
view.backgroundColorUniform.Set(gl, &[4]float32{0.0, 0.6, 0.0, 1.0})
|
||||
view.modelMatrixUniform.Set(gl, &modelMatrix)
|
||||
gl.DrawArrays(opengl.LINES, 2, 2)
|
||||
|
||||
modelMatrix = mgl.Ident4().Mul4(view.baseOrientation).Mul4(rotation)
|
||||
view.foregroundColorUniform.Set(gl, &[4]float32{1.0, 0.0, 0.0, 1.0})
|
||||
view.backgroundColorUniform.Set(gl, &[4]float32{0.6, 0.0, 0.0, 1.0})
|
||||
view.modelMatrixUniform.Set(gl, &modelMatrix)
|
||||
gl.DrawArrays(opengl.LINES, 0, 2)
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"github.com/inkyblackness/imgui-go/v3"
|
||||
|
||||
"github.com/inkyblackness/hacked/editor/graphics"
|
||||
"github.com/inkyblackness/hacked/ss1/resource"
|
||||
"github.com/inkyblackness/hacked/ui/gui"
|
||||
)
|
||||
|
||||
const (
|
||||
// BitmapTextureTypeResource specifies a bitmap texture directly from resources.
|
||||
BitmapTextureTypeResource = 0x00
|
||||
// BitmapTextureTypeFrame specifies a bitmap texture from the frame cache.
|
||||
BitmapTextureTypeFrame = 0x01
|
||||
)
|
||||
|
||||
// TextureIDForBitmapTexture returns a texture ID that identifies a bitmap texture from resources.
|
||||
func TextureIDForBitmapTexture(key resource.Key) imgui.TextureID {
|
||||
id := imgui.TextureID(gui.ImageTypeBitmapTexture) << 56
|
||||
id |= imgui.TextureID(BitmapTextureTypeResource) << 48
|
||||
id |= imgui.TextureID(key.Lang) << 32
|
||||
id |= imgui.TextureID(key.ID) << 16
|
||||
id |= imgui.TextureID(key.Index & 0xFFFF)
|
||||
return id
|
||||
}
|
||||
|
||||
// TextureIDForBitmapFrame returns a texture ID that identifies a bitmap texture from frame cache.
|
||||
func TextureIDForBitmapFrame(key graphics.FrameCacheKey) imgui.TextureID {
|
||||
id := imgui.TextureID(gui.ImageTypeBitmapTexture) << 56
|
||||
id |= imgui.TextureID(BitmapTextureTypeFrame) << 48
|
||||
id |= imgui.TextureID(key)
|
||||
return id
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/inkyblackness/imgui-go/v3"
|
||||
|
||||
"github.com/inkyblackness/hacked/editor/graphics"
|
||||
"github.com/inkyblackness/hacked/ss1/resource"
|
||||
)
|
||||
|
||||
// TextureImage renders an image centered and fitted within the given size.
|
||||
func TextureImage(label string, cache *graphics.TextureCache, key resource.Key, size imgui.Vec2) {
|
||||
textureID := TextureIDForBitmapTexture(key)
|
||||
|
||||
imgui.PushStyleColor(imgui.StyleColorChildBg, imgui.Vec4{X: 0, Y: 0, Z: 0, W: 1})
|
||||
imgui.PushStyleVarVec2(imgui.StyleVarWindowPadding, imgui.Vec2{X: 0, Y: 0})
|
||||
if imgui.BeginChildV(label, size, false,
|
||||
imgui.WindowFlagsNoNav|imgui.WindowFlagsNoInputs|imgui.WindowFlagsNoScrollWithMouse|
|
||||
imgui.WindowFlagsNoScrollbar) {
|
||||
texture, err := cache.Texture(key)
|
||||
if err == nil {
|
||||
var uv imgui.Vec2
|
||||
uv.X, uv.Y = texture.UV()
|
||||
width, height := texture.Size()
|
||||
|
||||
scaleFactor := float32(math.Min(float64(size.X/width), float64(size.Y/height)))
|
||||
imageSize := imgui.Vec2{X: width * scaleFactor, Y: height * scaleFactor}
|
||||
|
||||
bufferSize := imgui.Vec2{X: (size.X - imageSize.X) / 2, Y: (size.Y - imageSize.Y) / 2}
|
||||
imgui.SetCursorPos(bufferSize)
|
||||
|
||||
imgui.ImageV(textureID, imageSize, imgui.Vec2{}, uv,
|
||||
imgui.Vec4{X: 1, Y: 1, Z: 1, W: 1}, imgui.Vec4{X: 0, Y: 0, Z: 0, W: 0})
|
||||
}
|
||||
}
|
||||
imgui.EndChild()
|
||||
imgui.PopStyleVar()
|
||||
imgui.PopStyleColor()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/inkyblackness/hacked/ui/opengl"
|
||||
)
|
||||
|
||||
// TextureRenderer is a renderer within which something can be rendered onto a texture.
|
||||
// This texture can then be used to be displayed.
|
||||
type TextureRenderer struct {
|
||||
gl opengl.OpenGL
|
||||
|
||||
framebuffer uint32
|
||||
texture uint32
|
||||
|
||||
width int32
|
||||
height int32
|
||||
}
|
||||
|
||||
// NewTextureRenderer returns a new instance.
|
||||
func NewTextureRenderer(gl opengl.OpenGL) *TextureRenderer {
|
||||
renderer := &TextureRenderer{
|
||||
gl: gl,
|
||||
|
||||
framebuffer: gl.GenFramebuffers(1)[0],
|
||||
texture: gl.GenTextures(1)[0],
|
||||
|
||||
width: 200,
|
||||
height: 200,
|
||||
}
|
||||
|
||||
gl.BindTexture(opengl.TEXTURE_2D, renderer.texture)
|
||||
gl.TexParameteri(opengl.TEXTURE_2D, opengl.TEXTURE_MAG_FILTER, opengl.NEAREST)
|
||||
gl.TexParameteri(opengl.TEXTURE_2D, opengl.TEXTURE_MIN_FILTER, opengl.NEAREST)
|
||||
offset := unsafe.Pointer(uintptr(0)) // nolint: govet
|
||||
gl.TexImage2D(opengl.TEXTURE_2D, 0, opengl.RGBA, renderer.width, renderer.height, 0, opengl.RGBA, opengl.UNSIGNED_BYTE, offset)
|
||||
// gl.GenerateMipmap(opengl.TEXTURE_2D)
|
||||
gl.BindTexture(opengl.TEXTURE_2D, 0)
|
||||
|
||||
renderer.onFramebuffer(func() {
|
||||
gl.BindTexture(opengl.TEXTURE_2D, renderer.texture)
|
||||
gl.FramebufferTexture(opengl.FRAMEBUFFER, opengl.COLOR_ATTACHMENT0, renderer.texture, 0)
|
||||
gl.DrawBuffers([]uint32{opengl.COLOR_ATTACHMENT0})
|
||||
gl.BindTexture(opengl.TEXTURE_2D, 0)
|
||||
|
||||
// result := gl.CheckFramebufferStatus(opengl.FRAMEBUFFER)
|
||||
// fmt.Printf("status: 0x%04X\n", result)
|
||||
// result == FRAMEBUFFER_COMPLETE == 0x8CD5
|
||||
})
|
||||
return renderer
|
||||
}
|
||||
|
||||
// Dispose cleans up resources.
|
||||
func (renderer *TextureRenderer) Dispose() {
|
||||
gl := renderer.gl
|
||||
gl.DeleteFramebuffers([]uint32{renderer.framebuffer})
|
||||
gl.DeleteTextures([]uint32{renderer.texture})
|
||||
}
|
||||
|
||||
// Handle returns the texture handle.
|
||||
func (renderer *TextureRenderer) Handle() uint32 {
|
||||
return renderer.texture
|
||||
}
|
||||
|
||||
// Size returns the dimensions of the texture, in pixels.
|
||||
func (renderer *TextureRenderer) Size() (width, height float32) {
|
||||
return float32(renderer.width), float32(renderer.height)
|
||||
}
|
||||
|
||||
// Render calls the nested function. All drawing commands within this function will end up in the texture.
|
||||
func (renderer *TextureRenderer) Render(nested func()) {
|
||||
gl := renderer.gl
|
||||
renderer.onFramebuffer(func() {
|
||||
gl.Viewport(0, 0, renderer.width, renderer.height)
|
||||
gl.ClearColor(0.0, 0.0, 0.0, 0.0)
|
||||
gl.Clear(opengl.COLOR_BUFFER_BIT | opengl.DEPTH_BUFFER_BIT)
|
||||
|
||||
nested()
|
||||
})
|
||||
}
|
||||
|
||||
func (renderer *TextureRenderer) onFramebuffer(nested func()) {
|
||||
gl := renderer.gl
|
||||
gl.BindFramebuffer(opengl.FRAMEBUFFER, renderer.framebuffer)
|
||||
nested()
|
||||
gl.BindFramebuffer(opengl.FRAMEBUFFER, 0)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/inkyblackness/imgui-go/v3"
|
||||
|
||||
"github.com/inkyblackness/hacked/editor/graphics"
|
||||
"github.com/inkyblackness/hacked/ss1/resource"
|
||||
)
|
||||
|
||||
// TextureSelector renders a horizontal list of game textures, with selection capability.
|
||||
func TextureSelector(label string, width float32, guiScale float32,
|
||||
count int, selectedIndex int, cache *graphics.TextureCache, keyResolver func(int) resource.Key,
|
||||
tooltipText func(int) string,
|
||||
changeCallback func(int)) {
|
||||
if imgui.BeginChildV(label, imgui.Vec2{X: width * guiScale, Y: 100 * guiScale}, true,
|
||||
imgui.WindowFlagsHorizontalScrollbar|imgui.WindowFlagsNoScrollWithMouse) {
|
||||
for i := 0; i < count; i++ {
|
||||
key := keyResolver(i)
|
||||
imgui.PushStyleVarVec2(imgui.StyleVarWindowPadding, imgui.Vec2{X: 0, Y: 0})
|
||||
if imgui.BeginChildV(fmt.Sprintf("%3d", i), imgui.Vec2{X: 80 * guiScale, Y: 64 * guiScale}, false,
|
||||
imgui.WindowFlagsNoNav|imgui.WindowFlagsNoScrollWithMouse) {
|
||||
imgui.BeginGroup()
|
||||
if imgui.SelectableV("", selectedIndex == i, 0, imgui.Vec2{X: 0, Y: 64 * guiScale}) {
|
||||
changeCallback(i)
|
||||
}
|
||||
imgui.SameLine()
|
||||
TextureImage(fmt.Sprintf("%3d", i), cache, key, imgui.Vec2{X: 64 * guiScale, Y: 64 * guiScale})
|
||||
imgui.EndGroup()
|
||||
if imgui.IsItemHovered() {
|
||||
text := tooltipText(i)
|
||||
if len(text) > 0 {
|
||||
imgui.SetTooltip(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
imgui.EndChild()
|
||||
imgui.PopStyleVar()
|
||||
imgui.SameLine()
|
||||
}
|
||||
}
|
||||
imgui.EndChild()
|
||||
}
|
||||
Reference in New Issue
Block a user