• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

修訂98c546100a61b099940000a22a7db0f1d710e446 (tree)
時間2012-10-28 21:59:03
作者h2so5 <h2so5@git....>
Commiterh2so5

Log Message

起動時にステージモデルをキャッシュする機能を追加
ModelHandle2をModelHandleに改名

Change Summary

差異

--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,4 @@ log_*.txt
3737 /client/bin/log
3838 /client/bin/Log.txt
3939 /client/bin/user
40+/client/bin/cache
--- a/client/3d/FieldPlayer.cpp
+++ b/client/3d/FieldPlayer.cpp
@@ -211,10 +211,6 @@ void FieldPlayer::SetModel(const ModelHandle& model)
211211
212212 void FieldPlayer::Update()
213213 {
214- if (loading_model_handle_ && loading_model_handle_.CheckLoaded()) {
215- SetModel(loading_model_handle_);
216- loading_model_handle_ = ModelHandle();
217- }
218214
219215 // 落ちた時に強制復帰
220216 if (prev_stat_.pos.y < (*stage_)->min_height()) {
Binary files a/client/3d/FieldPlayer.hpp and b/client/3d/FieldPlayer.hpp differ
--- a/client/3d/PlayerCharacter.cpp
+++ b/client/3d/PlayerCharacter.cpp
@@ -236,7 +236,6 @@ public:
236236 }
237237
238238 // 床へのめり込みを防止
239- float floor_y;
240239 std::pair<bool, VECTOR> floor_coll;
241240 // 足で接地検査
242241 floor_coll = (*stage_)->FloorExists(moved_pos,model_height_,0);
--- a/client/3d/Stage.cpp
+++ b/client/3d/Stage.cpp
@@ -9,7 +9,7 @@
99 #include <string>
1010
1111 Stage::Stage(const ChannelPtr& channel,const ConfigManagerPtr &config_manager) :
12- map_handle_(ResourceManager::LoadModelFromName2(unicode::ToTString(channel->stage))),
12+ map_handle_(ResourceManager::LoadModelFromName(unicode::ToTString(channel->stage))),
1313 map_scale_(map_handle_.property().get<float>("scale", 20.0)),
1414 min_height_(map_handle_.property().get<float>("min_height", -200.0)),
1515 host_change_flag_(false),
@@ -320,7 +320,7 @@ void Stage::UpdateSkymapPosition(const VECTOR& pos)
320320 MV1SetPosition(skymap_handle_.handle(), VGet(pos.x, 800, pos.z));
321321 }
322322
323-const ModelHandle2& Stage::map_handle() const
323+const ModelHandle& Stage::map_handle() const
324324 {
325325 return map_handle_;
326326 }
--- a/client/3d/Stage.hpp
+++ b/client/3d/Stage.hpp
@@ -34,7 +34,7 @@ class Stage {
3434 bool IsVisiblePoint(const VECTOR& point) const;
3535 bool IsNearPoint(const VECTOR& point) const;
3636
37- const ModelHandle2& map_handle() const;
37+ const ModelHandle& map_handle() const;
3838 const ModelHandle& skymap_handle() const;
3939 float map_scale() const;
4040 float min_height() const;
@@ -50,13 +50,12 @@ class Stage {
5050 ConfigManagerPtr config_manager() const;
5151
5252 private:
53- ModelHandle2 map_handle_;
53+ ModelHandle map_handle_;
54+ ModelHandle skymap_handle_;
5455 float map_scale_;
5556 float min_height_;
5657
5758 std::unordered_set<int> draw_after_meshes_;
58-
59- ModelHandle skymap_handle_;
6059 std::vector<ModelHandle> warpobj_handles_;
6160
6261 std::vector<VECTOR> start_points_;
--- a/client/ResourceManager.cpp
+++ b/client/ResourceManager.cpp
@@ -4,11 +4,23 @@
44
55 #include <fstream>
66 #include <boost/filesystem.hpp>
7+#include <boost/crc.hpp>
78 #include "ResourceManager.hpp"
89 #include "../common/Logger.hpp"
910 #include "../common/unicode.hpp"
1011 #include "Music.hpp"
1112
13+
14+// MV1書き出し関数
15+namespace DxLib
16+{
17+extern int MV1SaveModelToMV1File( int MHandle, const char *FileName,
18+ int SaveType = ((0x0001) | (0x0002)), int AnimMHandle = -1,
19+ int AnimNameCheck = TRUE, int Normal8BitFlag = 1,
20+ int Position16BitFlag = 1, int Weight8BitFlag = 0,
21+ int Anim16BitFlag = 1 );
22+};
23+
1224 ResourceManager::MemoryPool ResourceManager::mempool;
1325
1426 const static TCHAR* CHAT_FONT_NAME = _T("UmePlus P Gothic");
@@ -109,10 +121,10 @@ std::vector<std::string> ResourceManager::model_name_list_;
109121 ptree ResourceManager::model_name_tree_;
110122 void ResourceManager::BuildModelFileTree()
111123 {
112- using namespace boost::filesystem;
113- using namespace std;
124+ using namespace boost::filesystem;
125+ using namespace std;
114126
115- model_name_tree_.clear();
127+ model_name_tree_.clear();
116128 model_name_list_.clear();
117129
118130 std::function<void(const path& p)> search_dir;
@@ -120,51 +132,55 @@ void ResourceManager::BuildModelFileTree()
120132
121133 using namespace boost::filesystem;
122134
123- if (exists(p) && is_directory(p)) {
124- for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) {
125- if (is_directory(*it_dir)) {
126- path json_path = it_dir->path() / "info.json";
127- if (exists(json_path)) {
128-
129- path model_path;
130- for (auto it = directory_iterator(*it_dir); it != directory_iterator(); ++it) {
131- auto extension = it->path().extension().string();
132-
133- if (extension == ".mv1" || extension == ".x"
134- || extension == ".pmd" || extension == ".pmx") {
135- model_path = it->path();
136- break;
137- }
138- }
139-
140- if (!model_path.empty()) {
141- ptree pt_json;
142- read_json(json_path.string(), pt_json);
135+ if (exists(p) && is_directory(p)) {
136+ for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) {
137+ if (is_directory(*it_dir)) {
138+ path json_path = it_dir->path() / "info.json";
139+ if (exists(json_path)) {
140+
141+ path model_path;
142+ for (auto it = directory_iterator(*it_dir); it != directory_iterator(); ++it) {
143+ auto extension = it->path().extension().string();
144+
145+ if (extension == ".mv1" || extension == ".x"
146+ || extension == ".pmd" || extension == ".pmx") {
147+ model_path = it->path();
148+ break;
149+ }
150+ }
151+
152+ if (!model_path.empty()) {
153+ ptree pt_json;
154+ read_json(json_path.string(), pt_json);
143155 MergePtree(&pt_json, GetDefaultInfoJSON());
144156
145- std::string name = pt_json.get<std::string>("name", "");
146- pt_json.put<std::string>("modelpath", unicode::sjis2utf8(model_path.string()));
157+ std::string name = pt_json.get<std::string>("name", "");
158+ auto model_path_str = unicode::sjis2utf8(model_path.string());
159+
160+ pt_json.put<std::string>("modelpath", model_path_str);
147161 if (!name.empty()) {
148162 model_name_list_.push_back(name);
149- }
163+ model_name_tree_.put_child(ptree::path_type(name + ":_info_", ':'), pt_json);
150164
151- if (name.size() > 0) {
152- model_name_tree_.put_child(ptree::path_type(name + ":_info_", ':'), pt_json);
153- }
154- }
155- } else {
165+ // ステージデータをキャッシュ
166+ if (name.find("stage:") == 0) {
167+ CreateModelCache(model_path_str, pt_json);
168+ }
169+ }
170+ }
171+ } else {
156172 search_dir(it_dir->path());
157173 }
158- }
159- }
160- }
174+ }
175+ }
176+ }
161177 };
162178
163- try {
179+ try {
164180 search_dir("./models");
165- } catch (const filesystem_error& ex) {
166- Logger::Error(_T("%s"), unicode::ToTString(ex.what()));
167- }
181+ } catch (const filesystem_error& ex) {
182+ Logger::Error(_T("%s"), unicode::ToTString(ex.what()));
183+ }
168184
169185 }
170186
@@ -272,6 +288,49 @@ void SetMotionNames(int handle, const ReadFuncData& funcdata)
272288 }
273289 }
274290
291+std::string ResourceManager::GetCacheFilename(const ptree& info, const std::shared_ptr<char>& fileimage, int filesize)
292+{
293+ boost::crc_32_type crc;
294+ crc.process_block(static_cast<void*>(fileimage.get()),
295+ static_cast<void*>(fileimage.get() + filesize));
296+
297+ boost::crc_32_type crc_info;
298+ std::stringstream stream;
299+ boost::archive::text_oarchive oa(stream);
300+ oa << info;
301+ while(stream.good()) {
302+ crc_info.process_byte(stream.get());
303+ }
304+
305+ auto cache_filename = "./cache/" +
306+ boost::lexical_cast<std::string>(crc.checksum()) + "_" +
307+ boost::lexical_cast<std::string>(crc_info.checksum()) +
308+ ".mv1";
309+
310+ return cache_filename;
311+}
312+
313+void ResourceManager::CreateModelCache(std::string filepath, const ptree& info)
314+{
315+ auto funcdata = std::make_shared<ReadFuncData>(info);
316+
317+ std::shared_ptr<char> fileimage;
318+ int filesize;
319+
320+ LoadFile(unicode::ToTString(filepath).c_str(), &fileimage, &filesize );
321+ auto cache_filename = GetCacheFilename(info, fileimage, filesize);
322+
323+ if (!boost::filesystem::exists(cache_filename)) {
324+ int handle = MV1LoadModelFromMem(fileimage.get(), filesize, FileReadFunc, FileReleaseFunc, &(*funcdata));
325+
326+ if (!boost::filesystem::exists("./cache")) {
327+ boost::filesystem::create_directory("./cache");
328+ }
329+ MV1SaveModelToMV1File(handle, cache_filename.c_str());
330+ MV1DeleteModel(handle);
331+ }
332+}
333+
275334 void ResourceManager::RequestModelFromName(const tstring& name)
276335 {
277336 if (!IsCachedModelName(name)) {
@@ -293,7 +352,7 @@ ReadFuncData::ReadFuncData(const ptree& info)
293352 {
294353 tstring filepath = unicode::ToTString(info.get<std::string>("modelpath", ""));
295354 auto path = boost::filesystem::wpath(unicode::ToWString(filepath));
296- model_dir = path.parent_path();
355+ model_dir = path.parent_path();
297356
298357 if (path.extension() == _T(".pmd") || path.extension() == _T(".pmx")) {
299358 auto motions_array = info.get_child("character.motions", ptree());
@@ -345,61 +404,13 @@ ReadFuncData::ReadFuncData(const ptree& info)
345404 }
346405 }
347406 }
348- motions_it = motions.begin();
407+ motions_it = motions.begin();
349408 }
350409
351410 std::unordered_map<std::string, std::string> ResourceManager::set_motions_ = std::unordered_map<std::string, std::string>();
352411 float ResourceManager::model_edge_size_ = 1.0f;
353-ModelHandle ResourceManager::LoadModelFromName(const tstring& name)
354-{
355- auto fullpath = ptree::path_type(unicode::ToString(NameToFullPath(name)), ':');
356- ptree p = model_name_tree_.get_child(fullpath, ptree());
357-
358- ptree info = p.get_child("_info_", ptree());
359- tstring filepath = unicode::ToTString(info.get<std::string>("modelpath", ""));
360- if(!filepath.size())
361- {
362- fullpath = ptree::path_type(unicode::ToString(NameToFullPath(UNKNOWN_MODEL_NAME)), ':');
363- p = model_name_tree_.get_child(fullpath, ptree());
364- info = p.get_child("_info_", ptree());
365- filepath = unicode::ToTString(info.get<std::string>("modelpath", ""));
366- }
367- if (filepath.size() > 0) {
368- auto it = model_handles_.find(unicode::ToTString(filepath));
369- if (it != model_handles_.end()) {
370- return it->second.Clone();
371- }else{
372- auto funcdata = std::make_shared<ReadFuncData>(info);
373- set_motions_ = funcdata->set_motions;
374-
375- //void *FileImage ;
376- std::shared_ptr<char> FileImage;
377- int FileSize ;
378-
379- LoadFile(unicode::ToTString(filepath).c_str(), &FileImage, &FileSize );
380-
381- int handle = MV1LoadModelFromMem( FileImage.get(), FileSize, FileReadFunc, FileReleaseFunc, &(*funcdata));
382-
383- auto material_num = MV1GetMaterialNum(handle);
384- for(int i = 0; i < material_num; ++i){
385- MV1SetMaterialType(handle,i,DX_MATERIAL_TYPE_TOON_2);
386- }
387412
388-
389- SetMotionNames(handle, *funcdata);
390-
391- auto model_handle = ModelHandle(handle, funcdata, std::make_shared<ptree>(info));
392- model_handles_[unicode::ToTString(filepath)] = model_handle;
393-
394- Logger::Debug(_T("Model %d"), handle);
395- return model_handle.Clone();
396- }
397- } else {
398- return ModelHandle();
399- }
400-}
401-
402-ModelHandle2 ResourceManager::LoadModelFromName2(const tstring& name)
413+ModelHandle ResourceManager::LoadModelFromName(const tstring& name)
403414 {
404415 auto fullpath = ptree::path_type(unicode::ToString(NameToFullPath(name)), ':');
405416 ptree p = model_name_tree_.get_child(fullpath, ptree());
@@ -416,16 +427,23 @@ ModelHandle2 ResourceManager::LoadModelFromName2(const tstring& name)
416427 if (filepath.size() > 0) {
417428 auto it = shared_model_data_.find(unicode::ToTString(filepath));
418429 if (it != shared_model_data_.end()) {
419- return ModelHandle2(it->second);
430+ return ModelHandle(it->second);
420431 }else{
421432 auto funcdata = std::make_shared<ReadFuncData>(info);
422433 set_motions_ = funcdata->set_motions;
423434
424- //void *FileImage ;
425435 std::shared_ptr<char> FileImage;
426- int FileSize ;
436+ int FileSize;
427437
428438 LoadFile(unicode::ToTString(filepath).c_str(), &FileImage, &FileSize );
439+
440+ // キャッシュ読み込み
441+ // モーションなしのモデルでないと上手くいかない
442+ auto cache_filename = GetCacheFilename(info, FileImage, FileSize);
443+ if (boost::filesystem::exists(cache_filename)) {
444+ FileImage.reset();
445+ LoadFile(unicode::ToTString(cache_filename).c_str(), &FileImage, &FileSize);
446+ }
429447
430448 int handle = MV1LoadModelFromMem( FileImage.get(), FileSize, FileReadFunc, FileReleaseFunc, &(*funcdata));
431449
@@ -436,20 +454,22 @@ ModelHandle2 ResourceManager::LoadModelFromName2(const tstring& name)
436454
437455 SetMotionNames(handle, *funcdata);
438456
457+ // CreateModelCache(handle, info, FileImage, FileSize);
458+
439459 SharedModelDataPtr shared_data =
440460 std::make_shared<SharedModelData>(handle, std::make_shared<ptree>(info));
441461
442462 shared_model_data_[unicode::ToTString(filepath)] = shared_data;
443463
444464 Logger::Debug(_T("Model %d"), handle);
445- return ModelHandle2(shared_data);
465+ return ModelHandle(shared_data);
446466 }
447467 } else {
448- return ModelHandle2();
468+ return ModelHandle();
449469 }
450470 }
451471
452-void ResourceManager::ClearModelHandle2()
472+void ResourceManager::ClearModelHandle()
453473 {
454474 std::list<tstring> erase_keys;
455475 BOOST_FOREACH(const auto& it, shared_model_data_) {
@@ -577,71 +597,6 @@ ImageHandle::operator int() const
577597 return handle_;
578598 }
579599
580-ModelHandle::ModelHandle(int handle, const ReadFuncDataPtr& funcdata, const std::shared_ptr<ptree>& property, bool async_load) :
581- handle_(handle),
582- funcdata_(funcdata),
583- property_(property),
584- name_(property_->get<std::string>("name", "")),
585- async_load_(async_load)
586-{
587-
588-}
589-
590-ModelHandle ModelHandle::Clone()
591-{
592- if (CheckHandleASyncLoad(handle_) == TRUE) {
593- return ModelHandle(handle_, funcdata_, property_, true);
594- } else {
595- return ModelHandle(MV1DuplicateModel(handle_), funcdata_, property_);
596- }
597-}
598-
599-bool ModelHandle::CheckLoaded()
600-{
601- if (!async_load_) {
602- return true;
603- } else if (async_load_ && CheckHandleASyncLoad(handle_) == FALSE) {
604- handle_ = MV1DuplicateModel(handle_);
605- SetMotionNames(handle_, *funcdata_);
606- async_load_ = false;
607- return true;
608- } else {
609- return false;
610- }
611-}
612-
613-ModelHandle::operator bool() const
614-{
615- return handle_ != -1;
616-}
617-
618-ModelHandle::ModelHandle() :
619- handle_(-1),
620- property_(std::make_shared<ptree>())
621-{
622-
623-}
624-
625-ModelHandle::~ModelHandle()
626-{
627-
628-}
629-
630-int ModelHandle::handle() const
631-{
632- return handle_;
633-}
634-
635-const ptree& ModelHandle::property() const
636-{
637- return *property_;
638-}
639-
640-std::string ModelHandle::name() const
641-{
642- return name_;
643-}
644-
645600 SharedModelData::SharedModelData(int base_handle, const PtreePtr& property) :
646601 base_handle_(base_handle),
647602 property_(property)
@@ -670,24 +625,34 @@ SharedModelData::~SharedModelData()
670625 MV1DeleteModel(base_handle_);
671626 }
672627
673-ModelHandle2::ModelHandle2(const SharedModelDataPtr& shared_data) :
628+ModelHandle::ModelHandle(const SharedModelDataPtr& shared_data) :
674629 shared_data_(shared_data),
675630 handle_(shared_data->DuplicateHandle())
676631 {
677632
678633 }
679634
680-ModelHandle2::operator bool() const
635+ModelHandle::ModelHandle()
636+{
637+
638+}
639+
640+ModelHandle::operator bool() const
681641 {
682642 return static_cast<bool>(shared_data_);
683643 }
684644
685-int ModelHandle2::handle() const
645+int ModelHandle::handle() const
686646 {
687647 return handle_;
688648 }
689649
690-const ptree& ModelHandle2::property() const
650+const ptree& ModelHandle::property() const
691651 {
692652 return shared_data_->property();
653+}
654+
655+std::string ModelHandle::name() const
656+{
657+ return property().get<std::string>("name", "");
693658 }
\ No newline at end of file
--- a/client/ResourceManager.hpp
+++ b/client/ResourceManager.hpp
@@ -22,7 +22,7 @@ class ModelHandle;
2222 class Music;
2323
2424 class SharedModelData;
25-class ModelHandle2;
25+class ModelHandle;
2626
2727 typedef std::shared_ptr<ImageHandle> ImageHandlePtr;
2828 typedef std::shared_ptr<ModelHandle> ModelHandlePtr;
@@ -106,10 +106,12 @@ class ResourceManager {
106106 // models
107107 static void BuildModelFileTree();
108108 static void CacheBakedModel();
109+
109110 static ModelHandle LoadModelFromName(const tstring&);
111+ static void ClearModelHandle();
110112
111- static ModelHandle2 LoadModelFromName2(const tstring&);
112- static void ClearModelHandle2();
113+ static std::string GetCacheFilename(const ptree& info, const std::shared_ptr<char>& fileimage, int filesize);
114+ static void CreateModelCache(std::string filepath, const ptree& info);
113115
114116 static void RequestModelFromName(const tstring&);
115117 static bool IsCachedModelName(const tstring&);
@@ -171,46 +173,6 @@ class ImageHandle {
171173
172174 };
173175
174-class ModelHandle {
175- friend class ResourceManager;
176-
177- private:
178- ModelHandle(int handle, const ReadFuncDataPtr& funcdata, const std::shared_ptr<ptree>& property, bool async_load = false);
179- ModelHandle Clone();
180-
181- public:
182- ModelHandle();
183- ~ModelHandle();
184-
185- int handle() const;
186- const ptree& property() const;
187- std::string name() const;
188-
189- operator bool() const;
190-
191- bool CheckLoaded();
192-
193- private:
194- int handle_;
195- ReadFuncDataPtr funcdata_;
196- std::shared_ptr<ptree> property_;
197- std::string name_;
198- bool async_load_;
199-
200- public:
201- void *operator new(size_t size)
202- {
203- return tlsf_new(ResourceManager::memory_pool(), size);
204- }
205- void *operator new(size_t, void *p){return p;}
206- void operator delete(void *p)
207- {
208- tlsf_delete(ResourceManager::memory_pool(), p);
209- }
210- void operator delete(void *, void *){};
211-
212-};
213-
214176 typedef std::shared_ptr<ptree> PtreePtr;
215177
216178 class SharedModelData {
@@ -227,12 +189,14 @@ class SharedModelData {
227189 PtreePtr property_;
228190 };
229191
230-class ModelHandle2 {
192+class ModelHandle {
231193 public:
232- ModelHandle2(const SharedModelDataPtr& shared_data = SharedModelDataPtr());
194+ ModelHandle(const SharedModelDataPtr& shared_data);
195+ ModelHandle();
233196 operator bool() const;
234197 int handle() const;
235198 const ptree& property() const;
199+ std::string name() const;
236200
237201 private:
238202 SharedModelDataPtr shared_data_;
--- a/client/scene/ChannelChange.cpp
+++ b/client/scene/ChannelChange.cpp
@@ -17,7 +17,8 @@ ChannelChange::ChannelChange(unsigned char channel, const ManagerAccessorPtr& ma
1717 account_manager_(manager_accessor->account_manager().lock()),
1818 config_manager_(manager_accessor->config_manager().lock()),
1919 player_manager_(manager_accessor->player_manager().lock()),
20- channel_(channel)
20+ channel_(channel),
21+ fade_counter_(0)
2122 {
2223
2324 }
@@ -28,18 +29,7 @@ ChannelChange::~ChannelChange()
2829
2930 void ChannelChange::Begin()
3031 {
31- // 古いステージを削除
32- player_manager_->ResetStage();
33- manager_accessor_->set_world_manager(WorldManagerPtr());
3432
35- ResourceManager::ClearModelHandle2();
36-
37- command_manager_->Write(network::ServerUpdateAccountProperty(CHANNEL, network::Utils::Serialize(channel_)));
38-
39- auto channel_ptr = command_manager_->channels().at(channel_);
40- StagePtr stage = std::make_shared<Stage>(channel_ptr,manager_accessor_->config_manager().lock());
41- world_manager_ = std::make_shared<WorldManager>(stage, manager_accessor_);
42- manager_accessor_->set_world_manager(world_manager_);
4333 }
4434
4535 void ChannelChange::End()
@@ -48,11 +38,22 @@ void ChannelChange::End()
4838
4939 void ChannelChange::Update()
5040 {
51- //if(world_manager_->stage()->host_change_flag())
52- //{
53- //account_manager_->set_host(world_manager_->stage()->host_change_flag().second);
41+ if (fade_counter_ < 120) {
42+ fade_counter_++;
43+ } else {
44+ // 古いステージを削除
45+ player_manager_->ResetStage();
46+ manager_accessor_->set_world_manager(WorldManagerPtr());
47+
48+ command_manager_->Write(network::ServerUpdateAccountProperty(CHANNEL, network::Utils::Serialize(channel_)));
49+
50+ auto channel_ptr = command_manager_->channels().at(channel_);
51+ StagePtr stage = std::make_shared<Stage>(channel_ptr,manager_accessor_->config_manager().lock());
52+ world_manager_ = std::make_shared<WorldManager>(stage, manager_accessor_);
53+ manager_accessor_->set_world_manager(world_manager_);
54+
5455 next_scene_ = std::make_shared<scene::MainLoop>(manager_accessor_);
55- //}
56+ }
5657 }
5758
5859 void ChannelChange::ProcessInput(InputManager* input)
@@ -62,6 +63,13 @@ void ChannelChange::ProcessInput(InputManager* input)
6263
6364 void ChannelChange::Draw()
6465 {
66+ if (fade_counter_ < 120) {
67+ SetDrawBlendMode(DX_BLENDMODE_ALPHA, 255 * fade_counter_ / 120);
68+ int width, height;
69+ GetScreenState(&width, &height, nullptr);
70+ DrawBox(0, 0, width, height, GetColor(0, 0, 0), TRUE);
71+ SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
72+ }
6573 }
6674
6775 }
\ No newline at end of file
--- a/client/scene/ChannelChange.hpp
+++ b/client/scene/ChannelChange.hpp
@@ -31,6 +31,7 @@ class ChannelChange : public Base{
3131 PlayerManagerPtr player_manager_;
3232
3333 unsigned char channel_;
34+ int fade_counter_;
3435 };
3536
3637 }
\ No newline at end of file
--- a/client/scene/MainLoop.cpp
+++ b/client/scene/MainLoop.cpp
@@ -36,7 +36,8 @@ MainLoop::MainLoop(const ManagerAccessorPtr& manager_accessor) :
3636 inputbox_(std::make_shared<InputBox>(manager_accessor_)),
3737 minimap_(std::make_shared<MiniMap>(manager_accessor)),
3838 snapshot_number_(0),
39- snapshot_(false)
39+ snapshot_(false),
40+ fade_counter_(0)
4041 {
4142 manager_accessor_->set_window_manager(window_manager_);
4243
@@ -55,6 +56,7 @@ MainLoop::MainLoop(const ManagerAccessorPtr& manager_accessor) :
5556 world_manager_->myself()->Init(unicode::ToTString(account_manager_->model_name()));
5657
5758 socket_server_manager_->Start();
59+
5860 }
5961
6062 MainLoop::~MainLoop()
@@ -79,6 +81,15 @@ void MainLoop::Update()
7981 world_manager_->Update();
8082 ResourceManager::music()->Update();
8183
84+ static int cleanup_counter = 0;
85+ if (cleanup_counter % (60 * 30) == 0) {
86+ ResourceManager::ClearModelHandle();
87+ }
88+ cleanup_counter++;
89+
90+ if (fade_counter_ < 120) {
91+ fade_counter_++;
92+ }
8293 }
8394
8495 void MainLoop::ProcessInput(InputManager* input)
@@ -187,9 +198,18 @@ void MainLoop::Draw()
187198 SetDrawBlendMode(DX_BLENDMODE_MUL, 120);
188199 DrawBox(0,0,config_manager_->screen_width(),config_manager_->screen_height(),GetColor(0,0,0),1);
189200 SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
190- auto str = unicode::ToTString("サーバーとの接続が切断されました");
201+ auto str = unicode::ToTString(_T("サーバーとの接続が切断されました"));
191202 auto width = GetDrawStringWidthToHandle(str.c_str(),str.length(),ResourceManager::default_font_handle());
192203 DrawStringToHandle(config_manager_->screen_width()/2.0f - width,config_manager_->screen_height()/2.0f - ResourceManager::default_font_size(),str.c_str(),GetColor(255,255,255),ResourceManager::default_font_handle());
204+ SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
205+ }
206+
207+ if (fade_counter_ < 120) {
208+ SetDrawBlendMode(DX_BLENDMODE_ALPHA, 255 * (120 - fade_counter_) / 120);
209+ int width, height;
210+ GetScreenState(&width, &height, nullptr);
211+ DrawBox(0, 0, width, height, GetColor(0, 0, 0), TRUE);
212+ SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
193213 }
194214 }
195215
--- a/client/scene/MainLoop.hpp
+++ b/client/scene/MainLoop.hpp
@@ -45,6 +45,7 @@ class MainLoop : public Base {
4545 int snapshot_number_;
4646 bool snapshot_;
4747
48+ int fade_counter_;
4849 //SocketServer socket_server_;
4950 };
5051