OSDN Git Service

fix cmake/Macros.cmake
[moflib/moflib.git] / moflib-1.0 / src / mof / script / Environment.cpp
1 #pragma once
2 #include <mof/script/Environment.hpp>
3 #include <mof/ConsoleIO.hpp>
4 #include "mof/EventScheduler.hpp"
5 #include "mof/OnceEventCondition.hpp"
6 #include "mof/KeyPressedEventCondition.hpp"
7 #include <mof/widgets.hpp>
8 #include <mof/streams.hpp>
9 #include <mof/Matrix3D.hpp>
10 #include <mof/Sprite.hpp>
11 #include <mof/script/ObjectData.hpp>
12 #include <mof/utilities.hpp>
13 #include <boost/bind.hpp>
14 #include <boost/format.hpp>
15 #include <boost/algorithm/string.hpp>
16 #include <mof/sound/SoundDevice.hpp>
17 #include <vector>
18 #include <memory>
19         
20 namespace mof
21 {
22 namespace script
23 {
24 //{{{ Impl
25         struct Environment::Impl
26         {
27                 bool waiting_;                  ///< Interpreterにコマンド実行の停止を伝えるための状態変数
28                 mof::EventScheduler scheduler_; ///< キー入力待機など
29         std::shared_ptr<mof::InputReceiver> input_;
30                 std::vector<std::shared_ptr<mof::script::MessageData>> message_data_list_;
31                 std::vector<std::shared_ptr<mof::script::MenuData>> menu_data_list_;
32                 std::vector<std::shared_ptr<mof::script::SoundData>> sound_data_list_;
33                 std::vector<mof::script::PictureData::ptr> picture_data_list_;
34                 std::vector<mof::script::ParticlegenData::ptr> particlegen_data_list_;
35                 std::map<std::string, int> property_map_;
36                 
37                 Impl(std::shared_ptr<mof::InputReceiver> input)
38                         : waiting_(false), input_(input)
39                 {
40                 }
41
42                 void setWaiting(bool waiting)
43                 {
44                         waiting_ = waiting;
45                 }
46
47         };
48 //}}}
49 //{{{ constructor
50         Environment::Environment(std::shared_ptr<mof::InputReceiver> input)
51         : impl_(new Impl(input))
52         {
53                 impl_->property_map_["system.menu.move_cursor_sound"] = sound_create(_T("sound/move_cursor.wav"));
54         }
55 //}}}
56 //{{{ destructor
57         Environment::~Environment()
58         {
59         }
60 //}}}
61 //{{{ message_create
62         int Environment::message_create(const mof::tstring& title, const GameData::entry_t& style)
63         {
64                 using namespace mof::script;
65                 using namespace boost;
66
67                 DEBUG_PRINT("message_create(" << title << ")");
68                 std::shared_ptr<MessageData> data = std::shared_ptr<MessageData>(create_message_data(title, style).release());
69                 impl_->message_data_list_.push_back(data);// TODO 再利用
70                 return impl_->message_data_list_.size() -1;
71         }
72 //}}}   
73 //{{{ massage_next
74         int Environment::message_next(int id, const tstring& text)
75         {
76                 DEBUG_PRINT("message_next(" << id << "," << text << ")");
77                 std::shared_ptr<mof::script::MessageData>& data = impl_->message_data_list_.at(id);
78                 data->message_->addPage(text);
79                 return data->message_->nextPage();
80         }
81 //}}}
82 //{{{ menu_create
83         int Environment::menu_create
84         (
85                 const mof::tstring& title,
86                 const std::vector<mof::tstring>& items,
87                 const GameData::entry_t& style
88         )
89         {
90                 using namespace mof::script;
91                 using namespace boost;
92
93                 DEBUG_PRINT("menu_create(" << title << ")");
94                 std::shared_ptr<MenuData> data = std::shared_ptr<MenuData>(create_menu_data(title, items, style).release());
95                 impl_->menu_data_list_.push_back(data);
96                 return impl_->menu_data_list_.size() -1;
97         }
98 //}}}   
99 //{{{ menu_move_cursor
100         int Environment::menu_move_cursor(int id, MoveDirection direction)
101         {
102                 using namespace mof::script;
103                 using namespace boost;
104
105                 DEBUG_PRINT(format("menu_move_cursor(%d, %d)") % id % direction);
106                 auto& data = impl_->menu_data_list_.at(id);
107                 auto& sound_data = impl_->sound_data_list_.at(impl_->property_map_["system.menu.move_cursor_sound"]);
108                 int prev_index = data->menu_->getSelectedIndex();
109                 mof::FrameNumber period;
110                 switch (direction) {
111                         case MOVE_UP : 
112                                 period = data->menu_->up();
113                                 break;
114                         case MOVE_DOWN : 
115                                 period = data->menu_->down();
116                                 break;
117                         case MOVE_LEFT : 
118                                 period = data->menu_->left();
119                                 break;
120                         case MOVE_RIGHT : 
121                                 period = data->menu_->right();
122                                 break;
123                         default:
124                                 return 0;
125                 }
126                 if (data->menu_->getSelectedIndex() != prev_index) {
127                         sound_data->sound_->stop();
128                         sound_data->sound_->play(sound_data->streaming_);
129                 }
130                 return period;
131         }
132 //}}}   
133 //{{{ menu_select
134         int Environment::menu_select(int id)
135         {
136                 using namespace mof::script;
137                 using namespace boost;
138
139                 DEBUG_PRINT(format("menu_select(%d)") % id);
140                 auto& data = impl_->menu_data_list_.at(id);
141                 return data->menu_->performAction();
142         }
143 //}}}   
144 //{{{ menu_get_current
145         int Environment::menu_get_current(int id)
146         {
147                 using namespace mof::script;
148                 using namespace boost;
149
150                 DEBUG_PRINT(format("menu_get_current(%d)") % id);
151                 auto& data = impl_->menu_data_list_.at(id);
152                 DEBUG_PRINT(data->menu_->getSelectedIndex());
153                 return data->menu_->getSelectedIndex();
154         }
155 //}}}   
156 //{{{ wait_for_key
157         void Environment::wait_for_key(mof::InputReceiver::Key key)
158         {
159                 DEBUG_PRINT("wait_for_key(" << key << ")");
160                 bool& waiting = impl_->waiting_;
161         impl_->scheduler_.addEvent
162         (
163             new mof::OnceEventCondition(new mof::KeyPressedEventCondition(key, impl_->input_)), 
164                         [&waiting](){waiting = false;}
165         );
166                 impl_->waiting_ = true;
167         }
168 //}}}
169 //{{{ wait_frame
170         void Environment::wait_frame(size_t frame)
171         {
172                 DEBUG_PRINT("wait_frame(" << frame << ")");
173                 if (frame == 0)return;
174                 bool& waiting = impl_->waiting_;
175                 impl_->scheduler_.addEvent(frame, [&waiting](){waiting = false;});// set waiting_ false after 'frame' 
176                 impl_->waiting_ = true;
177         }
178 //}}}
179 //{{{ get_last_key
180         mof::InputReceiver::Key Environment::get_last_key()
181         {
182                 //TODO 複数同時をtimestampで識別
183                 DEBUG_PRINT("get_last_key()");
184                 for (int key = mof::InputReceiver::BEGIN + 1; key < mof::InputReceiver::ANY; ++key) {
185                         if (impl_->input_->testKeyState(static_cast<mof::InputReceiver::Key>(key))) {
186                                 return static_cast<mof::InputReceiver::Key>(key);// 最初に見つかったものを選ぶ
187                         }
188                 }
189                 return mof::InputReceiver::END;// 何も入力されていないとき
190         }
191 //}}}
192 //{{{ sound_create
193         int Environment::sound_create(const mof::tstring& filepath)
194         {
195                 using namespace mof::script;
196                 using namespace boost;
197
198                 //TODO キャッシュ
199                 
200                 DEBUG_PRINT("sound_create(" << filepath << ")");
201                 auto ptr = mof::sound::SoundDevice::create_static_sound(filepath);
202                 //TODO 分岐
203                 auto data = std::make_shared<SoundData>();
204                 data->sound_ = std::shared_ptr<mof::SoundBuffer>(ptr.release());
205                 data->streaming_ = false;
206                 impl_->sound_data_list_.push_back(data);
207                 return impl_->sound_data_list_.size() -1;
208         }
209 //}}}   
210 //{{{ sound_play
211         void Environment::sound_play(int id)
212         {
213                 using namespace mof::script;
214                 using namespace boost;
215
216                 DEBUG_PRINT("sound_play(" << id << ")");
217                 impl_->sound_data_list_.at(id)->sound_->play(false);
218         }
219 //}}}   
220 //{{{ load_game_data
221         GameData::ptr Environment::load_game_data(const mof::tstring& resource_path)
222         {
223                 return get_game_data(resource_path);
224         }
225 //}}}   
226 //{{{ print_debug
227         void Environment::print_debug(const mof::tstring& message)
228         {
229                 DEBUG_PRINT(message);
230         }
231 //}}}
232 //{{{ picture_create
233         int Environment::picture_create(const mof::tstring& filepath)
234         {
235                 using namespace mof::script;
236                 using namespace boost;
237
238                 DEBUG_PRINT("picture_create(" << filepath << ")");
239                 auto data = std::make_shared<PictureData>();
240                 data->sprite_ = 
241                         std::make_shared<Sprite>
242                         (
243                                 std::make_shared<mof::Texture>(filepath),
244                                 mof::Rectangle<mof::real>(0, 0, 1, 1)
245                         );
246                 impl_->picture_data_list_.push_back(data);// TODO 再利用
247                 return impl_->picture_data_list_.size() -1;
248
249         }
250 //}}}   
251 //{{{ particlegen_create
252         int Environment::particlegen_create()
253         {
254                 using namespace mof::script;
255                 using namespace boost;
256
257                 DEBUG_PRINT("particlegen_create()");
258                 //DEBUG_PRINT("picture_create(" << filepath << ")");
259                 auto data = std::make_shared<ParticlegenData>();
260                 data->particlegen_ = std::make_shared<mof::particlegen>();
261                 data->particlegen_->world_transform() << data->position_ref_.makeRef(Matrix3D::createIdentity());
262                 impl_->particlegen_data_list_.push_back(data);// TODO 再利用
263                 return impl_->particlegen_data_list_.size() -1;
264
265         }
266 //}}}   
267 // methods for common objects 
268 //{{{ show
269 int Environment::show(int id, const mof::tstring& class_path)
270 {
271                 using namespace mof::script;
272                 using namespace boost;
273
274                 if (class_path == "menu") {
275                         DEBUG_PRINT("menu_show(" << id << ")");
276                         std::shared_ptr<MenuData>& data = impl_->menu_data_list_.at(id);
277                         return data->frame_->show();
278                 }
279                 else if (class_path == "message") {
280                         DEBUG_PRINT("message_show(" << id << ")");
281                         std::shared_ptr<mof::script::MessageData>& data = impl_->message_data_list_.at(id);
282                         return data->frame_->show();
283                 }
284                 else throw std::invalid_argument("unknown class path:" + class_path);
285 }
286 //}}}
287 //{{{ hide
288 int Environment::hide(int id, const mof::tstring& class_path)
289 {
290                 using namespace mof::script;
291                 using namespace boost;
292
293                 if (class_path == "menu") {
294                         DEBUG_PRINT("menu_hide(" << id << ")");
295                         std::shared_ptr<MenuData>& data = impl_->menu_data_list_.at(id);
296                         return data->frame_->hide();
297                 }
298                 else if (class_path == "message") {
299                         DEBUG_PRINT("message_hide(" << id << ")");
300                         std::shared_ptr<mof::script::MessageData>& data = impl_->message_data_list_.at(id);
301                         return data->frame_->hide();
302                 }
303                 else throw std::invalid_argument("unknown class path:" + class_path);
304 }
305 //}}}
306 //{{{ dispose
307 void Environment::dispose(int id, const mof::tstring& class_path)
308 {
309                 using namespace mof::script;
310                 using namespace boost;
311
312                 if (class_path == "menu") {
313                         DEBUG_PRINT("menu_dispose(" << id << ")");
314                         impl_->menu_data_list_.at(id) = std::shared_ptr<MenuData>();// NULLに設定
315                 }
316                 else if (class_path == "message") {
317                         DEBUG_PRINT("message_dispose(" << id << ")");
318                         impl_->message_data_list_.at(id) = std::shared_ptr<MessageData>();// NULLに設定
319                 }
320                 else if (class_path == "picture") {
321                         DEBUG_PRINT("picture_dispose(" << id << ")");
322                         impl_->picture_data_list_.at(id) = std::shared_ptr<PictureData>();// NULLに設定
323                 }
324                 else if (class_path == "particlegen") {
325                         DEBUG_PRINT("particlegen_dispose(" << id << ")");
326                         impl_->particlegen_data_list_.at(id) = std::shared_ptr<ParticlegenData>();// NULLに設定
327                 }
328                 else if (class_path == "sound") {
329                         DEBUG_PRINT("sound_dispose(" << id << ")");
330                         impl_->sound_data_list_.at(id) = std::shared_ptr<SoundData>();// NULLに設定
331                 }
332                 else throw std::invalid_argument("unknown class path:" + class_path);
333 }
334 //}}}
335 //{{{ get_properties
336         GameData::ptr Environment::get_properties(int id, const mof::tstring& class_path)
337         {
338                 using namespace mof::script;
339                 using namespace boost;
340                 GameData::ptr game_data = std::make_shared<GameData>();
341                 game_data->data_.resize(1);
342                 GameData::entry_t& e = game_data->data_.front();
343
344                 if (class_path == "menu") {
345                         DEBUG_PRINT("get_property(" << id << class_path << ")");
346                         std::shared_ptr<MenuData>& data = impl_->menu_data_list_.at(id);
347                         Vector2D v = data->frame_->getView()->getPreferredSize();
348                         e["preferred_size"] = (format("%d,%d") % v.x % v.y).str();
349                         Vector2D pos = data->frame_->getView()->getPositionStream().value();
350                         e["position2"] = (format("%d,%d") % pos.x % pos.y).str();
351                 }
352                 else if (class_path == "message") {
353                         DEBUG_PRINT("get_property(" << id << class_path << ")");
354                         std::shared_ptr<MessageData>& data = impl_->message_data_list_.at(id);
355                         Vector2D v = data->frame_->getView()->getPreferredSize();
356                         e["preferred_size"] = (format("%d,%d") % v.x % v.y).str();
357                         Vector2D pos = data->frame_->getView()->getPositionStream().value();
358                         e["position2"] = (format("%d,%d") % pos.x % pos.y).str();
359                 }
360                 else if (class_path == "picture") {
361                         DEBUG_PRINT("get_property(" << id << class_path << ")");
362                         std::shared_ptr<PictureData>& data = impl_->picture_data_list_.at(id);
363                         Vector2D v = data->sprite_->getPreferredSize();
364                         e["preferred_size"] = (format("%d,%d") % v.x % v.y).str();
365                         Vector2D pos = data->sprite_->getPositionStream().value();
366                         e["position2"] = (format("%d,%d") % pos.x % pos.y).str();
367                 }
368
369                 else throw std::invalid_argument("unknown class path:" + class_path);
370
371                 return game_data;
372         }
373 //}}}
374 //{{{ set_color_behavior
375         void Environment::set_color_behavior(int id, const mof::tstring& class_path, const Manipulator<Color4f>::ptr& seq, mof::FrameNumber period)
376         {
377                 using namespace boost::algorithm;
378                 DEBUG_PRINT("set_color_behavior(" << ")");      
379
380                 std::vector<mof::tstring> splited_list;
381                 split(splited_list, class_path, is_any_of("."));
382                 if (splited_list.front() == "picture") {
383                         auto picture = impl_->picture_data_list_.at(id);
384                         picture->sprite_->setColorStream(ColorStream(seq));
385                         return;
386                 }
387                 else if (splited_list.front() == "menu") {
388                         if (splited_list.at(1) == "open") {
389                                 auto menu = impl_->menu_data_list_.at(id);
390                                 menu->frame_->setBehaviorOnColor(mof::widget::Frame::FRAME_OPEN, seq, period);
391                                 return;
392                         }
393                         else if (splited_list.at(1) == "close") {
394                                 auto menu = impl_->menu_data_list_.at(id);
395                                 menu->frame_->setBehaviorOnColor(mof::widget::Frame::FRAME_CLOSE, seq, period);
396                                 return;
397                         }
398
399                 }
400                 else if (splited_list.front() == "message") {
401                         if (splited_list.at(1) == "open") {
402                                 auto message = impl_->message_data_list_.at(id);
403                                 message->frame_->setBehaviorOnColor(mof::widget::Frame::FRAME_OPEN, seq, period);
404                                 return;
405                         }
406                         else if (splited_list.at(1) == "close") {
407                                 auto message = impl_->message_data_list_.at(id);
408                                 message->frame_->setBehaviorOnColor(mof::widget::Frame::FRAME_CLOSE, seq, period);
409                                 return;
410                         }
411
412                 }
413
414
415
416                 throw std::logic_error("unknown class_path:" + class_path);
417         }
418 //}}}
419 //{{{ set_position_behavior
420         void Environment::set_position_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector2D>::ptr& seq, mof::FrameNumber period)
421         {
422                 using namespace boost::algorithm;
423                 DEBUG_PRINT("set_position_behavior(" << ")");   
424
425                 std::vector<mof::tstring> splited_list;
426                 split(splited_list, class_path, is_any_of("."));
427                 if (splited_list.front() == "picture") {
428                         auto picture = impl_->picture_data_list_.at(id);
429                         picture->sprite_->setPositionStream(Vector2DStream(seq));
430                         return;
431                 }
432                 else if (splited_list.front() == "menu") {
433                         if (splited_list.at(1) == "open") {
434                                 auto menu = impl_->menu_data_list_.at(id);
435                                 menu->frame_->setBehaviorOnPosition(mof::widget::Frame::FRAME_OPEN, seq, period);
436                                 return;
437                         }
438                         else if (splited_list.at(1) == "close") {
439                                 auto menu = impl_->menu_data_list_.at(id);
440                                 menu->frame_->setBehaviorOnPosition(mof::widget::Frame::FRAME_CLOSE, seq, period);
441                                 return;
442                         }
443
444                 }
445                 else if (splited_list.front() == "message") {
446                         if (splited_list.at(1) == "open") {
447                                 auto message = impl_->message_data_list_.at(id);
448                                 message->frame_->setBehaviorOnPosition(mof::widget::Frame::FRAME_OPEN, seq, period);
449                                 return;
450                         }
451                         else if (splited_list.at(1) == "close") {
452                                 auto message = impl_->message_data_list_.at(id);
453                                 message->frame_->setBehaviorOnPosition(mof::widget::Frame::FRAME_CLOSE, seq, period);
454                                 return;
455                         }
456                 }
457
458
459                 throw std::logic_error("unknown class_path:" + class_path);
460         }
461 //}}}
462 //{{{ set_position_behavior
463         void Environment::set_position_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector3D>::ptr& seq, mof::FrameNumber period)
464         {
465                 using namespace boost::algorithm;
466                 using namespace mof;
467                 DEBUG_PRINT("set_position_behavior(" << ")");   
468
469                 std::vector<mof::tstring> splited_list;
470                 split(splited_list, class_path, is_any_of("."));
471                 if (splited_list.front() == "particlegen") {
472                         auto p = impl_->particlegen_data_list_.at(id);
473                         p->position_ref_.replace(0, std::make_shared<Translation3D>(seq));
474                         return;
475                 }
476
477
478                 throw std::logic_error("unknown class_path:" + class_path);
479         }
480 //}}}
481 //{{{ set_size_behavior
482         void Environment::set_size_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector2D>::ptr& seq, mof::FrameNumber period)
483         {
484                 using namespace boost::algorithm;
485                 DEBUG_PRINT("set_position_behavior(" << ")");   
486
487                 std::vector<mof::tstring> splited_list;
488                 split(splited_list, class_path, is_any_of("."));
489                 if (splited_list.front() == "picture") {
490                         auto picture = impl_->picture_data_list_.at(id);
491                         picture->sprite_->setSizeStream(Vector2DStream(seq));
492                         return;
493                 }
494                 else if (splited_list.front() == "menu") {
495                         if (splited_list.at(1) == "open") {
496                                 auto menu = impl_->menu_data_list_.at(id);
497                                 menu->frame_->setBehaviorOnSize(mof::widget::Frame::FRAME_OPEN, seq, period);
498                                 return;
499                         }
500                         else if (splited_list.at(1) == "close") {
501                                 auto menu = impl_->menu_data_list_.at(id);
502                                 menu->frame_->setBehaviorOnSize(mof::widget::Frame::FRAME_CLOSE, seq, period);
503                                 return;
504                         }
505
506                 }
507                 else if (splited_list.front() == "message") {
508                         if (splited_list.at(1) == "open") {
509                                 auto message = impl_->message_data_list_.at(id);
510                                 message->frame_->setBehaviorOnSize(mof::widget::Frame::FRAME_OPEN, seq, period);
511                                 return;
512                         }
513                         else if (splited_list.at(1) == "close") {
514                                 auto message = impl_->message_data_list_.at(id);
515                                 message->frame_->setBehaviorOnSize(mof::widget::Frame::FRAME_CLOSE, seq, period);
516                                 return;
517                         }
518                 }
519
520                 throw std::logic_error("unknown class_path:" + class_path);
521         }
522 //}}}
523
524 //{{{ update
525         void Environment::update()
526         {
527                 using namespace mof::script;
528                 using namespace std;
529                 impl_->scheduler_.update();
530                 foreach (auto data, impl_->message_data_list_) {
531                         if (data.get()) data->frame_->update();
532                 }
533                 foreach (auto data, impl_->menu_data_list_) {
534                         if (data.get()) data->frame_->update(); 
535                 }
536                 foreach (auto data, impl_->sound_data_list_) {
537                         if (data.get()) data->sound_->update(); 
538                 }
539
540                 foreach (auto data, impl_->picture_data_list_) {
541                         if (data.get()) data->sprite_->update(); 
542                 }
543
544                 foreach (auto data, impl_->particlegen_data_list_) {
545                         if (data) data->particlegen_->update(); 
546                 }
547
548
549         }
550 //}}}
551 //{{{ draw
552         void Environment::draw() const
553         {
554                 using namespace mof::script;
555                 using namespace std;
556                 
557                 mof::GraphicsDevice::setAlphaBlendingMode(mof::GraphicsDevice::BLENDING_MODE_ADD);
558                 mof::GraphicsDevice::setZBuffer(false);
559                 foreach (auto& data, impl_->particlegen_data_list_) {
560                         if (data) {
561                                 auto& list = data->particlegen_->drawables(); 
562                                 foreach (auto p, list) p->draw();
563                         }
564
565                 }
566                 mof::GraphicsDevice::setZBuffer(true);
567                 mof::GraphicsDevice::setAlphaBlendingMode(mof::GraphicsDevice::BLENDING_MODE_ALPHA);
568
569                 foreach (auto data, impl_->picture_data_list_) {
570                         if (data.get()) data->sprite_->draw();
571                 }
572
573
574                 foreach (auto data,  impl_->message_data_list_) {
575                         if (data.get()) data->frame_->getView()->draw();
576                 }
577                 
578                 foreach (auto data, impl_->menu_data_list_) {
579                         if (data.get()) data->frame_->getView()->draw();
580                 }//TODO ソート
581         
582                 
583         }
584 //}}}
585 //{{{ isWaiting
586         bool Environment::isWaiting() const
587         {
588                 return impl_->waiting_;
589         }
590 //}}}
591 }
592 }