Add logic to remember imported files' relative filenames, and use
that to try to find them if we can't find them by absolute path. This is intended to make everything still work if you copy an entire directory tree of files that import each other. Also add a mechanism to not paint the scene if we're not sure it's consistent; otherwise got some crashes on startup. And disable both text and graphic window when displaying a modal dialog, wasn't doing that always. [git-p4: depot-paths = "//depot/solvespace/": change = 1808]
This commit is contained in:
parent
2ff309590e
commit
12942a74cf
6
draw.cpp
6
draw.cpp
|
@ -900,6 +900,12 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||||
glClearDepth(1.0);
|
glClearDepth(1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Nasty case when we're reloading the imported files; could be that
|
||||||
|
// we get an error, so a dialog pops up, and a message loop starts, and
|
||||||
|
// we have to get called to paint ourselves. If the sketch is screwed
|
||||||
|
// up, then we could trigger an oops trying to draw.
|
||||||
|
if(!SS.allConsistent) return;
|
||||||
|
|
||||||
// Let's use two lights, at the user-specified locations
|
// Let's use two lights, at the user-specified locations
|
||||||
GLfloat f;
|
GLfloat f;
|
||||||
glEnable(GL_LIGHT0);
|
glEnable(GL_LIGHT0);
|
||||||
|
|
37
file.cpp
37
file.cpp
|
@ -86,6 +86,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
||||||
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
|
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
|
||||||
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
||||||
{ 'g', "Group.impFile", 'P', &(SS.sv.g.impFile) },
|
{ 'g', "Group.impFile", 'P', &(SS.sv.g.impFile) },
|
||||||
|
{ 'g', "Group.impFileRel", 'P', &(SS.sv.g.impFileRel) },
|
||||||
|
|
||||||
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
|
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
|
||||||
{ 'p', "Param.val", 'f', &(SS.sv.p.val) },
|
{ 'p', "Param.val", 'f', &(SS.sv.p.val) },
|
||||||
|
@ -284,6 +285,8 @@ void SolveSpace::LoadUsingTable(char *key, char *val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SolveSpace::LoadFromFile(char *filename) {
|
bool SolveSpace::LoadFromFile(char *filename) {
|
||||||
|
allConsistent = false;
|
||||||
|
|
||||||
fh = fopen(filename, "rb");
|
fh = fopen(filename, "rb");
|
||||||
if(!fh) {
|
if(!fh) {
|
||||||
Error("Couldn't read from file '%s'", filename);
|
Error("Couldn't read from file '%s'", filename);
|
||||||
|
@ -398,6 +401,8 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::ReloadAllImported(void) {
|
void SolveSpace::ReloadAllImported(void) {
|
||||||
|
allConsistent = false;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < group.n; i++) {
|
for(i = 0; i < group.n; i++) {
|
||||||
Group *g = &(group.elem[i]);
|
Group *g = &(group.elem[i]);
|
||||||
|
@ -405,7 +410,37 @@ void SolveSpace::ReloadAllImported(void) {
|
||||||
|
|
||||||
g->impEntity.Clear();
|
g->impEntity.Clear();
|
||||||
g->impMesh.Clear();
|
g->impMesh.Clear();
|
||||||
if(!LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh))) {
|
|
||||||
|
FILE *test = fopen(g->impFile, "rb");
|
||||||
|
if(test) {
|
||||||
|
fclose(test); // okay, exists
|
||||||
|
} else {
|
||||||
|
// It doesn't exist. Perhaps the entire tree has moved, and we
|
||||||
|
// can use the relative filename to get us back.
|
||||||
|
if(SS.saveFile[0]) {
|
||||||
|
char fromRel[MAX_PATH];
|
||||||
|
strcpy(fromRel, g->impFileRel);
|
||||||
|
MakePathAbsolute(SS.saveFile, fromRel);
|
||||||
|
test = fopen(fromRel, "rb");
|
||||||
|
if(test) {
|
||||||
|
fclose(test);
|
||||||
|
// It worked, this is our new absolute path
|
||||||
|
strcpy(g->impFile, fromRel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh))) {
|
||||||
|
if(SS.saveFile[0]) {
|
||||||
|
// Record the imported file's name relative to our filename;
|
||||||
|
// if the entire tree moves, then everything will still work
|
||||||
|
strcpy(g->impFileRel, g->impFile);
|
||||||
|
MakePathRelative(SS.saveFile, g->impFileRel);
|
||||||
|
} else {
|
||||||
|
// We're not yet saved, so can't make it absolute
|
||||||
|
strcpy(g->impFileRel, g->impFile);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Error("Failed to load imported file '%s'", g->impFile);
|
Error("Failed to load imported file '%s'", g->impFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
sketch.h
1
sketch.h
|
@ -157,6 +157,7 @@ public:
|
||||||
int remapCache[REMAP_PRIME];
|
int remapCache[REMAP_PRIME];
|
||||||
|
|
||||||
char impFile[MAX_PATH];
|
char impFile[MAX_PATH];
|
||||||
|
char impFileRel[MAX_PATH];
|
||||||
SMesh impMesh;
|
SMesh impMesh;
|
||||||
EntityList impEntity;
|
EntityList impEntity;
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,8 @@ void SolveSpace::GenerateAll(int first, int last) {
|
||||||
deleted.groups, deleted.groups == 1 ? "" : "s");
|
deleted.groups, deleted.groups == 1 ? "" : "s");
|
||||||
memset(&deleted, 0, sizeof(deleted));
|
memset(&deleted, 0, sizeof(deleted));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allConsistent = true;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pruned:
|
pruned:
|
||||||
|
|
|
@ -58,6 +58,7 @@ int SaveFileYesNoCancel(void);
|
||||||
#define PNG_EXT "png"
|
#define PNG_EXT "png"
|
||||||
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
|
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
|
||||||
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
|
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
|
||||||
|
void GetAbsoluteFilename(char *file);
|
||||||
|
|
||||||
void CheckMenuById(int id, BOOL checked);
|
void CheckMenuById(int id, BOOL checked);
|
||||||
void EnableMenuById(int id, BOOL checked);
|
void EnableMenuById(int id, BOOL checked);
|
||||||
|
@ -142,6 +143,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||||
double a21, double a22, double a23, double a24,
|
double a21, double a22, double a23, double a24,
|
||||||
double a31, double a32, double a33, double a34,
|
double a31, double a32, double a33, double a34,
|
||||||
double a41, double a42, double a43, double a44);
|
double a41, double a42, double a43, double a44);
|
||||||
|
void MakePathRelative(char *base, char *path);
|
||||||
|
void MakePathAbsolute(char *base, char *path);
|
||||||
|
|
||||||
class System {
|
class System {
|
||||||
public:
|
public:
|
||||||
|
@ -336,6 +339,11 @@ public:
|
||||||
// The system to be solved.
|
// The system to be solved.
|
||||||
System sys;
|
System sys;
|
||||||
|
|
||||||
|
// Everything has been pruned, so we know there's no dangling references
|
||||||
|
// to entities that don't exist. Before that, we mustn't try to display
|
||||||
|
// the sketch!
|
||||||
|
bool allConsistent;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool showTW;
|
bool showTW;
|
||||||
bool generateAll;
|
bool generateAll;
|
||||||
|
|
|
@ -383,7 +383,7 @@ void TextWindow::ShowGroupInfo(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g->type == Group::IMPORTED) {
|
if(g->type == Group::IMPORTED) {
|
||||||
Printf(true, "%FtIMPORT%E '%s'", g->impFile);
|
Printf(true, "%FtIMPORT%E '%s'", g->impFileRel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g->type == Group::EXTRUDE ||
|
if(g->type == Group::EXTRUDE ||
|
||||||
|
|
70
util.cpp
70
util.cpp
|
@ -1,5 +1,75 @@
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
|
|
||||||
|
void MakePathRelative(char *basep, char *pathp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
char base[MAX_PATH], path[MAX_PATH], out[MAX_PATH];
|
||||||
|
|
||||||
|
// Convert everything to lowercase
|
||||||
|
p = basep;
|
||||||
|
for(i = 0; *p; p++) {
|
||||||
|
base[i++] = tolower(*p);
|
||||||
|
}
|
||||||
|
base[i++] = '\0';
|
||||||
|
p = pathp;
|
||||||
|
for(i = 0; *p; p++) {
|
||||||
|
path[i++] = tolower(*p);
|
||||||
|
}
|
||||||
|
path[i++] = '\0';
|
||||||
|
|
||||||
|
// Find the length of the common prefix
|
||||||
|
int com;
|
||||||
|
for(com = 0; base[com] && path[com]; com++) {
|
||||||
|
if(base[com] != path[com]) break;
|
||||||
|
}
|
||||||
|
if(!(base[com] && path[com])) return; // weird, prefix is entire string
|
||||||
|
if(com == 0) return; // maybe on different drive letters?
|
||||||
|
|
||||||
|
int sections = 0;
|
||||||
|
int secLen = 0, secStart = 0;
|
||||||
|
for(i = com; base[i]; i++) {
|
||||||
|
if(base[i] == '/' || base[i] == '\\') {
|
||||||
|
if(secLen == 2 && memcmp(base+secStart, "..", 2)==0) return;
|
||||||
|
if(secLen == 1 && memcmp(base+secStart, ".", 1)==0) return;
|
||||||
|
|
||||||
|
sections++;
|
||||||
|
secLen = 0;
|
||||||
|
secStart = i+1;
|
||||||
|
} else {
|
||||||
|
secLen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For every directory in the prefix of the base, we must go down a
|
||||||
|
// directory in the relative path name
|
||||||
|
strcpy(out, "");
|
||||||
|
for(i = 0; i < sections; i++) {
|
||||||
|
strcat(out, "../");
|
||||||
|
}
|
||||||
|
strcat(out, path+com);
|
||||||
|
|
||||||
|
strcpy(pathp, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakePathAbsolute(char *basep, char *pathp) {
|
||||||
|
char out[MAX_PATH];
|
||||||
|
strcpy(out, basep);
|
||||||
|
|
||||||
|
// Chop off the filename
|
||||||
|
int i;
|
||||||
|
for(i = strlen(out) - 1; i >= 0; i--) {
|
||||||
|
if(out[i] == '\\' || out[i] == '/') break;
|
||||||
|
}
|
||||||
|
if(i < 0) return; // base is not an absolute path, or something?
|
||||||
|
out[i+1] = '\0';
|
||||||
|
|
||||||
|
strcat(out, pathp);
|
||||||
|
GetAbsoluteFilename(out);
|
||||||
|
|
||||||
|
strcpy(pathp, out);
|
||||||
|
}
|
||||||
|
|
||||||
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||||
double a21, double a22, double a23, double a24,
|
double a21, double a22, double a23, double a24,
|
||||||
double a31, double a32, double a33, double a34,
|
double a31, double a32, double a33, double a34,
|
||||||
|
|
|
@ -63,8 +63,15 @@ void Error(char *str, ...)
|
||||||
vsprintf(buf, str, f);
|
vsprintf(buf, str, f);
|
||||||
va_end(f);
|
va_end(f);
|
||||||
|
|
||||||
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
EnableWindow(TextWnd, FALSE);
|
||||||
|
|
||||||
HWND h = GetForegroundWindow();
|
HWND h = GetForegroundWindow();
|
||||||
MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR);
|
MessageBox(h, buf, "SolveSpace Error", MB_OK | MB_ICONERROR);
|
||||||
|
|
||||||
|
EnableWindow(TextWnd, TRUE);
|
||||||
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
|
SetForegroundWindow(GraphicsWnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitNow(void) {
|
void ExitNow(void) {
|
||||||
|
@ -696,9 +703,14 @@ BOOL GetOpenFile(char *file, char *defExtension, char *selPattern)
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||||
|
|
||||||
EnableWindow(GraphicsWnd, FALSE);
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
EnableWindow(TextWnd, FALSE);
|
||||||
|
|
||||||
BOOL r = GetOpenFileName(&ofn);
|
BOOL r = GetOpenFileName(&ofn);
|
||||||
|
|
||||||
|
EnableWindow(TextWnd, TRUE);
|
||||||
EnableWindow(GraphicsWnd, TRUE);
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
SetForegroundWindow(GraphicsWnd);
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
|
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
|
||||||
|
@ -716,19 +728,38 @@ BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||||
|
|
||||||
EnableWindow(GraphicsWnd, FALSE);
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
EnableWindow(TextWnd, FALSE);
|
||||||
|
|
||||||
BOOL r = GetSaveFileName(&ofn);
|
BOOL r = GetSaveFileName(&ofn);
|
||||||
|
|
||||||
|
EnableWindow(TextWnd, TRUE);
|
||||||
EnableWindow(GraphicsWnd, TRUE);
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
SetForegroundWindow(GraphicsWnd);
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
int SaveFileYesNoCancel(void)
|
int SaveFileYesNoCancel(void)
|
||||||
{
|
{
|
||||||
return MessageBox(GraphicsWnd,
|
EnableWindow(GraphicsWnd, FALSE);
|
||||||
|
EnableWindow(TextWnd, FALSE);
|
||||||
|
|
||||||
|
int r = MessageBox(GraphicsWnd,
|
||||||
"The program has changed since it was last saved.\r\n\r\n"
|
"The program has changed since it was last saved.\r\n\r\n"
|
||||||
"Do you want to save the changes?", "SolveSpace",
|
"Do you want to save the changes?", "SolveSpace",
|
||||||
MB_YESNOCANCEL | MB_ICONWARNING);
|
MB_YESNOCANCEL | MB_ICONWARNING);
|
||||||
}
|
|
||||||
|
|
||||||
|
EnableWindow(TextWnd, TRUE);
|
||||||
|
EnableWindow(GraphicsWnd, TRUE);
|
||||||
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
void GetAbsoluteFilename(char *file)
|
||||||
|
{
|
||||||
|
char absoluteFile[MAX_PATH];
|
||||||
|
GetFullPathName(file, sizeof(absoluteFile), absoluteFile, NULL);
|
||||||
|
strcpy(file, absoluteFile);
|
||||||
|
}
|
||||||
|
|
||||||
static void MenuById(int id, BOOL yes, BOOL check)
|
static void MenuById(int id, BOOL yes, BOOL check)
|
||||||
{
|
{
|
||||||
|
@ -933,13 +964,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
s = strrchr(file, '"');
|
s = strrchr(file, '"');
|
||||||
if(s) *s = '\0';
|
if(s) *s = '\0';
|
||||||
}
|
}
|
||||||
char absoluteFile[MAX_PATH] = "";
|
|
||||||
if(*file != '\0') {
|
if(*file != '\0') {
|
||||||
GetFullPathName(file, sizeof(absoluteFile), absoluteFile, NULL);
|
GetAbsoluteFilename(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call in to the platform-independent code, and let them do their init
|
// Call in to the platform-independent code, and let them do their init
|
||||||
SS.Init(absoluteFile);
|
SS.Init(file);
|
||||||
|
|
||||||
ShowWindow(TextWnd, SW_SHOWNOACTIVATE);
|
ShowWindow(TextWnd, SW_SHOWNOACTIVATE);
|
||||||
ShowWindow(GraphicsWnd, SW_SHOW);
|
ShowWindow(GraphicsWnd, SW_SHOW);
|
||||||
|
|
|
@ -5,7 +5,6 @@ DXF export
|
||||||
TTF font text
|
TTF font text
|
||||||
some kind of rounding / chamfer
|
some kind of rounding / chamfer
|
||||||
remove back button in browser?
|
remove back button in browser?
|
||||||
relative paths for import
|
|
||||||
auto-generate circles and faces when lathing
|
auto-generate circles and faces when lathing
|
||||||
copy the section geometry to other end when sweeping
|
copy the section geometry to other end when sweeping
|
||||||
cylindrical faces
|
cylindrical faces
|
||||||
|
|
Loading…
Reference in New Issue
Block a user