#include "../common/database/AccountProperty.hpp"\r
#include "Profiler.hpp"\r
#include "GenerateJSON.hpp"\r
+#include "Music.hpp"\r
+\r
\r
char Card::STORAGE_DIR[] = "storage";\r
char Card::SCRIPT_PATH[] = "resources/js";\r
context->Global()->Set(String::New("Network"), script_object->Clone());\r
context->Global()->Set(String::New("Player"), script_object->Clone());\r
context->Global()->Set(String::New("Account"), script_object->Clone());\r
+ context->Global()->Set(String::New("Music"), script_object->Clone());\r
context->Global()->Set(String::New("InputBox"), script_object->Clone());\r
context->Global()->Set(String::New("Card"), script_object->Clone());\r
context->Global()->Set(String::New("Screen"), script_object->Clone());\r
return Undefined();\r
}\r
\r
+Handle<Value> Card::Function_Music_playBGM(const Arguments& args)\r
+{\r
+\r
+ if (args.Length() >= 2 && args[0]->IsString()) {\r
+ auto name = std::string(*String::Utf8Value(args[0]->ToString()));\r
+ auto fade = args[1]->ToBoolean()->BooleanValue();\r
+ ResourceManager::music()->Play(unicode::ToTString(name),fade);\r
+ }\r
+\r
+ return Undefined();\r
+}\r
+\r
+Handle<Value> Card::Function_Music_stopBGM(const Arguments& args)\r
+{\r
+\r
+ if (args.Length() == 1 && args[0]->IsBoolean()) {\r
+ auto fade = args[1]->ToBoolean()->BooleanValue();\r
+ ResourceManager::music()->Stop(fade);\r
+ }else if(args.Length() == 0) {\r
+ ResourceManager::music()->Stop(false);\r
+ }\r
+\r
+ return Undefined();\r
+}\r
+\r
+Handle<Value> Card::Function_Music_playME(const Arguments& args)\r
+{\r
+\r
+ if (args.Length() == 1 && args[0]->IsString()) {\r
+ auto name = std::string(*String::Utf8Value(args[0]->ToString()));\r
+ ResourceManager::music()->PlayME(unicode::ToTString(name));\r
+ }\r
+\r
+ return Undefined();\r
+}\r
+\r
+\r
+Handle<Value> Card::Function_Music_playSE(const Arguments& args)\r
+{\r
+\r
+ if (args.Length() == 1 && args[0]->IsString()) {\r
+ auto name = std::string(*String::Utf8Value(args[0]->ToString()));\r
+ ResourceManager::music()->PlaySE(unicode::ToTString(name));\r
+ }\r
+\r
+ return Undefined();\r
+}\r
+\r
+Handle<Value> Card::Function_Music_all(const Arguments& args)\r
+{\r
+ HandleScope handle;\r
+ auto array = Array::New();\r
+\r
+ int i = 0;\r
+ BOOST_FOREACH(const boost::filesystem::path& music_path, ResourceManager::music()->GetMusicList()) {\r
+ array->Set(i, String::New(music_path.stem().string().c_str()));\r
+ i++;\r
+ }\r
+ return array;\r
+}\r
+\r
+\r
+Handle<Value> Card::Function_Music_IsLoadingDone(const Arguments& args)\r
+{\r
+ if (args.Length() == 1 && args[0]->IsString()) {\r
+ auto name = std::string(*String::Utf8Value(args[0]->ToString()));\r
+ auto check = ResourceManager::music()->CheckLoadedBGM(unicode::ToTString(name));\r
+ return Boolean::New(check);\r
+ }\r
+ return Boolean::New(false);\r
+}\r
+\r
Handle<Value> Card::Function_Account_id(const Arguments& args)\r
{\r
auto self = static_cast<Card*>(args.Holder()->GetPointerFromInternalField(0));\r
auto name = std::string(*String::Utf8Value(args[0]->ToString()));\r
if (auto world_manager = self->manager_accessor_->world_manager().lock()) {\r
world_manager->myself()->LoadModel(unicode::ToTString(name));\r
+ world_manager->myself()->ResetMotion();\r
}\r
auto account_manager = self->manager_accessor_->account_manager().lock();\r
auto command_manager = self->manager_accessor_->command_manager().lock();\r
* @static\r
*/\r
script_.SetFunction("Player.stopMotion", Function_Player_stopMotion);\r
+\r
+ /**\r
+ * 音楽を再生します\r
+ *\r
+ * @method playMotion\r
+ * @param {String} name BGM名\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.play", Function_Music_playBGM);\r
+\r
/**\r
+ * 音楽を停止します\r
+ *\r
+ * @method playMotion\r
+ * @param\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.stop", Function_Music_stopBGM);\r
+\r
+ /**\r
+ * MEを再生します\r
+ *\r
+ * @method playMotion\r
+ * @param {String} name ME名\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.playME", Function_Music_playME);\r
+\r
+ /**\r
+ * SEを再生します\r
+ *\r
+ * @method playMotion\r
+ * @param {String} name SE名\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.playSE", Function_Music_playSE);\r
+\r
+ /**\r
+ * BGM,MEのロードが終了しているかチェックします\r
+ *\r
+ * @method playMotion\r
+ * @param {String} name BGM、ME名\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.loadCheck", Function_Music_IsLoadingDone);\r
+\r
+ /**\r
+ * BGMのリストを返します\r
+ *\r
+ * @method playMotion\r
+ * @param\r
+ * @static\r
+ */\r
+ script_.SetFunction("Music.all", Function_Music_all);\r
+\r
+ /**\r
* アカウント\r
*\r
* @class Account\r
DxLib::VECTOR prePos = {0},curPos = {0},lclPos = {0};\r
DxLib::MATRIX chglcl = {0};\r
\r
- char pmd_model_name_[256] = {0};\r
- TCHAR pmd_author_name_[256] = {0};\r
+ char pmd_model_name_[MAX_PATH] = {0};\r
+ TCHAR pmd_author_name_[MAX_PATH] = {0};\r
\r
int exist_num_pmd_ = 0;\r
\r
if(tmp_pos_x < absolute_x() + 12)tmp_pos_x = absolute_x() + 12;
if(tmp_pos_x > absolute_x() + absolute_width() - 12)tmp_pos_x = absolute_x() + absolute_width() - 12;
if(tmp_pos_z < absolute_y() + 12)tmp_pos_z = absolute_y() + 12;
- if(tmp_pos_z > absolute_y() + absolute_height() -12)tmp_pos_z = absolute_y() + absolute_height() - 12;
+ if(tmp_pos_z > absolute_y() + absolute_height() -12 - 16)tmp_pos_z = absolute_y() + absolute_height() - 12 - 16;
DrawCircle( tmp_pos_x, tmp_pos_z, 2, GetColor(23,162,175),TRUE);
}
prev_myself_pos_on_map_ = player_manager->char_data_providers()[player_manager->charmgr()->my_character_id()]->position();
--- /dev/null
+//
+// Music.cpp
+//
+
+#include <boost/filesystem.hpp>
+#include "Music.hpp"
+#include "../common/Logger.hpp"
+#include "../common/unicode.hpp"
+
+extern int LoadFile(const TCHAR *FilePath, void **FileImageAddr, int *FileSize);
+
+Music::Music() :
+bgm_handle_(),
+se_handle_(),
+prev_bgm_(-1),
+present_bgm_(-1),
+requested_bgm_(-1),
+music_paths_(),
+crossfade_now_(false),
+fade_count_(0)
+{
+}
+
+void Music::Init()
+{
+ using namespace boost::filesystem;
+ using namespace std;
+
+ music_paths_.clear();
+
+ path p("./resources/musics");
+
+ try{
+ if (exists(p) && is_directory(p)) {
+ for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) {
+ if (!is_directory(*it_dir)) {
+ path music_path = it_dir->path();
+ auto extension = music_path.extension().string();
+ if( extension == ".wave" || extension == ".wav" ||
+ extension == ".ogg" || extension == ".mp3")
+ {
+ music_paths_.push_back(music_path);
+ }
+ }
+ }
+ }
+ } catch (const filesystem_error& ex) {
+ Logger::Error(_T("%s"), unicode::ToTString(ex.what()));
+ }
+
+ se_paths_.clear();
+
+ p = "./resources/ses";
+
+ try{
+ if (exists(p) && is_directory(p)) {
+ for (auto it_dir = directory_iterator(p); it_dir != directory_iterator(); ++it_dir) {
+ if (!is_directory(*it_dir)) {
+ path music_path = it_dir->path();
+ auto extension = music_path.extension().string();
+ if( extension == ".wave" || extension == ".wav" ||
+ extension == ".ogg" || extension == ".mp3")
+ {
+ se_paths_.push_back(music_path);
+ }
+ }
+ }
+ }
+ } catch (const filesystem_error& ex) {
+ Logger::Error(_T("%s"), unicode::ToTString(ex.what()));
+ }
+
+}
+
+void Music::Play(tstring name,bool crossfade)
+{
+ if(bgm_handle_.find(name) == bgm_handle_.end())
+ {
+ SetUseASyncLoadFlag(FALSE);
+ auto NameFind = [&](boost::filesystem::path& src)->bool
+ {
+ return src.stem().string() == unicode::ToString(name);
+ };
+ auto bgm_it_ = std::find_if(music_paths_.begin(),music_paths_.end(),NameFind);
+ void *fileaddr;
+ int filesize;
+ LoadFile(unicode::ToTString(bgm_it_->string()).c_str(),&fileaddr,&filesize);
+ auto softhandle_ = LoadSoftSoundFromMemImage(fileaddr,filesize);
+ auto handle_ = LoadSoundMemByMemImage(fileaddr,filesize);
+ if(handle_ == -1)return;
+ bgm_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(bgm_it_->stem().string()),handle_));
+ SetUseASyncLoadFlag(TRUE);
+ }
+ if(crossfade)
+ {
+ requested_bgm_ = bgm_handle_[name];
+ }else{
+ if(present_bgm_ != -1)StopSoundMem(present_bgm_);
+ present_bgm_ = bgm_handle_[name];
+ PlaySoundMem(present_bgm_,DX_PLAYTYPE_LOOP);
+ }
+ fade_count_ = 0;
+ crossfade_now_ = crossfade;
+}
+
+void Music::PlayME(tstring name)
+{
+ if(present_bgm_ != -1)prev_bgm_ = present_bgm_;
+ if(bgm_handle_.find(name) == bgm_handle_.end())
+ {
+ SetUseASyncLoadFlag(FALSE);
+ auto NameFind = [&](boost::filesystem::path& src)->bool
+ {
+ return src.stem().string() == unicode::ToString(name);
+ };
+ auto bgm_it_ = std::find_if(music_paths_.begin(),music_paths_.end(),NameFind);
+ void *fileaddr;
+ int filesize;
+ LoadFile(unicode::ToTString(bgm_it_->string()).c_str(),&fileaddr,&filesize);
+ auto softhandle_ = LoadSoftSoundFromMemImage(fileaddr,filesize);
+ auto handle_ = LoadSoundMemByMemImage(fileaddr,filesize);
+ if(handle_ == -1)return;
+ bgm_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(bgm_it_->stem().string()),handle_));
+ SetUseASyncLoadFlag(TRUE);
+ }
+ if(present_bgm_ != -1)StopSoundMem(present_bgm_);
+ present_bgm_ = bgm_handle_[name];
+ PlaySoundMem(present_bgm_,DX_PLAYTYPE_BACK);
+ crossfade_now_ = false;
+ fade_count_ = 0;
+}
+
+void Music::Stop(bool fadeout)
+{
+ if(!CheckSoundMem(present_bgm_))return;
+ if(!fadeout)
+ {
+ StopSoundMem(present_bgm_);
+ }
+ crossfade_now_ = fadeout;
+ fade_count_ = 0;
+}
+
+void Music::PlaySE(tstring name)
+{
+ if(se_handle_.find(name) == se_handle_.end())
+ {
+ SetUseASyncLoadFlag(FALSE);
+ auto NameFind = [&](boost::filesystem::path& src)->bool
+ {
+ return src.stem().string() == unicode::ToString(name);
+ };
+ auto se_it_ = std::find_if(se_paths_.begin(),se_paths_.end(),NameFind);
+ auto handle_ = LoadSoundMemToBufNumSitei(unicode::ToTString(se_it_->string()).c_str(),64);
+ if(handle_ == -1)return;
+ se_handle_.insert(std::make_pair<tstring,int>(unicode::ToTString(se_it_->stem().string()),handle_));
+ }
+ PlaySoundMem(se_handle_[name],DX_PLAYTYPE_BACK);
+}
+
+bool Music::CheckLoadedBGM(tstring name)
+{
+ if(bgm_handle_.find(name) == bgm_handle_.end())return true;
+ return CheckHandleASyncLoad(bgm_handle_[name]);
+}
+
+void Music::Update()
+{
+ if(prev_bgm_ != -1)
+ {
+ if(!CheckSoundMem(present_bgm_))
+ {
+ present_bgm_ = -1;
+ requested_bgm_ = prev_bgm_;
+ fade_count_ = 0;
+ crossfade_now_ = true;
+ }
+ }
+ if(!crossfade_now_)return;
+ if(CheckHandleASyncLoad(requested_bgm_) == false && requested_bgm_ != -1)
+ {
+ if(fade_count_ == 0)PlaySoundMem(requested_bgm_,DX_PLAYTYPE_LOOP);
+ if(fade_count_ >= 120)
+ {
+ ChangeVolumeSoundMem(100,requested_bgm_);
+ StopSoundMem(present_bgm_);
+ ChangeVolumeSoundMem(100,present_bgm_);
+ present_bgm_ = requested_bgm_;
+ requested_bgm_ = -1;
+ fade_count_ = 0;
+ crossfade_now_ = false;
+ }
+ ChangeVolumeSoundMem((int)(fade_count_/1.2),requested_bgm_);
+ ChangeVolumeSoundMem((int)((120-fade_count_)/1.2),present_bgm_);
+ ++fade_count_;
+ }
+}
+
+std::vector<boost::filesystem::path>& Music::GetMusicList()
+{
+ return music_paths_;
+}
\ No newline at end of file
--- /dev/null
+//\r
+// Music.hpp\r
+//\r
+#include "../common/unicode.hpp"\r
+#include <v8.h>\r
+#include <map>\r
+#include <vector>\r
+\r
+//\89ð\90Í\82·\82é\90M\8d\86\82Ì\92·\82³(\95b)\r
+#define SIGNAL_LENGTH 0.5\r
+//\83X\83y\83N\83g\83\89\83\80\82Ì\90\94\r
+#define SPECTRUM_NUM 256\r
+//\83X\83y\83N\83g\83\89\83\80\82Ì\8ag\91å\95\9d\r
+#define SPECTRUM_WIDTH 2\r
+\r
+\r
+class Music\r
+{\r
+public:\r
+ Music();\r
+ virtual ~Music(){};\r
+ void Init();\r
+ void Update();\r
+ void Play(tstring name,bool crossfade);\r
+ void Stop(bool fadeout);\r
+ void PlaySE(tstring name);\r
+ void PlayME(tstring name);\r
+ bool CheckLoadedBGM(tstring name);\r
+ std::vector<boost::filesystem::path>& GetMusicList();\r
+\r
+private:\r
+ bool crossfade_now_;\r
+ int fade_count_;\r
+ int present_bgm_;\r
+ int prev_bgm_;\r
+ int requested_bgm_;\r
+ std::map<tstring,int> bgm_handle_;\r
+ std::map<tstring,int> se_handle_;\r
+\r
+ std::vector<boost::filesystem::path> music_paths_;\r
+ std::vector<boost::filesystem::path> se_paths_;\r
+};\r
class ImageHandle;
class ModelHandle;
+class Music;
typedef std::shared_ptr<ImageHandle> ImageHandlePtr;
typedef std::shared_ptr<ModelHandle> ModelHandlePtr;
+typedef std::shared_ptr<Music> MusicPtr;
struct ReadFuncData {
ReadFuncData(){};
static tstring NameToFullPath(const tstring& name);
+ //Musics
+ static MusicPtr& music();
+
private:
static int default_font_handle_;
static std::unordered_map<tstring, ImageHandlePtr> graph_handles_;
static std::unordered_map<tstring, ModelHandle> model_handles_;
static std::vector<std::string> model_name_list_;
static float model_edge_size_;
+ //Musics
+ static MusicPtr music_;
};
class ImageHandle {
--- /dev/null
+
+/***MetaData***
+
+{
+ "name": "BGM\83\8a\83X\83g",
+ "icon": "icon.png",
+ "api_version": 1
+}
+
+***MetaData***/
+
+var list;
+list = new UI.List({
+ docking: UI.DOCKING_TOP | UI.DOCKING_LEFT | UI.DOCKING_RIGHT | UI.DOCKING_BOTTOM
+});
+
+var even_line = false;
+var music_names = Music.all();
+for (var i = 0; i < music_names.length; i++) {
+ (function (music_name) {
+ list.addItem(
+ new UI.Label({
+ docking: UI.DOCKING_TOP | UI.DOCKING_LEFT | UI.DOCKING_RIGHT,
+ text: music_name,
+ bgcolor: ((even_line = !even_line) ? "#EEAFEECC" : "#FFFFFFCC"),
+ onclick: function () {
+ Music.play(music_name,true)
+ }
+ })
+ );
+ })(music_names[i])
+}
+
+Card.board.width = 240;
+Card.board.height = 120;
+Card.board.docking = UI.DOCKING_BOTTOM | UI.DOCKING_LEFT
+Card.board.addChild(list);
\ No newline at end of file
#include "../Core.hpp"
#include <shlwapi.h>
#include "ServerChange.hpp"
+#include "../Music.hpp"
namespace scene {
MainLoop::MainLoop(const ManagerAccessorPtr& manager_accessor) :
card_manager_->Update();
minimap_.Update();
world_manager_->Update();
+ ResourceManager::music()->Update();
}
void MainLoop::ProcessInput(InputManager* input)
#define MMO_VERSION_MAJOR 0
#define MMO_VERSION_MINOR 3
-#define MMO_VERSION_REVISION 8
+#define MMO_VERSION_REVISION 9
#define MMO_PROTOCOL_VERSION 2