New rotation system (see forum thread).

Major changes:
  - when rotating, the top left corner of the rectangle stays in place.
  - ValueViewers get a dc that is pre-rotated/translated for them, i.e. (0,0) is the top-left of the viewer (with ValueViewer::getRotation).
  - moved 'angle' from individual Styles to the Style base class.
  - any rotation angle is now possible. angle is still an int for now.

This warrants a version bump

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@782 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-12-23 21:58:58 +00:00
parent 94e4a1ce9e
commit b79f52db84
47 changed files with 498 additions and 371 deletions
+35 -17
View File
@@ -94,9 +94,10 @@ intrusive_ptr<Field> read_new<Field>(Reader& reader) {
Style::Style(const FieldP& field)
: fieldP(field)
, z_index(0)
, left(0), top(0)
, width(0), height(0)
, right(0), bottom(0)
, left(-1), top(-1)
, width(-1), height(-1)
, right(-1), bottom(-1)
, angle(0)
, visible(true)
, automatic_side(AUTO_UNKNOWN)
, content_dependent(false)
@@ -112,6 +113,7 @@ IMPLEMENT_REFLECTION(Style) {
REFLECT(top);
REFLECT(height);
REFLECT(bottom);
REFLECT(angle);
REFLECT(visible);
}
@@ -130,28 +132,44 @@ int Style::update(Context& ctx) {
| top .update(ctx)
| height .update(ctx)
| bottom .update(ctx)
| angle .update(ctx)
| visible.update(ctx);
// determine automatic_side
// determine automatic_side and attachment of rotation point
if (automatic_side == AUTO_UNKNOWN) {
if (right == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT);
else if (width == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_WIDTH);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_LEFT);
if (bottom == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_BOTTOM);
else if (height == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP);
}
if (automatic_side & AUTO_WIDTH){
changed=changed;//BREAKPOINT
if (right == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT);
else if (width == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_WIDTH);
else if (left == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_LEFT);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_LR);
if (bottom == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_BOTTOM);
else if (height == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT);
else if (top == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_TB);
changed = true;
}
if (!changed) return CHANGE_NONE;
// update the automatic_side
if (automatic_side & AUTO_LEFT) left = right - width;
else if (automatic_side & AUTO_WIDTH) width = right - left;
else right = left + width;
else if (automatic_side & AUTO_RIGHT) right = left + width;
else {int lr = left + right; left = (lr - width) / 2; right = (lr + width) / 2; }
if (automatic_side & AUTO_TOP) top = bottom - height;
else if (automatic_side & AUTO_HEIGHT) height = bottom - top;
else bottom = top + height;
// are there changes?
return changed;
else if (automatic_side & AUTO_BOTTOM) bottom = top + height;
else {int tb = top + bottom; top = (tb - height) / 2; bottom = (tb + height) / 2; }
// adjust rotation point
if (angle != 0 && (automatic_side & (AUTO_LEFT | AUTO_TOP))) {
double s = sin(angle * M_PI / 180), c = cos(angle * M_PI / 180);
if (automatic_side & AUTO_LEFT) { // attach right corner instead of left
left = left + width * (1 - c);
top = top + width * s;
}
if (automatic_side & AUTO_TOP) { // attach botom corner instead of top
left = left - height * s;
top = top + height * (1 - c);
}
}
// done
return CHANGE_OTHER;
}
void Style::initDependencies(Context& ctx, const Dependency& dep) const {
+8 -3
View File
@@ -13,6 +13,7 @@
#include <util/reflect.hpp>
#include <util/alignment.hpp>
#include <util/age.hpp>
#include <util/rotation.hpp>
#include <script/scriptable.hpp>
#include <script/dependency.hpp>
@@ -98,17 +99,21 @@ class Style : public IntrusivePtrVirtualBase {
Scriptable<double> left, top; ///< Position of this field
Scriptable<double> width, height; ///< Position of this field
Scriptable<double> right, bottom; ///< Position of this field
Scriptable<int> angle; ///< Rotation of the box
Scriptable<bool> visible; ///< Is this field visible?
enum AutomaticSide {
AUTO_UNKNOWN = 0x00,
AUTO_LEFT = 0x01, AUTO_WIDTH = 0x02, AUTO_RIGHT = 0x04,
AUTO_TOP = 0x10, AUTO_HEIGHT = 0x20, AUTO_BOTTOM = 0x40,
AUTO_LEFT = 0x01, AUTO_WIDTH = 0x02, AUTO_RIGHT = 0x04, AUTO_LR = 0x08,
AUTO_TOP = 0x10, AUTO_HEIGHT = 0x20, AUTO_BOTTOM = 0x40, AUTO_TB = 0x80,
ATTACH_LEFT = 0x04, ATTACH_CENTER = 0x02, ATTACH_RIGHT = 0x01,
ATTACH_TOP = 0x40, ATTACH_MIDDLE = 0x20, ATTACH_BOTTOM = 0x10,
} automatic_side : 8; ///< Which of (left, width, right) and (top, height, bottom) is determined automatically?
bool content_dependent; ///< Does this style depend on content properties?
inline RealPoint getPos() const { return RealPoint(left, top ); }
inline RealSize getSize() const { return RealSize ( width, height); }
inline RealRect getRect() const { return RealRect (left, top, width, height); }
inline RealRect getExternalRect() const { return RealRect (left, top, width, height); }
inline RealRect getInternalRect() const { return RealRect(0, 0, width, height); }
/// Get a copy of this style
virtual StyleP clone() const = 0;
-2
View File
@@ -178,7 +178,6 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
, choice_images_initialized(false)
, combine(COMBINE_NORMAL)
, alignment(ALIGN_STRETCH)
, angle(0)
, thumbnails(nullptr)
{}
@@ -291,7 +290,6 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT_N("mask",mask_filename);
REFLECT(combine);
REFLECT(alignment);
REFLECT(angle);
REFLECT(font);
REFLECT(image);
REFLECT(choice_images);
-1
View File
@@ -153,7 +153,6 @@ class ChoiceStyle : public Style {
ImageCombine combine; ///< Combining mode for drawing the images
Alignment alignment; ///< Alignment of images
Image mask; ///< The actual mask image
int angle; ///< Angle by which the images are rotated
wxImageList* thumbnails; ///< Thumbnails for the choices
vector<ThumbnailStatus> thumbnails_status; ///< Which thumbnails are up to date?
// information from image rendering
-2
View File
@@ -25,14 +25,12 @@ IMPLEMENT_REFLECTION(ImageField) {
IMPLEMENT_REFLECTION(ImageStyle) {
REFLECT_BASE(Style);
REFLECT(angle);
REFLECT_N("mask", mask_filename);
REFLECT_N("default", default_image);
}
int ImageStyle::update(Context& ctx) {
return Style ::update(ctx)
| angle .update(ctx) * CHANGE_OTHER
| mask_filename.update(ctx) * CHANGE_MASK
| default_image.update(ctx) * CHANGE_DEFAULT;
}
-1
View File
@@ -38,7 +38,6 @@ class ImageStyle : public Style {
inline ImageStyle(const ImageFieldP& field) : Style(field) {}
DECLARE_STYLE_TYPE(Image);
Scriptable<int> angle; ///< Rotation of images
Scriptable<String> mask_filename; ///< Filename for a mask image
ScriptableImage default_image; ///< Placeholder
+1 -4
View File
@@ -44,7 +44,6 @@ TextStyle::TextStyle(const TextFieldP& field)
: Style(field)
, always_symbol(false), allow_formating(true)
, alignment(ALIGN_TOP_LEFT)
, angle(0)
, padding_left (0), padding_left_min (10000)
, padding_right (0), padding_right_min (10000)
, padding_top (0), padding_top_min (10000)
@@ -73,8 +72,7 @@ int TextStyle::update(Context& ctx) {
return Style ::update(ctx)
| font .update(ctx) * CHANGE_OTHER
| symbol_font.update(ctx) * CHANGE_OTHER
| alignment .update(ctx) * CHANGE_OTHER
| angle .update(ctx) * CHANGE_OTHER;
| alignment .update(ctx) * CHANGE_OTHER;
}
void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const {
Style ::initDependencies(ctx, dep);
@@ -100,7 +98,6 @@ IMPLEMENT_REFLECTION(TextStyle) {
REFLECT(always_symbol);
REFLECT(allow_formating);
REFLECT(alignment);
REFLECT(angle);
REFLECT(padding_left);
REFLECT(padding_right);
REFLECT(padding_top);
+2 -9
View File
@@ -35,6 +35,8 @@ class TextField : public Field {
OptionalScript script; ///< Script to apply to all values
OptionalScript default_script; ///< Script that generates the default value
//%OptionalScript view_script; ///< Script to apply before viewing
//%OptionalScript unview_script; ///< Script to apply after changes to the view
bool multi_line; ///< Are newlines allowed in the text?
String default_name; ///< Name of "default" value
@@ -57,7 +59,6 @@ class TextStyle : public Style {
bool always_symbol; ///< Should everything be drawn as symbols?
bool allow_formating; ///< Is formating (bold/italic/..) allowed?
Scriptable<Alignment> alignment; ///< Alignment inside the box
Scriptable<int> angle; ///< Angle of the text inside the box
double padding_left, padding_left_min; ///< Padding
double padding_right, padding_right_min; ///< Padding
double padding_top, padding_top_min; ///< Padding
@@ -80,14 +81,6 @@ class TextStyle : public Style {
virtual void initDependencies(Context&, const Dependency&) const;
virtual void checkContentDependencies(Context&, const Dependency&) const;
/// The rotation to use when drawing
inline Rotation getRotation() const {
return Rotation(angle, getRect(), 1.0, getStretch());
}
/// The rotation to use when determining content layout, does not include the stretch factor
inline Rotation getRotationNoStretch() const {
return Rotation(angle, getRect());
}
/// Stretch factor to use
double getStretch() const;
+1 -1
View File
@@ -34,7 +34,7 @@ Rotation UnzoomedDataViewer::getRotation() const {
return DataViewer::getRotation();
} else {
if (!stylesheet) stylesheet = set->stylesheet;
return Rotation(0, stylesheet->getCardRect(), 1.0, 1.0, true);
return Rotation(0, stylesheet->getCardRect(), 1.0, 1.0, ROTATION_ATTACH_TOP_LEFT);
}
}
+1
View File
@@ -32,6 +32,7 @@ class StatsDimension : public IntrusivePtrBase<StatsDimension> {
String description; ///< Description, used in status bar
int position_hint; ///< Hint for the ordering
String icon_filename; ///< Icon for lists
Bitmap icon; ///< The loaded icon (optional of course)
OptionalScript script; ///< Script that determines the value(s)
bool numeric; ///< Are the values numeric? If so, they require special sorting
bool show_empty; ///< Should "" be shown?
+1 -1
View File
@@ -302,7 +302,7 @@ void SymbolFont::drawWithText(RotatedDC& dc, const RealRect& rect, double font_s
if (def) {
Bitmap bmp = def->getBitmap(*this, dc.trS(font_size));
// align symbol
sym_rect.size() = dc.trInvS(RealSize(bmp.GetWidth(), bmp.GetHeight()));
sym_rect.size() = dc.trInvS(RealSize(bmp));
sym_rect.position() = align_in_rect(align, sym_rect.size(), rect);
// draw
dc.DrawBitmap(bmp, sym_rect.position());