mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
folder settings & allow picking which dialog to use
This commit is contained in:
parent
1a82d12b7b
commit
56f878ccb3
4 changed files with 71 additions and 56 deletions
|
@ -328,16 +328,11 @@ namespace geode {
|
||||||
FileSettingV3(PrivateMarker);
|
FileSettingV3(PrivateMarker);
|
||||||
static Result<std::shared_ptr<FileSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
|
static Result<std::shared_ptr<FileSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
|
||||||
|
|
||||||
enum class FileType {
|
|
||||||
Any = 0,
|
|
||||||
File = 1,
|
|
||||||
Folder = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::filesystem::path getDefaultValue() const override;
|
std::filesystem::path getDefaultValue() const override;
|
||||||
Result<> isValid(std::filesystem::path const& value) const override;
|
Result<> isValid(std::filesystem::path const& value) const override;
|
||||||
|
|
||||||
FileType getFileType() const;
|
bool isFolder() const;
|
||||||
|
bool useSaveDialog() const;
|
||||||
|
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ private:
|
||||||
{ "float", &FloatSettingV3::parse },
|
{ "float", &FloatSettingV3::parse },
|
||||||
{ "string", &StringSettingV3::parse },
|
{ "string", &StringSettingV3::parse },
|
||||||
{ "file", &FileSettingV3::parse },
|
{ "file", &FileSettingV3::parse },
|
||||||
|
{ "folder", &FileSettingV3::parse },
|
||||||
{ "path", &FileSettingV3::parse },
|
{ "path", &FileSettingV3::parse },
|
||||||
{ "rgb", &Color3BSettingV3::parse },
|
{ "rgb", &Color3BSettingV3::parse },
|
||||||
{ "color", &Color3BSettingV3::parse },
|
{ "color", &Color3BSettingV3::parse },
|
||||||
|
|
|
@ -347,17 +347,17 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
|
||||||
labelBG->setScale(.25f);
|
labelBG->setScale(.25f);
|
||||||
labelBG->setColor({ 0, 0, 0 });
|
labelBG->setColor({ 0, 0, 0 });
|
||||||
labelBG->setOpacity(90);
|
labelBG->setOpacity(90);
|
||||||
labelBG->setContentSize({ 400, 80 });
|
labelBG->setContentSize({ 420, 80 });
|
||||||
this->getButtonMenu()->addChildAtPosition(labelBG, Anchor::Center, ccp(-15, 0));
|
this->getButtonMenu()->addChildAtPosition(labelBG, Anchor::Center, ccp(-10, 0));
|
||||||
|
|
||||||
m_fileIcon = CCSprite::create();
|
m_fileIcon = CCSprite::create();
|
||||||
this->getButtonMenu()->addChildAtPosition(m_fileIcon, Anchor::Left, ccp(3, 0));
|
this->getButtonMenu()->addChildAtPosition(m_fileIcon, Anchor::Left, ccp(5, 0));
|
||||||
|
|
||||||
m_nameLabel = CCLabelBMFont::create("", "bigFont.fnt");
|
m_nameLabel = CCLabelBMFont::create("", "bigFont.fnt");
|
||||||
this->getButtonMenu()->addChildAtPosition(m_nameLabel, Anchor::Left, ccp(11, 0), ccp(0, .5f));
|
this->getButtonMenu()->addChildAtPosition(m_nameLabel, Anchor::Left, ccp(13, 0), ccp(0, .5f));
|
||||||
|
|
||||||
auto selectSpr = CCSprite::createWithSpriteFrameName("GJ_plus2Btn_001.png");
|
auto selectSpr = CCSprite::createWithSpriteFrameName("GJ_plus2Btn_001.png");
|
||||||
selectSpr->setScale(.75f);
|
selectSpr->setScale(.7f);
|
||||||
auto selectBtn = CCMenuItemSpriteExtra::create(
|
auto selectBtn = CCMenuItemSpriteExtra::create(
|
||||||
selectSpr, this, menu_selector(FileSettingNodeV3::onPickFile)
|
selectSpr, this, menu_selector(FileSettingNodeV3::onPickFile)
|
||||||
);
|
);
|
||||||
|
@ -370,18 +370,21 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
|
||||||
|
|
||||||
void FileSettingNodeV3::updateState() {
|
void FileSettingNodeV3::updateState() {
|
||||||
SettingNodeV3::updateState();
|
SettingNodeV3::updateState();
|
||||||
auto ty = this->getSetting()->getFileType();
|
|
||||||
if (ty == FileSettingV3::FileType::Any) {
|
|
||||||
ty = std::filesystem::is_directory(m_path) ?
|
|
||||||
FileSettingV3::FileType::Folder :
|
|
||||||
FileSettingV3::FileType::File;
|
|
||||||
}
|
|
||||||
m_fileIcon->setDisplayFrame(CCSpriteFrameCache::get()->spriteFrameByName(
|
m_fileIcon->setDisplayFrame(CCSpriteFrameCache::get()->spriteFrameByName(
|
||||||
ty == FileSettingV3::FileType::File ? "file.png"_spr : "folderIcon_001.png"
|
this->getSetting()->isFolder() ? "folderIcon_001.png" : "file.png"_spr
|
||||||
));
|
));
|
||||||
limitNodeSize(m_fileIcon, ccp(10, 10), 1.f, .1f);
|
limitNodeSize(m_fileIcon, ccp(10, 10), 1.f, .1f);
|
||||||
m_nameLabel->setString(m_path.filename().string().c_str());
|
if (m_path.empty()) {
|
||||||
m_nameLabel->limitLabelWidth(75, .4f, .1f);
|
m_nameLabel->setString(this->getSetting()->isFolder() ? "No Folder Selected" : "No File Selected");
|
||||||
|
m_nameLabel->setColor(ccGRAY);
|
||||||
|
m_nameLabel->setOpacity(155);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_nameLabel->setString(m_path.filename().string().c_str());
|
||||||
|
m_nameLabel->setColor(ccWHITE);
|
||||||
|
m_nameLabel->setOpacity(255);
|
||||||
|
}
|
||||||
|
m_nameLabel->limitLabelWidth(75, .35f, .1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSettingNodeV3::onCommit() {
|
void FileSettingNodeV3::onCommit() {
|
||||||
|
@ -407,9 +410,9 @@ void FileSettingNodeV3::onPickFile(CCObject*) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_pickListener.setFilter(file::pick(
|
m_pickListener.setFilter(file::pick(
|
||||||
this->getSetting()->getFileType() == FileSettingV3::FileType::Folder ?
|
this->getSetting()->isFolder() ?
|
||||||
file::PickMode::OpenFolder :
|
file::PickMode::OpenFolder :
|
||||||
file::PickMode::OpenFile,
|
(this->getSetting()->useSaveDialog() ? file::PickMode::SaveFile : file::PickMode::OpenFile),
|
||||||
{
|
{
|
||||||
dirs::getGameDir(),
|
dirs::getGameDir(),
|
||||||
this->getSetting()->getFilters().value_or(std::vector<file::FilePickOptions::Filter>())
|
this->getSetting()->getFilters().value_or(std::vector<file::FilePickOptions::Filter>())
|
||||||
|
|
|
@ -609,7 +609,8 @@ class FileSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
std::filesystem::path value;
|
std::filesystem::path value;
|
||||||
std::filesystem::path defaultValue;
|
std::filesystem::path defaultValue;
|
||||||
FileType fileType;
|
bool folder = false;
|
||||||
|
bool useSaveDialog = false; // this option makes no sense if folder = true
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -623,7 +624,7 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
|
||||||
ret->parseDefaultValue(root, ret->m_impl->defaultValue);
|
ret->parseDefaultValue(root, ret->m_impl->defaultValue);
|
||||||
ret->m_impl->value = ret->m_impl->defaultValue;
|
ret->m_impl->value = ret->m_impl->defaultValue;
|
||||||
|
|
||||||
// Replace known paths like `{gd-save-dir}/`
|
// Replace known paths like `{gd-save-dir}/`
|
||||||
try {
|
try {
|
||||||
ret->m_impl->defaultValue = fmt::format(
|
ret->m_impl->defaultValue = fmt::format(
|
||||||
fmt::runtime(ret->m_impl->defaultValue.string()),
|
fmt::runtime(ret->m_impl->defaultValue.string()),
|
||||||
|
@ -639,29 +640,41 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
|
||||||
}
|
}
|
||||||
ret->m_impl->value = ret->m_impl->defaultValue;
|
ret->m_impl->value = ret->m_impl->defaultValue;
|
||||||
|
|
||||||
if (auto ty = root.has("filetype")) {
|
std::string type;
|
||||||
ty.assertIsString();
|
root.needs("type").into(type);
|
||||||
switch (hash(ty.template get<std::string>())) {
|
if (type == "folder") {
|
||||||
case hash("any"): ret->m_impl->fileType = FileType::Any; break;
|
ret->m_impl->folder = true;
|
||||||
case hash("file"): ret->m_impl->fileType = FileType::File; break;
|
// folder-specific stuff if they ever exist
|
||||||
case hash("folder"): ret->m_impl->fileType = FileType::Folder; break;
|
}
|
||||||
default: return Err(
|
else if (type == "file" || type == "path") {
|
||||||
"Setting '{}' in mod {}: Invalid filetype \"{}\"",
|
if (type == "path") {
|
||||||
key, modID, ty.template get<std::string>()
|
log::warn(
|
||||||
|
"Setting '{}' in mod {}: the \"path\" type has been "
|
||||||
|
"deprecated, use \"type\": \"file\" or \"type\": \"folder\" instead",
|
||||||
|
key, modID
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
std::string dialogType;
|
||||||
|
root.has("dialog").into(dialogType);
|
||||||
if (auto controls = root.has("control")) {
|
switch (hash(dialogType)) {
|
||||||
auto filters = std::vector<file::FilePickOptions::Filter>();
|
case hash("save"): ret->m_impl->useSaveDialog = true; break;
|
||||||
for (auto& item : controls.has("filters").items()) {
|
case hash("open"): ret->m_impl->useSaveDialog = false; break;
|
||||||
utils::file::FilePickOptions::Filter filter;
|
case hash(""): break;
|
||||||
item.has("description").into(filter.description);
|
default: return Err("Setting '{}' in mod {}: unknown \"dialog\" type \"{}\"", key, modID, dialogType);
|
||||||
item.has("files").into(filter.files);
|
|
||||||
filters.push_back(filter);
|
|
||||||
}
|
}
|
||||||
if (!filters.empty()) {
|
|
||||||
ret->m_impl->filters.emplace(filters);
|
// Filter controls only make sense for files but not for folders
|
||||||
|
if (auto controls = root.has("control")) {
|
||||||
|
auto filters = std::vector<file::FilePickOptions::Filter>();
|
||||||
|
for (auto& item : controls.has("filters").items()) {
|
||||||
|
utils::file::FilePickOptions::Filter filter;
|
||||||
|
item.has("description").into(filter.description);
|
||||||
|
item.has("files").into(filter.files);
|
||||||
|
filters.push_back(filter);
|
||||||
|
}
|
||||||
|
if (!filters.empty()) {
|
||||||
|
ret->m_impl->filters.emplace(filters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,22 +689,25 @@ std::filesystem::path FileSettingV3::getDefaultValue() const {
|
||||||
return m_impl->defaultValue;
|
return m_impl->defaultValue;
|
||||||
}
|
}
|
||||||
Result<> FileSettingV3::isValid(std::filesystem::path const& value) const {
|
Result<> FileSettingV3::isValid(std::filesystem::path const& value) const {
|
||||||
if (m_impl->fileType != FileType::Any) {
|
std::error_code ec;
|
||||||
if (!std::filesystem::exists(value)) {
|
if (m_impl->folder) {
|
||||||
return Err("{} must exist", m_impl->fileType == FileType::File ? "File" : "Folder");
|
if (!std::filesystem::is_directory(value, ec)) {
|
||||||
}
|
|
||||||
if (m_impl->fileType == FileType::File && !std::filesystem::is_regular_file(value)) {
|
|
||||||
return Err("Value must be a file");
|
|
||||||
}
|
|
||||||
if (m_impl->fileType == FileType::Folder && !std::filesystem::is_directory(value)) {
|
|
||||||
return Err("Value must be a folder");
|
return Err("Value must be a folder");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (!std::filesystem::is_regular_file(value, ec)) {
|
||||||
|
return Err("Value must be a file");
|
||||||
|
}
|
||||||
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSettingV3::FileType FileSettingV3::getFileType() const {
|
bool FileSettingV3::isFolder() const {
|
||||||
return m_impl->fileType;
|
return m_impl->folder;
|
||||||
|
}
|
||||||
|
bool FileSettingV3::useSaveDialog() const {
|
||||||
|
return m_impl->useSaveDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::getFilters() const {
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::getFilters() const {
|
||||||
|
|
Loading…
Reference in a new issue