smalruby-editor 0.1.15-x86-mingw32 → 0.1.16-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of smalruby-editor might be problematic. Click here for more details.

Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +16 -1
  3. data/app/assets/javascripts/blocks/character.js.coffee.erb +8 -1
  4. data/app/assets/javascripts/blocks/hardware.js.coffee.erb +59 -7
  5. data/app/assets/javascripts/blocks/motion.js.coffee.erb +1 -2
  6. data/app/assets/javascripts/models/character.js.coffee +27 -0
  7. data/app/assets/javascripts/smalruby.js.coffee +4 -0
  8. data/app/assets/javascripts/views/character_modal_view.js.coffee +22 -1
  9. data/app/assets/javascripts/views/character_selector_view.js.coffee +7 -6
  10. data/app/assets/stylesheets/application.css +8 -0
  11. data/app/assets/stylesheets/editor.css.scss +15 -5
  12. data/app/controllers/application_controller.rb +4 -7
  13. data/app/models/concerns/ruby_to_block/block/character.rb +14 -6
  14. data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car.rb +1 -1
  15. data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car_commands.rb +15 -0
  16. data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car_run.rb +19 -0
  17. data/app/models/concerns/ruby_to_block/block/motion_set_x.rb +1 -24
  18. data/app/models/concerns/ruby_to_block/block/motion_set_x_y.rb +21 -0
  19. data/app/models/source_code.rb +9 -6
  20. data/app/views/editor/_block_tab.html.haml +3 -1
  21. data/app/views/editor/_character_modal.html.haml +14 -5
  22. data/app/views/editor/_toolbox.html.haml +91 -78
  23. data/bin/smalruby-editor +15 -0
  24. data/lib/smalruby_editor.rb +39 -4
  25. data/lib/smalruby_editor/version.rb +1 -1
  26. data/public/assets/{application-51ab300acd1779bfba20b099e7000b7e.css → application-7f560d8d6d224f87269691c57ca9a376.css} +23 -9
  27. data/public/assets/{application-51ab300acd1779bfba20b099e7000b7e.css.gz → application-7f560d8d6d224f87269691c57ca9a376.css.gz} +0 -0
  28. data/public/assets/{application-dc485e2270d6c5fce20c149d1e2c4f8d.js → application-842ac8f5aa3fcc87bbb0e8b3a0fef5d7.js} +148 -21
  29. data/public/assets/{application-dc485e2270d6c5fce20c149d1e2c4f8d.js.gz → application-842ac8f5aa3fcc87bbb0e8b3a0fef5d7.js.gz} +0 -0
  30. data/public/assets/manifest-332a5a1668194028b55103e0ea45c054.json +1 -1
  31. data/smalruby-editor.gemspec +1 -1
  32. data/spec/acceptance/block_mode/blocks/motion/set_x_y.feature +2 -4
  33. data/spec/lib/smalruby_editor_spec.rb +12 -0
  34. data/spec/models/concerns/ruby_to_block/block/hardware_spec.rb +90 -10
  35. data/spec/models/concerns/ruby_to_block/block/motion_spec.rb +3 -6
  36. metadata +11 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d53fa32a3b8707706add17ac92e087881b7d4f2
4
- data.tar.gz: 842742995256fbc29130fbdd9de50b906ed1fd49
3
+ metadata.gz: 47874074016e9dd005b8b5b4eac725702132b95a
4
+ data.tar.gz: d44bf9676c75316949454979710c94ea1d7929c2
5
5
  SHA512:
