summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml6
m---------assets0
-rw-r--r--ext/ruby2d/ruby2d-opal.rb68
-rw-r--r--ext/ruby2d/ruby2d.c109
-rw-r--r--lib/ruby2d/application.rb4
-rw-r--r--lib/ruby2d/dsl.rb4
-rw-r--r--lib/ruby2d/window.rb248
-rw-r--r--test/input.rb35
-rw-r--r--test/key.rb30
-rw-r--r--test/mouse.rb53
-rw-r--r--test/testcard.rb7
11 files changed, 369 insertions, 195 deletions
diff --git a/.travis.yml b/.travis.yml
index 2d4190a..efbcf69 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,12 @@
os: osx
-osx_image: xcode8
+osx_image: xcode8.3
language: ruby
rvm:
- - 2.2.5
+ - 2.4.0
before_install:
- sw_vers
- brew update
- brew tap simple2d/tap
- - brew install simple2d
+ - brew install --HEAD simple2d
script:
- rake
diff --git a/assets b/assets
-Subproject da267e388d8865490276d8819f3113a9f8660af
+Subproject 265922df6da40531c322cde9f1a9a3ab15385c8
diff --git a/ext/ruby2d/ruby2d-opal.rb b/ext/ruby2d/ruby2d-opal.rb
index ff372dc..d4bea68 100644
--- a/ext/ruby2d/ruby2d-opal.rb
+++ b/ext/ruby2d/ruby2d-opal.rb
@@ -17,25 +17,69 @@ const $R2D_SPRITE = 4;
const $R2D_TEXT = 5;
-function on_key(e, key) {
- switch (e) {
- case S2D.KEYDOWN:
- #{$R2D_WINDOW.key_down_callback(`key`)};
+function on_key(e) {
+
+ switch (e.type) {
+ case S2D.KEY_DOWN:
+ #{type = :down};
break;
-
- case S2D.KEY:
- #{$R2D_WINDOW.key_callback(`key`)};
+ case S2D.KEY_HELD:
+ #{type = :held};
break;
-
- case S2D.KEYUP:
- #{$R2D_WINDOW.key_up_callback(`key`)};
+ case S2D.KEY_UP:
+ #{type = :up};
break;
}
+
+ #{$R2D_WINDOW.key_callback(type, `e.key`)};
}
-function on_mouse(x, y) {
- #{$R2D_WINDOW.mouse_callback("any", `x`, `y`)};
+function on_mouse(e) {
+
+ #{direction = nil}
+ #{button = nil}
+
+ switch (e.type) {
+ case S2D.MOUSE_DOWN:
+ #{type = :down};
+ break;
+ case S2D.MOUSE_UP:
+ #{type = :up};
+ break;
+ case S2D.MOUSE_SCROLL:
+ #{type = :scroll};
+ #{direction} = e.direction == S2D.MOUSE_SCROLL_NORMAL ? #{:normal} : #{:inverted};
+ break;
+ case S2D.MOUSE_MOVE:
+ #{type = :move};
+ break;
+ }
+
+ if (e.type == S2D.MOUSE_DOWN || e.type == S2D.MOUSE_UP) {
+ switch (e.button) {
+ case S2D.MOUSE_LEFT:
+ #{button = :left};
+ break;
+ case S2D.MOUSE_MIDDLE:
+ #{button = :middle};
+ break;
+ case S2D.MOUSE_RIGHT:
+ #{button = :right};
+ break;
+ case S2D.MOUSE_X1:
+ #{button = :x1};
+ break;
+ case S2D.MOUSE_X2:
+ #{button = :x2};
+ break;
+ }
+ }
+
+ #{$R2D_WINDOW.mouse_callback(
+ type, button, direction,
+ `e.x`, `e.y`, `e.delta_x`, `e.delta_y`
+ )};
}
diff --git a/ext/ruby2d/ruby2d.c b/ext/ruby2d/ruby2d.c
index f25587d..6c3dc4e 100644
--- a/ext/ruby2d/ruby2d.c
+++ b/ext/ruby2d/ruby2d.c
@@ -59,10 +59,12 @@
#define r_data_wrap_struct(name, data) mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &name##_data_type, data))
#define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(mrb, r_iv_get(self, var), mrb_type, data)
#define r_define_module(name) mrb_module_get(mrb, name)
- #define r_define_class(module, name) mrb_class_get_under(mrb, module, name);
+ #define r_define_class(module, name) mrb_class_get_under(mrb, module, name)
#define r_define_method(class, name, function, args) mrb_define_method(mrb, class, name, function, args)
#define r_args_none (MRB_ARGS_NONE())
#define r_args_req(n) MRB_ARGS_REQ(n)
+ // Helpers
+ #define r_char_to_sym(str) mrb_check_intern_cstr(mrb, str)
#else
// Ruby
#define R_VAL VALUE
@@ -79,10 +81,12 @@
#define r_data_wrap_struct(name, data) Data_Wrap_Struct(rb_cObject, NULL, (free_##name), data)
#define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(r_iv_get(self, var), rb_type, data)
#define r_define_module(name) rb_define_module(name)
- #define r_define_class(module, name) rb_define_class_under(module, name, rb_cObject);
+ #define r_define_class(module, name) rb_define_class_under(module, name, rb_cObject)
#define r_define_method(class, name, function, args) rb_define_method(class, name, function, args)
#define r_args_none 0
#define r_args_req(n) n
+ // Helpers
+ #define r_char_to_sym(str) ID2SYM(rb_intern(str))
#endif
// @type_id values for rendering
@@ -429,39 +433,106 @@ static void free_music(S2D_Music *mus) {
/*
* Simple 2D `on_key` input callback function
*/
-static void on_key(S2D_Event e, const char *key) {
- switch (e) {
- case S2D_KEYDOWN:
- r_funcall(ruby2d_window, "key_down_callback", 1, r_str_new(key));
+static void on_key(S2D_Event e) {
+
+ R_VAL type;
+
+ switch (e.type) {
+ case S2D_KEY_DOWN:
+ type = r_char_to_sym("down");
break;
-
- case S2D_KEY:
- r_funcall(ruby2d_window, "key_callback", 1, r_str_new(key));
+ case S2D_KEY_HELD:
+ type = r_char_to_sym("held");
break;
-
- case S2D_KEYUP:
- r_funcall(ruby2d_window, "key_up_callback", 1, r_str_new(key));
+ case S2D_KEY_UP:
+ type = r_char_to_sym("up");
break;
}
+
+ r_funcall(ruby2d_window, "key_callback", 2, type, r_str_new(e.key));
}
/*
* Simple 2D `on_mouse` input callback function
*/
-void on_mouse(int x, int y) {
- r_funcall(ruby2d_window, "mouse_callback", 3, r_str_new("any"), INT2NUM(x), INT2NUM(y));
+void on_mouse(S2D_Event e) {
+
+ R_VAL type = R_NIL; R_VAL button = R_NIL; R_VAL direction = R_NIL;
+
+ switch (e.type) {
+ case S2D_MOUSE_DOWN:
+ // type, button, x, y
+ type = r_char_to_sym("down");
+ break;
+ case S2D_MOUSE_UP:
+ // type, button, x, y
+ type = r_char_to_sym("up");
+ break;
+ case S2D_MOUSE_SCROLL:
+ // type, direction, delta_x, delta_y
+ type = r_char_to_sym("scroll");
+ direction = e.direction == S2D_MOUSE_SCROLL_NORMAL ?
+ r_str_new("normal") : r_str_new("inverted");
+ break;
+ case S2D_MOUSE_MOVE:
+ // type, x, y, delta_x, delta_y
+ type = r_char_to_sym("move");
+ break;
+ }
+
+ if (e.type == S2D_MOUSE_DOWN || e.type == S2D_MOUSE_UP) {
+ switch (e.button) {
+ case S2D_MOUSE_LEFT:
+ button = r_str_new("left");
+ break;
+ case S2D_MOUSE_MIDDLE:
+ button = r_str_new("middle");
+ break;
+ case S2D_MOUSE_RIGHT:
+ button = r_str_new("right");
+ break;
+ case S2D_MOUSE_X1:
+ button = r_str_new("x1");
+ break;
+ case S2D_MOUSE_X2:
+ button = r_str_new("x2");
+ break;
+ }
+ }
+
+ // Bug in MRuby: If `button` or `direction` are symbols (created with
+ // r_char_to_sym), they will always both be `nil`. Use `r_str_new` for now.
+
+ r_funcall(
+ ruby2d_window, "mouse_callback", 7, type, button, direction,
+ INT2NUM(e.x), INT2NUM(e.y), INT2NUM(e.delta_x), INT2NUM(e.delta_y)
+ );
}
/*
* Simple 2D `on_controller` input callback function
*/
-static void on_controller(int which, bool is_axis, int axis, int val, bool is_btn, int btn, bool pressed) {
- r_funcall(ruby2d_window, "controller_callback", 7,
- INT2NUM(which),
- is_axis ? R_TRUE : R_FALSE, INT2NUM(axis), INT2NUM(val),
- is_btn ? R_TRUE : R_FALSE, INT2NUM(btn), pressed ? R_TRUE : R_FALSE
+static void on_controller(S2D_Event e) {
+
+ R_VAL type = R_NIL;
+
+ switch (e.type) {
+ case S2D_AXIS:
+ type = r_char_to_sym("axis");
+ break;
+ case S2D_BUTTON_DOWN:
+ type = r_char_to_sym("button_down");
+ break;
+ case S2D_BUTTON_UP:
+ type = r_char_to_sym("button_up");
+ break;
+ }
+
+ r_funcall(
+ ruby2d_window, "controller_callback", 5, INT2NUM(e.which), type,
+ INT2NUM(e.axis), INT2NUM(e.value), INT2NUM(e.button)
);
}
diff --git a/lib/ruby2d/application.rb b/lib/ruby2d/application.rb
index 8de526d..a63b00d 100644
--- a/lib/ruby2d/application.rb
+++ b/lib/ruby2d/application.rb
@@ -12,8 +12,8 @@ module Ruby2D::Application
@@window.set(opts)
end
- def on(args = {}, &proc)
- @@window.on(args, &proc)
+ def on(event, &proc)
+ @@window.on(event, &proc)
end
def on_key(&proc)
diff --git a/lib/ruby2d/dsl.rb b/lib/ruby2d/dsl.rb
index 910c100..99b44af 100644
--- a/lib/ruby2d/dsl.rb
+++ b/lib/ruby2d/dsl.rb
@@ -9,8 +9,8 @@ module Ruby2D::DSL
Application.set(opts)
end
- def on(args = {}, &proc)
- Application.on(args, &proc)
+ def on(event, &proc)
+ Application.on(event, &proc)
end
def on_key(&proc)
diff --git a/lib/ruby2d/window.rb b/lib/ruby2d/window.rb
index 5bc68b1..4ae1d6e 100644
--- a/lib/ruby2d/window.rb
+++ b/lib/ruby2d/window.rb
@@ -6,27 +6,32 @@ module Ruby2D
attr_reader :objects
attr_accessor :mouse_x, :mouse_y, :frames, :fps
+ MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y)
+ KeyEvent = Struct.new(:type, :key)
+ ControllerEvent = Struct.new(:which, :type, :axis, :value, :button)
+
def initialize(args = {})
- @title = args[:title] || "Ruby 2D"
- @background = Color.new([0.0, 0.0, 0.0, 1.0])
- @width = args[:width] || 640
- @height = args[:height] || 480
+ @title = args[:title] || "Ruby 2D"
+ @background = Color.new([0.0, 0.0, 0.0, 1.0])
+ @width = args[:width] || 640
+ @height = args[:height] || 480
@viewport_width, @viewport_height = nil, nil
- @resizable = false
- @borderless = false
- @fullscreen = false
- @highdpi = false
- @frames = 0
- @fps_cap = args[:fps] || 60
- @fps = @fps_cap
- @vsync = args[:vsync] || true
- @mouse_x = 0; @mouse_y = 0
- @objects = []
- @keys_down, @keys, @keys_up, @mouse, @controller = {}, {}, {}, {}, {}
- @on_key_proc = Proc.new {}
- @on_controller_proc = Proc.new {}
- @update_proc = Proc.new {}
- @diagnostics = false
+ @resizable = false
+ @borderless = false
+ @fullscreen = false
+ @highdpi = false
+ @frames = 0
+ @fps_cap = args[:fps] || 60
+ @fps = @fps_cap
+ @vsync = args[:vsync] || true
+ @mouse_x, @mouse_y = 0, 0
+ @objects = []
+ @key, @key_down, @key_held, @key_up = [], [], [], []
+ @mouse, @mouse_down, @mouse_up, @mouse_scroll, @mouse_move = [], [], [], [], []
+ @controller, @controller_axis = [], []
+ @controller_button_down, @controller_button_up = [], []
+ @update_proc = Proc.new {}
+ @diagnostics = false
end
def get(sym)
@@ -100,86 +105,123 @@ module Ruby2D
true
end
- # def on(mouse: nil, key: nil, key_up: nil, key_down: nil, controller: nil, &proc)
- def on(args = {}, &proc)
- mouse = args[:mouse]
- key = args[:key]
- key_up = args[:key_up]
- key_down = args[:key_down]
- controller = args[:controller]
+ def on(event, &proc)
+ case event
+ when :key
+ @key.push(proc)
+ when :key_down
+ @key_down.push(proc)
+ when :key_held
+ @key_held.push(proc)
+ when :key_up
+ @key_up.push(proc)
+ when :mouse
+ @mouse.push(proc)
+ when :mouse_up
+ @mouse_up.push(proc)
+ when :mouse_down
+ @mouse_down.push(proc)
+ when :mouse_scroll
+ @mouse_scroll.push(proc)
+ when :mouse_move
+ @mouse_move.push(proc)
+ when :controller
+ @controller.push(proc)
+ when :controller_axis
+ @controller_axis.push(proc)
+ when :controller_button
+ @controller_button.push(proc)
+ end
+ end
+
+ def key_callback(type, key)
+ # puts "===", "type: #{type}", "key: #{key}"
- unless mouse.nil?
- reg_mouse(mouse, &proc)
- end
+ key = key.downcase
- unless key_down.nil?
- reg_key_down(key_down, &proc)
+ # All key events
+ @key.each do |e|
+ e.call(KeyEvent.new(type, key))
end
- unless key.nil?
- reg_key(key, &proc)
- end
+ case type
+ # When key is pressed, fired once
+ when :down
+ @key_down.each do |e|
+ e.call(KeyEvent.new(type, key))
+ end
+ # When key is being held down, fired every frame
+ when :held
+ @key_held.each do |e|
+ e.call(KeyEvent.new(type, key))
+ end
+ # When key released, fired once
+ when :up
+ @key_up.each do |e|
+ e.call(KeyEvent.new(type, key))
+ end
+ end
+ end
+
+ def mouse_callback(type, button, direction, x, y, delta_x, delta_y)
+ # Convert to symbols (see MRuby bug in native extension)
+ button = button.to_sym unless button == nil
+ direction = direction.to_sym unless direction == nil
- unless key_up.nil?
- reg_key_up(key_up, &proc)
+ # All mouse events
+ @mouse.each do |e|
+ e.call(MouseEvent.new(type, button, direction, x, y, delta_x, delta_y))
end
- unless controller.nil?
- reg_controller(controller, &proc)
- end
- end
-
- def mouse_callback(btn, x, y)
- if @mouse.has_key? 'any'
- @mouse[btn].call(x, y)
+ case type
+ # When mouse button pressed
+ when :down
+ @mouse_down.each do |e|
+ e.call(MouseEvent.new(type, button, nil, x, y, nil, nil))
+ end
+ # When mouse button released
+ when :up
+ @mouse_up.each do |e|
+ e.call(MouseEvent.new(type, button, nil, x, y, nil, nil))
+ end
+ # When mouse motion / movement
+ when :scroll
+ @mouse_scroll.each do |e|
+ e.call(MouseEvent.new(type, nil, direction, nil, nil, delta_x, delta_y))
+ end
+ # When mouse scrolling, wheel or trackpad
+ when :move
+ @mouse_move.each do |e|
+ e.call(MouseEvent.new(type, nil, nil, x, y, delta_x, delta_y))
+ end
+ end
+ end
+
+ def controller_callback(which, type, axis, value, button)
+ # All controller events
+ @controller.each do |e|
+ e.call(ControllerEvent.new(which, type, axis, value, button))
end
- end
-
- def on_key(&proc)
- @on_key_proc = proc
- true
- end
-
- def key_down_callback(key)
- key = key.downcase
- if @keys_down.has_key? 'any'
- @keys_down['any'].call
- end
- if @keys_down.has_key? key
- @keys_down[key].call
- end
- end
-
- def key_callback(key)
- key = key.downcase
- @on_key_proc.call(key)
- if @keys.has_key? 'any'
- @keys['any'].call
- end
- if @keys.has_key? key
- @keys[key].call
- end
- end
-
- def key_up_callback(key)
- key = key.downcase
- if @keys_up.has_key? 'any'
- @keys_up['any'].call
- end
- if @keys_up.has_key? key
- @keys_up[key].call
+
+ case type
+ # When controller axis motion, like analog sticks
+ when :axis
+ @controller_axis.each do |e|
+ e.call(ControllerEvent.new(which, type, axis, value, nil))
+ end
+ # When controller button is pressed
+ when :button_down
+ @controller_button_down.each do |e|
+ e.call(ControllerEvent.new(which, type, nil, nil, button))
+ end
+ # When controller button is released
+ when :button_up
+ @controller_button_up.each do |e|
+ e.call(ControllerEvent.new(which, type, nil, nil, button))
+ end
end
end
- def on_controller(&proc)
- @on_controller_proc = proc
- true
- end
-
- def controller_callback(which, is_axis, axis, val, is_btn, btn, pressed)
- @on_controller_proc.call(which, is_axis, axis, val, is_btn, btn, pressed)
- end
-
def update_callback
@update_proc.call
end
@@ -195,35 +237,5 @@ module Ruby2D
end
end
- # Register key string with proc
- def reg_key_down(key, &proc)
- @keys_down[key] = proc
- true
- end
-
- # Register key string with proc
- def reg_key(key, &proc)
- @keys[key] = proc
- true
- end
-
- # Register key string with proc
- def reg_key_up(key, &proc)
- @keys_up[key] = proc
- true
- end
-
- # Register mouse button string with proc
- def reg_mouse(btn, &proc)
- @mouse[btn] = proc
- true
- end
-
- # Register controller string with proc
- def reg_controller(event, &proc)
- @controller[event] = proc
- true
- end
-
end
end
diff --git a/test/input.rb b/test/input.rb
deleted file mode 100644
index 82bce4a..0000000
--- a/test/input.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'ruby2d'
-
-set width: 200, height: 100, title: "Ruby 2D — Input"
-
-on key_down: 'a' do
- puts "Key 'a' down"
-end
-
-on key: 'b' do
- puts "Key 'b' held down"
-end
-
-on key_up: 'c' do
- puts "Key 'c' up"
-end
-
-on key_down: 'any' do
- puts "A key was pressed"
-end
-
-on_key do |key|
- if key == 'd'
- puts "on_key: #{key}"
- end
-end
-
-on mouse: 'any' do |x, y|
- puts "Mouse clicked at: #{x}, #{y}"
-end
-
-on key: 'escape' do
- close
-end
-
-show
diff --git a/test/key.rb b/test/key.rb
new file mode 100644
index 0000000..3c2c8e6
--- /dev/null
+++ b/test/key.rb
@@ -0,0 +1,30 @@
+require 'ruby2d'
+
+set title: "Ruby 2D — Key", width: 300, height: 200
+
+s1 = Square.new(5, 5, 50, [1, 1, 1, 1])
+s2 = Square.new(60, 5, 50, [1, 1, 1, 1])
+
+on :key do |event|
+ puts event
+end
+
+on :key_down do |event|
+ s1.color = [1, 0, 0, 1]
+end
+
+on :key_held do |event|
+ s2.color = [0, 1, 0, 1]
+end
+
+on :key_up do |event|
+ s1.color = [1, 1, 1, 1]
+ s2.color = [1, 1, 1, 1]
+end
+
+
+on :key_down do |event|
+ close if event.key == 'escape'
+end
+
+show
diff --git a/test/mouse.rb b/test/mouse.rb
new file mode 100644
index 0000000..7daa738
--- /dev/null
+++ b/test/mouse.rb
@@ -0,0 +1,53 @@
+require 'ruby2d'
+
+set title: "Ruby 2D — Mouse", width: 400, height: 300
+
+on :mouse do |event|
+ puts event
+end
+
+s1 = Square.new(5, 5, 25, [1, 1, 0, 1]) # mouse down square
+s2 = Square.new(188, 10, 25) # mouse scroll square
+s3 = Square.new(188, 137, 25, [1, 1, 1, 1]) # mouse move delta square
+s4 = Square.new(35, 5, 10) # mouse move position square
+
+on :mouse_down do |event|
+ case event.button
+ when :left
+ s1.color = [1, 0, 0, 1]
+ when :middle
+ s1.color = [0, 0, 1, 1]
+ when :right
+ s1.color = [0, 1, 0, 1]
+ end
+ s1.x = event.x
+ s1.y = event.y
+end
+
+on :mouse_up do |event|
+ s1.color = [1, 1, 0, 1]
+ s1.x = event.x
+ s1.y = event.y
+end
+
+on :mouse_scroll do |event|
+ s2.x = s2.x + event.delta_x
+ s2.y = s2.y + event.delta_y
+end
+
+on :mouse_move do |event|
+ s3.x = 188 + event.delta_x
+ s3.y = 137 + event.delta_y
+ s4.x = event.x - 5
+ s4.y = event.y - 5
+end
+
+# Crosshairs
+Rectangle.new(199, 0, 2, 300, [1, 0, 0, 1])
+Rectangle.new(0, 149, 400, 2, [1, 0, 0, 1])
+
+on :key_down do |event|
+ close if event.key == 'escape'
+end
+
+show
diff --git a/test/testcard.rb b/test/testcard.rb
index 1951390..a7dc308 100644
--- a/test/testcard.rb
+++ b/test/testcard.rb
@@ -203,12 +203,11 @@ updated_text.remove
updated_text.add
UPDATED_TEXT_OPTIONS = "of various size".split(" ")
-on key: 'escape' do
- close
+on :key_down do |event|
+ close if event.key == 'escape'
end
-on mouse: 'any' do |x, y|
- puts "Mouse down at: #{x}, #{y}"
+on :mouse_down do
pointer_outline.x = (get :mouse_x) - 9
pointer_outline.y = (get :mouse_y) - 11
flash = 2