mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-12 13:37:00 -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(right_width);
|
||||||
REFLECT(top_width);
|
REFLECT(top_width);
|
||||||
REFLECT(bottom_width);
|
REFLECT(bottom_width);
|
||||||
|
REFLECT_N("mask", mask_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorStyle::update(Context& ctx) {
|
||||||
|
return Style ::update(ctx)
|
||||||
|
| mask_filename.update(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ColorValue
|
// ----------------------------------------------------------------------------- : ColorValue
|
||||||
|
|||||||
@@ -58,11 +58,14 @@ class ColorStyle : public Style {
|
|||||||
ColorStyle(const ColorFieldP& field);
|
ColorStyle(const ColorFieldP& field);
|
||||||
DECLARE_STYLE_TYPE(Color);
|
DECLARE_STYLE_TYPE(Color);
|
||||||
|
|
||||||
int radius; ///< Radius of round corners
|
double radius; ///< Radius of round corners
|
||||||
UInt left_width; ///< Width of the colored region on the left side
|
double left_width; ///< Width of the colored region on the left side
|
||||||
UInt right_width; ///< Width of the colored region on the right side
|
double right_width; ///< Width of the colored region on the right side
|
||||||
UInt top_width; ///< Width of the colored region on the top side
|
double top_width; ///< Width of the colored region on the top side
|
||||||
UInt bottom_width; ///< Width of the colored region on the bottom 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:
|
private:
|
||||||
DECLARE_REFLECTION();
|
DECLARE_REFLECTION();
|
||||||
|
|||||||
@@ -56,3 +56,16 @@ Color saturate(const Color& c, double amount) {
|
|||||||
col(static_cast<int>( (b - amount * l) / (1 - 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
|
/// A saturated version of a color
|
||||||
Color saturate(const Color& c, double amount);
|
Color saturate(const Color& c, double amount);
|
||||||
|
|
||||||
|
/// Fills an image with the specified color
|
||||||
|
void fill_image(Image& image, const Color& color);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : EOF
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,19 +15,6 @@
|
|||||||
// scaling factor to use when drawing resampled text
|
// scaling factor to use when drawing resampled text
|
||||||
const int text_scaling = 4;
|
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
|
// 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
|
// img_in must be text_scaling times as large as img_out
|
||||||
void downsample_to_alpha(Image& img_in, Image& img_out) {
|
void downsample_to_alpha(Image& img_in, Image& img_out) {
|
||||||
|
|||||||
+56
-18
@@ -7,6 +7,8 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <render/value/color.hpp>
|
#include <render/value/color.hpp>
|
||||||
|
#include <render/card/viewer.hpp>
|
||||||
|
#include <data/stylesheet.hpp>
|
||||||
|
|
||||||
DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
|
DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
|
||||||
|
|
||||||
@@ -38,22 +40,31 @@ void ColorValueViewer::draw(RotatedDC& dc) {
|
|||||||
dc.DrawRectangle(style().getRect().move(40, 0, -40, 0));
|
dc.DrawRectangle(style().getRect().move(40, 0, -40, 0));
|
||||||
dc.DrawText(color_name, style().getPos() + RealSize(43, 3));
|
dc.DrawText(color_name, style().getPos() + RealSize(43, 3));
|
||||||
} else {
|
} else {
|
||||||
// do we need clipping?
|
// is there a mask?
|
||||||
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
loadMask(dc);
|
||||||
style().top_width < style().height && style().bottom_width < style().height;
|
if (alpha_mask) {
|
||||||
if (clip) {
|
Image img(alpha_mask->size.x, alpha_mask->size.y);
|
||||||
// clip away the inside of the rectangle
|
fill_image(img, value().value());
|
||||||
wxRegion r = dc.tr(style().getRect()).toRect();
|
alpha_mask->setAlpha(img);
|
||||||
r.Subtract(dc.tr(RealRect(
|
dc.DrawImage(img, style().getPos());
|
||||||
style().left + style().left_width,
|
} else {
|
||||||
style().top + style().top_width,
|
// do we need clipping?
|
||||||
style().width - style().left_width - style().right_width,
|
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
||||||
style().height - style().top_width - style().bottom_width
|
style().top_width < style().height && style().bottom_width < style().height;
|
||||||
)));
|
if (clip) {
|
||||||
dc.getDC().SetClippingRegion(r);
|
// 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
|
// distance to each side
|
||||||
double left = p.x - style().left, right = style().left + style().width - p.x - 1;
|
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;
|
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
|
if (left < 0 || right < 0 || top < 0 || bottom < 0 || // outside bounding box
|
||||||
(left < style().left_width || right < style().right_width || // inside horizontal border
|
(left >= style().left_width && right >= style().right_width && // outside horizontal border
|
||||||
top < style().top_width || bottom < style().bottom_width); // inside vertical 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 <render/value/viewer.hpp>
|
||||||
#include <data/field/color.hpp>
|
#include <data/field/color.hpp>
|
||||||
|
|
||||||
|
DECLARE_POINTER_TYPE(AlphaMask);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ColorValueViewer
|
// ----------------------------------------------------------------------------- : ColorValueViewer
|
||||||
|
|
||||||
/// Viewer that displays a color value
|
/// Viewer that displays a color value
|
||||||
@@ -22,6 +24,12 @@ class ColorValueViewer : public ValueViewer {
|
|||||||
|
|
||||||
virtual void draw(RotatedDC& dc);
|
virtual void draw(RotatedDC& dc);
|
||||||
virtual bool containsPoint(const RealPoint& p) const;
|
virtual bool containsPoint(const RealPoint& p) const;
|
||||||
|
|
||||||
|
virtual void onStyleChange();
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable AlphaMaskP alpha_mask;
|
||||||
|
void loadMask(const Rotation& rot) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : EOF
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
|
|||||||
Reference in New Issue
Block a user