cyross-ruby-miyako 2.0.0 → 2.0.5.1.0

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.
Files changed (102) hide show
  1. data/README +106 -154
  2. data/defines.h +144 -0
  3. data/{miyako_no_katana/extconf.rb → extconf.rb} +10 -0
  4. data/extern.h +29 -0
  5. data/install_miyako.rb +26 -14
  6. data/lib/Miyako/API/audio.rb +2 -2
  7. data/lib/Miyako/API/basic_data.rb +183 -41
  8. data/lib/Miyako/API/bitmap.rb +474 -2
  9. data/lib/Miyako/API/choices.rb +215 -48
  10. data/lib/Miyako/API/collision.rb +267 -251
  11. data/lib/Miyako/API/diagram.rb +58 -70
  12. data/lib/Miyako/API/drawing.rb +93 -52
  13. data/lib/Miyako/API/fixedmap.rb +233 -120
  14. data/lib/Miyako/API/font.rb +59 -40
  15. data/lib/Miyako/API/input.rb +34 -27
  16. data/lib/Miyako/API/layout.rb +154 -172
  17. data/lib/Miyako/API/map.rb +285 -159
  18. data/lib/Miyako/API/map_event.rb +4 -4
  19. data/lib/Miyako/API/modules.rb +1 -1
  20. data/lib/Miyako/API/movie.rb +8 -5
  21. data/lib/Miyako/API/parts.rb +44 -9
  22. data/lib/Miyako/API/plane.rb +37 -2
  23. data/lib/Miyako/API/screen.rb +90 -22
  24. data/lib/Miyako/API/shape.rb +118 -37
  25. data/lib/Miyako/API/sprite.rb +475 -61
  26. data/lib/Miyako/API/sprite_animation.rb +83 -63
  27. data/lib/Miyako/API/spriteunit.rb +47 -13
  28. data/lib/Miyako/API/story.rb +123 -47
  29. data/lib/Miyako/API/textbox.rb +361 -132
  30. data/lib/Miyako/API/utility.rb +388 -0
  31. data/lib/Miyako/API/viewport.rb +54 -349
  32. data/lib/Miyako/API/yuki.rb +570 -353
  33. data/lib/Miyako/EXT/miyako_cairo.rb +5 -3
  34. data/lib/Miyako/EXT/slides.rb +22 -1
  35. data/lib/Miyako/miyako.rb +12 -13
  36. data/logo/EGSR_logo.png +0 -0
  37. data/logo/EGSR_logo_bg.png +0 -0
  38. data/logo/EGSR_logo_fg.png +0 -0
  39. data/logo/EGSR_title_banner.png +0 -0
  40. data/logo/EGSR_title_logo.png +0 -0
  41. data/logo/miyako.png +0 -0
  42. data/logo/miyako_banner.png +0 -0
  43. data/logo/space.png +0 -0
  44. data/miyako_basicdata.c +590 -0
  45. data/miyako_bitmap.c +1225 -0
  46. data/miyako_collision.c +403 -0
  47. data/miyako_drawing.c +187 -0
  48. data/miyako_font.c +334 -0
  49. data/miyako_hsv.c +830 -0
  50. data/miyako_layout.c +191 -0
  51. data/miyako_no_katana.c +1074 -0
  52. data/miyako_transform.c +438 -0
  53. data/miyako_utility.c +288 -0
  54. data/sample/Animation1/m1ku.rb +10 -31
  55. data/sample/Animation1/readme.txt +6 -6
  56. data/sample/Animation2/lex.rb +1 -0
  57. data/sample/Animation2/readme.txt +6 -6
  58. data/sample/Diagram_sample/diagram_sample_yuki2.rb +152 -48
  59. data/sample/Diagram_sample/readme.txt +9 -6
  60. data/sample/Room3/blue.rb +234 -187
  61. data/sample/Room3/ending.rb +68 -63
  62. data/sample/Room3/green.rb +159 -124
  63. data/sample/Room3/main.rb +50 -32
  64. data/sample/Room3/main_component.rb +3 -2
  65. data/sample/Room3/readme.txt +6 -6
  66. data/sample/Room3/red.rb +161 -134
  67. data/sample/Room3/room3.rb +1 -0
  68. data/sample/Room3/title.rb +75 -62
  69. data/sample/ball_action_sample.rb +204 -0
  70. data/sample/blit_rop.rb +70 -0
  71. data/sample/cairo_sample.rb +25 -0
  72. data/sample/circle_collision_test.rb +66 -0
  73. data/sample/collision_test.rb +33 -0
  74. data/sample/collision_test2.rb +108 -0
  75. data/sample/fixed_map_test/fixed_map_sample.rb +23 -32
  76. data/sample/fixed_map_test/readme.txt +38 -38
  77. data/sample/map_test/chara.rb +17 -9
  78. data/sample/map_test/main_parts.rb +30 -9
  79. data/sample/map_test/main_scene.rb +57 -41
  80. data/sample/map_test/map_manager.rb +13 -30
  81. data/sample/map_test/map_test.rb +2 -2
  82. data/sample/map_test/oasis.rb +17 -11
  83. data/sample/map_test/readme.txt +50 -48
  84. data/sample/map_test/route.rb +46 -33
  85. data/sample/map_test/town.rb +19 -13
  86. data/sample/polygon_test.rb +35 -0
  87. data/sample/rasterscroll.rb +25 -0
  88. data/sample/takahashi.rb +42 -0
  89. data/sample/text.png +0 -0
  90. data/sample/textbox_sample.rb +190 -0
  91. data/sample/transform.rb +54 -0
  92. data/sample/utility_test.rb +73 -0
  93. data/sample/utility_test2.rb +61 -0
  94. data/sample/utility_test3.rb +64 -0
  95. data/sample/utility_test4.rb +73 -0
  96. data/uninstall_miyako.rb +19 -0
  97. data/win/miyako_no_katana.so +0 -0
  98. metadata +165 -148
  99. data/miyako.png +0 -0
  100. data/miyako_banner.png +0 -0
  101. data/miyako_no_katana/miyako_no_katana.c +0 -3301
  102. data/sample/fixed_map_test/map_sample.rb +0 -121
