Add text angle for styles. Add ability to quickly change between
perspective and parallel projections. Add a snap grid, for points and for text comments. Draw text comments in the plane of their workplane if they have one, otherwise always facing forward. And fix a few nasty bugs: the possibility of an extremely long animation onto a workplane, accidental use of the wrong style line width for constraints, misplaced text box in style screen for default styles, other little stuff. [git-p4: depot-paths = "//depot/solvespace/": change = 2037]solver
parent
9f78ee3c33
commit
db565438e3
76
draw.cpp
76
draw.cpp
|
@ -1148,6 +1148,7 @@ void GraphicsWindow::GroupSelection(void) {
|
|||
Constraint *c = SK.GetConstraint(s->constraint);
|
||||
if(c->type == Constraint::COMMENT) {
|
||||
(gs.stylables)++;
|
||||
(gs.comments)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1226,7 +1227,7 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
|
||||
double mat[16];
|
||||
// Last thing before display is to apply the perspective
|
||||
double clp = SS.cameraTangent*scale;
|
||||
double clp = SS.CameraTangent()*scale;
|
||||
MakeMatrix(mat, 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
|
@ -1323,6 +1324,79 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
|
||||
glxUnlockColor();
|
||||
|
||||
if(showSnapGrid && LockedInWorkplane()) {
|
||||
hEntity he = ActiveWorkplane();
|
||||
EntityBase *wrkpl = SK.GetEntity(he),
|
||||
*norm = wrkpl->Normal();
|
||||
Vector wu, wv, wn, wp;
|
||||
wp = SK.GetEntity(wrkpl->point[0])->PointGetNum();
|
||||
wu = norm->NormalU();
|
||||
wv = norm->NormalV();
|
||||
wn = norm->NormalN();
|
||||
|
||||
double g = SS.gridSpacing;
|
||||
|
||||
double umin = VERY_POSITIVE, umax = VERY_NEGATIVE,
|
||||
vmin = VERY_POSITIVE, vmax = VERY_NEGATIVE;
|
||||
int a;
|
||||
for(a = 0; a < 4; a++) {
|
||||
// Ideally, we would just do +/- half the width and height; but
|
||||
// allow some extra slop for rounding.
|
||||
Vector horiz = projRight.ScaledBy((0.6*width)/scale + 2*g),
|
||||
vert = projUp. ScaledBy((0.6*height)/scale + 2*g);
|
||||
if(a == 2 || a == 3) horiz = horiz.ScaledBy(-1);
|
||||
if(a == 1 || a == 3) vert = vert. ScaledBy(-1);
|
||||
Vector tp = horiz.Plus(vert).Minus(offset);
|
||||
|
||||
// Project the point into our grid plane, normal to the screen
|
||||
// (not to the grid plane). If the plane is on edge then this is
|
||||
// impossible so don't try to draw the grid.
|
||||
bool parallel;
|
||||
Vector tpp = Vector::AtIntersectionOfPlaneAndLine(
|
||||
wn, wn.Dot(wp),
|
||||
tp, tp.Plus(n),
|
||||
¶llel);
|
||||
if(parallel) goto nogrid;
|
||||
|
||||
tpp = tpp.Minus(wp);
|
||||
double uu = tpp.Dot(wu),
|
||||
vv = tpp.Dot(wv);
|
||||
|
||||
umin = min(uu, umin);
|
||||
umax = max(uu, umax);
|
||||
vmin = min(vv, vmin);
|
||||
vmax = max(vv, vmax);
|
||||
}
|
||||
|
||||
int i, j, i0, i1, j0, j1;
|
||||
|
||||
i0 = (int)(umin / g);
|
||||
i1 = (int)(umax / g);
|
||||
j0 = (int)(vmin / g);
|
||||
j1 = (int)(vmax / g);
|
||||
|
||||
if(i0 > i1 || i1 - i0 > 400) goto nogrid;
|
||||
if(j0 > j1 || j1 - j0 > 400) goto nogrid;
|
||||
|
||||
glLineWidth(1);
|
||||
glxColorRGBa(Style::Color(Style::DATUM), 0.3);
|
||||
glBegin(GL_LINES);
|
||||
for(i = i0 + 1; i < i1; i++) {
|
||||
glxVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j0*g)));
|
||||
glxVertex3v(wp.Plus(wu.ScaledBy(i*g)).Plus(wv.ScaledBy(j1*g)));
|
||||
}
|
||||
for(j = j0 + 1; j < j1; j++) {
|
||||
glxVertex3v(wp.Plus(wu.ScaledBy(i0*g)).Plus(wv.ScaledBy(j*g)));
|
||||
glxVertex3v(wp.Plus(wu.ScaledBy(i1*g)).Plus(wv.ScaledBy(j*g)));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Clear the depth buffer, so that the grid is at the very back of
|
||||
// the Z order.
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
nogrid:;
|
||||
}
|
||||
|
||||
// Draw the active group; this fills the polygons in a drawing group, and
|
||||
// draws the solid mesh.
|
||||
(SK.GetGroup(activeGroup))->Draw();
|
||||
|
|
|
@ -31,8 +31,10 @@ void Constraint::LineDrawOrGetDistance(Vector a, Vector b) {
|
|||
if(dogd.sel) {
|
||||
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);
|
||||
// The only constraints with styles should be comments, so don't
|
||||
// check otherwise, save looking up the styles constantly.
|
||||
if(type == COMMENT && Style::Width(hs) >= 3.0) {
|
||||
glxFatLine(a, b, Style::Width(hs) / SS.GW.scale);
|
||||
} else {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glxVertex3v(a);
|
||||
|
@ -95,10 +97,18 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
|||
sheight = glxStrHeight(th);
|
||||
|
||||
// By default, the reference is from the center; but the style could
|
||||
// specify otherwise if one is present.
|
||||
// specify otherwise if one is present, and it could also specify a
|
||||
// rotation.
|
||||
if(type == COMMENT && disp.style.v) {
|
||||
Style *s = Style::Get(disp.style);
|
||||
int o = s->textOrigin;
|
||||
Style *st = Style::Get(disp.style);
|
||||
// rotation first
|
||||
double rads = st->textAngle*PI/180;
|
||||
double c = cos(rads), s = sin(rads);
|
||||
Vector pr = gr, pu = gu;
|
||||
gr = pr.ScaledBy( c).Plus(pu.ScaledBy(s));
|
||||
gu = pr.ScaledBy(-s).Plus(pu.ScaledBy(c));
|
||||
// then origin
|
||||
int o = st->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));
|
||||
|
@ -378,8 +388,15 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
// If the group is hidden, then the constraints are hidden and not
|
||||
// able to be selected.
|
||||
if(!(g->visible)) return;
|
||||
// And likewise if the group is not the active group.
|
||||
if(g->h.v != SS.GW.activeGroup.v) return;
|
||||
// And likewise if the group is not the active group; except for comments
|
||||
// with an assigned style.
|
||||
if(g->h.v != SS.GW.activeGroup.v && !(type == COMMENT && disp.style.v)) {
|
||||
return;
|
||||
}
|
||||
if(disp.style.v) {
|
||||
Style *s = Style::Get(disp.style);
|
||||
if(!s->visible) return;
|
||||
}
|
||||
|
||||
// Unit vectors that describe our current view of the scene. One pixel
|
||||
// long, not one actual unit.
|
||||
|
@ -917,13 +934,23 @@ s:
|
|||
}
|
||||
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);
|
||||
Vector u, v;
|
||||
if(workplane.v == Entity::FREE_IN_3D.v) {
|
||||
u = gr;
|
||||
v = gu;
|
||||
} else {
|
||||
EntityBase *norm = SK.GetEntity(workplane)->Normal();
|
||||
u = norm->NormalU();
|
||||
v = norm->NormalV();
|
||||
}
|
||||
DoLabel(disp.offset, labelPos, u, v);
|
||||
break;
|
||||
}
|
||||
|
||||
default: oops();
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ void SolveSpace::ExportViewTo(char *filename) {
|
|||
VectorFileWriter *out = VectorFileWriter::ForFile(filename);
|
||||
if(out) {
|
||||
ExportLinesAndMesh(&edges, &beziers, sm,
|
||||
u, v, n, origin, SS.cameraTangent*SS.GW.scale,
|
||||
u, v, n, origin, SS.CameraTangent()*SS.GW.scale,
|
||||
out);
|
||||
}
|
||||
edges.Clear();
|
||||
|
|
1
file.cpp
1
file.cpp
|
@ -157,6 +157,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ '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.textAngle", 'f', &(SS.sv.s.textAngle) },
|
||||
{ 's', "Style.textOrigin", 'x', &(SS.sv.s.textOrigin) },
|
||||
{ 's', "Style.color", 'x', &(SS.sv.s.color) },
|
||||
{ 's', "Style.visible", 'b', &(SS.sv.s.visible) },
|
||||
|
|
105
graphicswin.cpp
105
graphicswin.cpp
|
@ -32,9 +32,9 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "&Redo\tCtrl+Y", MNU_REDO, 'Y'|C, mEdit },
|
||||
{ 1, "Re&generate All\tSpace", MNU_REGEN_ALL, ' ', mEdit },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Snap Selection to &Grid\t.", MNU_SNAP_TO_GRID, '.', mEdit },
|
||||
{ 1, "Rotate Imported &90°\t9", MNU_ROTATE_90, '9', mEdit },
|
||||
{ 1, "&Delete\tDel", MNU_DELETE, 127, mEdit },
|
||||
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "&Unselect All\tEsc", MNU_UNSELECT_ALL, 27, mEdit },
|
||||
|
||||
|
@ -43,6 +43,9 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "Zoom &Out\t-", MNU_ZOOM_OUT, '-', mView },
|
||||
{ 1, "Zoom To &Fit\tF", MNU_ZOOM_TO_FIT, 'F', mView },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Show Snap &Grid\t>", MNU_SHOW_GRID, '.'|S, mView },
|
||||
{ 1, "Force &Parallel Projection\t`", MNU_PARALLEL_PROJ, '`', mView },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Nearest &Ortho View\tF2", MNU_NEAREST_ORTHO, F(2), mView },
|
||||
{ 1, "Nearest &Isometric View\tF3", MNU_NEAREST_ISO, F(3), mView },
|
||||
{ 1, "&Center View At Point\tF4", MNU_CENTER_VIEW, F(4), mView },
|
||||
|
@ -154,6 +157,7 @@ void GraphicsWindow::Init(void) {
|
|||
showTextWindow = true;
|
||||
ShowTextWindow(showTextWindow);
|
||||
|
||||
showSnapGrid = false;
|
||||
context.active = false;
|
||||
|
||||
// Do this last, so that all the menus get updated correctly.
|
||||
|
@ -199,7 +203,7 @@ Vector GraphicsWindow::ProjectPoint4(Vector p, double *w) {
|
|||
r.y = p.Dot(projUp);
|
||||
r.z = p.Dot(projUp.Cross(projRight));
|
||||
|
||||
*w = 1 + r.z*SS.cameraTangent*scale;
|
||||
*w = 1 + r.z*SS.CameraTangent()*scale;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -230,6 +234,10 @@ void GraphicsWindow::AnimateOnto(Quaternion quatf, Vector offsetf) {
|
|||
// Animate transition, unless it's a tiny move.
|
||||
SDWORD dt = (mp < 0.01 && mo < 10) ? (-20) :
|
||||
(SDWORD)(100 + 1000*mp + 0.4*mo);
|
||||
// Don't ever animate for longer than 2000 ms; we can get absurdly
|
||||
// long translations (as measured in pixels) if the user zooms out, moves,
|
||||
// and then zooms in again.
|
||||
if(dt > 2000) dt = 2000;
|
||||
SDWORD tn, t0 = GetMilliseconds();
|
||||
double s = 0;
|
||||
Quaternion dq = quatf.Times(quat0.Inverse());
|
||||
|
@ -347,7 +355,7 @@ void GraphicsWindow::ZoomToFit(bool includingInvisibles) {
|
|||
|
||||
// Adjust the scale so that no points are behind the camera
|
||||
if(wmin < 0.1) {
|
||||
double k = SS.cameraTangent;
|
||||
double k = SS.CameraTangent();
|
||||
// w = 1+k*scale*z
|
||||
double zmin = (wmin - 1)/(k*scale);
|
||||
// 0.1 = 1 + k*scale*zmin
|
||||
|
@ -370,6 +378,29 @@ void GraphicsWindow::MenuView(int id) {
|
|||
SS.GW.ZoomToFit(false);
|
||||
break;
|
||||
|
||||
case MNU_SHOW_GRID:
|
||||
SS.GW.showSnapGrid = !SS.GW.showSnapGrid;
|
||||
if(SS.GW.showSnapGrid && !SS.GW.LockedInWorkplane()) {
|
||||
Message("No workplane is active, so the grid will not "
|
||||
"appear.");
|
||||
}
|
||||
SS.GW.EnsureValidActives();
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
|
||||
case MNU_PARALLEL_PROJ:
|
||||
SS.forceParallelProj = !SS.forceParallelProj;
|
||||
if(SS.cameraTangent < 1e-6) {
|
||||
Error("The perspective factor is set to zero, so the view will "
|
||||
"always be a parallel projection.\r\n\r\n"
|
||||
"For a perspective projection, modify the camera tangent "
|
||||
"in the configuration screen. A value around 0.3 is "
|
||||
"typical.");
|
||||
}
|
||||
SS.GW.EnsureValidActives();
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
|
||||
case MNU_NEAREST_ORTHO:
|
||||
case MNU_NEAREST_ISO: {
|
||||
static const Vector ortho[3] = {
|
||||
|
@ -448,7 +479,7 @@ void GraphicsWindow::MenuView(int id) {
|
|||
case MNU_SHOW_TOOLBAR:
|
||||
SS.showToolbar = !SS.showToolbar;
|
||||
SS.GW.EnsureValidActives();
|
||||
PaintGraphics();
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
|
||||
case MNU_UNITS_MM:
|
||||
|
@ -532,6 +563,8 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
CheckMenuById(MNU_SHOW_TEXT_WND, SS.GW.showTextWindow);
|
||||
|
||||
CheckMenuById(MNU_SHOW_TOOLBAR, SS.showToolbar);
|
||||
CheckMenuById(MNU_PARALLEL_PROJ, SS.forceParallelProj);
|
||||
CheckMenuById(MNU_SHOW_GRID, SS.GW.showSnapGrid);
|
||||
|
||||
if(change) SS.later.showTW = true;
|
||||
}
|
||||
|
@ -583,6 +616,24 @@ void GraphicsWindow::DeleteTaggedRequests(void) {
|
|||
SS.later.showTW = true;
|
||||
}
|
||||
|
||||
Vector GraphicsWindow::SnapToGrid(Vector p) {
|
||||
if(!LockedInWorkplane()) return p;
|
||||
|
||||
EntityBase *wrkpl = SK.GetEntity(ActiveWorkplane()),
|
||||
*norm = wrkpl->Normal();
|
||||
Vector wo = SK.GetEntity(wrkpl->point[0])->PointGetNum(),
|
||||
wu = norm->NormalU(),
|
||||
wv = norm->NormalV(),
|
||||
wn = norm->NormalN();
|
||||
|
||||
Vector pp = (p.Minus(wo)).DotInToCsys(wu, wv, wn);
|
||||
pp.x = floor((pp.x / SS.gridSpacing) + 0.5)*SS.gridSpacing;
|
||||
pp.y = floor((pp.y / SS.gridSpacing) + 0.5)*SS.gridSpacing;
|
||||
pp.z = 0;
|
||||
|
||||
return pp.ScaleOutOfCsys(wu, wv, wn).Plus(wo);
|
||||
}
|
||||
|
||||
void GraphicsWindow::MenuEdit(int id) {
|
||||
switch(id) {
|
||||
case MNU_UNSELECT_ALL:
|
||||
|
@ -590,7 +641,10 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||
// If there's nothing selected to de-select, and no operation
|
||||
// to cancel, then perhaps they want to return to the home
|
||||
// screen in the text window.
|
||||
if(SS.GW.gs.n == 0 && SS.GW.pending.operation == 0) {
|
||||
if(SS.GW.gs.n == 0 &&
|
||||
SS.GW.gs.constraints == 0 &&
|
||||
SS.GW.pending.operation == 0)
|
||||
{
|
||||
if(!(TextEditControlIsVisible() ||
|
||||
GraphicsEditControlIsVisible()))
|
||||
{
|
||||
|
@ -667,6 +721,46 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||
break;
|
||||
}
|
||||
|
||||
case MNU_SNAP_TO_GRID: {
|
||||
if(!SS.GW.LockedInWorkplane()) {
|
||||
Error("No workplane is active. Select a workplane to define "
|
||||
"the plane for the snap grid.");
|
||||
break;
|
||||
}
|
||||
SS.GW.GroupSelection();
|
||||
if(SS.GW.gs.n != SS.GW.gs.points ||
|
||||
SS.GW.gs.constraints != SS.GW.gs.comments ||
|
||||
(SS.GW.gs.n == 0 && SS.GW.gs.constraints == 0))
|
||||
{
|
||||
Error("Can't snap these items to grid; select only points or "
|
||||
"text comments. To snap a line, select its endpoints.");
|
||||
break;
|
||||
}
|
||||
SS.UndoRemember();
|
||||
int i;
|
||||
for(i = 0; i < SS.GW.gs.points; i++) {
|
||||
hEntity hp = SS.GW.gs.point[i];
|
||||
Entity *ep = SK.GetEntity(hp);
|
||||
Vector p = ep->PointGetNum();
|
||||
|
||||
ep->PointForceTo(SS.GW.SnapToGrid(p));
|
||||
|
||||
// Regenerate, with this point marked as dragged so that it
|
||||
// gets placed as close as possible to our snap
|
||||
SS.GW.pending.point = hp;
|
||||
SS.MarkGroupDirty(ep->group);
|
||||
SS.GenerateAll();
|
||||
SS.GW.pending.point = Entity::NO_ENTITY;
|
||||
}
|
||||
for(i = 0; i < SS.GW.gs.constraints; i++) {
|
||||
Constraint *c = SK.GetConstraint(SS.GW.gs.constraint[i]);
|
||||
c->disp.offset = SS.GW.SnapToGrid(c->disp.offset);
|
||||
}
|
||||
SS.GW.ClearSelection();
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
}
|
||||
|
||||
case MNU_UNDO:
|
||||
SS.UndoUndo();
|
||||
break;
|
||||
|
@ -715,6 +809,7 @@ void GraphicsWindow::MenuRequest(int id) {
|
|||
SS.GW.SetWorkplaneFreeIn3d();
|
||||
SS.GW.EnsureValidActives();
|
||||
SS.later.showTW = true;
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
|
||||
case MNU_ARC: {
|
||||
|
|
1
sketch.h
1
sketch.h
|
@ -635,6 +635,7 @@ public:
|
|||
static const int ORIGIN_BOT = 0x04;
|
||||
static const int ORIGIN_TOP = 0x08;
|
||||
int textOrigin;
|
||||
double textAngle;
|
||||
DWORD color;
|
||||
bool visible;
|
||||
bool exportable;
|
||||
|
|
|
@ -64,6 +64,8 @@ void SolveSpace::Init(char *cmdLine) {
|
|||
viewUnits = (Unit)CnfThawDWORD((DWORD)UNIT_MM, "ViewUnits");
|
||||
// Camera tangent (determines perspective)
|
||||
cameraTangent = CnfThawFloat(0.0f, "CameraTangent");
|
||||
// Grid spacing
|
||||
gridSpacing = CnfThawFloat(5.0f, "GridSpacing");
|
||||
// Export scale factor
|
||||
exportScale = CnfThawFloat(1.0f, "ExportScale");
|
||||
// Export offset (cutter radius comp)
|
||||
|
@ -150,6 +152,8 @@ void SolveSpace::Exit(void) {
|
|||
CnfFreezeDWORD((DWORD)viewUnits, "ViewUnits");
|
||||
// Camera tangent (determines perspective)
|
||||
CnfFreezeFloat((float)cameraTangent, "CameraTangent");
|
||||
// Grid spacing
|
||||
CnfFreezeFloat(gridSpacing, "GridSpacing");
|
||||
// Export scale (a float, stored as a DWORD)
|
||||
CnfFreezeFloat(exportScale, "ExportScale");
|
||||
// Export offset (cutter radius comp)
|
||||
|
@ -191,25 +195,6 @@ void SolveSpace::DoLater(void) {
|
|||
ZERO(&later);
|
||||
}
|
||||
|
||||
int SolveSpace::CircleSides(double r) {
|
||||
// Let the pwl segment be symmetric about the x axis; then the curve
|
||||
// goes out to r, and if there's n segments, then the endpoints are
|
||||
// at +/- (2pi/n)/2 = +/- pi/n. So the chord goes to x = r cos pi/n,
|
||||
// from x = r, so it's
|
||||
// tol = r - r cos pi/n
|
||||
// tol = r(1 - cos pi/n)
|
||||
// tol ~ r(1 - (1 - (pi/n)^2/2)) (Taylor expansion)
|
||||
// tol = r((pi/n)^2/2)
|
||||
// 2*tol/r = (pi/n)^2
|
||||
// sqrt(2*tol/r) = pi/n
|
||||
// n = pi/sqrt(2*tol/r);
|
||||
|
||||
double tol = chordTol/GW.scale;
|
||||
int n = 3 + (int)(PI/sqrt(2*tol/r));
|
||||
|
||||
return max(7, min(n, maxSegments));
|
||||
}
|
||||
|
||||
char *SolveSpace::MmToString(double v) {
|
||||
static int WhichBuf;
|
||||
static char Bufs[8][128];
|
||||
|
@ -243,6 +228,13 @@ double SolveSpace::ChordTolMm(void) {
|
|||
return SS.chordTol / SS.GW.scale;
|
||||
}
|
||||
|
||||
double SolveSpace::CameraTangent(void) {
|
||||
if(forceParallelProj) {
|
||||
return 0;
|
||||
} else {
|
||||
return cameraTangent;
|
||||
}
|
||||
}
|
||||
|
||||
void SolveSpace::AfterNewFile(void) {
|
||||
// Clear out the traced point, which is no longer valid
|
||||
|
|
|
@ -547,6 +547,7 @@ public:
|
|||
double chordTol;
|
||||
int maxSegments;
|
||||
double cameraTangent;
|
||||
float gridSpacing;
|
||||
float exportScale;
|
||||
float exportOffset;
|
||||
int fixExportColors;
|
||||
|
@ -569,7 +570,6 @@ public:
|
|||
float dy;
|
||||
} exportCanvas;
|
||||
|
||||
int CircleSides(double r);
|
||||
typedef enum {
|
||||
UNIT_MM = 0,
|
||||
UNIT_INCHES,
|
||||
|
@ -579,6 +579,8 @@ public:
|
|||
double ExprToMm(Expr *e);
|
||||
double StringToMm(char *s);
|
||||
double ChordTolMm(void);
|
||||
bool forceParallelProj;
|
||||
double CameraTangent(void);
|
||||
|
||||
// The platform-dependent code calls this before entering the msg loop
|
||||
void Init(char *cmdLine);
|
||||
|
|
57
style.cpp
57
style.cpp
|
@ -73,6 +73,8 @@ void Style::CreateDefaultStyle(hStyle h) {
|
|||
ns.widthAs = UNITS_AS_PIXELS;
|
||||
ns.textHeight = DEFAULT_TEXT_HEIGHT;
|
||||
ns.textHeightAs = UNITS_AS_PIXELS;
|
||||
ns.textOrigin = 0;
|
||||
ns.textAngle = 0;
|
||||
ns.visible = true;
|
||||
ns.exportable = true;
|
||||
ns.h = h;
|
||||
|
@ -95,6 +97,8 @@ void Style::LoadFactoryDefaults(void) {
|
|||
s->widthAs = UNITS_AS_PIXELS;
|
||||
s->textHeight = DEFAULT_TEXT_HEIGHT;
|
||||
s->textHeightAs = UNITS_AS_PIXELS;
|
||||
s->textOrigin = 0;
|
||||
s->textAngle = 0;
|
||||
s->visible = true;
|
||||
s->exportable = true;
|
||||
s->name.strcpy(CnfPrefixToName(d->cnfPrefix));
|
||||
|
@ -375,8 +379,8 @@ void TextWindow::ScreenDeleteStyle(int link, DWORD v) {
|
|||
void TextWindow::ScreenChangeStyleWidthOrTextHeight(int link, DWORD v) {
|
||||
hStyle hs = { v };
|
||||
Style *s = Style::Get(hs);
|
||||
double val = (link == 'w') ? s->width : s->textHeight;
|
||||
int units = (link == 'w') ? s->widthAs : s->textHeightAs;
|
||||
double val = (link == 't') ? s->textHeight : s->width;
|
||||
int units = (link == 't') ? s->textHeightAs : s->widthAs;
|
||||
|
||||
char str[300];
|
||||
if(units == Style::UNITS_AS_PIXELS) {
|
||||
|
@ -384,10 +388,28 @@ void TextWindow::ScreenChangeStyleWidthOrTextHeight(int link, DWORD v) {
|
|||
} else {
|
||||
strcpy(str, SS.MmToString(val));
|
||||
}
|
||||
ShowTextEditControl((link == 'w') ? 21 : 26, 13, str);
|
||||
int row = 0;
|
||||
if(link == 'w') {
|
||||
row = 16; // width for a default style
|
||||
} else if(link == 'W') {
|
||||
row = 21; // width for a custom style
|
||||
} else if(link == 't') {
|
||||
row = 27; // text height (for custom styles only)
|
||||
}
|
||||
ShowTextEditControl(row, 13, str);
|
||||
SS.TW.edit.style = hs;
|
||||
SS.TW.edit.meaning = (link == 'w') ? EDIT_STYLE_WIDTH :
|
||||
EDIT_STYLE_TEXT_HEIGHT;
|
||||
SS.TW.edit.meaning = (link == 't') ? EDIT_STYLE_TEXT_HEIGHT :
|
||||
EDIT_STYLE_WIDTH;
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeStyleTextAngle(int link, DWORD v) {
|
||||
hStyle hs = { v };
|
||||
Style *s = Style::Get(hs);
|
||||
char str[300];
|
||||
sprintf(str, "%.2f", s->textAngle);
|
||||
ShowTextEditControl(32, 13, str);
|
||||
SS.TW.edit.style = hs;
|
||||
SS.TW.edit.meaning = EDIT_STYLE_TEXT_ANGLE;
|
||||
}
|
||||
|
||||
void TextWindow::ScreenChangeStyleColor(int link, DWORD v) {
|
||||
|
@ -491,6 +513,12 @@ bool TextWindow::EditControlDoneForStyles(char *str) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
case EDIT_STYLE_TEXT_ANGLE:
|
||||
SS.UndoRemember();
|
||||
s = Style::Get(edit.style);
|
||||
s->textAngle = WRAP_SYMMETRIC(atof(str), 360);
|
||||
return true;
|
||||
|
||||
case EDIT_BACKGROUND_COLOR:
|
||||
case EDIT_STYLE_COLOR: {
|
||||
double r, g, b;
|
||||
|
@ -565,13 +593,15 @@ void TextWindow::ShowStyleInfo(void) {
|
|||
|
||||
// The line width, and its units
|
||||
if(s->widthAs == Style::UNITS_AS_PIXELS) {
|
||||
Printf(true, "%FtLINE WIDTH %E%@ %D%f%Lw%Fl[change]%E",
|
||||
Printf(true, "%FtLINE WIDTH %E%@ %D%f%Lp%Fl[change]%E",
|
||||
s->width,
|
||||
s->h.v, &ScreenChangeStyleWidthOrTextHeight);
|
||||
s->h.v, &ScreenChangeStyleWidthOrTextHeight,
|
||||
(s->h.v < Style::FIRST_CUSTOM) ? 'w' : 'W');
|
||||
} else {
|
||||
Printf(true, "%FtLINE WIDTH %E%s %D%f%Lw%Fl[change]%E",
|
||||
Printf(true, "%FtLINE WIDTH %E%s %D%f%Lp%Fl[change]%E",
|
||||
SS.MmToString(s->width),
|
||||
s->h.v, &ScreenChangeStyleWidthOrTextHeight);
|
||||
s->h.v, &ScreenChangeStyleWidthOrTextHeight,
|
||||
(s->h.v < Style::FIRST_CUSTOM) ? 'w' : 'W');
|
||||
}
|
||||
|
||||
bool widthpx = (s->widthAs == Style::UNITS_AS_PIXELS);
|
||||
|
@ -589,14 +619,15 @@ void TextWindow::ShowStyleInfo(void) {
|
|||
}
|
||||
|
||||
// The text height, and its units
|
||||
Printf(false, "");
|
||||
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",
|
||||
Printf(false, "%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",
|
||||
Printf(false, "%FtTEXT HEIGHT %E%s %D%f%Lt%Fl%s%E",
|
||||
SS.MmToString(s->textHeight),
|
||||
s->h.v, &ScreenChangeStyleWidthOrTextHeight,
|
||||
chng);
|
||||
|
@ -619,6 +650,10 @@ void TextWindow::ShowStyleInfo(void) {
|
|||
if(s->h.v >= Style::FIRST_CUSTOM) {
|
||||
bool neither;
|
||||
|
||||
Printf(true, "%FtTEXT ANGLE %E%@ %D%f%Ll%Fl[change]%E",
|
||||
s->textAngle,
|
||||
s->h.v, &ScreenChangeStyleTextAngle);
|
||||
|
||||
neither = !(s->textOrigin & (Style::ORIGIN_LEFT | Style::ORIGIN_RIGHT));
|
||||
Printf(true, "%FtALIGN TEXT "
|
||||
"%Fh%D%f%LL%s%E%Fs%s%E / "
|
||||
|
|
|
@ -273,7 +273,7 @@ void TextWindow::ScreenChangeHelixParameter(int link, DWORD v) {
|
|||
sprintf(str, "%.3f", g->valA);
|
||||
SS.TW.edit.meaning = EDIT_HELIX_TURNS;
|
||||
r = 12;
|
||||
} else if(link == 'p') {
|
||||
} else if(link == 'i') {
|
||||
strcpy(str, SS.MmToString(g->valB));
|
||||
SS.TW.edit.meaning = EDIT_HELIX_PITCH;
|
||||
r = 14;
|
||||
|
@ -383,7 +383,7 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
(!rh ? "" : "left-hand"), (!rh ? "left-hand" : ""));
|
||||
Printf(false, "%FtTHROUGH%E %@ turns %Fl%Lt%D%f[change]%E",
|
||||
g->valA, g->h.v, &ScreenChangeHelixParameter);
|
||||
Printf(false, "%FtPITCH%E %s axially per turn %Fl%Lp%D%f[change]%E",
|
||||
Printf(false, "%FtPITCH%E %s axially per turn %Fl%Li%D%f[change]%E",
|
||||
SS.MmToString(g->valB), g->h.v, &ScreenChangeHelixParameter);
|
||||
Printf(false, "%FtdRADIUS%E %s radially per turn %Fl%Lr%D%f[change]%E",
|
||||
SS.MmToString(g->valC), g->h.v, &ScreenChangeHelixParameter);
|
||||
|
@ -625,15 +625,19 @@ void TextWindow::ScreenChangeCameraTangent(int link, DWORD v) {
|
|||
ShowTextEditControl(47, 3, str);
|
||||
SS.TW.edit.meaning = EDIT_CAMERA_TANGENT;
|
||||
}
|
||||
void TextWindow::ScreenChangeGridSpacing(int link, DWORD v) {
|
||||
ShowTextEditControl(51, 3, SS.MmToString(SS.gridSpacing));
|
||||
SS.TW.edit.meaning = EDIT_GRID_SPACING;
|
||||
}
|
||||
void TextWindow::ScreenChangeExportScale(int link, DWORD v) {
|
||||
char str[1024];
|
||||
sprintf(str, "%.3f", (double)SS.exportScale);
|
||||
|
||||
ShowTextEditControl(53, 3, str);
|
||||
ShowTextEditControl(57, 3, str);
|
||||
SS.TW.edit.meaning = EDIT_EXPORT_SCALE;
|
||||
}
|
||||
void TextWindow::ScreenChangeExportOffset(int link, DWORD v) {
|
||||
ShowTextEditControl(57, 3, SS.MmToString(SS.exportOffset));
|
||||
ShowTextEditControl(61, 3, SS.MmToString(SS.exportOffset));
|
||||
SS.TW.edit.meaning = EDIT_EXPORT_OFFSET;
|
||||
}
|
||||
void TextWindow::ScreenChangeFixExportColors(int link, DWORD v) {
|
||||
|
@ -670,7 +674,7 @@ void TextWindow::ScreenChangeCanvasSize(int link, DWORD v) {
|
|||
|
||||
default: return;
|
||||
}
|
||||
int row = 71, col;
|
||||
int row = 75, col;
|
||||
if(v < 10) {
|
||||
row += v*2;
|
||||
col = 11;
|
||||
|
@ -723,6 +727,10 @@ void TextWindow::ShowConfiguration(void) {
|
|||
Printf(false, "%Ba %3 %Fl%Ll%f%D[change]%E",
|
||||
SS.cameraTangent*1000,
|
||||
&ScreenChangeCameraTangent, 0);
|
||||
Printf(false, "%Ft snap grid spacing%E");
|
||||
Printf(false, "%Ba %s %Fl%Ll%f%D[change]%E",
|
||||
SS.MmToString(SS.gridSpacing),
|
||||
&ScreenChangeGridSpacing, 0);
|
||||
|
||||
Printf(false, "");
|
||||
Printf(false, "%Ft export scale factor (1.0=mm, 25.4=inch)");
|
||||
|
@ -984,6 +992,15 @@ void TextWindow::EditControlDone(char *s) {
|
|||
}
|
||||
case EDIT_CAMERA_TANGENT: {
|
||||
SS.cameraTangent = (min(2, max(0, atof(s))))/1000.0;
|
||||
if(SS.forceParallelProj) {
|
||||
Message("The perspective factor will have no effect until you "
|
||||
"disable View -> Force Parallel Projection.");
|
||||
}
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
}
|
||||
case EDIT_GRID_SPACING: {
|
||||
SS.gridSpacing = (float)min(1e4, max(1e-3, SS.StringToMm(s)));
|
||||
InvalidateGraphics();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -144,7 +144,11 @@ void TextWindow::Printf(bool halfLine, char *fmt, ...) {
|
|||
case 'L':
|
||||
if(fmt[1] == '\0') goto done;
|
||||
fmt++;
|
||||
if(*fmt == 'p') {
|
||||
link = va_arg(vl, int);
|
||||
} else {
|
||||
link = *fmt;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
|
23
ui.h
23
ui.h
|
@ -80,9 +80,10 @@ public:
|
|||
static const int EDIT_CHORD_TOLERANCE = 13;
|
||||
static const int EDIT_MAX_SEGMENTS = 14;
|
||||
static const int EDIT_CAMERA_TANGENT = 15;
|
||||
static const int EDIT_EXPORT_SCALE = 16;
|
||||
static const int EDIT_EXPORT_OFFSET = 17;
|
||||
static const int EDIT_CANVAS_SIZE = 18;
|
||||
static const int EDIT_GRID_SPACING = 16;
|
||||
static const int EDIT_EXPORT_SCALE = 17;
|
||||
static const int EDIT_EXPORT_OFFSET = 18;
|
||||
static const int EDIT_CANVAS_SIZE = 19;
|
||||
// For the helical sweep
|
||||
static const int EDIT_HELIX_TURNS = 20;
|
||||
static const int EDIT_HELIX_PITCH = 21;
|
||||
|
@ -95,9 +96,10 @@ public:
|
|||
// For the styles stuff
|
||||
static const int EDIT_STYLE_WIDTH = 50;
|
||||
static const int EDIT_STYLE_TEXT_HEIGHT = 51;
|
||||
static const int EDIT_STYLE_COLOR = 52;
|
||||
static const int EDIT_STYLE_NAME = 53;
|
||||
static const int EDIT_BACKGROUND_COLOR = 54;
|
||||
static const int EDIT_STYLE_TEXT_ANGLE = 52;
|
||||
static const int EDIT_STYLE_COLOR = 53;
|
||||
static const int EDIT_STYLE_NAME = 54;
|
||||
static const int EDIT_BACKGROUND_COLOR = 55;
|
||||
struct {
|
||||
int meaning;
|
||||
int i;
|
||||
|
@ -187,10 +189,12 @@ public:
|
|||
static void ScreenChangeChordTolerance(int link, DWORD v);
|
||||
static void ScreenChangeMaxSegments(int link, DWORD v);
|
||||
static void ScreenChangeCameraTangent(int link, DWORD v);
|
||||
static void ScreenChangeGridSpacing(int link, DWORD v);
|
||||
static void ScreenChangeExportScale(int link, DWORD v);
|
||||
static void ScreenChangeExportOffset(int link, DWORD v);
|
||||
static void ScreenChangeStyleName(int link, DWORD v);
|
||||
static void ScreenChangeStyleWidthOrTextHeight(int link, DWORD v);
|
||||
static void ScreenChangeStyleTextAngle(int link, DWORD v);
|
||||
static void ScreenChangeStyleColor(int link, DWORD v);
|
||||
static void ScreenChangeBackgroundColor(int link, DWORD v);
|
||||
|
||||
|
@ -220,6 +224,8 @@ public:
|
|||
MNU_ZOOM_IN,
|
||||
MNU_ZOOM_OUT,
|
||||
MNU_ZOOM_TO_FIT,
|
||||
MNU_SHOW_GRID,
|
||||
MNU_PARALLEL_PROJ,
|
||||
MNU_NEAREST_ORTHO,
|
||||
MNU_NEAREST_ISO,
|
||||
MNU_CENTER_VIEW,
|
||||
|
@ -231,6 +237,7 @@ public:
|
|||
MNU_UNDO,
|
||||
MNU_REDO,
|
||||
MNU_DELETE,
|
||||
MNU_SNAP_TO_GRID,
|
||||
MNU_ROTATE_90,
|
||||
MNU_UNSELECT_ALL,
|
||||
MNU_REGEN_ALL,
|
||||
|
@ -373,6 +380,7 @@ public:
|
|||
// The constraint that is being edited with the on-screen textbox.
|
||||
hConstraint constraintBeingEdited;
|
||||
|
||||
Vector SnapToGrid(Vector p);
|
||||
bool ConstrainPointByHovered(hEntity pt);
|
||||
void DeleteTaggedRequests(void);
|
||||
hRequest AddRequest(int type, bool rememberForUndo);
|
||||
|
@ -428,6 +436,7 @@ public:
|
|||
int vectors;
|
||||
int constraints;
|
||||
int stylables;
|
||||
int comments;
|
||||
int n;
|
||||
} gs;
|
||||
void GroupSelection(void);
|
||||
|
@ -469,6 +478,8 @@ public:
|
|||
bool showHdnLines;
|
||||
static void ToggleBool(int link, DWORD v);
|
||||
|
||||
bool showSnapGrid;
|
||||
|
||||
void UpdateDraggedNum(Vector *pos, double mx, double my);
|
||||
void UpdateDraggedPoint(hEntity hp, double mx, double my);
|
||||
|
||||
|
|
|
@ -539,9 +539,11 @@ static BOOL ProcessKeyDown(WPARAM wParam)
|
|||
case VK_OEM_MINUS: c = '-'; break;
|
||||
case VK_ESCAPE: c = 27; break;
|
||||
case VK_OEM_1: c = ';'; break;
|
||||
case VK_OEM_3: c = '`'; break;
|
||||
case VK_OEM_4: c = '['; break;
|
||||
case VK_OEM_6: c = ']'; break;
|
||||
case VK_OEM_5: c = '\\'; break;
|
||||
case VK_OEM_PERIOD: c = '.'; break;
|
||||
case VK_SPACE: c = ' '; break;
|
||||
case VK_DELETE: c = 127; break;
|
||||
case VK_TAB: c = '\t'; break;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
grid
|
||||
split draw.cpp
|
||||
multi-drag
|
||||
|
||||
-----
|
||||
|
|
Loading…
Reference in New Issue