Implement all the missing parts of the Edit Sheets and Edit Sounds dialogs
- On load, the game now detects graphic sheets and sounds whose IDs are "discontinuous", as well as graphics intended to directly replace preset graphic sheets. - Edit sheets dialog can now handle "discontinuous" graphics. (The edit sounds dialog already could.) - Edit sheets dialog prompts user to create a new sheet if there are none already, and also if there are some but not ID 0 (in the latter case they can cancel and still edit the sheets). - Edit sheets dialog prompts user to convert sheets if the scenario is legacy, rather than doing it silently - Edit sheets dialog now has "new" and "delete" buttons - Edit sounds dialog now has functioning "delete" button
This commit is contained in:
@@ -53,20 +53,10 @@ graphics.</p>
|
||||
will work). For monster, item, and missile graphics, the slots must have a transparent
|
||||
background.</p>
|
||||
|
||||
<p>Once you have your graphics sheet, there are a few ways to get it into the
|
||||
scenario. A scenario generally consists of a archive file (specifically, a gzipped
|
||||
tarball) containing various resource files, so you could put the graphics into the archive
|
||||
yourself, either by decompressing it and recompressing it or by using a program that
|
||||
allows you to open an archive without uncompressing it.</p>
|
||||
|
||||
<p>However, there's an easier way. Open your scenario in the scenario editor, then go to
|
||||
the OBoE temporary files folder, where you'll find an uncompressed copy of your scenario.
|
||||
(On the Mac, this can be found at "~/Library/Application Support/Blades of Exile"; on
|
||||
Windows, it will be at "%APPDATA%/Blades of Exile".) Simply drop the files into the
|
||||
graphics subdirectory within the scenario directory (if it doesn't exist, you can create
|
||||
it), then return to the scenario editor and save the scenario. The scenario will
|
||||
automatically add the new graphics to the archived copy of the scenario. You may need to
|
||||
reload the scenario in the editor before it notice them, however.</p>
|
||||
<p>Once you have your graphics sheet, the easiest way to get it into the scenario is to
|
||||
select "Edit Custom Graphic Sheets" from the "Scenario" menu and either paste the image in
|
||||
or click "Import" to load it in from a file. You may also need to click "New" first to
|
||||
ensure the target sheet actually exists.</p>
|
||||
|
||||
<h2>Placing and Using Your Custom Graphics</h2>
|
||||
|
||||
|
15
rsrc/dialogs/add-new-sheet.xml
Normal file
15
rsrc/dialogs/add-new-sheet.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog skin='light' defbtn='new'>
|
||||
<pict type='dlog' num='16' top='6' left='6'/>
|
||||
<text top='6' left='48' width='252' height='101'>
|
||||
Before you create the new sheet, you need to decide what its sheet number will be.
|
||||
Use the default value if you intend to fill the sheet with graphics such as terrains, items, monsters, etc.
|
||||
However, if you intend to use the sheet for certain special nodes that request a full sheet,
|
||||
you should probably give it a number of 100 or greater.
|
||||
</text>
|
||||
<text top='111' left='48' width='80' height='16'>Sheet number:</text>
|
||||
<field name='num' top='110' left='138' width='80' height='16'/>
|
||||
<button name='cancel' type='regular' top='141' left='234'>Cancel</button>
|
||||
<button name='new' type='regular' top='141' left='169'>Create</button>
|
||||
</dialog>
|
14
rsrc/dialogs/convert-pics-now.xml
Normal file
14
rsrc/dialogs/convert-pics-now.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog skin='light' defbtn='convert'>
|
||||
<pict type='dlog' num='16' top='6' left='6'/>
|
||||
<text top='6' left='48' width='252' height='121'>
|
||||
This scenario was loaded from a legacy file, and as such its custom graphics have not yet been converted.
|
||||
They need to be converted before you can edit them in the scenario editor.
|
||||
This will automatically happen when you save, but if you prefer, you can convert them now.
|
||||
Be aware that the conversion converts white to transparency,
|
||||
so it may create unwanted holes if you had terrain or dialog graphics that used pure white.
|
||||
</text>
|
||||
<button name='cancel' type='regular' top='131' left='234'>Cancel</button>
|
||||
<button name='convert' type='large' top='131' left='128'>Convert Now</button>
|
||||
</dialog>
|
12
rsrc/dialogs/have-no-pics.xml
Normal file
12
rsrc/dialogs/have-no-pics.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog skin='light' defbtn='new'>
|
||||
<pict type='dlog' num='16' top='6' left='6'/>
|
||||
<text top='6' left='48' width='252' height='51'>
|
||||
You don't yet have any custom sheets in this scenario!
|
||||
Would you like to create a new empty sheet?
|
||||
You can then paste your graphics in or import them from a file.
|
||||
</text>
|
||||
<button name='cancel' type='regular' top='61' left='234'>Cancel</button>
|
||||
<button name='new' type='large' top='61' left='128'>Create New</button>
|
||||
</dialog>
|
14
rsrc/dialogs/have-only-full-pics.xml
Normal file
14
rsrc/dialogs/have-only-full-pics.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog skin='light' defbtn='new'>
|
||||
<pict type='dlog' num='16' top='6' left='6'/>
|
||||
<text top='6' left='48' width='252' height='91'>
|
||||
Though this scenario does currently have some custom sheets,
|
||||
they will not be loaded for normal graphics and can only be used in special nodes that request a full sheet.
|
||||
This is because there is no sheet #0.
|
||||
Would you like to create a blank sheet #0?
|
||||
You can then paste in your graphics or import from a file.
|
||||
</text>
|
||||
<button name='cancel' type='regular' top='101' left='234'>Cancel</button>
|
||||
<button name='new' type='large' top='101' left='128'>Create New</button>
|
||||
</dialog>
|
13
rsrc/dialogs/must-delete-in-order.xml
Normal file
13
rsrc/dialogs/must-delete-in-order.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog skin='light' defbtn='cancel'>
|
||||
<pict type='dlog' num='16' top='6' left='6'/>
|
||||
<text top='6' left='48' width='252' height='91'>
|
||||
Warning: By deleting this sheet, graphics on subsequent sheets will no longer be recognized by the game.
|
||||
You can delete the sheet anyway, or you can move the subsequent sheets back one, overwriting this sheet.
|
||||
Note that, either way, anything referencing graphics on these sheets will have to be updated.
|
||||
</text>
|
||||
<button name='cancel' type='regular' top='101' left='234'>Cancel</button>
|
||||
<button name='move' type='large' top='101' left='63'>Move Sheets</button>
|
||||
<button name='del' type='regular' top='101' left='169'>Delete</button>
|
||||
</dialog>
|
@@ -493,6 +493,7 @@ void cPict::recalcRect() {
|
||||
break;
|
||||
case PIC_FULL:
|
||||
case PIC_CUSTOM_FULL:
|
||||
if(drawScaled) break;
|
||||
auto sheet = getSheet(SHEET_FULL, picNum);
|
||||
sf::Vector2u sz = sheet->getSize();
|
||||
bounds.width() = sz.x;
|
||||
|
@@ -3308,19 +3308,51 @@ void edit_custom_pics_types() {
|
||||
pic_dlg.run();
|
||||
}
|
||||
|
||||
void set_dlg_custom_sheet(cDialog& me, size_t sheet) {
|
||||
static void set_dlg_custom_sheet(cDialog& me, size_t sheet) {
|
||||
me["num"].setTextToNum(sheet);
|
||||
dynamic_cast<cPict&>(me["sheet"]).setPict(sheet, PIC_FULL);
|
||||
}
|
||||
|
||||
extern fs::path tempDir;
|
||||
void edit_custom_sheets() {
|
||||
// TODO: What about "disconnected" sheets? eg, we have sheets 0-6, but also sheet 100.
|
||||
int max_pic = -1;
|
||||
std::vector<int> all_pics;
|
||||
fs::path pic_dir = tempDir/"scenario/graphics";
|
||||
if(!fs::exists(pic_dir)) fs::create_directories(pic_dir);
|
||||
for(fs::directory_iterator iter(pic_dir); iter != fs::directory_iterator(); iter++) {
|
||||
std::string fname = iter->path().filename().string().c_str();
|
||||
int dot = fname.find_last_of('.');
|
||||
if(fname.substr(0,5) == "sheet" && fname.substr(dot) == ".png" && std::all_of(fname.begin()+5, fname.begin()+dot, isdigit)) {
|
||||
int this_pic = boost::lexical_cast<int>(fname.substr(5,dot-5));
|
||||
max_pic = max(max_pic, this_pic);
|
||||
all_pics.push_back(this_pic);
|
||||
}
|
||||
}
|
||||
|
||||
// First, make sure we even have custom graphics! Also make sure they're not legacy format.
|
||||
if(spec_scen_g.numSheets < 1) {
|
||||
bool must_init_spec_g = false;
|
||||
if(max_pic < 0) {
|
||||
if(cChoiceDlog("have-no-pics", {"cancel", "new"}).show() == "cancel")
|
||||
return;
|
||||
must_init_spec_g = true;
|
||||
} else if(max_pic >= 0 && spec_scen_g.numSheets < 1) {
|
||||
if(cChoiceDlog("have-only-full-pics", {"cancel", "new"}).show() == "new")
|
||||
must_init_spec_g = true;
|
||||
} else if(spec_scen_g.is_old) {
|
||||
if(cChoiceDlog("convert-pics-now", {"cancel", "convert"}).show() == "cancel")
|
||||
return;
|
||||
spec_scen_g.convert_sheets();
|
||||
}
|
||||
|
||||
if(must_init_spec_g) {
|
||||
spec_scen_g.clear();
|
||||
spec_scen_g.sheets = new sf::Texture[1];
|
||||
spec_scen_g.numSheets = 1;
|
||||
spec_scen_g.sheets[0].create(280, 360);
|
||||
spec_scen_g.sheets[0].copyToImage().saveToFile((pic_dir/"sheet0.png").string().c_str());
|
||||
all_pics.insert(all_pics.begin(), 0);
|
||||
}
|
||||
|
||||
set_cursor(watch_curs);
|
||||
|
||||
// Get image data from the sheets in memory
|
||||
@@ -3336,21 +3368,35 @@ void edit_custom_sheets() {
|
||||
cDialog pic_dlg("graphic-sheets");
|
||||
pic_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
|
||||
pic_dlg["okay"].attachClickHandler(std::bind(&cDialog::toast, _1, true));
|
||||
pic_dlg["copy"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
|
||||
pic_dlg["copy"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog&, std::string, eKeyMod) -> bool {
|
||||
if(cur >= spec_scen_g.numSheets) {
|
||||
fs::path fromPath = pic_dir/("sheet" + std::to_string(all_pics[cur]) + ".png");
|
||||
sf::Image img;
|
||||
img.loadFromFile(fromPath.string().c_str());
|
||||
set_clipboard_img(img);
|
||||
return true;
|
||||
}
|
||||
set_clipboard_img(sheets[cur]);
|
||||
return true;
|
||||
});
|
||||
pic_dlg["paste"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
|
||||
pic_dlg["paste"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog&, std::string, eKeyMod) -> bool {
|
||||
auto img = get_clipboard_img();
|
||||
if(img == nullptr) {
|
||||
beep();
|
||||
return true;
|
||||
}
|
||||
if(cur >= spec_scen_g.numSheets) {
|
||||
std::string resName = "sheet" + std::to_string(all_pics[cur]);
|
||||
fs::path toPath = pic_dir/(resName + ".png");
|
||||
img->saveToFile(toPath.string().c_str());
|
||||
ResMgr::free<ImageRsrc>(resName);
|
||||
return true;
|
||||
}
|
||||
sheets[cur] = *img;
|
||||
spec_scen_g.replace_sheet(cur, *img);
|
||||
return true;
|
||||
});
|
||||
pic_dlg["open"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
|
||||
pic_dlg["open"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog&, std::string, eKeyMod) -> bool {
|
||||
fs::path fpath = nav_get_rsrc({"png", "bmp", "jpg", "jpeg", "gif", "psd"});
|
||||
if(fpath.empty()) return true;
|
||||
sf::Image img;
|
||||
@@ -3358,39 +3404,133 @@ void edit_custom_sheets() {
|
||||
beep();
|
||||
return true;
|
||||
}
|
||||
if(cur >= spec_scen_g.numSheets) {
|
||||
std::string resName = "sheet" + std::to_string(all_pics[cur]);
|
||||
fs::path toPath = pic_dir/(resName + ".png");
|
||||
img.saveToFile(toPath.string().c_str());
|
||||
ResMgr::free<ImageRsrc>(resName);
|
||||
return true;
|
||||
}
|
||||
sheets[cur] = img;
|
||||
spec_scen_g.replace_sheet(cur, img);
|
||||
return true;
|
||||
});
|
||||
pic_dlg["save"].attachClickHandler([&sheets,&cur](cDialog&, std::string, eKeyMod) -> bool {
|
||||
pic_dlg["save"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog&, std::string, eKeyMod) -> bool {
|
||||
fs::path fpath = nav_put_rsrc({"png", "bmp", "jpg", "jpeg"});
|
||||
if(fpath.empty()) return true;
|
||||
if(cur >= spec_scen_g.numSheets) {
|
||||
fs::path fromPath = pic_dir/("sheet" + std::to_string(all_pics[cur]) + ".png");
|
||||
sf::Image img;
|
||||
img.loadFromFile(fromPath.string().c_str());
|
||||
img.saveToFile(fpath.string().c_str());
|
||||
return true;
|
||||
}
|
||||
sheets[cur].saveToFile(fpath.string().c_str());
|
||||
return true;
|
||||
});
|
||||
pic_dlg["new"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog& me, std::string, eKeyMod) -> bool {
|
||||
cChoiceDlog pickNum("add-new-sheet", {"cancel", "new"}, &me);
|
||||
pickNum->getControl("num").setTextToNum(spec_scen_g.numSheets);
|
||||
if(pickNum.show() == "cancel") return true;
|
||||
int newSheet = pickNum->getControl("num").getTextAsNum();
|
||||
fs::path sheetPath = pic_dir/("sheet" + std::to_string(newSheet) + ".png");
|
||||
if(newSheet == spec_scen_g.numSheets) {
|
||||
sf::Texture* wasSheets = spec_scen_g.sheets;
|
||||
spec_scen_g.sheets = new sf::Texture[spec_scen_g.numSheets + 1];
|
||||
std::copy_n(wasSheets, spec_scen_g.numSheets, spec_scen_g.sheets);
|
||||
spec_scen_g.sheets[newSheet].create(280,360);
|
||||
spec_scen_g.sheets[newSheet].copyToImage().saveToFile(sheetPath.string().c_str());
|
||||
spec_scen_g.numSheets++;
|
||||
auto iter = all_pics.insert(std::upper_bound(all_pics.begin(), all_pics.end(), newSheet), newSheet);
|
||||
cur = iter - all_pics.begin();
|
||||
} else {
|
||||
auto iter = std::lower_bound(all_pics.begin(), all_pics.end(), newSheet);
|
||||
if(*iter == newSheet) {
|
||||
giveError("Sorry, but that sheet already exists! Try creating a sheet with a different number.", "Sheet number: " + std::to_string(newSheet), &me);
|
||||
return true;
|
||||
}
|
||||
iter = all_pics.insert(iter, newSheet);
|
||||
cur = iter - all_pics.begin();
|
||||
sf::Image img;
|
||||
img.create(280, 360);
|
||||
img.saveToFile(sheetPath.string().c_str());
|
||||
}
|
||||
me["left"].show();
|
||||
me["right"].show();
|
||||
set_dlg_custom_sheet(me, all_pics[cur]);
|
||||
return true;
|
||||
});
|
||||
pic_dlg["del"].attachClickHandler([&sheets,&cur,&all_pics,&pic_dir](cDialog& me, std::string, eKeyMod) -> bool {
|
||||
int which_pic = all_pics[cur];
|
||||
if(which_pic < spec_scen_g.numSheets) {
|
||||
std::string choice = "del";
|
||||
if(which_pic < spec_scen_g.numSheets - 1)
|
||||
choice = cChoiceDlog("must-delete-in-order", {"cancel", "del", "move"}, &me).show();
|
||||
if(choice == "cancel") return true;
|
||||
sf::Texture* wasSheets = spec_scen_g.sheets;
|
||||
if(choice == "move") {
|
||||
spec_scen_g.sheets = new sf::Texture[spec_scen_g.numSheets-1];
|
||||
std::copy_n(wasSheets, which_pic, spec_scen_g.sheets);
|
||||
std::copy(wasSheets + which_pic + 1, wasSheets + spec_scen_g.numSheets, spec_scen_g.sheets + which_pic);
|
||||
spec_scen_g.numSheets--;
|
||||
for(; which_pic < spec_scen_g.numSheets; which_pic++) {
|
||||
fs::path from = pic_dir/("sheet" + std::to_string(which_pic + 1) + ".png");
|
||||
fs::path to = pic_dir/("sheet" + std::to_string(which_pic) + ".png");
|
||||
if(!fs::exists(from)) continue; // Just in case
|
||||
fs::remove(to);
|
||||
fs::rename(from, to);
|
||||
ResMgr::free<ImageRsrc>("sheet" + std::to_string(which_pic));
|
||||
}
|
||||
auto end = std::find(all_pics.begin() + cur, all_pics.end(), which_pic - 1);
|
||||
if(end != all_pics.end())
|
||||
all_pics.erase(end);
|
||||
else {
|
||||
// This shouldn't be reached
|
||||
std::cerr << "Whoops! Somehow failed to remove the index of the deleted sheet!" << std::endl;
|
||||
}
|
||||
} else if(choice == "del") {
|
||||
all_pics.erase(all_pics.begin() + cur);
|
||||
spec_scen_g.numSheets = which_pic;
|
||||
spec_scen_g.sheets = new sf::Texture[which_pic];
|
||||
std::copy_n(wasSheets, which_pic, spec_scen_g.sheets);
|
||||
ResMgr::free<ImageRsrc>("sheet" + std::to_string(which_pic));
|
||||
}
|
||||
delete[] wasSheets;
|
||||
}
|
||||
fs::path fpath = pic_dir/("sheet" + std::to_string(which_pic) + ".png");
|
||||
if(fs::exists(fpath)) fs::remove(fpath);
|
||||
if(all_pics.size() == 1) {
|
||||
me["left"].hide();
|
||||
me["right"].hide();
|
||||
} else if(all_pics.empty()) {
|
||||
cStrDlog("You've just deleted the last custom graphics sheet, so this dialog will now close. If you want to add more sheets, you can of course reopen the dialog.", "", "Last Sheet Deleted", 16, PIC_DLOG).show();
|
||||
me.toast(true);
|
||||
return true;
|
||||
}
|
||||
if(cur > 0) cur--;
|
||||
set_dlg_custom_sheet(me, all_pics[cur]);
|
||||
return true;
|
||||
});
|
||||
|
||||
// TODO: These buttons not implemented yet
|
||||
pic_dlg["new"].hide();
|
||||
pic_dlg["del"].hide();
|
||||
|
||||
if(spec_scen_g.numSheets == 1) {
|
||||
if(all_pics.size() == 1) {
|
||||
pic_dlg["left"].hide();
|
||||
pic_dlg["right"].hide();
|
||||
} else pic_dlg.attachClickHandlers([&sheets,&cur](cDialog& me, std::string dir, eKeyMod) -> bool {
|
||||
}
|
||||
pic_dlg.attachClickHandlers([&sheets,&cur,&all_pics](cDialog& me, std::string dir, eKeyMod) -> bool {
|
||||
if(dir == "left") {
|
||||
if(cur == 0)
|
||||
cur = spec_scen_g.numSheets - 1;
|
||||
cur = all_pics.size() - 1;
|
||||
else cur--;
|
||||
} else if(dir == "right") {
|
||||
cur++;
|
||||
if(cur >= spec_scen_g.numSheets)
|
||||
if(cur >= all_pics.size())
|
||||
cur = 0;
|
||||
} else return true;
|
||||
set_dlg_custom_sheet(me, cur);
|
||||
set_dlg_custom_sheet(me, all_pics[cur]);
|
||||
return true;
|
||||
}, {"left", "right"});
|
||||
|
||||
set_dlg_custom_sheet(pic_dlg, cur);
|
||||
set_dlg_custom_sheet(pic_dlg, all_pics[cur]);
|
||||
shut_down_menus(5); // So that cmd+O, cmd+N, cmd+S can work
|
||||
pic_dlg.run();
|
||||
|
||||
@@ -3408,8 +3548,7 @@ void edit_custom_sheets() {
|
||||
else shut_down_menus(3);
|
||||
}
|
||||
|
||||
extern fs::path tempDir;
|
||||
static bool edit_custom_sound_action(cDialog& me, std::string action, int curPage, int& max_snd) {
|
||||
static bool edit_custom_sound_action(cDialog& me, std::string action, std::vector<std::string>& snd_names, int curPage, int& max_snd) {
|
||||
size_t a_len = action.length();
|
||||
int which_snd = (curPage + 1) * 100 + (action[a_len-1] - '0');
|
||||
action.erase(action.end() - 1);
|
||||
@@ -3423,7 +3562,10 @@ static bool edit_custom_sound_action(cDialog& me, std::string action, int curPag
|
||||
if(action == "play") {
|
||||
play_sound(-which_snd);
|
||||
} else if(action == "del") {
|
||||
// TODO: Implement this action
|
||||
if(which_snd - 100 < snd_names.size())
|
||||
snd_names[which_snd - 100].clear();
|
||||
fs::remove(sndfile);
|
||||
me["name" + std::to_string(which_snd % 10)].setText("");
|
||||
} else if(action == "open") {
|
||||
fs::path fpath = nav_get_rsrc({"wav"});
|
||||
if(fpath.empty()) return true;
|
||||
@@ -3448,7 +3590,7 @@ static bool edit_custom_sound_action(cDialog& me, std::string action, int curPag
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fill_custom_sounds_page(cDialog& me, const std::vector<std::string>& snd_names, int& curPage, int& max_snd, bool firstTime) {
|
||||
static void fill_custom_sounds_page(cDialog& me, std::vector<std::string>& snd_names, int& curPage, int& max_snd, bool firstTime) {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
int which_snd = (curPage + 1) * 100 + i;
|
||||
std::string id = std::to_string(i);
|
||||
@@ -3458,7 +3600,7 @@ static void fill_custom_sounds_page(cDialog& me, const std::vector<std::string>&
|
||||
"play" + id, "del" + id,
|
||||
"open" + id, "save" + id,
|
||||
};
|
||||
me.attachClickHandlers(std::bind(edit_custom_sound_action, _1, _2, std::ref(curPage), std::ref(max_snd)), buttons);
|
||||
me.attachClickHandlers(std::bind(edit_custom_sound_action, _1, _2, std::ref(snd_names), std::ref(curPage), std::ref(max_snd)), buttons);
|
||||
}
|
||||
me["num" + id].setTextToNum(which_snd);
|
||||
if(which_snd - 100 < snd_names.size())
|
||||
@@ -3496,8 +3638,8 @@ void edit_custom_sounds() {
|
||||
}
|
||||
|
||||
int curPage = 0;
|
||||
fill_custom_sounds_page(snd_dlg, scenario.snd_names, curPage, max_snd, true);
|
||||
auto snd_names = scenario.snd_names;
|
||||
fill_custom_sounds_page(snd_dlg, snd_names, curPage, max_snd, true);
|
||||
|
||||
if(max_snd < 110) {
|
||||
snd_dlg["left"].hide();
|
||||
|
@@ -1881,29 +1881,37 @@ bool load_scenario_v2(fs::path file_to_load, cScenario& scenario) {
|
||||
int num_graphic_sheets = 0;
|
||||
if(is_packed) {
|
||||
fs::remove_all(tempDir/"scenario");
|
||||
int i = 0;
|
||||
std::string fname;
|
||||
while(fname = "scenario/graphics/sheet" + std::to_string(i) + ".png", pack.hasFile(fname)) {
|
||||
std::bitset<65536> have_pic = {0};
|
||||
for(auto& file : pack) {
|
||||
std::string fname = file.filename;
|
||||
int dot = fname.find_last_of('.');
|
||||
if(fname.substr(0,23) == "scenario/graphics/sheet") {
|
||||
if(fname.substr(dot,4) != ".png") continue;
|
||||
if(!std::all_of(fname.begin() + 23, fname.begin() + dot, isdigit)) continue;
|
||||
int i = boost::lexical_cast<int>(fname.substr(23, dot - 23));
|
||||
if(i >= 65536) continue;
|
||||
have_pic[i] = true;
|
||||
} else if(fname.substr(0,18) == "scenario/graphics/") {
|
||||
if(fname.substr(dot,4) != ".png") continue;
|
||||
// This would be an override sheet, one that replaces one of the preset sheets.
|
||||
// Or at least, we're going to assume it is. If it's not, there's no harm done
|
||||
// (except possibly storing a sheet that will never be used).
|
||||
// TODO: A way to edit these sheets in the scenario editor?
|
||||
} else if(fname.substr(0,19) == "scenario/sounds/SND") {
|
||||
if(fname.substr(dot,4) != ".wav") continue;
|
||||
if(!std::all_of(fname.begin() + 19, fname.begin() + dot, isdigit)) continue;
|
||||
} else continue;
|
||||
fs::path path = tempDir/fname;
|
||||
fs::create_directories(path.parent_path());
|
||||
std::istream& graphic = pack.getFile(fname);
|
||||
std::istream& f = pack.getFile(fname);
|
||||
std::ofstream fout(path.string().c_str(), std::ios::binary);
|
||||
fout << graphic.rdbuf();
|
||||
fout << f.rdbuf();
|
||||
fout.close();
|
||||
i++;
|
||||
}
|
||||
// This is a bit of trickery to get it to only count the first consecutive range of sheets
|
||||
while(have_pic[num_graphic_sheets])
|
||||
num_graphic_sheets++;
|
||||
ResMgr::pushPath<ImageRsrc>(tempDir/"scenario"/"graphics");
|
||||
num_graphic_sheets = i;
|
||||
i = 100;
|
||||
while(fname = "scenario/sounds/SND" + std::to_string(i) + ".wav", pack.hasFile(fname)) {
|
||||
fs::path path = tempDir/fname;
|
||||
fs::create_directories(path.parent_path());
|
||||
std::istream& snd = pack.getFile(fname);
|
||||
std::ofstream fout(path.string().c_str(), std::ios::binary);
|
||||
fout << snd.rdbuf();
|
||||
fout.close();
|
||||
i++;
|
||||
}
|
||||
ResMgr::pushPath<SoundRsrc>(tempDir/"scenario"/"sounds");
|
||||
} else {
|
||||
if(fs::is_directory(file_to_load/"graphics"))
|
||||
|
Reference in New Issue
Block a user