@@ -29,34 +29,32 @@ module Miyako
29
29
  include Layout
30
30
  extend Forwardable
31
31
 
32
- @@windows = Array.new
33
- @@select_margin = {:left => 1, :over => 0}
34
-
35
32
  attr_accessor :textarea
36
- attr_accessor :pause_type, :select_type, :waiting, :selecting
33
+ attr_accessor :select_type, :waiting, :selecting
37
34
  attr_accessor :font, :margin
38
35
  attr_reader :wait_cursor, :select_cursor, :choices
39
- attr_reader :draw_type, :locate, :size, :max_height
36
+ attr_reader :locate, :size, :max_height
40
37
 
41
38
  #===インスタンスの作成
42
39
  #テキストボックスを生成する。パラメータは以下の通り。
43
40
  #(括弧内は省略形)
44
- #:font:: 描画フォント(Fontクラスのインスタンス) デフォルトはFont.sans_serif
45
- #:size:: 描画文字数(2要素の配列またはSize構造体のインスタンス) デフォルトはSize(20,8)
46
- #:wait_cursor(:wc):: ボタン入力待ちを示すカーソル(SpriteもしくはSpriteAnimationクラスのインスタンス)
47
- #:select_cursor(:sc):: 選択カーソル(SpriteもしくはSpriteAnimationクラスのインスタンス)
48
- #:page_size:: 一度にテキストボックスに表示させる選択肢の数(縦方向、デフォルトは8)
41
+ #_:font_:: 描画フォント(Fontクラスのインスタンス) デフォルトはFont.sans_serif
42
+ #_:size_:: 描画文字数(2要素の配列またはSize構造体のインスタンス) デフォルトはSize(20,8)
43
+ #_:wait_cursor(:wc)_:: ボタン入力待ちを示すカーソル(SpriteもしくはSpriteAnimationクラスのインスタンス)
44
+ #_:select_cursor(:sc)_:: 選択カーソル(SpriteもしくはSpriteAnimationクラスのインスタンス)
45
+ #_:page_size_:: 一度にテキストボックスに表示させる選択肢の数(縦方向、デフォルトは8)
49
46
  #
50
47
  #_params_:: 生成時のパラメータ(ハッシュ引数)
51
48
  #返却値:: TextBoxクラスのインスタンス
52
49
  def initialize(params = {})
53
50
  init_layout
51
+ @visible = true
54
52
  @font = params[:font] || Font.sans_serif
55
53
  @max_height = @font.line_height
56
54
  @locate = Point.new(0, 0)
57
55
 
58
56
  @base = params[:size] || Size.new(20, 8)
