Rename some stuff in the IdList again. Rough in the file save
stuff, though no file load stuff, and perhaps this can all be made to work from a table somehow. Move the quaternion stuff into its own class, and add a fancy animated view when you orient onto a csys. [git-p4: depot-paths = "//depot/solvespace/": change = 1672]
This commit is contained in:
parent
c097fea4f3
commit
0d3217c0df
1
Makefile
1
Makefile
|
@ -19,6 +19,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
|
||||||
$(OBJDIR)\expr.obj \
|
$(OBJDIR)\expr.obj \
|
||||||
$(OBJDIR)\constraint.obj \
|
$(OBJDIR)\constraint.obj \
|
||||||
$(OBJDIR)\drawconstraint.obj \
|
$(OBJDIR)\drawconstraint.obj \
|
||||||
|
$(OBJDIR)\file.obj \
|
||||||
|
|
||||||
|
|
||||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib
|
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib
|
||||||
|
|
54
dsc.h
54
dsc.h
|
@ -5,6 +5,28 @@
|
||||||
typedef unsigned long DWORD;
|
typedef unsigned long DWORD;
|
||||||
typedef unsigned char BYTE;
|
typedef unsigned char BYTE;
|
||||||
|
|
||||||
|
class Vector;
|
||||||
|
|
||||||
|
class Quaternion {
|
||||||
|
public:
|
||||||
|
// a + bi + cj + dk
|
||||||
|
double a, b, c, d;
|
||||||
|
|
||||||
|
static Quaternion MakeFrom(double a, double b, double c, double d);
|
||||||
|
static Quaternion MakeFrom(Vector u, Vector v);
|
||||||
|
|
||||||
|
Quaternion Plus(Quaternion y);
|
||||||
|
Quaternion Minus(Quaternion y);
|
||||||
|
Quaternion ScaledBy(double s);
|
||||||
|
double Magnitude(void);
|
||||||
|
Quaternion WithMagnitude(double s);
|
||||||
|
|
||||||
|
// Call a rotation matrix [ u' v' n' ]'; this returns the first and
|
||||||
|
// second rows, where that matrix is generated by this quaternion
|
||||||
|
Vector RotationU(void);
|
||||||
|
Vector RotationV(void);
|
||||||
|
};
|
||||||
|
|
||||||
class Vector {
|
class Vector {
|
||||||
public:
|
public:
|
||||||
double x, y, z;
|
double x, y, z;
|
||||||
|
@ -21,12 +43,6 @@ public:
|
||||||
double Magnitude(void);
|
double Magnitude(void);
|
||||||
Vector WithMagnitude(double s);
|
Vector WithMagnitude(double s);
|
||||||
Vector ScaledBy(double s);
|
Vector ScaledBy(double s);
|
||||||
|
|
||||||
// Call a rotation matrix [ u' v' n' ]'; this returns the first and
|
|
||||||
// second rows, where that matrix is generated by the given quaternion
|
|
||||||
// a + bi + cj + dk
|
|
||||||
static Vector RotationU(double a, double b, double c, double d);
|
|
||||||
static Vector RotationV(double a, double b, double c, double d);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Point2d {
|
class Point2d {
|
||||||
|
@ -44,14 +60,14 @@ template <class T, class H>
|
||||||
class IdList {
|
class IdList {
|
||||||
public:
|
public:
|
||||||
T *elem;
|
T *elem;
|
||||||
int elems;
|
int n;
|
||||||
int elemsAllocated;
|
int elemsAllocated;
|
||||||
|
|
||||||
H AddAndAssignId(T *t) {
|
H AddAndAssignId(T *t) {
|
||||||
int i;
|
int i;
|
||||||
DWORD id = 0;
|
DWORD id = 0;
|
||||||
|
|
||||||
for(i = 0; i < elems; i++) {
|
for(i = 0; i < n; i++) {
|
||||||
id = max(id, elem[i].h.v);
|
id = max(id, elem[i].h.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,20 +78,20 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Add(T *t) {
|
void Add(T *t) {
|
||||||
if(elems >= elemsAllocated) {
|
if(n >= elemsAllocated) {
|
||||||
elemsAllocated = (elemsAllocated + 32)*2;
|
elemsAllocated = (elemsAllocated + 32)*2;
|
||||||
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
|
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
|
||||||
if(!elem) oops();
|
if(!elem) oops();
|
||||||
}
|
}
|
||||||
|
|
||||||
elem[elems] = *t;
|
elem[n] = *t;
|
||||||
elems++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *FindById(H h) {
|
T *FindById(H h) {
|
||||||
T *t = FindByIdNoOops(h);
|
T *t = FindByIdNoOops(h);
|
||||||
if(!t) {
|
if(!t) {
|
||||||
dbp("failed to look up item %16lx, searched %d items", h.v, elems);
|
dbp("failed to look up item %16lx, searched %d items", h.v, n);
|
||||||
oops();
|
oops();
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
@ -83,7 +99,7 @@ public:
|
||||||
|
|
||||||
T *FindByIdNoOops(H h) {
|
T *FindByIdNoOops(H h) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < elems; i++) {
|
for(i = 0; i < n; i++) {
|
||||||
if(elem[i].h.v == h.v) {
|
if(elem[i].h.v == h.v) {
|
||||||
return &(elem[i]);
|
return &(elem[i]);
|
||||||
}
|
}
|
||||||
|
@ -93,14 +109,14 @@ public:
|
||||||
|
|
||||||
void ClearTags(void) {
|
void ClearTags(void) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < elems; i++) {
|
for(i = 0; i < n; i++) {
|
||||||
elem[i].tag = 0;
|
elem[i].tag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tag(H h, int tag) {
|
void Tag(H h, int tag) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < elems; i++) {
|
for(i = 0; i < n; i++) {
|
||||||
if(elem[i].h.v == h.v) {
|
if(elem[i].h.v == h.v) {
|
||||||
elem[i].tag = tag;
|
elem[i].tag = tag;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +126,7 @@ public:
|
||||||
void RemoveTagged(void) {
|
void RemoveTagged(void) {
|
||||||
int src, dest;
|
int src, dest;
|
||||||
dest = 0;
|
dest = 0;
|
||||||
for(src = 0; src < elems; src++) {
|
for(src = 0; src < n; src++) {
|
||||||
if(elem[src].tag) {
|
if(elem[src].tag) {
|
||||||
// this item should be deleted
|
// this item should be deleted
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,18 +136,18 @@ public:
|
||||||
dest++;
|
dest++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elems = dest;
|
n = dest;
|
||||||
// and elemsAllocated is untouched, because we didn't resize
|
// and elemsAllocated is untouched, because we didn't resize
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveSelfInto(IdList<T,H> *l) {
|
void MoveSelfInto(IdList<T,H> *l) {
|
||||||
memcpy(l, this, sizeof(*this));
|
memcpy(l, this, sizeof(*this));
|
||||||
elemsAllocated = elems = 0;
|
elemsAllocated = n = 0;
|
||||||
elem = NULL;
|
elem = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear(void) {
|
void Clear(void) {
|
||||||
elemsAllocated = elems = 0;
|
elemsAllocated = n = 0;
|
||||||
if(elem) free(elem);
|
if(elem) free(elem);
|
||||||
elem = NULL;
|
elem = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,10 @@ void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) {
|
||||||
for(int i = 0; i < 4; i++) {
|
for(int i = 0; i < 4; i++) {
|
||||||
q[i] = SS.param.FindById(param(i))->val;
|
q[i] = SS.param.FindById(param(i))->val;
|
||||||
}
|
}
|
||||||
|
Quaternion quat = Quaternion::MakeFrom(q[0], q[1], q[2], q[3]);
|
||||||
|
|
||||||
*u = Vector::RotationU(q[0], q[1], q[2], q[3]);
|
*u = quat.RotationU();
|
||||||
*v = Vector::RotationV(q[0], q[1], q[2], q[3]);
|
*v = quat.RotationV();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||||
|
|
3
expr.cpp
3
expr.cpp
|
@ -130,6 +130,8 @@ void Expr::App(char *s, ...) {
|
||||||
vsprintf(StringBuffer+strlen(StringBuffer), s, f);
|
vsprintf(StringBuffer+strlen(StringBuffer), s, f);
|
||||||
}
|
}
|
||||||
char *Expr::Print(void) {
|
char *Expr::Print(void) {
|
||||||
|
if(!this) return "0";
|
||||||
|
|
||||||
StringBuffer[0] = '\0';
|
StringBuffer[0] = '\0';
|
||||||
PrintW();
|
PrintW();
|
||||||
return StringBuffer;
|
return StringBuffer;
|
||||||
|
@ -356,6 +358,7 @@ void Expr::Lex(char *in) {
|
||||||
|
|
||||||
Expr *Expr::FromString(char *in) {
|
Expr *Expr::FromString(char *in) {
|
||||||
UnparsedCnt = 0;
|
UnparsedCnt = 0;
|
||||||
|
UnparsedP = 0;
|
||||||
OperandsP = 0;
|
OperandsP = 0;
|
||||||
OperatorsP = 0;
|
OperatorsP = 0;
|
||||||
|
|
||||||
|
|
84
file.cpp
Normal file
84
file.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include "solvespace.h"
|
||||||
|
|
||||||
|
bool SolveSpace::SaveToFile(char *filename) {
|
||||||
|
fh = fopen(filename, "w");
|
||||||
|
if(!fh) {
|
||||||
|
Error("Couldn't write to file '%s'", fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fh, "!!SolveSpaceREVa\n\n\n");
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < group.n; i++) {
|
||||||
|
Group *g = &(group.elem[i]);
|
||||||
|
fprintf(fh, "Group.h.v=%08x\n", g->h.v);
|
||||||
|
fprintf(fh, "Group.name=%s\n", g->name.str);
|
||||||
|
fprintf(fh, "AddGroup\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < param.n; i++) {
|
||||||
|
Param *p = &(param.elem[i]);
|
||||||
|
fprintf(fh, "Param.h.v=%08x\n", p->h.v);
|
||||||
|
fprintf(fh, "Param.val=%.20f\n", p->val);
|
||||||
|
fprintf(fh, "AddParam\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < request.n; i++) {
|
||||||
|
Request *r = &(request.elem[i]);
|
||||||
|
fprintf(fh, "Request.h.v=%08x\n", r->h.v);
|
||||||
|
fprintf(fh, "Request.type=%d\n", r->type);
|
||||||
|
fprintf(fh, "Request.csys.v=%08x\n", r->csys.v);
|
||||||
|
fprintf(fh, "Request.group.v=%08x\n", r->group.v);
|
||||||
|
fprintf(fh, "Request.name=%s\n", r->name.str);
|
||||||
|
fprintf(fh, "AddRequest\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < entity.n; i++) {
|
||||||
|
Entity *e = &(entity.elem[i]);
|
||||||
|
fprintf(fh, "Entity.h.v=%08x\n", e->h.v);
|
||||||
|
fprintf(fh, "Entity.type=%d\n", e->type);
|
||||||
|
fprintf(fh, "AddEntity\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < point.n; i++) {
|
||||||
|
Point *p = &(point.elem[i]);
|
||||||
|
fprintf(fh, "Point.h.v=%08x\n", p->h.v);
|
||||||
|
fprintf(fh, "Point.type=%d\n", p->type);
|
||||||
|
fprintf(fh, "Point.csys.v=%08x\n", p->csys.v);
|
||||||
|
fprintf(fh, "AddPoint\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < constraint.n; i++) {
|
||||||
|
Constraint *c = &(constraint.elem[i]);
|
||||||
|
fprintf(fh, "Constraint.h.v=%08x\n", c->h.v);
|
||||||
|
fprintf(fh, "Constraint.type=%d\n", c->type);
|
||||||
|
fprintf(fh, "Constraint.group.v=%08x\n", c->group);
|
||||||
|
fprintf(fh, "Constraint.exprA=%s\n", c->exprA->Print());
|
||||||
|
fprintf(fh, "Constraint.exprB=%s\n", c->exprB->Print());
|
||||||
|
fprintf(fh, "Constraint.ptA.v=%08x\n", c->ptA.v);
|
||||||
|
fprintf(fh, "Constraint.ptB.v=%08x\n", c->ptB.v);
|
||||||
|
fprintf(fh, "Constraint.ptC.v=%08x\n", c->ptC.v);
|
||||||
|
fprintf(fh, "Constraint.entityA.v=%08x\n", c->entityA.v);
|
||||||
|
fprintf(fh, "Constraint.entityB.v=%08x\n", c->entityB.v);
|
||||||
|
fprintf(fh, "Constraint.disp.offset.x=%.20f\n", c->disp.offset.x);
|
||||||
|
fprintf(fh, "Constraint.disp.offset.y=%.20f\n", c->disp.offset.y);
|
||||||
|
fprintf(fh, "Constraint.disp.offset.z=%.20f\n", c->disp.offset.z);
|
||||||
|
fprintf(fh, "AddConstraint\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fh);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SolveSpace::LoadFromFile(char *filename) {
|
||||||
|
fh = fopen(filename, "r");
|
||||||
|
if(!fh) {
|
||||||
|
Error("Couldn't read from file '%s'", fh);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -6,15 +6,17 @@
|
||||||
#define mEdit (&GraphicsWindow::MenuEdit)
|
#define mEdit (&GraphicsWindow::MenuEdit)
|
||||||
#define mReq (&GraphicsWindow::MenuRequest)
|
#define mReq (&GraphicsWindow::MenuRequest)
|
||||||
#define mCon (&Constraint::MenuConstrain)
|
#define mCon (&Constraint::MenuConstrain)
|
||||||
|
#define mFile (&SolveSpace::MenuFile)
|
||||||
#define S 0x100
|
#define S 0x100
|
||||||
|
#define C 0x200
|
||||||
const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
{ 0, "&File", 0, NULL },
|
{ 0, "&File", 0, NULL },
|
||||||
{ 1, "&New\tCtrl+N", 0, NULL },
|
{ 1, "&New\tCtrl+N", MNU_NEW, 'N'|C, mFile },
|
||||||
{ 1, "&Open...\tCtrl+O", 0, NULL },
|
{ 1, "&Open...\tCtrl+O", MNU_OPEN, 'O'|C, mFile },
|
||||||
{ 1, "&Save\tCtrl+S", 0, NULL },
|
{ 1, "&Save\tCtrl+S", MNU_SAVE, 'S'|C, mFile },
|
||||||
{ 1, "Save &As...", 0, NULL },
|
{ 1, "Save &As...", MNU_SAVE_AS, 0, mFile },
|
||||||
{ 1, NULL, 0, NULL },
|
{ 1, NULL, 0, 0, NULL },
|
||||||
{ 1, "E&xit", 0, NULL },
|
{ 1, "E&xit", MNU_EXIT, 0, mFile },
|
||||||
|
|
||||||
{ 0, "&Edit", 0, NULL },
|
{ 0, "&Edit", 0, NULL },
|
||||||
{ 1, "&Undo\tCtrl+Z", 0, NULL },
|
{ 1, "&Undo\tCtrl+Z", 0, NULL },
|
||||||
|
@ -37,7 +39,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
|
|
||||||
{ 0, "&Request", 0, NULL },
|
{ 0, "&Request", 0, NULL },
|
||||||
{ 1, "Dra&w in 2d Coordinate System\tW", MNU_SEL_CSYS, 'W', mReq },
|
{ 1, "Dra&w in 2d Coordinate System\tW", MNU_SEL_CSYS, 'W', mReq },
|
||||||
{ 1, "Draw Anywhere in 3d\tF", MNU_NO_CSYS, 'Q', mReq },
|
{ 1, "Draw Anywhere in 3d\tQ", MNU_NO_CSYS, 'Q', mReq },
|
||||||
{ 1, NULL, 0, NULL },
|
{ 1, NULL, 0, NULL },
|
||||||
{ 1, "Datum &Point\tP", MNU_DATUM_POINT, 'P', mReq },
|
{ 1, "Datum &Point\tP", MNU_DATUM_POINT, 'P', mReq },
|
||||||
{ 1, "Datum A&xis\tX", 0, 'X', mReq },
|
{ 1, "Datum A&xis\tX", 0, 'X', mReq },
|
||||||
|
@ -132,18 +134,63 @@ void GraphicsWindow::MenuView(int id) {
|
||||||
CheckMenuById(MNU_LOCK_VIEW, SS.GW.viewLocked);
|
CheckMenuById(MNU_LOCK_VIEW, SS.GW.viewLocked);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MNU_ORIENT_ONTO:
|
case MNU_ORIENT_ONTO: {
|
||||||
SS.GW.GroupSelection();
|
SS.GW.GroupSelection();
|
||||||
|
Entity *e = NULL;
|
||||||
if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) {
|
if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) {
|
||||||
Entity *e = SS.entity.FindById(SS.GW.gs.entity[0]);
|
e = SS.entity.FindById(SS.GW.gs.entity[0]);
|
||||||
e->Get2dCsysBasisVectors( &(SS.GW.projRight), &(SS.GW.projUp));
|
} else if(SS.GW.activeCsys.v != Entity::NO_CSYS.v) {
|
||||||
SS.GW.offset = SS.point.FindById(e->point(16))->GetCoords();
|
e = SS.entity.FindById(SS.GW.activeCsys);
|
||||||
|
}
|
||||||
|
if(e) {
|
||||||
|
// A quaternion with our original rotation
|
||||||
|
Quaternion quat0 = Quaternion::MakeFrom(
|
||||||
|
SS.GW.projRight, SS.GW.projUp);
|
||||||
|
// And with our final rotation
|
||||||
|
Vector pr, pu;
|
||||||
|
e->Get2dCsysBasisVectors(&pr, &pu);
|
||||||
|
Quaternion quatf = Quaternion::MakeFrom(pr, pu);
|
||||||
|
// Make sure we take the shorter of the two possible paths.
|
||||||
|
double mp = (quatf.Minus(quat0)).Magnitude();
|
||||||
|
double mm = (quatf.Plus(quat0)).Magnitude();
|
||||||
|
if(mp > mm) {
|
||||||
|
quatf = quatf.ScaledBy(-1);
|
||||||
|
mp = mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And also get the offsets.
|
||||||
|
Vector offset0 = SS.GW.offset;
|
||||||
|
Vector offsetf = SS.point.FindById(e->point(16))->GetCoords();
|
||||||
|
|
||||||
|
// Animate transition, unless it's a tiny move.
|
||||||
|
SDWORD dt = (mp < 0.01) ? (-20) : (SDWORD)(100 + 1000*mp);
|
||||||
|
SDWORD tn, t0 = GetMilliseconds();
|
||||||
|
double s = 0;
|
||||||
|
do {
|
||||||
|
SS.GW.offset =
|
||||||
|
(offset0.ScaledBy(1 - s)).Plus(offsetf.ScaledBy(s));
|
||||||
|
Quaternion quat =
|
||||||
|
(quat0.ScaledBy(1 - s)).Plus(quatf.ScaledBy(s));
|
||||||
|
quat = quat.WithMagnitude(1);
|
||||||
|
SS.GW.projRight = quat.RotationU();
|
||||||
|
SS.GW.projUp = quat.RotationV();
|
||||||
|
PaintGraphics();
|
||||||
|
|
||||||
|
tn = GetMilliseconds();
|
||||||
|
s = (tn - t0)/((double)dt);
|
||||||
|
} while((tn - t0) < dt);
|
||||||
|
SS.GW.projRight = pr;
|
||||||
|
SS.GW.projUp = pu;
|
||||||
|
SS.GW.offset = offsetf;
|
||||||
|
|
||||||
|
SS.GW.hover.Clear();
|
||||||
SS.GW.ClearSelection();
|
SS.GW.ClearSelection();
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
} else {
|
} else {
|
||||||
Error("Select plane or coordinate system before orienting.");
|
Error("Select plane or coordinate system before orienting.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
|
@ -156,12 +203,12 @@ void GraphicsWindow::EnsureValidActives(void) {
|
||||||
Group *g = SS.group.FindByIdNoOops(activeGroup);
|
Group *g = SS.group.FindByIdNoOops(activeGroup);
|
||||||
if((!g) || (g->h.v == Group::HGROUP_REFERENCES.v)) {
|
if((!g) || (g->h.v == Group::HGROUP_REFERENCES.v)) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < SS.group.elems; i++) {
|
for(i = 0; i < SS.group.n; i++) {
|
||||||
if(SS.group.elem[i].h.v != Group::HGROUP_REFERENCES.v) {
|
if(SS.group.elem[i].h.v != Group::HGROUP_REFERENCES.v) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i >= SS.group.elems) oops();
|
if(i >= SS.group.n) oops();
|
||||||
activeGroup = SS.group.elem[i].h;
|
activeGroup = SS.group.elem[i].h;
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
|
@ -174,6 +221,8 @@ void GraphicsWindow::EnsureValidActives(void) {
|
||||||
change = true;
|
change = true;
|
||||||
}
|
}
|
||||||
if(change) SS.TW.Show();
|
if(change) SS.TW.Show();
|
||||||
|
|
||||||
|
EnableMenuById(MNU_NO_CSYS, (activeCsys.v != Entity::NO_CSYS.v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsWindow::MenuEdit(int id) {
|
void GraphicsWindow::MenuEdit(int id) {
|
||||||
|
@ -362,7 +411,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(dest, 0, sizeof(*dest));
|
||||||
|
|
||||||
// Do the points
|
// Do the points
|
||||||
for(i = 0; i < SS.entity.elems; i++) {
|
for(i = 0; i < SS.entity.n; i++) {
|
||||||
d = SS.entity.elem[i].GetDistance(mp);
|
d = SS.entity.elem[i].GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < 10 && d < dmin) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(dest, 0, sizeof(*dest));
|
||||||
|
@ -371,7 +420,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entities
|
// Entities
|
||||||
for(i = 0; i < SS.point.elems; i++) {
|
for(i = 0; i < SS.point.n; i++) {
|
||||||
d = SS.point.elem[i].GetDistance(mp);
|
d = SS.point.elem[i].GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < 10 && d < dmin) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(dest, 0, sizeof(*dest));
|
||||||
|
@ -380,7 +429,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constraints
|
// Constraints
|
||||||
for(i = 0; i < SS.constraint.elems; i++) {
|
for(i = 0; i < SS.constraint.n; i++) {
|
||||||
d = SS.constraint.elem[i].GetDistance(mp);
|
d = SS.constraint.elem[i].GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < 10 && d < dmin) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(dest, 0, sizeof(*dest));
|
||||||
|
@ -581,15 +630,15 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||||
|
|
||||||
// First, draw the entire scene.
|
// First, draw the entire scene.
|
||||||
glColor3f(1, 1, 1);
|
glColor3f(1, 1, 1);
|
||||||
for(i = 0; i < SS.entity.elems; i++) {
|
for(i = 0; i < SS.entity.n; i++) {
|
||||||
SS.entity.elem[i].Draw();
|
SS.entity.elem[i].Draw();
|
||||||
}
|
}
|
||||||
glColor3f(0, 0.8f, 0);
|
glColor3f(0, 0.8f, 0);
|
||||||
for(i = 0; i < SS.point.elems; i++) {
|
for(i = 0; i < SS.point.n; i++) {
|
||||||
SS.point.elem[i].Draw();
|
SS.point.elem[i].Draw();
|
||||||
}
|
}
|
||||||
glColor3f(1.0f, 0, 1.0f);
|
glColor3f(1.0f, 0, 1.0f);
|
||||||
for(i = 0; i < SS.constraint.elems; i++) {
|
for(i = 0; i < SS.constraint.n; i++) {
|
||||||
SS.constraint.elem[i].Draw();
|
SS.constraint.elem[i].Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
sketch.h
17
sketch.h
|
@ -82,9 +82,9 @@ public:
|
||||||
hRequest h;
|
hRequest h;
|
||||||
|
|
||||||
// Types of requests
|
// Types of requests
|
||||||
static const int CSYS_2D = 10;
|
static const int CSYS_2D = 100;
|
||||||
static const int DATUM_POINT = 11;
|
static const int DATUM_POINT = 101;
|
||||||
static const int LINE_SEGMENT = 20;
|
static const int LINE_SEGMENT = 200;
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
|
@ -107,6 +107,9 @@ public:
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
public:
|
public:
|
||||||
|
int tag;
|
||||||
|
hEntity h;
|
||||||
|
|
||||||
static const hEntity NO_CSYS;
|
static const hEntity NO_CSYS;
|
||||||
|
|
||||||
static const int CSYS_2D = 1000;
|
static const int CSYS_2D = 1000;
|
||||||
|
@ -114,11 +117,6 @@ public:
|
||||||
static const int LINE_SEGMENT = 1010;
|
static const int LINE_SEGMENT = 1010;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
int tag;
|
|
||||||
hEntity h;
|
|
||||||
|
|
||||||
Expr *expr[16];
|
|
||||||
|
|
||||||
inline hRequest request(void)
|
inline hRequest request(void)
|
||||||
{ hRequest r; r.v = (this->h.v >> 10); return r; }
|
{ hRequest r; r.v = (this->h.v >> 10); return r; }
|
||||||
inline hParam param(int i)
|
inline hParam param(int i)
|
||||||
|
@ -161,7 +159,6 @@ public:
|
||||||
int type;
|
int type;
|
||||||
static const int IN_FREE_SPACE = 0; // three params, x y z
|
static const int IN_FREE_SPACE = 0; // three params, x y z
|
||||||
static const int IN_2D_CSYS = 1; // two params, u v, plus csys
|
static const int IN_2D_CSYS = 1; // two params, u v, plus csys
|
||||||
static const int BY_EXPR = 2; // three Expr *, could be anything
|
|
||||||
|
|
||||||
hEntity csys;
|
hEntity csys;
|
||||||
|
|
||||||
|
@ -234,9 +231,7 @@ public:
|
||||||
|
|
||||||
// These define how the constraint is drawn on-screen.
|
// These define how the constraint is drawn on-screen.
|
||||||
struct {
|
struct {
|
||||||
hEntity csys;
|
|
||||||
Vector offset;
|
Vector offset;
|
||||||
Vector u, v;
|
|
||||||
} disp;
|
} disp;
|
||||||
|
|
||||||
static hConstraint AddConstraint(Constraint *c);
|
static hConstraint AddConstraint(Constraint *c);
|
||||||
|
|
|
@ -58,11 +58,11 @@ void SolveSpace::GenerateAll(void) {
|
||||||
|
|
||||||
entity.Clear();
|
entity.Clear();
|
||||||
point.Clear();
|
point.Clear();
|
||||||
for(i = 0; i < request.elems; i++) {
|
for(i = 0; i < request.n; i++) {
|
||||||
request.elem[i].Generate(&entity, &point, ¶m);
|
request.elem[i].Generate(&entity, &point, ¶m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < param.elems; i++) {
|
for(i = 0; i < param.n; i++) {
|
||||||
Param *p = prev.FindByIdNoOops(param.elem[i].h);
|
Param *p = prev.FindByIdNoOops(param.elem[i].h);
|
||||||
if(p) {
|
if(p) {
|
||||||
param.elem[i].val = p->val;
|
param.elem[i].val = p->val;
|
||||||
|
@ -80,8 +80,8 @@ void SolveSpace::ForceReferences(void) {
|
||||||
double a, b, c, d;
|
double a, b, c, d;
|
||||||
} Quat[] = {
|
} Quat[] = {
|
||||||
{ Request::HREQUEST_REFERENCE_XY, 1, 0, 0, 0, },
|
{ Request::HREQUEST_REFERENCE_XY, 1, 0, 0, 0, },
|
||||||
{ Request::HREQUEST_REFERENCE_YZ, 0.5, -0.5, -0.5, -0.5, },
|
{ Request::HREQUEST_REFERENCE_YZ, 0.5, 0.5, 0.5, 0.5, },
|
||||||
{ Request::HREQUEST_REFERENCE_ZX, 0.5, 0.5, 0.5, 0.5, },
|
{ Request::HREQUEST_REFERENCE_ZX, 0.5, -0.5, -0.5, -0.5, },
|
||||||
};
|
};
|
||||||
for(int i = 0; i < 3; i++) {
|
for(int i = 0; i < 3; i++) {
|
||||||
hEntity he;
|
hEntity he;
|
||||||
|
@ -101,3 +101,21 @@ void SolveSpace::ForceReferences(void) {
|
||||||
void SolveSpace::Solve(void) {
|
void SolveSpace::Solve(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SolveSpace::MenuFile(int id) {
|
||||||
|
switch(id) {
|
||||||
|
case GraphicsWindow::MNU_NEW:
|
||||||
|
case GraphicsWindow::MNU_OPEN:
|
||||||
|
|
||||||
|
case GraphicsWindow::MNU_SAVE:
|
||||||
|
SS.SaveToFile("t.slv");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GraphicsWindow::MNU_SAVE_AS:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GraphicsWindow::MNU_EXIT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: oops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
solvespace.h
19
solvespace.h
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
||||||
|
|
||||||
|
typedef signed long SDWORD;
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -26,12 +28,21 @@
|
||||||
class Expr;
|
class Expr;
|
||||||
|
|
||||||
// From the platform-specific code.
|
// From the platform-specific code.
|
||||||
|
int SaveFileYesNoCancel(void);
|
||||||
|
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
|
||||||
|
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
|
||||||
|
|
||||||
void CheckMenuById(int id, BOOL checked);
|
void CheckMenuById(int id, BOOL checked);
|
||||||
void EnableMenuById(int id, BOOL checked);
|
void EnableMenuById(int id, BOOL checked);
|
||||||
|
|
||||||
void InvalidateGraphics(void);
|
void InvalidateGraphics(void);
|
||||||
void InvalidateText(void);
|
void InvalidateText(void);
|
||||||
|
SDWORD GetMilliseconds(void);
|
||||||
|
void PaintGraphics(void);
|
||||||
|
|
||||||
void dbp(char *str, ...);
|
void dbp(char *str, ...);
|
||||||
void Error(char *str, ...);
|
void Error(char *str, ...);
|
||||||
|
|
||||||
Expr *AllocExpr(void);
|
Expr *AllocExpr(void);
|
||||||
void FreeAllExprs(void);
|
void FreeAllExprs(void);
|
||||||
void *MemRealloc(void *p, int n);
|
void *MemRealloc(void *p, int n);
|
||||||
|
@ -82,13 +93,19 @@ public:
|
||||||
inline Param *GetParam (hParam h) { return param. FindById(h); }
|
inline Param *GetParam (hParam h) { return param. FindById(h); }
|
||||||
inline Point *GetPoint (hPoint h) { return point. FindById(h); }
|
inline Point *GetPoint (hPoint h) { return point. FindById(h); }
|
||||||
|
|
||||||
hGroup activeGroup;
|
hGroup activeGroup;
|
||||||
|
|
||||||
|
FILE *fh;
|
||||||
|
|
||||||
void GenerateAll(void);
|
void GenerateAll(void);
|
||||||
void ForceReferences(void);
|
void ForceReferences(void);
|
||||||
|
|
||||||
void Init(void);
|
void Init(void);
|
||||||
void Solve(void);
|
void Solve(void);
|
||||||
|
|
||||||
|
static void MenuFile(int id);
|
||||||
|
bool SaveToFile(char *filename);
|
||||||
|
bool LoadFromFile(char *filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SolveSpace SS;
|
extern SolveSpace SS;
|
||||||
|
|
|
@ -254,10 +254,10 @@ void TextWindow::ShowHeader(void) {
|
||||||
void TextWindow::ShowAllGroups(void) {
|
void TextWindow::ShowAllGroups(void) {
|
||||||
Printf("%C8[[all groups in sketch follow]]%E");
|
Printf("%C8[[all groups in sketch follow]]%E");
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i <= SS.group.elems; i++) {
|
for(i = 0; i <= SS.group.n; i++) {
|
||||||
DWORD v;
|
DWORD v;
|
||||||
char *s;
|
char *s;
|
||||||
if(i == SS.group.elems) {
|
if(i == SS.group.n) {
|
||||||
s = "all requests from all groups";
|
s = "all requests from all groups";
|
||||||
v = 0;
|
v = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -293,7 +293,7 @@ void TextWindow::ShowRequestsInGroup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < SS.request.elems; i++) {
|
for(i = 0; i < SS.request.n; i++) {
|
||||||
Request *r = &(SS.request.elem[i]);
|
Request *r = &(SS.request.elem[i]);
|
||||||
|
|
||||||
if(r->group.v == shown->group.v || shown->group.v == 0) {
|
if(r->group.v == shown->group.v || shown->group.v == 0) {
|
||||||
|
|
8
ui.h
8
ui.h
|
@ -74,8 +74,14 @@ public:
|
||||||
|
|
||||||
// This table describes the top-level menus in the graphics winodw.
|
// This table describes the top-level menus in the graphics winodw.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
// File
|
||||||
|
MNU_NEW = 100,
|
||||||
|
MNU_OPEN,
|
||||||
|
MNU_SAVE,
|
||||||
|
MNU_SAVE_AS,
|
||||||
|
MNU_EXIT,
|
||||||
// View
|
// View
|
||||||
MNU_ZOOM_IN = 100,
|
MNU_ZOOM_IN,
|
||||||
MNU_ZOOM_OUT,
|
MNU_ZOOM_OUT,
|
||||||
MNU_ZOOM_TO_FIT,
|
MNU_ZOOM_TO_FIT,
|
||||||
MNU_ORIENT_ONTO,
|
MNU_ORIENT_ONTO,
|
||||||
|
|
88
util.cpp
88
util.cpp
|
@ -23,27 +23,85 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||||
mat[15] = a44;
|
mat[15] = a44;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::MakeFrom(double a, double b, double c, double d) {
|
||||||
|
Quaternion q;
|
||||||
|
q.a = a;
|
||||||
|
q.b = b;
|
||||||
|
q.c = c;
|
||||||
|
q.d = d;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::MakeFrom(Vector u, Vector v)
|
||||||
|
{
|
||||||
|
Vector n = u.Cross(v);
|
||||||
|
|
||||||
|
Quaternion q;
|
||||||
|
q.a = 0.5*sqrt(1 + u.x + v.y + n.z);
|
||||||
|
q.b = (1/(4*(q.a)))*(v.z - n.y);
|
||||||
|
q.c = (1/(4*(q.a)))*(n.x - u.z);
|
||||||
|
q.d = (1/(4*(q.a)))*(u.y - v.x);
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Plus(Quaternion y) {
|
||||||
|
Quaternion q;
|
||||||
|
q.a = a + y.a;
|
||||||
|
q.b = b + y.b;
|
||||||
|
q.c = c + y.c;
|
||||||
|
q.d = d + y.d;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Minus(Quaternion y) {
|
||||||
|
Quaternion q;
|
||||||
|
q.a = a - y.a;
|
||||||
|
q.b = b - y.b;
|
||||||
|
q.c = c - y.c;
|
||||||
|
q.d = d - y.d;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::ScaledBy(double s) {
|
||||||
|
Quaternion q;
|
||||||
|
q.a = a*s;
|
||||||
|
q.b = b*s;
|
||||||
|
q.c = c*s;
|
||||||
|
q.d = d*s;
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Quaternion::Magnitude(void) {
|
||||||
|
return sqrt(a*a + b*b + c*c + d*d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::WithMagnitude(double s) {
|
||||||
|
return ScaledBy(s/Magnitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector Quaternion::RotationU(void) {
|
||||||
|
Vector v;
|
||||||
|
v.x = a*a + b*b - c*c - d*d;
|
||||||
|
v.y = 2*a*d + 2*b*c;
|
||||||
|
v.z = 2*b*d - 2*a*c;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector Quaternion::RotationV(void) {
|
||||||
|
Vector v;
|
||||||
|
v.x = 2*b*c - 2*a*d;
|
||||||
|
v.y = a*a - b*b + c*c - d*d;
|
||||||
|
v.z = 2*a*b + 2*c*d;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector Vector::MakeFrom(double x, double y, double z) {
|
Vector Vector::MakeFrom(double x, double y, double z) {
|
||||||
Vector v;
|
Vector v;
|
||||||
v.x = x; v.y = y; v.z = z;
|
v.x = x; v.y = y; v.z = z;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector Vector::RotationU(double a, double b, double c, double d) {
|
|
||||||
Vector v;
|
|
||||||
v.x = a*a + b*b - c*c - d*d;
|
|
||||||
v.y = 2*b*c - 2*a*d;
|
|
||||||
v.z = 2*a*c + 2*b*d;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector Vector::RotationV(double a, double b, double c, double d) {
|
|
||||||
Vector v;
|
|
||||||
v.x = 2*a*d + 2*b*c;
|
|
||||||
v.y = a*a - b*b + c*c - d*d;
|
|
||||||
v.z = 2*c*d - 2*a*b;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector Vector::Plus(Vector b) {
|
Vector Vector::Plus(Vector b) {
|
||||||
Vector r;
|
Vector r;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include <commdlg.h>
|
||||||
#include <gl/gl.h>
|
#include <gl/gl.h>
|
||||||
#include <gl/glu.h>
|
#include <gl/glu.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -349,6 +350,32 @@ void InvalidateGraphics(void)
|
||||||
{
|
{
|
||||||
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
static void PaintGraphicsWithHdc(HDC hdc)
|
||||||
|
{
|
||||||
|
HGLRC hgrc = CreateGlContext(hdc);
|
||||||
|
|
||||||
|
RECT r;
|
||||||
|
GetClientRect(GraphicsWnd, &r);
|
||||||
|
int w = r.right - r.left;
|
||||||
|
int h = r.bottom - r.top;
|
||||||
|
|
||||||
|
SS.GW.Paint(w, h);
|
||||||
|
|
||||||
|
SwapBuffers(hdc);
|
||||||
|
|
||||||
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
wglDeleteContext(hgrc);
|
||||||
|
}
|
||||||
|
void PaintGraphics(void)
|
||||||
|
{
|
||||||
|
HDC hdc = GetDC(GraphicsWnd);
|
||||||
|
PaintGraphicsWithHdc(hdc);
|
||||||
|
}
|
||||||
|
SDWORD GetMilliseconds(void)
|
||||||
|
{
|
||||||
|
return (SDWORD)GetTickCount();
|
||||||
|
}
|
||||||
|
|
||||||
void InvalidateText(void)
|
void InvalidateText(void)
|
||||||
{
|
{
|
||||||
InvalidateRect(TextWnd, NULL, FALSE);
|
InvalidateRect(TextWnd, NULL, FALSE);
|
||||||
|
@ -370,19 +397,7 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
HDC hdc = BeginPaint(hwnd, &ps);
|
HDC hdc = BeginPaint(hwnd, &ps);
|
||||||
|
|
||||||
HGLRC hgrc = CreateGlContext(hdc);
|
PaintGraphicsWithHdc(hdc);
|
||||||
|
|
||||||
RECT r;
|
|
||||||
GetClientRect(GraphicsWnd, &r);
|
|
||||||
int w = r.right - r.left;
|
|
||||||
int h = r.bottom - r.top;
|
|
||||||
|
|
||||||
SS.GW.Paint(w, h);
|
|
||||||
|
|
||||||
SwapBuffers(hdc);
|
|
||||||
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
|
||||||
wglDeleteContext(hgrc);
|
|
||||||
|
|
||||||
EndPaint(hwnd, &ps);
|
EndPaint(hwnd, &ps);
|
||||||
break;
|
break;
|
||||||
|
@ -446,6 +461,58 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Common dialog routines, to open or save a file.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern)
|
||||||
|
{
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hInstance = Instance;
|
||||||
|
ofn.hwndOwner = GraphicsWnd;
|
||||||
|
ofn.lpstrFilter = selPattern;
|
||||||
|
ofn.lpstrDefExt = defExtension;
|
||||||
|
ofn.lpstrFile = file;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||||
|
|
||||||
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
BOOL r = GetOpenFileName(&ofn);
|
||||||
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
|
||||||
|
{
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hInstance = Instance;
|
||||||
|
ofn.hwndOwner = GraphicsWnd;
|
||||||
|
ofn.lpstrFilter = selPattern;
|
||||||
|
ofn.lpstrDefExt = defExtension;
|
||||||
|
ofn.lpstrFile = file;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||||
|
|
||||||
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
BOOL r = GetSaveFileName(&ofn);
|
||||||
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
int SaveFileYesNoCancel(void)
|
||||||
|
{
|
||||||
|
return MessageBox(GraphicsWnd,
|
||||||
|
"The program has changed since it was last saved.\r\n\r\n"
|
||||||
|
"Do you want to save the changes?", "SolveSpace",
|
||||||
|
MB_YESNOCANCEL | MB_ICONWARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void MenuById(int id, BOOL yes, BOOL check)
|
static void MenuById(int id, BOOL yes, BOOL check)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user