Skip to content

Commit 2c3bb54

Browse files
committed
Added a better logger for internal use
Now we have some context based logger
1 parent 84bdeaa commit 2c3bb54

4 files changed

Lines changed: 217 additions & 20 deletions

File tree

modules/engine/mrblib/engine.rb

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ class Engine
99
# @!attribute step
1010
# @return [Proc] per frame step function
1111
attr_accessor :step
12-
12+
# @return [Hash<Symbol, Object>]
1313
attr_accessor :config
14-
15-
attr_accessor :log
14+
# @return [Moon::ContextLogger, ILogger] any logger like interface
15+
attr_accessor :logger
16+
# @return [Moon::Screen]
1617
attr_reader :screen
18+
# @return [Moon::Input]
1719
attr_reader :input
1820

1921
# Initializes the engine. The block should be a step function to be called
@@ -27,7 +29,7 @@ def initialize(&block)
2729
@input = nil
2830
@fps = Moon::Clock.new
2931
@step = block
30-
@log = STDERR
32+
@logger = Moon::ContextLogger.new(STDERR, 'Engine')
3133
end
3234

3335
# @return [Float] Returns the time since the engine has started.
@@ -39,10 +41,12 @@ def uptime
3941
#
4042
# @raise {EngineQuit}
4143
def quit
44+
@logger.debug 'Quitting Engine!'
4245
raise EngineQuit
4346
end
4447

4548
private def setup_glfw
49+
@logger.debug 'Initializing Screen'
4650
@screen = Screen.new(@config.fetch(:width), @config.fetch(:height))
4751
@screen.make_current
4852
# debugging
@@ -51,18 +55,21 @@ def quit
5155
end
5256

5357
private def create_input
58+
@logger.debug 'Initializing Input'
5459
@input = Input.new @screen.window
55-
@log.puts 'Input initialized'
60+
@logger.debug 'Input initialized'
5661
end
5762

5863
private def setup_glew
64+
@logger.debug 'Initializing GLEW'
5965
# http://openglbook.com/blog/glgenvertexarrays-access-violationsegfault-with-glew/
6066
GLEW.experimental = true
6167
GLEW.init
62-
@log.puts 'GLEW initialized'
68+
@logger.debug 'GLEW initialized'
6369
end
6470

6571
private def setup_default_shaders
72+
@logger.debug 'Initializing default shaders'
6673
@shaders = {}
6774
sd = Moon::Shader::DEFAULTS
6875
shader_path = Moon::Shader.is_legacy ? '120' : '330'
@@ -79,28 +86,37 @@ def quit
7986
Moon::Spritesheet.default_shader = @shaders[:quad]
8087
Moon::Tilemap.default_shader = @shaders[:quad]
8188
Moon::Text.default_shader = @shaders[:text]
89+
@logger.debug 'Default Shaders Initialized'
90+
self
8291
end
8392

93+
# Initializes all internal systems and prepares for main loop
94+
#
8495
# @return [self]
8596
def setup
97+
@logger.debug "Initializing"
8698
setup_glfw
8799
setup_glew
88100
@screen.setup
89101
create_input
90102
setup_default_shaders
103+
@logger.debug "Initialized"
91104
self
92105
end
93106

94-
# Destroys the current screen and cleans up.
107+
# Destroys the systems and cleans up
95108
def shutdown
96-
@screen.close if @screen
109+
@logger.debug "Shutting down"
110+
@input.shutdown if @input
111+
@screen.shutdown if @screen
112+
@logger.debug "Shutdown"
97113
self
98114
end
99115

100116
# Starts the main loop, terminate the loop using {#quit}
101117
def main
102-
@log.puts "Audio Module: #{Audio::NAME}"
103-
@log.puts 'Starting main loop'
118+
@logger.info "Audio Module: #{Audio::NAME}"
119+
@logger.debug 'Starting main loop'
104120
clear_bits = GL2::GL_COLOR_BUFFER_BIT | GL2::GL_DEPTH_BUFFER_BIT
105121
until @screen.should_close?
106122
GL2.glClear clear_bits
@@ -111,6 +127,7 @@ def main
111127
GLFW.poll_events
112128
end
113129
rescue EngineQuit
130+
@logger.debug 'Got an EngineQuit request'
114131
end
115132

116133
# Sets everything up, runs the main loop, and ensures we take care of

modules/engine/mrblib/input.rb

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,20 +150,33 @@ class Input
150150
attr_reader :window
151151
# @return [Moon::Input::Mouse]
152152
attr_reader :mouse
153+
# @return [Moon::ContextLogger, ILogger] any logger like interface
154+
attr_accessor :logger
153155
#attr_reader :keyboard
154156

