ruby-miyako-mswin32 2.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 (148) hide show
  1. data/README +1115 -0
  2. data/img/cursor.png +0 -0
  3. data/img/cursors.png +0 -0
  4. data/img/dice.png +0 -0
  5. data/img/wait_cursor.png +0 -0
  6. data/img/win_base.png +0 -0
  7. data/img/window.png +0 -0
  8. data/install_miyako.rb +87 -0
  9. data/lib/Miyako/API/audio.rb +584 -0
  10. data/lib/Miyako/API/basic_data.rb +1026 -0
  11. data/lib/Miyako/API/bitmap.rb +534 -0
  12. data/lib/Miyako/API/choices.rb +481 -0
  13. data/lib/Miyako/API/collision.rb +638 -0
  14. data/lib/Miyako/API/diagram.rb +586 -0
  15. data/lib/Miyako/API/drawing.rb +151 -0
  16. data/lib/Miyako/API/exceptions.rb +105 -0
  17. data/lib/Miyako/API/fixedmap.rb +462 -0
  18. data/lib/Miyako/API/font.rb +430 -0
  19. data/lib/Miyako/API/input.rb +456 -0
  20. data/lib/Miyako/API/layout.rb +644 -0
  21. data/lib/Miyako/API/map.rb +583 -0
  22. data/lib/Miyako/API/map_event.rb +222 -0
  23. data/lib/Miyako/API/modules.rb +357 -0
  24. data/lib/Miyako/API/movie.rb +166 -0
  25. data/lib/Miyako/API/parts.rb +188 -0
  26. data/lib/Miyako/API/plane.rb +205 -0
  27. data/lib/Miyako/API/screen.rb +341 -0
  28. data/lib/Miyako/API/shape.rb +443 -0
  29. data/lib/Miyako/API/sprite.rb +773 -0
  30. data/lib/Miyako/API/sprite_animation.rb +494 -0
  31. data/lib/Miyako/API/sprite_list.rb +1135 -0
  32. data/lib/Miyako/API/spriteunit.rb +168 -0
  33. data/lib/Miyako/API/story.rb +350 -0
  34. data/lib/Miyako/API/textbox.rb +773 -0
  35. data/lib/Miyako/API/utility.rb +419 -0
  36. data/lib/Miyako/API/viewport.rb +190 -0
  37. data/lib/Miyako/API/yuki.rb +1180 -0
  38. data/lib/Miyako/EXT/miyako_cairo.rb +62 -0
  39. data/lib/Miyako/EXT/raster_scroll.rb +138 -0
  40. data/lib/Miyako/EXT/slides.rb +157 -0
  41. data/lib/Miyako/miyako.rb +201 -0
  42. data/lib/Miyako/miyako_no_katana.so +0 -0
  43. data/lib/Miyako/miyako_require_only.rb +35 -0
  44. data/logo/EGSR_logo.png +0 -0
  45. data/logo/EGSR_logo_bg.png +0 -0
  46. data/logo/EGSR_logo_fg.png +0 -0
  47. data/logo/EGSR_title_banner.png +0 -0
  48. data/logo/EGSR_title_logo.png +0 -0
  49. data/logo/miyako.png +0 -0
  50. data/logo/miyako_banner.png +0 -0
  51. data/logo/space.png +0 -0
  52. data/sample/Animation1/m1ku.rb +68 -0
  53. data/sample/Animation1/m1ku_arm_0.png +0 -0
  54. data/sample/Animation1/m1ku_arm_1.png +0 -0
  55. data/sample/Animation1/m1ku_arm_2.png +0 -0
  56. data/sample/Animation1/m1ku_arm_3.png +0 -0
  57. data/sample/Animation1/m1ku_back.jpg +0 -0
  58. data/sample/Animation1/m1ku_body.png +0 -0
  59. data/sample/Animation1/m1ku_eye_0.png +0 -0
  60. data/sample/Animation1/m1ku_eye_1.png +0 -0
  61. data/sample/Animation1/m1ku_eye_2.png +0 -0
  62. data/sample/Animation1/m1ku_eye_3.png +0 -0
  63. data/sample/Animation1/m1ku_hair_front.png +0 -0
  64. data/sample/Animation1/m1ku_hair_rear.png +0 -0
  65. data/sample/Animation1/readme.txt +72 -0
  66. data/sample/Animation2/lex.rb +96 -0
  67. data/sample/Animation2/lex_back.png +0 -0
  68. data/sample/Animation2/lex_body.png +0 -0
  69. data/sample/Animation2/lex_roadroller.png +0 -0
  70. data/sample/Animation2/lex_wheel_0.png +0 -0
  71. data/sample/Animation2/lex_wheel_1.png +0 -0
  72. data/sample/Animation2/lex_wheel_2.png +0 -0
  73. data/sample/Animation2/readme.txt +72 -0
  74. data/sample/Animation2/song_title.png +0 -0
  75. data/sample/Diagram_sample/back.png +0 -0
  76. data/sample/Diagram_sample/chr01.png +0 -0
  77. data/sample/Diagram_sample/chr02.png +0 -0
  78. data/sample/Diagram_sample/cursor.png +0 -0
  79. data/sample/Diagram_sample/diagram_sample_yuki2.rb +329 -0
  80. data/sample/Diagram_sample/readme.txt +90 -0
  81. data/sample/Diagram_sample/wait_cursor.png +0 -0
  82. data/sample/Room3/blue.rb +297 -0
  83. data/sample/Room3/ending.rb +180 -0
  84. data/sample/Room3/green.rb +220 -0
  85. data/sample/Room3/image/akamatsu.png +0 -0
  86. data/sample/Room3/image/aoyama.png +0 -0
  87. data/sample/Room3/image/congra.png +0 -0
  88. data/sample/Room3/image/congratulation.png +0 -0
  89. data/sample/Room3/image/congratulation_bg.png +0 -0
  90. data/sample/Room3/image/cursor.png +0 -0
  91. data/sample/Room3/image/midori.png +0 -0
  92. data/sample/Room3/image/mittsu_no_oheya.png +0 -0
  93. data/sample/Room3/image/mittsu_no_oheya_logo.png +0 -0
  94. data/sample/Room3/image/room_blue.png +0 -0
  95. data/sample/Room3/image/room_green.png +0 -0
  96. data/sample/Room3/image/room_red.png +0 -0
  97. data/sample/Room3/image/start.png +0 -0
  98. data/sample/Room3/image/three_doors.png +0 -0
  99. data/sample/Room3/image/wait_cursor.png +0 -0
  100. data/sample/Room3/main.rb +120 -0
  101. data/sample/Room3/main_component.rb +59 -0
  102. data/sample/Room3/readme.txt +76 -0
  103. data/sample/Room3/red.rb +227 -0
  104. data/sample/Room3/room3.rb +25 -0
  105. data/sample/Room3/title.rb +184 -0
  106. data/sample/ball_action_sample.rb +204 -0
  107. data/sample/blit_rop.rb +70 -0
  108. data/sample/cairo_sample.rb +25 -0
  109. data/sample/circle_collision_test.rb +66 -0
  110. data/sample/collision_test.rb +33 -0
  111. data/sample/collision_test2.rb +108 -0
  112. data/sample/fixed_map_test/cursor.png +0 -0
  113. data/sample/fixed_map_test/fixed_map_sample.rb +140 -0
  114. data/sample/fixed_map_test/map.csv +19 -0
  115. data/sample/fixed_map_test/map_01.png +0 -0
  116. data/sample/fixed_map_test/mapchip.csv +23 -0
  117. data/sample/fixed_map_test/monster.png +0 -0
  118. data/sample/fixed_map_test/readme.txt +72 -0
  119. data/sample/map_test/chara.rb +58 -0
  120. data/sample/map_test/chr1.png +0 -0
  121. data/sample/map_test/cursor.png +0 -0
  122. data/sample/map_test/main_parts.rb +69 -0
  123. data/sample/map_test/main_scene.rb +153 -0
  124. data/sample/map_test/map.png +0 -0
  125. data/sample/map_test/map2.png +0 -0
  126. data/sample/map_test/map_layer.csv +127 -0
  127. data/sample/map_test/map_manager.rb +75 -0
  128. data/sample/map_test/map_test.rb +23 -0
  129. data/sample/map_test/mapchip.csv +21 -0
  130. data/sample/map_test/oasis.rb +71 -0
  131. data/sample/map_test/readme.txt +89 -0
  132. data/sample/map_test/route.rb +157 -0
  133. data/sample/map_test/sea.png +0 -0
  134. data/sample/map_test/town.rb +74 -0
  135. data/sample/map_test/wait_cursor.png +0 -0
  136. data/sample/map_test/window.png +0 -0
  137. data/sample/polygon_test.rb +35 -0
  138. data/sample/rasterscroll.rb +25 -0
  139. data/sample/takahashi.rb +42 -0
  140. data/sample/text.png +0 -0
  141. data/sample/textbox_sample.rb +190 -0
  142. data/sample/transform.rb +54 -0
  143. data/sample/utility_test.rb +73 -0
  144. data/sample/utility_test2.rb +61 -0
  145. data/sample/utility_test3.rb +64 -0
  146. data/sample/utility_test4.rb +73 -0
  147. data/uninstall_miyako.rb +19 -0
  148. metadata +199 -0
