增加File类和Resource类;图片和音乐资源统一为Resource map
This commit is contained in:
parent
0423b49bb9
commit
b7c4c409cb
|
|
@ -3,9 +3,7 @@
|
|||
#include "..\e2dtool.h"
|
||||
#include <map>
|
||||
|
||||
static std::map<size_t, ID2D1Bitmap*> s_mBitmapsFromFile;
|
||||
static std::map<int, ID2D1Bitmap*> s_mBitmapsFromResource;
|
||||
static std::set<ID2D1Bitmap*> s_vBitmaps;
|
||||
static std::map<e2d::Resource, ID2D1Bitmap*> s_mBitmapsFromResource;
|
||||
|
||||
|
||||
e2d::Image::Image()
|
||||
|
|
@ -14,33 +12,33 @@ e2d::Image::Image()
|
|||
{
|
||||
}
|
||||
|
||||
e2d::Image::Image(const String& filePath)
|
||||
e2d::Image::Image(const Resource& res)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(filePath);
|
||||
this->open(res);
|
||||
}
|
||||
|
||||
e2d::Image::Image(int resNameId, const String& resType)
|
||||
e2d::Image::Image(const Resource& res, const Rect& cropRect)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(resNameId, resType);
|
||||
}
|
||||
|
||||
e2d::Image::Image(const String& filePath, const Rect& cropRect)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(filePath);
|
||||
this->open(res);
|
||||
this->crop(cropRect);
|
||||
}
|
||||
|
||||
e2d::Image::Image(int resNameId, const String& resType, const Rect& cropRect)
|
||||
e2d::Image::Image(const String & fileName)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(resNameId, resType);
|
||||
this->open(Resource(fileName));
|
||||
}
|
||||
|
||||
e2d::Image::Image(const String & fileName, const Rect & cropRect)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(Resource(fileName));
|
||||
this->crop(cropRect);
|
||||
}
|
||||
|
||||
|
|
@ -48,33 +46,29 @@ e2d::Image::~Image()
|
|||
{
|
||||
}
|
||||
|
||||
bool e2d::Image::open(const String& filePath)
|
||||
bool e2d::Image::open(const Resource& res)
|
||||
{
|
||||
WARN_IF(filePath.isEmpty(), "Image open failed! Invalid file name.");
|
||||
if (!res.isResource())
|
||||
{
|
||||
WARN_IF(res.getFileName().isEmpty(), "Image open failed! Invalid file name.");
|
||||
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
if (res.getFileName().isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Image::preload(filePath))
|
||||
if (!Image::preload(res))
|
||||
{
|
||||
WARN("Load Image from file failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_setBitmap(s_mBitmapsFromFile.at(filePath.getHashCode()));
|
||||
this->_setBitmap(s_mBitmapsFromResource.at(res));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool e2d::Image::open(int resNameId, const String& resType)
|
||||
bool e2d::Image::open(const String & fileName)
|
||||
{
|
||||
if (!Image::preload(resNameId, resType))
|
||||
{
|
||||
WARN("Load Image from file failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_setBitmap(s_mBitmapsFromResource.at(resNameId));
|
||||
return true;
|
||||
return open(Resource(fileName));
|
||||
}
|
||||
|
||||
void e2d::Image::crop(const Rect& cropRect)
|
||||
|
|
@ -154,94 +148,9 @@ e2d::Point e2d::Image::getCropPos() const
|
|||
return _cropRect.origin;
|
||||
}
|
||||
|
||||
bool e2d::Image::preload(const String& filePath)
|
||||
bool e2d::Image::preload(const Resource& res)
|
||||
{
|
||||
if (s_mBitmapsFromFile.find(filePath.getHashCode()) != s_mBitmapsFromFile.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
String actualFilePath = Path::findFile(filePath);
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
IWICBitmapDecoder *pDecoder = nullptr;
|
||||
IWICBitmapFrameDecode *pSource = nullptr;
|
||||
IWICStream *pStream = nullptr;
|
||||
IWICFormatConverter *pConverter = nullptr;
|
||||
ID2D1Bitmap *pBitmap = nullptr;
|
||||
|
||||
// 创建解码器
|
||||
hr = Renderer::getImagingFactory()->CreateDecoderFromFilename(
|
||||
(LPCWSTR)actualFilePath,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = pDecoder->GetFrame(0, &pSource);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
|
||||
hr = Renderer::getImagingFactory()->CreateFormatConverter(&pConverter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bbpPBGRA
|
||||
hr = pConverter->Initialize(
|
||||
pSource,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = Renderer::getInstance()->getRenderTarget()->CreateBitmapFromWicBitmap(
|
||||
pConverter,
|
||||
nullptr,
|
||||
&pBitmap
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 保存图片指针和图片的 Hash 名
|
||||
s_mBitmapsFromFile.insert(
|
||||
std::map<size_t, ID2D1Bitmap*>::value_type(
|
||||
filePath.getHashCode(),
|
||||
pBitmap)
|
||||
);
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(pDecoder);
|
||||
SafeRelease(pSource);
|
||||
SafeRelease(pStream);
|
||||
SafeRelease(pConverter);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool e2d::Image::preload(int resNameId, const String& resType)
|
||||
{
|
||||
if (s_mBitmapsFromResource.find(resNameId) != s_mBitmapsFromResource.end())
|
||||
if (s_mBitmapsFromResource.find(res) != s_mBitmapsFromResource.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -252,63 +161,87 @@ bool e2d::Image::preload(int resNameId, const String& resType)
|
|||
IWICBitmapFrameDecode *pSource = nullptr;
|
||||
IWICStream *pStream = nullptr;
|
||||
IWICFormatConverter *pConverter = nullptr;
|
||||
IWICBitmapScaler *pScaler = nullptr;
|
||||
ID2D1Bitmap *pBitmap = nullptr;
|
||||
IWICImagingFactory *pImagingFactory = Renderer::getImagingFactory();
|
||||
|
||||
HRSRC imageResHandle = nullptr;
|
||||
HGLOBAL imageResDataHandle = nullptr;
|
||||
void *pImageFile = nullptr;
|
||||
DWORD imageFileSize = 0;
|
||||
|
||||
// 定位资源
|
||||
imageResHandle = ::FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType);
|
||||
|
||||
hr = imageResHandle ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
if (res.isResource())
|
||||
{
|
||||
// 加载资源
|
||||
imageResDataHandle = ::LoadResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
HRSRC imageResHandle = nullptr;
|
||||
HGLOBAL imageResDataHandle = nullptr;
|
||||
void *pImageFile = nullptr;
|
||||
DWORD imageFileSize = 0;
|
||||
|
||||
hr = imageResDataHandle ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 获取文件指针,并锁定资源
|
||||
pImageFile = ::LockResource(imageResDataHandle);
|
||||
|
||||
hr = pImageFile ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 计算大小
|
||||
imageFileSize = ::SizeofResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageFileSize ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = Renderer::getImagingFactory()->CreateStream(&pStream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = pStream->InitializeFromMemory(
|
||||
reinterpret_cast<BYTE*>(pImageFile),
|
||||
imageFileSize
|
||||
// 定位资源
|
||||
imageResHandle = ::FindResourceW(
|
||||
HINST_THISCOMPONENT,
|
||||
MAKEINTRESOURCE(res.getResNameId()),
|
||||
(LPCWSTR)res.getResType()
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = imageResHandle ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 加载资源
|
||||
imageResDataHandle = ::LoadResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageResDataHandle ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 获取文件指针,并锁定资源
|
||||
pImageFile = ::LockResource(imageResDataHandle);
|
||||
|
||||
hr = pImageFile ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 计算大小
|
||||
imageFileSize = ::SizeofResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageFileSize ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = pImagingFactory->CreateStream(&pStream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = pStream->InitializeFromMemory(
|
||||
reinterpret_cast<BYTE*>(pImageFile),
|
||||
imageFileSize
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = pImagingFactory->CreateDecoderFromStream(
|
||||
pStream,
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = Renderer::getImagingFactory()->CreateDecoderFromStream(
|
||||
pStream,
|
||||
String actualFilePath = File(res.getFileName()).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建解码器
|
||||
hr = pImagingFactory->CreateDecoderFromFilename(
|
||||
(LPCWSTR)actualFilePath,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
|
|
@ -323,8 +256,7 @@ bool e2d::Image::preload(int resNameId, const String& resType)
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
|
||||
hr = Renderer::getImagingFactory()->CreateFormatConverter(&pConverter);
|
||||
hr = pImagingFactory->CreateFormatConverter(&pConverter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -352,7 +284,7 @@ bool e2d::Image::preload(int resNameId, const String& resType)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
s_mBitmapsFromResource.insert(std::pair<int, ID2D1Bitmap*>(resNameId, pBitmap));
|
||||
s_mBitmapsFromResource.insert(std::make_pair(res, pBitmap));
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
|
|
@ -360,31 +292,17 @@ bool e2d::Image::preload(int resNameId, const String& resType)
|
|||
SafeRelease(pSource);
|
||||
SafeRelease(pStream);
|
||||
SafeRelease(pConverter);
|
||||
SafeRelease(pScaler);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
|
||||
void e2d::Image::clearCache()
|
||||
{
|
||||
for (auto bitmap : s_mBitmapsFromFile)
|
||||
{
|
||||
SafeRelease(bitmap.second);
|
||||
}
|
||||
s_mBitmapsFromFile.clear();
|
||||
|
||||
for (auto bitmap : s_mBitmapsFromResource)
|
||||
{
|
||||
SafeRelease(bitmap.second);
|
||||
}
|
||||
s_mBitmapsFromResource.clear();
|
||||
|
||||
for (auto bitmap : s_vBitmaps)
|
||||
{
|
||||
SafeRelease(bitmap);
|
||||
}
|
||||
s_vBitmaps.clear();
|
||||
}
|
||||
|
||||
void e2d::Image::_setBitmap(ID2D1Bitmap * bitmap)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
#include "..\e2dtool.h"
|
||||
|
||||
e2d::Resource::Resource(const String & fileName)
|
||||
: _isResource(false)
|
||||
, _fileName(fileName)
|
||||
, _resNameId(0)
|
||||
, _resType()
|
||||
{
|
||||
}
|
||||
|
||||
e2d::Resource::Resource(int resNameId, const String & resType)
|
||||
: _isResource(true)
|
||||
, _fileName()
|
||||
, _resNameId(resNameId)
|
||||
, _resType(resType)
|
||||
{
|
||||
}
|
||||
|
||||
bool e2d::Resource::isResource() const
|
||||
{
|
||||
return _isResource;
|
||||
}
|
||||
|
||||
const e2d::String & e2d::Resource::getFileName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
int e2d::Resource::getResNameId() const
|
||||
{
|
||||
return _resNameId;
|
||||
}
|
||||
|
||||
const e2d::String & e2d::Resource::getResType() const
|
||||
{
|
||||
return _resType;
|
||||
}
|
||||
|
||||
int e2d::Resource::getKey() const
|
||||
{
|
||||
if (_isResource)
|
||||
{
|
||||
return _resNameId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _fileName.getHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator>(const Resource &res) const
|
||||
{
|
||||
return this->getKey() > res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator>=(const Resource &res) const
|
||||
{
|
||||
return this->getKey() >= res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator<(const Resource &res) const
|
||||
{
|
||||
return this->getKey() < res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator<=(const Resource &res) const
|
||||
{
|
||||
return this->getKey() <= res.getKey();
|
||||
}
|
||||
|
|
@ -12,29 +12,29 @@ e2d::Sprite::Sprite(Image * image)
|
|||
open(image);
|
||||
}
|
||||
|
||||
e2d::Sprite::Sprite(const String& filePath)
|
||||
e2d::Sprite::Sprite(const Resource& res)
|
||||
: _image(nullptr)
|
||||
{
|
||||
open(filePath);
|
||||
open(res);
|
||||
}
|
||||
|
||||
e2d::Sprite::Sprite(int resNameId, const String& resType)
|
||||
e2d::Sprite::Sprite(const Resource& res, const Rect& cropRect)
|
||||
: _image(nullptr)
|
||||
{
|
||||
open(resNameId, resType);
|
||||
}
|
||||
|
||||
e2d::Sprite::Sprite(const String& filePath, const Rect& cropRect)
|
||||
: _image(nullptr)
|
||||
{
|
||||
open(filePath);
|
||||
open(res);
|
||||
crop(cropRect);
|
||||
}
|
||||
|
||||
e2d::Sprite::Sprite(int resNameId, const String& resType, const Rect& cropRect)
|
||||
e2d::Sprite::Sprite(const String & fileName)
|
||||
: _image(nullptr)
|
||||
{
|
||||
open(resNameId, resType);
|
||||
open(fileName);
|
||||
}
|
||||
|
||||
e2d::Sprite::Sprite(const String & fileName, const Rect & cropRect)
|
||||
: _image(nullptr)
|
||||
{
|
||||
open(fileName);
|
||||
crop(cropRect);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ bool e2d::Sprite::open(Image * image)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool e2d::Sprite::open(const String& filePath)
|
||||
bool e2d::Sprite::open(const Resource& res)
|
||||
{
|
||||
if (!_image)
|
||||
{
|
||||
|
|
@ -65,7 +65,7 @@ bool e2d::Sprite::open(const String& filePath)
|
|||
GC::retain(_image);
|
||||
}
|
||||
|
||||
if (_image->open(filePath))
|
||||
if (_image->open(res))
|
||||
{
|
||||
Node::setSize(_image->getWidth(), _image->getHeight());
|
||||
return true;
|
||||
|
|
@ -73,20 +73,9 @@ bool e2d::Sprite::open(const String& filePath)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool e2d::Sprite::open(int resNameId, const String& resType)
|
||||
bool e2d::Sprite::open(const String & fileName)
|
||||
{
|
||||
if (!_image)
|
||||
{
|
||||
_image = new (e2d::autorelease) Image();
|
||||
GC::retain(_image);
|
||||
}
|
||||
|
||||
if (_image->open(resNameId, resType))
|
||||
{
|
||||
Node::setSize(_image->getWidth(), _image->getHeight());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return open(Resource(fileName));
|
||||
}
|
||||
|
||||
void e2d::Sprite::crop(const Rect& cropRect)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
#include "..\e2dtool.h"
|
||||
#include <commdlg.h>
|
||||
|
||||
std::list<e2d::String> e2d::File::_searchPaths;
|
||||
|
||||
e2d::File::File()
|
||||
: _fileName()
|
||||
, _attributes(0)
|
||||
{
|
||||
}
|
||||
|
||||
e2d::File::File(const String & fileName)
|
||||
: _fileName(fileName)
|
||||
, _attributes(0)
|
||||
{
|
||||
this->open(fileName);
|
||||
}
|
||||
|
||||
e2d::File::~File()
|
||||
{
|
||||
}
|
||||
|
||||
bool e2d::File::open(const String & fileName)
|
||||
{
|
||||
auto FindFile = [=](const String & path) -> bool
|
||||
{
|
||||
if (::_waccess((const wchar_t*)path, 0) == 0)
|
||||
{
|
||||
_attributes = ::GetFileAttributes((LPCTSTR)path);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (FindFile(fileName))
|
||||
{
|
||||
_fileName = fileName;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& resPath : _searchPaths)
|
||||
{
|
||||
if (FindFile(resPath + fileName))
|
||||
{
|
||||
_fileName = resPath + fileName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool e2d::File::exists() const
|
||||
{
|
||||
return ::_waccess((const wchar_t*)_fileName, 0) == 0;
|
||||
}
|
||||
|
||||
bool e2d::File::isFolder() const
|
||||
{
|
||||
return _attributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
e2d::String e2d::File::getFilePath() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
e2d::String e2d::File::getExtension() const
|
||||
{
|
||||
String fileExtension;
|
||||
// 找到文件名中的最后一个 '.' 的位置
|
||||
size_t pos = _fileName.getWString().find_last_of(L'.');
|
||||
// 判断 pos 是否是有效位置
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
// 截取扩展名
|
||||
fileExtension = _fileName.subtract(static_cast<int>(pos));
|
||||
// 转换为小写字母
|
||||
fileExtension = fileExtension.toLower();
|
||||
}
|
||||
return fileExtension;
|
||||
}
|
||||
|
||||
bool e2d::File::deleteFile()
|
||||
{
|
||||
if (::DeleteFile((LPCWSTR)_fileName))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
e2d::File e2d::File::extract(int resNameId, const String & resType, const String& destFileName)
|
||||
{
|
||||
String destFilePath = Path::getTempPath() + destFileName;
|
||||
// 创建文件
|
||||
HANDLE hFile = ::CreateFile((LPCWSTR)destFilePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return std::move(File());
|
||||
|
||||
// 查找资源文件中、加载资源到内存、得到资源大小
|
||||
HRSRC hRes = ::FindResource(NULL, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType);
|
||||
HGLOBAL hMem = ::LoadResource(NULL, hRes);
|
||||
DWORD dwSize = ::SizeofResource(NULL, hRes);
|
||||
|
||||
if (hRes && hMem && dwSize)
|
||||
{
|
||||
// 写入文件
|
||||
DWORD dwWrite = 0;
|
||||
::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL);
|
||||
::CloseHandle(hFile);
|
||||
return File(destFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
::CloseHandle(hFile);
|
||||
::DeleteFile((LPCWSTR)destFilePath);
|
||||
return std::move(File());
|
||||
}
|
||||
}
|
||||
|
||||
void e2d::File::addSearchPath(const String & path)
|
||||
{
|
||||
String tmp = path;
|
||||
tmp.replace(L"/", L"\\");
|
||||
if (tmp[tmp.getLength() - 1] != L'\\')
|
||||
{
|
||||
tmp << L"\\";
|
||||
}
|
||||
auto iter = std::find(_searchPaths.cbegin(), _searchPaths.cend(), tmp);
|
||||
if (iter == _searchPaths.cend())
|
||||
{
|
||||
_searchPaths.push_front(path);
|
||||
}
|
||||
}
|
||||
|
||||
bool e2d::File::createFolder(const String & dirPath)
|
||||
{
|
||||
if (dirPath.isEmpty() || dirPath.getLength() >= MAX_PATH)
|
||||
return false;
|
||||
|
||||
wchar_t tmpDirPath[_MAX_PATH] = { 0 };
|
||||
int length = dirPath.getLength();
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
tmpDirPath[i] = dirPath.at(i);
|
||||
if (tmpDirPath[i] == L'\\' || tmpDirPath[i] == L'/' || i == (length - 1))
|
||||
{
|
||||
if (::_waccess(tmpDirPath, 0) != 0)
|
||||
{
|
||||
if (::_wmkdir(tmpDirPath) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
e2d::String e2d::File::getSaveFilePath(const String& title, const String& defExt)
|
||||
{
|
||||
// 弹出保存对话框
|
||||
OPENFILENAME ofn = { 0 };
|
||||
wchar_t strFilename[MAX_PATH] = { 0 }; // 用于接收文件名
|
||||
ofn.lStructSize = sizeof(OPENFILENAME); // 结构体大小
|
||||
ofn.hwndOwner = Window::getInstance()->getHWnd(); // 窗口句柄
|
||||
ofn.lpstrFilter = L"所有文件\0*.*\0\0"; // 设置过滤
|
||||
ofn.nFilterIndex = 1; // 过滤器索引
|
||||
ofn.lpstrFile = strFilename; // 接收返回的文件路径和文件名
|
||||
ofn.nMaxFile = sizeof(strFilename); // 缓冲区长度
|
||||
ofn.lpstrInitialDir = nullptr; // 初始目录为默认
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||
ofn.lpstrTitle = (LPCWSTR)title; // 标题
|
||||
ofn.lpstrDefExt = (LPCWSTR)defExt; // 默认追加的扩展名
|
||||
|
||||
if (GetSaveFileName(&ofn))
|
||||
{
|
||||
return strFilename;
|
||||
}
|
||||
return std::move(String());
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ e2d::Music::Music(const e2d::String & filePath)
|
|||
this->open(filePath);
|
||||
}
|
||||
|
||||
e2d::Music::Music(int resNameId, const String & resType)
|
||||
e2d::Music::Music(const Resource& res)
|
||||
: _opened(false)
|
||||
, _playing(false)
|
||||
, _wfx(nullptr)
|
||||
|
|
@ -60,7 +60,7 @@ e2d::Music::Music(int resNameId, const String & resType)
|
|||
, _voice(nullptr)
|
||||
, _voiceCallback(this)
|
||||
{
|
||||
this->open(resNameId, resType);
|
||||
this->open(res);
|
||||
}
|
||||
|
||||
e2d::Music::~Music()
|
||||
|
|
@ -69,6 +69,11 @@ e2d::Music::~Music()
|
|||
}
|
||||
|
||||
bool e2d::Music::open(const e2d::String& filePath)
|
||||
{
|
||||
return open(Resource(filePath));
|
||||
}
|
||||
|
||||
bool e2d::Music::open(const Resource& res)
|
||||
{
|
||||
if (_opened)
|
||||
{
|
||||
|
|
@ -76,114 +81,68 @@ bool e2d::Music::open(const e2d::String& filePath)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (filePath.isEmpty())
|
||||
if (res.isResource())
|
||||
{
|
||||
WARN("MusicInfo::open Invalid file name.");
|
||||
return false;
|
||||
}
|
||||
HRSRC hResInfo;
|
||||
HGLOBAL hResData;
|
||||
DWORD dwSize;
|
||||
void* pvRes;
|
||||
|
||||
String actualFilePath = Path::findFile(filePath);
|
||||
if (actualFilePath.isEmpty())
|
||||
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(res.getResNameId()), (LPCWSTR)res.getResType())))
|
||||
return TraceError(L"FindResource");
|
||||
|
||||
if (nullptr == (hResData = LoadResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"LoadResource");
|
||||
|
||||
if (0 == (dwSize = SizeofResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"SizeofResource");
|
||||
|
||||
if (nullptr == (pvRes = LockResource(hResData)))
|
||||
return TraceError(L"LockResource");
|
||||
|
||||
_resBuffer = new CHAR[dwSize];
|
||||
memcpy(_resBuffer, pvRes, dwSize);
|
||||
|
||||
MMIOINFO mmioInfo;
|
||||
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
|
||||
mmioInfo.fccIOProc = FOURCC_MEM;
|
||||
mmioInfo.cchBuffer = dwSize;
|
||||
mmioInfo.pchBuffer = (CHAR*)_resBuffer;
|
||||
|
||||
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("MusicInfo::open File not found.");
|
||||
return false;
|
||||
}
|
||||
String filePath = res.getFileName();
|
||||
if (filePath.isEmpty())
|
||||
{
|
||||
WARN("MusicInfo::open Invalid file name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 定位 wave 文件
|
||||
wchar_t pFilePath[MAX_PATH];
|
||||
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
|
||||
{
|
||||
WARN("Failed to find media file: %s", pFilePath);
|
||||
return false;
|
||||
}
|
||||
String actualFilePath = File(filePath).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
WARN("MusicInfo::open File not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||
// ¶¨Î» wave Îļþ
|
||||
wchar_t pFilePath[MAX_PATH];
|
||||
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
|
||||
{
|
||||
WARN("Failed to find media file: %s", pFilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||
}
|
||||
|
||||
if (nullptr == _hmmio)
|
||||
{
|
||||
return TraceError(L"mmioOpen");
|
||||
}
|
||||
|
||||
if (!_readMMIO())
|
||||
{
|
||||
// 读取非 wave 文件时 ReadMMIO 调用失败
|
||||
mmioClose(_hmmio, 0);
|
||||
return TraceError(L"_readMMIO");
|
||||
}
|
||||
|
||||
if (!_resetFile())
|
||||
return TraceError(L"_resetFile");
|
||||
|
||||
// 重置文件后,wave 文件的大小是 _ck.cksize
|
||||
_dwSize = _ck.cksize;
|
||||
|
||||
// 将样本数据读取到内存中
|
||||
_waveData = new BYTE[_dwSize];
|
||||
|
||||
if (!_read(_waveData, _dwSize))
|
||||
{
|
||||
TraceError(L"Failed to read WAV data");
|
||||
SAFE_DELETE_ARRAY(_waveData);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建音源
|
||||
HRESULT hr = Player::getInstance()->getXAudio2()->CreateSourceVoice(
|
||||
&_voice,
|
||||
_wfx,
|
||||
0,
|
||||
XAUDIO2_DEFAULT_FREQ_RATIO,
|
||||
&this->_voiceCallback
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
TraceError(L"Create source voice error", hr);
|
||||
SAFE_DELETE_ARRAY(_waveData);
|
||||
return false;
|
||||
}
|
||||
|
||||
_opened = true;
|
||||
_playing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool e2d::Music::open(int resNameId, const e2d::String& resType)
|
||||
{
|
||||
HRSRC hResInfo;
|
||||
HGLOBAL hResData;
|
||||
DWORD dwSize;
|
||||
void* pvRes;
|
||||
|
||||
if (_opened)
|
||||
{
|
||||
WARN("MusicInfo can be opened only once!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType)))
|
||||
return TraceError(L"FindResource");
|
||||
|
||||
if (nullptr == (hResData = LoadResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"LoadResource");
|
||||
|
||||
if (0 == (dwSize = SizeofResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"SizeofResource");
|
||||
|
||||
if (nullptr == (pvRes = LockResource(hResData)))
|
||||
return TraceError(L"LockResource");
|
||||
|
||||
_resBuffer = new CHAR[dwSize];
|
||||
memcpy(_resBuffer, pvRes, dwSize);
|
||||
|
||||
MMIOINFO mmioInfo;
|
||||
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
|
||||
mmioInfo.fccIOProc = FOURCC_MEM;
|
||||
mmioInfo.cchBuffer = dwSize;
|
||||
mmioInfo.pchBuffer = (CHAR*)_resBuffer;
|
||||
|
||||
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
|
||||
|
||||
if (!_readMMIO())
|
||||
{
|
||||
// 读取非 wave 文件时 ReadMMIO 调用失败
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "..\e2dtool.h"
|
||||
#include <algorithm>
|
||||
#include <commdlg.h>
|
||||
|
||||
|
||||
extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_LocalAppData = {
|
||||
|
|
@ -8,49 +7,33 @@ extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_LocalAppData = {
|
|||
};
|
||||
|
||||
|
||||
e2d::String e2d::Path::_tempPath;
|
||||
e2d::String e2d::Path::_dataPath;
|
||||
std::list<e2d::String> e2d::Path::_paths;
|
||||
|
||||
|
||||
void e2d::Path::addSearchPath(String path)
|
||||
{
|
||||
path.replace(L"/", L"\\");
|
||||
if (path[path.getLength() - 1] != L'\\')
|
||||
{
|
||||
path << L"\\";
|
||||
}
|
||||
auto iter = std::find(_paths.cbegin(), _paths.cend(), path);
|
||||
if (iter == _paths.cend())
|
||||
{
|
||||
_paths.push_front(path);
|
||||
}
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::getDataPath()
|
||||
{
|
||||
if (_dataPath.isEmpty())
|
||||
static String dataPath;
|
||||
if (dataPath.isEmpty())
|
||||
{
|
||||
// 设置数据的保存路径
|
||||
String localAppDataPath = Path::getLocalAppDataPath();
|
||||
String gameName = Game::getInstance()->getConfig()->getGameName();
|
||||
if (!localAppDataPath.isEmpty() && !gameName.isEmpty())
|
||||
{
|
||||
_dataPath = localAppDataPath + L"\\Easy2DGameData\\" << gameName << L"\\";
|
||||
dataPath = localAppDataPath + L"\\Easy2DGameData\\" << gameName << L"\\";
|
||||
|
||||
if (!Path::exists(_dataPath) && !Path::createFolder(_dataPath))
|
||||
File file(dataPath);
|
||||
if (!file.exists() && !File::createFolder(dataPath))
|
||||
{
|
||||
_dataPath = L"";
|
||||
dataPath = L"";
|
||||
}
|
||||
}
|
||||
_dataPath << L"Data.ini";
|
||||
dataPath << L"Data.ini";
|
||||
}
|
||||
return _dataPath;
|
||||
return dataPath;
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::getTempPath()
|
||||
{
|
||||
if (_tempPath.isEmpty())
|
||||
static String tempPath;
|
||||
if (tempPath.isEmpty())
|
||||
{
|
||||
// 设置临时文件保存路径
|
||||
wchar_t path[_MAX_PATH];
|
||||
|
|
@ -58,15 +41,16 @@ e2d::String e2d::Path::getTempPath()
|
|||
|
||||
if (0 != ::GetTempPath(_MAX_PATH, path) && !gameName.isEmpty())
|
||||
{
|
||||
_tempPath << path << L"\\Easy2DGameTemp\\" << gameName << L"\\";
|
||||
tempPath << path << L"\\Easy2DGameTemp\\" << gameName << L"\\";
|
||||
|
||||
if (!Path::exists(_tempPath) && !Path::createFolder(_tempPath))
|
||||
File file(tempPath);
|
||||
if (!file.exists() && !File::createFolder(tempPath))
|
||||
{
|
||||
_tempPath = L"";
|
||||
tempPath = L"";
|
||||
}
|
||||
}
|
||||
}
|
||||
return _tempPath;
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::getLocalAppDataPath()
|
||||
|
|
@ -94,134 +78,14 @@ e2d::String e2d::Path::getLocalAppDataPath()
|
|||
|
||||
e2d::String e2d::Path::getCurrentFilePath()
|
||||
{
|
||||
TCHAR szPath[_MAX_PATH] = { 0 };
|
||||
if (::GetModuleFileName(nullptr, szPath, _MAX_PATH) != 0)
|
||||
static String currFilePath;
|
||||
if (currFilePath.isEmpty())
|
||||
{
|
||||
return std::move(String(szPath));
|
||||
}
|
||||
return std::move(String());
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::findFile(const String& path)
|
||||
{
|
||||
if (Path::exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& resPath : _paths)
|
||||
TCHAR szPath[_MAX_PATH] = { 0 };
|
||||
if (::GetModuleFileName(nullptr, szPath, _MAX_PATH) != 0)
|
||||
{
|
||||
if (Path::exists(resPath + path))
|
||||
{
|
||||
return resPath + path;
|
||||
}
|
||||
currFilePath = szPath;
|
||||
}
|
||||
}
|
||||
return std::move(String());
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::extractResource(int resNameId, const String & resType, const String & destFileName)
|
||||
{
|
||||
String destFilePath = _tempPath + destFileName;
|
||||
// 创建文件
|
||||
HANDLE hFile = ::CreateFile((LPCWSTR)destFilePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return std::move(String());
|
||||
|
||||
// 查找资源文件中、加载资源到内存、得到资源大小
|
||||
HRSRC hRes = ::FindResource(NULL, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType);
|
||||
HGLOBAL hMem = ::LoadResource(NULL, hRes);
|
||||
DWORD dwSize = ::SizeofResource(NULL, hRes);
|
||||
|
||||
if (hRes && hMem && dwSize)
|
||||
{
|
||||
// 写入文件
|
||||
DWORD dwWrite = 0;
|
||||
::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL);
|
||||
::CloseHandle(hFile);
|
||||
return destFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
::CloseHandle(hFile);
|
||||
::DeleteFile((LPCWSTR)destFilePath);
|
||||
return std::move(String());
|
||||
}
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::getFileExtension(const String& filePath)
|
||||
{
|
||||
String fileExtension;
|
||||
// 找到文件名中的最后一个 '.' 的位置
|
||||
size_t pos = filePath.getWString().find_last_of(L'.');
|
||||
// 判断 pos 是否是有效位置
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
// 截取扩展名
|
||||
fileExtension = filePath.subtract(static_cast<int>(pos));
|
||||
// 转换为小写字母
|
||||
fileExtension = fileExtension.toLower();
|
||||
}
|
||||
|
||||
return fileExtension;
|
||||
}
|
||||
|
||||
e2d::String e2d::Path::getSaveFilePath(const String& title, const String& defExt)
|
||||
{
|
||||
// 弹出保存对话框
|
||||
OPENFILENAME ofn = { 0 };
|
||||
wchar_t strFilename[MAX_PATH] = { 0 }; // 用于接收文件名
|
||||
ofn.lStructSize = sizeof(OPENFILENAME); // 结构体大小
|
||||
ofn.hwndOwner = Window::getInstance()->getHWnd(); // 窗口句柄
|
||||
ofn.lpstrFilter = L"所有文件\0*.*\0\0"; // 设置过滤
|
||||
ofn.nFilterIndex = 1; // 过滤器索引
|
||||
ofn.lpstrFile = strFilename; // 接收返回的文件路径和文件名
|
||||
ofn.nMaxFile = sizeof(strFilename); // 缓冲区长度
|
||||
ofn.lpstrInitialDir = nullptr; // 初始目录为默认
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||
ofn.lpstrTitle = (LPCWSTR)title; // 标题
|
||||
ofn.lpstrDefExt = (LPCWSTR)defExt; // 默认追加的扩展名
|
||||
|
||||
if (GetSaveFileName(&ofn))
|
||||
{
|
||||
return strFilename;
|
||||
}
|
||||
return std::move(String());
|
||||
}
|
||||
|
||||
bool e2d::Path::createFolder(const String& dirPath)
|
||||
{
|
||||
if (dirPath.isEmpty() || dirPath.getLength() >= MAX_PATH)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wchar_t tmpDirPath[_MAX_PATH] = { 0 };
|
||||
int length = dirPath.getLength();
|
||||
|
||||
for (int i = 0; i < length; ++i)
|
||||
{
|
||||
tmpDirPath[i] = dirPath.at(i);
|
||||
if (tmpDirPath[i] == L'\\' || tmpDirPath[i] == L'/' || i == (length - 1))
|
||||
{
|
||||
if (::_waccess(tmpDirPath, 0) != 0)
|
||||
{
|
||||
if (::_wmkdir(tmpDirPath) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool e2d::Path::exists(const String & path)
|
||||
{
|
||||
if (path.isEmpty() || path.getLength() >= MAX_PATH)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ::_waccess((const wchar_t *)path, 0) == 0;
|
||||
return currFilePath;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,6 @@ e2d::Player::Player()
|
|||
|
||||
e2d::Player::~Player()
|
||||
{
|
||||
for (auto pair : _fileList)
|
||||
GC::release(pair.second);
|
||||
_fileList.clear();
|
||||
|
||||
for (auto pair : _resList)
|
||||
GC::release(pair.second);
|
||||
_resList.clear();
|
||||
|
|
@ -61,67 +57,42 @@ IXAudio2 * e2d::Player::getXAudio2()
|
|||
|
||||
bool e2d::Player::preload(const String& filePath)
|
||||
{
|
||||
UINT hash = filePath.getHashCode();
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
if (_fileList.end() != _fileList.find(hash))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Music * music = new (e2d::autorelease) Music();
|
||||
|
||||
if (music->open(filePath))
|
||||
{
|
||||
GC::retain(music);
|
||||
music->setVolume(_volume);
|
||||
_fileList.insert(std::pair<UINT, Music *>(hash, music));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return preload(Resource(filePath));
|
||||
}
|
||||
|
||||
bool e2d::Player::preload(int resNameId, const String& resType)
|
||||
bool e2d::Player::preload(const Resource& res)
|
||||
{
|
||||
if (_resList.end() != _resList.find(resNameId))
|
||||
{
|
||||
if (_resList.end() != _resList.find(res))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Music * music = new (e2d::autorelease) Music();
|
||||
|
||||
if (music->open(resNameId, resType))
|
||||
{
|
||||
GC::retain(music);
|
||||
music->setVolume(_volume);
|
||||
_resList.insert(std::pair<UINT, Music *>(resNameId, music));
|
||||
return true;
|
||||
}
|
||||
Music * music = new (e2d::autorelease) Music();
|
||||
|
||||
if (music->open(res))
|
||||
{
|
||||
GC::retain(music);
|
||||
music->setVolume(_volume);
|
||||
_resList.insert(std::make_pair(res, music));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool e2d::Player::play(const String& filePath, int nLoopCount)
|
||||
{
|
||||
if (Player::preload(filePath))
|
||||
{
|
||||
UINT hash = filePath.getHashCode();
|
||||
auto music = _fileList[hash];
|
||||
if (music->play(nLoopCount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
return play(Resource(filePath), nLoopCount);
|
||||
}
|
||||
|
||||
bool e2d::Player::play(int resNameId, const String& resType, int nLoopCount)
|
||||
bool e2d::Player::play(const Resource& res, int nLoopCount)
|
||||
{
|
||||
if (Player::preload(resNameId, resType))
|
||||
if (Player::preload(res))
|
||||
{
|
||||
auto music = _resList[resNameId];
|
||||
auto music = _resList[res];
|
||||
if (music->play(nLoopCount))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -135,16 +106,13 @@ void e2d::Player::pause(const String& filePath)
|
|||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
UINT hash = filePath.getHashCode();
|
||||
|
||||
if (_fileList.end() != _fileList.find(hash))
|
||||
_fileList[hash]->pause();
|
||||
pause(Resource(filePath));
|
||||
}
|
||||
|
||||
void e2d::Player::pause(int resNameId, const String& resType)
|
||||
void e2d::Player::pause(const Resource& res)
|
||||
{
|
||||
if (_resList.end() != _resList.find(resNameId))
|
||||
_resList[resNameId]->pause();
|
||||
if (_resList.end() != _resList.find(res))
|
||||
_resList[res]->pause();
|
||||
}
|
||||
|
||||
void e2d::Player::resume(const String& filePath)
|
||||
|
|
@ -152,16 +120,13 @@ void e2d::Player::resume(const String& filePath)
|
|||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
UINT hash = filePath.getHashCode();
|
||||
|
||||
if (_fileList.end() != _fileList.find(hash))
|
||||
_fileList[hash]->resume();
|
||||
resume(Resource(filePath));
|
||||
}
|
||||
|
||||
void e2d::Player::resume(int resNameId, const String& resType)
|
||||
void e2d::Player::resume(const Resource& res)
|
||||
{
|
||||
if (_resList.end() != _resList.find(resNameId))
|
||||
_resList[resNameId]->pause();
|
||||
if (_resList.end() != _resList.find(res))
|
||||
_resList[res]->pause();
|
||||
}
|
||||
|
||||
void e2d::Player::stop(const String& filePath)
|
||||
|
|
@ -169,16 +134,17 @@ void e2d::Player::stop(const String& filePath)
|
|||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
UINT hash = filePath.getHashCode();
|
||||
|
||||
if (_fileList.end() != _fileList.find(hash))
|
||||
_fileList[hash]->stop();
|
||||
stop(Resource(filePath));
|
||||
}
|
||||
|
||||
void e2d::Player::stop(int resNameId, const String& resType)
|
||||
void e2d::Player::stop(const Resource& res)
|
||||
{
|
||||
if (_resList.end() != _resList.find(resNameId))
|
||||
_resList[resNameId]->stop();
|
||||
if (res.isResource())
|
||||
{
|
||||
|
||||
}
|
||||
if (_resList.end() != _resList.find(res))
|
||||
_resList[res]->stop();
|
||||
}
|
||||
|
||||
bool e2d::Player::isPlaying(const String& filePath)
|
||||
|
|
@ -186,18 +152,13 @@ bool e2d::Player::isPlaying(const String& filePath)
|
|||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
UINT hash = filePath.getHashCode();
|
||||
|
||||
if (_fileList.end() != _fileList.find(hash))
|
||||
return _fileList[hash]->isPlaying();
|
||||
|
||||
return false;
|
||||
return isPlaying(Resource(filePath));
|
||||
}
|
||||
|
||||
bool e2d::Player::isPlaying(int resNameId, const String& resType)
|
||||
bool e2d::Player::isPlaying(const Resource& res)
|
||||
{
|
||||
if (_resList.end() != _resList.find(resNameId))
|
||||
return _resList[resNameId]->isPlaying();
|
||||
if (_resList.end() != _resList.find(res))
|
||||
return _resList[res]->isPlaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +170,6 @@ double e2d::Player::getVolume()
|
|||
void e2d::Player::setVolume(double volume)
|
||||
{
|
||||
_volume = std::min(std::max(float(volume), -224.f), 224.f);
|
||||
for (auto pair : _fileList)
|
||||
{
|
||||
pair.second->setVolume(_volume);
|
||||
}
|
||||
|
||||
for (auto pair : _resList)
|
||||
{
|
||||
pair.second->setVolume(_volume);
|
||||
|
|
@ -222,11 +178,6 @@ void e2d::Player::setVolume(double volume)
|
|||
|
||||
void e2d::Player::pauseAll()
|
||||
{
|
||||
for (auto pair : _fileList)
|
||||
{
|
||||
pair.second->pause();
|
||||
}
|
||||
|
||||
for (auto pair : _resList)
|
||||
{
|
||||
pair.second->pause();
|
||||
|
|
@ -235,11 +186,6 @@ void e2d::Player::pauseAll()
|
|||
|
||||
void e2d::Player::resumeAll()
|
||||
{
|
||||
for (auto pair : _fileList)
|
||||
{
|
||||
pair.second->resume();
|
||||
}
|
||||
|
||||
for (auto pair : _resList)
|
||||
{
|
||||
pair.second->resume();
|
||||
|
|
@ -248,11 +194,6 @@ void e2d::Player::resumeAll()
|
|||
|
||||
void e2d::Player::stopAll()
|
||||
{
|
||||
for (auto pair : _fileList)
|
||||
{
|
||||
pair.second->stop();
|
||||
}
|
||||
|
||||
for (auto pair : _resList)
|
||||
{
|
||||
pair.second->stop();
|
||||
|
|
@ -261,12 +202,6 @@ void e2d::Player::stopAll()
|
|||
|
||||
void e2d::Player::clearCache()
|
||||
{
|
||||
for (auto pair : _fileList)
|
||||
{
|
||||
GC::release(pair.second);
|
||||
}
|
||||
_fileList.clear();
|
||||
|
||||
for (auto pair : _resList)
|
||||
{
|
||||
GC::release(pair.second);
|
||||
|
|
|
|||
|
|
@ -521,6 +521,44 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
// 资源
|
||||
class Resource
|
||||
{
|
||||
public:
|
||||
Resource(
|
||||
const String& fileName /* 文件路径 */
|
||||
);
|
||||
|
||||
Resource(
|
||||
int resNameId, /* 资源名称 */
|
||||
const String& resType /* 资源类型 */
|
||||
);
|
||||
|
||||
// 是否是资源类型
|
||||
bool isResource() const;
|
||||
|
||||
const String& getFileName() const;
|
||||
|
||||
int getResNameId() const;
|
||||
|
||||
const String& getResType() const;
|
||||
|
||||
int getKey() const;
|
||||
|
||||
// 比较运算符
|
||||
bool operator> (const Resource &) const;
|
||||
bool operator>= (const Resource &) const;
|
||||
bool operator< (const Resource &) const;
|
||||
bool operator<= (const Resource &) const;
|
||||
|
||||
protected:
|
||||
bool _isResource;
|
||||
String _fileName;
|
||||
int _resNameId;
|
||||
String _resType;
|
||||
};
|
||||
|
||||
|
||||
// 引用计数对象
|
||||
class Ref
|
||||
{
|
||||
|
|
@ -554,36 +592,33 @@ public:
|
|||
Image();
|
||||
|
||||
explicit Image(
|
||||
const String& filePath /* 图片文件路径 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType /* 图片资源类型 */
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
const String& filePath, /* 图片文件路径 */
|
||||
const Resource& res,
|
||||
const Rect& cropRect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType, /* 图片资源类型 */
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
explicit Image(
|
||||
const String& fileName,
|
||||
const Rect& cropRect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
virtual ~Image();
|
||||
|
||||
// 加载图片文件
|
||||
// 加载图片资源
|
||||
bool open(
|
||||
const String& filePath /* 图片文件路径 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
// 加载图片资源
|
||||
bool open(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType /* 图片资源类型 */
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
// 将图片裁剪为矩形
|
||||
|
|
@ -621,15 +656,9 @@ public:
|
|||
// 获取 ID2D1Bitmap 对象
|
||||
ID2D1Bitmap * getBitmap();
|
||||
|
||||
// 预加载图片文件
|
||||
static bool preload(
|
||||
const String& filePath /* 图片文件路径 */
|
||||
);
|
||||
|
||||
// 预加载图片资源
|
||||
static bool preload(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType /* 图片资源类型 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
// 清空缓存
|
||||
|
|
|
|||
|
|
@ -452,22 +452,20 @@ public:
|
|||
);
|
||||
|
||||
explicit Sprite(
|
||||
const String& filePath /* 图片文件路径 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
explicit Sprite(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType /* 图片资源类型 */
|
||||
);
|
||||
|
||||
explicit Sprite(
|
||||
const String& filePath, /* 图片文件路径 */
|
||||
const Resource& res,
|
||||
const Rect& cropRect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
explicit Sprite(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType, /* 图片资源类型 */
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
explicit Sprite(
|
||||
const String& fileName,
|
||||
const Rect& cropRect /* 裁剪矩形 */
|
||||
);
|
||||
|
||||
|
|
@ -475,13 +473,12 @@ public:
|
|||
|
||||
// 加载图片文件
|
||||
bool open(
|
||||
const String& filePath
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
// 加载图片资源
|
||||
// 加载图片文件
|
||||
bool open(
|
||||
int resNameId, /* 图片资源名称 */
|
||||
const String& resType /* 图片资源类型 */
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
// 加载图片
|
||||
|
|
|
|||
123
core/e2dtool.h
123
core/e2dtool.h
|
|
@ -62,8 +62,7 @@ public:
|
|||
);
|
||||
|
||||
explicit Music(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
virtual ~Music();
|
||||
|
|
@ -75,8 +74,7 @@ public:
|
|||
|
||||
// 打开音乐资源
|
||||
bool open(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res
|
||||
);
|
||||
|
||||
// 播放
|
||||
|
|
@ -152,7 +150,7 @@ protected:
|
|||
class Player
|
||||
{
|
||||
friend class Game;
|
||||
typedef std::map<UINT, Music*> MusicMap;
|
||||
typedef std::map<Resource, Music*> MusicMap;
|
||||
|
||||
public:
|
||||
// 获取播放器实例
|
||||
|
|
@ -194,39 +192,33 @@ public:
|
|||
|
||||
// 预加载音乐资源
|
||||
bool preload(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 播放音乐
|
||||
bool play(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType, /* 音乐资源类型 */
|
||||
const Resource& res, /* 音乐资源 */
|
||||
int nLoopCount = 0 /* 重复播放次数,设置 -1 为循环播放 */
|
||||
);
|
||||
|
||||
// 暂停音乐
|
||||
void pause(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 继续播放音乐
|
||||
void resume(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 停止音乐
|
||||
void stop(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 获取音乐播放状态
|
||||
bool isPlaying(
|
||||
int resNameId, /* 音乐资源名称 */
|
||||
const String& resType /* 音乐资源类型 */
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
// 获取音量
|
||||
|
|
@ -261,7 +253,6 @@ private:
|
|||
|
||||
private:
|
||||
float _volume;
|
||||
MusicMap _fileList;
|
||||
MusicMap _resList;
|
||||
IXAudio2* _xAudio2;
|
||||
IXAudio2MasteringVoice* _masteringVoice;
|
||||
|
|
@ -504,29 +495,75 @@ public:
|
|||
};
|
||||
|
||||
|
||||
// 路径工具
|
||||
class Path
|
||||
// 文件
|
||||
class File
|
||||
{
|
||||
friend class Game;
|
||||
|
||||
public:
|
||||
// 添加资源搜索路径
|
||||
static void addSearchPath(
|
||||
String path
|
||||
File();
|
||||
|
||||
File(
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
// 检索文件路径
|
||||
static String findFile(
|
||||
const String& path
|
||||
virtual ~File();
|
||||
|
||||
// 打开文件
|
||||
bool open(
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
// 提取资源文件,返回提取后的文件路径
|
||||
static String extractResource(
|
||||
// 文件或文件夹是否存在
|
||||
bool exists() const;
|
||||
|
||||
// 是否是文件夹
|
||||
bool isFolder() const;
|
||||
|
||||
// 删除文件
|
||||
bool deleteFile();
|
||||
|
||||
// 获取文件路径
|
||||
String getFilePath() const;
|
||||
|
||||
// 获取文件扩展名
|
||||
String getExtension() const;
|
||||
|
||||
// 释放资源到临时文件目录
|
||||
static File extract(
|
||||
int resNameId, /* 资源名称 */
|
||||
const String& resType, /* 资源类型 */
|
||||
const String& destFileName /* 目标文件名 */
|
||||
);
|
||||
|
||||
// 添加文件搜索路径
|
||||
static void addSearchPath(
|
||||
const String& path
|
||||
);
|
||||
|
||||
// 创建文件夹
|
||||
static bool createFolder(
|
||||
const String& dirPath /* 文件夹路径 */
|
||||
);
|
||||
|
||||
// 打开保存文件对话框
|
||||
static String getSaveFilePath(
|
||||
const String& title = L"保存到", /* 对话框标题 */
|
||||
const String& defExt = L"" /* 默认扩展名 */
|
||||
);
|
||||
|
||||
protected:
|
||||
DWORD _attributes;
|
||||
String _fileName;
|
||||
|
||||
static std::list<String> _searchPaths;
|
||||
};
|
||||
|
||||
|
||||
// 路径
|
||||
class Path
|
||||
{
|
||||
friend class Game;
|
||||
|
||||
public:
|
||||
// 获取数据的默认保存路径
|
||||
static String getDataPath();
|
||||
|
||||
|
|
@ -538,32 +575,6 @@ public:
|
|||
|
||||
// 获取当前程序的运行路径
|
||||
static String getCurrentFilePath();
|
||||
|
||||
// 获取文件扩展名
|
||||
static String getFileExtension(
|
||||
const String& filePath
|
||||
);
|
||||
|
||||
// 打开保存文件对话框
|
||||
static String getSaveFilePath(
|
||||
const String& title = L"保存到", /* 对话框标题 */
|
||||
const String& defExt = L"" /* 默认扩展名 */
|
||||
);
|
||||
|
||||
// 创建文件夹
|
||||
static bool createFolder(
|
||||
const String& dirPath /* 文件夹路径 */
|
||||
);
|
||||
|
||||
// 判断文件或文件夹是否存在
|
||||
static bool exists(
|
||||
const String& dirPath /* 文件夹路径 */
|
||||
);
|
||||
|
||||
private:
|
||||
static String _tempPath;
|
||||
static String _dataPath;
|
||||
static std::list<String> _paths;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -230,6 +230,7 @@
|
|||
<ClCompile Include="..\..\core\Common\Point.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\Rect.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\Ref.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\Resource.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\Scene.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\Size.cpp" />
|
||||
<ClCompile Include="..\..\core\Common\String.cpp" />
|
||||
|
|
@ -253,6 +254,7 @@
|
|||
<ClCompile Include="..\..\core\Node\Sprite.cpp" />
|
||||
<ClCompile Include="..\..\core\Node\Text.cpp" />
|
||||
<ClCompile Include="..\..\core\Tool\Data.cpp" />
|
||||
<ClCompile Include="..\..\core\Tool\File.cpp" />
|
||||
<ClCompile Include="..\..\core\Tool\Listener.cpp" />
|
||||
<ClCompile Include="..\..\core\Tool\Music.cpp" />
|
||||
<ClCompile Include="..\..\core\Tool\Path.cpp" />
|
||||
|
|
|
|||
|
|
@ -240,6 +240,12 @@
|
|||
<ClCompile Include="..\..\core\Common\Ref.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\core\Tool\File.cpp">
|
||||
<Filter>Tool</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\core\Common\Resource.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\core\easy2d.h" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue