diff --git a/Makefile b/Makefile
index 3412c30a..b5e15249 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
$(OBJDIR)\graphicswin.obj \
$(OBJDIR)\modify.obj \
$(OBJDIR)\clipboard.obj \
+ $(OBJDIR)\view.obj \
$(OBJDIR)\util.obj \
$(OBJDIR)\style.obj \
$(OBJDIR)\entity.obj \
diff --git a/confscreen.cpp b/confscreen.cpp
index 77c9d71f..8de4a719 100644
--- a/confscreen.cpp
+++ b/confscreen.cpp
@@ -317,7 +317,7 @@ bool TextWindow::EditControlDoneForConfiguration(char *s) {
break;
}
case EDIT_EXPORT_SCALE: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(e) {
double ev = e->Eval();
if(fabs(ev) < 0.001 || isnan(ev)) {
@@ -325,13 +325,11 @@ bool TextWindow::EditControlDoneForConfiguration(char *s) {
} else {
SS.exportScale = (float)ev;
}
- } else {
- Error("Not a valid number or expression: '%s'", s);
}
break;
}
case EDIT_EXPORT_OFFSET: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(e) {
double ev = SS.ExprToMm(e);
if(isnan(ev) || ev < 0) {
@@ -339,15 +337,12 @@ bool TextWindow::EditControlDoneForConfiguration(char *s) {
} else {
SS.exportOffset = (float)ev;
}
- } else {
- Error("Not a valid number or expression: '%s'", s);
}
break;
}
case EDIT_CANVAS_SIZE: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(!e) {
- Error("Not a valid number or expression: '%s'", s);
break;
}
float d = (float)SS.ExprToMm(e);
diff --git a/draw.cpp b/draw.cpp
index 183f224e..d4e5b210 100644
--- a/draw.cpp
+++ b/draw.cpp
@@ -429,7 +429,16 @@ Vector GraphicsWindow::UnProjectPoint(Point2d p) {
}
void GraphicsWindow::NormalizeProjectionVectors(void) {
+ if(projRight.Magnitude() < LENGTH_EPS) {
+ projRight = Vector::From(1, 0, 0);
+ }
+
Vector norm = projRight.Cross(projUp);
+ // If projRight and projUp somehow ended up parallel, then pick an
+ // arbitrary projUp normal to projRight.
+ if(norm.Magnitude() < LENGTH_EPS) {
+ norm = projRight.Normal(0);
+ }
projUp = norm.Cross(projRight);
projUp = projUp.WithMagnitude(1);
@@ -762,12 +771,12 @@ nogrid:;
glEnd();
}
- if(pending.drawLine) {
+ if(SS.extraLine.draw) {
glLineWidth(1);
glxLockColorTo(Style::Color(Style::DATUM));
glBegin(GL_LINES);
- glxVertex3v(pending.lnA);
- glxVertex3v(pending.lnB);
+ glxVertex3v(SS.extraLine.ptA);
+ glxVertex3v(SS.extraLine.ptB);
glEnd();
}
diff --git a/expr.cpp b/expr.cpp
index 6c046010..fe9df8e6 100644
--- a/expr.cpp
+++ b/expr.cpp
@@ -763,7 +763,7 @@ void Expr::Lex(char *in) {
}
}
-Expr *Expr::From(char *in) {
+Expr *Expr::From(char *in, bool popUpError) {
UnparsedCnt = 0;
UnparsedP = 0;
OperandsP = 0;
@@ -776,6 +776,9 @@ Expr *Expr::From(char *in) {
r = PopOperand();
} catch (char *e) {
dbp("exception: parse/lex error: %s", e);
+ if(popUpError) {
+ Error("Not a valid number or expression: '%s'", in);
+ }
return NULL;
}
return r;
diff --git a/expr.h b/expr.h
index 06f47b2d..6e4564bb 100644
--- a/expr.h
+++ b/expr.h
@@ -105,7 +105,7 @@ public:
Expr *DeepCopyWithParamsAsPointers(IdList *firstTry,
IdList *thenTry);
- static Expr *From(char *in);
+ static Expr *From(char *in, bool popUpError);
static void Lex(char *in);
static Expr *Next(void);
static void Consume(void);
diff --git a/graphicswin.cpp b/graphicswin.cpp
index 82547411..a733ac3b 100644
--- a/graphicswin.cpp
+++ b/graphicswin.cpp
@@ -342,6 +342,7 @@ void GraphicsWindow::MenuView(int id) {
case MNU_ZOOM_TO_FIT:
SS.GW.ZoomToFit(false);
+ SS.later.showTW = true;
break;
case MNU_SHOW_GRID:
@@ -521,6 +522,7 @@ void GraphicsWindow::EnsureValidActives(void) {
break;
default:
SS.viewUnits = SolveSpace::UNIT_MM;
+ break;
}
CheckMenuById(MNU_UNITS_MM, SS.viewUnits == SolveSpace::UNIT_MM);
CheckMenuById(MNU_UNITS_INCHES, SS.viewUnits == SolveSpace::UNIT_INCHES);
diff --git a/mouse.cpp b/mouse.cpp
index 8b8bbabd..8939a74a 100644
--- a/mouse.cpp
+++ b/mouse.cpp
@@ -79,7 +79,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
if(GraphicsEditControlIsVisible()) return;
if(context.active) return;
- pending.drawLine = false;
+ SS.extraLine.draw = false;
if(!orig.mouseDown) {
// If someone drags the mouse into our window with the left button
@@ -133,9 +133,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
} else if(ctrlDown) {
double theta = atan2(orig.mouse.y, orig.mouse.x);
theta -= atan2(y, x);
- pending.drawLine = true;
- pending.lnA = UnProjectPoint(Point2d::From(0, 0));
- pending.lnB = UnProjectPoint(mp);
+ SS.extraLine.draw = true;
+ SS.extraLine.ptA = UnProjectPoint(Point2d::From(0, 0));
+ SS.extraLine.ptB = UnProjectPoint(mp);
Vector normal = orig.projRight.Cross(orig.projUp);
projRight = orig.projRight.RotatedAbout(normal, theta);
@@ -154,7 +154,13 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
orig.mouse.x = x;
orig.mouse.y = y;
+ if(SS.TW.shown.screen == TextWindow::SCREEN_EDIT_VIEW) {
+ if(havePainted) {
+ SS.later.showTW = true;
+ }
+ }
InvalidateGraphics();
+ havePainted = false;
return;
}
@@ -246,9 +252,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
// no sense solving a frame and not displaying it.
if(!havePainted) {
if(pending.operation == DRAGGING_POINTS && ctrlDown) {
- pending.lnA = UnProjectPoint(orig.mouseOnButtonDown);
- pending.lnB = UnProjectPoint(mp);
- pending.drawLine = true;
+ SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
+ SS.extraLine.ptB = UnProjectPoint(mp);
+ SS.extraLine.draw = true;
}
return;
}
@@ -293,9 +299,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
Vector gn = projRight.Cross(projUp);
qt = Quaternion::From(gn, -theta);
- pending.drawLine = true;
- pending.lnA = UnProjectPoint(orig.mouseOnButtonDown);
- pending.lnB = UnProjectPoint(mp);
+ SS.extraLine.draw = true;
+ SS.extraLine.ptA = UnProjectPoint(orig.mouseOnButtonDown);
+ SS.extraLine.ptB = UnProjectPoint(mp);
} else {
double dx = -(x - orig.mouse.x);
double dy = -(y - orig.mouse.y);
@@ -312,9 +318,9 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
if(e->type != Entity::POINT_N_ROT_TRANS) {
if(ctrlDown) {
Vector p = e->PointGetNum();
- p = p.Minus(pending.lnA);
+ p = p.Minus(SS.extraLine.ptA);
p = qt.Rotate(p);
- p = p.Plus(pending.lnA);
+ p = p.Plus(SS.extraLine.ptA);
e->PointForceTo(p);
SS.MarkGroupDirtyByEntity(e->h);
}
@@ -478,7 +484,7 @@ void GraphicsWindow::ContextMenuListStyles(void) {
}
void GraphicsWindow::MouseRightUp(double x, double y) {
- pending.drawLine = false;
+ SS.extraLine.draw = false;
InvalidateGraphics();
// Don't show a context menu if the user is right-clicking the toolbar,
@@ -1134,7 +1140,7 @@ void GraphicsWindow::EditControlDone(char *s) {
return;
}
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(e) {
SS.UndoRemember();
@@ -1167,8 +1173,6 @@ void GraphicsWindow::EditControlDone(char *s) {
}
SS.MarkGroupDirty(c->group);
SS.GenerateAll();
- } else {
- Error("Not a valid number or expression: '%s'", s);
}
}
@@ -1201,6 +1205,12 @@ void GraphicsWindow::MouseScroll(double x, double y, int delta) {
offset = offset.Plus(projRight.ScaledBy(rightf - righti));
offset = offset.Plus(projUp.ScaledBy(upf - upi));
+ if(SS.TW.shown.screen == TextWindow::SCREEN_EDIT_VIEW) {
+ if(havePainted) {
+ SS.later.showTW = true;
+ }
+ }
+ havePainted = false;
InvalidateGraphics();
}
diff --git a/solvespace.cpp b/solvespace.cpp
index 377e9f9d..2e8eb5a7 100644
--- a/solvespace.cpp
+++ b/solvespace.cpp
@@ -199,6 +199,20 @@ void SolveSpace::DoLater(void) {
ZERO(&later);
}
+double SolveSpace::MmPerUnit(void) {
+ if(viewUnits == UNIT_INCHES) {
+ return 25.4;
+ } else {
+ return 1.0;
+ }
+}
+char *SolveSpace::UnitName(void) {
+ if(viewUnits == UNIT_INCHES) {
+ return "inch";
+ } else {
+ return "mm";
+ }
+}
char *SolveSpace::MmToString(double v) {
static int WhichBuf;
static char Bufs[8][128];
@@ -215,18 +229,10 @@ char *SolveSpace::MmToString(double v) {
return s;
}
double SolveSpace::ExprToMm(Expr *e) {
- if(viewUnits == UNIT_INCHES) {
- return (e->Eval())*25.4;
- } else {
- return e->Eval();
- }
+ return (e->Eval()) * MmPerUnit();
}
double SolveSpace::StringToMm(char *str) {
- if(viewUnits == UNIT_INCHES) {
- return atof(str)*25.4;
- } else {
- return atof(str);
- }
+ return atof(str) * MmPerUnit();
}
double SolveSpace::ChordTolMm(void) {
return SS.chordTol / SS.GW.scale;
diff --git a/solvespace.h b/solvespace.h
index 139bbea4..c281f323 100644
--- a/solvespace.h
+++ b/solvespace.h
@@ -609,6 +609,8 @@ public:
char *MmToString(double v);
double ExprToMm(Expr *e);
double StringToMm(char *s);
+ char *UnitName(void);
+ double MmPerUnit(void);
double ChordTolMm(void);
bool forceParallelProj;
double CameraTangent(void);
@@ -677,6 +679,11 @@ public:
hEntity point;
} traced;
SEdgeList nakedEdges;
+ struct {
+ bool draw;
+ Vector ptA;
+ Vector ptB;
+ } extraLine;
struct {
BYTE *fromFile;
int w, h;
diff --git a/style.cpp b/style.cpp
index f3bd5aa0..372e5f69 100644
--- a/style.cpp
+++ b/style.cpp
@@ -404,9 +404,7 @@ err:
void TextWindow::ScreenChangeBackgroundImageScale(int link, DWORD v) {
char str[300];
- sprintf(str, "%.3f",
- (SS.viewUnits == SolveSpace::UNIT_MM) ? SS.bgImage.scale :
- SS.bgImage.scale * 25.4);
+ sprintf(str, "%.3f", SS.bgImage.scale * SS.MmPerUnit());
SS.TW.edit.meaning = EDIT_BACKGROUND_IMG_SCALE;
ShowTextEditControl(v, 10, str);
}
@@ -443,15 +441,12 @@ void TextWindow::ShowListOfStyles(void) {
if(SS.bgImage.fromFile) {
Printf(false, "%Ba %Ftwidth:%E %dpx %Ftheight:%E %dpx",
SS.bgImage.w, SS.bgImage.h);
- if(SS.viewUnits == SolveSpace::UNIT_MM) {
- Printf(false, " %Ftscale:%E %# px/mm %Fl%Ll%f%D[change]%E",
- SS.bgImage.scale,
- &ScreenChangeBackgroundImageScale, top[rows-1] + 2);
- } else {
- Printf(false, " %Ftscale:%E %# px/inch %Fl%Ll%f%D[change]%E",
- SS.bgImage.scale*25.4,
- &ScreenChangeBackgroundImageScale, top[rows-1] + 2);
- }
+
+ Printf(false, " %Ftscale:%E %# px/%s %Fl%Ll%f%D[change]%E",
+ SS.bgImage.scale*SS.MmPerUnit(),
+ SS.UnitName(),
+ &ScreenChangeBackgroundImageScale, top[rows-1] + 2);
+
Printf(false, "%Ba %Fl%Lc%fclear background image%E",
&ScreenBackgroundImage);
} else {
@@ -682,18 +677,14 @@ bool TextWindow::EditControlDoneForStyles(char *str) {
break;
case EDIT_BACKGROUND_IMG_SCALE: {
- Expr *e = Expr::From(str);
+ Expr *e = Expr::From(str, true);
if(e) {
double ev = e->Eval();
if(ev < 0.001 || isnan(ev)) {
Error("Scale must not be zero or negative!");
} else {
- SS.bgImage.scale =
- (SS.viewUnits == SolveSpace::UNIT_MM) ? ev :
- ev / 25.4;
+ SS.bgImage.scale = ev / SS.MmPerUnit();
}
- } else {
- Error("Not a valid number or expression: '%s'", str);
}
break;
}
@@ -722,8 +713,6 @@ void TextWindow::ShowStyleInfo(void) {
REDf(s->color), GREENf(s->color), BLUEf(s->color),
s->h.v, ScreenChangeStyleColor);
- 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%Lp%Fl[change]%E",
@@ -747,8 +736,8 @@ void TextWindow::ShowStyleInfo(void) {
( widthpx ? "" : "pixels"),
( widthpx ? "pixels" : ""),
s->h.v, &ScreenChangeStyleYesNo,
- (!widthpx ? "" : unit),
- (!widthpx ? unit : ""));
+ (!widthpx ? "" : SS.UnitName()),
+ (!widthpx ? SS.UnitName() : ""));
}
if(s->h.v >= Style::FIRST_CUSTOM) {
@@ -793,8 +782,8 @@ void TextWindow::ShowStyleInfo(void) {
( textHeightpx ? "" : "pixels"),
( textHeightpx ? "pixels" : ""),
s->h.v, &ScreenChangeStyleYesNo,
- (!textHeightpx ? "" : unit),
- (!textHeightpx ? unit : ""));
+ (!textHeightpx ? "" : SS.UnitName()),
+ (!textHeightpx ? SS.UnitName() : ""));
}
if(s->h.v >= Style::FIRST_CUSTOM) {
diff --git a/textscreens.cpp b/textscreens.cpp
index a2e96f17..8d66ecc6 100644
--- a/textscreens.cpp
+++ b/textscreens.cpp
@@ -100,6 +100,9 @@ void TextWindow::ScreenHowGroupSolved(int link, DWORD v) {
void TextWindow::ScreenShowConfiguration(int link, DWORD v) {
SS.TW.GoToScreen(SCREEN_CONFIGURATION);
}
+void TextWindow::ScreenShowEditView(int link, DWORD v) {
+ SS.TW.GoToScreen(SCREEN_EDIT_VIEW);
+}
void TextWindow::ScreenGoToWebsite(int link, DWORD v) {
OpenWebsite("http://solvespace.com/txtlink");
}
@@ -143,8 +146,11 @@ void TextWindow::ShowListOfGroups(void) {
Printf(true, " %Fl%Ls%fshow all%E / %Fl%Lh%fhide all%E",
&(TextWindow::ScreenShowGroupsSpecial),
&(TextWindow::ScreenShowGroupsSpecial));
- Printf(true, " %Fl%Ls%fline styles%E / %Fl%Ls%fconfiguration%E",
+ Printf(true, " %Fl%Ls%fline styles%E /"
+ " %Fl%Ls%fview%E /"
+ " %Fl%Ls%fconfiguration%E",
&(TextWindow::ScreenShowListOfStyles),
+ &(TextWindow::ScreenShowEditView),
&(TextWindow::ScreenShowConfiguration));
// Show license info
@@ -674,10 +680,11 @@ void TextWindow::ShowStepDimension(void) {
void TextWindow::ShowMeshVolume(void) {
Printf(true, "%FtMESH VOLUME");
- if(SS.viewUnits == SolveSpace::UNIT_INCHES) {
- Printf(true, " %3 in^3", shown.volume/(25.4*25.4*25.4));
- } else {
- Printf(true, " %2 mm^3", shown.volume);
+ Printf(true, " %3 %s^3",
+ shown.volume / pow(SS.MmPerUnit(), 3),
+ SS.UnitName());
+
+ if(SS.viewUnits == SolveSpace::UNIT_MM) {
Printf(false, " %2 mL", shown.volume/(10*10*10));
}
@@ -688,9 +695,11 @@ void TextWindow::ShowMeshVolume(void) {
// The edit control is visible, and the user just pressed enter.
//-----------------------------------------------------------------------------
void TextWindow::EditControlDone(char *s) {
+ edit.showAgain = false;
+
switch(edit.meaning) {
case EDIT_TIMES_REPEATED: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(e) {
SS.UndoRemember();
@@ -721,8 +730,6 @@ void TextWindow::EditControlDone(char *s) {
SS.MarkGroupDirty(g->h);
SS.later.generateAll = true;
- } else {
- Error("Not a valid number or expression: '%s'", s);
}
break;
}
@@ -738,7 +745,7 @@ void TextWindow::EditControlDone(char *s) {
break;
}
case EDIT_GROUP_SCALE: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(e) {
double ev = e->Eval();
if(fabs(ev) < 1e-6) {
@@ -749,8 +756,6 @@ void TextWindow::EditControlDone(char *s) {
SS.MarkGroupDirty(g->h);
SS.later.generateAll = true;
}
- } else {
- Error("Not a valid number or expression: '%s'", s);
}
break;
}
@@ -759,9 +764,8 @@ void TextWindow::EditControlDone(char *s) {
case EDIT_HELIX_DRADIUS: {
SS.UndoRemember();
Group *g = SK.GetGroup(edit.group);
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(!e) {
- Error("Not a valid number or expression: '%s'", s);
break;
}
if(edit.meaning == EDIT_HELIX_TURNS) {
@@ -786,9 +790,8 @@ void TextWindow::EditControlDone(char *s) {
break;
}
case EDIT_STEP_DIM_FINISH: {
- Expr *e = Expr::From(s);
+ Expr *e = Expr::From(s, true);
if(!e) {
- Error("Not a valid number or expression: '%s'", s);
break;
}
if(shown.dimIsDistance) {
@@ -807,6 +810,7 @@ void TextWindow::EditControlDone(char *s) {
if(EditControlDoneForStyles(s)) cnt++;
if(EditControlDoneForConfiguration(s)) cnt++;
if(EditControlDoneForPaste(s)) cnt++;
+ if(EditControlDoneForView(s)) cnt++;
if(cnt > 1) {
// The identifiers were somehow assigned not uniquely?
oops();
@@ -816,7 +820,10 @@ void TextWindow::EditControlDone(char *s) {
}
InvalidateGraphics();
SS.later.showTW = true;
- HideTextEditControl();
- edit.meaning = EDIT_NOTHING;
+
+ if(!edit.showAgain) {
+ HideTextEditControl();
+ edit.meaning = EDIT_NOTHING;
+ }
}
diff --git a/textwin.cpp b/textwin.cpp
index ea8bf6e5..d1140d73 100644
--- a/textwin.cpp
+++ b/textwin.cpp
@@ -238,6 +238,7 @@ void TextWindow::Show(void) {
case SCREEN_LIST_OF_STYLES: ShowListOfStyles(); break;
case SCREEN_STYLE_INFO: ShowStyleInfo(); break;
case SCREEN_PASTE_TRANSFORMED: ShowPasteTransformed(); break;
+ case SCREEN_EDIT_VIEW: ShowEditView(); break;
}
}
Printf(false, "");
diff --git a/ui.h b/ui.h
index 31b38218..c57e1bdc 100644
--- a/ui.h
+++ b/ui.h
@@ -55,6 +55,7 @@ public:
static const int SCREEN_LIST_OF_STYLES = 6;
static const int SCREEN_STYLE_INFO = 7;
static const int SCREEN_PASTE_TRANSFORMED = 8;
+ static const int SCREEN_EDIT_VIEW = 9;
typedef struct {
int screen;
@@ -116,7 +117,13 @@ public:
static const int EDIT_PASTE_TIMES_REPEATED = 60;
static const int EDIT_PASTE_ANGLE = 61;
static const int EDIT_PASTE_SCALE = 62;
+ // For view
+ static const int EDIT_VIEW_SCALE = 70;
+ static const int EDIT_VIEW_ORIGIN = 71;
+ static const int EDIT_VIEW_PROJ_RIGHT = 72;
+ static const int EDIT_VIEW_PROJ_UP = 73;
struct {
+ bool showAgain;
int meaning;
int i;
hGroup group;
@@ -140,6 +147,7 @@ public:
void ShowStepDimension(void);
void ShowMeshVolume(void);
void ShowPasteTransformed(void);
+ void ShowEditView(void);
// Special screen, based on selection
void DescribeSelection(void);
@@ -179,6 +187,7 @@ public:
static void ScreenBackgroundImage(int link, DWORD v);
static void ScreenShowConfiguration(int link, DWORD v);
+ static void ScreenShowEditView(int link, DWORD v);
static void ScreenGoToWebsite(int link, DWORD v);
static void ScreenChangeFixExportColors(int link, DWORD v);
@@ -217,10 +226,14 @@ public:
static void ScreenChangeBackgroundColor(int link, DWORD v);
static void ScreenChangeBackgroundImageScale(int link, DWORD v);
static void ScreenChangePasteTransformed(int link, DWORD v);
+ static void ScreenChangeViewScale(int link, DWORD v);
+ static void ScreenChangeViewOrigin(int link, DWORD v);
+ static void ScreenChangeViewProjection(int link, DWORD v);
bool EditControlDoneForStyles(char *s);
bool EditControlDoneForConfiguration(char *s);
bool EditControlDoneForPaste(char *s);
+ bool EditControlDoneForView(char *s);
void EditControlDone(char *s);
};
@@ -413,9 +426,6 @@ public:
hEntity normal;
hConstraint constraint;
- bool drawLine;
- Vector lnA, lnB;
-
char *description;
} pending;
void ClearPending(void);
diff --git a/view.cpp b/view.cpp
new file mode 100644
index 00000000..fd247662
--- /dev/null
+++ b/view.cpp
@@ -0,0 +1,109 @@
+#include "solvespace.h"
+
+void TextWindow::ShowEditView(void) {
+ Printf(true, "%Ft3D VIEW PARAMETERS%E");
+
+ Printf(true, "%Bd %Ftoverall scale factor%E");
+ Printf(false, "%Ba %# px/%s %Fl%Ll%f[edit]%E",
+ SS.GW.scale * SS.MmPerUnit(),
+ SS.UnitName(),
+ &ScreenChangeViewScale);
+ Printf(false, "");
+
+ Printf(false, "%Bd %Ftorigin (maps to center of screen)%E");
+ Printf(false, "%Ba (%s, %s, %s) %Fl%Ll%f[edit]%E",
+ SS.MmToString(-SS.GW.offset.x),
+ SS.MmToString(-SS.GW.offset.y),
+ SS.MmToString(-SS.GW.offset.z),
+ &ScreenChangeViewOrigin);
+ Printf(false, "");
+
+ Vector n = (SS.GW.projRight).Cross(SS.GW.projUp);
+ Printf(false, "%Bd %Ftprojection onto screen%E");
+ Printf(false, "%Ba %Ftright%E (%3, %3, %3) %Fl%Ll%f[edit]%E",
+ CO(SS.GW.projRight),
+ &ScreenChangeViewProjection);
+ Printf(false, "%Ba %Ftup%E (%3, %3, %3)", CO(SS.GW.projUp));
+ Printf(false, "%Ba %Ftout%E (%3, %3, %3)", CO(n));
+ Printf(false, "");
+
+ Printf(false, "The perspective may be changed in the");
+ Printf(false, "configuration screen.");
+}
+
+void TextWindow::ScreenChangeViewScale(int link, DWORD v) {
+ char buf[1024];
+ sprintf(buf, "%.3f", SS.GW.scale * SS.MmPerUnit());
+
+ SS.TW.edit.meaning = EDIT_VIEW_SCALE;
+ ShowTextEditControl(12, 3, buf);
+}
+
+void TextWindow::ScreenChangeViewOrigin(int link, DWORD v) {
+ char buf[1024];
+ sprintf(buf, "%s, %s, %s",
+ SS.MmToString(-SS.GW.offset.x),
+ SS.MmToString(-SS.GW.offset.y),
+ SS.MmToString(-SS.GW.offset.z));
+
+ SS.TW.edit.meaning = EDIT_VIEW_ORIGIN;
+ ShowTextEditControl(18, 3, buf);
+}
+
+void TextWindow::ScreenChangeViewProjection(int link, DWORD v) {
+ char buf[1024];
+ sprintf(buf, "%.3f, %.3f, %.3f", CO(SS.GW.projRight));
+ SS.TW.edit.meaning = EDIT_VIEW_PROJ_RIGHT;
+ ShowTextEditControl(24, 10, buf);
+}
+
+bool TextWindow::EditControlDoneForView(char *s) {
+ switch(edit.meaning) {
+ case EDIT_VIEW_SCALE: {
+ Expr *e = Expr::From(s, true);
+ if(e) {
+ SS.GW.scale = e->Eval() / SS.MmPerUnit();
+ }
+ break;
+ }
+
+ case EDIT_VIEW_ORIGIN: {
+ Vector pt;
+ if(sscanf(s, "%lf, %lf, %lf", &pt.x, &pt.y, &pt.z) == 3) {
+ pt = pt.ScaledBy(SS.MmPerUnit());
+ SS.GW.offset = pt.ScaledBy(-1);
+ } else {
+ Error("Bad format: specify x, y, z");
+ }
+ break;
+ }
+
+ case EDIT_VIEW_PROJ_RIGHT:
+ case EDIT_VIEW_PROJ_UP: {
+ Vector pt;
+ if(sscanf(s, "%lf, %lf, %lf", &pt.x, &pt.y, &pt.z) != 3) {
+ Error("Bad format: specify x, y, z");
+ break;
+ }
+ if(edit.meaning == EDIT_VIEW_PROJ_RIGHT) {
+ SS.GW.projRight = pt;
+ SS.GW.NormalizeProjectionVectors();
+ edit.meaning = EDIT_VIEW_PROJ_UP;
+ char buf[1024];
+ sprintf(buf, "%.3f, %.3f, %.3f", CO(SS.GW.projUp));
+ HideTextEditControl();
+ ShowTextEditControl(26, 10, buf);
+ edit.showAgain = true;
+ } else {
+ SS.GW.projUp = pt;
+ SS.GW.NormalizeProjectionVectors();
+ }
+ break;
+ }
+
+ default:
+ return false;
+ }
+ return true;
+}
+
diff --git a/wishlist.txt b/wishlist.txt
index 7fb36790..339bf0d3 100644
--- a/wishlist.txt
+++ b/wishlist.txt
@@ -1,6 +1,4 @@
-show and modify view parameters (translate, rotate, scale)
-
-----
associative entities from solid model, as a special group
some kind of import