ruby-miyako-mswin32 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,1180 @@
1
+ # -*- encoding: utf-8 -*-
2
+ =begin
3
+ --
4
+ Miyako v2.1
5
+ Copyright (C) 2007-2009 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
+ #lambdaの別名として、yuki_plotメソッドを追加
24
+ alias :yuki_plot :lambda
25
+
26
+ #=シナリオ言語Yuki実装モジュール
27
+ module Miyako
28
+
29
+ #==Yuki本体クラス
30
+ #Yukiの内容をオブジェクト化したクラス
31
+ #Yukiのプロット処理を外部メソッドで管理可能
32
+ #プロットは、引数を一つ(Yuki2クラスのインスタンス)を取ったメソッドもしくはブロック
33
+ #として記述する。
34
+ class Yuki
35
+ include SpriteBase
36
+ include Animation
37
+
38
+ #==キャンセルを示す構造体
39
+ #コマンド選択がキャンセルされたときに生成される構造体
40
+ Canceled = Struct.new(:dummy)
41
+
42
+ #==コマンド構造体
43
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
44
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
45
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
46
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
47
+ Command = Struct.new(:body, :body_selected, :condition, :result)
48
+
49
+ #==コマンド構造体
50
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
51
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
52
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
53
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
54
+ #_end_select_proc_:: この選択肢を選択したときに優先的に処理するブロック。
55
+ #ブロックは1つの引数を取る(コマンド選択テキストボックス))。デフォルトはnil
56
+ CommandEX = Struct.new(:body, :body_selected, :condition, :result, :end_select_proc)
57
+
58
+ #===Yuki#update実行中に行わせる処理を実装するテンプレートメソッド
59
+ #但し、メソッド本体は、update_inner=メソッドで設定する必要がある
60
+ #_yuki_:: 実行中のYukiクラスインスタンス
61
+ def update_inner(yuki)
62
+ end
63
+
64
+ #===Yuki#text実行中に行わせる処理を実装するテンプレートメソッド
65
+ #update_textテンプレートメソッドは、textメソッドで渡した文字列全体ではなく、
66
+ #内部で1文字ずつ分割して、その字が処理されるごとに呼ばれる。
67
+ #そのため、引数chで入ってくるのは、分割された1文字となる。
68
+ #但し、メソッド本体は、update_text=メソッドで設定する必要がある
69
+ #_yuki_:: 実行中のYukiクラスインスタンス
70
+ #_ch_:: textメソッドで処理中の文字(分割済みの1文字)
71
+ def update_text(yuki, ch)
72
+ end
73
+
74
+ #===Yuki#cr呼び出し時に行わせる処理を実装するテンプレートメソッド
75
+ #但し、メソッド本体は、update_cr=メソッドで設定する必要がある
76
+ #_yuki_:: 実行中のYukiクラスインスタンス
77
+ def update_cr(yuki)
78
+ end
79
+
80
+ #===Yuki#clear呼び出し時に行わせる処理を実装するテンプレートメソッド
81
+ #但し、メソッド本体は、update_clear=メソッドで設定する必要がある
82
+ #_yuki_:: 実行中のYukiクラスインスタンス
83
+ def update_clear(yuki)
84
+ end
85
+
86
+ attr_accessor :visible
87
+ attr_accessor :update_inner, :update_text, :update_cr, :update_clear
88
+ attr_reader :valign
89
+ #release_checks:: ポーズ解除を問い合わせるブロックの配列。
90
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
91
+ #ok_checks:: コマンド選択決定を問い合わせるブロックの配列。
92
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
93
+ #cancel_checks:: コマンド選択解除(キャンセル)を問い合わせるブロックの配列。
94
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
95
+ attr_reader :release_checks, :ok_checks, :cancel_checks
96
+ attr_reader :pre_pause, :pre_command, :pre_cancel, :post_pause, :post_command, :post_cancel
97
+ #selecting_procs:: コマンド選択時に行うブロックの配列。
98
+ #ブロックは4つの引数を取る必要がある。
99
+ #(1)コマンド決定ボタンを押した?(true/false)
100
+ #(2)キャンセルボタンを押した?(true/false)
101
+ #(3)キーパッドの移動量を示す配列([dx,dy])
102
+ #(4)マウスの位置を示す配列([x,y])
103
+ #callメソッドを持つブロックが使用可能。
104
+ attr_reader :selecting_procs
105
+
106
+ #===Yukiにメソッドを追加する
107
+ #ブロックを渡すことで、Yukiに新しいメソッドを追加できる。
108
+ #コンテキストはYukiクラスのインスタンスとなるため、Yukiスクリプトと同じ感覚でメソッドを追加できる。
109
+ #ただし、すでに追加したメソッド(もしくはYukiクラスですでに追加されているメソッド)を追加しようとすると例外が発生する
110
+ #
111
+ #_name_:: ブロックに渡す引数リスト
112
+ #_block_:: メソッドとして実行させるブロック
113
+ def Yuki.add_method(name, &block)
114
+ name = name.to_sym
115
+ raise MiyakoError, "Already added method! : #{name.to_s}" if self.methods.include?(name)
116
+ define_method(name, block)
117
+ return nil
118
+ end
119
+
120
+ #===Yukiを初期化する
121
+ #
122
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
123
+ #引数の数とブロック引数の数が違っていれば例外が発生する
124
+ #_params_:: ブロックに渡す引数リスト(ただし、ブロックを渡しているときのみに有効)
125
+ def initialize(*params, &proc)
126
+ @yuki = { }
127
+ @over_yuki = nil
128
+ @over_exec = false
129
+ @text_box = nil
130
+ @command_box = nil
131
+
132
+ @executing = false
133
+
134
+ @exec_plot = nil
135
+
136
+ @pausing = false
137
+ @selecting = false
138
+ @waiting = false
139
+
140
+ @pause_release = false
141
+ @select_ok = false
142
+ @select_cancel = false
143
+ @select_amount = [0, 0]
144
+ @mouse_amount = nil
145
+
146
+ @result = nil
147
+ @plot_result = nil
148
+
149
+ @update_inner = lambda{|yuki|}
150
+ @update_text = lambda{|yuki, ch|}
151
+ @update_cr = lambda{|yuki|}
152
+ @update_clear = lambda{|yuki|}
153
+
154
+ @parts = {}
155
+ @visibles = SpriteList.new
156
+ @vars = {}
157
+ @visible = true
158
+
159
+ @executing_fiber = nil
160
+
161
+ @text_methods = {:char => self.method(:text_by_char),
162
+ :string => self.method(:text_by_str) }
163
+ @text_method_name = :char
164
+
165
+ @valign = :middle
166
+
167
+ @release_checks_default = [lambda{ Input.pushed_any?(:btn1, :spc) }, lambda{ Input.click?(:left) } ]
168
+ @release_checks = @release_checks_default.dup
169
+
170
+ @ok_checks_default = [lambda{ Input.pushed_any?(:btn1, :spc) },
171
+ lambda{ self.commandbox.attach_any_command?(*Input.get_mouse_position) && Input.click?(:left) } ]
172
+ @ok_checks = @ok_checks_default.dup
173
+
174
+ @cancel_checks_default = [lambda{ Input.pushed_any?(:btn2, :esc) },
175
+ lambda{ Input.click?(:right) } ]
176
+ @cancel_checks = @cancel_checks_default.dup
177
+
178
+ @key_amount_proc = lambda{ Input.pushed_amount }
179
+ @mouse_amount_proc = lambda{ Input.mouse_cursor_inner? ? Input.get_mouse_position : nil }
180
+
181
+ @pre_pause = []
182
+ @pre_command = []
183
+ @pre_cancel = []
184
+ @post_pause = []
185
+ @post_command = []
186
+ @post_cancel = []
187
+ @selecting_procs = []
188
+
189
+ @is_outer_height = self.method(:is_outer_height)
190
+
191
+ @now_page = nil
192
+ @first_page = nil
193
+
194
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
195
+ instance_exec(*params, &proc) if block_given?
196
+ end
197
+
198
+ def initialize_copy(obj) #:nodoc:
199
+ raise MiyakoCopyError.not_copy("Yuki")
200
+ end
201
+
202
+ #===Yuki#showで表示指定した画像を描画する
203
+ #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
204
+ #なお、visibleの値がfalseの時は描画されない。
205
+ #返却値:: 自分自身を返す
206
+ def render
207
+ @visibles.render if @visible
208
+ @over_yuki.render if @over_yuki && @over_yuki.executing?
209
+ return self
210
+ end
211
+
212
+ #===Yuki#showで表示指定した画像を描画する
213
+ #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
214
+ #なお、visibleの値がfalseの時は描画されない。
215
+ #返却値:: 自分自身を返す
216
+ def render_to(dst)
217
+ @visibles.render_to(dst) if @visible
218
+ @over_yuki.render_to(dst) if @over_yuki && @over_yuki.executing?
219
+ return self
220
+ end
221
+
222
+ #===Yuki#showで表示指定した画像のアニメーションを更新する
223
+ #showメソッドで指定した画像のupdate_animationメソッドを呼び出す
224
+ #返却値:: 描く画像のupdate_spriteメソッドを呼び出した結果を配列で返す
225
+ def update_animation
226
+ @over_yuki.update_animation if @over_yuki && @over_yuki.executing?
227
+ @visibles.update_animation
228
+ end
229
+
230
+ #===変数を参照する
231
+ #[[Yukiスクリプトとして利用可能]]
232
+ #変数の管理オブジェクトを、ハッシュとして参照する。
233
+ #変数名nameを指定して、インスタンスを参照できる。
234
+ #未登録の変数はnilが変える。
235
+ #(例)vars[:a] = 2 # 変数への代入
236
+ # vars[:b] = vars[:a] + 5
237
+ # show vars[:my_name]
238
+ #
239
+ #_name_:: パーツ名(シンボル)
240
+ #
241
+ #返却値:: 変数管理ハッシュ
242
+ def vars
243
+ @vars
244
+ end
245
+
246
+ #===変数を参照する
247
+ #[[Yukiスクリプトとして利用可能]]
248
+ #変数の管理オブジェクトを、ハッシュとして参照する。
249
+ #変数名nameを指定して、インスタンスを参照できる。
250
+ #未登録の変数はnilが変える。
251
+ #(例)vars[:a] = 2 # 変数への代入
252
+ # vars[:b] = vars[:a] + 5
253
+ # vars_names => [:a, :b]
254
+ #
255
+ #_name_:: パーツ名(シンボル)
256
+ #
257
+ #返却値:: 変数管理ハッシュ
258
+ def vars_names
259
+ @vars.keys
260
+ end
261
+
262
+ #===パーツを参照する
263
+ #[[Yukiスクリプトとして利用可能]]
264
+ #パーツの管理オブジェクトを、ハッシュとして参照する。
265
+ #パーツ名nameを指定して、インスタンスを参照できる
266
+ #未登録のパーツはnilが返る
267
+ #(例)parts[:chr1]
268
+ #
269
+ #返却値:: パーツ管理ハッシュ
270
+ def parts
271
+ @parts
272
+ end
273
+
274
+ #===パーツ名の一覧を参照する
275
+ #[[Yukiスクリプトとして利用可能]]
276
+ #パーツ管理オブジェクトに登録されているパーツ名の一覧を配列として返す。
277
+ #順番は登録順。
278
+ #まだ何も登録されていないときは空の配列が返る。
279
+ #(例)regist_parts :chr1, hoge
280
+ # regist_parts :chr2, fuga
281
+ # parts_names # => [:chr1, :chr2]
282
+ #
283
+ #返却値:: パーツ管理ハッシュ
284
+ def parts_names
285
+ @parts.keys
286
+ end
287
+
288
+ #===現在描画対象のパーツ名のリストを取得する
289
+ #[[Yukiスクリプトとして利用可能]]
290
+ #現在描画しているパーツ名の配列を参照する。
291
+ #実体のインスタンスは、partsメソッドで参照できるハッシュの値として格納されている。
292
+ #Yuki#renderで描画する際、配列の先頭から順に、要素に対応するインスタンスを描画する(つまり、配列の後ろにある方が前に描画される
293
+ #(例):[:a, :b, :c]の順に並んでいたら、:cが指すインスタンスが一番前に描画される。
294
+ #
295
+ #返却値:: 描画対象リスト
296
+ def visibles
297
+ @visibles.names
298
+ end
299
+
300
+ #===オブジェクトを登録する
301
+ #[[Yukiスクリプトとして利用可能]]
302
+ #オブジェクトをパーツnameとして登録する。
303
+ #Yuki::parts[name]で参照可能
304
+ #_name_:: パーツ名(シンボル)
305
+ #_parts_:: 登録対象のインスタンス
306
+ #
307
+ #返却値:: 自分自身を返す
308
+ def regist_parts(name, parts)
309
+ @parts[name] = parts
310
+ return self
311
+ end
312
+
313
+ #===表示・描画対象のテキストボックスを選択する
314
+ #[[Yukiスクリプトとして利用可能]]
315
+ #_box_:: テキストボックスのインスタンス
316
+ #
317
+ #返却値:: 自分自身を返す
318
+ def select_textbox(box)
319
+ @text_box = box
320
+ return self
321
+ end
322
+
323
+ #===表示・描画対象のコマンドボックスを選択する
324
+ #[[Yukiスクリプトとして利用可能]]
325
+ #_box_:: テキストボックスのインスタンス
326
+ #
327
+ #返却値:: 自分自身を返す
328
+ def select_commandbox(box)
329
+ @command_box = box
330
+ return self
331
+ end
332
+
333
+ #===テキストボックスを取得する
334
+ #[[Yukiスクリプトとして利用可能]]
335
+ #テキストボックスが登録されていないときはnilを返す
336
+ #返却値:: テキストボックスのインスタンス
337
+ def textbox
338
+ return @text_box
339
+ end
340
+
341
+ #===コマンドボックスを取得する
342
+ #[[Yukiスクリプトとして利用可能]]
343
+ #コマンドボックスが登録されていないときはnilを返す
344
+ #返却値:: コマンドボックスのインスタンス
345
+ def commandbox
346
+ return @command_box
347
+ end
348
+
349
+ #===オブジェクトの登録を解除する
350
+ #[[Yukiスクリプトとして利用可能]]
351
+ #パーツnameとして登録されているオブジェクトを登録から解除する。
352
+ #_name_:: パーツ名(シンボル)
353
+ #
354
+ #返却値:: 自分自身を返す
355
+ def remove_parts(name)
356
+ @parts.delete(name)
357
+ return self
358
+ end
359
+
360
+ #===パーツで指定したオブジェクトを先頭に表示する
361
+ #[[Yukiスクリプトとして利用可能]]
362
+ #描画時に、指定したパーツを描画する
363
+ #すでにshowメソッドで表示指定している場合は、先頭に表示させる
364
+ #_names_:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
365
+ #返却値:: 自分自身を返す
366
+ def show(*names)
367
+ names.each{|name|
368
+ @visibles.add(name, @parts[name])
369
+ @parts[name].show
370
+ }
371
+ return self
372
+ end
373
+
374
+ #===パーツで指定したオブジェクトを隠蔽する
375
+ #[[Yukiスクリプトとして利用可能]]
376
+ #描画時に、指定したパーツを描画させないよう指定する
377
+ #_names_:: パーツ名(シンボル)、複数指定可能
378
+ #返却値:: 自分自身を返す
379
+ def hide(*names)
380
+ names.each{|name|
381
+ @parts[name].hide
382
+ @visibles.delete(name)
383
+ }
384
+ return self
385
+ end
386
+
387
+ #===パーツで指定したオブジェクトの処理を開始する
388
+ #[[Yukiスクリプトとして利用可能]]
389
+ #nameで指定したパーツが持つ処理(例:アニメーション)を開始する。
390
+ #(但し、パーツで指定したオブジェクトがstartメソッドを持つことが条件)
391
+ #_name_:: パーツ名(シンボル)
392
+ #返却値:: 自分自身を返す
393
+ def start(name)
394
+ @parts[name].start
395
+ return self
396
+ end
397
+
398
+ #===パーツで指定したオブジェクトを再生する
399
+ #[[Yukiスクリプトとして利用可能]]
400
+ #nameで指定したパーツを再生(例:BGM)する。
401
+ #(但し、パーツで指定したオブジェクトがplayメソッドを持つことが条件)
402
+ #_name_:: パーツ名(シンボル)
403
+ #返却値:: 自分自身を返す
404
+ def play(name)
405
+ @parts[name].play
406
+ return self
407
+ end
408
+
409
+ #===パーツで指定したオブジェクトの処理を停止する
410
+ #[[Yukiスクリプトとして利用可能]]
411
+ #nameで指定したパーツが持つ処理を停止する。
412
+ #(但し、パーツで指定したオブジェクトがstopメソッドを持つことが条件)
413
+ #_name_:: パーツ名(シンボル)
414
+ #返却値:: 自分自身を返す
415
+ def stop(name)
416
+ @parts[name].stop
417
+ return self
418
+ end
419
+
420
+ #===遷移図の処理が終了するまで待つ
421
+ #[[Yukiスクリプトとして利用可能]]
422
+ #nameで指定した遷移図の処理が終了するまで、プロットを停止する
423
+ #_name_: 遷移図名(シンボル)
424
+ #返却値:: 自分自身を返す
425
+ def wait_by_finish(name)
426
+ until @parts[name].finish?
427
+ @update_inner.call(self)
428
+ end
429
+ return self
430
+ end
431
+
432
+ #===別のYukiエンジンを実行する
433
+ #[[Yukiスクリプトとして利用可能]]
434
+ #もう一つのYukiエンジンを実行させ、並行実行させることができる
435
+ #ウインドウの上にウインドウを表示したりするときに、このメソッドを使う
436
+ #renderメソッドで描画する際は、自分のインスタンスが描画した直後に描画される
437
+ #自分自身を実行しようとするとMiyakoValueError例外が発生する
438
+ #_yuki_:: 実行対象のYukiインスタンス(事前にsetupの呼び出しが必要)
439
+ #_plot_:: プロットインスタンス。すでにsetupなどで登録しているときはnilを渡す
440
+ #_params_:: プロット実行開始時に、プロットに渡す引数
441
+ #返却値:: 自分自身を返す
442
+ def over_exec(yuki, plot, *params)
443
+ raise MiyakoValueError, "This Yuki engine is same as self!" if yuki.eql?(self)
444
+ @over_yuki = yuki
445
+ @over_yuki.start_plot(plot, *params)
446
+ return self
447
+ end
448
+
449
+ #===別のYukiエンジンの実行が終わるまで待つ
450
+ #[[Yukiスクリプトとして利用可能]]
451
+ #over_execを呼び出した時、処理がすぐに次の行へ移るため、
452
+ #over_execの処理が終了するのを待たせるためのメソッド
453
+ #返却値:: 自分自身を返す
454
+ def wait_over_exec
455
+ @over_exec = true
456
+ while @over_yuki && @over_yuki.executing?
457
+ @over_yuki.update
458
+ Fiber.yield
459
+ end
460
+ return self
461
+ end
462
+
463
+ #===シーンのセットアップ時に実行する処理
464
+ #
465
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
466
+ #引数の数とブロック引数の数が違っていれば例外が発生する
467
+ #_params_:: ブロックに渡す引数リスト(ブロックを渡しているときのみ)
468
+ #返却値:: 自分自身を返す
469
+ def setup(*params, &proc)
470
+ @exec_plot = nil
471
+
472
+ @executing = false
473
+
474
+ @pausing = false
475
+ @selecting = false
476
+ @waiting = false
477
+
478
+ @pause_release = false
479
+ @select_ok = false
480
+ @select_cancel = false
481
+ @select_amount = [0, 0]
482
+ @mouse_amount = nil
483
+
484
+ @result = nil
485
+ @plot_result = nil
486
+
487
+ @now_page = nil
488
+ @first_page = nil
489
+
490
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
491
+ instance_exec(*params, &proc) if proc
492
+
493
+ return self
494
+ end
495
+
496
+ #===実行するプロットと登録する
497
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
498
+ #返却値:: 自分自身を返す
499
+ def select_plot(plot_proc)
500
+ @exec_plot = plot_proc
501
+ return self
502
+ end
503
+
504
+ #===プロット処理を実行する(明示的に呼び出す必要がある場合)
505
+ #引数もしくはブロックで指定したプロット処理を非同期に実行する。
506
+ #呼び出し可能なプロットは以下の3種類。(上から優先度が高い順)
507
+ #プロットが見つからなければ例外が発生する
508
+ #
509
+ #1)引数prot_proc(Procクラスのインスタンス)
510
+ #
511
+ #2)引数として渡したブロック
512
+ #
513
+ #3)select_plotメソッドで登録したブロック(Procクラスのインスタンス)
514
+ #
515
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト。省略時はnil(paramsを指定するときは必ず設定すること)
516
+ #_params_:: プロットに引き渡す引数リスト
517
+ #返却値:: 自分自身を返す
518
+ def start_plot(plot_proc = nil, *params, &plot_block)
519
+ raise MiyakoValueError, "Yuki Error! Textbox is not selected!" unless @text_box
520
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if plot_proc && plot_proc.arity.abs != params.length
521
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if plot_block && plot_block.arity.abs != params.length
522
+ raise MiyakoProcError, "Aagument count is not same block parameter count!" if @exec_plot && @exec_plot.arity.abs != params.length
523
+ @executing_fiber = Fiber.new{ plot_facade(plot_proc, *params, &plot_block) }
524
+ @executing_fiber.resume
525
+ return self
526
+ end
527
+
528
+ #===プロット処理を更新する
529
+ #ポーズ中、コマンド選択中、 Yuki#wait メソッドによるウェイトの状態確認を行う。
530
+ #プロット処理の実行確認は出来ない
531
+ def update
532
+ return unless @executing
533
+ return @over_yuki.update if @over_yuki && @over_yuki.executing? && !@over_exec
534
+ update_plot_input
535
+ pausing if @pausing
536
+ selecting if @selecting
537
+ waiting if @waiting
538
+ @pause_release = false
539
+ @select_ok = false
540
+ @select_cancel = false
541
+ @select_amount = [0, 0]
542
+ @executing_fiber.resume
543
+ end
544
+
545
+ #===プロット用ブロックをYukiへ渡すためのインスタンスを作成する
546
+ #プロット用に用意したブロック(ブロック引数無し)を、Yukiでの選択結果や移動先として利用できる
547
+ #インスタンスに変換する
548
+ #返却値:: ブロックをオブジェクトに変換したものを返す
549
+ def to_plot(&plot)
550
+ return plot
551
+ end
552
+
553
+ #===プロット処理に使用する入力情報を更新する
554
+ #ポーズ中、コマンド選択中に使用する入力デバイスの押下状態を更新する
555
+ #(但し、プロット処理の実行中にのみ更新する)
556
+ #Yuki#update メソッドをそのまま使う場合は呼び出す必要がないが、 Yuki#exec_plot メソッドを呼び出す
557
+ #プロット処理の場合は、メインスレッドから明示的に呼び出す必要がある
558
+ #返却値:: nil を返す
559
+ def update_plot_input
560
+ return nil if @over_yuki && @over_yuki.executing?
561
+ return nil unless @executing
562
+ if @pausing && @release_checks.inject(false){|r, c| r |= c.call }
563
+ @pause_release = true
564
+ elsif @selecting
565
+ @select_ok = true if @ok_checks.inject(false){|r, c| r |= c.call }
566
+ @select_cancel = true if @cancel_checks.inject(false){|r, c| r |= c.call }
567
+ @select_amount = @key_amount_proc.call
568
+ @mouse_amount = @mouse_amount_proc.call
569
+ end
570
+ return nil
571
+ end
572
+
573
+ def plot_facade(plot_proc = nil, *params, &plot_block) #:nodoc:
574
+ @plot_result = nil
575
+ @executing = true
576
+ exec_plot = @exec_plot
577
+ @plot_result = plot_proc ? self.instance_exec(*params, &plot_proc) :
578
+ block_given? ? self.instance_exec(*params, &plot_block) :
579
+ exec_plot ? self.instance_exec(*params, &exec_plot) :
580
+ raise(MiyakoProcError, "Cannot find plot!")
581
+ @executing = false
582
+ end
583
+
584
+ #===プロット処理中に別のプロットを呼び出す
585
+ #呼び出し可能なプロットは以下の2種類。(上から優先度が高い順)
586
+ #
587
+ #1)引数prot_proc(Procクラスのインスタンス)
588
+ #
589
+ #2)引数として渡したブロック
590
+ #
591
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
592
+ #返却値:: プロットの実行結果を返す
593
+ def call_plot(plot_proc = nil, &plot_block)
594
+ return plot_proc ? self.instance_exec(&plot_proc) :
595
+ self.instance_exec(&plot_block)
596
+ end
597
+
598
+ #===プロット処理が実行中かどうかを確認する
599
+ #返却値:: プロット処理実行中の時はtrueを返す
600
+ def executing?
601
+ return @executing
602
+ end
603
+
604
+ #===ポーズ解除問い合わせメソッド配列を初期状態に戻す
605
+ #返却値:: 自分自身を返す
606
+ def reset_release_checks
607
+ @release_checks = @release_checks_default.dup
608
+ return self
609
+ end
610
+
611
+ #===コマンド選択決定問い合わせメソッド配列を初期状態に戻す
612
+ #返却値:: 自分自身を返す
613
+ def reset_ok_checks
614
+ @ok_checks = @ok_checks_default.dup
615
+ return self
616
+ end
617
+
618
+ #===コマンド選択キャンセル問い合わせメソッド配列を初期状態に戻す
619
+ #返却値:: 自分自身を返す
620
+ def reset_cancel_checks
621
+ @cancel_checks = @cancel_checks_default.dup
622
+ return self
623
+ end
624
+
625
+ #===ポーズ前後処理メソッド配列を初期状態に戻す
626
+ #pre_pause/post_pauseの処理を初期状態([])に戻す
627
+ #返却値:: 自分自身を返す
628
+ def reset_pre_post_release
629
+ @pre_pause = []
630
+ @post_pause = []
631
+ return self
632
+ end
633
+
634
+ #===コマンド選択前後処理メソッド配列を初期状態に戻す
635
+ #pre_command/post_commandの処理を初期状態([])に戻す
636
+ #返却値:: 自分自身を返す
637
+ def reset_pre_post_command
638
+ @pre_command = []
639
+ @post_command = []
640
+ return self
641
+ end
642
+
643
+ #===コマンド選択キャンセル前後処理メソッド配列を初期状態に戻す
644
+ #pre_cancel/post_cancelの処理を初期状態([])に戻す
645
+ #返却値:: 自分自身を返す
646
+ def reset_pre_post_cancel
647
+ @pre_acncel = []
648
+ @post_cancel = []
649
+ return self
650
+ end
651
+
652
+ #===ブロック評価中、ポーズ解除問い合わせメソッド配列を置き換える
653
+ #同時に、ポーズ時処理(Yuki#pre_pause)、ポーズ解除時処理(Yuki#post_pause)を引数で設定できる。
654
+ #ブロックの評価が終われば、メソッド配列・ポーズ時処理・ポーズ解除時処理を元に戻す
655
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
656
+ #pre_proc:: ポーズ開始時に実行させるProc(デフォルトは[](何もしない))
657
+ #post_proc:: ポーズ解除時に実行させるProc(デフォルトは[](何もしない))
658
+ #返却値:: 自分自身を返す
659
+ def release_checks_during(procs, pre_procs = [], post_procs = [])
660
+ raise MiyakoProcError, "Can't find block!" unless block_given?
661
+ backup = [@release_checks, @pre_pause, @post_pause]
662
+ @release_checks, @pre_pause, @post_pause = procs, pre_proc, post_proc
663
+ yield
664
+ @release_checks, @pre_pause, @post_pause = backup.pop(3)
665
+ return self
666
+ end
667
+
668
+ #===ブロック評価中、コマンド選択決定問い合わせメソッド配列を置き換える
669
+ #同時に、コマンド選択開始時処理(Yuki#pre_command)、コマンド選択終了時処理(Yuki#post_command)を引数で設定できる。
670
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
671
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
672
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
673
+ #post_proc:: コマンド選択決定時に実行させるProc(デフォルトは[](何もしない))
674
+ #返却値:: 自分自身を返す
675
+ def ok_checks_during(procs, pre_procs = [], post_procs = [])
676
+ raise MiyakoProcError, "Can't find block!" unless block_given?
677
+ backup = [@ok_checks, @pre_command, @post_command]
678
+ @ok_checks, @pre_command, @post_command = procs, pre_proc, post_proc
679
+ yield
680
+ @ok_checks, @pre_command, @post_command = backup.pop(3)
681
+ return self
682
+ end
683
+
684
+ #===ブロック評価中、コマンド選択キャンセル問い合わせメソッド配列を置き換える
685
+ #同時に、コマンド選択開始時処理(Yuki#pre_cancel)、コマンド選択終了時処理(Yuki#post_cancel)を引数で設定できる。
686
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
687
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
688
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
689
+ #post_proc:: コマンド選択キャンセル時に実行させるProc(デフォルトは[](何もしない))
690
+ #返却値:: 自分自身を返す
691
+ def cancel_checks_during(procs, pre_procs = [], post_procs = [])
692
+ raise MiyakoProcError, "Can't find block!" unless block_given?
693
+ backup = [@cancel_checks, @pre_cancel, @post_cancel]
694
+ @cancel_checks, @pre_cancel, @post_cancel = procs, pre_proc, post_proc
695
+ yield
696
+ @cancel_checks, @pre_cancel, @post_cancel = backup.pop(3)
697
+ return self
698
+ end
699
+
700
+ #===プロットの処理結果を返す
701
+ #[[Yukiスクリプトとして利用可能]]
702
+ #プロット処理の結果を返す。
703
+ #まだ結果が得られていない場合はnilを得る
704
+ #プロット処理が終了していないのに結果を得られるので注意!
705
+ #返却値:: プロットの処理結果
706
+ def result
707
+ return @plot_result
708
+ end
709
+
710
+ #===プロット処理の結果を設定する
711
+ #[[Yukiスクリプトとして利用可能]]
712
+ #_ret_:: 設定する結果。デフォルトはnil
713
+ #返却値:: 自分自身を返す
714
+ def result=(ret = nil)
715
+ @plot_result = ret
716
+ return self
717
+ end
718
+
719
+ #===結果がシーンかどうかを問い合わせる
720
+ #[[Yukiスクリプトとして利用可能]]
721
+ #結果がシーン(シーンクラス名)のときはtrueを返す
722
+ #対象の結果は、選択結果、プロット処理結果ともに有効
723
+ #返却値:: 結果がシーンかどうか(true/false)
724
+ def is_scene?(result)
725
+ return (result.class == Class && result.include?(Story::Scene))
726
+ end
727
+
728
+ #===結果がシナリオかどうかを問い合わせる
729
+ #[[Yukiスクリプトとして利用可能]]
730
+ #結果がシナリオ(メソッド)のときはtrueを返す
731
+ #対象の結果は、選択結果、プロット処理結果ともに有効
732
+ #返却値:: 結果がシナリオかどうか(true/false)
733
+ def is_scenario?(result)
734
+ return (result.kind_of?(Proc) || result.kind_of?(Method))
735
+ end
736
+
737
+ #===コマンド選択がキャンセルされたときの結果を返す
738
+ #[[Yukiスクリプトとして利用可能]]
739
+ #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
740
+ def canceled?
741
+ return result == @cancel
742
+ end
743
+
744
+ #===ブロックを条件として設定する
745
+ #[[Yukiスクリプトとして利用可能]]
746
+ #メソッドをMethodクラスのインスタンスに変換する
747
+ #_block_:: シナリオインスタンスに変換したいメソッド名(シンボル)
748
+ #返却値:: シナリオインスタンスに変換したメソッド
749
+ def condition(&block)
750
+ return block
751
+ end
752
+
753
+ #===コマンド選択中の問い合わせメソッド
754
+ #[[Yukiスクリプトとして利用可能]]
755
+ #返却値:: コマンド選択中の時はtrueを返す
756
+ def selecting?
757
+ return @selecting
758
+ end
759
+
760
+ #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
761
+ #[[Yukiスクリプトとして利用可能]]
762
+ #返却値:: 処理待ちの時はtrueを返す
763
+ def waiting?
764
+ return @waiting
765
+ end
766
+
767
+ #===メッセージ送り待ちの問い合わせメソッド
768
+ #[[Yukiスクリプトとして利用可能]]
769
+ #返却値:: メッセージ送り待ちの時はtrueを返す
770
+ def pausing?
771
+ return @pausing
772
+ end
773
+
774
+ #===条件に合っていればポーズをかける
775
+ #[[Yukiスクリプトとして利用可能]]
776
+ #引数で設定した条件(Proc,メソッドインスタンス,ブロック)を評価した結果、trueのときはポーズを行い、
777
+ #condの値がnilで、ブロックが渡されていないときは何もしない
778
+ #falseのときは改行してプロットの処理を継続する
779
+ #_cond_:: 条件を示すオブジェクト(返却値はtrue/false)。デフォルトはnil(渡されたブロックを評価する)
780
+ #返却値:: 自分自身を返す
781
+ def wait_by_cond(cond = nil)
782
+ return yield ? pause_and_clear : cr if block_given?
783
+ return cond.call ? pause_and_clear : cr if cond
784
+ return self
785
+ end
786
+
787
+ #===テキストボックスに文字を表示する方法を指定する
788
+ #引数に、:charを渡すと1文字ごと、:stringを渡すと文字列ごとに表示される。それ以外を指定したときは例外が発生
789
+ #ブロックを渡せば、ブロックの評価中のみ設定が有効になる。
790
+ #ブロック評価終了後、呼び出し前の設定に戻る
791
+ #_mode_:: テキストの表示方法。:charのときは文字ごと、:stringのときは文字列ごとに表示される。それ以外を指定したときは例外が発生
792
+ #返却値:: 自分自身を返す
793
+ def text_method(mode)
794
+ raise MiyakoValueError, "undefined text_mode! #{mode}" unless [:char,:string].include?(mode)
795
+ backup = @text_method_name
796
+ @text_method_name = mode
797
+ if block_given?
798
+ yield
799
+ @text_method_name = backup
800
+ end
801
+ return self
802
+ end
803
+
804
+ #===テキストボックスに文字を表示する
805
+ #[[Yukiスクリプトとして利用可能]]
806
+ #テキストボックスとして用意している画像に文字を描画する。
807
+ #描画する単位(文字単位、文字列単位)によって、挙動が違う。
808
+ #(文字単位の時)
809
+ #Yuki#text_by_charメソッドと同じ挙動。
810
+ #(文字列単位の時)
811
+ #Yuki#text_by_strメソッドと同じ挙動。
812
+ #デフォルトは文字単位。
813
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
814
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
815
+ #_txt_:: 表示させるテキスト
816
+ #返却値:: 自分自身を返す
817
+ def text(txt)
818
+ return self if txt.eql?(self)
819
+ return self if txt.empty?
820
+ return @text_methods[@text_method_name].call(txt)
821
+ end
822
+
823
+ #===テキストボックスに文字を1文字ずつ表示する
824
+ #[[Yukiスクリプトとして利用可能]]
825
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
826
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
827
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
828
+ #_txt_:: 表示させるテキスト
829
+ #返却値:: 自分自身を返す
830
+ def text_by_char(txt)
831
+ return self if txt.eql?(self)
832
+ txt.chars{|ch|
833
+ if /[\n\r]/.match(ch)
834
+ next wait_by_cond(@is_outer_height)
835
+ elsif @text_box.locate.x + @text_box.font.text_size(ch)[0] >= @text_box.textarea.w
836
+ wait_by_cond(@is_outer_height)
837
+ elsif /[\t\f]/.match(ch)
838
+ next nil
839
+ end
840
+ @text_box.draw_text(ch)
841
+ @update_text.call(self, ch)
842
+ Fiber.yield
843
+ }
844
+ return self
845
+ end
846
+
847
+ #===テキストボックスに文字を表示する
848
+ #[[Yukiスクリプトとして利用可能]]
849
+ #文字列が描画されるごとに、update_textメソッドが呼び出され、
850
+ #続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
851
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
852
+ #_txt_:: 表示させるテキスト
853
+ #返却値:: 自分自身を返す
854
+ def text_by_str(txt)
855
+ return self if txt.eql?(self)
856
+ use_cr = false
857
+ until txt.empty? do
858
+ if /[\n\r]/.match(txt)
859
+ tmp = Regexp.last_match.pre_match
860
+ txt = Regexp.last_match.post_match
861
+ use_cr = true
862
+ elsif @text_box.locate.x + @text_box.font.text_size(txt)[0] >= @text_box.textarea.w
863
+ w = (@text_box.textarea.w - @text_box.locate.x) / @text_box.font.size
864
+ tmp = txt.slice!(0,w)
865
+ use_cr = true
866
+ elsif /[\t\f]/.match(txt)
867
+ next nil
868
+ else
869
+ tmp = txt
870
+ txt = ""
871
+ end
872
+ @text_box.draw_text(tmp)
873
+ self.cr if use_cr
874
+ @update_text.call(self, tmp)
875
+ Fiber.yield
876
+ use_cr = false
877
+ end
878
+ return self
879
+ end
880
+
881
+ def is_outer_height #:nodoc:
882
+ return @text_box.locate.y + @text_box.max_height >= @text_box.textarea.h
883
+ end
884
+
885
+ private :is_outer_height
886
+
887
+ #===文字色を変更する
888
+ #[[Yukiスクリプトとして利用可能]]
889
+ #ブロック内で指定した文字列を、指定の色で描画する
890
+ #_color_:: 文字色
891
+ #返却値:: 自分自身を返す
892
+ def color(color, &block)
893
+ @text_box.color_during(Color.to_rgb(color)){ text block.call }
894
+ return self
895
+ end
896
+
897
+ #===ブロック評価中、行中の表示位置を変更する
898
+ #[[Yukiスクリプトとして利用可能]]
899
+ #ブロックを評価している間だけ、デフォルトの縦の表示位置を変更する
900
+ #変更できる値は、:top、:middle、:bottomの3種類。
901
+ #ブロックを渡していないときはエラーを返す
902
+ #_valign_:: 文字の縦の位置(top, middle, bottom)
903
+ #返却値:: 自分自身を返す
904
+ def valign_during(valign)
905
+ raise MiyakoProcError, "Can't find block!" unless block_given?
906
+ oalign, @valign = @valign, valign
907
+ yield
908
+ @valign = oalign
909
+ return self
910
+ end
911
+
912
+ #===文字の大きさを変更する
913
+ #[[Yukiスクリプトとして利用可能]]
914
+ #ブロック内で指定した文字列を、指定の大きさで描画する
915
+ #_size_:: 文字の大きさ(整数)
916
+ #_valign_:: 文字の縦の位置(top, middle, bottom)。デフォルトは:middle(Yuki#valign=,Yuki#valign_duringで変更可能)
917
+ #返却値:: 自分自身を返す
918
+ def size(size, valign = @valign, &block)
919
+ @text_box.font_size_during(size){
920
+ @text_box.margin_during(@text_box.margin_height(valign)){ text block.call }
921
+ }
922
+ return self
923
+ end
924
+
925
+ #===太文字を描画する
926
+ #[[Yukiスクリプトとして利用可能]]
927
+ #ブロック内で指定した文字列を太文字で表示する
928
+ #(使用すると文字の端が切れてしまう場合あり!)
929
+ #返却値:: 自分自身を返す
930
+ def bold(&block)
931
+ @text_box.font_bold{ text block.call }
932
+ return self
933
+ end
934
+
935
+ #===斜体文字を描画する
936
+ #[[Yukiスクリプトとして利用可能]]
937
+ #ブロック内で指定した文字列を斜体で表示する
938
+ #(使用すると文字の端が切れてしまう場合あり!)
939
+ #返却値:: 自分自身を返す
940
+ def italic(&block)
941
+ @text_box.font_italic{ text block.call }
942
+ return self
943
+ end
944
+
945
+ #===下線付き文字を描画する
946
+ #[[Yukiスクリプトとして利用可能]]
947
+ #ブロック内で指定した文字列を下線付きで表示する
948
+ #返却値:: 自分自身を返す
949
+ def under_line(&block)
950
+ @text_box.font_under_line{ text block.call }
951
+ return self
952
+ end
953
+
954
+ #===改行を行う
955
+ #[[Yukiスクリプトとして利用可能]]
956
+ #開業後にupdate_crテンプレートメソッドが1回呼ばれる
957
+ #_tm_:: 改行回数。デフォルトは1
958
+ #返却値:: 自分自身を返す
959
+ def cr(tm = 1)
960
+ tm.times{|n|
961
+ @text_box.cr
962
+ @update_cr.call(self)
963
+ }
964
+ return self
965
+ end
966
+
967
+ #===テキストボックスの内容を消去する
968
+ #[[Yukiスクリプトとして利用可能]]
969
+ #開業後にupdate_clearテンプレートメソッドが1回呼ばれる
970
+ #返却値:: 自分自身を返す
971
+ def clear
972
+ @text_box.clear
973
+ @update_clear.call(self)
974
+ return self
975
+ end
976
+
977
+ #===ポーズを行う
978
+ #[[Yukiスクリプトとして利用可能]]
979
+ #ポーズが行われると、ポーズ用のカーソルが表示される
980
+ #所定のボタンを押すとポーズが解除され、カーソルが消える
981
+ #解除後は、プロットの続きを処理する
982
+ #引数無しのブロックを渡せば、ポーズ開始前に行いたい処理を施すことが出来る
983
+ #ポーズ中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
984
+ #Yuki#updateが呼び出されてもポーズ中の場合は、再び上記の処理を繰り返す
985
+ #(たとえば、一定時間後に自動的にポーズ解除する場合、そのタイマーを開始させるなど)
986
+ #返却値:: 自分自身を返す
987
+ def pause
988
+ @pre_pause.each{|proc| proc.call}
989
+ yield if block_given?
990
+ @text_box.pause
991
+ @pausing = true
992
+ while @pausing
993
+ @update_inner.call(self)
994
+ Fiber.yield
995
+ end
996
+ @post_pause.each{|proc| proc.call}
997
+ return self
998
+ end
999
+
1000
+ def pausing #:nodoc:
1001
+ return unless @pause_release
1002
+ @text_box.release
1003
+ @pausing = false
1004
+ @pause_release = false
1005
+ end
1006
+
1007
+ #===ポーズをかけて、テキストボックスの内容を消去する
1008
+ #[[Yukiスクリプトとして利用可能]]
1009
+ #ポーズをかけ、ポーズを解除するときにテキストボックスの内容を消去する
1010
+ #返却値:: 自分自身を返す
1011
+ def pause_and_clear
1012
+ return pause.clear
1013
+ end
1014
+
1015
+ #===コマンドを表示する
1016
+ #[[Yukiスクリプトとして利用可能]]
1017
+ #表示対象のコマンド群をCommand構造体の配列で示す。
1018
+ #キャンセルのときの結果も指定可能(既定ではキャンセル不可状態)
1019
+ #body_selectedをnilにした場合は、bodyと同一となる
1020
+ #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
1021
+ #引数無しのブロックを渡せば、コマンド選択開始前に、決定判別・キャンセル判別に必要な前処理を施すことが出来る
1022
+ #選択中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
1023
+ #Yuki#updateが呼び出されても選択中の場合は、再び上記の処理を繰り返す
1024
+ #_command_list_:: 表示するコマンド群。各要素はCommand構造体の配列
1025
+ #_cancel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
1026
+ #_chain_block_:: コマンドの表示方法。TextBox#create_choices_chainメソッド参照
1027
+ #返却値:: 自分自身を返す
1028
+ def command(command_list, cancel_to = Canceled, &chain_block)
1029
+ raise MiyakoValueError, "Yuki Error! Commandbox is not selected!" unless @command_box
1030
+ @cancel = cancel_to
1031
+
1032
+ choices = []
1033
+ command_list.each{|cm|
1034
+ if (cm[:condition] == nil || cm[:condition].call)
1035
+ cm_array = [cm[:body], cm[:body_selected], cm[:result]]
1036
+ methods = cm.methods
1037
+ cm_array << (methods.include?(:end_select_proc) ? cm[:end_select_proc] : nil)
1038
+ choices.push(cm_array)
1039
+ end
1040
+ }
1041
+ return self if choices.length == 0
1042
+
1043
+ @pre_command.each{|proc| proc.call}
1044
+ @pre_cancel.each{|proc| proc.call}
1045
+ yield if block_given?
1046
+ @command_box.command(@command_box.create_choices_chain(choices, &chain_block))
1047
+ @result = nil
1048
+ @selecting = true
1049
+ while @selecting
1050
+ @update_inner.call(self)
1051
+ Fiber.yield
1052
+ end
1053
+ @post_cancel.each{|proc| proc.call}
1054
+ @post_command.each{|proc| proc.call}
1055
+ return self
1056
+ end
1057
+
1058
+ def selecting #:nodoc:
1059
+ return unless @selecting
1060
+ return unless @command_box.selecting?
1061
+ @selecting_procs.each{|sp|
1062
+ sp.call(@select_ok, @select_cansel, @select_amount, @mouse_amount)
1063
+ }
1064
+ if @select_ok
1065
+ @result = @command_box.result
1066
+ @command_box.finish_command
1067
+ @text_box.release
1068
+ @selecting = false
1069
+ reset_selecting
1070
+ elsif @select_cancel
1071
+ @result = @cancel
1072
+ @command_box.finish_command
1073
+ @text_box.release
1074
+ @selecting = false
1075
+ reset_selecting
1076
+ elsif @select_amount != [0,0]
1077
+ @command_box.move_cursor(*@select_amount)
1078
+ reset_selecting
1079
+ elsif @mouse_amount
1080
+ @command_box.attach_cursor(*@mouse_amount.to_a)
1081
+ reset_selecting
1082
+ end
1083
+ end
1084
+
1085
+ def reset_selecting #:nodoc:
1086
+ @select_ok = false
1087
+ @select_cancel = false
1088
+ @select_amount = [0, 0]
1089
+ end
1090
+
1091
+ #===コマンドの選択結果を返す
1092
+ #[[Yukiスクリプトとして利用可能]]
1093
+ #コマンド選択の結果を返す。
1094
+ #まだ結果が得られていない場合はnilを得る
1095
+ #プロット処理・コマンド選択が終了していないのに結果を得られるので注意!
1096
+ #返却値:: コマンドの選択結果
1097
+ def select_result
1098
+ return @result
1099
+ end
1100
+
1101
+ #===プロットの処理を待機する
1102
+ #[[Yukiスクリプトとして利用可能]]
1103
+ #指定の秒数(少数可)、プロットの処理を待機する。
1104
+ #待機中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
1105
+ #Yuki#updateが呼び出されても待機中の場合は、再び上記の処理を繰り返す
1106
+ #_length_:: 待機する長さ。単位は秒。少数可。
1107
+ #返却値:: 自分自身を返す
1108
+ def wait(length)
1109
+ @waiting_timer = WaitCounter.new(length)
1110
+ @waiting_timer.start
1111
+ @waiting = true
1112
+ while @waiting
1113
+ @update_inner.call(self)
1114
+ Fiber.yield
1115
+ end
1116
+ return self
1117
+ end
1118
+
1119
+ def waiting #:nodoc:
1120
+ return if @waiting_timer.waiting?
1121
+ @waiting = false
1122
+ end
1123
+
1124
+ #===シナリオ上の括り(ページ)を実装する
1125
+ #[[Yukiスクリプトとして利用可能]]
1126
+ #シナリオ上、「このプロットの明示的な範囲」を示すために使用する(セーブ時の再現位置の指定など)
1127
+ #Yuki#select_first_pageメソッドで開始位置が指定されている場合、以下の処理を行う。
1128
+ #(1)select_first_pageメソッドで指定されたページから処理する。それまでのページは無視される
1129
+ #(2)開始ページを処理する前に、select_first_pageメソッドの内容をクリアする(nilに変更する)
1130
+ #このメソッドはブロックが必須。ブロックがないと例外が発生する。
1131
+ #_name_:: ページ名。select_first_pageメソッドは、この名前を検索する。また、now_pageメソッドの返却値でもある
1132
+ #_use_pause_::ページの処理が終了した後、必ずpauseメソッドを呼び出すかどうかのフラグ。デフォルトはtrue
1133
+ #返却値:: select_first_pageメソッドで指定されていないページのときはnil、指定されているページの場合は引数nameの値
1134
+ def page(name, use_pause = true)
1135
+ raise MiyakoProcError, "Yuki#page needs block!" unless block_given?
1136
+ return nil if (@first_page && name != @first_page)
1137
+ @first_page = nil
1138
+ @now_page = name
1139
+ yield
1140
+ pause if use_pause
1141
+ @now_page = nil
1142
+ return name
1143
+ end
1144
+
1145
+ #===シナリオ上の現在のページを返す
1146
+ #[[Yukiスクリプトとして利用可能]]
1147
+ #呼び出し当時、シナリオ上、pageメソッドでくくられていない場合は、nilを返す
1148
+ #返却値:: ページ名
1149
+ def now_page
1150
+ return @now_page
1151
+ end
1152
+
1153
+ #===プロット上の最初に実行するページを指定知る
1154
+ #[[Yukiスクリプトとして利用可能]]
1155
+ #但し、ページ名を指定しないときはnilを指定する。
1156
+ #_name_:: 最初に実行するページ名
1157
+ def select_first_page(name)
1158
+ @first_page = name
1159
+ end
1160
+
1161
+ #===インスタンスで使用しているオブジェクトを解放する
1162
+ def dispose
1163
+ @update_inner = nil
1164
+ @update_text = nil
1165
+ @update_cr = nil
1166
+ @update_clear = nil
1167
+
1168
+ @executing_fiber = nil
1169
+
1170
+ @parts.clear
1171
+ @parts = nil
1172
+ @visibles.clear
1173
+ @visibles = nil
1174
+ @vars.clear
1175
+ @vars = nil
1176
+
1177
+ @is_outer_height = nil
1178
+ end
1179
+ end
1180
+ end