13 Commits

Author SHA1 Message Date
da16ab1ec9 Bump version 2023-02-01 15:48:29 -06:00
eb5d170733 Added #find_element_by_tag to Common module 2023-01-31 14:33:17 -06:00
14e9d4946f Add GameState#needs_repaint? and Container#remove 2023-01-31 10:17:51 -06:00
e3b8a9b102 Fixed overdrawing on BorderCanvas for left side, fixed BackgroundImage fill mode not filling correctly, fixed Progress in marquee mode not request repaint each frame. 2023-01-11 15:05:58 -06:00
458731a534 Added shaders from i-mic-fps, preload shaders if cyberarm_engine/opengl has been required. 2023-01-08 17:30:37 -06:00
d1d87db070 Made GuiState#update safe to call when it is not the active state 2023-01-08 03:36:33 -06:00
6e8948bd81 Repaint when Slider value changes 2023-01-06 16:14:18 -06:00
01a9187a57 Request a repaint when popping and shifting states 2023-01-05 08:36:38 -06:00
186ad220cc Added more triggers for repainting 2023-01-04 20:17:49 -06:00
f82c0953b2 Implemented support for dynamic repainting of gui states with GuiState#needs_repaint? 2023-01-03 22:16:07 -06:00
a2d44ea2dc Fix Element#scroll_height not accounting for padding_top and border_thickness_top 2023-01-02 16:45:43 -06:00
c46664778a Fixed Image element causing clipping issues to sibling elements due to not properly flooring @width/@height 2022-11-16 20:31:00 -06:00
c597a67ca6 Allow 1 pixel wide/tall Gui elements by only apply percentage based sizing on Floats, fixed max/min sizing not working if the element uses fill mode for either dimension 2022-10-30 11:57:20 -05:00
22 changed files with 286 additions and 38 deletions

View File

@@ -0,0 +1,30 @@
# version 330 core
layout(location = 0) out vec3 fragPosition;
layout (location = 1) out vec4 fragColor;
layout (location = 2) out vec3 fragNormal;
layout (location = 3) out vec3 fragUV;
in vec3 outPosition, outColor, outNormal, outUV, outFragPos, outCameraPos;
out vec4 outputFragColor;
flat in int outHasTexture;
uniform sampler2D diffuse_texture;
void main() {
vec3 result;
if (outHasTexture == 0) {
result = outColor;
} else {
result = texture(diffuse_texture, outUV.xy).xyz + 0.25;
}
fragPosition = outPosition;
fragColor = vec4(result, 1.0);
fragNormal = outNormal;
fragUV = outUV;
float gamma = 2.2;
outputFragColor.rgb = pow(fragColor.rgb, vec3(1.0 / gamma));
}

View File

@@ -0,0 +1,63 @@
#version 330 core
out vec4 FragColor;
@include "light_struct"
const int DIRECTIONAL = 0;
const int POINT = 1;
const int SPOT = 2;
in vec2 outTexCoords;
flat in Light outLight[1];
uniform sampler2D diffuse, position, texcoord, normal, depth;
vec4 directionalLight(Light light) {
vec3 norm = normalize(texture(normal, outTexCoords).rgb);
vec3 diffuse_color = texture(diffuse, outTexCoords).rgb;
vec3 fragPos = texture(position, outTexCoords).rgb;
vec3 lightDir = normalize(light.position - fragPos);
float diff = max(dot(norm, lightDir), 0);
vec3 _ambient = light.ambient;
vec3 _diffuse = light.diffuse * diff;
vec3 _specular = light.specular;
return vec4(_diffuse + _ambient + _specular, 1.0);
}
vec4 pointLight(Light light) {
return vec4(0.25, 0.25, 0.25, 1);
}
vec4 spotLight(Light light) {
return vec4(0.5, 0.5, 0.5, 1);
}
vec4 calculateLighting(Light light) {
vec4 result;
// switch(light.type) {
// case DIRECTIONAL: {
// result = directionalLight(light);
// }
// case SPOT: {
// result = spotLight(light);
// }
// default: {
// result = pointLight(light);
// }
// }
if (light.type == DIRECTIONAL) {
result = directionalLight(light);
} else {
result = pointLight(light);
}
return result;
}
void main() {
FragColor = texture(diffuse, outTexCoords) * calculateLighting(outLight[0]);
}

View File

@@ -0,0 +1,11 @@
struct Light {
int type;
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 ambient;
vec3 specular;
float intensity;
};

View File