155157
# @param [GLFW::Window] window
156158
def initialize(window)
159+
@logger = Moon::ContextLogger.new STDERR, 'Input'
157160
@window = window
158-
init_mouse
161+
init
162+
end
163+
164+
# Initializes handlers and callbacks
165+
#
166+
# @api private
167+
def init
168+
initialize_mouse
159169
register_callbacks
160170
end
161171

162-
private def init_mouse
172+
private def initialize_mouse
173+
@logger.debug 'Initializing Mouse Handler'
163174
@mouse = Mouse.new @window
175+
@logger.debug 'Mouse Handler Initialized'
164176
end
165177

166178
private def register_callbacks
179+
@logger.debug 'Registering Callbacks'
167180
@window.set_key_callback do |_, key_id, scancode, action, mods|
168181
on_key KEY_MAP.fetch(key_id), scancode, STATE_MAP.fetch(action), mods unless key_id == -1
169182
end
@@ -179,6 +192,26 @@ def initialize(window)
179192
@window.set_cursor_pos_callback do |_, x, y|
180193
on_mousemove x, y
181194
end
195+
@logger.debug 'Callbacks Registered'
196+
end
197+
198+
private def unregister_callbacks
199+
@logger.debug 'Unregistering Callbacks'
200+
@window.set_key_callback
201+
@window.set_mouse_button_callback
202+
@window.set_char_callback
203+
@window.set_cursor_pos_callback
204+
@logger.debug 'Callbacks Unregistered'
205+
end
206+
207+
# Removes all handlers to the underlying window
208+
#
209+
# @api private
210+
def shutdown
211+
@logger.debug 'Shutting down'
212+
unregister_callbacks
213+
@mouse = nil
214+
@logger.debug 'Shutdown'
182215
end
183216

184217
# Called on every keypress.

modules/graphics/mrblib/screen.rb

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ class Screen
1414
attr_reader :clear_color
1515
# Underlying window implementation (in default case GLFW).
1616
attr_reader :window
17-
attr_accessor :log
17+
# @return [Moon::ContextLogger, ILogger] any logger like interface
18+
attr_accessor :logger
1819

1920
# Creates a new game window with the given width and height.
2021
#
2122
# @param [Integer] w
2223
# @param [Integer] h
2324
def initialize(w, h)
2425
@scale = 1.0
25-
@log = STDERR
26+
@logger = Moon::ContextLogger.new(STDERR, 'Screen')
2627
create_window w, h
2728
initialize_renderer
2829
initialize_clear_color
@@ -35,6 +36,7 @@ def initialize(w, h)
3536
# @param [Integer] w width of the window
3637
# @param [Integer] h height of the window
3738
def create_window(w, h)
39+
@logger.debug "Creating Window: w=#{w} h=#{h}"
3840
GLFW.window_hint GLFW::RESIZABLE, GL2::GL_FALSE
3941
GLFW.window_hint GLFW::CONTEXT_VERSION_MAJOR, 3
4042
GLFW.window_hint GLFW::CONTEXT_VERSION_MINOR, 3
@@ -45,13 +47,16 @@ def create_window(w, h)
4547
title = 'Moon Player'
4648
begin
4749
@window = GLFW::Window.new w, h, title
50+
@logger.warn "3.3 Window Created"
4851
rescue GLFWError
52+
@logger.warn "Failed to obtain 3.3 context, falling back to 2.1"
4953
GLFW.default_window_hints
5054
GLFW.window_hint GLFW::CONTEXT_VERSION_MAJOR, 2
5155
GLFW.window_hint GLFW::CONTEXT_VERSION_MINOR, 1
5256
Moon::Shader.is_legacy = true
5357

5458
@window = GLFW::Window.new w, h, title
59+
@logger.warn "2.1 Window Created"
5560
end
5661
end
5762

@@ -77,9 +82,9 @@ def glsl_version
7782

7883
# Prints all the available version strings to the @log
7984
def print_versions
80-
@log.puts "OpenGL v" + gl_version
81-
@log.puts "GLSL v" + glsl_version
82-
@log.puts "GLFW v" + GLFW.version_string
85+
@logger.info "OpenGL v" + gl_version
86+
@logger.info "GLSL v" + glsl_version
87+
@logger.info "GLFW v" + GLFW.version_string
8388
end
8489

8590
# Make the screen the current context
@@ -99,10 +104,18 @@ def swap
99104
@window.swap_buffers
100105
end
101106