@@ -0,0 +1,773 @@
1
+ # -*- encoding: utf-8 -*-
2
+ =begin
3
+ --
4
+ Miyako v2.1
5
+ Copyright (C) 2007-2008 Cyross Makoto
6
+
7
+ This library is free software; you can redistribute it and/or
8
+ modify it under the terms of the GNU Lesser General Public
9
+ License as published by the Free Software Foundation; either
10
+ version 2.1 of the License, or (at your option) any later version.
11
+
12
+ This library is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with this library; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ ++
21
+ =end
22
+
23
+ module Miyako
24
+ #==テキストボックスを構成するクラス
25
+ #テキスト表示部、ウェイトカーソル、選択カーソルで構成される
26
+ class TextBox
27
+ include SpriteBase
28
+ include Animation
29
+ include Layout
30
+ extend Forwardable
31
+
32
+ attr_accessor :textarea
33
+ attr_accessor :select_type, :waiting, :selecting
34
+ attr_accessor :font, :margin
35
+ attr_reader :wait_cursor, :select_cursor, :choices
36
+ attr_reader :locate, :size, :max_height
37
+
38
+ #===インスタンスの作成
39
+ #テキストボックスを生成する。パラメータは以下の通り。
40
+ #(括弧内は省略形)
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)
46
+ #
47
+ #_params_:: 生成時のパラメータ(ハッシュ引数)
48
+ #返却値:: TextBoxクラスのインスタンス
49
+ def initialize(params = {})
50
+ init_layout
51
+ @visible = true
52
+ @font = params[:font] || Font.sans_serif
53
+ @max_height = @font.line_height
54
+ @locate = Point.new(0, 0)
55
+
56
+ @base = params[:size] || Size.new(20, 8)
57
+ @size = Size.new((@font.size + @font.hspace) * @base[0] - @font.hspace +
58
+ (@font.use_shadow ? @font.shadow_margin[0] : 0),
59
+ @font.line_height *
60
+ @base[1] - @font.vspace)
61
+ @pos = Point.new(0, 0)
62
+ set_layout_size(*@size)
63
+
64
+ @margin = 0
65
+
66
+ @textarea = Sprite.new({:size => @size, :type => :ac, :is_fill => true})
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
+
71
+ @wait_cursor = params[:wait_cursor] || params[:wc] || nil
72
+ @wait_cursor_position = @default_wait_cursor_position
73
+ @select_cursor = params[:select_cursor] || params[:sc] || nil
74
+ @select_cursor_position = @default_select_cursor_position
75
+
76
+ @on_pause = lambda{}
77
+
78
+ @on_release = lambda{}
79
+
80
+ @on_draw = lambda{}
81
+
82
+ @command_page_size = params[:page_size] || @base[1]
83
+
84
+ @choices = Choices.new
85
+ @choices.snap(self)
86
+ @choices.left!.top!
87
+
88
+ @now_choice = nil
89
+ @pre_attach = false
90
+
91
+ @waiting = false
92
+ @select_type = :left
93
+ @selecting = false
94
+
95
+ @textarea.snap(self)
96
+ @textarea.centering!
97
+
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
+ ]
117
+
118
+ end
119
+
120
+ #===複写時に呼び出されるメソッド
121
+ #複写と同時に、本インスタンスに対するスナップの関係を解消するが、
122
+ #内部で使用するスプライトとはスナップをやり直す
123
+ def initialize_copy(obj)
124
+ copy_layout
125
+ reset_snap
126
+
127
+ @locate = @locate.dup
128
+ @base = @base.dup
129
+ @size = @size.dup
130
+ @pos = @pos.dup
131
+
132
+ @default_wait_cursor_position = @default_wait_cursor_position.dup
133
+ @default_select_cursor_position = @default_select_cursor_position.dup
134
+
135
+ @wait_cursor = @wait_cursor.dup
136
+ @wait_cursor_position = @wait_cursor_position.dup
137
+ @select_cursor = @select_cursor.dup
138
+ @select_cursor_position = @select_cursor_position.dup
139
+
140
+ @on_pause = @on_pause.dup
141
+
142
+ @on_release = @on_release.dup
143
+
144
+ @on_draw = @on_draw.dup
145
+
146
+ @choices = @choices.dup
147
+ @choices.snap(self)
148
+ @choices.left!.top!
149
+
150
+ @waiting = false
151
+ @select_type = :left
152
+ @selecting = false
153
+
154
+ @textarea = @textarea.dup
155
+ @textarea.snap(self)
156
+ @textarea.centering!
157
+
158
+ if @wait_cursor
159
+ @wait_cursor.snap(self)
160
+ @default_wait_cursor_position.call(@wait_cursor, self)
161
+ end
162
+ @select_cursor.snap(self) if @select_cursor
163
+
164
+ @move_list = @move_list.dup
165
+ end
166
+
167
+ #===表示可能な文字行数を取得する
168
+ #返却値:: 表示可能な行数
169
+ def rows
170
+ return @base.h
171
+ end
172
+
173
+ #===一列に表示可能な文字数を取得する
174
+ # 返却される値は全角文字の数だが、半角文字も全角文字1文字と計算されるので注意
175
+ #返却値:: 表示可能な文字数
176
+ def columns
177
+ return @base.w
178
+ end
179
+
180
+ #===一列に表示可能な文字数と行数を取得する
181
+ # 文字数はcolumns、行数はrowsの値と同一
182
+ # Size構造体のインスタンスとして取得
183
+ #返却値:: 表示可能な文字数と行数
184
+ def text_size
185
+ return Size.new(@base.w, @base.h)
186
+ end
187
+
188
+ #===並行なブロック処理を開始する
189
+ # ブロックをFiberに渡して、並行実行できるようにして、Fiberを開始する
190
+ # ブロックには引数を必ず一つ付けること。引数には自分自身と、
191
+ #executeメソッドの引数リスト(配列化されて渡ってくる)が渡ってくる。
192
+ # 渡したブロックは、現在の処理と切り替えて実行することになる
193
+ # 現在の処理からブロック処理へ切り替えるときは、TextBox#updateメソッドを呼び出す
194
+ # ブロック処理から現在の処理に戻るには、ブロックから抜け出すか、
195
+ #draw_text・command・pause・clear・cr・spaceのどれかのメソッドを呼び出す。
196
+ #_params_:: Fiberに渡す引数リスト。Fiberへは配列として渡される
197
+ def execute(*params, &block)
198
+ raise MiyakoProcError, "This method needs a block!" unless block
199
+ raise MiyakoProcError, "This method needs a block with one parameter!" unless block.arity == 2
200
+ @fiber = Fiber.new(&block)
201
+ @fiber.resume(self, params)
202
+ end
203
+
204
+ #===並行ブロック処理が実行中かどうかを問い合わせる
205
+ #返却値:: Fiberが評価中ならば、trueを返す
206
+ def execute?
207
+ return @fiber != nil
208
+ end
209
+
210
+ #===並行ブロック処理を更新する
211
+ # 内部でFiberが評価中ならば、Fiberに処理を移す
212
+ #返却値:: 自分自身を返す
213
+ def update
214
+ begin
215
+ @fiber.resume if @fiber
216
+ rescue FiberError
217
+ @fiber = nil
218
+ end
219
+ return self
220
+ end
221
+
222
+ #===テキストボックスのアニメーションを開始する
223
+ #返却値:: 自分自身を返す
224
+ def start
225
+ @textarea.start
226
+ @wait_cursor.start if @wait_cursor
227
+ @choices.start
228
+ @select_cursor.start if @select_cursor
229
+ return self
230
+ end
231
+
232
+ #===テキストボックスのアニメーションを停止する
233
+ #返却値:: 自分自身を返す
234
+ def stop
235
+ @textarea.stop
236
+ @wait_cursor.stop if @wait_cursor
237
+ @choices.stop
238
+ @select_cursor.stop if @select_cursor
239
+ return self
240
+ end
241
+
242
+ #===テキストボックスのアニメーションを先頭に戻す
243
+ #返却値:: 自分自身を返す
244
+ def reset
245
+ @textarea.reset
246
+ @wait_cursor.reset if @wait_cursor
247
+ @choices.reset
248
+ @select_cursor.reset if @select_cursor
249
+ return self
250
+ end
251
+
252
+ #===テキストボックスの表示を更新する
253
+ #テキストボックス・選択カーソル・選択肢・ウェイトカーソルのアニメーションを更新する
254
+ #返却値:: どれか一つ変更があったときはtrueを返す。それ以外はfalseを返す
255
+ def update_animation
256
+ f = false
257
+ f |= @textarea.update_animation
258
+ f |= @wait_cursor.update_animation if (@wait_cursor && @waiting)
259
+ if @selecting
260
+ f |= @choices.update_animation.any?
261
+ f |= @select_cursor.update_animation if @select_cursor
262
+ end
263
+ return f
264
+ end
265
+
266
+ #===スプライトに変換した画像を表示する
267
+ #すべてのパーツを貼り付けた、1枚のスプライトを返す
268
+ #引数1個のブロックを渡せば、スプライトに補正をかけることが出来る
269
+ #返却値:: 描画したスプライト
270
+ def to_sprite
271
+ rect = self.broad_rect
272
+ sprite = Sprite.new(:size=>rect.to_a[2,2], :type=>:ac)
273
+ Drawing.fill(sprite, [0,0,0])
274
+ Bitmap.ck_to_ac!(sprite, [0,0,0])
275
+ self.render_to(sprite){|sunit, dunit| sunit.x -= rect.x; sunit.y -= rect.y }
276
+ yield sprite if block_given?
277
+ return sprite
278
+ end
279
+
280
+ #===SpriteUnit構造体を生成する
281
+ #いったんSpriteインスタンスを作成し、それをもとにSpriteUnit構造体を生成する。
282
+ #返却値:: 生成したSpriteUnit構造体
283
+ def to_unit
284
+ return self.to_sprite.to_unit
285
+ end
286
+
287
+ #===現在の画面の最大の大きさを矩形で取得する
288
+ #テキストボックスの状態により、取得できる矩形の大きさが変わる
289
+ #返却値:: 生成された矩形(Rect構造体のインスタンス)
290
+ def broad_rect
291
+ rect = self.rect.to_a
292
+ rect_list = []
293
+ rect_list << @wait_cursor.broad_rect if (@wait_cursor && @waiting)
294
+ if @selecting
295
+ rect_list << @choices.broad_rect
296
+ rect_list << @select_cursor.broad_rect if @select_cursor
297
+ end
298
+ return self.rect if rect_list.length == 0
299
+ rect_list = rect.zip(*rect_list)
300
+ # width -> right
301
+ rect_list[2] = rect_list[2].zip(rect_list[0]).map{|xw| xw[0] + xw[1]}
302
+ # height -> bottom
303
+ rect_list[3] = rect_list[3].zip(rect_list[1]).map{|xw| xw[0] + xw[1]}
304
+ x, y = rect_list[0].min, rect_list[1].min
305
+ return Rect.new(x, y, rect_list[2].max - x, rect_list[3].max - y)
306
+ end
307
+
308
+ #===画面に描画する
309
+ #現在のテキストエリア・カーソルを、現在の状態で描画する
310
+ #ブロック付きで呼び出し可能(レシーバに対応したSpriteUnit構造体が引数として得られるので、補正をかけることが出来る。
311
+ #ブロックの引数は、|インスタンスのSpriteUnit, 画面のSpriteUnit|となる。
312
+ #visibleメソッドの値がfalseのときは描画されない。
313
+ #返却値:: 自分自身を返す
314
+ def render(&block)
315
+ return unless @visible
316
+ @textarea.render(&block)
317
+ @wait_cursor.render(&block) if (@wait_cursor && @waiting)
318
+ if @selecting
319
+ @choices.render(&block)
320
+ @select_cursor.render(&block) if @select_cursor
321
+ end
322
+ return self
323
+ end
324
+
325
+ #===画面に描画する
326
+ #現在のテキストエリア・カーソルを、現在の状態で描画する
327
+ #ブロック付きで呼び出し可能(レシーバに対応したSpriteUnit構造体が引数として得られるので、補正をかけることが出来る。
328
+ #ブロックの引数は、|インスタンスのSpriteUnit, 転送先のSpriteUnit|となる。
329
+ #visibleメソッドの値がfalseのときは描画されない。
330
+ #返却値:: 自分自身を返す
331
+ def render_to(dst, &block)
332
+ return unless @visible
333
+ @textarea.render_to(dst, &block)
334
+ @wait_cursor.render(dst, &block) if (@wait_cursor && @waiting)
335
+ if @selecting
336
+ @choices.render(dst, &block)
337
+ @select_cursor.render(dst, &block) if @select_cursor
338
+ end
339
+ return self
340
+ end
341
+
342
+ #===文字の描画位置にマージンを設定する
343
+ #marginで指定したピクセルぶん、下に描画する
344
+ #ブロックを渡すと、ブロックを評価している間だけマージンが有効になる
345
+ #_margin_:: 設定するマージン
346
+ #返却値:: 自分自身を返す
347
+ def margin_during(margin)
348
+ raise MiyakoError, "not given block!" unless block_given?
349
+ omargin, @margin = @margin, margin
350
+ yield
351
+ @margin = omargin
352
+ return self
353
+ end
354
+
355
+ #===指定した高さで描画する際のマージンを求める
356
+ #現在のフォントの設定で指定の文字列を描画したとき、予想される描画サイズを返す。実際に描画は行われない。
357
+ #第1引数に渡す"align"は、以下の3種類のシンボルのどれかを渡す
358
+ #_:top_:: 上側に描画(マージンはゼロ)
359
+ #_:middle_:: 中間に描画
360
+ #_:bottom_:: 下部に描画
361
+ #
362
+ #_align_:: 描画位置
363
+ #_height_:: 描画する高さ(デフォルトは、描画した最大の高さ)
364
+ #返却値:: マージンの値
365
+ def margin_height(align, height = @max_height)
366
+ return @font.margin_height(align, height)
367
+ end
368
+
369
+ #===ブロックを評価している間、文字色を変更する
370
+ #_color_:: 変更する文字色([r,g,b]の3要素の配列(値:0~255))
371
+ #返却値:: 自分自身を返す
372
+ def color_during(color)
373
+ raise MiyakoProcError, "not given block!" unless block_given?
374
+ @font.color_during(Color.to_rgb(color)){ yield }
375
+ return self
376
+ end
377
+
378
+ #===フォントサイズを変更する
379
+ #行中の最大フォントサイズが更新されるので、見栄えの良い表示のためにこちらを使用することをお薦めします
380
+ #_size_:: 変更するフォントサイズ
381
+ #返却値:: 自分自身を返す
382
+ def font_size=(size)
383
+ @font.size = size
384
+ @max_height = @font.line_height if @max_height < @font.line_height
385
+ return self
386
+ end
387
+
388
+ #===ブロックを評価している間、フォントサイズを変更する
389
+ #_size_:: 変更するフォントサイズ
390
+ #返却値:: 自分自身を返す
391
+ def font_size_during(size)
392
+ raise MiyakoProcError, "not given block!" unless block_given?
393
+ @font.size_during(size){
394
+ @max_height = @font.line_height if @max_height < @font.line_height
395
+ yield
396
+ }
397
+ return self
398
+ end
399
+
400
+ #===ブロックを評価している間、太字に変更する
401
+ #文字が領域外にはみ出る場合があるので注意!
402
+ #返却値:: 自分自身を返す
403
+ def font_bold
404
+ raise MiyakoProcError, "not given block!" unless block_given?
405
+ @font.bold{ yield }
406
+ return self
407
+ end
408
+
409
+ #===ブロックを評価している間、斜体文字に変更する
410
+ #文字が領域外にはみ出る場合があるので注意!
411
+ #返却値:: 自分自身を返す
412
+ def font_italic
413
+ raise MiyakoProcError, "not given block!" unless block_given?
414
+ @font.italic{ yield }
415
+ return self
416
+ end
417
+
418
+ #===ブロックを評価している間、下線付き文字に変更する
419
+ #返却値:: 自分自身を返す
420
+ def font_under_line
421
+ raise MiyakoProcError, "not given block!" unless block_given?
422
+ @font.under_line{ yield }
423
+ return self
424
+ end
425
+
426
+ #===テキストエリアに文字を描画する
427
+ #_text_:: 描画する文字列
428
+ #返却値:: 自分自身を返す
429
+ def draw_text(text)
430
+ @locate.x = @font.draw_text(@textarea, text, @locate.x, @locate.y + @margin)
431
+ @max_height = [@max_height, @font.line_height].max
432
+ @on_draw.call
433
+ Fiber.yield if @fiber
434
+ return self
435
+ end
436
+
437
+ #===文字描画時に行う処理を記述したブロックを登録する
438
+ #処理を行うブロックはオブジェクトとして渡す。
439
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
440
+ #_event_:: 文字描画時処理するブロック
441
+ #返却値:: 自分自身を返す
442
+ def on_draw=(event)
443
+ tdraw = @on_draw
444
+ @on_draw = event
445
+ if block_given?
446
+ yield
447
+ @on_draw = tdraw
448
+ end
449
+ return self
450
+ end
451
+
452
+ #===選択肢の集合をTextBoxインスタンスに見合う形のChoicesクラスインスタンスの配列に変換する
453
+ #ブロック(引数一つのブロックのみ有効)を渡したときは、ブロックを評価して変換したChoicesクラスの配列を作成する。
454
+ #引数は、以下の構成を持つ配列のリスト。
455
+ #[非選択時スプライト(文字列可),選択時スプライト(文字列・nil可),選択結果インスタンス]
456
+ # 非選択時スプライト:自身が選択されていない時に表示するスプライト。文字列の時は、Shapeクラスなどでスプライトに変更する
457
+ # 選択時スプライト:自身が選択されている時に表示するスプライト。文字列の時は、Shapeクラスなどでスプライトに変更する
458
+ # (そのとき、文字色が赤色になる)。
459
+ # nilを渡すと、非選択時スプライトが使われる
460
+ # 注:スプライトは、画面にスナップしておくこと
461
+ # 選択結果インスタンス:コマンドが決定したときに、resultメソッドの値として渡すインスタンス。
462
+ # デフォルト処理の選択肢の位置は、画面左上から下へ順番に設定される
463
+ # 注:ブロックを渡すとき、選択肢の位置計算が、全選択肢の左上位置が[0,0]とする相対座標になっていること
464
+ #_choices_:: 選択肢の集合(上記参照)
465
+ #返却値:: Choicesクラスのインスタンスの配列
466
+ def create_choices_chain(choices)
467
+ if block_given?
468
+ return yield(choices)
469
+ end
470
+ choices = choices.map{|v|
471
+ org_font_color = @font.color
472
+ @font.color = Color[:white]
473
+ body = v[0].method(:to_sprite).arity == 0 ? v[0].to_sprite : v[0].to_sprite(@font)
474
+ @font.color = Color[:red]
475
+ body_selected = v[1] ? (v[1].method(:to_sprite).arity == 0 ? v[1].to_sprite : v[1].to_sprite(@font)) : body
476
+ @font.color = org_font_color
477
+ choice = Choices.create_choice(body, body_selected)
478
+ choice.result = v[2]
479
+ choice.end_select_proc = v[3]
480
+ next choice
481
+ }
482
+ choices2 = choices.each_slice(@command_page_size).to_a
483
+ choices2.each_with_index{|cc, x|
484
+ len = cc.length
485
+ right = choices2[x + 1] || choices2[0]
486
+ left = choices2[x - 1]
487
+ yp = 0
488
+ cc.each_with_index{|v, y|
489
+ v.down = cc[y + 1] || cc[0]
490
+ v.up = cc[y - 1]
491
+ v.right = right[y] || right.last
492
+ v.left = left[y] || left.last
493
+ v.body.move_to!(0, yp)
494
+ v.body_selected.move_to!(0, yp)
495
+ yp += [v.body.broad_rect.h, v.body_selected.broad_rect.h].max
496
+ }
497
+ }
498
+ return choices2
499
+ end
500
+
501
+ #===コマンド選択を設定する
502
+ #コマンド選択処理に移る(self#selecting?メソッドがtrueになる)
503
+ #
504
+ # 引数choicesに配列を渡すとき、各要素の構成は以下のようになる
505
+ # [コマンド文字列・画像,選択時コマンド文字列・画像,選択した結果(オブジェクト)]
506
+ #
507
+ # 引数choicesにChoicesクラスインスタンスを渡したとき、内部で、インスタンスを複写したものに置き換える
508
+ #
509
+ # このメソッドが呼び出された時、選択肢はlocateメソッドの値となる位置に移動する
510
+ # 引数dx,dyともにnil以外の数値を渡すと、上記の位置から更に移動する(位置が補正される)
511
+ # body_selectedをnilにした場合は、bodyと同一となる
512
+ # body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
513
+ #_choices_:: 選択肢の配列、もしくはChoicesクラスのインスタンス
514
+ #_dx_:: 選択肢を表示するx座標の移動量。デフォルトはnil(移動しない)
515
+ #_dy_:: 選択肢を表示するy座標の移動量。デフォルトはnil(移動しない)
516
+ #返却値:: 自分自身を返す
517
+ def command(choices, dx = nil, dy = nil)
518
+ if choices.methods.include?(:start_choice)
519
+ @choices = choices.dup
520
+ @choices.snap(self)
521
+ else
522
+ @choices.clear
523
+ choices.each{|cc| @choices.create_choices(cc) }
524
+ end
525
+ @choices.left!{|b| @locate.x}.top!{|b| @locate.y}
526
+ @choices.move!(dx, dy) if (dx != nil && dy != nil)
527
+ start_command
528
+ Fiber.yield if @fiber
529
+ return self
530
+ end
531
+
532
+ #===コマンド選択を開始する
533
+ #但し、commandメソッドを呼び出したときは自動的に呼ばれる
534
+ #返却値:: 自分自身を返す
535
+ def start_command
536
+ raise MiyakoValueError, "don't set Choice!" if @choices.length == 0
537
+ @choices.start_choice
538
+ if @select_cursor
539
+ @select_cursor.snap(@choices.body)
540
+ @select_cursor_position.call(@select_cursor, @choices.body)
541
+ end
542
+ @selecting = true
543
+ return self
544
+ end
545
+
546
+ #===コマンド選択を終了する
547
+ # 選択した選択肢(Choice構造体)にend_select_procブロックが設定されていれば自動的に評価される
548
+ #返却値:: 自分自身を返す
549
+ def finish_command
550
+ @choices.end_choice(self)
551
+ @choices.left!.top!
552
+ @selecting = false
553
+ return self
554
+ end
555
+
556
+ #===選択肢・選択カーソルを移動させる
557
+ #但し、非選択状態だったときは、選択状態に戻るだけ
558
+ #(そのときの選択肢は、最後に選択した選択肢を指定する)
559
+ #_dx_:: 移動量(x軸方向)。-1,0,1の3種類
560
+ #_dy_:: 移動量(y軸方向)。-1,0,1の3種類
561
+ #返却値:: 自分自身を返す
562
+ def move_cursor(dx, dy)
563
+ unless @choices.any_select?
564
+ @choices.start_choice(nil) # 選択状態を元に戻す
565
+ return self
566
+ end
567
+ @move_list[dy][dx].call
568
+ if @select_cursor
569
+ @select_cursor.snap(@choices.body)
570
+ @select_cursor_position.call(@select_cursor, @choices.body)
571
+ end
572
+ return self
573
+ end
574
+
575
+ #===マウスカーソルの位置とコマンドを照合する
576
+ #選択肢・選択カーソルを、マウスカーソルが当たっているコマンドに移動させる
577
+ #どのコマンドにも当たっていない場合は、すべてのコマンドは非選択状態になる
578
+ #_x_:: マウスカーソルの位置(x軸方向)
579
+ #_y_:: マウスカーソルの位置(y軸方向)
580
+ #返却値:: 自分自身を返す
581
+ def attach_cursor(x, y)
582
+ attach = @choices.attach(x, y)
583
+ if attach
584
+ if @select_cursor
585
+ @select_cursor.snap(@choices.body)
586
+ @select_cursor_position.call(@select_cursor, @choices.body)
587
+ end
588
+ else
589
+ @choices.non_select if @pre_attach
590
+ end
591
+ @pre_attach = attach
592
+ return self
593
+ end
594
+
595
+ #===マウスカーソルの位置にコマンドがあるかどうかを問い合わせる
596
+ #マウスカーソルがどれかのコマンドの上にあるときはtrue、どれにも当たっていないときはfalseを返す
597
+ #_x_:: マウスカーソルの位置(x軸方向)
598
+ #_y_:: マウスカーソルの位置(y軸方向)
599
+ #返却値:: マウスカーソルがどれかのコマンドにあるときはtrueを返す
600
+ def attach_any_command?(x, y)
601
+ return @choices.attach(x, y)
602
+ end
603
+
604
+ def update_layout_position #:nodoc:
605
+ @pos.move_to!(*@layout.pos)
606
+ end
607
+
608
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置を設定する
609
+ #ポーズカーソルの位置を、パラメータ二つ(カーソル本体・テキストボックス)を引数に取るブロックで実装する
610
+ #位置は、テキストエリアをsnapしていると想定して実装する
611
+ #デフォルトは、テキストエリアの中下に置かれる(center!.bottom!)
612
+ # (例)テキストボックスの中下(テキストエリアの外) -> {|wc, tbox| wc.center!.outside_bottom! }
613
+ #   テキストボックスの右下(テキストエリアの中) -> {|wc, tbox| wc.right!.bottom! }
614
+ #   テキストの最後尾 -> {|wc, tbox| wc.left!{|b| tbox.locate.x }.top!{|b| tbox.locate.y} }
615
+ # (テキストエリアの左上から右下へ現在の描画開始位置(tbox.locateメソッドで示した値)の距離移動した箇所)
616
+ #ブロックを渡していなかったり、ブロックの引数が2個でなければエラーを返す
617
+ #返却値:: 自分自身を返す
618
+ def set_wait_cursor_position(&proc)
619
+ raise MiyakoProcError, "Can't find block!" unless proc
620
+ raise MiyakoProcError, "This method must have two parameters!" unless proc.arity == 2
621
+ @wait_cursor_position = proc
622
+ @wait_cursor_position.call(@wait_cursor, self) if @wait_cursor
623
+ return self
624
+ end
625
+
626
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置をデフォルトに戻す
627
+ #デフォルトの位置は、テキストエリアの中下(center!.bottom!)に設定されている
628
+ #返却値:: 自分自身を返す
629
+ def reset_wait_cursor_position
630
+ @wait_cursor_position = @default_wait_cursor_position
631
+ @wait_cursor_position.call(@wait_cursor, self) if @wait_cursor
632
+ return self
633
+ end
634
+
635
+ #===コマンド選択時に表示するカーソルの位置を設定する
636
+ #カーソルの位置を、パラメータ二つ(カーソル本体・選択肢)を引数に取るブロックで実装する
637
+ #位置は、テキストエリアをsnapしていると想定して実装する
638
+ #デフォルトは、選択肢の左側に置かれる(outside_left!.middle!)
639
+ # (例)選択肢の右側 -> {|wc, choice| wc.outside_right!.middle! }
640
+ #   選択肢の真上 -> {|wc, choice| wc.centering! }
641
+ #ブロックを渡していなかったり、ブロックの引数が2個でなければエラーを返す
642
+ #返却値:: 自分自身を返す
643
+ def set_select_cursor_position(&proc)
644
+ raise MiyakoProcError, "Can't find block!" unless proc
645
+ raise MiyakoProcError, "This method must have two parameters!" unless proc.arity == 2
646
+ @select_cursor_position = proc
647
+ @select_cursor_position.call(@select_cursor, @choices.body) if (@select_cursor && @choices.body)
648
+ return self
649
+ end
650
+
651
+ #===入力待ち状態(ポーズ)に表示するカーソルの位置をデフォルトに戻す
652
+ #デフォルトの位置は、テキストエリアの中下(center!.bottom!)に設定されている
653
+ #返却値:: 自分自身を返す
654
+ def reset_select_cursor_position
655
+ @select_cursor_position = @default_select_cursor_position
656
+ @select_cursor_position.call(@select_cursor, @choices.body) if (@select_cursor && @choices.body)
657
+ return self
658
+ end
659
+
660
+ #===入力待ち状態(ポーズ)にする
661
+ #ポーズカーソルを表示する。pause?メソッドの結果がtrueになる
662
+ #ポーズカーソルの位置は、set_wait_cursor_positionで設定したブロックが評価されて決定される
663
+ #(デフォルトはテキストエリアの中下
664
+ #返却値:: 自分自身を返す
665
+ def pause
666
+ @waiting = true
667
+ return self unless @wait_cursor
668
+ @wait_cursor_position.call(@wait_cursor, self)
669
+ @on_pause.call
670
+ Fiber.yield if @fiber
671
+ return self
672
+ end
673
+
674
+ #===ポーズ時に行う処理を記述したブロックを登録する
675
+ #処理を行うブロックはオブジェクトとして渡す。
676
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
677
+ #_event_:: ポーズ時処理するブロック
678
+ #返却値:: 自分自身を返す
679
+ def on_pause=(event)
680
+ tpause = @on_pause
681
+ @on_pause = event
682
+ if block_given?
683
+ yield
684
+ @on_pause = tpause
685
+ end
686
+ return self
687
+ end
688
+
689
+ #===入力待ち状態を解除する
690
+ #同時に、ポーズカーソルを隠蔽する。pause?メソッドの結果がfalseになる
691
+ #返却値:: 自分自身を返す
692
+ def release
693
+ @waiting = false
694
+ @on_release.call
695
+ return self
696
+ end
697
+
698
+ #===ポーズ解除時に行う処理を記述したブロックを登録する
699
+ #処理を行うブロックはオブジェクトとして渡す。
700
+ #ブロック引数の時は、そのブロックを処理している間のみ、そのオブジェクトを呼び出して処理させる
701
+ #_event_:: ポーズ解除時処理するブロック
702
+ #返却値:: 自分自身を返す
703
+ def on_release=(event)
704
+ trelease = @on_release
705
+ @on_release = event
706
+ if block_given?
707
+ yield
708
+ @on_release = trelease
709
+ end
710
+ return self
711
+ end
712
+
713
+ #===入力待ち状態かを確認する
714
+ #返却値:: 入力待ち状態の時はtrueを返す
715
+ def pause?
716
+ return @waiting
717
+ end
718
+
719
+ #===コマンド選択中かどうかを確認する
720
+ #返却値:: 選択中の時はtrueを返す
721
+ def selecting?
722
+ return @selecting
723
+ end
724
+
725
+ #===選択結果を取得する
726
+ #返却値:: コマンドの選択結果(選択中のnilを返す)
727
+ def result
728
+ return @choices.result
729
+ end
730
+
731
+ #===テキストエリアに描画している文字を消去する
732
+ #透明色で消去したあと、描画開始位置を左上(0,0)に移動する
733
+ #返却値:: 自分自身を返す
734
+ def clear
735
+ @textarea.bitmap.fillRect(0, 0, @size[0], @size[1], [0, 0, 0, 0])
736
+ @locate = Point.new(0, 0)
737
+ @max_height = @font.line_height
738
+ Fiber.yield if @fiber
739
+ return self
740
+ end
741
+
742
+ #===縦方向のスペースを空ける
743
+ #現在描画可能な位置から、指定したピクセルで下方向に移動する
744
+ #但し、文字の大きさもピクセル数に含むことに注意すること
745
+ #_height_:: スペースを空けるピクセル数
746
+ #返却値:: 自分自身を返す
747
+ def cr(height = @max_height)
748
+ @locate.x = 0
749
+ @locate.y += height
750
+ @max_height = @font.line_height
751
+ Fiber.yield if @fiber
752
+ return self
753
+ end
754
+
755
+ #===横方向のスペースを空ける
756
+ #現在描画可能な位置から、指定したピクセルで右方向に移動する
757
+ #_length_:: スペースを空けるピクセル数
758
+ #返却値:: 自分自身を返す
759
+ def space(length)
760
+ @locate.x += length
761
+ Fiber.yield if @fiber
762
+ return self
763
+ end
764
+
765
+ #===情報を解放する
766
+ def dispose
767
+ @textarea.dispose
768
+ @textarea = nil
769
+ end
770
+
771
+ def_delegators(:@pos, :x, :y)
772
+ end
773
+ end