@@ -0,0 +1,28 @@
# version 330 core
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec3 inNormal;
layout(location = 3) in vec3 inUV;
uniform mat4 projection, view, model;
uniform int hasTexture;
uniform vec3 cameraPos;
out vec3 outPosition, outColor, outNormal, outUV;
out vec3 outFragPos, outViewPos, outCameraPos;
flat out int outHasTexture;
void main() {
// projection * view * model * position
outPosition = inPosition;
outColor = inColor;
outNormal= normalize(transpose(inverse(mat3(model))) * inNormal);
outUV = inUV;
outHasTexture = hasTexture;
outCameraPos = cameraPos;
outFragPos = vec3(model * vec4(inPosition, 1.0));
gl_Position = projection * view * model * vec4(inPosition, 1.0);
}

View File

@@ -0,0 +1,17 @@
#version 330 core
@include "light_struct"
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inTexCoords;
uniform sampler2D diffuse, position, texcoord, normal, depth;
uniform Light light[1];
out vec2 outTexCoords;
flat out Light outLight[1];
void main() {
gl_Position = vec4(inPosition.x, inPosition.y, inPosition.z, 1.0);
outTexCoords = inTexCoords;
outLight = light;
}

View File

@@ -75,7 +75,7 @@ module CyberarmEngine
end end
def draw_fill def draw_fill
if @width * width_scale > height * height_scale if (@image.width * width_scale) >= @width && (@image.height * width_scale) >= @height
draw_fill_width draw_fill_width
else else
draw_fill_height draw_fill_height

View File

@@ -7,8 +7,8 @@ module CyberarmEngine
@title_size = 56 @title_size = 56
@caption_size = 24 @caption_size = 24
@title = CyberarmEngine::Text.new("", size: @title_size, shadow_color: 0xaa_222222) @title = CyberarmEngine::Text.new("", size: @title_size, shadow_color: 0xaa_222222, static: true)
@caption = CyberarmEngine::Text.new("", size: @caption_size, shadow_color: 0xaa_222222) @caption = CyberarmEngine::Text.new("", size: @caption_size, shadow_color: 0xaa_222222, static: true)
@spacer_width = 256 @spacer_width = 256
@spacer_height = 6 @spacer_height = 6

View File

@@ -31,6 +31,18 @@ module CyberarmEngine
window.show_cursor = boolean window.show_cursor = boolean
end end
def find_element_by_tag(container, tag, list = [])
return unless container
container.children.each do |child|
list << child if child.style.tag == tag
find_element_by_tag(child, tag, list) if child.is_a?(CyberarmEngine::Element::Container)
end
list.first
end
def draw_rect(x, y, width, height, color, z = 0, mode = :default) def draw_rect(x, y, width, height, color, z = 0, mode = :default)
Gosu.draw_rect(x, y, width, height, color, z, mode) Gosu.draw_rect(x, y, width, height, color, z, mode)
end end

View File

@@ -34,6 +34,10 @@ module CyberarmEngine
true true
end end
def needs_repaint?
true
end
def drop(filename) def drop(filename)
end end

View File

@@ -11,7 +11,19 @@ module CyberarmEngine
if e != GL_NO_ERROR if e != GL_NO_ERROR
warn "OpenGL error detected by handler at: #{caller[0]}" warn "OpenGL error detected by handler at: #{caller[0]}"
warn " #{gluErrorString(e)} (#{e})\n" warn " #{gluErrorString(e)} (#{e})\n"
exit if window.exit_on_opengl_error? exit if Window.instance&.exit_on_opengl_error?
end
end
def preload_default_shaders
shaders = %w[g_buffer lighting]
shaders.each do |shader|
Shader.new(
name: shader,
includes_dir: "#{CYBERARM_ENGINE_ROOT_PATH}/assets/shaders/include",
vertex: "#{CYBERARM_ENGINE_ROOT_PATH}/assets/shaders/vertex/#{shader}.glsl",
fragment: "#{CYBERARM_ENGINE_ROOT_PATH}/assets/shaders/fragment/#{shader}.glsl"
)
end end
end end
end end

View File

@@ -1,6 +1,7 @@
module CyberarmEngine module CyberarmEngine
class GBuffer class GBuffer
attr_reader :screen_vbo, :vertices, :uvs attr_reader :screen_vbo, :vertices, :uvs
attr_reader :width, :height
def initialize(width:, height:) def initialize(width:, height:)
@width = width @width = width

View File

@@ -62,11 +62,11 @@ module CyberarmEngine
def update def update
# TOP # TOP
@top.x = @element.x # + @element.border_thickness_left @top.x = @element.x + @element.style.border_thickness_left
@top.y = @element.y @top.y = @element.y
@top.z = @element.z @top.z = @element.z
@top.width = @element.width @top.width = @element.width - @element.style.border_thickness_left
@top.height = @element.style.border_thickness_top @top.height = @element.style.border_thickness_top
# RIGHT # RIGHT

View File

@@ -65,6 +65,8 @@ module CyberarmEngine
set_border_thickness set_border_thickness
set_border_color set_border_color
root.gui_state.request_repaint
end end
def safe_style_fetch(*args) def safe_style_fetch(*args)
@@ -166,10 +168,10 @@ module CyberarmEngine
return if self.is_a?(ToolTip) return if self.is_a?(ToolTip)
if old_width != width || old_height != height if old_width != width || old_height != height
(root&.gui_state || @gui_state).request_recalculate root.gui_state.request_recalculate
else
stylize
end end
stylize
end end
def default_events def default_events
@@ -256,6 +258,8 @@ module CyberarmEngine
end end
def enabled=(boolean) def enabled=(boolean)
root.gui_state.request_repaint if @enabled != boolean
@enabled = boolean @enabled = boolean
recalculate recalculate
@@ -267,6 +271,10 @@ module CyberarmEngine
@enabled @enabled
end end
def focused?
@focus
end
def visible? def visible?
@visible @visible
end end
@@ -278,18 +286,21 @@ module CyberarmEngine
def toggle def toggle
@visible = !@visible @visible = !@visible
root.gui_state.request_recalculate root.gui_state.request_recalculate
root.gui_state.request_repaint
end end
def show def show
bool = visible? bool = visible?
@visible = true @visible = true
root.gui_state.request_recalculate unless bool root.gui_state.request_recalculate unless bool
root.gui_state.request_repaint unless bool
end end
def hide def hide
bool = visible? bool = visible?
@visible = false @visible = false
root.gui_state.request_recalculate if bool root.gui_state.request_recalculate if bool
root.gui_state.request_repaint if bool
end end
def draw def draw
@@ -423,9 +434,9 @@ module CyberarmEngine
pairs_ << a_ unless pairs_.last == a_ pairs_ << a_ unless pairs_.last == a_
pairs_.sum { |pair| pair.map(&:outer_height).max } + @style.padding_bottom + @style.border_thickness_bottom pairs_.sum { |pair| + @style.padding_top + @style.border_thickness_top + pair.map(&:outer_height).max } + @style.padding_bottom + @style.border_thickness_bottom
else else
@children.sum(&:outer_height) + @style.padding_bottom + @style.border_thickness_bottom @style.padding_top + @style.border_thickness_top + @children.sum(&:outer_height) + @style.padding_bottom + @style.border_thickness_bottom
end end
end end
@@ -440,21 +451,21 @@ module CyberarmEngine
def dimensional_size(size, dimension) def dimensional_size(size, dimension)
raise "dimension must be either :width or :height" unless %i[width height].include?(dimension) raise "dimension must be either :width or :height" unless %i[width height].include?(dimension)
new_size = if size.is_a?(Numeric) && size.between?(0.0, 1.0) new_size = if size.is_a?(Float) && size.between?(0.0, 1.0)
(@parent.send(:"content_#{dimension}") * size).floor - send(:"noncontent_#{dimension}").floor (@parent.send(:"content_#{dimension}") * size).floor - send(:"noncontent_#{dimension}").floor
else else
size size
end end
if @parent && @style.fill # Handle fill behavior # Handle fill behavior
if dimension == :width && @parent.is_a?(Flow) if @parent && @style.fill &&
return space_available_width - noncontent_width (dimension == :width && @parent.is_a?(Flow) ||
dimension == :height && @parent.is_a?(Stack))
return space_available_width - noncontent_width if dimension == :width && @parent.is_a?(Flow)
return space_available_height - noncontent_height if dimension == :height && @parent.is_a?(Stack)
elsif dimension == :height && @parent.is_a?(Stack) # Handle min_width/height and max_width/height
return space_available_height - noncontent_height else
end
else # Handle min_width/height and max_width/height
return @style.send(:"min_#{dimension}") if @style.send(:"min_#{dimension}") && new_size.to_f < @style.send(:"min_#{dimension}") return @style.send(:"min_#{dimension}") if @style.send(:"min_#{dimension}") && new_size.to_f < @style.send(:"min_#{dimension}")
return @style.send(:"max_#{dimension}") if @style.send(:"max_#{dimension}") && new_size.to_f > @style.send(:"max_#{dimension}") return @style.send(:"max_#{dimension}") if @style.send(:"max_#{dimension}") && new_size.to_f > @style.send(:"max_#{dimension}")
end end
@@ -479,6 +490,8 @@ module CyberarmEngine
end end
def background=(_background) def background=(_background)
root.gui_state.request_repaint
@style.background_canvas.background = _background @style.background_canvas.background = _background
update_background update_background
end end
@@ -497,6 +510,8 @@ module CyberarmEngine
end end
def background_nine_slice=(_image_path) def background_nine_slice=(_image_path)
root.gui_state.request_repaint
@style.background_nine_slice_canvas.image = _image_path @style.background_nine_slice_canvas.image = _image_path
update_background_nine_slice update_background_nine_slice
end end
@@ -521,6 +536,8 @@ module CyberarmEngine
end end
def background_image=(image_path) def background_image=(image_path)
root.gui_state.request_repaint
@style.background_image = image_path.is_a?(Gosu::Image) ? image_path : get_image(image_path) @style.background_image = image_path.is_a?(Gosu::Image) ? image_path : get_image(image_path)
update_background_image update_background_image
end end