102-
# Closes the underlying window
103-
def close
104-
@window.destroy if @window
107+
# Closes the underlying window and cleans up
108+
def shutdown
109+
@logger.debug "Shutting Down"
110+
if @window
111+
@logger.debug "Closing Window"
112+
@window.should_close = true
113+
GLFW.wait_events
114+
@window.destroy
115+
end
105116
@window = nil
117+
@logger.debug "Shutdown"
118+
self
106119
end
107120

108121
private def initialize_clear_color
@@ -135,6 +148,7 @@ def update_projection
135148
# @param [Integer] w
136149
# @param [Integer] h
137150
def resize(w, h)
151+
@logger.debug "Resizing Screen to w=#{w} h=#{h}"
138152
@window.window_size = [w, h]
139153
@w, @h = *@window.window_size
140154
@rect = Rect.new(0, 0, @w, @h)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
module Moon
2+
# Internal Logger used by moon classes and systems
3+
# It implements a very generic subset of the Logger methods
4+
class ContextLogger
5+
# The logging level
6+
module Level
7+
# Low-level information, mostly for developers.
8+
DEBUG = 0
9+
# Generic (useful) information about system operation.
10+
INFO = 1
11+
# A warning.
12+
WARN = 2
13+
# A handleable error condition.
14+
ERROR = 3
15+
# An unhandleable error that results in a program crash.
16+
FATAL = 4
17+
# An unknown message that should always be logged.
18+
UNKNOWN = 5
19+
# @return [Hash<Integer, String>]
20+
LEVEL_TO_NAME = {
21+
DEBUG => 'DEBUG',
22+
INFO => 'INFO',
23+
WARN => 'WARN',
24+
ERROR => 'ERROR',
25+
FATAL => 'FATAL',
26+
UNKNOWN => 'UNKNOWN'
27+
}
28+
# @return [Hash<String, Integer>]
29+
NAME_TO_LEVEL = LEVEL_TO_NAME.invert
30+
end
31+
32+
class << self
33+
# @!attribute [rw] context_separator
34+
# @return [String] default '/'
35+
attr_accessor :context_separator
36+
end
37+
38+
self.context_separator = '/'
39+
40+
# @return [IO, #puts]
41+
attr_accessor :device
42+
# @return [Integer]
43+
attr_reader :level
44+
# @return [String]
45+
attr_accessor :context
46+
protected :context=
47+
48+
# @param [IO, #puts] device
49+
# @param [String] ctx
50+
# @param [String, Symbol, Integer] lvl
51+
def initialize(device, ctx = nil, lvl = Level::DEBUG)
52+
@device = device
53+
@context = ctx
54+
self.level = lvl
55+
end
56+
57+
# Change the logger's level
58+
#
59+
# @param [String, Symbol, Integer] lvl
60+
def level=(lvl)
61+
@level = if lvl.is_a?(Integer)
62+
lvl
63+
else
64+
Level::NAME_TO_LEVEL.fetch(lvl.to_s.upcase)
65+
end
66+
end
67+
68+
def initialize_copy(other)
69+
@device = other.device
70+
@context = other.context.dup
71+
@level = other.level
72+
end
73+
74+
private def context_separator
75+
self.class.context_separator
76+
end
77+
78+
# Writes the specified message to the device, if the level is above the
79+
# current logging level
80+
#
81+
# @param [Integer] lvl logging level
82+
# @param [String] message message to log
83+
private def write(lvl, msg)
84+
return if lvl < @level
85+
level_name = Level::LEVEL_TO_NAME.fetch(lvl)
86+
if @context
87+
@device.puts "#{level_name}: [#{@context}] #{msg}"
88+
else
89+
@device.puts "#{level_name}: #{msg}"
90+
end
91+
end
92+
93+
# @param [String] msg message to log
94+
def debug(msg)
95+
write Level::DEBUG, msg
96+
end
97+
98+
# @param [String] msg message to log
99+
def info(msg)
100+
write Level::INFO, msg
101+
end
102+
103+
# @param [String] msg message to log
104+
def error(msg)
105+
write Level::ERROR, msg
106+
end
107+
108+
# @param [String] msg message to log
109+
def warn(msg)
110+
write Level::WARN, msg
111+
end
112+
113+
# @param [String] msg message to log
114+
def fatal(msg)
115+
write Level::FATAL, msg
116+
end
117+
118+
# @param [String] msg message to log
119+
def unknown(msg)
120+
write Level::UNKNOWN, msg
121+
end
122+
123+
# Creates a new logger with the context joined to the current
124+
#
125+
# @param [String] context
126+
# @return [Moon::ContextLogger] new instance with context appended
127+
def new(context)
128+
dup.tap do |logger|
129+
logger.context = "#{logger.context}#{context_separator}#{context}"
130+
end
131+
end
132+
end
133+
end

0 commit comments

Comments
 (0)