6
- metadata.gz: 9bab4b91459b18253fca144251ddcbb68a445f2f6cb12702b645a1e5ff894c2411b301bea079d4557875c2b9174e4973044dc8f1a0008b9c4c45da1adf34d4c1
7
- data.tar.gz: 32d4a35fb1a7a727b91f8ef59f860589ffa59e2b1810a2338eda4c01a06de5b2a70c4745ab36c58c636dcefdf56643ea285b5196ff87ed356a42e4e121a60ec1
6
+ metadata.gz: b7c276231be625d03b1b0114d9ab578481eeca372320a9eac85b321ef0f24de124dcbce6d8c32338c2ed9f3777ce30fd5d3da06cc642408203a2888500fabba1
7
+ data.tar.gz: 69a417672aadef53615da7c5d8f82836290900c2ced56613513a6b624fde363ae5ef21beb571332ff18badd9e86b9f54b36fdfbe63f5d5311333aa4aee1789e8
data/README.rdoc CHANGED
@@ -11,10 +11,24 @@ The smalruby-editor is a visual programming editor that can create a Ruby script
11
11
  * DEMO: http://smalruby.herokuapp.com/demo/
12
12
  * DEMO(Arduino): http://smalruby.herokuapp.com/demo/rgb_led_anode/
13
13
 
14
- The smalruby-editor is a part of the Smalruby Project.
14
+ The smalruby-editor is a part of the Smalruby (http://smalruby.jp) Project.
15
15
 
16
16
  The Smalruby(smɔ́ːrúːbi) Project will provide a Ruby learning environment for middle school students from the upper grades of elementary school. The goal of this project is to achieve software and community sites such as the {Scratch}[http://scratch.mit.edu/] in Ruby. The Scratch has experience as educational programming environment can be used in elementary school. This project consists of the following elements.
17
17
 
18
+ == Installation (for User)
19
+
20
+ requirements:
21
+
22
+ * Windows or UNIX like OS (Mac OS X, Linux, etc...)
23
+ * Ruby 2.0.0-p353 or higher.
24
+ * dxruby_sdl (only Mac OS X and Linux): https://github.com/takaokouji/dxruby_sdl/
25
+ * rsdl (only Mac OS X): http://www.kumaryu.net/proj/ruby-rsdl/
26
+
27
+ execute below commands.
28
+
29
+ gem install smalruby-editor
30
+ smalruby-editor
31
+
18
32
  == Installation (for Developer)
19
33
 
20
34
  requirements:
@@ -32,6 +46,7 @@ execute below commands.
32
46
  rake db:create
33
47
  rake db:migrate
34
48
  rake
49
+ touch tmp/standalone
35
50
  rails server
36
51
 
37
52
  access <tt>localhost:3000</tt> with your web browser.
@@ -65,8 +65,15 @@ Blockly.Blocks['<%= n %>'] =
65
65
 
66
66
  Blockly.Ruby['<%= n %>'] = (block) ->
67
67
  c = block.character
68
+ switch c.get('rotationStyle')
69
+ when 'left_right'
70
+ rotationStyle = ', rotation_style: :left_right'
71
+ when 'none'
72
+ rotationStyle = ', rotation_style: :none'
73
+ else
74
+ rotationStyle = ''
68
75
  Blockly.Ruby.definitions_["character_#{c.get('name')}"] =
69
- "#{c.get('name')} = Character.new(costume: #{Blockly.Ruby.quote_(c.costume())}, x: #{c.get('x')}, y: #{c.get('y')}, angle: #{c.get('angle')})"
76
+ "#{c.get('name')} = Character.new(costume: #{Blockly.Ruby.quote_(c.costume())}, x: #{c.get('x')}, y: #{c.get('y')}, angle: #{c.get('angle')}#{rotationStyle})"
70
77
  Blockly.Ruby.cs_().push(c)
71
78
  try
72
79
  targetBlock = block.getInputTargetBlock('DO')
@@ -29,6 +29,8 @@ acDropdown = [
29
29
  ['カソード', 'cathode']
30
30
  ]
31
31
 
32
+ twoWDPinDropdown = (["D#{n}", "D#{n}"] for n in [2..10])
33
+
32
34
  # ハードウェアを準備する
33
35
  <% n = "#{category}_init_hardware" %>
34
36
  Blockly.Blocks['<%= n %>'] =
@@ -241,12 +243,13 @@ Blockly.Ruby['<%= n %>'] = (block) ->
241
243
  Blockly.Ruby.characterMethodCall_("servo(#{Blockly.Ruby.quote_(pin)}).position = #{pos}")
242
244
 
243
245
  # 「車」サブジャンル
246
+ <% subcategory = 'two_wheel_drive_car' %>
244
247
 
245
- # 2WD車[▼ピン]を進める」ブロック
246
- # 2WD車[▼ピン]をバックさせる」ブロック
247
- # 2WD車[▼ピン]を左に曲げる」ブロック
248
- # 2WD車[▼ピン]を右に曲げる」ブロック
249
- # 2WD車[▼ピン]を止める」ブロック
248
+ # 2WD車[▼ピン]を進める
249
+ # 2WD車[▼ピン]をバックさせる
250
+ # 2WD車[▼ピン]を左に曲げる
251
+ # 2WD車[▼ピン]を右に曲げる
252
+ # 2WD車[▼ピン]を止める
250
253
  <%
251
254
  [
252
255
  ['forward', '進める'],
@@ -255,7 +258,7 @@ Blockly.Ruby['<%= n %>'] = (block) ->
255
258
  ['turn_right', '右に曲げる'],
256
259
  ['stop', '止める'],
257
260
  ].each do |method, label|
258
- n = "#{category}_two_wheel_drive_car_#{method}"
261
+ n = "#{category}_#{subcategory}_#{method}"
259
262
  %>
260
263
 
261
264
  Blockly.Blocks['<%= n %>'] =
@@ -266,7 +269,7 @@ Blockly.Blocks['<%= n %>'] =
266
269
  @setColour(<%= color %>)
267
270
  @appendDummyInput()
268
271
  .appendField('2WD車')
269
- .appendField(new Blockly.FieldDropdown(dropdown), 'PIN')
272
+ .appendField(new Blockly.FieldDropdown(twoWDPinDropdown), 'PIN')
270
273
  .appendField('を<%= label %>')
271
274
  @setInputsInline(true)
272
275
  @setPreviousStatement(true)
@@ -279,6 +282,55 @@ Blockly.Ruby['<%= n %>'] = (block) ->
279
282
  Blockly.Ruby.characterMethodCall_("two_wheel_drive_car(#{Blockly.Ruby.quote_(pin)}).<%= method %>")
280
283
  <% end %>
281
284
 
285
+ # 2WD車[▼ピン]を( )秒[▼コマンド]
286
+ <% n = "#{category}_#{subcategory}_run" %>
287
+ Blockly.Blocks['<%= n %>'] =
288
+ init: ()->
289
+ @setHelpUrl('')
290
+ @setColour(<%= color %>)
291
+ @appendDummyInput()
292
+ .appendField('2WD車')
293
+ .appendField(new Blockly.FieldDropdown(twoWDPinDropdown), 'PIN')
294
+ .appendField('を')
295
+ @appendValueInput('SEC')
296
+ .setCheck('Number')
297
+ @appendDummyInput()
298
+ .appendField('秒')
299
+ @appendValueInput('COMMAND').setCheck('String')
300
+ @setInputsInline(true)
301
+ @setPreviousStatement(true)
302
+ @setNextStatement(true)
303
+ @setTooltip('')
304
+
305
+ Blockly.Ruby['<%= n %>'] = (block) ->
306
+ pin = @getFieldValue('PIN')
307
+ sec = Blockly.Ruby.valueToCode(@, 'SEC', Blockly.Ruby.ORDER_NONE) || 0
308
+ command = Blockly.Ruby.valueToCode(@, 'COMMAND', Blockly.Ruby.ORDER_NONE) || Blockly.Ruby.quote_('stop')
309
+
310
+ Blockly.Ruby.characterMethodCall_("two_wheel_drive_car(#{Blockly.Ruby.quote_(pin)}).run(command: #{command}, sec: #{sec})")
311
+
312
+ # [▼コマンド]
313
+ <% n = "#{category}_#{subcategory}_commands" %>
314
+ Blockly.Blocks['<%= n %>'] =
315
+ init: ()->
316
+ commands = [
317
+ ['進める', 'forward'],
318
+ ['バックさせる', 'backward'],
319
+ ['左に曲げる', 'turn_left'],
320
+ ['右に曲げる', 'turn_right'],
321
+ ['止める', 'stop'],
322
+ ]
323
+ @setHelpUrl('')
324
+ @setColour(<%= color %>)
325
+ @appendDummyInput()
326
+ .appendField(new Blockly.FieldDropdown(commands), 'COMMAND')
327
+ @setOutput(true, 'String')
328
+ @setTooltip('')
329
+
330
+ Blockly.Ruby['<%= n %>'] = (block) ->
331
+ code = Blockly.Ruby.quote_(@getFieldValue('COMMAND'))
332
+ [code, Blockly.Ruby.ORDER_ATOMIC]
333
+
282
334
  # 「ボタン」サブジャンル
283
335
 
284
336
  # 条件:ボタン[▼]を押している
@@ -119,8 +119,7 @@ Blockly.Blocks['<%= n %>'] =
119
119
  Blockly.Ruby['<%= n %>'] = (block) ->
120
120
  x = Blockly.Ruby.valueToCode(@, 'X', Blockly.Ruby.ORDER_NONE) || '0'
121
121
  y = Blockly.Ruby.valueToCode(@, 'Y', Blockly.Ruby.ORDER_NONE) || '0'
122
- Blockly.Ruby.characterSetVariable_('x', x) +
123
- Blockly.Ruby.characterSetVariable_('y', y)
122
+ Blockly.Ruby.characterSetVariable_('position', "[#{x}, #{y}]")
124
123
 
125
124
  # マウスポインターへ行く
126
125
  <% n = "#{category}_go_to_mouse" %>
@@ -6,6 +6,7 @@ Smalruby.Character = Backbone.Model.extend({
6
6
  x: 0
7
7
  y: 0
8
8
  angle: 0
9
+ rotationStyle: 'free'
9
10
  visible: true
10
11
  using: false
11
12
 
@@ -64,6 +65,32 @@ Smalruby.Character = Backbone.Model.extend({
64
65
  i = 0 if i >= @get('costumes').length
65
66
  @set({ 'costumeIndex': i })
66
67
  i
68
+
69
+ rotationStyleIconName: ->
70
+ switch @get('rotationStyle')
71
+ when 'free'
72
+ 'icon-repeat'
73
+ when 'left_right'
74
+ 'icon-resize-horizontal'
75
+ when 'none'
76
+ 'icon-arrow-right'
77
+
78
+ rotateImage: (selector) ->
79
+ angle = @get('angle')
80
+ switch @get('rotationStyle')
81
+ when 'free'
82
+ transformValue = "rotate(#{angle}deg) scaleX(1)"
83
+ when 'left_right'
84
+ if angle < 90 || angle >= 270
85
+ transformValue = "rotate(0deg) scaleX(1)"
86
+ else
87
+ transformValue = "rotate(0deg) scaleX(-1)"
88
+ when 'none'
89
+ transformValue = "rotate(0deg) scaleX(1)"
90
+ $(selector).css
91
+ '-moz-transform': transformValue
92
+ '-webkit-transform': transformValue
93
+ transform: transformValue
67
94
  }, {
68
95
  PRESET_COSTUMES: [
69
96
  'car1.png'
@@ -131,6 +131,7 @@ window.Smalruby =
131
131
  x: parseInt(xmlChild.getAttribute('x'), 10)
132
132
  y: parseInt(xmlChild.getAttribute('y'), 10)
133
133
  angle: parseInt(xmlChild.getAttribute('angle'), 10)
134
+ rotationStyle: xmlChild.getAttribute('rotation_style') || 'free'
134
135
  chars.push(c)
135
136
  i++
136
137
  Smalruby.Collections.CharacterSet.reset(chars)
@@ -146,6 +147,9 @@ window.Smalruby =
146
147
  e.setAttribute('name', c.get('name'))
147
148
  e.setAttribute('costumes', c.get('costumes').join(','))
148
149
  e.setAttribute('angle', c.get('angle'))
150
+ rotationStyle = c.get('rotationStyle')
151
+ if rotationStyle != 'free'
152
+ e.setAttribute('rotation_style', rotationStyle)
149
153
  xmlDom.insertBefore(e, blocklyDom)
150
154
  Blockly.Xml.domToPrettyText(xmlDom)
151
155
 
@@ -4,6 +4,9 @@ Smalruby.CharacterModalView = Backbone.View.extend
4
4
 
5
5
  events:
6
6
  'click #character-modal-costume-selector a': 'onSelectCostume'
7
+ 'click #character_rotation_style_free': 'onRotationStyleFree'
8
+ 'click #character_rotation_style_left_right': 'onRotationStyleLeftRight'
9
+ 'click #character_rotation_style_none': 'onRotationStyleNone'
7
10
  'click #character-modal-ok-button': 'onOk'
8
11
 
9
12
  previewZoomLevel: 0.5
@@ -57,6 +60,7 @@ Smalruby.CharacterModalView = Backbone.View.extend
57
60
  @listenTo(@model, 'change:y', @onChangeY)
58
61
  @listenTo(@model, 'change:angle', @onChangeAngle)
59
62
  @listenTo(@model, 'change:costumes', @onChangeCostumes)
63
+ @listenTo(@model, 'change:rotationStyle', @onChangeRotationStyle)
60
64
  @listenTo(@model, 'change', @onChange)
61
65
 
62
66
  @callAllOnChangeAttributes_()
@@ -85,6 +89,7 @@ Smalruby.CharacterModalView = Backbone.View.extend
85
89
  @onChangeY(@model, @model.get('y'))
86
90
  @onChangeAngle(@model, @model.get('angle'))
87
91
  @onChangeCostumes(@model, @model.get('costumes'))
92
+ @onChangeRotationStyle(@model, @model.get('rotationStyle'))
88
93
 
89
94
  onChangeName: (model, value, options) ->
90
95
  @$el.find('input[name="character[name]"]').val(value)
@@ -103,11 +108,13 @@ Smalruby.CharacterModalView = Backbone.View.extend
103
108
  @$el.find('input[name="character[angle]"]').val(value)
104
109
  $('#character_angle_value').text("#{value}°")
105
110
  rotate = "rotate(#{value}deg)"
106
- $('#character-modal-character').css
111
+ $('#character_angle_vector').css
107
112
  '-moz-transform': rotate
108
113
  '-webkit-transform': rotate
109
114
  transform: rotate
110
115
 
116
+ @model.rotateImage('#character-modal-character')
117
+
111
118
  onChangeCostumes: (model, value, options) ->
112
119
  img = $('<img>').attr
113
120
  src: model.costumeUrl()
@@ -123,6 +130,11 @@ Smalruby.CharacterModalView = Backbone.View.extend
123
130
  else
124
131
  @readImageSizeflag = true
125
132
 
133
+ onChangeRotationStyle: (model, value, options) ->
134
+ $('#character_rotation_style button.btn').removeClass('btn-primary')
135
+ $("#character_rotation_style_#{value}").addClass('btn-primary')
136
+ @onChangeAngle(@model, @model.get('angle'))
137
+
126
138
  onChange: (model, options) ->
127
139
  return unless @target
128
140
 
@@ -157,6 +169,15 @@ Smalruby.CharacterModalView = Backbone.View.extend
157
169
 
158
170
  @model.set(attrs)
159
171
 
172
+ onRotationStyleFree: ->
173
+ @model.set({ rotationStyle: 'free' })
174
+
175
+ onRotationStyleLeftRight: ->
176
+ @model.set({ rotationStyle: 'left_right' })
177
+
178
+ onRotationStyleNone: ->
179
+ @model.set({ rotationStyle: 'none' })
180
+
160
181
  onOk: ->
161
182
  @$el.modal('hide')
162
183
  if @target
@@ -5,7 +5,7 @@ Smalruby.CharacterSelectorView = Backbone.View.extend({
5
5
  initialize: ->
6
6
  @klass = Smalruby.CharacterSelectorView
7
7
 
8
- @listenTo(@model, name, @render) for name in ['add', 'remove', 'reset', 'change']
8
+ @listenTo(@model, name, @onChange) for name in ['add', 'remove', 'reset', 'change']
9
9
 
10
10
  @templateText = $('#character-selector-template').text()
11
11
 
@@ -49,15 +49,16 @@ Smalruby.CharacterSelectorView = Backbone.View.extend({
49
49
  if character.get('using')
50
50
  removeButton.hide()
51
51
 
52
- rotate = "rotate(#{character.get('angle')}deg)"
53
52
  img = html.find('img')
54
- img.css
55
- '-moz-transform': rotate
56
- '-webkit-transform': rotate
57
- transform: rotate
53
+ character.rotateImage(img)
58
54
  img.on 'dragstart', (e) ->
59
55
  e.preventDefault()
60
56
 
57
+ onChange: ->
58
+ unless Smalruby.blocklyLoading
59
+ Smalruby.changedAfterTranslating = true
60
+ window.changed = true
61
+ @render()
61
62
 
62
63
  addBlock_: (character) ->
63
64
  newBlock = new Blockly.Block(Blockly.mainWorkspace, 'character_new')
@@ -17,3 +17,11 @@ html, body {
17
17
  height: 100%;
18
18
  margin: 0;
19
19
  }
20
+
21
+ body {
22
+ user-select: none;
23
+ -moz-user-select: none;
24
+ -khtml-user-select: none;
25
+ -webkit-user-select: none;
26
+ -ms-user-select: none;
27
+ }
@@ -168,6 +168,11 @@ $left-pane-width: $character-size + $margin * 2;
168
168
  img, div {
169
169
  margin: -$border-size;
170
170
  }
171
+
172
+ img {
173
+ max-width: $character-size;
174
+ max-height: $character-size;
175
+ }
171
176
  }
172
177
 
173
178
  a.character:hover {
@@ -235,11 +240,11 @@ $left-pane-width: $character-size + $margin * 2;
235
240
 
236
241
  $attributes-height: 160px;
237
242
 
238
- $left-pane-width: $preview-width;
243
+ $left-pane-width: $preview-width + 2px;
239
244
  $right-pane-width: $character-size * 3 + $modal-body-margin;
240
245
 
241
246
  $modal-width: $left-pane-width + $right-pane-width + $modal-margin * 2;
242
- $modal-height: $preview-height + $attributes-height + $modal-margin * 2;
247
+ $modal-height: $preview-height + 2px + $attributes-height + $modal-margin * 2;
243
248
 
244
249
  width: $modal-width;
245
250
  height: $modal-height;
@@ -259,7 +264,8 @@ $left-pane-width: $character-size + $margin * 2;
259
264
 
260
265
  width: $preview-width;
261
266
  height: $preview-height;
262
- background-color: black;
267
+ background-color: white;
268
+ border: 1px solid gray;
263
269
  overflow: hidden;
264
270
 
265
271
  #character-modal-character {
@@ -289,15 +295,19 @@ $left-pane-width: $character-size + $margin * 2;
289
295
  margin-bottom: 8px;
290
296
 
291
297
  .control-label {
292
- width: 100px;
298
+ width: 50px;
293
299
  }
294
300
 
295
301
  .controls {
296
- margin-left: 100px + $modal-body-margin;
302
+ margin-left: 50px + $modal-body-margin;
297
303
 
298
304
  input[type=range] {
299
305
  padding: 0;
300
306
  }
307
+
308
+ span#character_angle_vector {
309
+ display: inline-block;
310
+ }
301
311
  }
302
312
  }
303
313
  }
@@ -1,4 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
+
3
+ require 'smalruby_editor'
4
+
2
5
  class ApplicationController < ActionController::Base
3
6
  # Prevent CSRF attacks by raising an exception.
4
7
  # For APIs, you may want to use :null_session instead.
@@ -24,13 +27,7 @@ class ApplicationController < ActionController::Base
24
27
 
25
28
  # Raspberry Piかどうかを返す
26
29
  def raspberrypi?
27
- if Rails.env != 'test' &&
28
- (ENV['SMALRUBY_EDITOR_RASPBERRYPI_MODE'] ||
29
- File.exist?(Rails.root.join('tmp', 'raspberrypi')))
30
- true
31
- else
32
- RbConfig::CONFIG['arch'] == 'armv6l-linux-eabihf'
33
- end
30
+ SmalrubyEditor.raspberrypi?
34
31
  end
35
32
 
36
33
  def check_whether_standalone
@@ -4,7 +4,7 @@ module RubyToBlock
4
4
  # ソースコードに含まれるキャラクターを表現するクラス
5
5
  class Character < Base
6
6
  # rubocop:disable LineLength
7
- blocknize '^\s*(\S+)\s*=\s*Character\.new\(costume:\s*"(\s*[^"]+\s*)"\s*,\s*x:\s*(\s*\d+\s*)\s*,\s*y:\s*(\s*\d+\s*)\s*,\s*angle:\s*(\s*\d+\s*)\)\s*$',
7
+ blocknize '^\s*(\S+)\s*=\s*Character\.new\(costume:\s*"(\s*[^"]+\s*)"\s*,\s*x:\s*(\s*\d+\s*)\s*,\s*y:\s*(\s*\d+\s*)\s*,\s*angle:\s*(\s*\d+\s*)(?:,\s*rotation_style:\s*\s*:(free|left_right|none)\s*)?\)\s*$',
8
8
  statement: true
9
9
  # rubocop:enable LineLength
10
10
 
@@ -13,12 +13,14 @@ module RubyToBlock
13
13
  attr_accessor :x
14
14
  attr_accessor :y
15
15
  attr_accessor :angle
16
+ attr_accessor :rotation_style
16
17
 
17
18
  def self.process_match_data(md, context)
18
19
  md2 = regexp.match(md[type])
19
20
  name = md2[1]
20
21
  context[:characters][name] = new(name: name, costumes: [md2[2]],
21
- x: md2[3], y: md2[4], angle: md2[5])
22
+ x: md2[3], y: md2[4], angle: md2[5],
23
+ rotation_style: md2[6] || 'free')
22
24
 
23
25
  true
24
26
  end
@@ -29,13 +31,19 @@ module RubyToBlock
29
31
  @x = options[:x]
30
32
  @y = options[:y]
31
33
  @angle = options[:angle]
34
+ @rotation_style = options[:rotation_style]
32
35
  end
33
36
 
34
37
  def to_xml(parent)
35
- parent.add_element('character',
36
- 'name' => @name,
37
- 'x' => @x, 'y' => @y, 'angle' => @angle,
38
- 'costumes' => @costumes.join(','))
38
+ attrs = {
39
+ 'name' => @name,
40
+ 'x' => @x,
41
+ 'y' => @y,
42
+ 'angle' => @angle,
43
+ 'costumes' => @costumes.join(',')
44
+ }
45
+ attrs['rotationStyle'] = @rotation_style if @rotation_style != 'free'
46
+ parent.add_element('character', attrs)
39
47
  end
40
48
  end
41
49
  end