View File

@@ -42,6 +42,10 @@ module CyberarmEngine
root.gui_state.request_recalculate root.gui_state.request_recalculate
end end
def remove(element)
root.gui_state.request_recalculate if @children.delete(element)
end
def clear(&block) def clear(&block)
@children.clear @children.clear
@@ -122,6 +126,9 @@ module CyberarmEngine
layout layout
old_width = @width
old_height = @height
if is_root? if is_root?
@width = @style.width = window.width @width = @style.width = window.width
@height = @style.height = window.height @height = @style.height = window.height
@@ -178,6 +185,8 @@ module CyberarmEngine
# puts "TOOK: #{Gosu.milliseconds - s}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}" # puts "TOOK: #{Gosu.milliseconds - s}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}"
update_background update_background
root.gui_state.request_repaint if @width != old_width || @height != old_height
end end
def layout def layout
@@ -242,6 +251,7 @@ module CyberarmEngine
@scroll_position.y = 0 if @scroll_position.y > 0 @scroll_position.y = 0 if @scroll_position.y > 0
root.gui_state.request_recalculate_for(self) root.gui_state.request_recalculate_for(self)
root.gui_state.request_repaint
return :handled return :handled
end end
@@ -257,6 +267,7 @@ module CyberarmEngine
@scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
root.gui_state.request_recalculate_for(self) root.gui_state.request_recalculate_for(self)
root.gui_state.request_repaint
return :handled return :handled
end end
@@ -278,7 +289,7 @@ module CyberarmEngine
end end
def value def value
@children.map { |c| c.class }.join(", ") @children.map(&:class).join(", ")
end end
def to_s def to_s

View File

@@ -80,16 +80,22 @@ module CyberarmEngine
@show_caret = true @show_caret = true
@caret_last_interval = Gosu.milliseconds @caret_last_interval = Gosu.milliseconds
root.gui_state.request_repaint
publish(:changed, value) publish(:changed, value)
end end
if @last_caret_position != @text_input.caret_pos if @last_caret_position != @text_input.caret_pos
@last_caret_position = @text_input.caret_pos @last_caret_position = @text_input.caret_pos
root.gui_state.request_repaint
@show_caret = true @show_caret = true
@caret_last_interval = Gosu.milliseconds @caret_last_interval = Gosu.milliseconds
end end
if Gosu.milliseconds >= @caret_last_interval + @caret_interval if Gosu.milliseconds >= @caret_last_interval + @caret_interval
root.gui_state.request_repaint
@caret_last_interval = Gosu.milliseconds @caret_last_interval = Gosu.milliseconds
@show_caret = !@show_caret @show_caret = !@show_caret

View File

@@ -45,8 +45,8 @@ module CyberarmEngine
@scale_y = 1 @scale_y = 1
end end
@width = _width || @image.width.floor * @scale_x @width = _width || (@image.width * @scale_x).floor
@height = _height || @image.height.floor * @scale_y @height = _height || (@image.height * @scale_y).floor
update_background update_background
end end

View File

@@ -52,6 +52,7 @@ module CyberarmEngine
@marquee_animation_time = Gosu.milliseconds if @marquee_offset > range @marquee_animation_time = Gosu.milliseconds if @marquee_offset > range
update_background update_background
root.gui_state.request_repaint
end end
def type=(type) def type=(type)
@@ -77,9 +78,13 @@ module CyberarmEngine
def value=(decimal) def value=(decimal)
raise "value must be number" unless decimal.is_a?(Numeric) raise "value must be number" unless decimal.is_a?(Numeric)
old_value = @fraction
@fraction = decimal.clamp(0.0, 1.0) @fraction = decimal.clamp(0.0, 1.0)
update_background update_background
root.gui_state.request_repaint if @fraction != old_value
publish(:changed, @fraction) publish(:changed, @fraction)
@fraction @fraction
end end

View File

@@ -97,6 +97,8 @@ module CyberarmEngine
position_handle position_handle
@handle.recalculate @handle.recalculate
root.gui_state.request_repaint
publish(:changed, @value) publish(:changed, @value)
end end
end end

View File

@@ -36,6 +36,9 @@ module CyberarmEngine
@text.color = @style.color @text.color = @style.color
end end
old_width = @width
old_height = @height
@width = 0 @width = 0
@height = 0 @height = 0
@@ -79,6 +82,8 @@ module CyberarmEngine
end end
update_background update_background
root.gui_state.request_repaint if @width != old_width || @height != old_height
end end
def handle_text_wrapping(max_width) def handle_text_wrapping(max_width)
@@ -159,6 +164,7 @@ module CyberarmEngine
end end
def value=(value) def value=(value)
old_value = @raw_text
@raw_text = value.to_s.chomp @raw_text = value.to_s.chomp
old_width = width old_width = width
@@ -170,6 +176,8 @@ module CyberarmEngine
recalculate recalculate
end end
root.gui_state.request_repaint if old_value != @raw_text
publish(:changed, self.value) publish(:changed, self.value)
end end
end end

View File

@@ -27,6 +27,8 @@ module CyberarmEngine
@pending_recalculate_request = false @pending_recalculate_request = false
@pending_element_recalculate_requests = [] @pending_element_recalculate_requests = []
@needs_repaint = false
@menu = nil @menu = nil
@min_drag_distance = 0 @min_drag_distance = 0
@mouse_pos = Vector.new @mouse_pos = Vector.new
@@ -55,7 +57,7 @@ module CyberarmEngine
@menu.draw @menu.draw
end end
if @tip.value.length.positive? if @tip && @tip.value.length.positive?
Gosu.flush Gosu.flush
@tip.draw @tip.draw
@@ -66,6 +68,12 @@ module CyberarmEngine
@root_container.debug_draw @root_container.debug_draw
end end
@needs_repaint = false
end
def needs_repaint?
@needs_repaint
end end
def update def update
@@ -88,9 +96,19 @@ module CyberarmEngine
end end
@menu&.update @menu&.update
super super
if @active_width != window.width || @active_height != window.height
request_recalculate
@root_container.publish(:window_size_changed)
end
@active_width = window.width
@active_height = window.height
return unless window.has_focus? return unless window.has_focus?
return unless window.current_state == self
new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu
new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y) new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y)
@@ -127,14 +145,6 @@ module CyberarmEngine
@last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y) @last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y)
@mouse_pos = @last_mouse_pos.clone @mouse_pos = @last_mouse_pos.clone
if @active_width != window.width || @active_height != window.height
request_recalculate
@root_container.publish(:window_size_changed)
end
@active_width = window.width
@active_height = window.height
end end
def button_down(id) def button_down(id)
@@ -253,6 +263,12 @@ module CyberarmEngine
@pending_focus_element = element @pending_focus_element = element
end end
def request_repaint
# puts caller[0..4]
# puts
@needs_repaint = true
end
def show_menu(list_box) def show_menu(list_box)
@menu = list_box @menu = list_box
end end

View File

@@ -1,4 +1,4 @@
module CyberarmEngine module CyberarmEngine
NAME = "InDev".freeze NAME = "InDev".freeze
VERSION = "0.22.0".freeze VERSION = "0.23.0".freeze
end end

View File

@@ -41,6 +41,7 @@ module CyberarmEngine
@states = [] @states = []
@exit_on_opengl_error = false @exit_on_opengl_error = false
preload_default_shaders if respond_to?(:preload_default_shaders)
setup if defined?(setup) setup if defined?(setup)
end end
@@ -141,10 +142,14 @@ module CyberarmEngine
def pop_state def pop_state
@states.pop @states.pop
current_state.request_repaint if current_state&.is_a?(GuiState)
end end
def shift_state def shift_state
@states.shift @states.shift
current_state.request_repaint if current_state&.is_a?(GuiState)
end end
def has_focus? def has_focus?