Add ability to assign styles to cosmetic text (in the form of
Constraint::COMMENTs), including line width and color, and text height and origin location. [git-p4: depot-paths = "//depot/solvespace/": change = 2033]
This commit is contained in:
parent
9416faca88
commit
4634961054
@ -654,10 +654,9 @@ void Constraint::MenuConstrain(int id) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GraphicsWindow::MNU_COMMENT:
|
case GraphicsWindow::MNU_COMMENT:
|
||||||
c.type = COMMENT;
|
SS.GW.pending.operation = GraphicsWindow::MNU_COMMENT;
|
||||||
c.comment.strcpy("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
|
SS.GW.pending.description = "click center of comment text";
|
||||||
c.disp.offset = SS.GW.offset.ScaledBy(-1);
|
SS.later.showTW = true;
|
||||||
AddConstraint(&c);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
|
72
draw.cpp
72
draw.cpp
@ -409,17 +409,18 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||||||
// selection.
|
// selection.
|
||||||
bool toggleForStyles = false,
|
bool toggleForStyles = false,
|
||||||
toggleForGroupInfo = false,
|
toggleForGroupInfo = false,
|
||||||
toggleForDelete = false;
|
toggleForDelete = false,
|
||||||
|
toggleForStyleInfo = false;
|
||||||
|
|
||||||
if(!hover.IsEmpty()) {
|
if(!hover.IsEmpty()) {
|
||||||
AddContextMenuItem("Toggle Hovered Item Selection",
|
AddContextMenuItem("Toggle Hovered Item Selection",
|
||||||
CMNU_TOGGLE_SELECTION);
|
CMNU_TOGGLE_SELECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gs.entities > 0) {
|
if(gs.stylables > 0) {
|
||||||
ContextMenuListStyles();
|
ContextMenuListStyles();
|
||||||
AddContextMenuItem("Assign Selection to Style", CONTEXT_SUBMENU);
|
AddContextMenuItem("Assign Selection to Style", CONTEXT_SUBMENU);
|
||||||
} else if(hover.entity.v && gs.n == 0 && gs.constraints == 0) {
|
} else if(gs.n == 0 && gs.constraints == 0 && hover.IsStylable()) {
|
||||||
ContextMenuListStyles();
|
ContextMenuListStyles();
|
||||||
AddContextMenuItem("Assign Hovered Item to Style", CONTEXT_SUBMENU);
|
AddContextMenuItem("Assign Hovered Item to Style", CONTEXT_SUBMENU);
|
||||||
toggleForStyles = true;
|
toggleForStyles = true;
|
||||||
@ -432,9 +433,16 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||||||
toggleForGroupInfo = true;
|
toggleForGroupInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(gs.n + gs.constraints == 1 && gs.stylables == 1) {
|
||||||
|
AddContextMenuItem("Style Info for Selected Item", CMNU_STYLE_INFO);
|
||||||
|
} else if(hover.IsStylable() && gs.n == 0 && gs.constraints == 0) {
|
||||||
|
AddContextMenuItem("Style Info for Hovered Item", CMNU_STYLE_INFO);
|
||||||
|
toggleForStyleInfo = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(hover.constraint.v && gs.n == 0 && gs.constraints == 0) {
|
if(hover.constraint.v && gs.n == 0 && gs.constraints == 0) {
|
||||||
Constraint *c = SK.GetConstraint(hover.constraint);
|
Constraint *c = SK.GetConstraint(hover.constraint);
|
||||||
if(c->HasLabel()) {
|
if(c->HasLabel() && c->type != Constraint::COMMENT) {
|
||||||
AddContextMenuItem("Toggle Reference Dimension",
|
AddContextMenuItem("Toggle Reference Dimension",
|
||||||
CMNU_REFERENCE_DIM);
|
CMNU_REFERENCE_DIM);
|
||||||
}
|
}
|
||||||
@ -483,8 +491,9 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||||||
|
|
||||||
case CMNU_GROUP_INFO: {
|
case CMNU_GROUP_INFO: {
|
||||||
if(toggleForGroupInfo) ToggleSelectionStateOfHovered();
|
if(toggleForGroupInfo) ToggleSelectionStateOfHovered();
|
||||||
GroupSelection();
|
|
||||||
hGroup hg;
|
hGroup hg;
|
||||||
|
GroupSelection();
|
||||||
if(gs.entities == 1) {
|
if(gs.entities == 1) {
|
||||||
hg = SK.GetEntity(gs.entity[0])->group;
|
hg = SK.GetEntity(gs.entity[0])->group;
|
||||||
} else if(gs.points == 1) {
|
} else if(gs.points == 1) {
|
||||||
@ -495,12 +504,36 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
|
|
||||||
SS.TW.GoToScreen(TextWindow::SCREEN_GROUP_INFO);
|
SS.TW.GoToScreen(TextWindow::SCREEN_GROUP_INFO);
|
||||||
SS.TW.shown.group = hg;
|
SS.TW.shown.group = hg;
|
||||||
SS.later.showTW = true;
|
SS.later.showTW = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CMNU_STYLE_INFO: {
|
||||||
|
if(toggleForStyleInfo) ToggleSelectionStateOfHovered();
|
||||||
|
|
||||||
|
hStyle hs;
|
||||||
|
GroupSelection();
|
||||||
|
if(gs.entities == 1) {
|
||||||
|
hs = Style::ForEntity(gs.entity[0]);
|
||||||
|
} else if(gs.points == 1) {
|
||||||
|
hs = Style::ForEntity(gs.point[0]);
|
||||||
|
} else if(gs.constraints == 1) {
|
||||||
|
hs = SK.GetConstraint(gs.constraint[0])->disp.style;
|
||||||
|
if(!hs.v) hs.v = Style::CONSTRAINT;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ClearSelection();
|
||||||
|
|
||||||
|
SS.TW.GoToScreen(TextWindow::SCREEN_STYLE_INFO);
|
||||||
|
SS.TW.shown.style = hs;
|
||||||
|
SS.later.showTW = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case CMNU_NEW_CUSTOM_STYLE: {
|
case CMNU_NEW_CUSTOM_STYLE: {
|
||||||
if(toggleForStyles) ToggleSelectionStateOfHovered();
|
if(toggleForStyles) ToggleSelectionStateOfHovered();
|
||||||
DWORD v = Style::CreateCustomStyle();
|
DWORD v = Style::CreateCustomStyle();
|
||||||
@ -602,8 +635,6 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||||||
ConstrainPointByHovered(hr.entity(0));
|
ConstrainPointByHovered(hr.entity(0));
|
||||||
|
|
||||||
ClearSuper();
|
ClearSuper();
|
||||||
|
|
||||||
pending.operation = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MNU_LINE_SEGMENT:
|
case MNU_LINE_SEGMENT:
|
||||||
@ -738,6 +769,19 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MNU_COMMENT: {
|
||||||
|
ClearSuper();
|
||||||
|
Constraint c;
|
||||||
|
ZERO(&c);
|
||||||
|
c.group = SS.GW.activeGroup;
|
||||||
|
c.workplane = SS.GW.ActiveWorkplane();
|
||||||
|
c.type = Constraint::COMMENT;
|
||||||
|
c.disp.offset = v;
|
||||||
|
c.comment.strcpy("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
|
||||||
|
Constraint::AddConstraint(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DRAGGING_RADIUS:
|
case DRAGGING_RADIUS:
|
||||||
case DRAGGING_NEW_POINT:
|
case DRAGGING_NEW_POINT:
|
||||||
// The MouseMoved event has already dragged it as desired.
|
// The MouseMoved event has already dragged it as desired.
|
||||||
@ -925,6 +969,15 @@ bool GraphicsWindow::Selection::IsEmpty(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsWindow::Selection::IsStylable(void) {
|
||||||
|
if(entity.v) return true;
|
||||||
|
if(constraint.v) {
|
||||||
|
Constraint *c = SK.GetConstraint(constraint);
|
||||||
|
if(c->type == Constraint::COMMENT) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsWindow::Selection::Clear(void) {
|
void GraphicsWindow::Selection::Clear(void) {
|
||||||
entity.v = constraint.v = 0;
|
entity.v = constraint.v = 0;
|
||||||
emphasized = false;
|
emphasized = false;
|
||||||
@ -1045,6 +1098,7 @@ void GraphicsWindow::GroupSelection(void) {
|
|||||||
gs.point[(gs.points)++] = s->entity;
|
gs.point[(gs.points)++] = s->entity;
|
||||||
} else {
|
} else {
|
||||||
gs.entity[(gs.entities)++] = s->entity;
|
gs.entity[(gs.entities)++] = s->entity;
|
||||||
|
(gs.stylables)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// And an auxiliary list of normals, including normals from
|
// And an auxiliary list of normals, including normals from
|
||||||
@ -1081,6 +1135,10 @@ void GraphicsWindow::GroupSelection(void) {
|
|||||||
}
|
}
|
||||||
if(s->constraint.v) {
|
if(s->constraint.v) {
|
||||||
gs.constraint[(gs.constraints)++] = s->constraint;
|
gs.constraint[(gs.constraints)++] = s->constraint;
|
||||||
|
Constraint *c = SK.GetConstraint(s->constraint);
|
||||||
|
if(c->type == Constraint::COMMENT) {
|
||||||
|
(gs.stylables)++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,27 @@ bool Constraint::HasLabel(void) {
|
|||||||
|
|
||||||
void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
|
void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
|
// Draw comments in the specified style, but everything else in the
|
||||||
|
// default style for constraints.
|
||||||
|
hStyle hs;
|
||||||
|
if(type == COMMENT && disp.style.v) {
|
||||||
|
hs = disp.style;
|
||||||
|
} else {
|
||||||
|
hs.v = Style::CONSTRAINT;
|
||||||
|
}
|
||||||
|
|
||||||
if(dogd.sel) {
|
if(dogd.sel) {
|
||||||
dogd.sel->AddEdge(a, b, Style::CONSTRAINT);
|
dogd.sel->AddEdge(a, b, hs.v);
|
||||||
|
} else {
|
||||||
|
if(hs.v && Style::Width(disp.style) >= 3.0) {
|
||||||
|
glxFatLine(a, b, Style::Width(disp.style) / SS.GW.scale);
|
||||||
} else {
|
} else {
|
||||||
glBegin(GL_LINE_STRIP);
|
glBegin(GL_LINE_STRIP);
|
||||||
glxVertex3v(a);
|
glxVertex3v(a);
|
||||||
glxVertex3v(b);
|
glxVertex3v(b);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Point2d ap = SS.GW.ProjectPoint(a);
|
Point2d ap = SS.GW.ProjectPoint(a);
|
||||||
Point2d bp = SS.GW.ProjectPoint(b);
|
Point2d bp = SS.GW.ProjectPoint(b);
|
||||||
@ -70,8 +83,28 @@ char *Constraint::Label(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
||||||
|
double th;
|
||||||
|
if(type == COMMENT) {
|
||||||
|
th = Style::TextHeight(disp.style);
|
||||||
|
} else {
|
||||||
|
th = DEFAULT_TEXT_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
char *s = Label();
|
char *s = Label();
|
||||||
double swidth = glxStrWidth(s), sheight = glxStrHeight();
|
double swidth = glxStrWidth(s, th),
|
||||||
|
sheight = glxStrHeight(th);
|
||||||
|
|
||||||
|
// By default, the reference is from the center; but the style could
|
||||||
|
// specify otherwise if one is present.
|
||||||
|
if(type == COMMENT && disp.style.v) {
|
||||||
|
Style *s = Style::Get(disp.style);
|
||||||
|
int o = s->textOrigin;
|
||||||
|
if(o & Style::ORIGIN_LEFT) ref = ref.Plus(gr.WithMagnitude(swidth/2));
|
||||||
|
if(o & Style::ORIGIN_RIGHT) ref = ref.Minus(gr.WithMagnitude(swidth/2));
|
||||||
|
if(o & Style::ORIGIN_BOT) ref = ref.Plus(gu.WithMagnitude(sheight/2));
|
||||||
|
if(o & Style::ORIGIN_TOP) ref = ref.Minus(gu.WithMagnitude(sheight/2));
|
||||||
|
}
|
||||||
|
|
||||||
if(labelPos) {
|
if(labelPos) {
|
||||||
// labelPos is from the top left corner (for the text box used to
|
// labelPos is from the top left corner (for the text box used to
|
||||||
// edit things), but ref is from the center.
|
// edit things), but ref is from the center.
|
||||||
@ -79,8 +112,9 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
|||||||
gu.WithMagnitude(sheight/2));
|
gu.WithMagnitude(sheight/2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
glxWriteTextRefCenter(s, ref, gr, gu, LineCallback, this);
|
glxWriteTextRefCenter(s, th, ref, gr, gu, LineCallback, this);
|
||||||
} else {
|
} else {
|
||||||
double l = swidth/2 - sheight/2;
|
double l = swidth/2 - sheight/2;
|
||||||
l = max(l, 5/SS.GW.scale);
|
l = max(l, 5/SS.GW.scale);
|
||||||
@ -88,7 +122,7 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
|||||||
Point2d b = SS.GW.ProjectPoint(ref.Plus (gr.WithMagnitude(l)));
|
Point2d b = SS.GW.ProjectPoint(ref.Plus (gr.WithMagnitude(l)));
|
||||||
double d = dogd.mp.DistanceToLine(a, b.Minus(a), true);
|
double d = dogd.mp.DistanceToLine(a, b.Minus(a), true);
|
||||||
|
|
||||||
dogd.dmin = min(dogd.dmin, d - 3);
|
dogd.dmin = min(dogd.dmin, d - (th / 2));
|
||||||
dogd.refp = ref;
|
dogd.refp = ref;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,8 +150,8 @@ int Constraint::DoLineTrimmedAgainstBox(Vector ref, Vector a, Vector b) {
|
|||||||
|
|
||||||
double pixels = 1.0 / SS.GW.scale;
|
double pixels = 1.0 / SS.GW.scale;
|
||||||
char *s = Label();
|
char *s = Label();
|
||||||
double swidth = glxStrWidth(s) + 4*pixels,
|
double swidth = glxStrWidth(s, DEFAULT_TEXT_HEIGHT) + 4*pixels,
|
||||||
sheight = glxStrHeight() + 8*pixels;
|
sheight = glxStrHeight(DEFAULT_TEXT_HEIGHT) + 8*pixels;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
Vector n;
|
Vector n;
|
||||||
@ -322,15 +356,18 @@ void Constraint::DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db,
|
|||||||
// complex and this looks pretty good.
|
// complex and this looks pretty good.
|
||||||
double tl = atan2(rm.Dot(gu), rm.Dot(gr));
|
double tl = atan2(rm.Dot(gu), rm.Dot(gr));
|
||||||
double adj = EllipticalInterpolation(
|
double adj = EllipticalInterpolation(
|
||||||
glxStrWidth(Label())/2, glxStrHeight()/2, tl);
|
glxStrWidth(Label(), DEFAULT_TEXT_HEIGHT)/2,
|
||||||
|
glxStrHeight(DEFAULT_TEXT_HEIGHT)/2,
|
||||||
|
tl);
|
||||||
*ref = (*ref).Plus(rm.WithMagnitude(adj + 3/SS.GW.scale));
|
*ref = (*ref).Plus(rm.WithMagnitude(adj + 3/SS.GW.scale));
|
||||||
} else {
|
} else {
|
||||||
// The lines are skew; no wonderful way to illustrate that.
|
// The lines are skew; no wonderful way to illustrate that.
|
||||||
*ref = a0.Plus(b0);
|
*ref = a0.Plus(b0);
|
||||||
*ref = (*ref).ScaledBy(0.5).Plus(disp.offset);
|
*ref = (*ref).ScaledBy(0.5).Plus(disp.offset);
|
||||||
gu = gu.WithMagnitude(1);
|
gu = gu.WithMagnitude(1);
|
||||||
Vector trans = (*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight()));
|
Vector trans =
|
||||||
glxWriteTextRefCenter("angle between skew lines",
|
(*ref).Plus(gu.ScaledBy(-1.5*glxStrHeight(DEFAULT_TEXT_HEIGHT)));
|
||||||
|
glxWriteTextRefCenter("angle between skew lines", DEFAULT_TEXT_HEIGHT,
|
||||||
trans, gr, gu, LineCallback, this);
|
trans, gr, gu, LineCallback, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -653,7 +690,8 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
glxWriteTextRefCenter("T", textAt, u, v, LineCallback, this);
|
glxWriteTextRefCenter("T", DEFAULT_TEXT_HEIGHT,
|
||||||
|
textAt, u, v, LineCallback, this);
|
||||||
} else {
|
} else {
|
||||||
dogd.refp = textAt;
|
dogd.refp = textAt;
|
||||||
Point2d ref = SS.GW.ProjectPoint(dogd.refp);
|
Point2d ref = SS.GW.ProjectPoint(dogd.refp);
|
||||||
@ -835,8 +873,8 @@ s:
|
|||||||
(type == VERTICAL) ? "V" : (
|
(type == VERTICAL) ? "V" : (
|
||||||
(type == AT_MIDPOINT) ? "M" : NULL));
|
(type == AT_MIDPOINT) ? "M" : NULL));
|
||||||
|
|
||||||
glxWriteTextRefCenter(s, m.Plus(offset), r, u,
|
glxWriteTextRefCenter(s, DEFAULT_TEXT_HEIGHT,
|
||||||
LineCallback, this);
|
m.Plus(offset), r, u, LineCallback, this);
|
||||||
} else {
|
} else {
|
||||||
dogd.refp = m.Plus(offset);
|
dogd.refp = m.Plus(offset);
|
||||||
Point2d ref = SS.GW.ProjectPoint(dogd.refp);
|
Point2d ref = SS.GW.ProjectPoint(dogd.refp);
|
||||||
@ -880,6 +918,10 @@ s:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMENT:
|
case COMMENT:
|
||||||
|
if(disp.style.v) {
|
||||||
|
glLineWidth(Style::Width(disp.style));
|
||||||
|
glxColorRGB(Style::Color(disp.style));
|
||||||
|
}
|
||||||
DoLabel(disp.offset, labelPos, gr, gu);
|
DoLabel(disp.offset, labelPos, gr, gu);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -10,55 +10,6 @@ char *Entity::DescriptionString(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::FatLineEndcap(Vector p, Vector u, Vector v) {
|
|
||||||
// A table of cos and sin of (pi*i/10 + pi/2), as i goes from 0 to 10
|
|
||||||
static const double Circle[11][2] = {
|
|
||||||
{ 0.0000, 1.0000 },
|
|
||||||
{ -0.3090, 0.9511 },
|
|
||||||
{ -0.5878, 0.8090 },
|
|
||||||
{ -0.8090, 0.5878 },
|
|
||||||
{ -0.9511, 0.3090 },
|
|
||||||
{ -1.0000, 0.0000 },
|
|
||||||
{ -0.9511, -0.3090 },
|
|
||||||
{ -0.8090, -0.5878 },
|
|
||||||
{ -0.5878, -0.8090 },
|
|
||||||
{ -0.3090, -0.9511 },
|
|
||||||
{ 0.0000, -1.0000 },
|
|
||||||
};
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
|
||||||
for(int i = 0; i <= 10; i++) {
|
|
||||||
double c = Circle[i][0], s = Circle[i][1];
|
|
||||||
glxVertex3v(p.Plus(u.ScaledBy(c)).Plus(v.ScaledBy(s)));
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Entity::FatLine(Vector a, Vector b) {
|
|
||||||
// The half-width of the line we're drawing.
|
|
||||||
double hw = (dogd.lineWidth/SS.GW.scale) / 2;
|
|
||||||
Vector ab = b.Minus(a);
|
|
||||||
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
|
|
||||||
Vector abn = (ab.Cross(gn)).WithMagnitude(1);
|
|
||||||
abn = abn.Minus(gn.ScaledBy(gn.Dot(abn)));
|
|
||||||
// So now abn is normal to the projection of ab into the screen, so the
|
|
||||||
// line will always have constant thickness as the view is rotated.
|
|
||||||
|
|
||||||
abn = abn.WithMagnitude(hw);
|
|
||||||
ab = gn.Cross(abn);
|
|
||||||
ab = ab. WithMagnitude(hw);
|
|
||||||
|
|
||||||
// The body of a line is a quad
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glxVertex3v(a.Minus(abn));
|
|
||||||
glxVertex3v(b.Minus(abn));
|
|
||||||
glxVertex3v(b.Plus (abn));
|
|
||||||
glxVertex3v(a.Plus (abn));
|
|
||||||
glEnd();
|
|
||||||
// And the line has two semi-circular end caps.
|
|
||||||
FatLineEndcap(a, ab, abn);
|
|
||||||
FatLineEndcap(b, ab.ScaledBy(-1), abn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) {
|
void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) {
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
// Draw lines from active group in front of those from previous
|
// Draw lines from active group in front of those from previous
|
||||||
@ -71,7 +22,7 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) {
|
|||||||
glxVertex3v(b);
|
glxVertex3v(b);
|
||||||
glEnd();
|
glEnd();
|
||||||
} else {
|
} else {
|
||||||
FatLine(a, b);
|
glxFatLine(a, b, dogd.lineWidth/SS.GW.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
glxDepthRangeOffset(0);
|
glxDepthRangeOffset(0);
|
||||||
@ -506,11 +457,12 @@ void Entity::DrawOrGetDistance(void) {
|
|||||||
glDisable(GL_LINE_STIPPLE);
|
glDisable(GL_LINE_STIPPLE);
|
||||||
|
|
||||||
char *str = DescriptionString()+5;
|
char *str = DescriptionString()+5;
|
||||||
|
double th = DEFAULT_TEXT_HEIGHT;
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
glxWriteText(str, mm2, u, v, NULL, NULL);
|
glxWriteText(str, th, mm2, u, v, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str)/2)).Plus(
|
Vector pos = mm2.Plus(u.ScaledBy(glxStrWidth(str, th)/2)).Plus(
|
||||||
v.ScaledBy(glxStrHeight()/2));
|
v.ScaledBy(glxStrHeight(th)/2));
|
||||||
Point2d pp = SS.GW.ProjectPoint(pos);
|
Point2d pp = SS.GW.ProjectPoint(pos);
|
||||||
dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10);
|
dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10);
|
||||||
// If a line lies in a plane, then select the line, not
|
// If a line lies in a plane, then select the line, not
|
||||||
|
7
file.cpp
7
file.cpp
@ -154,7 +154,10 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||||||
{ 's', "Style.h.v", 'x', &(SS.sv.s.h.v) },
|
{ 's', "Style.h.v", 'x', &(SS.sv.s.h.v) },
|
||||||
{ 's', "Style.name", 'N', &(SS.sv.s.name) },
|
{ 's', "Style.name", 'N', &(SS.sv.s.name) },
|
||||||
{ 's', "Style.width", 'f', &(SS.sv.s.width) },
|
{ 's', "Style.width", 'f', &(SS.sv.s.width) },
|
||||||
{ 's', "Style.widthHow", 'd', &(SS.sv.s.widthHow) },
|
{ 's', "Style.widthAs", 'd', &(SS.sv.s.widthAs) },
|
||||||
|
{ 's', "Style.textHeight", 'f', &(SS.sv.s.textHeight) },
|
||||||
|
{ 's', "Style.textHeightAs", 'd', &(SS.sv.s.textHeightAs) },
|
||||||
|
{ 's', "Style.textOrigin", 'x', &(SS.sv.s.textOrigin) },
|
||||||
{ 's', "Style.color", 'x', &(SS.sv.s.color) },
|
{ 's', "Style.color", 'x', &(SS.sv.s.color) },
|
||||||
{ 's', "Style.visible", 'b', &(SS.sv.s.visible) },
|
{ 's', "Style.visible", 'b', &(SS.sv.s.visible) },
|
||||||
{ 's', "Style.exportable", 'b', &(SS.sv.s.exportable) },
|
{ 's', "Style.exportable", 'b', &(SS.sv.s.exportable) },
|
||||||
@ -484,6 +487,8 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le,
|
|||||||
|
|
||||||
} else if(strcmp(line, "AddConstraint")==0) {
|
} else if(strcmp(line, "AddConstraint")==0) {
|
||||||
|
|
||||||
|
} else if(strcmp(line, "AddStyle")==0) {
|
||||||
|
|
||||||
} else if(strcmp(line, VERSION_STRING)==0) {
|
} else if(strcmp(line, VERSION_STRING)==0) {
|
||||||
|
|
||||||
} else if(StrStartsWith(line, "Triangle ")) {
|
} else if(StrStartsWith(line, "Triangle ")) {
|
||||||
|
77
glhelper.cpp
77
glhelper.cpp
@ -6,8 +6,8 @@
|
|||||||
static bool ColorLocked;
|
static bool ColorLocked;
|
||||||
static bool DepthOffsetLocked;
|
static bool DepthOffsetLocked;
|
||||||
|
|
||||||
#define FONT_SCALE (0.55)
|
#define FONT_SCALE(h) ((h)/22.0)
|
||||||
double glxStrWidth(char *str) {
|
double glxStrWidth(char *str, double h) {
|
||||||
int w = 0;
|
int w = 0;
|
||||||
for(; *str; str++) {
|
for(; *str; str++) {
|
||||||
int c = *str;
|
int c = *str;
|
||||||
@ -16,21 +16,21 @@ double glxStrWidth(char *str) {
|
|||||||
|
|
||||||
w += Font[c].width;
|
w += Font[c].width;
|
||||||
}
|
}
|
||||||
return w*FONT_SCALE/SS.GW.scale;
|
return w*FONT_SCALE(h)/SS.GW.scale;
|
||||||
}
|
}
|
||||||
double glxStrHeight(void) {
|
double glxStrHeight(double h) {
|
||||||
// The characters have height ~21, as they appear in the table.
|
// The characters have height ~22, as they appear in the table.
|
||||||
return 21.0*FONT_SCALE/SS.GW.scale;
|
return 22.0*FONT_SCALE(h)/SS.GW.scale;
|
||||||
}
|
}
|
||||||
void glxWriteTextRefCenter(char *str, Vector t, Vector u, Vector v,
|
void glxWriteTextRefCenter(char *str, double h, Vector t, Vector u, Vector v,
|
||||||
glxLineFn *fn, void *fndata)
|
glxLineFn *fn, void *fndata)
|
||||||
{
|
{
|
||||||
u = u.WithMagnitude(1);
|
u = u.WithMagnitude(1);
|
||||||
v = v.WithMagnitude(1);
|
v = v.WithMagnitude(1);
|
||||||
|
|
||||||
double scale = FONT_SCALE/SS.GW.scale;
|
double scale = FONT_SCALE(h)/SS.GW.scale;
|
||||||
double fh = glxStrHeight();
|
double fh = glxStrHeight(h);
|
||||||
double fw = glxStrWidth(str);
|
double fw = glxStrWidth(str, h);
|
||||||
|
|
||||||
t = t.Plus(u.ScaledBy(-fw/2));
|
t = t.Plus(u.ScaledBy(-fw/2));
|
||||||
t = t.Plus(v.ScaledBy(-fh/2));
|
t = t.Plus(v.ScaledBy(-fh/2));
|
||||||
@ -39,7 +39,7 @@ void glxWriteTextRefCenter(char *str, Vector t, Vector u, Vector v,
|
|||||||
t = t.Plus(u.ScaledBy(-5*scale));
|
t = t.Plus(u.ScaledBy(-5*scale));
|
||||||
t = t.Plus(v.ScaledBy(-5*scale));
|
t = t.Plus(v.ScaledBy(-5*scale));
|
||||||
|
|
||||||
glxWriteText(str, t, u, v, fn, fndata);
|
glxWriteText(str, h, t, u, v, fn, fndata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LineDrawCallback(void *fndata, Vector a, Vector b)
|
static void LineDrawCallback(void *fndata, Vector a, Vector b)
|
||||||
@ -51,14 +51,14 @@ static void LineDrawCallback(void *fndata, Vector a, Vector b)
|
|||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void glxWriteText(char *str, Vector t, Vector u, Vector v,
|
void glxWriteText(char *str, double h, Vector t, Vector u, Vector v,
|
||||||
glxLineFn *fn, void *fndata)
|
glxLineFn *fn, void *fndata)
|
||||||
{
|
{
|
||||||
if(!fn) fn = LineDrawCallback;
|
if(!fn) fn = LineDrawCallback;
|
||||||
u = u.WithMagnitude(1);
|
u = u.WithMagnitude(1);
|
||||||
v = v.WithMagnitude(1);
|
v = v.WithMagnitude(1);
|
||||||
|
|
||||||
double scale = FONT_SCALE/SS.GW.scale;
|
double scale = FONT_SCALE(h)/SS.GW.scale;
|
||||||
int xo = 5;
|
int xo = 5;
|
||||||
int yo = 5;
|
int yo = 5;
|
||||||
|
|
||||||
@ -96,6 +96,57 @@ void glxVertex3v(Vector u)
|
|||||||
glVertex3f((GLfloat)u.x, (GLfloat)u.y, (GLfloat)u.z);
|
glVertex3f((GLfloat)u.x, (GLfloat)u.y, (GLfloat)u.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FatLineEndcap(Vector p, Vector u, Vector v)
|
||||||
|
{
|
||||||
|
// A table of cos and sin of (pi*i/10 + pi/2), as i goes from 0 to 10
|
||||||
|
static const double Circle[11][2] = {
|
||||||
|
{ 0.0000, 1.0000 },
|
||||||
|
{ -0.3090, 0.9511 },
|
||||||
|
{ -0.5878, 0.8090 },
|
||||||
|
{ -0.8090, 0.5878 },
|
||||||
|
{ -0.9511, 0.3090 },
|
||||||
|
{ -1.0000, 0.0000 },
|
||||||
|
{ -0.9511, -0.3090 },
|
||||||
|
{ -0.8090, -0.5878 },
|
||||||
|
{ -0.5878, -0.8090 },
|
||||||
|
{ -0.3090, -0.9511 },
|
||||||
|
{ 0.0000, -1.0000 },
|
||||||
|
};
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
for(int i = 0; i <= 10; i++) {
|
||||||
|
double c = Circle[i][0], s = Circle[i][1];
|
||||||
|
glxVertex3v(p.Plus(u.ScaledBy(c)).Plus(v.ScaledBy(s)));
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void glxFatLine(Vector a, Vector b, double width) {
|
||||||
|
// The half-width of the line we're drawing.
|
||||||
|
double hw = width / 2;
|
||||||
|
Vector ab = b.Minus(a);
|
||||||
|
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
|
||||||
|
Vector abn = (ab.Cross(gn)).WithMagnitude(1);
|
||||||
|
abn = abn.Minus(gn.ScaledBy(gn.Dot(abn)));
|
||||||
|
// So now abn is normal to the projection of ab into the screen, so the
|
||||||
|
// line will always have constant thickness as the view is rotated.
|
||||||
|
|
||||||
|
abn = abn.WithMagnitude(hw);
|
||||||
|
ab = gn.Cross(abn);
|
||||||
|
ab = ab. WithMagnitude(hw);
|
||||||
|
|
||||||
|
// The body of a line is a quad
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glxVertex3v(a.Minus(abn));
|
||||||
|
glxVertex3v(b.Minus(abn));
|
||||||
|
glxVertex3v(b.Plus (abn));
|
||||||
|
glxVertex3v(a.Plus (abn));
|
||||||
|
glEnd();
|
||||||
|
// And the line has two semi-circular end caps.
|
||||||
|
FatLineEndcap(a, ab, abn);
|
||||||
|
FatLineEndcap(b, ab.ScaledBy(-1), abn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void glxLockColorTo(DWORD rgb)
|
void glxLockColorTo(DWORD rgb)
|
||||||
{
|
{
|
||||||
ColorLocked = false;
|
ColorLocked = false;
|
||||||
|
@ -591,7 +591,9 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||||||
// to cancel, then perhaps they want to return to the home
|
// to cancel, then perhaps they want to return to the home
|
||||||
// screen in the text window.
|
// screen in the text window.
|
||||||
if(SS.GW.gs.n == 0 && SS.GW.pending.operation == 0) {
|
if(SS.GW.gs.n == 0 && SS.GW.pending.operation == 0) {
|
||||||
if(!TextEditControlIsVisible()) {
|
if(!(TextEditControlIsVisible() ||
|
||||||
|
GraphicsEditControlIsVisible()))
|
||||||
|
{
|
||||||
if(SS.TW.shown.screen == TextWindow::SCREEN_STYLE_INFO) {
|
if(SS.TW.shown.screen == TextWindow::SCREEN_STYLE_INFO) {
|
||||||
SS.TW.GoToScreen(TextWindow::SCREEN_LIST_OF_STYLES);
|
SS.TW.GoToScreen(TextWindow::SCREEN_LIST_OF_STYLES);
|
||||||
} else {
|
} else {
|
||||||
|
@ -424,7 +424,7 @@ void Group::Draw(void) {
|
|||||||
glxVertex3v(polyError.notClosedAt.b);
|
glxVertex3v(polyError.notClosedAt.b);
|
||||||
glEnd();
|
glEnd();
|
||||||
glxColorRGB(Style::Color(Style::DRAW_ERROR));
|
glxColorRGB(Style::Color(Style::DRAW_ERROR));
|
||||||
glxWriteText("not closed contour!",
|
glxWriteText("not closed contour!", DEFAULT_TEXT_HEIGHT,
|
||||||
polyError.notClosedAt.b, SS.GW.projRight, SS.GW.projUp,
|
polyError.notClosedAt.b, SS.GW.projRight, SS.GW.projUp,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
@ -439,7 +439,7 @@ void Group::Draw(void) {
|
|||||||
char *msg = (polyError.how == POLY_NOT_COPLANAR) ?
|
char *msg = (polyError.how == POLY_NOT_COPLANAR) ?
|
||||||
"points not all coplanar!" :
|
"points not all coplanar!" :
|
||||||
"contour is self-intersecting!";
|
"contour is self-intersecting!";
|
||||||
glxWriteText(msg,
|
glxWriteText(msg, DEFAULT_TEXT_HEIGHT,
|
||||||
polyError.errorPointAt, SS.GW.projRight, SS.GW.projUp,
|
polyError.errorPointAt, SS.GW.projRight, SS.GW.projUp,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
16
sketch.h
16
sketch.h
@ -415,8 +415,6 @@ public:
|
|||||||
Vector refp;
|
Vector refp;
|
||||||
double lineWidth;
|
double lineWidth;
|
||||||
} dogd; // state for drawing or getting distance (for hit testing)
|
} dogd; // state for drawing or getting distance (for hit testing)
|
||||||
void FatLine(Vector a, Vector b);
|
|
||||||
void FatLineEndcap(Vector p, Vector u, Vector v);
|
|
||||||
void LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat=false);
|
void LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat=false);
|
||||||
void DrawOrGetDistance(void);
|
void DrawOrGetDistance(void);
|
||||||
|
|
||||||
@ -626,10 +624,17 @@ public:
|
|||||||
|
|
||||||
NameStr name;
|
NameStr name;
|
||||||
|
|
||||||
static const int WIDTH_AS_MM = 0;
|
static const int UNITS_AS_PIXELS = 0;
|
||||||
static const int WIDTH_AS_PIXELS = 1;
|
static const int UNITS_AS_MM = 1;
|
||||||
double width;
|
double width;
|
||||||
int widthHow;
|
int widthAs;
|
||||||
|
double textHeight;
|
||||||
|
int textHeightAs;
|
||||||
|
static const int ORIGIN_LEFT = 0x01;
|
||||||
|
static const int ORIGIN_RIGHT = 0x02;
|
||||||
|
static const int ORIGIN_BOT = 0x04;
|
||||||
|
static const int ORIGIN_TOP = 0x08;
|
||||||
|
int textOrigin;
|
||||||
DWORD color;
|
DWORD color;
|
||||||
bool visible;
|
bool visible;
|
||||||
bool exportable;
|
bool exportable;
|
||||||
@ -662,6 +667,7 @@ public:
|
|||||||
static DWORD Color(int hs, bool forExport=false);
|
static DWORD Color(int hs, bool forExport=false);
|
||||||
static float Width(int hs);
|
static float Width(int hs);
|
||||||
static double WidthMm(int hs);
|
static double WidthMm(int hs);
|
||||||
|
static double TextHeight(hStyle hs);
|
||||||
static bool Exportable(int hs);
|
static bool Exportable(int hs);
|
||||||
static hStyle ForEntity(hEntity he);
|
static hStyle ForEntity(hEntity he);
|
||||||
|
|
||||||
|
10
solvespace.h
10
solvespace.h
@ -181,6 +181,7 @@ typedef IdList<Param,hParam> ParamList;
|
|||||||
|
|
||||||
// Utility functions that are provided in the platform-independent code.
|
// Utility functions that are provided in the platform-independent code.
|
||||||
void glxVertex3v(Vector u);
|
void glxVertex3v(Vector u);
|
||||||
|
#define DEFAULT_TEXT_HEIGHT (11.5)
|
||||||
#define GLX_CALLBACK __stdcall
|
#define GLX_CALLBACK __stdcall
|
||||||
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
||||||
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
||||||
@ -191,13 +192,14 @@ void glxDrawEdges(SEdgeList *l, bool endpointsToo);
|
|||||||
void glxDebugMesh(SMesh *m);
|
void glxDebugMesh(SMesh *m);
|
||||||
void glxMarkPolygonNormal(SPolygon *p);
|
void glxMarkPolygonNormal(SPolygon *p);
|
||||||
typedef void glxLineFn(void *data, Vector a, Vector b);
|
typedef void glxLineFn(void *data, Vector a, Vector b);
|
||||||
void glxWriteText(char *str, Vector t, Vector u, Vector v,
|
void glxWriteText(char *str, double h, Vector t, Vector u, Vector v,
|
||||||
glxLineFn *fn, void *fndata);
|
glxLineFn *fn, void *fndata);
|
||||||
void glxWriteTextRefCenter(char *str, Vector t, Vector u, Vector v,
|
void glxWriteTextRefCenter(char *str, double h, Vector t, Vector u, Vector v,
|
||||||
glxLineFn *fn, void *fndata);
|
glxLineFn *fn, void *fndata);
|
||||||
double glxStrWidth(char *str);
|
double glxStrWidth(char *str, double h);
|
||||||
double glxStrHeight(void);
|
double glxStrHeight(double h);
|
||||||
void glxLockColorTo(DWORD rgb);
|
void glxLockColorTo(DWORD rgb);
|
||||||
|
void glxFatLine(Vector a, Vector b, double width);
|
||||||
void glxUnlockColor(void);
|
void glxUnlockColor(void);
|
||||||
void glxColorRGB(DWORD rgb);
|
void glxColorRGB(DWORD rgb);
|
||||||
void glxColorRGBa(DWORD rgb, double a);
|
void glxColorRGBa(DWORD rgb, double a);
|
||||||
|
242
style.cpp
242
style.cpp
@ -70,7 +70,9 @@ void Style::CreateDefaultStyle(hStyle h) {
|
|||||||
ZERO(&ns);
|
ZERO(&ns);
|
||||||
ns.color = CnfThawDWORD(d->color, CnfColor(d->cnfPrefix));
|
ns.color = CnfThawDWORD(d->color, CnfColor(d->cnfPrefix));
|
||||||
ns.width = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
ns.width = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
||||||
ns.widthHow = WIDTH_AS_PIXELS;
|
ns.widthAs = UNITS_AS_PIXELS;
|
||||||
|
ns.textHeight = DEFAULT_TEXT_HEIGHT;
|
||||||
|
ns.textHeightAs = UNITS_AS_PIXELS;
|
||||||
ns.visible = true;
|
ns.visible = true;
|
||||||
ns.exportable = true;
|
ns.exportable = true;
|
||||||
ns.h = h;
|
ns.h = h;
|
||||||
@ -90,7 +92,9 @@ void Style::LoadFactoryDefaults(void) {
|
|||||||
|
|
||||||
s->color = d->color;
|
s->color = d->color;
|
||||||
s->width = d->width;
|
s->width = d->width;
|
||||||
s->widthHow = WIDTH_AS_PIXELS;
|
s->widthAs = UNITS_AS_PIXELS;
|
||||||
|
s->textHeight = DEFAULT_TEXT_HEIGHT;
|
||||||
|
s->textHeightAs = UNITS_AS_PIXELS;
|
||||||
s->visible = true;
|
s->visible = true;
|
||||||
s->exportable = true;
|
s->exportable = true;
|
||||||
s->name.strcpy(CnfPrefixToName(d->cnfPrefix));
|
s->name.strcpy(CnfPrefixToName(d->cnfPrefix));
|
||||||
@ -119,7 +123,8 @@ void Style::AssignSelectionToStyle(DWORD v) {
|
|||||||
SS.GW.GroupSelection();
|
SS.GW.GroupSelection();
|
||||||
|
|
||||||
SS.UndoRemember();
|
SS.UndoRemember();
|
||||||
for(int i = 0; i < SS.GW.gs.entities; i++) {
|
int i;
|
||||||
|
for(i = 0; i < SS.GW.gs.entities; i++) {
|
||||||
hEntity he = SS.GW.gs.entity[i];
|
hEntity he = SS.GW.gs.entity[i];
|
||||||
if(!he.isFromRequest()) {
|
if(!he.isFromRequest()) {
|
||||||
showError = true;
|
showError = true;
|
||||||
@ -131,6 +136,13 @@ void Style::AssignSelectionToStyle(DWORD v) {
|
|||||||
r->style.v = v;
|
r->style.v = v;
|
||||||
SS.later.generateAll = true;
|
SS.later.generateAll = true;
|
||||||
}
|
}
|
||||||
|
for(i = 0; i < SS.GW.gs.constraints; i++) {
|
||||||
|
hConstraint hc = SS.GW.gs.constraint[i];
|
||||||
|
Constraint *c = SK.GetConstraint(hc);
|
||||||
|
if(c->type != Constraint::COMMENT) continue;
|
||||||
|
|
||||||
|
c->disp.style.v = v;
|
||||||
|
}
|
||||||
|
|
||||||
if(showError) {
|
if(showError) {
|
||||||
Error("Can't assign style to an entity that's derived from another "
|
Error("Can't assign style to an entity that's derived from another "
|
||||||
@ -204,9 +216,9 @@ DWORD Style::Color(hStyle h, bool forExport) {
|
|||||||
float Style::Width(hStyle h) {
|
float Style::Width(hStyle h) {
|
||||||
double r = 1.0;
|
double r = 1.0;
|
||||||
Style *s = Get(h);
|
Style *s = Get(h);
|
||||||
if(s->widthHow == WIDTH_AS_MM) {
|
if(s->widthAs == UNITS_AS_MM) {
|
||||||
r = s->width * SS.GW.scale;
|
r = s->width * SS.GW.scale;
|
||||||
} else if(s->widthHow == WIDTH_AS_PIXELS) {
|
} else if(s->widthAs == UNITS_AS_PIXELS) {
|
||||||
r = s->width;
|
r = s->width;
|
||||||
}
|
}
|
||||||
// This returns a float because glLineWidth expects a float, avoid casts.
|
// This returns a float because glLineWidth expects a float, avoid casts.
|
||||||
@ -221,6 +233,20 @@ double Style::WidthMm(int hs) {
|
|||||||
return widthpx / SS.GW.scale;
|
return widthpx / SS.GW.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Return the associated text height, in pixels.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
double Style::TextHeight(hStyle hs) {
|
||||||
|
Style *s = Get(hs);
|
||||||
|
if(s->textHeightAs == UNITS_AS_MM) {
|
||||||
|
return s->textHeight * SS.GW.scale;
|
||||||
|
} else if(s->textHeightAs == UNITS_AS_PIXELS) {
|
||||||
|
return s->textHeight;
|
||||||
|
} else {
|
||||||
|
return DEFAULT_TEXT_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Should lines and curves from this style appear in the output file? Only
|
// Should lines and curves from this style appear in the output file? Only
|
||||||
// if it's both shown and exportable.
|
// if it's both shown and exportable.
|
||||||
@ -346,18 +372,22 @@ void TextWindow::ScreenDeleteStyle(int link, DWORD v) {
|
|||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextWindow::ScreenChangeStyleWidth(int link, DWORD v) {
|
void TextWindow::ScreenChangeStyleWidthOrTextHeight(int link, DWORD v) {
|
||||||
hStyle hs = { v };
|
hStyle hs = { v };
|
||||||
Style *s = Style::Get(hs);
|
Style *s = Style::Get(hs);
|
||||||
|
double val = (link == 'w') ? s->width : s->textHeight;
|
||||||
|
int units = (link == 'w') ? s->widthAs : s->textHeightAs;
|
||||||
|
|
||||||
char str[300];
|
char str[300];
|
||||||
if(s->widthHow == Style::WIDTH_AS_PIXELS) {
|
if(units == Style::UNITS_AS_PIXELS) {
|
||||||
sprintf(str, "%.2f", s->width);
|
sprintf(str, "%.2f", val);
|
||||||
} else {
|
} else {
|
||||||
strcpy(str, SS.MmToString(s->width));
|
strcpy(str, SS.MmToString(val));
|
||||||
}
|
}
|
||||||
ShowTextEditControl(16, 8, str);
|
ShowTextEditControl((link == 'w') ? 21 : 26, 13, str);
|
||||||
SS.TW.edit.style = hs;
|
SS.TW.edit.style = hs;
|
||||||
SS.TW.edit.meaning = EDIT_STYLE_WIDTH;
|
SS.TW.edit.meaning = (link == 'w') ? EDIT_STYLE_WIDTH :
|
||||||
|
EDIT_STYLE_TEXT_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextWindow::ScreenChangeStyleColor(int link, DWORD v) {
|
void TextWindow::ScreenChangeStyleColor(int link, DWORD v) {
|
||||||
@ -377,10 +407,24 @@ void TextWindow::ScreenChangeStyleYesNo(int link, DWORD v) {
|
|||||||
Style *s = Style::Get(hs);
|
Style *s = Style::Get(hs);
|
||||||
switch(link) {
|
switch(link) {
|
||||||
case 'w':
|
case 'w':
|
||||||
if(s->widthHow == Style::WIDTH_AS_PIXELS) {
|
// Units for the width
|
||||||
s->widthHow = Style::WIDTH_AS_MM;
|
if(s->widthAs == Style::UNITS_AS_PIXELS) {
|
||||||
|
s->widthAs = Style::UNITS_AS_MM;
|
||||||
|
s->width /= SS.GW.scale;
|
||||||
} else {
|
} else {
|
||||||
s->widthHow = Style::WIDTH_AS_PIXELS;
|
s->widthAs = Style::UNITS_AS_PIXELS;
|
||||||
|
s->width *= SS.GW.scale;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
// Units for the height
|
||||||
|
if(s->textHeightAs == Style::UNITS_AS_PIXELS) {
|
||||||
|
s->textHeightAs = Style::UNITS_AS_MM;
|
||||||
|
s->textHeight /= SS.GW.scale;
|
||||||
|
} else {
|
||||||
|
s->textHeightAs = Style::UNITS_AS_PIXELS;
|
||||||
|
s->textHeight *= SS.GW.scale;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -391,6 +435,34 @@ void TextWindow::ScreenChangeStyleYesNo(int link, DWORD v) {
|
|||||||
case 'v':
|
case 'v':
|
||||||
s->visible = !(s->visible);
|
s->visible = !(s->visible);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Horizontal text alignment
|
||||||
|
case 'L':
|
||||||
|
s->textOrigin |= Style::ORIGIN_LEFT;
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_RIGHT;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_LEFT;
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_RIGHT;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_LEFT;
|
||||||
|
s->textOrigin |= Style::ORIGIN_RIGHT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Vertical text alignment
|
||||||
|
case 'B':
|
||||||
|
s->textOrigin |= Style::ORIGIN_BOT;
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_TOP;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_BOT;
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_TOP;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
s->textOrigin &= ~Style::ORIGIN_BOT;
|
||||||
|
s->textOrigin |= Style::ORIGIN_TOP;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
}
|
}
|
||||||
@ -398,17 +470,27 @@ void TextWindow::ScreenChangeStyleYesNo(int link, DWORD v) {
|
|||||||
bool TextWindow::EditControlDoneForStyles(char *str) {
|
bool TextWindow::EditControlDoneForStyles(char *str) {
|
||||||
Style *s;
|
Style *s;
|
||||||
switch(edit.meaning) {
|
switch(edit.meaning) {
|
||||||
case EDIT_STYLE_WIDTH:
|
case EDIT_STYLE_TEXT_HEIGHT:
|
||||||
|
case EDIT_STYLE_WIDTH: {
|
||||||
SS.UndoRemember();
|
SS.UndoRemember();
|
||||||
s = Style::Get(edit.style);
|
s = Style::Get(edit.style);
|
||||||
if(s->widthHow == Style::WIDTH_AS_MM) {
|
|
||||||
s->width = SS.StringToMm(str);
|
|
||||||
} else {
|
|
||||||
s->width = atof(str);
|
|
||||||
}
|
|
||||||
s->width = max(0, s->width);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
double v;
|
||||||
|
int units = (edit.meaning == EDIT_STYLE_TEXT_HEIGHT) ?
|
||||||
|
s->textHeightAs : s->widthAs;
|
||||||
|
if(units == Style::UNITS_AS_MM) {
|
||||||
|
v = SS.StringToMm(str);
|
||||||
|
} else {
|
||||||
|
v = atof(str);
|
||||||
|
}
|
||||||
|
v = max(0, v);
|
||||||
|
if(edit.meaning == EDIT_STYLE_TEXT_HEIGHT) {
|
||||||
|
s->textHeight = v;
|
||||||
|
} else {
|
||||||
|
s->width = v;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case EDIT_BACKGROUND_COLOR:
|
case EDIT_BACKGROUND_COLOR:
|
||||||
case EDIT_STYLE_COLOR: {
|
case EDIT_STYLE_COLOR: {
|
||||||
double r, g, b;
|
double r, g, b;
|
||||||
@ -462,31 +544,6 @@ void TextWindow::ShowStyleInfo(void) {
|
|||||||
REDf(s->color), GREENf(s->color), BLUEf(s->color),
|
REDf(s->color), GREENf(s->color), BLUEf(s->color),
|
||||||
s->h.v, ScreenChangeStyleColor);
|
s->h.v, ScreenChangeStyleColor);
|
||||||
|
|
||||||
if(s->widthHow == Style::WIDTH_AS_PIXELS) {
|
|
||||||
Printf(true, "%FtWIDTH %E%@ %D%f%Ll%Fl[change]%E",
|
|
||||||
s->width,
|
|
||||||
s->h.v, &ScreenChangeStyleWidth);
|
|
||||||
} else {
|
|
||||||
Printf(true, "%FtWIDTH %E%s %D%f%Ll%Fl[change]%E",
|
|
||||||
SS.MmToString(s->width),
|
|
||||||
s->h.v, &ScreenChangeStyleWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *unit = (SS.viewUnits == SolveSpace::UNIT_INCHES) ? "inches" : "mm";
|
|
||||||
bool widthpx = (s->widthHow == Style::WIDTH_AS_PIXELS);
|
|
||||||
|
|
||||||
if(s->h.v < Style::FIRST_CUSTOM) {
|
|
||||||
Printf(false,"%FtUNITS %Fspixels%E");
|
|
||||||
} else {
|
|
||||||
Printf(false,"%FtUNITS %Fh%D%f%Lw%s%E%Fs%s%E / %Fh%D%f%Lw%s%E%Fs%s%E",
|
|
||||||
s->h.v, &ScreenChangeStyleYesNo,
|
|
||||||
( widthpx ? "" : "pixels"),
|
|
||||||
( widthpx ? "pixels" : ""),
|
|
||||||
s->h.v, &ScreenChangeStyleYesNo,
|
|
||||||
(!widthpx ? "" : unit),
|
|
||||||
(!widthpx ? unit : ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s->h.v >= Style::FIRST_CUSTOM) {
|
if(s->h.v >= Style::FIRST_CUSTOM) {
|
||||||
Printf(true, "%FtSHOW %Fh%D%f%Lv%s%E%Fs%s%E / %Fh%D%f%Lv%s%E%Fs%s%E",
|
Printf(true, "%FtSHOW %Fh%D%f%Lv%s%E%Fs%s%E / %Fh%D%f%Lv%s%E%Fs%s%E",
|
||||||
s->h.v, &ScreenChangeStyleYesNo,
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
@ -502,7 +559,98 @@ void TextWindow::ShowStyleInfo(void) {
|
|||||||
s->h.v, &ScreenChangeStyleYesNo,
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
(!s->exportable ? "" : "no"),
|
(!s->exportable ? "" : "no"),
|
||||||
(!s->exportable ? "no" : ""));
|
(!s->exportable ? "no" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *unit = (SS.viewUnits == SolveSpace::UNIT_INCHES) ? "inches" : "mm";
|
||||||
|
|
||||||
|
// The line width, and its units
|
||||||
|
if(s->widthAs == Style::UNITS_AS_PIXELS) {
|
||||||
|
Printf(true, "%FtLINE WIDTH %E%@ %D%f%Lw%Fl[change]%E",
|
||||||
|
s->width,
|
||||||
|
s->h.v, &ScreenChangeStyleWidthOrTextHeight);
|
||||||
|
} else {
|
||||||
|
Printf(true, "%FtLINE WIDTH %E%s %D%f%Lw%Fl[change]%E",
|
||||||
|
SS.MmToString(s->width),
|
||||||
|
s->h.v, &ScreenChangeStyleWidthOrTextHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool widthpx = (s->widthAs == Style::UNITS_AS_PIXELS);
|
||||||
|
if(s->h.v < Style::FIRST_CUSTOM) {
|
||||||
|
Printf(false,"%FtIN UNITS OF %Fspixels%E");
|
||||||
|
} else {
|
||||||
|
Printf(false,"%FtIN UNITS OF "
|
||||||
|
"%Fh%D%f%Lw%s%E%Fs%s%E / %Fh%D%f%Lw%s%E%Fs%s%E",
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
( widthpx ? "" : "pixels"),
|
||||||
|
( widthpx ? "pixels" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
(!widthpx ? "" : unit),
|
||||||
|
(!widthpx ? unit : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The text height, and its units
|
||||||
|
char *chng = (s->h.v < Style::FIRST_CUSTOM) ? "" : "[change]";
|
||||||
|
if(s->textHeightAs == Style::UNITS_AS_PIXELS) {
|
||||||
|
Printf(true, "%FtTEXT HEIGHT %E%@ %D%f%Lt%Fl%s%E",
|
||||||
|
s->textHeight,
|
||||||
|
s->h.v, &ScreenChangeStyleWidthOrTextHeight,
|
||||||
|
chng);
|
||||||
|
} else {
|
||||||
|
Printf(true, "%FtTEXT HEIGHT %E%s %D%f%Lt%Fl%s%E",
|
||||||
|
SS.MmToString(s->textHeight),
|
||||||
|
s->h.v, &ScreenChangeStyleWidthOrTextHeight,
|
||||||
|
chng);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool textHeightpx = (s->textHeightAs == Style::UNITS_AS_PIXELS);
|
||||||
|
if(s->h.v < Style::FIRST_CUSTOM) {
|
||||||
|
Printf(false,"%FtIN UNITS OF %Fspixels%E");
|
||||||
|
} else {
|
||||||
|
Printf(false,"%FtIN UNITS OF "
|
||||||
|
"%Fh%D%f%Lh%s%E%Fs%s%E / %Fh%D%f%Lh%s%E%Fs%s%E",
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
( textHeightpx ? "" : "pixels"),
|
||||||
|
( textHeightpx ? "pixels" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
(!textHeightpx ? "" : unit),
|
||||||
|
(!textHeightpx ? unit : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s->h.v >= Style::FIRST_CUSTOM) {
|
||||||
|
bool neither;
|
||||||
|
|
||||||
|
neither = !(s->textOrigin & (Style::ORIGIN_LEFT | Style::ORIGIN_RIGHT));
|
||||||
|
Printf(true, "%FtALIGN TEXT "
|
||||||
|
"%Fh%D%f%LL%s%E%Fs%s%E / "
|
||||||
|
"%Fh%D%f%LH%s%E%Fs%s%E / "
|
||||||
|
"%Fh%D%f%LR%s%E%Fs%s%E",
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
((s->textOrigin & Style::ORIGIN_LEFT) ? "" : "left"),
|
||||||
|
((s->textOrigin & Style::ORIGIN_LEFT) ? "left" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
(neither ? "" : "center"),
|
||||||
|
(neither ? "center" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
((s->textOrigin & Style::ORIGIN_RIGHT) ? "" : "right"),
|
||||||
|
((s->textOrigin & Style::ORIGIN_RIGHT) ? "right" : ""));
|
||||||
|
|
||||||
|
neither = !(s->textOrigin & (Style::ORIGIN_BOT | Style::ORIGIN_TOP));
|
||||||
|
Printf(false, "%Ft "
|
||||||
|
"%Fh%D%f%LB%s%E%Fs%s%E / "
|
||||||
|
"%Fh%D%f%LV%s%E%Fs%s%E / "
|
||||||
|
"%Fh%D%f%LT%s%E%Fs%s%E",
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
((s->textOrigin & Style::ORIGIN_BOT) ? "" : "bottom"),
|
||||||
|
((s->textOrigin & Style::ORIGIN_BOT) ? "bottom" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
(neither ? "" : "center"),
|
||||||
|
(neither ? "center" : ""),
|
||||||
|
s->h.v, &ScreenChangeStyleYesNo,
|
||||||
|
((s->textOrigin & Style::ORIGIN_TOP) ? "" : "top"),
|
||||||
|
((s->textOrigin & Style::ORIGIN_TOP) ? "top" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s->h.v >= Style::FIRST_CUSTOM) {
|
||||||
Printf(false, "");
|
Printf(false, "");
|
||||||
Printf(false, "To assign lines or curves to this style,");
|
Printf(false, "To assign lines or curves to this style,");
|
||||||
Printf(false, "select them on the drawing. Then commit");
|
Printf(false, "select them on the drawing. Then commit");
|
||||||
|
12
ui.h
12
ui.h
@ -94,9 +94,10 @@ public:
|
|||||||
static const int EDIT_STEP_DIM_STEPS = 41;
|
static const int EDIT_STEP_DIM_STEPS = 41;
|
||||||
// For the styles stuff
|
// For the styles stuff
|
||||||
static const int EDIT_STYLE_WIDTH = 50;
|
static const int EDIT_STYLE_WIDTH = 50;
|
||||||
static const int EDIT_STYLE_COLOR = 51;
|
static const int EDIT_STYLE_TEXT_HEIGHT = 51;
|
||||||
static const int EDIT_STYLE_NAME = 52;
|
static const int EDIT_STYLE_COLOR = 52;
|
||||||
static const int EDIT_BACKGROUND_COLOR = 53;
|
static const int EDIT_STYLE_NAME = 53;
|
||||||
|
static const int EDIT_BACKGROUND_COLOR = 54;
|
||||||
struct {
|
struct {
|
||||||
int meaning;
|
int meaning;
|
||||||
int i;
|
int i;
|
||||||
@ -189,7 +190,7 @@ public:
|
|||||||
static void ScreenChangeExportScale(int link, DWORD v);
|
static void ScreenChangeExportScale(int link, DWORD v);
|
||||||
static void ScreenChangeExportOffset(int link, DWORD v);
|
static void ScreenChangeExportOffset(int link, DWORD v);
|
||||||
static void ScreenChangeStyleName(int link, DWORD v);
|
static void ScreenChangeStyleName(int link, DWORD v);
|
||||||
static void ScreenChangeStyleWidth(int link, DWORD v);
|
static void ScreenChangeStyleWidthOrTextHeight(int link, DWORD v);
|
||||||
static void ScreenChangeStyleColor(int link, DWORD v);
|
static void ScreenChangeStyleColor(int link, DWORD v);
|
||||||
static void ScreenChangeBackgroundColor(int link, DWORD v);
|
static void ScreenChangeBackgroundColor(int link, DWORD v);
|
||||||
|
|
||||||
@ -400,6 +401,7 @@ public:
|
|||||||
void Clear(void);
|
void Clear(void);
|
||||||
bool IsEmpty(void);
|
bool IsEmpty(void);
|
||||||
bool Equals(Selection *b);
|
bool Equals(Selection *b);
|
||||||
|
bool IsStylable(void);
|
||||||
};
|
};
|
||||||
Selection hover;
|
Selection hover;
|
||||||
static const int MAX_SELECTED = 32;
|
static const int MAX_SELECTED = 32;
|
||||||
@ -425,6 +427,7 @@ public:
|
|||||||
int anyNormals;
|
int anyNormals;
|
||||||
int vectors;
|
int vectors;
|
||||||
int constraints;
|
int constraints;
|
||||||
|
int stylables;
|
||||||
int n;
|
int n;
|
||||||
} gs;
|
} gs;
|
||||||
void GroupSelection(void);
|
void GroupSelection(void);
|
||||||
@ -439,6 +442,7 @@ public:
|
|||||||
static const int CMNU_GROUP_INFO = 0x105;
|
static const int CMNU_GROUP_INFO = 0x105;
|
||||||
static const int CMNU_REFERENCE_DIM = 0x106;
|
static const int CMNU_REFERENCE_DIM = 0x106;
|
||||||
static const int CMNU_OTHER_ANGLE = 0x107;
|
static const int CMNU_OTHER_ANGLE = 0x107;
|
||||||
|
static const int CMNU_STYLE_INFO = 0x108;
|
||||||
static const int CMNU_FIRST_STYLE = 0x40000000;
|
static const int CMNU_FIRST_STYLE = 0x40000000;
|
||||||
void ContextMenuListStyles(void);
|
void ContextMenuListStyles(void);
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
|
|
||||||
grid
|
grid
|
||||||
better text
|
|
||||||
right-click menu
|
|
||||||
wireframe export
|
wireframe export
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
Loading…
Reference in New Issue
Block a user