mirror of
https://github.com/mattrberry/crab.git
synced 2024-12-27 09:58:55 +01:00
very minimal imgui frontend
This commit is contained in:
parent
3b71156bd3
commit
c7bc2c31f9
5 changed files with 112 additions and 16 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@
|
|||
/.shards/
|
||||
*.dwarf
|
||||
/shard.lock
|
||||
cimgui.so
|
||||
imgui.ini
|
||||
|
|
|
@ -18,6 +18,10 @@ dependencies:
|
|||
github: ysbaddaden/sdl.cr
|
||||
lib_gl:
|
||||
github: nulldotpro/LibGL
|
||||
imgui:
|
||||
github: oprypin/crystal-imgui
|
||||
imgui-backends:
|
||||
github: mattrberry/crystal-imgui-backends
|
||||
|
||||
development_dependencies:
|
||||
stumpy_png:
|
||||
|
|
|
@ -3,6 +3,9 @@ require "option_parser"
|
|||
|
||||
require "bitfield"
|
||||
require "sdl"
|
||||
require "imgui"
|
||||
require "imgui-backends"
|
||||
require "imgui-backends/lib"
|
||||
|
||||
require "./crab/common/*"
|
||||
require "./crab/gb"
|
||||
|
|
|
@ -49,32 +49,87 @@ private class DisplayImpl < Display
|
|||
SCALE = 4
|
||||
SHADERS = "src/crab/common/shaders"
|
||||
|
||||
@window : SDL::Window
|
||||
@gl_context : LibSDL::GLContext
|
||||
@io : ImGui::ImGuiIO
|
||||
|
||||
@microseconds = 0
|
||||
@frames = 0
|
||||
@last_time = Time.utc
|
||||
@seconds : Int32 = Time.utc.second
|
||||
|
||||
@blend : Bool = false
|
||||
@enable_blend = false
|
||||
@blending = false
|
||||
@enable_overlay = false
|
||||
|
||||
@opengl_info : OpenGLInfo
|
||||
|
||||
def initialize(@console : Display::Console)
|
||||
@window = SDL::Window.new(window_title(59.7), console.width * SCALE, console.height * SCALE, flags: SDL::Window::Flags::OPENGL)
|
||||
setup_gl
|
||||
end
|
||||
|
||||
def draw(framebuffer : Slice(UInt16)) : Nil
|
||||
LibGL.tex_image_2d(LibGL::TEXTURE_2D, 0, LibGL::RGB5, @console.width, @console.height, 0, LibGL::RGBA, LibGL::UNSIGNED_SHORT_1_5_5_5_REV, framebuffer)
|
||||
LibGL.draw_arrays(LibGL::TRIANGLE_STRIP, 0, 4)
|
||||
LibSDL.gl_swap_window(@window)
|
||||
update_draw_count
|
||||
@gl_context = setup_gl
|
||||
@opengl_info = OpenGLInfo.new
|
||||
@io = setup_imgui
|
||||
end
|
||||
|
||||
def toggle_blending : Nil
|
||||
if @blend
|
||||
if @blending
|
||||
LibGL.disable(LibGL::BLEND)
|
||||
else
|
||||
LibGL.enable(LibGL::BLEND)
|
||||
end
|
||||
@blend = !@blend
|
||||
@blending = @enable_blend = !@blending
|
||||
end
|
||||
|
||||
def draw(framebuffer : Slice(UInt16)) : Nil
|
||||
render_game(framebuffer)
|
||||
render_imgui
|
||||
LibSDL.gl_swap_window(@window)
|
||||
update_draw_count
|
||||
end
|
||||
|
||||
private def render_game(framebuffer : Slice(UInt16)) : Nil
|
||||
LibGL.tex_image_2d(LibGL::TEXTURE_2D, 0, LibGL::RGB5, @console.width, @console.height, 0, LibGL::RGBA, LibGL::UNSIGNED_SHORT_1_5_5_5_REV, framebuffer)
|
||||
LibGL.draw_arrays(LibGL::TRIANGLE_STRIP, 0, 4)
|
||||
end
|
||||
|
||||
private def render_imgui : Nil
|
||||
ImGui::OpenGL3.new_frame
|
||||
ImGui::SDL2.new_frame(@window)
|
||||
ImGui.new_frame
|
||||
|
||||
overlay_height = 10.0
|
||||
|
||||
if LibSDL.get_mouse_focus
|
||||
if ImGui.begin_main_menu_bar
|
||||
if ImGui.begin_menu "File"
|
||||
ImGui.menu_item "Overlay", "", pointerof(@enable_overlay)
|
||||
ImGui.menu_item "Blend", "", pointerof(@enable_blend)
|
||||
toggle_blending if @enable_blend ^ @blending
|
||||
ImGui.end_menu
|
||||
end
|
||||
overlay_height += ImGui.get_window_size.y
|
||||
ImGui.end_main_menu_bar
|
||||
end
|
||||
end
|
||||
|
||||
if @enable_overlay
|
||||
ImGui.set_next_window_pos(ImGui::ImVec2.new 10, overlay_height)
|
||||
ImGui.set_next_window_bg_alpha(0.5)
|
||||
ImGui.begin("fps", pointerof(@enable_overlay),
|
||||
ImGui::ImGuiWindowFlags::NoDecoration | ImGui::ImGuiWindowFlags::NoMove |
|
||||
ImGui::ImGuiWindowFlags::NoSavedSettings)
|
||||
io_framerate = @io.framerate
|
||||
ImGui.text("FPS: #{io_framerate.format(decimal_places: 1)}")
|
||||
ImGui.text("Frame time: #{(1000 / io_framerate).format(decimal_places: 3)}ms")
|
||||
ImGui.separator
|
||||
ImGui.text("OpenGL")
|
||||
ImGui.text(" Version: #{@opengl_info.version}")
|
||||
ImGui.text(" Shading: #{@opengl_info.shading}")
|
||||
ImGui.end
|
||||
end
|
||||
|
||||
ImGui.render
|
||||
ImGui::OpenGL3.render_draw_data(ImGui.get_draw_data)
|
||||
end
|
||||
|
||||
private def window_title(fps : Float) : String
|
||||
|
@ -112,7 +167,7 @@ private class DisplayImpl < Display
|
|||
shader
|
||||
end
|
||||
|
||||
private def setup_gl : Nil
|
||||
private def setup_gl : LibSDL::GLContext
|
||||
{% if flag?(:darwin) %}
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_FLAGS, LibSDL::GLcontextFlag::FORWARD_COMPATIBLE_FLAG)
|
||||
{% end %}
|
||||
|
@ -120,6 +175,11 @@ private class DisplayImpl < Display
|
|||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MAJOR_VERSION, 3)
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_CONTEXT_MINOR_VERSION, 3)
|
||||
|
||||
# Maybe for Dear ImGui
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_DOUBLEBUFFER, 1)
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_DEPTH_SIZE, 24)
|
||||
LibSDL.gl_set_attribute(LibSDL::GLattr::SDL_GL_STENCIL_SIZE, 8)
|
||||
|
||||
{% unless flag?(:darwin) %}
|
||||
# todo: proper debug messages for mac
|
||||
LibGL.enable(LibGL::DEBUG_OUTPUT)
|
||||
|
@ -127,13 +187,10 @@ private class DisplayImpl < Display
|
|||
LibGL.debug_message_callback(->DisplayImpl.callback, nil)
|
||||
{% end %}
|
||||
|
||||
LibSDL.gl_create_context @window
|
||||
gl_context = LibSDL.gl_create_context @window
|
||||
LibSDL.gl_set_swap_interval(0) # disable vsync
|
||||
shader_program = LibGL.create_program
|
||||
|
||||
puts "OpenGL version: #{String.new(LibGL.get_string(LibGL::VERSION))}"
|
||||
puts "Shader language version: #{String.new(LibGL.get_string(LibGL::SHADING_LANGUAGE_VERSION))}"
|
||||
|
||||
LibGL.blend_func(LibGL::SRC_ALPHA, LibGL::ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
vert_shader_id = compile_shader(File.read("#{SHADERS}/identity.vert"), LibGL::VERTEX_SHADER)
|
||||
|
@ -156,9 +213,38 @@ private class DisplayImpl < Display
|
|||
vao = 0_u32 # required even if not used in modern opengl
|
||||
LibGL.gen_vertex_arrays(1, pointerof(vao))
|
||||
LibGL.bind_vertex_array(vao)
|
||||
|
||||
gl_context
|
||||
end
|
||||
|
||||
private def setup_imgui : ImGui::ImGuiIO
|
||||
LibImGuiBackends.gl3wInit
|
||||
|
||||
ImGui.debug_check_version_and_data_layout(
|
||||
ImGui.get_version, *{
|
||||
sizeof(LibImGui::ImGuiIO), sizeof(LibImGui::ImGuiStyle), sizeof(ImGui::ImVec2),
|
||||
sizeof(ImGui::ImVec4), sizeof(ImGui::ImDrawVert), sizeof(ImGui::ImDrawIdx),
|
||||
}.map &->LibC::SizeT.new(Int32))
|
||||
|
||||
ImGui.create_context
|
||||
io = ImGui.get_io
|
||||
ImGui.style_colors_dark
|
||||
|
||||
glsl_version = "#version 330"
|
||||
ImGui::SDL2.init_for_opengl(@window, @gl_context)
|
||||
ImGui::OpenGL3.init(glsl_version)
|
||||
|
||||
io
|
||||
end
|
||||
|
||||
protected def self.callback(source : UInt32, type : UInt32, id : UInt32, severity : UInt32, length : Int32, message : Pointer(UInt8), userParam : Pointer(Void)) : Nil
|
||||
puts "OpenGL debug message: #{String.new message}"
|
||||
end
|
||||
|
||||
record OpenGLInfo, version : String, shading : String do
|
||||
def initialize
|
||||
@version = String.new(LibGL.get_string(LibGL::VERSION))
|
||||
@shading = String.new(LibGL.get_string(LibGL::SHADING_LANGUAGE_VERSION))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,6 +11,7 @@ abstract class Emu
|
|||
def handle_events(interval : Int) : Nil
|
||||
scheduler.schedule interval, Proc(Nil).new { handle_events interval }
|
||||
while event = SDL::Event.poll
|
||||
ImGui::SDL2.process_event(event)
|
||||
case event
|
||||
when SDL::Event::Quit then exit 0
|
||||
when SDL::Event::JoyHat,
|
||||
|
|
Loading…
Reference in a new issue