mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 13:17:00 -04:00
Added the necessery classes to handle symmetry objects/mirrors in symbols; What used to be SymbolPart is now SymbolShape, SymbolPart is a base class.
This should also pave the way for grouping. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@526 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+105
-74
@@ -8,12 +8,19 @@
|
||||
|
||||
#include <data/action/symbol.hpp>
|
||||
#include <data/action/symbol_part.hpp>
|
||||
#include <util/error.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(pair<SymbolPartP COMMA SymbolPartCombine>);
|
||||
DECLARE_TYPEOF_COLLECTION(pair<SymbolPartP COMMA size_t >);
|
||||
DECLARE_TYPEOF_COLLECTION(pair<SymbolShapeP COMMA SymbolShapeCombine>);
|
||||
DECLARE_TYPEOF_COLLECTION(pair<SymbolPartP COMMA size_t >);
|
||||
DECLARE_TYPEOF_COLLECTION(SymbolPartP);
|
||||
DECLARE_TYPEOF_COLLECTION(ControlPointP);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Utility
|
||||
|
||||
String action_name_for(const set<SymbolPartP>& parts, const String& action) {
|
||||
return format_string(action, parts.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes"));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Moving symbol parts
|
||||
|
||||
SymbolPartMoveAction::SymbolPartMoveAction(const set<SymbolPartP>& parts)
|
||||
@@ -23,23 +30,31 @@ SymbolPartMoveAction::SymbolPartMoveAction(const set<SymbolPartP>& parts)
|
||||
, snap(0)
|
||||
{
|
||||
// Determine min/max_pos
|
||||
FOR_EACH(p,parts) {
|
||||
min_pos = piecewise_min(min_pos, p->min_pos);
|
||||
max_pos = piecewise_max(max_pos, p->max_pos);
|
||||
FOR_EACH(p, parts) {
|
||||
if (SymbolShape* s = p->isSymbolShape()) {
|
||||
min_pos = piecewise_min(min_pos, s->min_pos);
|
||||
max_pos = piecewise_max(max_pos, s->max_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String SymbolPartMoveAction::getName(bool to_undo) const {
|
||||
return parts.size() == 1 ? _("Move shape") : _("Move shapes");
|
||||
return action_name_for(parts, _ACTION_("move"));
|
||||
}
|
||||
|
||||
void SymbolPartMoveAction::perform(bool to_undo) {
|
||||
// move the points back
|
||||
FOR_EACH(p, parts) {
|
||||
p->min_pos -= moved;
|
||||
p->max_pos -= moved;
|
||||
FOR_EACH(pnt, p->points) {
|
||||
pnt->pos -= moved;
|
||||
if (SymbolShape* s = p->isSymbolShape()) {
|
||||
s->min_pos -= moved;
|
||||
s->max_pos -= moved;
|
||||
FOR_EACH(pnt, s->points) {
|
||||
pnt->pos -= moved;
|
||||
}
|
||||
} else if (SymbolSymmetry* s = p->isSymbolSymmetry()) {
|
||||
s->center -= moved;
|
||||
} else {
|
||||
throw InternalError(_("Invalid symbol part type"));
|
||||
}
|
||||
}
|
||||
moved = -moved;
|
||||
@@ -49,15 +64,10 @@ void SymbolPartMoveAction::move(const Vector2D& deltaDelta) {
|
||||
delta += deltaDelta;
|
||||
// Determine actual delta, possibly constrained and snapped
|
||||
Vector2D d = constrain_snap_vector_offset(min_pos, max_pos, delta, constrain, snap);
|
||||
Vector2D dd = d - moved;
|
||||
Vector2D dd = d - moved; // move this much more
|
||||
// Move each point by d
|
||||
FOR_EACH(p, parts) {
|
||||
p->min_pos += dd;
|
||||
p->max_pos += dd;
|
||||
FOR_EACH(pnt, p->points) {
|
||||
pnt->pos += dd;
|
||||
}
|
||||
}
|
||||
moved = -dd;
|
||||
perform(false); // (ab)use perform to move by +dd
|
||||
moved = d;
|
||||
}
|
||||
|
||||
@@ -71,13 +81,19 @@ SymbolPartMatrixAction::SymbolPartMatrixAction(const set<SymbolPartP>& parts, co
|
||||
void SymbolPartMatrixAction::transform(const Vector2D& mx, const Vector2D& my) {
|
||||
// Transform each point
|
||||
FOR_EACH(p, parts) {
|
||||
FOR_EACH(pnt, p->points) {
|
||||
pnt->pos = (pnt->pos - center).mul(mx,my) + center;
|
||||
pnt->delta_before = pnt->delta_before.mul(mx,my);
|
||||
pnt->delta_after = pnt->delta_after .mul(mx,my);
|
||||
if (SymbolShape* s = p->isSymbolShape()) {
|
||||
FOR_EACH(pnt, s->points) {
|
||||
pnt->pos = (pnt->pos - center).mul(mx,my) + center;
|
||||
pnt->delta_before = pnt->delta_before.mul(mx,my);
|
||||
pnt->delta_after = pnt->delta_after .mul(mx,my);
|
||||
}
|
||||
// bounds change after transforming
|
||||
s->calculateBounds();
|
||||
} else if (SymbolSymmetry* s = p->isSymbolSymmetry()) {
|
||||
s->handle = s->handle.mul(mx,my);
|
||||
} else {
|
||||
throw InternalError(_("Invalid symbol part type"));
|
||||
}
|
||||
// bounds change after transforming
|
||||
p->calculateBounds();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +105,7 @@ SymbolPartRotateAction::SymbolPartRotateAction(const set<SymbolPartP>& parts, co
|
||||
{}
|
||||
|
||||
String SymbolPartRotateAction::getName(bool to_undo) const {
|
||||
return parts.size() == 1 ? _("Rotate shape") : _("Rotate shapes");
|
||||
return action_name_for(parts, _ACTION_("rotate"));
|
||||
}
|
||||
|
||||
void SymbolPartRotateAction::perform(bool to_undo) {
|
||||
@@ -128,7 +144,7 @@ SymbolPartShearAction::SymbolPartShearAction(const set<SymbolPartP>& parts, cons
|
||||
{}
|
||||
|
||||
String SymbolPartShearAction::getName(bool to_undo) const {
|
||||
return parts.size() == 1 ? _("Shear shape") : _("Shear shapes");
|
||||
return action_name_for(parts, _ACTION_("shear"));
|
||||
}
|
||||
|
||||
void SymbolPartShearAction::perform(bool to_undo) {
|
||||
@@ -169,89 +185,104 @@ SymbolPartScaleAction::SymbolPartScaleAction(const set<SymbolPartP>& parts, int
|
||||
, snap(0)
|
||||
{
|
||||
// Find min and max coordinates
|
||||
oldMin = Vector2D::infinity();
|
||||
Vector2D oldMax = -Vector2D::infinity();
|
||||
old_min = Vector2D( 1e6, 1e6);
|
||||
Vector2D old_max (-1e6,-1e6);
|
||||
FOR_EACH(p, parts) {
|
||||
oldMin = piecewise_min(oldMin, p->min_pos);
|
||||
oldMax = piecewise_max(oldMax, p->max_pos);
|
||||
if (SymbolShape* s = p->isSymbolShape()) {
|
||||
old_min = piecewise_min(old_min, s->min_pos);
|
||||
old_max = piecewise_max(old_max, s->max_pos);
|
||||
}
|
||||
}
|
||||
// new == old
|
||||
newMin = newRealMin = oldMin;
|
||||
newSize = newRealSize = oldSize = oldMax - oldMin;
|
||||
new_min = new_real_min = old_min;
|
||||
new_size = new_real_size = old_size = old_max - old_min;
|
||||
}
|
||||
|
||||
String SymbolPartScaleAction::getName(bool to_undo) const {
|
||||
return parts.size() == 1 ? _("Scale shape") : _("Scale shapes");
|
||||
return action_name_for(parts, _ACTION_("scale"));
|
||||
}
|
||||
|
||||
void SymbolPartScaleAction::perform(bool to_undo) {
|
||||
swap(oldMin, newMin);
|
||||
swap(oldSize, newSize);
|
||||
swap(old_min, new_min);
|
||||
swap(old_size, new_size);
|
||||
transformAll();
|
||||
}
|
||||
|
||||
void SymbolPartScaleAction::move(const Vector2D& deltaMin, const Vector2D& deltaMax) {
|
||||
newRealMin += deltaMin;
|
||||
newRealSize += deltaMax - deltaMin;
|
||||
void SymbolPartScaleAction::move(const Vector2D& delta_min, const Vector2D& delta_max) {
|
||||
new_real_min += delta_min;
|
||||
new_real_size += delta_max - delta_min;
|
||||
update();
|
||||
}
|
||||
|
||||
void SymbolPartScaleAction::update() {
|
||||
// Move each point so the range <oldMin...oldMax> maps to <newMin...newMax>
|
||||
// we have already moved to the current <newMin...newMax>
|
||||
Vector2D tmpMin = oldMin, tmpSize = oldSize; // the size before any scaling
|
||||
oldMin = newMin; oldSize = newSize; // the size before this move
|
||||
// Move each point so the range [old_min...old_max] maps to [new_min...new_max]
|
||||
// we have already moved to the current [new_min...new_max]
|
||||
Vector2D tmp_min = old_min, tmp_size = old_size; // the size before any scaling
|
||||
old_min = new_min; old_size = new_size; // the size before this move
|
||||
// the size after the move
|
||||
newMin = newRealMin; newSize = newRealSize;
|
||||
new_min = new_real_min; new_size = new_real_size;
|
||||
if (constrain && scaleX != 0 && scaleY != 0) {
|
||||
Vector2D scale = newSize.div(tmpSize);
|
||||
Vector2D scale = new_size.div(tmp_size);
|
||||
scale = constrain_vector(scale, true, true);
|
||||
newSize = tmpSize.mul(scale);
|
||||
newMin += (newRealSize - newSize).mul(Vector2D(scaleX == -1 ? 1 : 0, scaleY == -1 ? 1 : 0));
|
||||
new_size = tmp_size.mul(scale);
|
||||
new_min += (new_real_size - new_size).mul(Vector2D(scaleX == -1 ? 1 : 0, scaleY == -1 ? 1 : 0));
|
||||
// TODO : snapping
|
||||
} else if (snap >= 0) {
|
||||
if (scaleX + scaleY < 0) {
|
||||
newMin = snap_vector(newMin, snap);
|
||||
newSize += newRealMin - newMin;
|
||||
new_min = snap_vector(new_min, snap);
|
||||
new_size += new_real_min - new_min;
|
||||
} else {
|
||||
Vector2D newMax = snap_vector(newMin + newSize, snap);
|
||||
newSize = newMax - newMin;
|
||||
Vector2D new_max = snap_vector(new_min + new_size, snap);
|
||||
new_size = new_max - new_min;
|
||||
}
|
||||
}
|
||||
// now move all points
|
||||
transformAll();
|
||||
// restore oldMin/Size
|
||||
oldMin = tmpMin; oldSize = tmpSize;
|
||||
// restore old_min/size
|
||||
old_min = tmp_min; old_size = tmp_size;
|
||||
}
|
||||
|
||||
void SymbolPartScaleAction::transformAll() {
|
||||
Vector2D scale = newSize.div(oldSize);
|
||||
Vector2D scale = new_size.div(old_size);
|
||||
FOR_EACH(p, parts) {
|
||||
p->min_pos = transform(p->min_pos);
|
||||
p->max_pos = transform(p->max_pos);
|
||||
// make sure that max >= min
|
||||
if (p->min_pos.x > p->max_pos.x) swap(p->min_pos.x, p->max_pos.x);
|
||||
if (p->min_pos.y > p->max_pos.y) swap(p->min_pos.y, p->max_pos.y);
|
||||
// scale all points
|
||||
FOR_EACH(pnt, p->points) {
|
||||
pnt->pos = transform(pnt->pos);
|
||||
// also scale handles
|
||||
pnt->delta_before = pnt->delta_before.mul(scale);
|
||||
pnt->delta_after = pnt->delta_after .mul(scale);
|
||||
if (SymbolShape* s = p->isSymbolShape()) {
|
||||
s->min_pos = transform(s->min_pos);
|
||||
s->max_pos = transform(s->max_pos);
|
||||
// make sure that max >= min
|
||||
if (s->min_pos.x > s->max_pos.x) swap(s->min_pos.x, s->max_pos.x);
|
||||
if (s->min_pos.y > s->max_pos.y) swap(s->min_pos.y, s->max_pos.y);
|
||||
// scale all points
|
||||
FOR_EACH(pnt, s->points) {
|
||||
pnt->pos = transform(pnt->pos);
|
||||
// also scale handles
|
||||
pnt->delta_before = pnt->delta_before.mul(scale);
|
||||
pnt->delta_after = pnt->delta_after .mul(scale);
|
||||
}
|
||||
} else if (SymbolSymmetry* s = p->isSymbolSymmetry()) {
|
||||
throw "TODO";
|
||||
} else {
|
||||
throw InternalError(_("Invalid symbol part type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D SymbolPartScaleAction::transform(const Vector2D& v) {
|
||||
// TODO: prevent div by 0
|
||||
return (v - old_min).div(old_size).mul(new_size) + new_min;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change combine mode
|
||||
|
||||
CombiningModeAction::CombiningModeAction(const set<SymbolPartP>& parts, SymbolPartCombine mode) {
|
||||
CombiningModeAction::CombiningModeAction(const set<SymbolPartP>& parts, SymbolShapeCombine mode) {
|
||||
FOR_EACH(p, parts) {
|
||||
this->parts.push_back(make_pair(p,mode));
|
||||
if (p->isSymbolShape()) {
|
||||
this->parts.push_back(make_pair(static_pointer_cast<SymbolShape>(p),mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String CombiningModeAction::getName(bool to_undo) const {
|
||||
return _("Change combine mode");
|
||||
return _ACTION_("change combine mode");
|
||||
}
|
||||
|
||||
void CombiningModeAction::perform(bool to_undo) {
|
||||
@@ -263,15 +294,15 @@ void CombiningModeAction::perform(bool to_undo) {
|
||||
// ----------------------------------------------------------------------------- : Change name
|
||||
|
||||
SymbolPartNameAction::SymbolPartNameAction(const SymbolPartP& part, const String& name)
|
||||
: part(part), partName(name)
|
||||
: part(part), part_name(name)
|
||||
{}
|
||||
|
||||
String SymbolPartNameAction::getName(bool to_undo) const {
|
||||
return _("Change shape name");
|
||||
return _ACTION_("change shape name");
|
||||
}
|
||||
|
||||
void SymbolPartNameAction::perform(bool to_undo) {
|
||||
swap(part->name, partName);
|
||||
swap(part->name, part_name);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Add symbol part
|
||||
@@ -281,7 +312,7 @@ AddSymbolPartAction::AddSymbolPartAction(Symbol& symbol, const SymbolPartP& part
|
||||
{}
|
||||
|
||||
String AddSymbolPartAction::getName(bool to_undo) const {
|
||||
return _("Add ") + part->name;
|
||||
return format_string(_ACTION_("add"), part->name);
|
||||
}
|
||||
|
||||
void AddSymbolPartAction::perform(bool to_undo) {
|
||||
@@ -308,7 +339,7 @@ RemoveSymbolPartsAction::RemoveSymbolPartsAction(Symbol& symbol, const set<Symbo
|
||||
}
|
||||
|
||||
String RemoveSymbolPartsAction::getName(bool to_undo) const {
|
||||
return removals.size() == 1 ? _("Remove shape") : _("Remove shapes");
|
||||
return format_string(_ACTION_("remove parts"), removals.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes"));
|
||||
}
|
||||
|
||||
void RemoveSymbolPartsAction::perform(bool to_undo) {
|
||||
@@ -346,7 +377,7 @@ DuplicateSymbolPartsAction::DuplicateSymbolPartsAction(Symbol& symbol, const set
|
||||
}
|
||||
|
||||
String DuplicateSymbolPartsAction::getName(bool to_undo) const {
|
||||
return duplications.size() == 1 ? _("Duplicate shape") : _("Duplicate shapes");
|
||||
return format_string(_ACTION_("duplicate"), duplications.size() == 1 ? _TYPE_("shape") : _TYPE_("shapes"));
|
||||
}
|
||||
|
||||
void DuplicateSymbolPartsAction::perform(bool to_undo) {
|
||||
@@ -380,7 +411,7 @@ ReorderSymbolPartsAction::ReorderSymbolPartsAction(Symbol& symbol, size_t part_i
|
||||
{}
|
||||
|
||||
String ReorderSymbolPartsAction::getName(bool to_undo) const {
|
||||
return _("Reorder");
|
||||
return _ACTION_("reorder parts");
|
||||
}
|
||||
|
||||
void ReorderSymbolPartsAction::perform(bool to_undo) {
|
||||
|
||||
+15
-16
@@ -63,7 +63,7 @@ class SymbolPartMatrixAction : public SymbolPartAction {
|
||||
/// Perform the transformation using the given matrix
|
||||
void transform(const Vector2D& mx, const Vector2D& my);
|
||||
|
||||
set<SymbolPartP> parts; ///< Parts to transform
|
||||
set<SymbolPartP> parts; ///< Parts to transform
|
||||
Vector2D center; ///< Center to transform around
|
||||
};
|
||||
|
||||
@@ -122,22 +122,20 @@ class SymbolPartScaleAction : public SymbolPartAction {
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
/// Change min and max coordinates
|
||||
void move(const Vector2D& deltaMin, const Vector2D& deltaMax);
|
||||
void move(const Vector2D& delta_min, const Vector2D& delta_max);
|
||||
/// Update the action's effect
|
||||
void update();
|
||||
|
||||
private:
|
||||
set<SymbolPartP> parts; ///< Parts to scale
|
||||
Vector2D oldMin, oldSize; ///< the original pos/size
|
||||
Vector2D newRealMin, newRealSize; ///< the target pos/sizevoid shearBy(const Vector2D& shear)
|
||||
Vector2D newMin, newSize; ///< the target pos/size after applying constrains
|
||||
int scaleX, scaleY; ///< to what corner are we attached?
|
||||
set<SymbolPartP> parts; ///< Parts to scale
|
||||
Vector2D old_min, old_size; ///< the original pos/size
|
||||
Vector2D new_real_min, new_real_size; ///< the target pos/sizevoid shearBy(const Vector2D& shear)
|
||||
Vector2D new_min, new_size; ///< the target pos/size after applying constrains
|
||||
int scaleX, scaleY; ///< to what corner are we attached?
|
||||
/// Transform everything in the parts
|
||||
void transformAll();
|
||||
/// Transform a single vector
|
||||
inline Vector2D transform(const Vector2D& v) {
|
||||
return (v - oldMin).div(oldSize).mul(newSize) + newMin;
|
||||
}
|
||||
inline Vector2D transform(const Vector2D& v);
|
||||
public:
|
||||
bool constrain; ///< Constrain movement?
|
||||
int snap; ///< Snap to grid?
|
||||
@@ -148,13 +146,14 @@ class SymbolPartScaleAction : public SymbolPartAction {
|
||||
/// Change the name of a symbol part
|
||||
class CombiningModeAction : public SymbolPartListAction {
|
||||
public:
|
||||
CombiningModeAction(const set<SymbolPartP>& parts, SymbolPartCombine mode);
|
||||
// All parts must be SymbolParts
|
||||
CombiningModeAction(const set<SymbolPartP>& parts, SymbolShapeCombine mode);
|
||||
|
||||
virtual String getName(bool to_undo) const;
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
private:
|
||||
vector<pair<SymbolPartP,SymbolPartCombine> > parts; ///< Affected parts with new combining modes
|
||||
vector<pair<SymbolShapeP,SymbolShapeCombine> > parts; ///< Affected parts with new combining modes
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Change name
|
||||
@@ -168,8 +167,8 @@ class SymbolPartNameAction : public SymbolPartListAction {
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
private:
|
||||
SymbolPartP part; ///< Affected part
|
||||
String partName; ///< New name
|
||||
SymbolPartP part; ///< Affected part
|
||||
String part_name; ///< New name
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Add symbol part
|
||||
@@ -183,8 +182,8 @@ class AddSymbolPartAction : public SymbolPartListAction {
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
private:
|
||||
Symbol& symbol; ///< Symbol to add the part to
|
||||
SymbolPartP part; ///< Part to add
|
||||
Symbol& symbol; ///< Symbol to add the part to
|
||||
SymbolPartP part; ///< Part to add
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Remove symbol part
|
||||
|
||||
@@ -80,6 +80,10 @@ Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& off2
|
||||
return dd;
|
||||
}
|
||||
|
||||
String action_name_for(const set<ControlPointP>& points, const String& action) {
|
||||
return format_string(action, points.size() == 1 ? _TYPE_("point") : _TYPE_("points"));
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : Move control point
|
||||
|
||||
@@ -95,7 +99,7 @@ ControlPointMoveAction::ControlPointMoveAction(const set<ControlPointP>& points)
|
||||
}
|
||||
|
||||
String ControlPointMoveAction::getName(bool to_undo) const {
|
||||
return points.size() == 1 ? _("Move point") : _("Move points");
|
||||
return action_name_for(points, _ACTION_("move"));
|
||||
}
|
||||
|
||||
void ControlPointMoveAction::perform(bool to_undo) {
|
||||
@@ -126,7 +130,7 @@ HandleMoveAction::HandleMoveAction(const SelectedHandle& handle)
|
||||
{}
|
||||
|
||||
String HandleMoveAction::getName(bool to_undo) const {
|
||||
return _("Move handle");
|
||||
return _ACTION_("move handle");
|
||||
}
|
||||
|
||||
void HandleMoveAction::perform(bool to_undo) {
|
||||
@@ -171,8 +175,8 @@ SegmentModeAction::SegmentModeAction(const ControlPointP& p1, const ControlPoint
|
||||
}
|
||||
String SegmentModeAction::getName(bool to_undo) const {
|
||||
SegmentMode mode = to_undo ? point1.point->segment_after : point1.other.segment_after;
|
||||
if (mode == SEGMENT_LINE) return _("Convert to line");
|
||||
else return _("Convert to curve");
|
||||
if (mode == SEGMENT_LINE) return _ACTION_("convert to line");
|
||||
else return _ACTION_("convert to curve");
|
||||
}
|
||||
|
||||
void SegmentModeAction::perform(bool to_undo) {
|
||||
@@ -191,7 +195,7 @@ LockModeAction::LockModeAction(const ControlPointP& p, LockMode lock)
|
||||
}
|
||||
|
||||
String LockModeAction::getName(bool to_undo) const {
|
||||
return _("Lock point");
|
||||
return _ACTION_("lock point");
|
||||
}
|
||||
|
||||
void LockModeAction::perform(bool to_undo) {
|
||||
@@ -206,7 +210,7 @@ CurveDragAction::CurveDragAction(const ControlPointP& point1, const ControlPoint
|
||||
{}
|
||||
|
||||
String CurveDragAction::getName(bool to_undo) const {
|
||||
return _("Move curve");
|
||||
return _ACTION_("move curve");
|
||||
}
|
||||
|
||||
void CurveDragAction::perform(bool to_undo) {
|
||||
@@ -239,12 +243,12 @@ void CurveDragAction::move(const Vector2D& delta, double t) {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Add control point
|
||||
|
||||
ControlPointAddAction::ControlPointAddAction(const SymbolPartP& part, UInt insert_after, double t)
|
||||
: part(part)
|
||||
ControlPointAddAction::ControlPointAddAction(const SymbolShapeP& shape, UInt insert_after, double t)
|
||||
: shape(shape)
|
||||
, new_point(new ControlPoint())
|
||||
, insert_after(insert_after)
|
||||
, point1(part->getPoint(insert_after))
|
||||
, point2(part->getPoint(insert_after + 1))
|
||||
, point1(shape->getPoint(insert_after))
|
||||
, point2(shape->getPoint(insert_after + 1))
|
||||
{
|
||||
// calculate new point
|
||||
if (point1.other.segment_after == SEGMENT_CURVE) {
|
||||
@@ -265,14 +269,14 @@ ControlPointAddAction::ControlPointAddAction(const SymbolPartP& part, UInt inser
|
||||
}
|
||||
|
||||
String ControlPointAddAction::getName(bool to_undo) const {
|
||||
return _("Add control point");
|
||||
return _ACTION_("add control point");
|
||||
}
|
||||
|
||||
void ControlPointAddAction::perform(bool to_undo) {
|
||||
if (to_undo) { // remove the point
|
||||
part->points.erase( part->points.begin() + insert_after + 1);
|
||||
shape->points.erase( shape->points.begin() + insert_after + 1);
|
||||
} else {
|
||||
part->points.insert(part->points.begin() + insert_after + 1, new_point);
|
||||
shape->points.insert(shape->points.begin() + insert_after + 1, new_point);
|
||||
}
|
||||
// update points before/after
|
||||
point1.perform();
|
||||
@@ -291,24 +295,24 @@ double ssqrt(double x) {
|
||||
// Remove a single control point
|
||||
class SinglePointRemoveAction : public Action, public IntrusivePtrBase<SinglePointRemoveAction> {
|
||||
public:
|
||||
SinglePointRemoveAction(const SymbolPartP& part, UInt position);
|
||||
SinglePointRemoveAction(const SymbolShapeP& shape, UInt position);
|
||||
|
||||
virtual String getName(bool to_undo) const { return _("Delete point"); }
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
private:
|
||||
SymbolPartP part;
|
||||
SymbolShapeP shape;
|
||||
UInt position;
|
||||
ControlPointP point; ///< Removed point
|
||||
ControlPointUpdate point1, point2; ///< Points before/after
|
||||
};
|
||||
|
||||
SinglePointRemoveAction::SinglePointRemoveAction(const SymbolPartP& part, UInt position)
|
||||
: part(part)
|
||||
SinglePointRemoveAction::SinglePointRemoveAction(const SymbolShapeP& shape, UInt position)
|
||||
: shape(shape)
|
||||
, position(position)
|
||||
, point (part->getPoint(position))
|
||||
, point1(part->getPoint(position - 1))
|
||||
, point2(part->getPoint(position + 1))
|
||||
, point (shape->getPoint(position))
|
||||
, point1(shape->getPoint(position - 1))
|
||||
, point2(shape->getPoint(position + 1))
|
||||
{
|
||||
if (point1.other.segment_after == SEGMENT_CURVE || point2.other.segment_before == SEGMENT_CURVE) {
|
||||
// try to preserve curve
|
||||
@@ -359,10 +363,10 @@ SinglePointRemoveAction::SinglePointRemoveAction(const SymbolPartP& part, UInt p
|
||||
void SinglePointRemoveAction::perform(bool to_undo) {
|
||||
if (to_undo) {
|
||||
// reinsert the point
|
||||
part->points.insert(part->points.begin() + position, point);
|
||||
shape->points.insert(shape->points.begin() + position, point);
|
||||
} else {
|
||||
// remove the point
|
||||
part->points.erase( part->points.begin() + position);
|
||||
shape->points.erase( shape->points.begin() + position);
|
||||
}
|
||||
// update points around removed point
|
||||
point1.perform();
|
||||
@@ -373,12 +377,12 @@ DECLARE_POINTER_TYPE(SinglePointRemoveAction);
|
||||
DECLARE_TYPEOF_COLLECTION(SinglePointRemoveActionP);
|
||||
|
||||
|
||||
// Remove a set of points from a symbol part.
|
||||
// Remove a set of points from a symbol shape.
|
||||
// Internally represented as a list of Single Point Remove Actions.
|
||||
// Not all points mat be removed, at least two points must remain.
|
||||
class ControlPointRemoveAction : public Action {
|
||||
public:
|
||||
ControlPointRemoveAction(const SymbolPartP& part, const set<ControlPointP>& toDelete);
|
||||
ControlPointRemoveAction(const SymbolShapeP& shape, const set<ControlPointP>& to_delete);
|
||||
|
||||
virtual String getName(bool to_undo) const;
|
||||
virtual void perform(bool to_undo);
|
||||
@@ -387,20 +391,20 @@ class ControlPointRemoveAction : public Action {
|
||||
vector<SinglePointRemoveActionP> removals;
|
||||
};
|
||||
|
||||
ControlPointRemoveAction::ControlPointRemoveAction(const SymbolPartP& part, const set<ControlPointP>& toDelete) {
|
||||
ControlPointRemoveAction::ControlPointRemoveAction(const SymbolShapeP& shape, const set<ControlPointP>& to_delete) {
|
||||
int index = 0;
|
||||
// find points to remove, in reverse order
|
||||
FOR_EACH(point, part->points) {
|
||||
if (toDelete.find(point) != toDelete.end()) {
|
||||
FOR_EACH(point, shape->points) {
|
||||
if (to_delete.find(point) != to_delete.end()) {
|
||||
// remove this point
|
||||
removals.push_back(new_intrusive2<SinglePointRemoveAction>(part, index));
|
||||
removals.push_back(new_intrusive2<SinglePointRemoveAction>(shape, index));
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
String ControlPointRemoveAction::getName(bool to_undo) const {
|
||||
return removals.size() == 1 ? _("Delete point") : _("Delete points");
|
||||
return removals.size() == 1 ? _ACTION_("delete point") : _ACTION_("delete points");
|
||||
}
|
||||
|
||||
void ControlPointRemoveAction::perform(bool to_undo) {
|
||||
@@ -414,12 +418,12 @@ void ControlPointRemoveAction::perform(bool to_undo) {
|
||||
}
|
||||
|
||||
|
||||
Action* controlPointRemoveAction(const SymbolPartP& part, const set<ControlPointP>& toDelete) {
|
||||
if (part->points.size() - toDelete.size() < 2) {
|
||||
Action* control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete) {
|
||||
if (shape->points.size() - to_delete.size() < 2) {
|
||||
// TODO : remove part?
|
||||
//new_intrusive<ControlPointRemoveAllAction>(part);
|
||||
return 0; // no action
|
||||
} else {
|
||||
return new ControlPointRemoveAction(part, toDelete);
|
||||
return new ControlPointRemoveAction(shape, to_delete);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/** @file data/action/symbol_part.hpp
|
||||
*
|
||||
* Actions operating on the insides of SymbolParts (ControlPoints and the like).
|
||||
* Actions operating on the insides of SymbolParts/SymbolShapes (ControlPoints and the like).
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
@@ -147,11 +147,11 @@ class CurveDragAction : public SegmentModeAction {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Add control point
|
||||
|
||||
/// Insert a new point in a symbol part
|
||||
/// Insert a new point in a symbol shape
|
||||
class ControlPointAddAction : public Action {
|
||||
public:
|
||||
/// Insert a new point in part, after position insertAfter_, at the time t on the segment
|
||||
ControlPointAddAction(const SymbolPartP& part, UInt insert_after, double t);
|
||||
/// Insert a new point in shape, after position insertAfter_, at the time t on the segment
|
||||
ControlPointAddAction(const SymbolShapeP& shape, UInt insert_after, double t);
|
||||
|
||||
virtual String getName(bool to_undo) const;
|
||||
virtual void perform(bool to_undo);
|
||||
@@ -159,17 +159,17 @@ class ControlPointAddAction : public Action {
|
||||
inline ControlPointP getNewPoint() const { return new_point; }
|
||||
|
||||
private:
|
||||
SymbolPartP part; ///< SymbolPart we are in
|
||||
ControlPointP new_point; ///< The point to insert
|
||||
SymbolShapeP shape; ///< SymbolShape we are in
|
||||
ControlPointP new_point; ///< The point to insert
|
||||
UInt insert_after; ///< Insert after index .. in the array
|
||||
ControlPointUpdate point1, point2; ///< Update the points around the new point
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Remove control point
|
||||
|
||||
/// Action that removes any number of points from a symbol part
|
||||
/// TODO: If less then 3 points are left removes the entire part?
|
||||
Action* controlPointRemoveAction(const SymbolPartP& part, const set<ControlPointP>& toDelete);
|
||||
/// Action that removes any number of points from a symbol shape
|
||||
/// TODO: If less then 3 points are left removes the entire shape?
|
||||
Action* control_point_remove_action(const SymbolShapeP& shape, const set<ControlPointP>& to_delete);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
Reference in New Issue
Block a user