mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Added icon for MSE in packages window;
Added resample(image,width,height), instead of always passing in images git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@806 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+20
-6
@@ -15,7 +15,7 @@
|
||||
#include <data/export_template.hpp>
|
||||
#include <util/io/package_manager.hpp>
|
||||
#include <util/platform.hpp>
|
||||
#include <script/to_value.hpp>
|
||||
#include <gui/util.hpp> // load_resource_image
|
||||
#include <wx/filename.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
@@ -195,10 +195,20 @@ PackageDescription::PackageDescription(const Packaged& package)
|
||||
if (full_name.empty()) full_name = short_name;
|
||||
// installer group
|
||||
if (installer_group.empty()) {
|
||||
// "game-style.mse-something" -> "game/style" -> "game"
|
||||
installer_group = replace_all(package.name(),_("-"),_("/"));
|
||||
size_t pos = installer_group.find_last_of(_('/'));
|
||||
// "game-style.mse-something" -> "game/style_short_name"
|
||||
installer_group = package.name();
|
||||
size_t pos = installer_group.find_last_of(_('-'));
|
||||
if (pos != String::npos) installer_group.resize(pos);
|
||||
if (!installer_group.empty()) {
|
||||
installer_group = _("unclassified/") + replace_all(installer_group,_("-"),_("/")) + _("/");
|
||||
} else {
|
||||
installer_group = _("unclassified/");
|
||||
}
|
||||
if (dynamic_cast<const Game*>(&package)) {
|
||||
installer_group += _("Game files");
|
||||
} else {
|
||||
installer_group += short_name;
|
||||
}
|
||||
}
|
||||
// icon
|
||||
InputStreamP file = const_cast<Packaged&>(package).openIconFile();
|
||||
@@ -219,6 +229,9 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) {
|
||||
|
||||
void PackageDescription::merge(const PackageDescription& p2) {
|
||||
if (!icon.Ok() && !icon_url) icon = p2.icon;
|
||||
if (installer_group.empty()) installer_group = p2.installer_group;
|
||||
if (short_name.empty()) short_name = p2.short_name;
|
||||
if (full_name.empty()) full_name = p2.full_name;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(InstallerDescription) {
|
||||
@@ -454,9 +467,10 @@ InstallablePackageP mse_installable_package() {
|
||||
mse_version->version = app_version;
|
||||
PackageDescriptionP mse_description(new PackageDescription);
|
||||
mse_description->name = mse_package;
|
||||
mse_description->short_name = mse_description->full_name = _TITLE_("magic set editor");
|
||||
mse_description->short_name = mse_description->full_name = mse_description->installer_group
|
||||
= _TITLE_("magic set editor");
|
||||
mse_description->position_hint = -100;
|
||||
//mse_description->icon = load_resource_image(_("mse_icon"));
|
||||
mse_description->icon = load_resource_image(_("installer_program"));
|
||||
//mse_description->description = _LABEL_("magic set editor package");
|
||||
return new_intrusive2<InstallablePackage>(mse_version,mse_description);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ enum PackageStatus
|
||||
, PACKAGE_INSTALLABLE = 0x0110 ///< Package can be installed (it makes sense to do so)
|
||||
, PACKAGE_UPDATES = 0x0111 ///< Remote updates available
|
||||
, PACKAGE_MODIFIED = 0x1001 ///< Local changes made
|
||||
, PACKAGE_MISSING_DEP = 0x0200 ///< Missing a dependency for installation
|
||||
, PACKAGE_CONFLICTS = PACKAGE_UPDATES | PACKAGE_MODIFIED
|
||||
};
|
||||
|
||||
|
||||
@@ -31,24 +31,18 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
|
||||
if ((iw == options.width && ih == options.height) || (options.width == 0 && options.height == 0)) {
|
||||
// zoom?
|
||||
if (options.zoom != 1.0) {
|
||||
Image resampled_image(iw * options.zoom, ih * options.zoom, false);
|
||||
resample(image, resampled_image);
|
||||
image = resampled_image;
|
||||
image = resample(image, iw * options.zoom, ih * options.zoom);
|
||||
} else {
|
||||
// already the right size
|
||||
}
|
||||
} else if (options.height == 0) {
|
||||
// width is given, determine height
|
||||
int h = options.width * ih / iw;
|
||||
Image resampled_image(options.width, h, false);
|
||||
resample(image, resampled_image);
|
||||
image = resampled_image;
|
||||
image = resample(image, options.width, h);
|
||||
} else if (options.width == 0) {
|
||||
// height is given, determine width
|
||||
int w = options.height * iw / ih;
|
||||
Image resampled_image(w, options.height, false);
|
||||
resample(image, resampled_image);
|
||||
image = resampled_image;
|
||||
image = resample(image, w, options.height);
|
||||
} else if (options.preserve_aspect == ASPECT_FIT) {
|
||||
// determine actual size of resulting image
|
||||
int w, h;
|
||||
@@ -59,18 +53,14 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
|
||||
w = options.height * iw / ih;
|
||||
h = options.height;
|
||||
}
|
||||
Image resampled_image(w, h, false);
|
||||
resample(image, resampled_image);
|
||||
image = resampled_image;
|
||||
image = resample(image, w, h);
|
||||
} else {
|
||||
Image resampled_image(options.width, options.height, false);
|
||||
if (options.preserve_aspect == ASPECT_BORDER && (options.width < options.height * 3) && (options.height < options.width * 3)) {
|
||||
// preserve the aspect ratio if there is not too much difference
|
||||
resample_preserve_aspect(image, resampled_image);
|
||||
image = resample_preserve_aspect(image, options.width, options.height);
|
||||
} else {
|
||||
resample(image, resampled_image);
|
||||
image = resample(image, options.width, options.height);
|
||||
}
|
||||
image = resampled_image;
|
||||
}
|
||||
// saturate?
|
||||
if (options.saturate) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
/// Resample (resize) an image, uses bilenear filtering
|
||||
void resample(const Image& img_in, Image& img_out);
|
||||
Image resample(const Image& img_in, int width, int height);
|
||||
|
||||
/// Resamples an image, first clips the input image to a specified rectangle
|
||||
/** The selected rectangle is resampled into the entire output image */
|
||||
@@ -35,6 +36,7 @@ enum PreserveAspect
|
||||
|
||||
/// Resample an image, but preserve the aspect ratio by adding a transparent border around the output if needed.
|
||||
void resample_preserve_aspect(const Image& img_in, Image& img_out);
|
||||
Image resample_preserve_aspect(const Image& img_in, int width, int height);
|
||||
|
||||
/// Resample an image to create a sharp result by applying a sharpening filter
|
||||
/** Amount must be between 0 and 100 */
|
||||
|
||||
@@ -125,6 +125,15 @@ void resample_pass(const Image& img_in, Image& img_out, int offset_in, int offse
|
||||
void resample(const Image& img_in, Image& img_out) {
|
||||
resample_and_clip(img_in, img_out, wxRect(0, 0, img_in.GetWidth(), img_in.GetHeight()));
|
||||
}
|
||||
Image resample(const Image& img_in, int width, int height) {
|
||||
if (img_in.GetWidth() == width && img_in.GetHeight() == height) {
|
||||
return img_in; // already the right size
|
||||
} else {
|
||||
Image img_out(width,height,false);
|
||||
resample(img_in, img_out);
|
||||
return img_out;
|
||||
}
|
||||
}
|
||||
|
||||
void resample_and_clip(const Image& img_in, Image& img_out, wxRect rect) {
|
||||
// mask to alpha
|
||||
@@ -171,6 +180,16 @@ void resample_preserve_aspect(const Image& img_in, Image& img_out) {
|
||||
resample_pass(img_temp, img_out, 0, offset_out, img_in.GetHeight(), img_temp.GetWidth(), rheight, img_out.GetWidth(), rwidth, 1, 1);
|
||||
}
|
||||
|
||||
Image resample_preserve_aspect(const Image& img_in, int width, int height) {
|
||||
if (img_in.GetWidth() == width && img_in.GetHeight() == height) {
|
||||
return img_in; // already the right size
|
||||
} else {
|
||||
Image img_out(width,height,false);
|
||||
resample_preserve_aspect(img_in, img_out);
|
||||
return img_out;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Sharpening
|
||||
|
||||
void sharp_downsample(const Image& img_in, Image& img_out, int amount);
|
||||
|
||||
@@ -65,9 +65,7 @@ class CardThumbnailRequest : public ThumbnailRequest {
|
||||
if (image.LoadFile(*parent->set->openIn(filename))) {
|
||||
// two step anti aliased resampling
|
||||
image.Rescale(36, 28); // step 1: no anti aliassing
|
||||
Image image2(18, 14, false); // step 2: with anti aliassing
|
||||
resample(image, image2);
|
||||
return image2;
|
||||
return resample(image, 18, 14); // step 2: with anti aliassing
|
||||
} else {
|
||||
return Image();
|
||||
}
|
||||
|
||||
@@ -541,8 +541,7 @@ void ImageSliceSelector::createBitmap() {
|
||||
// create image, resampled to fit in control
|
||||
wxSize s = GetClientSize();
|
||||
int width = s.GetWidth() - 2*border, height = s.GetHeight() - 2*border;
|
||||
Image img(width, height, false);
|
||||
resample(slice.source, img);
|
||||
Image img = resample(slice.source, width, height);
|
||||
bitmap = Bitmap(img);
|
||||
scaleX = (double)width / slice.source.GetWidth();
|
||||
scaleY = (double)height / slice.source.GetHeight();
|
||||
|
||||
+88
-46
@@ -139,14 +139,31 @@ class PackageUpdateList : public TreeList {
|
||||
typedef intrusive_ptr<TreeItem> TreeItemP;
|
||||
class TreeItem : public Item {
|
||||
public:
|
||||
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
|
||||
String label;
|
||||
vector<TreeItemP> children;
|
||||
InstallablePackageP package;
|
||||
Bitmap icon, icon_grey;
|
||||
// positioning
|
||||
enum PackageType {
|
||||
TYPE_PROG,
|
||||
TYPE_LOCALE,
|
||||
TYPE_GAME,
|
||||
TYPE_STYLESHEET,
|
||||
TYPE_EXPORT_TEMPLATE,
|
||||
TYPE_SYMBOL_FONT,
|
||||
TYPE_INCLUDE,
|
||||
TYPE_FONT,
|
||||
TYPE_OTHER,
|
||||
} position_type;
|
||||
int position_hint;
|
||||
|
||||
void add(const InstallablePackageP& package, const String& path, int level = -1);
|
||||
void toItems(vector<TreeList::ItemP>& items);
|
||||
void setIcon(const Image& image);
|
||||
bool highlight() const;
|
||||
|
||||
static PackageType package_type(const PackageDescription& desc);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -156,6 +173,22 @@ DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP);
|
||||
|
||||
|
||||
void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const String& path, int level) {
|
||||
// this node
|
||||
this->level = level;
|
||||
PackageType new_type = package_type(*package->description);
|
||||
int new_hint = package->description->position_hint;
|
||||
if (new_type < position_type || (new_type == position_type && new_hint < position_hint)) {
|
||||
// this is a lower position hint, use it
|
||||
position_type = new_type;
|
||||
position_hint = new_hint;
|
||||
}
|
||||
// end of the path?
|
||||
if (path.empty()) {
|
||||
assert(!this->package);
|
||||
this->package = package;
|
||||
return;
|
||||
}
|
||||
// split path
|
||||
size_t pos = path.find_first_of(_('/'));
|
||||
String name = path.substr(0,pos);
|
||||
String rest = pos == String::npos ? _("") : path.substr(pos+1);
|
||||
@@ -163,17 +196,12 @@ void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const
|
||||
FOR_EACH(ti, children) {
|
||||
if (ti->label == name) {
|
||||
// already have this child
|
||||
if (pos == String::npos) {
|
||||
if (ti->package) {
|
||||
// two packages with the same path
|
||||
TreeItemP ti2(new TreeItem);
|
||||
ti2->level = level + 1;
|
||||
ti2->label = name;
|
||||
ti2->package = package;
|
||||
children.insert(ti_IT.first, ti2);
|
||||
} else {
|
||||
ti->package = package;
|
||||
}
|
||||
if (pos == String::npos && ti->package) {
|
||||
// two packages with the same path
|
||||
TreeItemP ti2(new TreeItem);
|
||||
ti2->label = name;
|
||||
children.insert(ti_IT.first, ti2);
|
||||
ti2->add(package, rest, level + 1);
|
||||
} else {
|
||||
ti->add(package, rest, level + 1);
|
||||
}
|
||||
@@ -183,20 +211,15 @@ void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const
|
||||
// don't have this child
|
||||
TreeItemP ti(new TreeItem);
|
||||
children.push_back(ti);
|
||||
ti->level = level + 1;
|
||||
ti->label = name;
|
||||
if (pos == String::npos) {
|
||||
ti->package = package;
|
||||
} else {
|
||||
ti->add(package, rest, level + 1);
|
||||
}
|
||||
ti->add(package, rest, level + 1);
|
||||
}
|
||||
|
||||
bool compare_pos_hint(const PackageUpdateList::TreeItemP& a, const PackageUpdateList::TreeItemP& b) {
|
||||
int pa = a->package ? a->package->description->position_hint : 0;
|
||||
int pb = b->package ? b->package->description->position_hint : 0;
|
||||
if (pa < pb) return true;
|
||||
if (pa > pb) return false;
|
||||
if (a->position_type < b->position_type) return true;
|
||||
if (a->position_type > b->position_type) return false;
|
||||
if (a->position_hint < b->position_hint) return true;
|
||||
if (a->position_hint > b->position_hint) return false;
|
||||
return a->label < b->label;
|
||||
}
|
||||
|
||||
@@ -214,6 +237,38 @@ bool PackageUpdateList::TreeItem::highlight() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
PackageUpdateList::TreeItem::PackageType PackageUpdateList::TreeItem::package_type(const PackageDescription& desc) {
|
||||
if (desc.name == mse_package) return TYPE_PROG;
|
||||
size_t pos = desc.name.find_last_of(_('.'));
|
||||
if (pos == String::npos) return TYPE_OTHER;
|
||||
if (is_substr(desc.name,pos,_(".mse-locale"))) return TYPE_LOCALE;
|
||||
if (is_substr(desc.name,pos,_(".mse-game"))) return TYPE_GAME;
|
||||
if (is_substr(desc.name,pos,_(".mse-style"))) return TYPE_STYLESHEET;
|
||||
if (is_substr(desc.name,pos,_(".mse-export-template"))) return TYPE_EXPORT_TEMPLATE;
|
||||
if (is_substr(desc.name,pos,_(".mse-symbol-font"))) return TYPE_SYMBOL_FONT;
|
||||
if (is_substr(desc.name,pos,_(".mse-include"))) return TYPE_INCLUDE;
|
||||
if (is_substr(desc.name,pos,_(".ttf"))) return TYPE_FONT;
|
||||
return TYPE_OTHER;
|
||||
}
|
||||
|
||||
void PackageUpdateList::TreeItem::setIcon(const Image& img) {
|
||||
Image image = img;
|
||||
int iw = image.GetWidth(), ih = image.GetHeight();
|
||||
if (ih > 107) {
|
||||
int w = 107 * iw / ih;
|
||||
image = resample(image, w, 107);
|
||||
} else if (iw > 107) {
|
||||
int h = 107 * ih / iw;
|
||||
image = resample(image, 107, h);
|
||||
}
|
||||
if (package) package->description->icon = image;
|
||||
Image resampled = resample_preserve_aspect(image,16,16);
|
||||
icon = Bitmap(resampled);
|
||||
saturate(resampled, -.75);
|
||||
set_alpha(resampled,0.5);
|
||||
icon_grey = Bitmap(resampled);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : PackageIconRequest
|
||||
|
||||
/// wx doesn't allow seeking on InputStreams from a wxURL
|
||||
@@ -273,13 +328,7 @@ class PackageIconRequest : public ThumbnailRequest {
|
||||
}
|
||||
virtual void store(const Image& image) {
|
||||
if (!image.Ok()) return;
|
||||
ti->package->description->icon = image;
|
||||
Image resampled(16,16,false);
|
||||
resample_preserve_aspect(image,resampled);
|
||||
ti->icon = Bitmap(resampled);
|
||||
saturate(resampled, -.75);
|
||||
set_alpha(resampled,0.5);
|
||||
ti->icon_grey = Bitmap(resampled);
|
||||
ti->setIcon(image);
|
||||
list->Refresh(false);
|
||||
}
|
||||
private:
|
||||
@@ -294,8 +343,7 @@ void PackageUpdateList::initItems() {
|
||||
TreeItem root;
|
||||
FOR_EACH(ip, parent->installable_packages) {
|
||||
String group = ip->description->installer_group;
|
||||
if (!group.empty()) group += _("/");
|
||||
group += ip->description->short_name;
|
||||
if (group.empty()) group = _("custom");
|
||||
root.add(ip, group);
|
||||
}
|
||||
// tree to treelist items
|
||||
@@ -307,23 +355,17 @@ void PackageUpdateList::initItems() {
|
||||
const InstallablePackageP& p = ti.package;
|
||||
Image image;
|
||||
if (p && p->description->icon.Ok()) {
|
||||
Image resampled(16,16,false);
|
||||
resample_preserve_aspect(p->description->icon, resampled);
|
||||
image = resampled;
|
||||
ti.setIcon(p->description->icon);
|
||||
} else if (p) {
|
||||
image = load_resource_image(_("installer_package"));
|
||||
} else if (ti.label == _("locales")) {
|
||||
image = load_resource_image(_("installer_locales"));
|
||||
ti.setIcon(load_resource_image(_("installer_package")));
|
||||
if (!p->description->icon_url.empty()) {
|
||||
// download icon
|
||||
thumbnail_thread.request(new_intrusive2<PackageIconRequest>(this,&ti));
|
||||
}
|
||||
} else if (ti.position_type == TreeItem::TYPE_LOCALE) {
|
||||
ti.setIcon(load_resource_image(_("installer_locales")));
|
||||
} else {
|
||||
image = load_resource_image(_("installer_group"));
|
||||
}
|
||||
ti.icon = Bitmap(image);
|
||||
saturate(image, -.75);
|
||||
set_alpha(image, 0.5);
|
||||
ti.icon_grey = Bitmap(image);
|
||||
if (p && !p->description->icon.Ok() && !p->description->icon_url.empty()) {
|
||||
// download icon
|
||||
thumbnail_thread.request(new_intrusive2<PackageIconRequest>(this,&ti));
|
||||
ti.setIcon(load_resource_image(_("installer_group")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,7 +378,7 @@ void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int
|
||||
const Bitmap& bmp = ti.highlight() ? ti.icon : ti.icon_grey;
|
||||
if (bmp.Ok()) dc.DrawBitmap(bmp,x,y);
|
||||
dc.SetTextForeground(color);
|
||||
dc.DrawText(ti.label, x+18, y+2);
|
||||
dc.DrawText(capitalize_sentence(ti.label), x+18, y+2);
|
||||
} else if (column == 1 && ti.package) {
|
||||
// Status
|
||||
int stat = ti.package->status;
|
||||
|
||||
@@ -77,9 +77,9 @@ void StatCategoryList::drawItem(DC& dc, int x, int y, size_t item, bool selected
|
||||
if (!cat.icon_filename.empty() && !cat.icon.Ok()) {
|
||||
InputStreamP file = game->openIn(cat.icon_filename);
|
||||
Image img(*file);
|
||||
Image resampled(21, 21);
|
||||
resample_preserve_aspect(img, resampled);
|
||||
if (img.Ok()) cat.icon = Bitmap(resampled);
|
||||
if (img.Ok()) {
|
||||
cat.icon = Bitmap(resample_preserve_aspect(img, 21, 21));
|
||||
}
|
||||
}
|
||||
if (cat.icon.Ok()) {
|
||||
dc.DrawBitmap(cat.icon, x+1, y+1);
|
||||
|
||||
@@ -129,9 +129,7 @@ void ImageValueViewer::loadMask(const Rotation& rot) const {
|
||||
Image image;
|
||||
InputStreamP image_file = viewer.stylesheet->openIn(style().mask_filename);
|
||||
if (image.LoadFile(*image_file)) {
|
||||
Image resampled(w,h);
|
||||
resample(image, resampled);
|
||||
alpha_mask = new_intrusive1<AlphaMask>(resampled);
|
||||
alpha_mask = new_intrusive1<AlphaMask>(resample(image,w,h));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,7 @@ void PackageChoiceValueViewer::initItems() {
|
||||
Image image;
|
||||
InputStreamP stream = p->openIconFile();
|
||||
if (stream && image.LoadFile(*stream)) {
|
||||
Image resampled(16,16,false);
|
||||
resample(image, resampled);
|
||||
i.image = Bitmap(resampled);
|
||||
i.image = Bitmap(resample(image, 16,16));
|
||||
}
|
||||
items.push_back(i);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@@ -172,6 +172,7 @@ edit_symbol IMAGE "../common/edit_symbol.png"
|
||||
installer_group IMAGE "../common/installer_group.png"
|
||||
installer_package IMAGE "../common/installer_package.png"
|
||||
installer_locales IMAGE "../common/installer_locales.png"
|
||||
installer_program IMAGE "../common/installer_program.png"
|
||||
//installer_font IMAGE "../common/installer_font.png"
|
||||
|
||||
// -------------------------------------------------------- : WX
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ String capitalize(const String& s) {
|
||||
}
|
||||
|
||||
String capitalize_sentence(const String& s) {
|
||||
String ret = s.Lower();
|
||||
String ret = s;//.Lower();
|
||||
if (!ret.empty()) {
|
||||
ret[0] = toUpper(ret[0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user