59
- @size = Size.new(@font.size * @base[0] +
57
+ @size = Size.new((@font.size + @font.hspace) * @base[0] - @font.hspace +
60
58
  (@font.use_shadow ? @font.shadow_margin[0] : 0),
61
59
  @font.line_height *
62
60
  @base[1] - @font.vspace)
@@ -67,15 +65,29 @@ module Miyako
67
65
 
68
66
  @textarea = Sprite.new({:size => @size, :type => :ac, :is_fill => true})
69
67
 
68
+ @default_wait_cursor_position = lambda{|wcursor, tbox| wcursor.center.outside_bottom}
69
+ @default_select_cursor_position = lambda{|scursor, tbox| scursor.outside_left.middle}
70
+
70
71
  @wait_cursor = params[:wait_cursor] || params[:wc] || nil
72
+ @wait_cursor_position = @default_wait_cursor_position
71
73
  @select_cursor = params[:select_cursor] || params[:sc] || nil
74
+ @select_cursor_position = @default_select_cursor_position
75
+
76
+ @on_pause = lambda{}
72
77
 
78
+ @on_release = lambda{}
79
+
80
+ @on_draw = lambda{}
81
+
73
82
  @command_page_size = params[:page_size] || @base[1]
74
83
 
75
84
  @choices = Choices.new
76
- @now_choice = nil
85
+ @choices.snap(self)
86
+ @choices.left.top
77
87
 
78
- @pause_type = :bottom
88
+ @now_choice = nil
89
+ @pre_attach = false
90
+
79
91
  @waiting = false
80
92
  @select_type = :left
81
93
  @selecting = false
@@ -83,17 +95,25 @@ module Miyako
83
95
  @textarea.snap(self)
84
96
  @textarea.centering
85
97
 
86
- @@windows.push(self)
87
-
88
- @move_list = [[lambda{ },
89
- lambda{ @choices.right },
90
- lambda{ @choices.left }],
91
- [lambda{ @choices.down },
92
- lambda{ },
93
- lambda{ }],
94
- [lambda{ @choices.up },
95
- lambda{ },
96
- lambda{ }]]
98
+ @fiber = nil
99
+
100
+ if @wait_cursor
101
+ @wait_cursor.snap(self)
102
+ @default_wait_cursor_position.call(@wait_cursor, self)
103
+ end
104
+ @select_cursor.snap(self) if @select_cursor
105
+
106
+ @move_list = [
107
+ [lambda{ },
108
+ lambda{ @choices.right_choice },
109
+ lambda{ @choices.left_choice }],
110
+ [lambda{ @choices.down_choice },
111
+ lambda{ },
112
+ lambda{ }],
113
+ [lambda{ @choices.up_choice },
114
+ lambda{ },
115
+ lambda{ }]
116
+ ]
97
117
 
98
118
  end
99
119
 
@@ -104,21 +124,82 @@ module Miyako
104
124
  end
105
125
 
106
126
  #===一列に表示可能な文字数を取得する
107
- #返却される値は全角文字の数だが、半角文字も全角文字1文字と計算されるので注意
127
+ # 返却される値は全角文字の数だが、半角文字も全角文字1文字と計算されるので注意
108
128
  #返却値:: 表示可能な文字数
109
129
  def columns
110
130
  return @base.w
111
131
  end
112
132
 
113
133
  #===一列に表示可能な文字数と行数を取得する
114
- #文字数はcolumns、行数はrowsの値と同一
115
- #Size構造体のインスタンスとして取得
134
+ # 文字数はcolumns、行数はrowsの値と同一
135
+ # Size構造体のインスタンスとして取得
116
136
  #返却値:: 表示可能な文字数と行数
117
137
  def text_size
118
138
  return Size.new(@base.w, @base.h)
119
139
  end
120
140
 
121
- def update #:nodoc:
141
+ #===並行なブロック処理を開始する
142
+ # ブロックをFiberに渡して、並行実行できるようにして、Fiberを開始する
143
+ # ブロックには引数を必ず一つ付けること。引数には自分自身と、
144
+ #executeメソッドの引数リスト(配列化されて渡ってくる)が渡ってくる。
145
+ # 渡したブロックは、現在の処理と切り替えて実行することになる
146
+ # 現在の処理からブロック処理へ切り替えるときは、TextBox#updateメソッドを呼び出す
147
+ # ブロック処理から現在の処理に戻るには、ブロックから抜け出すか、
148
+ #draw_text・command・pause・clear・cr・spaceのどれかのメソッドを呼び出す。
149
+ #_params_:: Fiberに渡す引数リスト。Fiberへは配列として渡される
150
+ def execute(*params, &block)
151
+ raise MiyakoError, "This method needs a block!" unless block
152
+ raise MiyakoError, "This method needs a block with one parameter!" unless block.arity == 2
153
+ @fiber = Fiber.new(&block)
154
+ @fiber.resume(self, params)
155
+ end
156
+
157
+ #===並行ブロック処理が実行中かどうかを問い合わせる
158
+ #返却値:: Fiberが評価中ならば、trueを返す
159
+ def execute?
160
+ return @fiber != nil
161
+ end
162
+
163
+ #===並行ブロック処理を更新する
164
+ # 内部でFiberが評価中ならば、Fiberに処理を移す
165
+ #返却値:: 自分自身を返す
166
+ def update
167
+ begin
168
+ @fiber.resume if @fiber
169
+ rescue FiberError
170
+ @fiber = nil
171
+ end
172
+ return self
173
+ end
174
+
175
+ #===テキストボックスのアニメーションを開始する
176
+ #返却値:: 自分自身を返す
177
+ def start
178
+ @textarea.start
179
+ @wait_cursor.start if @wait_cursor
180
+ @choices.start
181
+ @select_cursor.start if @select_cursor
182
+ return self
183
+ end
184
+
185
+ #===テキストボックスのアニメーションを停止する
186
+ #返却値:: 自分自身を返す
187
+ def stop
188
+ @textarea.stop
189
+ @wait_cursor.stop if @wait_cursor
190
+ @choices.stop
191
+ @select_cursor.stop if @select_cursor
192
+ return self
193
+ end
194
+
195
+ #===テキストボックスのアニメーションを先頭に戻す
196
+ #返却値:: 自分自身を返す
197
+ def reset
198
+ @textarea.reset
199
+ @wait_cursor.reset if @wait_cursor
200
+ @choices.reset
201
+ @select_cursor.reset if @select_cursor
202
+ return self
122
203
  end
123
204
 
124
205
  #===テキストボックスの表示を更新する
@@ -136,14 +217,25 @@ module Miyako
136
217
 
137
218
  #===スプライトに変換した画像を表示する
138
219
  #すべてのパーツを貼り付けた、1枚のスプライトを返す
220
+ #引数1個のブロックを渡せば、スプライトに補正をかけることが出来る
139
221
  #返却値:: 描画したスプライト
140
222
  def to_sprite
141
223
  rect = self.broad_rect
142
224
  sprite = Sprite.new(:size=>rect.to_a[2,2], :type=>:ac)
225
+ Drawing.fill(sprite, [0,0,0])
226
+ Bitmap.ck_to_ac!(sprite, [0,0,0])
143
227
  self.render_to(sprite){|sunit, dunit| sunit.x -= rect.x; sunit.y -= rect.y }
228
+ yield sprite if block_given?
144
229
  return sprite
145
230
  end
146
231
 
232
+ #===SpriteUnit構造体を生成する
233
+ #いったんSpriteインスタンスを作成し、それをもとにSpriteUnit構造体を生成する。
234
+ #返却値:: 生成したSpriteUnit構造体
235
+ def to_unit
236
+ return self.to_sprite.to_unit
237
+ end
238
+
147
239
  #===現在の画面の最大の大きさを矩形で取得する
148
240
  #テキストボックスの状態により、取得できる矩形の大きさが変わる
149
241
  #返却値:: 生成された矩形(Rect構造体のインスタンス)
@@ -169,8 +261,10 @@ module Miyako
169
261
  #現在のテキストエリア・カーソルを、現在の状態で描画する
170
262
  #ブロック付きで呼び出し可能(レシーバに対応したSpriteUnit構造体が引数として得られるので、補正をかけることが出来る。
171
263
  #ブロックの引数は、|インスタンスのSpriteUnit, 画面のSpriteUnit|となる。
264
+ #visibleメソッドの値がfalseのときは描画されない。
172
265
  #返却値:: 自分自身を返す
173
266
  def render(&block)
267
+ return unless @visible
174
268
  @textarea.render(&block)
175
269
  @wait_cursor.render(&block) if (@wait_cursor && @waiting)
176
270
  if @selecting
@@ -184,8 +278,10 @@ module Miyako
184
278
  #現在のテキストエリア・カーソルを、現在の状態で描画する
185
279
  #ブロック付きで呼び出し可能(レシーバに対応したSpriteUnit構造体が引数として得られるので、補正をかけることが出来る。
186
280
  #ブロックの引数は、|インスタンスのSpriteUnit, 転送先のSpriteUnit|となる。
281
+ #visibleメソッドの値がfalseのときは描画されない。
187
282
  #返却値:: 自分自身を返す
188
283
  def render_to(dst, &block)
284
+ return unless @visible
189
285
  @textarea.render_to(dst, &block)
190
286
  @wait_cursor.render(dst, &block) if (@wait_cursor && @waiting)
191
287
  if @selecting
@@ -211,9 +307,9 @@ module Miyako
211
307
  #===指定した高さで描画する際のマージンを求める
212
308
  #現在のフォントの設定で指定の文字列を描画したとき、予想される描画サイズを返す。実際に描画は行われない。
213
309
  #第1引数に渡す"align"は、以下の3種類のシンボルのどれかを渡す
214
- #:top:: 上側に描画(マージンはゼロ)
215
- #:middle:: 中間に描画
216
- #:bottom:: 下部に描画
310
+ #_:top_:: 上側に描画(マージンはゼロ)
311
+ #_:middle_:: 中間に描画
312
+ #_:bottom_:: 下部に描画
217
313
  #
218
314
  #_align_:: 描画位置
219
315
  #_height_:: 描画する高さ(デフォルトは、描画した最大の高さ)
@@ -227,7 +323,17 @@ module Miyako
227
323
  #返却値:: 自分自身を返す
228
324
  def color_during(color)
229
325
  raise MiyakoError, "not given block!" unless block_given?
230
- @font.color_during(color){ yield }
326
+ @font.color_during(Color.to_rgb(color)){ yield }
327
+ return self
328
+ end
329
+
330
+ #===フォントサイズを変更する
331
+ #行中の最大フォントサイズが更新されるので、見栄えの良い表示のためにこちらを使用することをお薦めします
332
+ #_size_:: 変更するフォントサイズ
333
+ #返却値:: 自分自身を返す
334
+ def font_size=(size)
335
+ @font.size = size
336
+ @max_height = @font.line_height if @max_height < @font.line_height
231
337
  return self
232
338
  end
233
339
 
@@ -236,7 +342,10 @@ module Miyako
236
342
  #返却値:: 自分自身を返す
237
343
  def font_size_during(size)
238
344
  raise MiyakoError, "not given block!" unless block_given?
239
- @font.size_during(size){ yield }
345
+ @font.size_during(size){
346
+ @max_height = @font.line_height if @max_height < @font.line_height
347
+ yield
348
+ }
240
349
  return self
241
350
  end
242
351
 
@@ -272,147 +381,260 @@ module Miyako
272
381
  def draw_text(text)
273
382
  @locate.x = @font.draw_text(@textarea, text, @locate.x, @locate.y + @margin)
274
383
  @max_height = [@max_height, @font.line_height].max
384
+ @on_draw.call
385
+ Fiber.yield if @fiber
386
+ return self
387
+ end
388
+
389
+ #===文字描画時に行う処理を記述したブロックを登録する
390
+ #処理を行うブロックはオブジェクトとして渡す。
391
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
392
+ #_event_:: 文字描画時処理するブロック
393
+ #返却値:: 自分自身を返す
394
+ def on_draw=(event)
395
+ tdraw = @on_draw
396
+ @on_draw = event
397
+ if block_given?
398
+ yield
399
+ @on_draw = tdraw
400
+ end
275
401
  return self
276
402
  end
277
403
 
278
- #===あとで書く
279
- #_choices_:: あとで書く
280
- #返却値:: あとで書く
404
+ #===選択肢の集合をTextBoxインスタンスに見合う形のChoicesクラスインスタンスの配列に変換する
405
+ #ブロック(引数一つのブロックのみ有効)を渡したときは、ブロックを評価して変換したChoicesクラスの配列を作成する。
406
+ #引数は、以下の構成を持つ配列のリスト。
407
+ #[非選択時スプライト(文字列可),選択時スプライト(文字列・nil可),選択結果インスタンス]
408
+ # 非選択時スプライト:自身が選択されていない時に表示するスプライト。文字列の時は、Shapeクラスなどでスプライトに変更する
409
+ # 選択時スプライト:自身が選択されている時に表示するスプライト。文字列の時は、Shapeクラスなどでスプライトに変更する
410
+ # (そのとき、文字色が赤色になる)。
411
+ # nilを渡すと、非選択時スプライトが使われる
412
+ # 注:スプライトは、画面にスナップしておくこと
413
+ # 選択結果インスタンス:コマンドが決定したときに、resultメソッドの値として渡すインスタンス。
414
+ # デフォルト処理の選択肢の位置は、画面左上から下へ順番に設定される
415
+ # 注:ブロックを渡すとき、選択肢の位置計算が、全選択肢の左上位置が[0,0]とする相対座標になっていること
416
+ #_choices_:: 選択肢の集合(上記参照)
417
+ #返却値:: Choicesクラスのインスタンスの配列
281
418
  def create_choices_chain(choices)
419
+ if block_given?
420
+ return yield(choices)
421
+ end
282
422
  choices = choices.map{|v|
423
+ org_font_color = @font.color
283
424
  @font.color = Color[:white]
284
- body = v[0].to_sprite(@font)
425
+ body = v[0].method(:to_sprite).arity == 0 ? v[0].to_sprite : v[0].to_sprite(@font)
285
426
  @font.color = Color[:red]
286
- body_selected = v[1] ? v[1].to_sprite(@font) : body
427
+ body_selected = v[1] ? (v[1].method(:to_sprite).arity == 0 ? v[1].to_sprite : v[1].to_sprite(@font)) : body
428
+ @font.color = org_font_color
287
429
  choice = Choices.create_choice(body, body_selected)
288
430
  choice.result = v[2]
431
+ choice.end_select_proc = v[3]
289
432
  next choice
290
433
  }
291
- if block_given?
292
- return yield(choices)
293
- end
294
- list = []
295
- pos = 0
296
- choices2 = []
297
- while cpart = choices[pos, @command_page_size]
298
- break if cpart.length == 0
299
- choices2.push(cpart)
300
- pos += @command_page_size
301
- end
434
+ choices2 = choices.each_slice(@command_page_size).to_a
302
435
  choices2.each_with_index{|cc, x|
303
436
  len = cc.length
304
- right = choices2[(x + 1) % choices2.length]
437
+ right = choices2[x + 1] || choices2[0]
305
438
  left = choices2[x - 1]
306
- yp = @textarea.y + @locate.y
439
+ yp = 0
307
440
  cc.each_with_index{|v, y|
308
- v.down = cc[(y + 1) % len]
441
+ v.down = cc[y + 1] || cc[0]
309
442
  v.up = cc[y - 1]
310
- v.right = (y >= right.length ? right.last : right[y])
311
- v.left = (y >= left.length ? left.last : left[y])
312
- v.body.move_to(@textarea.x +
313
- @locate.x +
314
- @select_cursor.ow *
315
- @@select_margin[@select_type],
316
- yp)
317
- if v.body_selected
318
- v.body_selected.move_to(@textarea.x +
319
- @locate.x +
320
- @select_cursor.ow *
321
- @@select_margin[@select_type],
322
- yp)
323
- end
324
- yp += v.body.oh
443
+ v.right = right[y] || right.last
444
+ v.left = left[y] || left.last
445
+ v.body.move_to(0, yp)
446
+ v.body_selected.move_to(0, yp)
447
+ yp += [v.body.broad_rect.h, v.body_selected.broad_rect.h].max
325
448
  }
326
- list.push(cc)
327
449
  }
328
- return list
450
+ return choices2
329
451
  end
330
452
 
331
453
  #===コマンド選択を設定する
332
454
  #コマンド選択処理に移る(self#selecting?メソッドがtrueになる)
333
- #引数choicesは配列だが、要素は、[コマンド文字列・画像,選択時コマンド文字列・画像,選択した結果(オブジェクト)]
334
- #として構成されている
335
- #body_selectedをnilにした場合は、bodyと同一となる
336
- #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
337
- #_choices_:: 選択肢の配列
455
+ #
456
+ # 引数choicesに配列を渡すとき、各要素の構成は以下のようになる
457
+ # [コマンド文字列・画像,選択時コマンド文字列・画像,選択した結果(オブジェクト)]
458
+ #
459
+ # 引数choicesにChoicesクラスインスタンスを渡したとき、内部で、インスタンスを複写したものに置き換える
460
+ #
461
+ # このメソッドが呼び出された時、選択肢はlocateメソッドの値となる位置に移動する
462
+ # 引数dx,dyともにnil以外の数値を渡すと、上記の位置から更に移動する(位置が補正される)
463
+ # body_selectedをnilにした場合は、bodyと同一となる
464
+ # body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
465
+ #_choices_:: 選択肢の配列、もしくはChoicesクラスのインスタンス
466
+ #_dx_:: 選択肢を表示するx座標の移動量。デフォルトはnil(移動しない)
467
+ #_dy_:: 選択肢を表示するy座標の移動量。デフォルトはnil(移動しない)
338
468
  #返却値:: 自分自身を返す
339
- def command(choices)
340
- @choices.clear
341
- choices.each{|cc| @choices.create_choices(cc) }
469
+ def command(choices, dx = nil, dy = nil)
470
+ if choices.methods.include?(:start_choice)
471
+ @choices = choices.dup
472
+ @choices.snap(self)
473
+ else
474
+ @choices.clear
475
+ choices.each{|cc| @choices.create_choices(cc) }
476
+ end
477
+ @choices.left{|b| @locate.x}.top{|b| @locate.y}
478
+ @choices.move(dx, dy) if (dx != nil && dy != nil)
342
479
  start_command
480
+ Fiber.yield if @fiber
343
481
  return self
344
482
  end
345
483
 
346
484
  #===コマンド選択を開始する
347
- #但し、commandメソッドを呼び出したときは自動的に呼ばれるので注意
485
+ #但し、commandメソッドを呼び出したときは自動的に呼ばれる
348
486
  #返却値:: 自分自身を返す
349
487
  def start_command
350
488
  raise MiyakoError, "don't set Choice!" if @choices.length == 0
351
489
  @choices.start_choice
352
490
  if @select_cursor
353
- @select_cursor.move_to(@choices.body.x -
354
- @select_cursor.ow *
355
- @@select_margin[@select_type],
356
- @choices.body.y +
357
- (@choices.body.oh - @select_cursor.oh) / 2)
358
- @select_cursor.start
491
+ @select_cursor.snap(@choices.body)
492
+ @select_cursor_position.call(@select_cursor, @choices.body)
359
493
  end
360
- @choices.start
361
494
  @selecting = true
362
495
  return self
363
496
  end
364
497
 
365
498
  #===コマンド選択を終了する
499
+ # 選択した選択肢(Choice構造体)にend_select_procブロックが設定されていれば自動的に評価される
366
500
  #返却値:: 自分自身を返す
367
501
  def finish_command
368
- @choices.stop
369
- @select_cursor.stop
502
+ @choices.end_choice(self)
503
+ @choices.left.top
370
504
  @selecting = false
371
505
  return self
372
506
  end
373
507
 
374
- #===あとで書く
375
- #_dx_:: あとで書く
376
- #_dy_:: あとで書く
377
- #返却値:: あとで書く
508
+ #===選択肢・選択カーソルを移動させる
509
+ #但し、非選択状態だったときは、選択状態に戻るだけ
510
+ #(そのときの選択肢は、最後に選択した選択肢を指定する)
511
+ #_dx_:: 移動量(x軸方向)。-1,0,1の3種類
512
+ #_dy_:: 移動量(y軸方向)。-1,0,1の3種類
513
+ #返却値:: 自分自身を返す
378
514
  def move_cursor(dx, dy)
515
+ unless @choices.any_select?
516
+ @choices.start_choice(nil) # 選択状態を元に戻す
517
+ return self
518
+ end
379
519
  @move_list[dy][dx].call
380
520
  if @select_cursor
381
- @select_cursor.move_to(@choices.body.x -
382
- @select_cursor.ow *
383
- @@select_margin[@select_type],
384
- @choices.body.y +
385
- (@choices.body.oh - @select_cursor.oh) / 2)
521
+ @select_cursor.snap(@choices.body)
522
+ @select_cursor_position.call(@select_cursor, @choices.body)
523
+ end
524
+ return self
525
+ end
526
+
527
+ #===マウスカーソルの位置とコマンドを照合する
528
+ #選択肢・選択カーソルを、マウスカーソルが当たっているコマンドに移動させる
529
+ #どのコマンドにも当たっていない場合は、すべてのコマンドは非選択状態になる
530
+ #_x_:: マウスカーソルの位置(x軸方向)
531
+ #_y_:: マウスカーソルの位置(y軸方向)
532
+ #返却値:: 自分自身を返す
533
+ def attach_cursor(x, y)
534
+ attach = @choices.attach(x, y)
535
+ if attach
536
+ if @select_cursor
537
+ @select_cursor.snap(@choices.body)
538
+ @select_cursor_position.call(@select_cursor, @choices.body)
539
+ end
540
+ else
541
+ @choices.non_select if @pre_attach
386
542
  end
543
+ @pre_attach = attach
387
544
  return self
388
545
  end
389
546
 
390
- #===あとで書く
391
- #返却値:: あとで書く
392
- def update_layout_position
547
+ #===マウスカーソルの位置にコマンドがあるかどうかを問い合わせる
548
+ #マウスカーソルがどれかのコマンドの上にあるときはtrue、どれにも当たっていないときはfalseを返す
549
+ #_x_:: マウスカーソルの位置(x軸方向)
550
+ #_y_:: マウスカーソルの位置(y軸方向)
551
+ #返却値:: マウスカーソルがどれかのコマンドにあるときはtrueを返す
552
+ def attach_any_command?(x, y)
553
+ return @choices.attach(x, y)
554
+ end
555
+
556
+ def update_layout_position #:nodoc:
393
557
  @pos.move_to(*@layout.pos)
394
558
  end
395
559
 
560
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置を設定する
561
+ #ポーズカーソルの位置を、パラメータ二つ(カーソル本体・テキストボックス)を引数に取るブロックで実装する
562
+ #位置は、テキストエリアをsnapしていると想定して実装する
563
+ #デフォルトは、テキストエリアの中下に置かれる(center.bottom)
564
+ # (例)テキストボックスの中下(テキストエリアの外) -> {|wc, tbox| wc.center.outside_bottom }
565
+ #   テキストボックスの右下(テキストエリアの中) -> {|wc, tbox| wc.right.bottom }
566
+ #   テキストの最後尾 -> {|wc, tbox| wc.left{|b| tbox.locate.x }.top{|b| tbox.locate.y} }
567
+ # (テキストエリアの左上から右下へ現在の描画開始位置(tbox.locateメソッドで示した値)の距離移動した箇所)
568
+ #ブロックを渡していなかったり、ブロックの引数が2個でなければエラーを返す
569
+ #返却値:: 自分自身を返す
570
+ def set_wait_cursor_position(&proc)
571
+ raise MiyakoError, "Can't find block!" unless proc
572
+ raise MiyakoError, "This method must have two parameters!" unless proc.arity == 2
573
+ @wait_cursor_position = proc
574
+ @wait_cursor_position.call(@wait_cursor, self) if @wait_cursor
575
+ return self
576
+ end
577
+
578
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置をデフォルトに戻す
579
+ #デフォルトの位置は、テキストエリアの中下(center.bottom)に設定されている
580
+ #返却値:: 自分自身を返す
581
+ def reset_wait_cursor_position
582
+ @wait_cursor_position = @default_wait_cursor_position
583
+ @wait_cursor_position.call(@wait_cursor, self) if @wait_cursor
584
+ return self
585
+ end
586
+
587
+ #===コマンド選択時に表示するカーソルの位置を設定する
588
+ #カーソルの位置を、パラメータ二つ(カーソル本体・選択肢)を引数に取るブロックで実装する
589
+ #位置は、テキストエリアをsnapしていると想定して実装する
590
+ #デフォルトは、選択肢の左側に置かれる(outside_left.middle)
591
+ # (例)選択肢の右側 -> {|wc, choice| wc.outside_right.middle }
592
+ #   選択肢の真上 -> {|wc, choice| wc.centering }
593
+ #ブロックを渡していなかったり、ブロックの引数が2個でなければエラーを返す
594
+ #返却値:: 自分自身を返す
595
+ def set_select_cursor_position(&proc)
596
+ raise MiyakoError, "Can't find block!" unless proc
597
+ raise MiyakoError, "This method must have two parameters!" unless proc.arity == 2
598
+ @select_cursor_position = proc
599
+ @select_cursor_position.call(@select_cursor, @choices.body) if (@select_cursor && @choices.body)
600
+ return self
601
+ end
602
+
603
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置をデフォルトに戻す
604
+ #デフォルトの位置は、テキストエリアの中下(center.bottom)に設定されている
605
+ #返却値:: 自分自身を返す
606
+ def reset_select_cursor_position
607
+ @select_cursor_position = @default_select_cursor_position
608
+ @select_cursor_position.call(@select_cursor, @choices.body) if (@select_cursor && @choices.body)
609
+ return self
610
+ end
611
+
396
612
  #===入力待ち状態(ポーズ)にする
397
613
  #ポーズカーソルを表示する。pause?メソッドの結果がtrueになる
398
- #ポーズカーソルの位置は、pause_type=メソッドの結果に依る(デフォルトは:bottom)
614
+ #ポーズカーソルの位置は、set_wait_cursor_positionで設定したブロックが評価されて決定される
615
+ #(デフォルトはテキストエリアの中下
399
616
  #返却値:: 自分自身を返す
400
617
  def pause
401
618
  @waiting = true
402
619
  return self unless @wait_cursor
403
- case @pause_type
404
- when :bottom
405
- @wait_cursor.move_to(@textarea.x +
406
- (@textarea.w - @wait_cursor.ow) / 2,
407
- @textarea.y + @textarea.h - @wait_cursor.oh)
408
- when :out
409
- @wait_cursor.move_to(@textarea.x +
410
- (@textarea.w - @wait_cursor.ow) / 2,
411
- @textarea.y + @textarea.h)
412
- when :last
413
- @wait_cursor.move_to(@textarea.x + @locate.x, @textarea.y + @locate.y)
620
+ @wait_cursor_position.call(@wait_cursor, self)
621
+ @on_pause.call
622
+ Fiber.yield if @fiber
623
+ return self
624
+ end
625
+
626
+ #===ポーズ時に行う処理を記述したブロックを登録する
627
+ #処理を行うブロックはオブジェクトとして渡す。
628
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
629
+ #_event_:: ポーズ時処理するブロック
630
+ #返却値:: 自分自身を返す
631
+ def on_pause=(event)
632
+ tpause = @on_pause
633
+ @on_pause = event
634
+ if block_given?
635
+ yield
636
+ @on_pause = tpause
414
637
  end
415
- @wait_cursor.start
416
638
  return self
417
639
  end
418
640
 
@@ -421,7 +643,22 @@ module Miyako
421
643
  #返却値:: 自分自身を返す
422
644
  def release
423
645
  @waiting = false
424
- @wait_cursor.stop if @wait_cursor
646
+ @on_release.call
647
+ return self
648
+ end
649
+
650
+ #===ポーズ解除時に行う処理を記述したブロックを登録する
651
+ #処理を行うブロックはオブジェクトとして渡す。
652
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
653
+ #_event_:: ポーズ解除時処理するブロック
654
+ #返却値:: 自分自身を返す
655
+ def on_release=(event)
656
+ trelease = @on_release
657
+ @on_release = event
658
+ if block_given?
659
+ yield
660
+ @on_release = trelease
661
+ end
425
662
  return self
426
663
  end
427
664
 
@@ -431,24 +668,26 @@ module Miyako
431
668
  return @waiting
432
669
  end
433
670
 
434
- #===あとで書く
435
- #返却値:: あとで書く
671
+ #===コマンド選択中かどうかを確認する
672
+ #返却値:: 選択中の時はtrueを返す
436
673
  def selecting?
437
674
  return @selecting
438
675
  end
439
676
 
440
- #===あとで書く
441
- #返却値:: あとで書く
677
+ #===選択結果を取得する
678
+ #返却値:: コマンドの選択結果(選択中のnilを返す)
442
679
  def result
443
680
  return @choices.result
444
681
  end
445
682
 
446
- #===あとで書く
447
- #返却値:: あとで書く
683
+ #===テキストエリアに描画している文字を消去する
684
+ #透明色で消去したあと、描画開始位置を左上(0,0)に移動する
685
+ #返却値:: 自分自身を返す
448
686
  def clear
449
687
  @textarea.bitmap.fillRect(0, 0, @size[0], @size[1], [0, 0, 0, 0])
450
688
  @locate = Point.new(0, 0)
451
689
  @max_height = @font.line_height
690
+ Fiber.yield if @fiber
452
691
  return self
453
692
  end
454
693
 
@@ -461,6 +700,7 @@ module Miyako
461
700
  @locate.x = 0
462
701
  @locate.y += height
463
702
  @max_height = @font.line_height
703
+ Fiber.yield if @fiber
464
704
  return self
465
705
  end
466
706
 
@@ -470,25 +710,14 @@ module Miyako
470
710
  #返却値:: 自分自身を返す
471
711
  def space(length)
472
712
  @locate.x += length
713
+ Fiber.yield if @fiber
473
714
  return self
474
715
  end
475
716
 
476
- #===ブロックで指定した描画処理を非同期に行う
477
- #ブロックを渡すと、描画処理を非同期に行う。
478
- #更新処理はスレッドを使うが、現在、終了を確認する方法が無いため、扱いに注意すること
479
- #(確実にスレッド処理が終わるコードになっているか確認すること)
480
- #返却値:: 自分自身を返す
481
- def exec
482
- Thread.new(Proc.new){|proc| proc.call } if block_given?
483
- return self
484
- end
485
-
486
- #===あとで書く
487
- #返却値:: あとで書く
717
+ #===情報を解放する
488
718
  def dispose
489
719
  @textarea.dispose
490
720
  @textarea = nil
491
- @@windows.delete(self)
492
721
  end
493
722
 
494
723
  def_delegators(:@pos, :x, :y)