Commit b73d8012 authored by mercury233's avatar mercury233

Merge branch 'master' of https://github.com/Fluorohydride/ygopro into server

parents 12f9e87c b824c77e
Pipeline #43048 passed with stages
in 2 minutes and 40 seconds
......@@ -32,14 +32,15 @@ ClientCard::~ClientCard() {
overlayed.clear();
}
void ClientCard::SetCode(unsigned int x) {
if((location == LOCATION_HAND) && (code != x)) {
code = x;
if (code == x) {
return;
}
if (x == 0) {
chain_code = code;
}
code = x;
if (location == LOCATION_HAND) {
mainGame->dField.MoveCard(this, 5);
} else {
if (x == 0 && code != 0) {
chain_code = code;
}
code = x;
}
}
void ClientCard::UpdateInfo(unsigned char* buf) {
......
......@@ -456,17 +456,15 @@ void ClientField::ShowSelectCard(bool buttonok, bool is_continuous) {
if(mainGame->dInfo.curMsg != MSG_SORT_CARD) {
// text
wchar_t formatBuffer[2048];
if(select_continuous)
if (select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
else if (cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i]->overlayTarget->location, selectable_cards[i]->overlayTarget->sequence),
selectable_cards[i]->overlayTarget->sequence + 1, selectable_cards[i]->sequence + 1);
else if (selectable_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i]->overlayTarget), selectable_cards[i]->overlayTarget->sequence + 1, selectable_cards[i]->sequence + 1);
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]->location, selectable_cards[i]->sequence),
selectable_cards[i]->sequence + 1);
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]), selectable_cards[i]->sequence + 1);
mainGame->stCardPos[i]->setText(formatBuffer);
// color
if (selectable_cards[i]->is_selected)
......@@ -542,8 +540,7 @@ void ClientField::ShowChainCard() {
mainGame->btnCardSelect[i]->setPressed(false);
mainGame->btnCardSelect[i]->setVisible(true);
wchar_t formatBuffer[2048];
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]->location, selectable_cards[i]->sequence),
selectable_cards[i]->sequence + 1);
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]), selectable_cards[i]->sequence + 1);
mainGame->stCardPos[i]->setText(formatBuffer);
if(selectable_cards[i]->location == LOCATION_OVERLAY) {
if(selectable_cards[i]->owner != selectable_cards[i]->overlayTarget->controler)
......@@ -597,13 +594,11 @@ void ClientField::ShowLocationCard() {
mainGame->btnCardDisplay[i]->setPressed(false);
mainGame->btnCardDisplay[i]->setVisible(true);
wchar_t formatBuffer[2048];
if(display_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i]->overlayTarget->location, display_cards[i]->overlayTarget->sequence),
display_cards[i]->overlayTarget->sequence + 1, display_cards[i]->sequence + 1);
if (display_cards[i]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i]->overlayTarget), display_cards[i]->overlayTarget->sequence + 1, display_cards[i]->sequence + 1);
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i]->location, display_cards[i]->sequence),
display_cards[i]->sequence + 1);
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i]), display_cards[i]->sequence + 1);
mainGame->stDisplayPos[i]->setText(formatBuffer);
if(display_cards[i]->location == LOCATION_OVERLAY) {
if(display_cards[i]->owner != display_cards[i]->overlayTarget->controler)
......
#include "data_manager.h"
#include "game.h"
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
#include "client_card.h"
#include "spmemvfs/spmemvfs.h"
#endif
......@@ -245,34 +246,26 @@ const wchar_t* DataManager::GetDesc(uint32_t strCode) const {
return csit->second.desc[offset].c_str();
return unknown_string;
}
const wchar_t* DataManager::GetSysString(int code) const {
if (code < 0 || code > MAX_STRING_ID)
return unknown_string;
auto csit = _sysStrings.find(code);
if(csit == _sysStrings.end())
const wchar_t* DataManager::GetMapString(const wstring_map& table, uint32_t code) const {
auto csit = table.find(code);
if (csit == table.end())
return unknown_string;
return csit->second.c_str();
}
const wchar_t* DataManager::GetVictoryString(int code) const {
auto csit = _victoryStrings.find(code);
if(csit == _victoryStrings.end())
return unknown_string;
return csit->second.c_str();
const wchar_t* DataManager::GetSysString(uint32_t code) const {
return GetMapString(_sysStrings, code);
}
const wchar_t* DataManager::GetCounterName(int code) const {
auto csit = _counterStrings.find(code);
if(csit == _counterStrings.end())
return unknown_string;
return csit->second.c_str();
const wchar_t* DataManager::GetVictoryString(uint32_t code) const {
return GetMapString(_victoryStrings, code);
}
const wchar_t* DataManager::GetSetName(int code) const {
auto csit = _setnameStrings.find(code);
if(csit == _setnameStrings.end())
return unknown_string;
return csit->second.c_str();
const wchar_t* DataManager::GetCounterName(uint32_t code) const {
return GetMapString(_counterStrings, code);
}
const wchar_t* DataManager::GetSetName(uint32_t code) const {
return GetMapString(_setnameStrings, code);
}
std::vector<unsigned int> DataManager::GetSetCodes(std::wstring setname) const {
std::vector<unsigned int> matchingCodes;
std::vector<uint32_t> DataManager::GetSetCodes(std::wstring setname) const {
std::vector<uint32_t> matchingCodes;
for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) {
auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info
if(setname.size() < 2) {
......@@ -305,11 +298,10 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const {
else
return GetSysString(1009);
}
int i = 1000;
int string_id = 0;
for (unsigned filter = LOCATION_DECK; filter <= LOCATION_PZONE; filter <<= 1, ++i) {
if (filter == location) {
string_id = i;
for (int i = 0; i < 10; ++i) {
if ((0x1U << i) == location) {
string_id = STRING_ID_LOCATION + i;
break;
}
}
......@@ -318,6 +310,11 @@ const wchar_t* DataManager::FormatLocation(int location, int sequence) const {
else
return unknown_string;
}
const wchar_t* DataManager::FormatLocation(ClientCard* card) const {
if (!card)
return unknown_string;
return FormatLocation(card->location, card->sequence);
}
std::wstring DataManager::FormatAttribute(unsigned int attribute) const {
std::wstring buffer;
for (int i = 0; i < ATTRIBUTES_COUNT; ++i) {
......@@ -328,7 +325,7 @@ std::wstring DataManager::FormatAttribute(unsigned int attribute) const {
}
}
if (buffer.empty())
return std::wstring(unknown_string);
buffer = unknown_string;
return buffer;
}
std::wstring DataManager::FormatRace(unsigned int race) const {
......@@ -341,7 +338,7 @@ std::wstring DataManager::FormatRace(unsigned int race) const {
}
}
if (buffer.empty())
return std::wstring(unknown_string);
buffer = unknown_string;
return buffer;
}
std::wstring DataManager::FormatType(unsigned int type) const {
......@@ -354,7 +351,7 @@ std::wstring DataManager::FormatType(unsigned int type) const {
}
}
if (buffer.empty())
return std::wstring(unknown_string);
buffer = unknown_string;
return buffer;
}
std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const {
......@@ -368,7 +365,7 @@ std::wstring DataManager::FormatSetName(const uint16_t setcode[]) const {
buffer.append(setname);
}
if (buffer.empty())
return std::wstring(unknown_string);
buffer = unknown_string;
return buffer;
}
std::wstring DataManager::FormatLinkMarker(unsigned int link_marker) const {
......
......@@ -57,6 +57,9 @@ struct CardString {
};
using code_pointer = std::unordered_map<uint32_t, CardDataC>::const_iterator;
using string_pointer = std::unordered_map<uint32_t, CardString>::const_iterator;
using wstring_map = std::unordered_map<uint32_t, std::wstring>;
class ClientCard;
class DataManager {
public:
......@@ -88,23 +91,24 @@ public:
const wchar_t* GetName(uint32_t code) const;
const wchar_t* GetText(uint32_t code) const;
const wchar_t* GetDesc(uint32_t strCode) const;
const wchar_t* GetSysString(int code) const;
const wchar_t* GetVictoryString(int code) const;
const wchar_t* GetCounterName(int code) const;
const wchar_t* GetSetName(int code) const;
std::vector<unsigned int> GetSetCodes(std::wstring setname) const;
const wchar_t* GetSysString(uint32_t code) const;
const wchar_t* GetVictoryString(uint32_t code) const;
const wchar_t* GetCounterName(uint32_t code) const;
const wchar_t* GetSetName(uint32_t code) const;
std::vector<uint32_t> GetSetCodes(std::wstring setname) const;
std::wstring GetNumString(int num, bool bracket = false) const;
const wchar_t* FormatLocation(int location, int sequence) const;
const wchar_t* FormatLocation(ClientCard* card) const;
std::wstring FormatAttribute(unsigned int attribute) const;
std::wstring FormatRace(unsigned int race) const;
std::wstring FormatType(unsigned int type) const;
std::wstring FormatSetName(const uint16_t setcode[]) const;
std::wstring FormatLinkMarker(unsigned int link_marker) const;
std::unordered_map<unsigned int, std::wstring> _counterStrings;
std::unordered_map<unsigned int, std::wstring> _victoryStrings;
std::unordered_map<unsigned int, std::wstring> _setnameStrings;
std::unordered_map<unsigned int, std::wstring> _sysStrings;
wstring_map _counterStrings;
wstring_map _victoryStrings;
wstring_map _setnameStrings;
wstring_map _sysStrings;
#endif
char errmsg[512]{};
const wchar_t* unknown_string{ L"???" };
......@@ -112,9 +116,10 @@ public:
irr::io::IFileSystem* FileSystem{};
#endif
static constexpr int STRING_ID_ATTRIBUTE = 1010;
static constexpr int STRING_ID_RACE = 1020;
static constexpr int STRING_ID_TYPE = 1050;
static constexpr uint32_t STRING_ID_LOCATION = 1000;
static constexpr uint32_t STRING_ID_ATTRIBUTE = 1010;
static constexpr uint32_t STRING_ID_RACE = 1020;
static constexpr uint32_t STRING_ID_TYPE = 1050;
static constexpr int TYPES_COUNT = 27;
static unsigned char scriptBuffer[0x100000];
......@@ -136,6 +141,7 @@ public:
#endif
private:
const wchar_t* GetMapString(const wstring_map& table, uint32_t code) const;
std::unordered_map<uint32_t, CardDataC> _datas;
std::unordered_map<uint32_t, CardString> _strings;
std::unordered_map<uint32_t, std::vector<uint16_t>> extra_setcode;
......
......@@ -179,10 +179,12 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
std::sort(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), DataManager::deck_sort_lv);
std::sort(deckManager.current_deck.extra.begin(), deckManager.current_deck.extra.end(), DataManager::deck_sort_lv);
std::sort(deckManager.current_deck.side.begin(), deckManager.current_deck.side.end(), DataManager::deck_sort_lv);
is_modified = true;
break;
}
case BUTTON_SHUFFLE_DECK: {
std::shuffle(deckManager.current_deck.main.begin(), deckManager.current_deck.main.end(), rnd);
is_modified = true;
break;
}
case BUTTON_SAVE_DECK: {
......@@ -740,6 +742,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
deckManager.current_deck.main.clear();
deckManager.current_deck.extra.clear();
deckManager.current_deck.side.clear();
is_modified = true;
} else if(prev_operation == BUTTON_DELETE_DECK) {
int sel = prev_sel;
mainGame->cbDBDecks->setSelected(sel);
......@@ -1083,6 +1086,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
is_starting_dragging = false;
irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement();
if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == mainGame->imgCard) {
soundManager.PlaySoundEffect(SOUND_CARD_DROP);
ShowBigCard(mainGame->showingcode, 1);
break;
}
......@@ -1112,6 +1116,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case irr::EMIE_LMOUSE_DOUBLE_CLICK: {
irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement();
if(!is_draging && !mainGame->is_siding && root->getElementFromPoint(mouse_pos) == root && hovered_code) {
soundManager.PlaySoundEffect(SOUND_CARD_DROP);
ShowBigCard(hovered_code, 1);
break;
}
......@@ -1371,8 +1376,6 @@ void DeckBuilder::GetHoveredCard() {
if(!is_draging && pre_code != hovered_code) {
if(hovered_code)
mainGame->ShowCardInfo(hovered_code);
if(pre_code)
imageManager.RemoveTexture(pre_code);
}
}
void DeckBuilder::StartFilter() {
......@@ -1393,7 +1396,7 @@ void DeckBuilder::FilterCards() {
results.clear();
struct element_t {
std::wstring keyword;
std::vector<unsigned int> setcodes;
std::vector<uint32_t> setcodes;
enum class type_t {
all,
name,
......
......@@ -905,17 +905,15 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
else
myswprintf(formatBuffer, L"");
} else {
if(select_continuous)
if (select_continuous)
myswprintf(formatBuffer, L"%ls", dataManager.unknown_string);
else if(cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
else if (cant_check_grave && selectable_cards[i]->location == LOCATION_GRAVE)
myswprintf(formatBuffer, L"%ls", dataManager.FormatLocation(selectable_cards[i]->location, 0));
else if(selectable_cards[i + pos]->location == LOCATION_OVERLAY)
else if (selectable_cards[i + pos]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i + pos]->overlayTarget->location, selectable_cards[i + pos]->overlayTarget->sequence),
selectable_cards[i + pos]->overlayTarget->sequence + 1, selectable_cards[i + pos]->sequence + 1);
dataManager.FormatLocation(selectable_cards[i + pos]->overlayTarget), selectable_cards[i + pos]->overlayTarget->sequence + 1, selectable_cards[i + pos]->sequence + 1);
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i + pos]->location, selectable_cards[i + pos]->sequence),
selectable_cards[i + pos]->sequence + 1);
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i + pos]), selectable_cards[i + pos]->sequence + 1);
}
mainGame->stCardPos[i]->setText(formatBuffer);
// color
......@@ -961,13 +959,11 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
mainGame->btnCardDisplay[i]->setImage(imageManager.tCover[display_cards[i + pos]->controler + 2]);
mainGame->btnCardDisplay[i]->setRelativePosition(irr::core::rect<irr::s32>(30 + i * 125, 55, 30 + 120 + i * 125, 225));
wchar_t formatBuffer[2048];
if(display_cards[i + pos]->location == LOCATION_OVERLAY) {
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i + pos]->overlayTarget->location, display_cards[i + pos]->overlayTarget->sequence),
display_cards[i + pos]->overlayTarget->sequence + 1, display_cards[i + pos]->sequence + 1);
} else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i + pos]->location, display_cards[i + pos]->sequence),
display_cards[i + pos]->sequence + 1);
if(display_cards[i + pos]->location == LOCATION_OVERLAY)
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(display_cards[i + pos]->overlayTarget), display_cards[i + pos]->overlayTarget->sequence + 1, display_cards[i + pos]->sequence + 1);
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(display_cards[i + pos]), display_cards[i + pos]->sequence + 1);
mainGame->stDisplayPos[i]->setText(formatBuffer);
if(display_cards[i + pos]->location == LOCATION_OVERLAY) {
if(display_cards[i + pos]->owner != display_cards[i + pos]->overlayTarget->controler)
......
......@@ -1135,16 +1135,13 @@ void Game::InitStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, i
scrCardText->setPos(0);
}
std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, irr::u32 pos) {
size_t pbuffer = 0;
irr::u32 _width = 0, _height = 0;
wchar_t prev = 0;
wchar_t strBuffer[4096]{};
constexpr size_t buffer_len = sizeof strBuffer / sizeof strBuffer[0] - 1;
std::wstring result;
result.reserve(4096);
const size_t text_len = std::wcslen(text);
for(size_t i = 0; i < text_len ; ++i) {
if (pbuffer >= buffer_len)
break;
wchar_t c = text[i];
irr::u32 w = font->getCharDimension(c).Width + font->getKerningWidth(c, prev);
prev = c;
......@@ -1152,31 +1149,28 @@ std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cW
continue;
}
if (c == L'\n') {
strBuffer[pbuffer++] = L'\n';
result.push_back(L'\n');
_width = 0;
_height++;
prev = 0;
if (_height == pos)
pbuffer = 0;
result.clear();
continue;
}
if (_width > 0 && _width + w > cWidth) {
strBuffer[pbuffer++] = L'\n';
result.push_back(L'\n');
_width = 0;
_height++;
prev = 0;
if (_height == pos)
pbuffer = 0;
result.clear();
}
if (pbuffer >= buffer_len)
break;
_width += w;
strBuffer[pbuffer++] = c;
result.push_back(c);
}
strBuffer[pbuffer] = 0;
if (pControl)
pControl->setText(strBuffer);
return std::wstring(strBuffer);
pControl->setText(result.c_str());
return result;
}
#endif //YGOPRO_SERVER_MODE
void Game::LoadExpansions() {
......@@ -1397,8 +1391,6 @@ void Game::LoadConfig() {
gameConf.antialias = std::strtol(valbuf, nullptr, 10);
} else if(!std::strcmp(strbuf, "use_d3d")) {
gameConf.use_d3d = std::strtol(valbuf, nullptr, 10) > 0;
} else if(!std::strcmp(strbuf, "use_image_scale")) {
gameConf.use_image_scale = std::strtol(valbuf, nullptr, 10) > 0;
} else if (!std::strcmp(strbuf, "use_image_scale_multi_thread")) {
gameConf.use_image_scale_multi_thread = std::strtol(valbuf, nullptr, 10) > 0;
} else if (!std::strcmp(strbuf, "use_image_load_background_thread")) {
......@@ -1533,7 +1525,6 @@ void Game::SaveConfig() {
std::fprintf(fp, "#config file\n#nickname & gamename should be less than 20 characters\n");
char linebuf[CONFIG_LINE_SIZE];
std::fprintf(fp, "use_d3d = %d\n", gameConf.use_d3d ? 1 : 0);
std::fprintf(fp, "use_image_scale = %d\n", gameConf.use_image_scale ? 1 : 0);
std::fprintf(fp, "use_image_scale_multi_thread = %d\n", gameConf.use_image_scale_multi_thread ? 1 : 0);
std::fprintf(fp, "use_image_load_background_thread = %d\n", gameConf.use_image_load_background_thread ? 1 : 0);
std::fprintf(fp, "antialias = %d\n", gameConf.antialias);
......
......@@ -57,7 +57,6 @@ bool IsExtension(const char* filename, const char(&extension)[N]) {
#ifndef YGOPRO_SERVER_MODE
struct Config {
bool use_d3d{ false };
bool use_image_scale{ true };
bool use_image_scale_multi_thread{ true };
#ifdef _OPENMP
bool use_image_load_background_thread{ false };
......
This diff is collapsed.
......@@ -10,13 +10,17 @@
namespace ygo {
class ImageManager {
private:
void resizeImage(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
irr::video::ITexture* addTexture(const char* name, irr::video::IImage* srcimg, irr::s32 width, irr::s32 height);
public:
bool Initial();
void SetDevice(irr::IrrlichtDevice* dev);
void ClearTexture();
void RemoveTexture(int code);
void ResizeTexture();
irr::video::ITexture* GetTextureFromFile(const char* file, irr::s32 width, irr::s32 height);
irr::video::IImage* GetImage(int code);
irr::video::ITexture* GetTexture(int code, irr::s32 width, irr::s32 height);
irr::video::ITexture* GetTexture(int code, bool fit = false);
irr::video::ITexture* GetBigPicture(int code, float zoom);
irr::video::ITexture* GetTextureThumb(int code);
......
#include "image_resizer.h"
#include <cmath>
#ifdef _OPENMP
#include <omp.h>
#endif
#define STB_IMAGE_RESIZE2_IMPLEMENTATION
#include "stb_image_resize2.h"
namespace ygo {
ImageResizer imageResizer;
struct StbSamplerCache {
STBIR_RESIZE resize{};
int in_w = 0;
int in_h = 0;
int out_w = 0;
int out_h = 0;
stbir_pixel_layout layout = STBIR_BGRA;
bool samplers_built = false;
~StbSamplerCache() {
if(samplers_built) {
stbir_free_samplers(&resize);
samplers_built = false;
}
}
void reset_if_needed(int new_in_w, int new_in_h, int new_out_w, int new_out_h, stbir_pixel_layout new_layout) {
if(new_in_w == in_w && new_in_h == in_h && new_out_w == out_w && new_out_h == out_h && new_layout == layout)
return;
if(samplers_built) {
stbir_free_samplers(&resize);
samplers_built = false;
}
in_w = new_in_w;
in_h = new_in_h;
out_w = new_out_w;
out_h = new_out_h;
layout = new_layout;
resize = STBIR_RESIZE{};
}
};
/**
* Scale image using stb_image_resize2.
* Returns true on success, false on failure or unsupported format.
*/
bool ImageResizer::imageScaleSTB(irr::video::IImage* src, irr::video::IImage* dest) {
if(!src || !dest)
return false;
const auto srcDim = src->getDimension();
const auto destDim = dest->getDimension();
if(srcDim.Width == 0 || srcDim.Height == 0 || destDim.Width == 0 || destDim.Height == 0)
return false;
if(src->getColorFormat() != dest->getColorFormat())
return false;
stbir_pixel_layout layout = STBIR_BGRA;
// Fast-paths (8-bit per channel only):
// - ECF_A8R8G8B8: Irrlicht stores as BGRA in memory on little-endian.
// - ECF_R8G8B8: common for JPEGs (3 channels).
switch(src->getColorFormat()) {
case irr::video::ECF_A8R8G8B8:
layout = STBIR_BGRA;
break;
case irr::video::ECF_R8G8B8:
layout = STBIR_RGB;
break;
default:
return false;
}
void* srcPtr = src->lock();
if(!srcPtr)
return false;
void* destPtr = dest->lock();
if(!destPtr) {
src->unlock();
return false;
}
const int srcStride = (int)src->getPitch();
const int destStride = (int)dest->getPitch();
thread_local StbSamplerCache cache;
cache.reset_if_needed((int)srcDim.Width, (int)srcDim.Height, (int)destDim.Width, (int)destDim.Height, layout);
if(!cache.samplers_built) {
stbir_resize_init(&cache.resize,
srcPtr, (int)srcDim.Width, (int)srcDim.Height, srcStride,
destPtr, (int)destDim.Width, (int)destDim.Height, destStride,
layout, STBIR_TYPE_UINT8);
stbir_set_edgemodes(&cache.resize, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP);
// Use box filters to reduce aliasing when downscaling.
stbir_set_filters(&cache.resize, STBIR_FILTER_BOX, STBIR_FILTER_BOX);
cache.samplers_built = (stbir_build_samplers(&cache.resize) != 0);
if(!cache.samplers_built) {
dest->unlock();
src->unlock();
return false;
}
} else {
// Reuse samplers but update buffer pointers for the current images
stbir_set_buffer_ptrs(&cache.resize, srcPtr, srcStride, destPtr, destStride);
}
const int ok = stbir_resize_extended(&cache.resize);
dest->unlock();
src->unlock();
return ok != 0;
}
/**
* Scale image using nearest neighbor anti-aliasing.
* Function by Warr1024, from https://github.com/minetest/minetest/issues/2419, modified.
*/
void ImageResizer::imageScaleNNAA(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading) {
const auto& srcDim = src->getDimension();
const auto& destDim = dest->getDimension();
if (destDim.Width == 0 || destDim.Height == 0)
return;
// Cache scale ratios.
const double rx = (double)srcDim.Width / destDim.Width;
const double ry = (double)srcDim.Height / destDim.Height;
#pragma omp parallel if(use_threading)
{
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for(irr::s32 dy = 0; dy < (irr::s32)destDim.Height; dy++) {
for(irr::s32 dx = 0; dx < (irr::s32)destDim.Width; dx++) {
// Calculate floating-point source rectangle bounds.
double minsx = dx * rx;
double maxsx = minsx + rx;
double minsy = dy * ry;
double maxsy = minsy + ry;
irr::u32 sx_begin = (irr::u32)std::floor(minsx);
irr::u32 sx_end = (irr::u32)std::ceil(maxsx);
if (sx_end > srcDim.Width)
sx_end = srcDim.Width;
irr::u32 sy_begin = (irr::u32)std::floor(minsy);
irr::u32 sy_end = (irr::u32)std::ceil(maxsy);
if (sy_end > srcDim.Height)
sy_end = srcDim.Height;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
double area = 0, ra = 0, ga = 0, ba = 0, aa = 0;
irr::video::SColor pxl, npxl;
// Loop over the integral pixel positions described by those bounds.
for(irr::u32 sy = sy_begin; sy < sy_end; sy++) {
for(irr::u32 sx = sx_begin; sx < sx_end; sx++) {
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
double pw = 1;
if(minsx > sx)
pw += sx - minsx;
if(maxsx < (sx + 1))
pw += maxsx - sx - 1;
double ph = 1;
if(minsy > sy)
ph += sy - minsy;
if(maxsy < (sy + 1))
ph += maxsy - sy - 1;
double pa = pw * ph;
// Get source pixel and add it to totals, weighted
// by covered area and alpha.
pxl = src->getPixel(sx, sy);
area += pa;
ra += pa * pxl.getRed();
ga += pa * pxl.getGreen();
ba += pa * pxl.getBlue();
aa += pa * pxl.getAlpha();
}
}
// Set the destination image pixel to the average color.
if(area > 0) {
npxl.set((irr::u32)(aa / area + 0.5),
(irr::u32)(ra / area + 0.5),
(irr::u32)(ga / area + 0.5),
(irr::u32)(ba / area + 0.5));
} else {
npxl.set(0);
}
dest->setPixel(dx, dy, npxl);
}
}
} // end of parallel region
}
void ImageResizer::resize(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading) {
if(imageScaleSTB(src, dest))
return;
imageScaleNNAA(src, dest, use_threading);
}
} // namespace ygo
#ifndef IMAGE_RESIZER_H
#define IMAGE_RESIZER_H
#include <irrlicht.h>
namespace ygo {
class ImageResizer {
private:
bool imageScaleSTB(irr::video::IImage* src, irr::video::IImage* dest);
void imageScaleNNAA(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
public:
void resize(irr::video::IImage* src, irr::video::IImage* dest, bool use_threading);
};
extern ImageResizer imageResizer;
} // namespace ygo
#endif // IMAGE_RESIZER_H
......@@ -8,8 +8,10 @@
#ifndef _WIN32
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#include <algorithm>
#include <string>
#endif
#ifdef _WIN32
......@@ -182,7 +184,7 @@ public:
bool success = true;
TraversalDir(dir, [dir, &success](const char *name, bool isdir) {
char full_path[1024];
int len = mysnprintf(full_path, "%s/%s", dir, name);
int len = std::snprintf(full_path, sizeof(full_path), "%s/%s", dir, name);
if (len < 0 || len >= (int)(sizeof full_path)) {
success = false;
return;
......@@ -234,7 +236,7 @@ public:
file_unit funit;
#endif
char fname[1024];
int len = mysnprintf(fname, "%s/%s", path, dirp->d_name);
int len = std::snprintf(fname, sizeof(fname), "%s/%s", path, dirp->d_name);
if (len < 0 || len >= (int)(sizeof fname))
continue;
stat(fname, &fileStat);
......
......@@ -88,143 +88,142 @@ void SoundManager::PlaySoundEffect(int sound) {
#ifdef YGOPRO_USE_AUDIO
if(!mainGame->chkEnableSound->isChecked())
return;
char soundName[32];
std::string soundName;
switch(sound) {
case SOUND_SUMMON: {
strcpy(soundName, "summon");
soundName = "summon";
break;
}
case SOUND_SPECIAL_SUMMON: {
strcpy(soundName, "specialsummon");
soundName = "specialsummon";
break;
}
case SOUND_ACTIVATE: {
strcpy(soundName, "activate");
soundName = "activate";
break;
}
case SOUND_SET: {
strcpy(soundName, "set");
soundName = "set";
break;
}
case SOUND_FLIP: {
strcpy(soundName, "flip");
soundName = "flip";
break;
}
case SOUND_REVEAL: {
strcpy(soundName, "reveal");
soundName = "reveal";
break;
}
case SOUND_EQUIP: {
strcpy(soundName, "equip");
soundName = "equip";
break;
}
case SOUND_DESTROYED: {
strcpy(soundName, "destroyed");
soundName = "destroyed";
break;
}
case SOUND_BANISHED: {
strcpy(soundName, "banished");
soundName = "banished";
break;
}
case SOUND_TOKEN: {
strcpy(soundName, "token");
soundName = "token";
break;
}
case SOUND_NEGATE: {
strcpy(soundName, "negate");
soundName = "negate";
break;
}
case SOUND_ATTACK: {
strcpy(soundName, "attack");
soundName = "attack";
break;
}
case SOUND_DIRECT_ATTACK: {
strcpy(soundName, "directattack");
soundName = "directattack";
break;
}
case SOUND_DRAW: {
strcpy(soundName, "draw");
soundName = "draw";
break;
}
case SOUND_SHUFFLE: {
strcpy(soundName, "shuffle");
soundName = "shuffle";
break;
}
case SOUND_DAMAGE: {
strcpy(soundName, "damage");
soundName = "damage";
break;
}
case SOUND_RECOVER: {
strcpy(soundName, "gainlp");
soundName = "gainlp";
break;
}
case SOUND_COUNTER_ADD: {
strcpy(soundName, "addcounter");
soundName = "addcounter";
break;
}
case SOUND_COUNTER_REMOVE: {
strcpy(soundName, "removecounter");
soundName = "removecounter";
break;
}
case SOUND_COIN: {
strcpy(soundName, "coinflip");
soundName = "coinflip";
break;
}
case SOUND_DICE: {
strcpy(soundName, "diceroll");
soundName = "diceroll";
break;
}
case SOUND_NEXT_TURN: {
strcpy(soundName, "nextturn");
soundName = "nextturn";
break;
}
case SOUND_PHASE: {
strcpy(soundName, "phase");
soundName = "phase";
break;
}
case SOUND_MENU: {
strcpy(soundName, "menu");
soundName = "menu";
break;
}
case SOUND_BUTTON: {
strcpy(soundName, "button");
soundName = "button";
break;
}
case SOUND_INFO: {
strcpy(soundName, "info");
soundName = "info";
break;
}
case SOUND_QUESTION: {
strcpy(soundName, "question");
soundName = "question";
break;
}
case SOUND_CARD_PICK: {
strcpy(soundName, "cardpick");
soundName = "cardpick";
break;
}
case SOUND_CARD_DROP: {
strcpy(soundName, "carddrop");
soundName = "carddrop";
break;
}
case SOUND_PLAYER_ENTER: {
strcpy(soundName, "playerenter");
soundName = "playerenter";
break;
}
case SOUND_CHAT: {
strcpy(soundName, "chatmessage");
soundName = "chatmessage";
break;
}
default:
break;
return;
}
char soundPath[40];
mysnprintf(soundPath, "./sound/%s.wav", soundName);
std::string soundPath = "./sound/" + soundName + ".wav";
SetSoundVolume(mainGame->gameConf.sound_volume);
#ifdef YGOPRO_USE_MINIAUDIO
ma_engine_play_sound(&engineSound, soundPath, nullptr);
ma_engine_play_sound(&engineSound, soundPath.c_str(), nullptr);
#endif
#ifdef YGOPRO_USE_IRRKLANG
engineSound->play2D(soundPath);
engineSound->play2D(soundPath.c_str());
#endif
#endif // YGOPRO_USE_AUDIO
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -671,6 +671,7 @@
!counter 0x70 盘子指示物
!counter 0x71 纠罪指示物
!counter 0x1072 少女指示物
!counter 0x73 T指示物
#setnames, using tab for comment
!setname 0x1 正义盟军 AOJ
!setname 0x2 次世代 ジェネクス
......@@ -832,7 +833,7 @@
!setname 0x106e 魔导书 魔導書
!setname 0x6f 英豪 ヒロイック
!setname 0x106f 英豪挑战者 HC
#setname 0x206f 英豪冠军 H-C
!setname 0x206f 英豪冠军 HC
!setname 0x70 先史遗产 先史遺産
!setname 0x71 魔偶甜点 マドルチェ
!setname 0x72 齿轮齿轮 ギアギア
......@@ -1278,3 +1279,6 @@
!setname 0x1d8 耀圣 エルフェンノーツ
!setname 0x1d9 磁力 マグネット
!setname 0x1da 世界末日 エンド・オブ・ザ・ワールド
!setname 0x1db 妖精传姬 妖精伝姫
!setname 0x1dc 道化一座 道化の一座
!setname 0x1dd GMX
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment