Changed all resources to .png files;
Added 'snap to grid' to symbol editor git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@207 0fc631ac-6414-0410-93d0-97cfa31319b6
@@ -18,8 +18,16 @@ DECLARE_TYPEOF_COLLECTION(ControlPointP);
|
|||||||
|
|
||||||
SymbolPartMoveAction::SymbolPartMoveAction(const set<SymbolPartP>& parts)
|
SymbolPartMoveAction::SymbolPartMoveAction(const set<SymbolPartP>& parts)
|
||||||
: parts(parts)
|
: parts(parts)
|
||||||
|
, min_pos(Vector2D::infinity()), max_pos(-Vector2D::infinity())
|
||||||
, constrain(false)
|
, constrain(false)
|
||||||
{}
|
, 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String SymbolPartMoveAction::getName(bool to_undo) const {
|
String SymbolPartMoveAction::getName(bool to_undo) const {
|
||||||
return parts.size() == 1 ? _("Move shape") : _("Move shapes");
|
return parts.size() == 1 ? _("Move shape") : _("Move shapes");
|
||||||
@@ -39,9 +47,10 @@ void SymbolPartMoveAction::perform(bool to_undo) {
|
|||||||
|
|
||||||
void SymbolPartMoveAction::move(const Vector2D& deltaDelta) {
|
void SymbolPartMoveAction::move(const Vector2D& deltaDelta) {
|
||||||
delta += deltaDelta;
|
delta += deltaDelta;
|
||||||
// Move each point by deltaDelta, possibly constrained
|
// Determine actual delta, possibly constrained and snapped
|
||||||
Vector2D d = constrainVector(delta, constrain);
|
Vector2D d = constrain_snap_vector_offset(min_pos, max_pos, delta, constrain, snap);
|
||||||
Vector2D dd = d - moved;
|
Vector2D dd = d - moved;
|
||||||
|
// Move each point by d
|
||||||
FOR_EACH(p, parts) {
|
FOR_EACH(p, parts) {
|
||||||
p->min_pos += dd;
|
p->min_pos += dd;
|
||||||
p->max_pos += dd;
|
p->max_pos += dd;
|
||||||
@@ -114,7 +123,8 @@ void SymbolPartRotateAction::rotateBy(double deltaAngle) {
|
|||||||
|
|
||||||
SymbolPartShearAction::SymbolPartShearAction(const set<SymbolPartP>& parts, const Vector2D& center)
|
SymbolPartShearAction::SymbolPartShearAction(const set<SymbolPartP>& parts, const Vector2D& center)
|
||||||
: SymbolPartMatrixAction(parts, center)
|
: SymbolPartMatrixAction(parts, center)
|
||||||
, constrain(false)
|
// , constrain(false)
|
||||||
|
, snap(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String SymbolPartShearAction::getName(bool to_undo) const {
|
String SymbolPartShearAction::getName(bool to_undo) const {
|
||||||
@@ -130,12 +140,14 @@ void SymbolPartShearAction::perform(bool to_undo) {
|
|||||||
// <1 -x> /
|
// <1 -x> /
|
||||||
// <-y 1> / (1 - xy)
|
// <-y 1> / (1 - xy)
|
||||||
// we have: xy = 0 => (1 - xy) = 1
|
// we have: xy = 0 => (1 - xy) = 1
|
||||||
shearBy(-shear);
|
shearBy(-moved);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolPartShearAction::move(const Vector2D& deltaShear) {
|
void SymbolPartShearAction::move(const Vector2D& deltaShear) {
|
||||||
shear += deltaShear;
|
shear += deltaShear;
|
||||||
shearBy(deltaShear);
|
Vector2D d = snap_vector(shear - moved, snap);
|
||||||
|
shearBy(d);
|
||||||
|
moved += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolPartShearAction::shearBy(const Vector2D& shear) {
|
void SymbolPartShearAction::shearBy(const Vector2D& shear) {
|
||||||
@@ -154,6 +166,7 @@ SymbolPartScaleAction::SymbolPartScaleAction(const set<SymbolPartP>& parts, int
|
|||||||
: parts(parts)
|
: parts(parts)
|
||||||
, scaleX(scaleX), scaleY(scaleY)
|
, scaleX(scaleX), scaleY(scaleY)
|
||||||
, constrain(false)
|
, constrain(false)
|
||||||
|
, snap(0)
|
||||||
{
|
{
|
||||||
// Find min and max coordinates
|
// Find min and max coordinates
|
||||||
oldMin = Vector2D::infinity();
|
oldMin = Vector2D::infinity();
|
||||||
@@ -191,10 +204,19 @@ void SymbolPartScaleAction::update() {
|
|||||||
// the size after the move
|
// the size after the move
|
||||||
newMin = newRealMin; newSize = newRealSize;
|
newMin = newRealMin; newSize = newRealSize;
|
||||||
if (constrain && scaleX != 0 && scaleY != 0) {
|
if (constrain && scaleX != 0 && scaleY != 0) {
|
||||||
|
// TODO : snapping
|
||||||
Vector2D scale = newSize.div(tmpSize);
|
Vector2D scale = newSize.div(tmpSize);
|
||||||
scale = constrainVector(scale, true, true);
|
scale = constrain_vector(scale, true, true);
|
||||||
newSize = tmpSize.mul(scale);
|
newSize = tmpSize.mul(scale);
|
||||||
newMin += (newRealSize - newSize).mul(Vector2D(scaleX == -1 ? 1 : 0, scaleY == -1 ? 1 : 0));
|
newMin += (newRealSize - newSize).mul(Vector2D(scaleX == -1 ? 1 : 0, scaleY == -1 ? 1 : 0));
|
||||||
|
} else if (snap >= 0) {
|
||||||
|
if (scaleX + scaleY < 0) {
|
||||||
|
newMin = snap_vector(newMin, snap);
|
||||||
|
newSize += newRealMin - newMin;
|
||||||
|
} else {
|
||||||
|
Vector2D newMax = snap_vector(newMin + newSize, snap);
|
||||||
|
newSize = newMax - newMin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// now move all points
|
// now move all points
|
||||||
transformAll();
|
transformAll();
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ class SymbolPartMoveAction : public SymbolPartAction {
|
|||||||
set<SymbolPartP> parts; ///< Parts to move
|
set<SymbolPartP> parts; ///< Parts to move
|
||||||
Vector2D delta; ///< How much to move
|
Vector2D delta; ///< How much to move
|
||||||
Vector2D moved; ///< How much has been moved
|
Vector2D moved; ///< How much has been moved
|
||||||
|
Vector2D min_pos, max_pos; ///< Bounding box of the thing we are moving
|
||||||
public:
|
public:
|
||||||
bool constrain; ///< Constrain movement?
|
bool constrain; ///< Constrain movement?
|
||||||
|
int snap; ///< Snap to grid?
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Rotating symbol parts
|
// ----------------------------------------------------------------------------- : Rotating symbol parts
|
||||||
@@ -101,9 +103,11 @@ class SymbolPartShearAction : public SymbolPartMatrixAction {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2D shear; ///< Shearing, shear.x == 0 || shear.y == 0
|
Vector2D shear; ///< Shearing, shear.x == 0 || shear.y == 0
|
||||||
|
Vector2D moved;
|
||||||
void shearBy(const Vector2D& shear);
|
void shearBy(const Vector2D& shear);
|
||||||
public:
|
public:
|
||||||
bool constrain; ///< Constrain movement?
|
// bool constrain; ///< Constrain movement?
|
||||||
|
int snap; ///< Snap to grid?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -135,7 +139,8 @@ class SymbolPartScaleAction : public SymbolPartAction {
|
|||||||
return (v - oldMin).div(oldSize).mul(newSize) + newMin;
|
return (v - oldMin).div(oldSize).mul(newSize) + newMin;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
bool constrain; ///< Constrain movement?
|
bool constrain; ///< Constrain movement?
|
||||||
|
int snap; ///< Snap to grid?
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Change combine mode
|
// ----------------------------------------------------------------------------- : Change combine mode
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ DECLARE_TYPEOF_COLLECTION(ControlPointP);
|
|||||||
|
|
||||||
inline double sgn(double v) { return v > 0 ? 1 : -1; }
|
inline double sgn(double v) { return v > 0 ? 1 : -1; }
|
||||||
|
|
||||||
Vector2D constrainVector(const Vector2D& v, bool constrain, bool onlyDiagonal) {
|
Vector2D constrain_vector(const Vector2D& v, bool constrain, bool only_diagonal) {
|
||||||
if (!constrain) return v;
|
if (!constrain) return v;
|
||||||
double ax = fabs(v.x), ay = fabs(v.y);
|
double ax = fabs(v.x), ay = fabs(v.y);
|
||||||
if (ax * 2 < ay && !onlyDiagonal) {
|
if (ax * 2 < ay && !only_diagonal) {
|
||||||
return Vector2D(0, v.y); // vertical
|
return Vector2D(0, v.y); // vertical
|
||||||
} else if(ay * 2 < ax && !onlyDiagonal) {
|
} else if(ay * 2 < ax && !only_diagonal) {
|
||||||
return Vector2D(v.x, 0); // horizontal
|
return Vector2D(v.x, 0); // horizontal
|
||||||
} else {
|
} else {
|
||||||
return Vector2D( // diagonal
|
return Vector2D( // diagonal
|
||||||
@@ -31,11 +31,62 @@ Vector2D constrainVector(const Vector2D& v, bool constrain, bool onlyDiagonal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double snap(double x, int steps) {
|
||||||
|
return steps <= 0 ? x : floor(x * steps + 0.5) / steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D snap_vector(const Vector2D& v, int steps) {
|
||||||
|
return Vector2D(snap(v.x, steps), snap(v.y, steps));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D constrain_snap_vector(const Vector2D& v, const Vector2D& d, bool constrain, int steps) {
|
||||||
|
if (!constrain) return snap_vector(v+d, steps);
|
||||||
|
double ax = fabs(d.x), ay = fabs(d.y);
|
||||||
|
if (ax * 2 < ay) {
|
||||||
|
return Vector2D(v.x, snap(d.y + v.y, steps)); // vertical
|
||||||
|
} else if(ay * 2 < ax) {
|
||||||
|
return Vector2D(snap(d.x + v.x, steps), v.y); // horizontal
|
||||||
|
} else {
|
||||||
|
double dc = (ax + ay) / 2; // delta in both directions
|
||||||
|
double dxs = snap(v.x + dc, steps) - v.x; // snapped to x
|
||||||
|
double dys = snap(v.y + dc, steps) - v.y; // snapped to y
|
||||||
|
if (fabs(dxs-dc) < fabs(dys-dc)) {
|
||||||
|
// take the one that is closest to the unsnaped delta
|
||||||
|
return Vector2D(v.x + sgn(d.x) * dxs, v.y + sgn(d.y) * dxs);
|
||||||
|
} else {
|
||||||
|
return Vector2D(v.x + sgn(d.x) * dys, v.y + sgn(d.y) * dys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& d, bool constrain, int steps) {
|
||||||
|
return constrain_snap_vector(off1, d, constrain, steps) - off1;
|
||||||
|
}
|
||||||
|
// calculate constrained delta for the given offset, store in output if it is better
|
||||||
|
void constrain_snap_vector_offset_(const Vector2D& off, const Vector2D& d, bool constrain, int steps, Vector2D& best, double& best_length) {
|
||||||
|
Vector2D d2 = constrain_snap_vector_offset(off, d, constrain, steps);
|
||||||
|
double l2 = d2.lengthSqr();
|
||||||
|
if (l2 < best_length) {
|
||||||
|
best_length = l2;
|
||||||
|
best = d2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& off2, const Vector2D& d, bool constrain, int steps) {
|
||||||
|
Vector2D dd; double l = numeric_limits<double>::infinity();
|
||||||
|
constrain_snap_vector_offset_(off1, d, constrain, steps, dd, l);
|
||||||
|
constrain_snap_vector_offset_(off2, d, constrain, steps, dd, l);
|
||||||
|
constrain_snap_vector_offset_(Vector2D(off1.x,off2.y), d, constrain, steps, dd, l);
|
||||||
|
constrain_snap_vector_offset_(Vector2D(off2.x,off1.y), d, constrain, steps, dd, l);
|
||||||
|
return dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Move control point
|
// ----------------------------------------------------------------------------- : Move control point
|
||||||
|
|
||||||
ControlPointMoveAction::ControlPointMoveAction(const set<ControlPointP>& points)
|
ControlPointMoveAction::ControlPointMoveAction(const set<ControlPointP>& points)
|
||||||
: points(points)
|
: points(points)
|
||||||
, constrain(false)
|
, constrain(false)
|
||||||
|
, snap(0)
|
||||||
{
|
{
|
||||||
oldValues.reserve(points.size());
|
oldValues.reserve(points.size());
|
||||||
FOR_EACH(p, points) {
|
FOR_EACH(p, points) {
|
||||||
@@ -48,13 +99,6 @@ String ControlPointMoveAction::getName(bool to_undo) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ControlPointMoveAction::perform(bool to_undo) {
|
void ControlPointMoveAction::perform(bool to_undo) {
|
||||||
/*
|
|
||||||
set<ControlPointP>::const_iterator it = points.begin();
|
|
||||||
vector<Vector2D> ::iterator it2 = oldValues.begin();
|
|
||||||
for( ; it != points.end() && it2 != oldValues.end() ; ++it, ++it2) {
|
|
||||||
swap<Vector2D>((*it)->pos, *it2);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
FOR_EACH_2(p,points, op,oldValues) {
|
FOR_EACH_2(p,points, op,oldValues) {
|
||||||
swap(p->pos, op);
|
swap(p->pos, op);
|
||||||
}
|
}
|
||||||
@@ -63,11 +107,10 @@ void ControlPointMoveAction::perform(bool to_undo) {
|
|||||||
void ControlPointMoveAction::move (const Vector2D& deltaDelta) {
|
void ControlPointMoveAction::move (const Vector2D& deltaDelta) {
|
||||||
delta += deltaDelta;
|
delta += deltaDelta;
|
||||||
// Move each point by delta, possibly constrained
|
// Move each point by delta, possibly constrained
|
||||||
Vector2D d = constrainVector(delta, constrain);
|
|
||||||
set<ControlPointP>::const_iterator it = points.begin();
|
set<ControlPointP>::const_iterator it = points.begin();
|
||||||
vector<Vector2D> ::iterator it2 = oldValues.begin();
|
vector<Vector2D> ::iterator it2 = oldValues.begin();
|
||||||
for( ; it != points.end() && it2 != oldValues.end() ; ++it, ++it2) {
|
for( ; it != points.end() && it2 != oldValues.end() ; ++it, ++it2) {
|
||||||
(*it)->pos = (*it2) + d;
|
(*it)->pos = constrain_snap_vector(*it2, delta, constrain, snap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +122,7 @@ HandleMoveAction::HandleMoveAction(const SelectedHandle& handle)
|
|||||||
, old_handle(handle.getHandle())
|
, old_handle(handle.getHandle())
|
||||||
, old_other (handle.getOther())
|
, old_other (handle.getOther())
|
||||||
, constrain(false)
|
, constrain(false)
|
||||||
|
, snap(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String HandleMoveAction::getName(bool to_undo) const {
|
String HandleMoveAction::getName(bool to_undo) const {
|
||||||
@@ -92,7 +136,7 @@ void HandleMoveAction::perform(bool to_undo) {
|
|||||||
|
|
||||||
void HandleMoveAction::move(const Vector2D& deltaDelta) {
|
void HandleMoveAction::move(const Vector2D& deltaDelta) {
|
||||||
delta += deltaDelta;
|
delta += deltaDelta;
|
||||||
handle.getHandle() = constrainVector(old_handle + delta, constrain);
|
handle.getHandle() = constrain_snap_vector_offset(handle.point->pos, old_handle + delta, constrain, snap);
|
||||||
handle.getOther() = old_other;
|
handle.getOther() = old_other;
|
||||||
handle.onUpdateHandle();
|
handle.onUpdateHandle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,25 @@
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Utility
|
// ----------------------------------------------------------------------------- : Utility
|
||||||
|
|
||||||
/// Constrain a vector to be horizontal, vertical or diagonal
|
/// Constrain a vector to be horizontal, vertical or diagonal.
|
||||||
/// If constraint==false does nothing
|
/** If constraint==false does nothing
|
||||||
Vector2D constrainVector(const Vector2D& v, bool constrain = true, bool onlyDiagonal = false);
|
*/
|
||||||
|
Vector2D constrain_vector(const Vector2D& v, bool constrain = true, bool only_diagonal = false);
|
||||||
|
|
||||||
|
/// Snap a vector to the grid with the given number of steps per unit interval.
|
||||||
|
/** If spacing==0 does not snap. */
|
||||||
|
Vector2D snap_vector(const Vector2D& v, int steps);
|
||||||
|
|
||||||
|
/// Add a delta to a vector
|
||||||
|
/** Possibly constrain the delta, and snap to result to grid
|
||||||
|
*/
|
||||||
|
Vector2D constrain_snap_vector(const Vector2D& v, const Vector2D& d, bool constrain, int steps);
|
||||||
|
|
||||||
|
/// Constrain a vector a vector, and snap to an offset grid
|
||||||
|
Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& d, bool constrain, int steps);
|
||||||
|
/// Constrain a vector a vector, and snap to two possible offset grids
|
||||||
|
/** Takes the closest snap */
|
||||||
|
Vector2D constrain_snap_vector_offset(const Vector2D& off1, const Vector2D& off2, const Vector2D& d, bool constrain, int steps);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Move control point
|
// ----------------------------------------------------------------------------- : Move control point
|
||||||
|
|
||||||
@@ -43,6 +59,7 @@ class ControlPointMoveAction : public Action {
|
|||||||
Vector2D delta; ///< Amount we moved
|
Vector2D delta; ///< Amount we moved
|
||||||
public:
|
public:
|
||||||
bool constrain; ///< Constrain movement?
|
bool constrain; ///< Constrain movement?
|
||||||
|
int snap; ///< Snap to grid?
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Move handle
|
// ----------------------------------------------------------------------------- : Move handle
|
||||||
@@ -65,6 +82,7 @@ class HandleMoveAction : public Action {
|
|||||||
Vector2D delta; ///< Amount we moved
|
Vector2D delta; ///< Amount we moved
|
||||||
public:
|
public:
|
||||||
bool constrain; ///< Constrain movement?
|
bool constrain; ///< Constrain movement?
|
||||||
|
int snap; ///< Snap to grid?
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Segment mode
|
// ----------------------------------------------------------------------------- : Segment mode
|
||||||
|
|||||||
@@ -220,6 +220,10 @@ SymbolP import_symbol(Image& img) {
|
|||||||
if (is_mse1_symbol(img)) {
|
if (is_mse1_symbol(img)) {
|
||||||
Image img2 = img.GetSubImage(wxRect(20,0,40,40));
|
Image img2 = img.GetSubImage(wxRect(20,0,40,40));
|
||||||
symbol = image_to_symbol(img2);
|
symbol = image_to_symbol(img2);
|
||||||
|
} else if (img.GetWidth() > 100 || img.GetHeight() > 100) {
|
||||||
|
// 100x100 ought to be enough, we trow out most afterwards data anyway
|
||||||
|
Image resampled = img.Rescale(100,100);
|
||||||
|
symbol = image_to_symbol(resampled);
|
||||||
} else {
|
} else {
|
||||||
symbol = image_to_symbol(img);
|
symbol = image_to_symbol(img);
|
||||||
}
|
}
|
||||||
@@ -387,7 +391,7 @@ void remove_point(SymbolPart& part, int i);
|
|||||||
* stop when the cost becomes too high
|
* stop when the cost becomes too high
|
||||||
*/
|
*/
|
||||||
void remove_points(SymbolPart& part) {
|
void remove_points(SymbolPart& part) {
|
||||||
const double treshold = 0.002; // maximum cost
|
const double treshold = 0.0002; // maximum cost
|
||||||
while (true) {
|
while (true) {
|
||||||
// Find the point with the lowest cost of removal
|
// Find the point with the lowest cost of removal
|
||||||
int best = -1;
|
int best = -1;
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ Settings::Settings()
|
|||||||
, set_window_width (790)
|
, set_window_width (790)
|
||||||
, set_window_height (300)
|
, set_window_height (300)
|
||||||
, card_notes_height (40)
|
, card_notes_height (40)
|
||||||
|
, symbol_grid_size (30)
|
||||||
|
, symbol_grid (true)
|
||||||
|
, symbol_grid_snap (false)
|
||||||
, updates_url (_("http://magicseteditor.sourceforge.net/updates"))
|
, updates_url (_("http://magicseteditor.sourceforge.net/updates"))
|
||||||
, check_updates (CHECK_IF_CONNECTED)
|
, check_updates (CHECK_IF_CONNECTED)
|
||||||
, website_url (_("http://magicseteditor.sourceforge.net/"))
|
, website_url (_("http://magicseteditor.sourceforge.net/"))
|
||||||
@@ -155,6 +158,9 @@ IMPLEMENT_REFLECTION(Settings) {
|
|||||||
REFLECT(set_window_width);
|
REFLECT(set_window_width);
|
||||||
REFLECT(set_window_height);
|
REFLECT(set_window_height);
|
||||||
REFLECT(card_notes_height);
|
REFLECT(card_notes_height);
|
||||||
|
REFLECT(symbol_grid_size);
|
||||||
|
REFLECT(symbol_grid);
|
||||||
|
REFLECT(symbol_grid_snap);
|
||||||
REFLECT(default_game);
|
REFLECT(default_game);
|
||||||
REFLECT(apprentice_location);
|
REFLECT(apprentice_location);
|
||||||
REFLECT(updates_url);
|
REFLECT(updates_url);
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ class Settings {
|
|||||||
UInt set_window_height;
|
UInt set_window_height;
|
||||||
UInt card_notes_height;
|
UInt card_notes_height;
|
||||||
|
|
||||||
|
// --------------------------------------------------- : Symbol editor
|
||||||
|
UInt symbol_grid_size;
|
||||||
|
bool symbol_grid;
|
||||||
|
bool symbol_grid_snap;
|
||||||
|
|
||||||
// --------------------------------------------------- : Default pacakge selections
|
// --------------------------------------------------- : Default pacakge selections
|
||||||
String default_game;
|
String default_game;
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ void GalleryList::onChar(wxKeyEvent& ev) {
|
|||||||
|
|
||||||
wxSize GalleryList::DoGetBestSize() const {
|
wxSize GalleryList::DoGetBestSize() const {
|
||||||
wxSize ws = GetSize(), cs = GetClientSize();
|
wxSize ws = GetSize(), cs = GetClientSize();
|
||||||
const int w = item_size.x + SPACING;
|
const int w = item_size.x + 2*MARGIN + 2*BORDER;
|
||||||
const int h = item_size.y + SPACING;
|
const int h = item_size.y + 2*MARGIN + 2*BORDER;
|
||||||
return wxSize(w, h) + ws - cs;
|
return wxSize(w, h) + ws - cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ void SymbolBasicShapeEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
tb->RemoveChild(sidesL);
|
tb->RemoveChild(sidesL);
|
||||||
tb->RemoveChild(sides);
|
tb->RemoveChild(sides);
|
||||||
// HACK: hardcoded size of rest of toolbar
|
// HACK: hardcoded size of rest of toolbar
|
||||||
tb->DeleteToolByPos(4); // delete separator
|
tb->DeleteToolByPos(7); // delete separator
|
||||||
tb->DeleteToolByPos(4); // delete sidesL
|
tb->DeleteToolByPos(7); // delete sidesL
|
||||||
tb->DeleteToolByPos(4); // delete sides
|
tb->DeleteToolByPos(7); // delete sides
|
||||||
#if wxVERSION_NUMBER < 2600
|
#if wxVERSION_NUMBER < 2600
|
||||||
delete sides;
|
delete sides;
|
||||||
delete sidesL;
|
delete sidesL;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <gui/symbol/basic_shape_editor.hpp>
|
#include <gui/symbol/basic_shape_editor.hpp>
|
||||||
#include <gui/util.hpp>
|
#include <gui/util.hpp>
|
||||||
#include <data/action/symbol.hpp>
|
#include <data/action/symbol.hpp>
|
||||||
|
#include <data/settings.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
|
|
||||||
@@ -65,7 +66,18 @@ void SymbolControl::onModeChange(wxCommandEvent& ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SymbolControl::onExtraTool(wxCommandEvent& ev) {
|
void SymbolControl::onExtraTool(wxCommandEvent& ev) {
|
||||||
if (editor) editor->onCommand(ev.GetId());
|
switch (ev.GetId()) {
|
||||||
|
case ID_VIEW_GRID:
|
||||||
|
settings.symbol_grid = !settings.symbol_grid;
|
||||||
|
Refresh(false);
|
||||||
|
break;
|
||||||
|
case ID_VIEW_GRID_SNAP:
|
||||||
|
settings.symbol_grid_snap = !settings.symbol_grid_snap;
|
||||||
|
Refresh(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (editor) editor->onCommand(ev.GetId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolControl::onAction(const Action& action, bool undone) {
|
void SymbolControl::onAction(const Action& action, bool undone) {
|
||||||
@@ -135,6 +147,25 @@ void SymbolControl::draw(DC& dc) {
|
|||||||
clearDC(dc, Color(0, 128, 0));
|
clearDC(dc, Color(0, 128, 0));
|
||||||
// draw symbol iself
|
// draw symbol iself
|
||||||
SymbolViewer::draw(dc);
|
SymbolViewer::draw(dc);
|
||||||
|
// draw grid
|
||||||
|
if (settings.symbol_grid) {
|
||||||
|
wxSize s = dc.GetSize();
|
||||||
|
int lines = settings.symbol_grid_size;
|
||||||
|
for (int i = 0 ; i <= lines ; ++i) {
|
||||||
|
int x = rotation.trS((double)i/lines-0.0001);
|
||||||
|
//dc.SetPen(Color(0, i%5 == 0 ? 64 : 31, 0));
|
||||||
|
//dc.SetPen(Color(i%5 == 0 ? 64 : 31, 0, 0));
|
||||||
|
dc.SetLogicalFunction(wxAND);
|
||||||
|
dc.SetPen(i%5 == 0 ? Color(191,255,191) : Color(191, 255, 191));
|
||||||
|
dc.DrawLine(x, 0, x, s.y);
|
||||||
|
dc.DrawLine(0, x, s.x, x);
|
||||||
|
dc.SetLogicalFunction(wxOR);
|
||||||
|
dc.SetPen(i%5 == 0 ? Color(0,63,0) : Color(0, 31, 0));
|
||||||
|
dc.DrawLine(x, 0, x, s.y);
|
||||||
|
dc.DrawLine(0, x, s.x, x);
|
||||||
|
}
|
||||||
|
dc.SetLogicalFunction(wxCOPY);
|
||||||
|
}
|
||||||
// draw editing overlay
|
// draw editing overlay
|
||||||
if (editor) {
|
if (editor) {
|
||||||
editor->draw(dc);
|
editor->draw(dc);
|
||||||
@@ -196,7 +227,7 @@ void SymbolControl::onChar(wxKeyEvent& ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SymbolControl::onSize(wxSizeEvent& ev) {
|
void SymbolControl::onSize(wxSizeEvent& ev) {
|
||||||
wxSize s = ev.GetSize();
|
wxSize s = GetClientSize();
|
||||||
rotation.setZoom(min(s.GetWidth(), s.GetHeight()));
|
rotation.setZoom(min(s.GetWidth(), s.GetHeight()));
|
||||||
Refresh(false);
|
Refresh(false);
|
||||||
}
|
}
|
||||||
@@ -213,6 +244,12 @@ void SymbolControl::onUpdateUI(wxUpdateUIEvent& ev) {
|
|||||||
case ID_MODE_PAINT:
|
case ID_MODE_PAINT:
|
||||||
ev.Enable(false); // TODO
|
ev.Enable(false); // TODO
|
||||||
break;
|
break;
|
||||||
|
case ID_VIEW_GRID:
|
||||||
|
ev.Check(settings.symbol_grid);
|
||||||
|
break;
|
||||||
|
case ID_VIEW_GRID_SNAP:
|
||||||
|
ev.Check(settings.symbol_grid_snap);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (ev.GetId() >= ID_CHILD_MIN && ev.GetId() < ID_CHILD_MAX) {
|
if (ev.GetId() >= ID_CHILD_MIN && ev.GetId() < ID_CHILD_MAX) {
|
||||||
editor->onUpdateUI(ev); // foward to editor
|
editor->onUpdateUI(ev); // foward to editor
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <gui/util.hpp>
|
#include <gui/util.hpp>
|
||||||
#include <gfx/bezier.hpp>
|
#include <gfx/bezier.hpp>
|
||||||
#include <data/action/symbol_part.hpp>
|
#include <data/action/symbol_part.hpp>
|
||||||
|
#include <data/settings.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
|
|
||||||
@@ -172,8 +173,8 @@ void SymbolPointEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
tb->DeleteTool(ID_LOCK_DIR);
|
tb->DeleteTool(ID_LOCK_DIR);
|
||||||
tb->DeleteTool(ID_LOCK_SIZE);
|
tb->DeleteTool(ID_LOCK_SIZE);
|
||||||
// HACK: hardcoded size of rest of toolbar
|
// HACK: hardcoded size of rest of toolbar
|
||||||
tb->DeleteToolByPos(4); // delete separator
|
tb->DeleteToolByPos(7); // delete separator
|
||||||
tb->DeleteToolByPos(4); // delete separator
|
tb->DeleteToolByPos(7); // delete separator
|
||||||
// TODO : menu bar
|
// TODO : menu bar
|
||||||
//mb->Remove(2)
|
//mb->Remove(2)
|
||||||
}
|
}
|
||||||
@@ -215,8 +216,10 @@ void SymbolPointEditor::onCommand(int id) {
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case ID_SEGMENT_LINE: case ID_SEGMENT_CURVE:
|
case ID_SEGMENT_LINE: case ID_SEGMENT_CURVE:
|
||||||
onChangeSegment( static_cast<SegmentMode>(id - ID_SEGMENT) );
|
onChangeSegment( static_cast<SegmentMode>(id - ID_SEGMENT) );
|
||||||
|
break;
|
||||||
case ID_LOCK_FREE: case ID_LOCK_DIR: case ID_LOCK_SIZE:
|
case ID_LOCK_FREE: case ID_LOCK_DIR: case ID_LOCK_SIZE:
|
||||||
onChangeLock( static_cast<LockMode>(id - ID_LOCK) );
|
onChangeLock( static_cast<LockMode>(id - ID_LOCK) );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +276,10 @@ void SymbolPointEditor::onMouseMove(const Vector2D& from, const Vector2D& to, wx
|
|||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Event> int snap(Event& ev) {
|
||||||
|
return settings.symbol_grid_snap != ev.ShiftDown() ? settings.symbol_grid_size : 0; // shift toggles snap
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wxMouseEvent& ev) {
|
void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wxMouseEvent& ev) {
|
||||||
Vector2D delta = to - from;
|
Vector2D delta = to - from;
|
||||||
if (selection == SELECTED_LINE && ev.AltDown()) {
|
if (selection == SELECTED_LINE && ev.AltDown()) {
|
||||||
@@ -293,6 +300,7 @@ void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wx
|
|||||||
getSymbol()->actions.add(controlPointMoveAction);
|
getSymbol()->actions.add(controlPointMoveAction);
|
||||||
}
|
}
|
||||||
controlPointMoveAction->constrain = ev.ControlDown(); // ctrl constrains
|
controlPointMoveAction->constrain = ev.ControlDown(); // ctrl constrains
|
||||||
|
controlPointMoveAction->snap = snap(ev);
|
||||||
controlPointMoveAction->move(delta);
|
controlPointMoveAction->move(delta);
|
||||||
new_point += delta;
|
new_point += delta;
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
@@ -302,7 +310,8 @@ void SymbolPointEditor::onMouseDrag(const Vector2D& from, const Vector2D& to, wx
|
|||||||
handleMoveAction = new HandleMoveAction(selected_handle);
|
handleMoveAction = new HandleMoveAction(selected_handle);
|
||||||
getSymbol()->actions.add(handleMoveAction);
|
getSymbol()->actions.add(handleMoveAction);
|
||||||
}
|
}
|
||||||
handleMoveAction->constrain = ev.ControlDown(); // ctrl constrains
|
handleMoveAction->constrain = ev.ControlDown(); // ctrl constrains
|
||||||
|
handleMoveAction->snap = snap(ev);
|
||||||
handleMoveAction->move(delta);
|
handleMoveAction->move(delta);
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
@@ -323,14 +332,16 @@ void SymbolPointEditor::onKeyChange(wxKeyEvent& ev) {
|
|||||||
SetStatusText(_("Alt + drag to move curve; double click to add control point on this line"));
|
SetStatusText(_("Alt + drag to move curve; double click to add control point on this line"));
|
||||||
}
|
}
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
} else if (ev.GetKeyCode() == WXK_CONTROL) {
|
} else if (ev.GetKeyCode() == WXK_CONTROL || ev.GetKeyCode() == WXK_SHIFT) {
|
||||||
// constrain changed
|
// constrain/snap changed
|
||||||
if (controlPointMoveAction) {
|
if (controlPointMoveAction) {
|
||||||
controlPointMoveAction->constrain = ev.ControlDown();
|
controlPointMoveAction->constrain = ev.ControlDown();
|
||||||
|
controlPointMoveAction->snap = snap(ev);
|
||||||
controlPointMoveAction->move(Vector2D()); //refresh action
|
controlPointMoveAction->move(Vector2D()); //refresh action
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
} else if (handleMoveAction) {
|
} else if (handleMoveAction) {
|
||||||
handleMoveAction->constrain = ev.ControlDown();
|
handleMoveAction->constrain = ev.ControlDown();
|
||||||
|
handleMoveAction->snap = snap(ev);
|
||||||
handleMoveAction->move(Vector2D()); //refresh action
|
handleMoveAction->move(Vector2D()); //refresh action
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <gui/util.hpp>
|
#include <gui/util.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <data/action/symbol.hpp>
|
#include <data/action/symbol.hpp>
|
||||||
|
#include <data/settings.hpp>
|
||||||
#include <gfx/gfx.hpp>
|
#include <gfx/gfx.hpp>
|
||||||
|
|
||||||
DECLARE_TYPEOF_COLLECTION(SymbolPartP);
|
DECLARE_TYPEOF_COLLECTION(SymbolPartP);
|
||||||
@@ -122,7 +123,7 @@ void SymbolSelectEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
|||||||
tb->DeleteTool(ID_PART_OVERLAP);
|
tb->DeleteTool(ID_PART_OVERLAP);
|
||||||
tb->DeleteTool(ID_PART_BORDER);
|
tb->DeleteTool(ID_PART_BORDER);
|
||||||
// HACK: hardcoded size of rest of toolbar
|
// HACK: hardcoded size of rest of toolbar
|
||||||
tb->DeleteToolByPos(4); // delete separator
|
tb->DeleteToolByPos(7); // delete separator
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolSelectEditor::onUpdateUI(wxUpdateUIEvent& ev) {
|
void SymbolSelectEditor::onUpdateUI(wxUpdateUIEvent& ev) {
|
||||||
@@ -173,6 +174,40 @@ int SymbolSelectEditor::modeToolId() {
|
|||||||
// ----------------------------------------------------------------------------- : Mouse Events
|
// ----------------------------------------------------------------------------- : Mouse Events
|
||||||
|
|
||||||
void SymbolSelectEditor::onLeftDown (const Vector2D& pos, wxMouseEvent& ev) {
|
void SymbolSelectEditor::onLeftDown (const Vector2D& pos, wxMouseEvent& ev) {
|
||||||
|
have_dragged = true;
|
||||||
|
// change selection
|
||||||
|
// Are we on a handle?
|
||||||
|
int dx, dy;
|
||||||
|
if (onAnyHandle(pos, &dx, &dy)) return; // don't change the selection
|
||||||
|
// Select the part under the cursor
|
||||||
|
SymbolPartP part = findPart(pos);
|
||||||
|
if (part) {
|
||||||
|
if (ev.ShiftDown()) {
|
||||||
|
// toggle selection
|
||||||
|
set<SymbolPartP>::iterator it = control.selected_parts.find(part);
|
||||||
|
if (it != control.selected_parts.end()) {
|
||||||
|
control.selected_parts.erase(it);
|
||||||
|
} else {
|
||||||
|
control.selected_parts.insert(part);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (control.selected_parts.find(part) != control.selected_parts.end()) {
|
||||||
|
// already selected, do nothing
|
||||||
|
have_dragged = false; // we haven't done anything
|
||||||
|
} else {
|
||||||
|
// select the part under the cursor
|
||||||
|
control.selected_parts.clear();
|
||||||
|
control.selected_parts.insert(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!ev.ShiftDown()) {
|
||||||
|
// select nothing
|
||||||
|
control.selected_parts.clear();
|
||||||
|
}
|
||||||
|
// selection has changed
|
||||||
|
updateBoundingBox();
|
||||||
|
control.signalSelectionChange();
|
||||||
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolSelectEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) {
|
void SymbolSelectEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) {
|
||||||
@@ -180,39 +215,18 @@ void SymbolSelectEditor::onLeftUp (const Vector2D& pos, wxMouseEvent& ev) {
|
|||||||
// stop editing
|
// stop editing
|
||||||
resetActions();
|
resetActions();
|
||||||
} else {
|
} else {
|
||||||
// mouse not moved, change selection
|
// mouse not moved -> change selection
|
||||||
// Are we on a handle?
|
if (!have_dragged && !ev.ShiftDown()) {
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
if (onAnyHandle(pos, &dx, &dy)) return; // don't change the selection
|
if (onAnyHandle(pos, &dx, &dy)) return; // don't change the selection
|
||||||
// Select the part under the cursor
|
// Find the part under the cursor
|
||||||
SymbolPartP part = findPart(pos);
|
SymbolPartP part = findPart(pos);
|
||||||
if (part) {
|
if (control.selected_parts.find(part) != control.selected_parts.end()) {
|
||||||
if (ev.ShiftDown()) {
|
// already selected, don't change selection
|
||||||
// toggle selection
|
// instead switch between rotate and resize mode
|
||||||
set<SymbolPartP>::iterator it = control.selected_parts.find(part);
|
rotate = !rotate;
|
||||||
if (it != control.selected_parts.end()) {
|
|
||||||
control.selected_parts.erase(it);
|
|
||||||
} else {
|
|
||||||
control.selected_parts.insert(part);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (control.selected_parts.find(part) != control.selected_parts.end()) {
|
|
||||||
// already selected, don't change selection
|
|
||||||
// instead switch between rotate and resize mode
|
|
||||||
rotate = !rotate;
|
|
||||||
} else {
|
|
||||||
// select the part under the cursor
|
|
||||||
control.selected_parts.clear();
|
|
||||||
control.selected_parts.insert(part);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (!ev.ShiftDown()) {
|
|
||||||
// select nothing
|
|
||||||
control.selected_parts.clear();
|
|
||||||
}
|
}
|
||||||
// selection has changed
|
|
||||||
updateBoundingBox();
|
|
||||||
control.signalSelectionChange();
|
|
||||||
}
|
}
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
@@ -261,7 +275,12 @@ void SymbolSelectEditor::onMouseMove (const Vector2D& from, const Vector2D& to,
|
|||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Event> int snap(Event& ev) {
|
||||||
|
return settings.symbol_grid_snap != ev.ShiftDown() ? settings.symbol_grid_size : 0; // shift toggles snap
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to, wxMouseEvent& ev) {
|
void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to, wxMouseEvent& ev) {
|
||||||
|
have_dragged = true;
|
||||||
if (control.selected_parts.empty()) return;
|
if (control.selected_parts.empty()) return;
|
||||||
if (!isEditing()) {
|
if (!isEditing()) {
|
||||||
// we don't have an action yet, determine what to do
|
// we don't have an action yet, determine what to do
|
||||||
@@ -294,6 +313,7 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
|
|||||||
if (moveAction) {
|
if (moveAction) {
|
||||||
// move the selected parts
|
// move the selected parts
|
||||||
moveAction->constrain = ev.ControlDown();
|
moveAction->constrain = ev.ControlDown();
|
||||||
|
moveAction->snap = snap(ev);
|
||||||
moveAction->move(to - from);
|
moveAction->move(to - from);
|
||||||
} else if (scaleAction) {
|
} else if (scaleAction) {
|
||||||
// scale the selected parts
|
// scale the selected parts
|
||||||
@@ -303,7 +323,9 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
|
|||||||
if (scaleX == 1) dMax.x = delta.x;
|
if (scaleX == 1) dMax.x = delta.x;
|
||||||
if (scaleY == -1) dMin.y = delta.y;
|
if (scaleY == -1) dMin.y = delta.y;
|
||||||
if (scaleY == 1) dMax.y = delta.y;
|
if (scaleY == 1) dMax.y = delta.y;
|
||||||
scaleAction->constrain = ev.ControlDown();
|
// scaleAction->constrain = ev.ControlDown();
|
||||||
|
scaleAction->constrain = true; // always constrain diagonal scaling
|
||||||
|
scaleAction->snap = snap(ev);
|
||||||
scaleAction->move(dMin, dMax);
|
scaleAction->move(dMin, dMax);
|
||||||
} else if (rotateAction) {
|
} else if (rotateAction) {
|
||||||
// rotate the selected parts
|
// rotate the selected parts
|
||||||
@@ -315,7 +337,8 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
|
|||||||
Vector2D delta = to-from;
|
Vector2D delta = to-from;
|
||||||
delta = delta.mul(Vector2D(scaleY, scaleX));
|
delta = delta.mul(Vector2D(scaleY, scaleX));
|
||||||
delta = delta.div(maxV - minV);
|
delta = delta.div(maxV - minV);
|
||||||
shearAction->constrain = ev.ControlDown();
|
// shearAction->constrain = ev.ControlDown();
|
||||||
|
shearAction->snap = snap(ev);
|
||||||
shearAction->move(delta);
|
shearAction->move(delta);
|
||||||
}
|
}
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
@@ -324,21 +347,28 @@ void SymbolSelectEditor::onMouseDrag (const Vector2D& from, const Vector2D& to,
|
|||||||
// ----------------------------------------------------------------------------- : Key Events
|
// ----------------------------------------------------------------------------- : Key Events
|
||||||
|
|
||||||
void SymbolSelectEditor::onKeyChange (wxKeyEvent& ev) {
|
void SymbolSelectEditor::onKeyChange (wxKeyEvent& ev) {
|
||||||
if (ev.GetKeyCode() == WXK_CONTROL) {
|
if (ev.GetKeyCode() == WXK_CONTROL || ev.GetKeyCode() == WXK_SHIFT) {
|
||||||
// changed constrains
|
// changed constrains
|
||||||
if (moveAction) {
|
if (moveAction) {
|
||||||
moveAction->constrain = ev.ControlDown();
|
moveAction->constrain = ev.ControlDown();
|
||||||
|
moveAction->snap = snap(ev);
|
||||||
moveAction->move(Vector2D()); // apply constrains
|
moveAction->move(Vector2D()); // apply constrains
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
} else if (scaleAction) {
|
} else if (scaleAction) {
|
||||||
// only allow constrained scaling in diagonal direction
|
// only allow constrained scaling in diagonal direction
|
||||||
scaleAction->constrain = ev.ControlDown();
|
// scaleAction->constrain = ev.ControlDown();
|
||||||
|
scaleAction->constrain = true; // always constrain diagonal scaling
|
||||||
|
scaleAction->snap = snap(ev);
|
||||||
scaleAction->update(); // apply constrains
|
scaleAction->update(); // apply constrains
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
} else if (rotateAction) {
|
} else if (rotateAction) {
|
||||||
rotateAction->constrain = ev.ControlDown();
|
rotateAction->constrain = ev.ControlDown();
|
||||||
rotateAction->rotateBy(0); // apply constrains
|
rotateAction->rotateBy(0); // apply constrains
|
||||||
control.Refresh(false);
|
control.Refresh(false);
|
||||||
|
} else if (shearAction) {
|
||||||
|
shearAction->snap = snap(ev);
|
||||||
|
shearAction->move(Vector2D()); // apply constrains
|
||||||
|
control.Refresh(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,7 +438,7 @@ void SymbolSelectEditor::updateBoundingBox() {
|
|||||||
minV = piecewise_min(minV, p->min_pos);
|
minV = piecewise_min(minV, p->min_pos);
|
||||||
maxV = piecewise_max(maxV, p->max_pos);
|
maxV = piecewise_max(maxV, p->max_pos);
|
||||||
}
|
}
|
||||||
// Find rotation center
|
/* // Find rotation center
|
||||||
center = Vector2D(0,0);
|
center = Vector2D(0,0);
|
||||||
FOR_EACH(p, control.selected_parts) {
|
FOR_EACH(p, control.selected_parts) {
|
||||||
Vector2D size = p->max_pos - p->min_pos;
|
Vector2D size = p->max_pos - p->min_pos;
|
||||||
@@ -416,6 +446,8 @@ void SymbolSelectEditor::updateBoundingBox() {
|
|||||||
center += p->min_pos + size;
|
center += p->min_pos + size;
|
||||||
}
|
}
|
||||||
center /= control.selected_parts.size();
|
center /= control.selected_parts.size();
|
||||||
|
*/
|
||||||
|
center = (minV + maxV) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolSelectEditor::resetActions() {
|
void SymbolSelectEditor::resetActions() {
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class SymbolSelectEditor : public SymbolEditorBase {
|
|||||||
double startAngle;
|
double startAngle;
|
||||||
// what side are we dragging/rotating on?
|
// what side are we dragging/rotating on?
|
||||||
int scaleX, scaleY;
|
int scaleX, scaleY;
|
||||||
|
// have we dragged?
|
||||||
|
bool have_dragged;
|
||||||
// Do we want to rotate?
|
// Do we want to rotate?
|
||||||
bool rotate;
|
bool rotate;
|
||||||
// Graphics assets
|
// Graphics assets
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ void SymbolWindow::init(Window* parent, SymbolP symbol) {
|
|||||||
tb->AddSeparator();
|
tb->AddSeparator();
|
||||||
tb->AddTool(ID_EDIT_UNDO, _("Undo"), load_resource_tool_image(_("undo")), wxNullBitmap, wxITEM_NORMAL, _TOOL_1_("undo",wxEmptyString));
|
tb->AddTool(ID_EDIT_UNDO, _("Undo"), load_resource_tool_image(_("undo")), wxNullBitmap, wxITEM_NORMAL, _TOOL_1_("undo",wxEmptyString));
|
||||||
tb->AddTool(ID_EDIT_REDO, _("Redo"), load_resource_tool_image(_("redo")), wxNullBitmap, wxITEM_NORMAL, _TOOL_1_("redo",wxEmptyString));
|
tb->AddTool(ID_EDIT_REDO, _("Redo"), load_resource_tool_image(_("redo")), wxNullBitmap, wxITEM_NORMAL, _TOOL_1_("redo",wxEmptyString));
|
||||||
|
tb->AddSeparator();
|
||||||
|
tb->AddTool(ID_VIEW_GRID, _("Grid"), load_resource_tool_image(_("grid")), wxNullBitmap, wxITEM_CHECK, _TOOL_("grid"));
|
||||||
|
tb->AddTool(ID_VIEW_GRID_SNAP,_("Snap"), load_resource_tool_image(_("grid_snap")), wxNullBitmap, wxITEM_CHECK, _TOOL_("snap"));
|
||||||
tb->Realize();
|
tb->Realize();
|
||||||
|
|
||||||
// Edit mode toolbar
|
// Edit mode toolbar
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ wxIcon load_resource_icon(const String& name) {
|
|||||||
|
|
||||||
wxBitmap load_resource_tool_image(const String& name) {
|
wxBitmap load_resource_tool_image(const String& name) {
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
return wxBitmap(_("tool/") + name);
|
return load_resource_image(_("tool/") + name);
|
||||||
#else
|
#else
|
||||||
return load_resource_image(_("tool/") + name);
|
return load_resource_image(_("tool/") + name);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ wxCursor load_resource_cursor(const String& name);
|
|||||||
wxIcon load_resource_icon(const String& name);
|
wxIcon load_resource_icon(const String& name);
|
||||||
|
|
||||||
/// Load an image for use in a toolbar (filename: tool/...) from a resource
|
/// Load an image for use in a toolbar (filename: tool/...) from a resource
|
||||||
/** Note: should ONLY be used for ".bmp" images for now
|
|
||||||
*/
|
|
||||||
wxBitmap load_resource_tool_image(const String& name);
|
wxBitmap load_resource_tool_image(const String& name);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Platform look
|
// ----------------------------------------------------------------------------- : Platform look
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ void SymbolViewer::highlightPart(DC& dc, const SymbolPart& part, HighlightStyle
|
|||||||
dc.DrawPolygon((int)points.size(), &points[0]);
|
dc.DrawPolygon((int)points.size(), &points[0]);
|
||||||
if (part.combine == PART_SUBTRACT || part.combine == PART_BORDER) {
|
if (part.combine == PART_SUBTRACT || part.combine == PART_BORDER) {
|
||||||
dc.SetLogicalFunction(wxAND);
|
dc.SetLogicalFunction(wxAND);
|
||||||
dc.SetBrush(Color(192,192,255));
|
dc.SetBrush(Color(191,191,255));
|
||||||
dc.DrawPolygon((int)points.size(), &points[0]);
|
dc.DrawPolygon((int)points.size(), &points[0]);
|
||||||
}
|
}
|
||||||
dc.SetLogicalFunction(wxCOPY);
|
dc.SetLogicalFunction(wxCOPY);
|
||||||
|
|||||||
@@ -19,36 +19,36 @@ icon/symbol ICON "icon/symbol.ico"
|
|||||||
|
|
||||||
cursor/rot_text CURSOR "cursor/rot_text.cur"
|
cursor/rot_text CURSOR "cursor/rot_text.cur"
|
||||||
|
|
||||||
tool/new BITMAP "tool/new.bmp"
|
tool/new IMAGE "tool/new.png"
|
||||||
tool/open BITMAP "tool/open.bmp"
|
tool/open IMAGE "tool/open.png"
|
||||||
tool/save BITMAP "tool/save.bmp"
|
tool/save IMAGE "tool/save.png"
|
||||||
|
|
||||||
tool/undo BITMAP "tool/undo.bmp"
|
tool/undo IMAGE "tool/undo.png"
|
||||||
tool/redo BITMAP "tool/redo.bmp"
|
tool/redo IMAGE "tool/redo.png"
|
||||||
tool/cut BITMAP "tool/cut.bmp"
|
tool/cut IMAGE "tool/cut.png"
|
||||||
tool/copy BITMAP "tool/copy.bmp"
|
tool/copy IMAGE "tool/copy.png"
|
||||||
tool/paste BITMAP "tool/paste.bmp"
|
tool/paste IMAGE "tool/paste.png"
|
||||||
tool/find BITMAP "tool/find.bmp"
|
tool/find IMAGE "tool/find.png"
|
||||||
|
|
||||||
tool/bold BITMAP "tool/bold.bmp"
|
tool/bold IMAGE "tool/bold.png"
|
||||||
tool/italic BITMAP "tool/italic.bmp"
|
tool/italic IMAGE "tool/italic.png"
|
||||||
tool/symbol BITMAP "tool/symbol.bmp"
|
tool/symbol IMAGE "tool/symbol.png"
|
||||||
tool/reminder BITMAP "tool/reminder.bmp"
|
tool/reminder IMAGE "tool/reminder.png"
|
||||||
tool/no_auto BITMAP "tool/no_auto.bmp"
|
tool/no_auto IMAGE "tool/no_auto.png"
|
||||||
|
|
||||||
tool/card_add BITMAP "tool/card_add.bmp"
|
tool/card_add IMAGE "tool/card_add.png"
|
||||||
tool/card_add_multiple BITMAP "tool/card_add_multiple.bmp"
|
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
||||||
tool/card_del BITMAP "tool/card_del.bmp"
|
tool/card_del IMAGE "tool/card_del.png"
|
||||||
tool/card_rotate BITMAP "tool/card_rotate.bmp"
|
tool/card_rotate IMAGE "tool/card_rotate.png"
|
||||||
tool/card_rotate_0 BITMAP "tool/card_rotate_0.bmp"
|
tool/card_rotate_0 IMAGE "tool/card_rotate_0.png"
|
||||||
tool/card_rotate_90 BITMAP "tool/card_rotate_90.bmp"
|
tool/card_rotate_90 IMAGE "tool/card_rotate_90.png"
|
||||||
tool/card_rotate_180 BITMAP "tool/card_rotate_180.bmp"
|
tool/card_rotate_180 IMAGE "tool/card_rotate_180.png"
|
||||||
tool/card_rotate_270 BITMAP "tool/card_rotate_270.bmp"
|
tool/card_rotate_270 IMAGE "tool/card_rotate_270.png"
|
||||||
|
|
||||||
tool/keyword_add BITMAP "tool/keyword_add.bmp"
|
tool/keyword_add IMAGE "tool/keyword_add.png"
|
||||||
tool/keyword_del BITMAP "tool/keyword_del.bmp"
|
tool/keyword_del IMAGE "tool/keyword_del.png"
|
||||||
|
|
||||||
tool/help BITMAP "tool/help.bmp"
|
tool/help IMAGE "tool/help.png"
|
||||||
|
|
||||||
// -------------------------------------------------------- : Symbol editor
|
// -------------------------------------------------------- : Symbol editor
|
||||||
|
|
||||||
@@ -60,23 +60,25 @@ cursor/rotate CURSOR "cursor/rotate.cur"
|
|||||||
cursor/shear_x CURSOR "cursor/shear_x.cur"
|
cursor/shear_x CURSOR "cursor/shear_x.cur"
|
||||||
cursor/shear_y CURSOR "cursor/shear_y.cur"
|
cursor/shear_y CURSOR "cursor/shear_y.cur"
|
||||||
|
|
||||||
tool/line BITMAP "tool/line.bmp"
|
tool/line IMAGE "tool/line.png"
|
||||||
tool/curve BITMAP "tool/curve.bmp"
|
tool/curve IMAGE "tool/curve.png"
|
||||||
tool/lock_free BITMAP "tool/lock_free.bmp"
|
tool/lock_free IMAGE "tool/lock_free.png"
|
||||||
tool/lock_dir BITMAP "tool/lock_dir.bmp"
|
tool/lock_dir IMAGE "tool/lock_dir.png"
|
||||||
tool/lock_size BITMAP "tool/lock_size.bmp"
|
tool/lock_size IMAGE "tool/lock_size.png"
|
||||||
|
|
||||||
tool/circle BITMAP "tool/circle.bmp"
|
tool/circle IMAGE "tool/circle.png"
|
||||||
tool/rectangle BITMAP "tool/rectangle.bmp"
|
tool/rectangle IMAGE "tool/rectangle.png"
|
||||||
tool/triangle BITMAP "tool/triangle.bmp"
|
tool/triangle IMAGE "tool/triangle.png"
|
||||||
tool/star BITMAP "tool/star.bmp"
|
tool/star IMAGE "tool/star.png"
|
||||||
|
|
||||||
tool/mode_select BITMAP "tool/mode_select.bmp"
|
tool/mode_select IMAGE "tool/mode_select.png"
|
||||||
tool/mode_rotate BITMAP "tool/mode_rotate.bmp"
|
tool/mode_rotate IMAGE "tool/mode_rotate.png"
|
||||||
tool/mode_curve BITMAP "tool/mode_curve.bmp"
|
tool/mode_curve IMAGE "tool/mode_curve.png"
|
||||||
tool/mode_paint BITMAP "tool/mode_paint.bmp"
|
tool/mode_paint IMAGE "tool/mode_paint.png"
|
||||||
tool/apply BITMAP "tool/apply.bmp"
|
tool/apply IMAGE "tool/apply.png"
|
||||||
tool/duplicate BITMAP "tool/duplicate.bmp"
|
tool/duplicate IMAGE "tool/duplicate.png"
|
||||||
|
tool/grid IMAGE "tool/grid.png"
|
||||||
|
tool/grid_snap IMAGE "tool/grid_snap.png"
|
||||||
|
|
||||||
combine_or IMAGE "tool/combine_or.png"
|
combine_or IMAGE "tool/combine_or.png"
|
||||||
combine_sub IMAGE "tool/combine_sub.png"
|
combine_sub IMAGE "tool/combine_sub.png"
|
||||||
@@ -93,19 +95,19 @@ handle_center IMAGE "../common/handle_center.png"
|
|||||||
|
|
||||||
// -------------------------------------------------------- : Other
|
// -------------------------------------------------------- : Other
|
||||||
|
|
||||||
sort_asc IMAGE "other/sort_asc.bmp"
|
sort_asc IMAGE "other/sort_asc.png"
|
||||||
sort_desc IMAGE "other/sort_desc.bmp"
|
sort_desc IMAGE "other/sort_desc.png"
|
||||||
plus IMAGE "other/plus.bmp"
|
plus IMAGE "other/plus.png"
|
||||||
minus IMAGE "other/minus.bmp"
|
minus IMAGE "other/minus.png"
|
||||||
selected IMAGE "other/selected_yes.png"
|
selected IMAGE "other/selected_yes.png"
|
||||||
deselected IMAGE "other/selected_no.png"
|
deselected IMAGE "other/selected_no.png"
|
||||||
|
|
||||||
bool_yes IMAGE "../common/bool_yes.png"
|
bool_yes IMAGE "../common/bool_yes.png"
|
||||||
bool_no IMAGE "../common/bool_no.png"
|
bool_no IMAGE "../common/bool_no.png"
|
||||||
|
|
||||||
//help_book BITMAP "help_book.bmp"
|
//help_book BITMAP "help_book.png"
|
||||||
//help_book_open BITMAP "help_book_open.bmp"
|
//help_book_open BITMAP "help_book_open.png"
|
||||||
//help_page BITMAP "help_page.bmp"
|
//help_page BITMAP "help_page.png"
|
||||||
|
|
||||||
about IMAGE "../common/about.png"
|
about IMAGE "../common/about.png"
|
||||||
two IMAGE "../common/two_beta.png"
|
two IMAGE "../common/two_beta.png"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 310 B |
|
After Width: | Height: | Size: 315 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 113 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 288 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 264 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 270 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 342 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 322 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 331 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 205 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 145 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 222 B |
|
Before Width: | Height: | Size: 334 B |
|
After Width: | Height: | Size: 178 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 132 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 253 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 247 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 330 B |
|
After Width: | Height: | Size: 228 B |
|
Before Width: | Height: | Size: 330 B |
|
After Width: | Height: | Size: 237 B |
|
Before Width: | Height: | Size: 330 B |
|
After Width: | Height: | Size: 230 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 176 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 131 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 193 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 94 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 131 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 99 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 822 B |
|
After Width: | Height: | Size: 318 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 123 B |
|
Before Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 176 B |