mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Support for masks for color fields
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@325 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -63,6 +63,12 @@ IMPLEMENT_REFLECTION(ColorStyle) {
|
||||
REFLECT(right_width);
|
||||
REFLECT(top_width);
|
||||
REFLECT(bottom_width);
|
||||
REFLECT_N("mask", mask_filename);
|
||||
}
|
||||
|
||||
bool ColorStyle::update(Context& ctx) {
|
||||
return Style ::update(ctx)
|
||||
| mask_filename.update(ctx);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ColorValue
|
||||
|
||||
@@ -58,12 +58,15 @@ class ColorStyle : public Style {
|
||||
ColorStyle(const ColorFieldP& field);
|
||||
DECLARE_STYLE_TYPE(Color);
|
||||
|
||||
int radius; ///< Radius of round corners
|
||||
UInt left_width; ///< Width of the colored region on the left side
|
||||
UInt right_width; ///< Width of the colored region on the right side
|
||||
UInt top_width; ///< Width of the colored region on the top side
|
||||
UInt bottom_width; ///< Width of the colored region on the bottom side
|
||||
|
||||
double radius; ///< Radius of round corners
|
||||
double left_width; ///< Width of the colored region on the left side
|
||||
double right_width; ///< Width of the colored region on the right side
|
||||
double top_width; ///< Width of the colored region on the top side
|
||||
double bottom_width; ///< Width of the colored region on the bottom side
|
||||
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
|
||||
|
||||
virtual bool update(Context&);
|
||||
|
||||
private:
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
@@ -56,3 +56,16 @@ Color saturate(const Color& c, double amount) {
|
||||
col(static_cast<int>( (b - amount * l) / (1 - amount) ))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void fill_image(Image& image, const Color& color) {
|
||||
Byte* pos = image.GetData();
|
||||
Byte* end = pos + image.GetWidth() * image.GetHeight() * 3;
|
||||
Byte r = color.Red(), g = color.Green(), b = color.Blue();
|
||||
// fill the image
|
||||
while (pos != end) {
|
||||
*pos++ = r;
|
||||
*pos++ = g;
|
||||
*pos++ = b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,5 +189,8 @@ Color darken(const Color& c);
|
||||
/// A saturated version of a color
|
||||
Color saturate(const Color& c, double amount);
|
||||
|
||||
/// Fills an image with the specified color
|
||||
void fill_image(Image& image, const Color& color);
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
@@ -15,19 +15,6 @@
|
||||
// scaling factor to use when drawing resampled text
|
||||
const int text_scaling = 4;
|
||||
|
||||
// Fills an image with the specified color
|
||||
void fill_image(Image& image, const Color& color) {
|
||||
Byte* pos = image.GetData();
|
||||
Byte* end = pos + image.GetWidth() * image.GetHeight() * 3;
|
||||
Byte r = color.Red(), g = color.Green(), b = color.Blue();
|
||||
// fill the image
|
||||
while (pos != end) {
|
||||
*pos++ = r;
|
||||
*pos++ = g;
|
||||
*pos++ = b;
|
||||
}
|
||||
}
|
||||
|
||||
// Downsamples the red channel of the input image to the alpha channel of the output image
|
||||
// img_in must be text_scaling times as large as img_out
|
||||
void downsample_to_alpha(Image& img_in, Image& img_out) {
|
||||
|
||||
+56
-18
@@ -7,6 +7,8 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <render/value/color.hpp>
|
||||
#include <render/card/viewer.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
|
||||
|
||||
@@ -38,22 +40,31 @@ void ColorValueViewer::draw(RotatedDC& dc) {
|
||||
dc.DrawRectangle(style().getRect().move(40, 0, -40, 0));
|
||||
dc.DrawText(color_name, style().getPos() + RealSize(43, 3));
|
||||
} else {
|
||||
// do we need clipping?
|
||||
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
||||
style().top_width < style().height && style().bottom_width < style().height;
|
||||
if (clip) {
|
||||
// clip away the inside of the rectangle
|
||||
wxRegion r = dc.tr(style().getRect()).toRect();
|
||||
r.Subtract(dc.tr(RealRect(
|
||||
style().left + style().left_width,
|
||||
style().top + style().top_width,
|
||||
style().width - style().left_width - style().right_width,
|
||||
style().height - style().top_width - style().bottom_width
|
||||
)));
|
||||
dc.getDC().SetClippingRegion(r);
|
||||
// is there a mask?
|
||||
loadMask(dc);
|
||||
if (alpha_mask) {
|
||||
Image img(alpha_mask->size.x, alpha_mask->size.y);
|
||||
fill_image(img, value().value());
|
||||
alpha_mask->setAlpha(img);
|
||||
dc.DrawImage(img, style().getPos());
|
||||
} else {
|
||||
// do we need clipping?
|
||||
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
||||
style().top_width < style().height && style().bottom_width < style().height;
|
||||
if (clip) {
|
||||
// clip away the inside of the rectangle
|
||||
wxRegion r = dc.tr(style().getRect()).toRect();
|
||||
r.Subtract(dc.tr(RealRect(
|
||||
style().left + style().left_width,
|
||||
style().top + style().top_width,
|
||||
style().width - style().left_width - style().right_width,
|
||||
style().height - style().top_width - style().bottom_width
|
||||
)));
|
||||
dc.getDC().SetClippingRegion(r);
|
||||
}
|
||||
dc.DrawRoundedRectangle(style().getRect(), style().radius);
|
||||
if (clip) dc.getDC().DestroyClippingRegion();
|
||||
}
|
||||
dc.DrawRoundedRectangle(style().getRect(), style().radius);
|
||||
if (clip) dc.getDC().DestroyClippingRegion();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +72,34 @@ bool ColorValueViewer::containsPoint(const RealPoint& p) const {
|
||||
// distance to each side
|
||||
double left = p.x - style().left, right = style().left + style().width - p.x - 1;
|
||||
double top = p.y - style().top, bottom = style().top + style().height - p.y - 1;
|
||||
return left >= 0 && right >= 0 && top >= 0 && bottom >= 0 && // inside bounding box
|
||||
(left < style().left_width || right < style().right_width || // inside horizontal border
|
||||
top < style().top_width || bottom < style().bottom_width); // inside vertical border
|
||||
if (left < 0 || right < 0 || top < 0 || bottom < 0 || // outside bounding box
|
||||
(left >= style().left_width && right >= style().right_width && // outside horizontal border
|
||||
top >= style().top_width && bottom >= style().bottom_width)) { // outside vertical border
|
||||
return false;
|
||||
}
|
||||
// check against mask
|
||||
if (!style().mask_filename().empty()) {
|
||||
loadMask(viewer.getRotation());
|
||||
return !alpha_mask || !alpha_mask->isTransparent((int)left, (int)top);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ColorValueViewer::onStyleChange() {
|
||||
alpha_mask = AlphaMaskP();
|
||||
}
|
||||
|
||||
void ColorValueViewer::loadMask(const Rotation& rot) const {
|
||||
if (style().mask_filename().empty()) return; // no mask
|
||||
int w = (int) rot.trS(style().width), h = (int) rot.trS(style().height);
|
||||
if (alpha_mask && alpha_mask->size == wxSize(w,h)) return; // mask loaded and right size
|
||||
// (re) load the mask
|
||||
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_shared1<AlphaMask>(resampled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <render/value/viewer.hpp>
|
||||
#include <data/field/color.hpp>
|
||||
|
||||
DECLARE_POINTER_TYPE(AlphaMask);
|
||||
|
||||
// ----------------------------------------------------------------------------- : ColorValueViewer
|
||||
|
||||
/// Viewer that displays a color value
|
||||
@@ -22,6 +24,12 @@ class ColorValueViewer : public ValueViewer {
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
|
||||
virtual void onStyleChange();
|
||||
|
||||
private:
|
||||
mutable AlphaMaskP alpha_mask;
|
||||
void loadMask(const Rotation& rot) const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
Reference in New Issue
Block a user