diff --git a/glhelper.cpp b/glhelper.cpp index 1f1a7a3..c88b1a3 100644 --- a/glhelper.cpp +++ b/glhelper.cpp @@ -111,6 +111,53 @@ void glxColor4d(double r, double g, double b, double a) if(!ColorLocked) glColor4d(r, g, b, a); } +static void Stipple(BOOL forSel) +{ + static BOOL Init; + const int BYTES = (32*32)/8; + static GLubyte HoverMask[BYTES]; + static GLubyte SelMask[BYTES]; + if(!Init) { + int x, y; + for(x = 0; x < 32; x++) { + for(y = 0; y < 32; y++) { + int i = y*4 + x/8, b = x % 8; + int ym = y % 4, xm = x % 4; + for(int k = 0; k < 2; k++) { + if(xm >= 1 && xm <= 2 && ym >= 1 && ym <= 2) { + (k == 0 ? SelMask : HoverMask)[i] |= (0x80 >> b); + } + ym = (ym + 2) % 4; xm = (xm + 2) % 4; + } + } + } + Init = TRUE; + } + + glEnable(GL_POLYGON_STIPPLE); + if(forSel) { + glPolygonStipple(SelMask); + } else { + glPolygonStipple(HoverMask); + } +} + +static void StippleTriangle(STriangle *tr, BOOL s, double r, double g, double b) +{ + glEnd(); + glDisable(GL_LIGHTING); + glColor3d(r, g, b); + Stipple(s); + glBegin(GL_TRIANGLES); + glxVertex3v(tr->a); + glxVertex3v(tr->b); + glxVertex3v(tr->c); + glEnd(); + glEnable(GL_LIGHTING); + glDisable(GL_POLYGON_STIPPLE); + glBegin(GL_TRIANGLES); +} + void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2) { glEnable(GL_NORMALIZE); @@ -122,13 +169,7 @@ void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2) glNormal3d(n.x, n.y, n.z); int color; - if((s1 != 0 && tr->meta.face == s1) || - (s2 != 0 && tr->meta.face == s2)) - { - color = RGB(200, 0, 0); - } else if(h != 0 && tr->meta.face == h) { - color = RGB(200, 200, 0); - } else if(specColor < 0) { + if(specColor < 0) { color = tr->meta.color; } else { color = specColor; @@ -146,6 +187,15 @@ void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2) glxVertex3v(tr->a); glxVertex3v(tr->b); glxVertex3v(tr->c); + + if((s1 != 0 && tr->meta.face == s1) || + (s2 != 0 && tr->meta.face == s2)) + { + StippleTriangle(tr, TRUE, 1, 0, 0); + } + if(h != 0 && tr->meta.face == h) { + StippleTriangle(tr, FALSE, 1, 1, 0); + } } glEnd(); } diff --git a/graphicswin.cpp b/graphicswin.cpp index 2b42023..dab70af 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -102,12 +102,14 @@ void GraphicsWindow::Init(void) { projRight.x = 1; projRight.y = projRight.z = 0; projUp.y = 1; projUp.z = projUp.x = 0; - // And with the latest visible group active + // And with the latest visible group active, or failing that the first + // group after the references int i; for(i = 0; i < SS.group.n; i++) { Group *g = &(SS.group.elem[i]); - if(i == 0 || g->visible) activeGroup = g->h; + if(i == 1 || g->visible) activeGroup = g->h; } + SS.GetGroup(activeGroup)->Activate(); EnsureValidActives(); @@ -248,6 +250,7 @@ void GraphicsWindow::EnsureValidActives(void) { } if(i >= SS.group.n) oops(); activeGroup = SS.group.elem[i].h; + SS.GetGroup(activeGroup)->Activate(); change = true; } @@ -746,7 +749,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) { } // Faces, from the triangle mesh; these are lowest priority - if(s.constraint.v == 0 && s.entity.v == 0 && (showMesh || showShaded)) { + if(s.constraint.v == 0 && s.entity.v == 0 && showShaded && showFaces) { SMesh *m = &((SS.GetGroup(activeGroup))->mesh); DWORD v = m->FirstIntersectionWith(mp); if(v) { @@ -1063,6 +1066,19 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { } if(i != MAX_SELECTED) break; + if(hover.entity.v != 0 && SS.GetEntity(hover.entity)->IsFace()) { + // In the interest of speed for the triangle drawing code, + // only two faces may be selected at a time. + int c = 0; + for(i = 0; i < MAX_SELECTED; i++) { + hEntity he = selection[i].entity; + if(he.v != 0 && SS.GetEntity(he)->IsFace()) { + c++; + if(c >= 2) selection[i].Clear(); + } + } + } + for(i = 0; i < MAX_SELECTED; i++) { if(selection[i].IsEmpty()) { selection[i] = hover; @@ -1147,6 +1163,10 @@ void GraphicsWindow::ToggleBool(int link, DWORD v) { bool *vb = (bool *)v; *vb = !*vb; + // The faces are shown as special stippling on the shaded triangle mesh, + // so not meaningful to show them and hide the shaded. + if(!SS.GW.showShaded) SS.GW.showFaces = false; + SS.GW.GeneratePerSolving(); InvalidateGraphics(); SS.TW.Show(); diff --git a/sketch.cpp b/sketch.cpp index 6482e32..559044c 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -141,6 +141,7 @@ void Group::MenuGroup(int id) { if(g.type == DRAWING_WORKPLANE) { SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0); } + SS.GetGroup(g.h)->Activate(); SS.GW.AnimateOntoWorkplane(); TextWindow::ScreenSelectGroup(0, g.h.v); SS.TW.Show(); @@ -156,6 +157,15 @@ char *Group::DescriptionString(void) { return ret; } +void Group::Activate(void) { + if(type == EXTRUDE || type == IMPORTED) { + SS.GW.showFaces = true; + } else { + SS.GW.showFaces = false; + } + SS.TW.Show(); +} + void Group::Generate(IdList *entity, IdList *param) { diff --git a/sketch.h b/sketch.h index 27a966f..fcab3ca 100644 --- a/sketch.h +++ b/sketch.h @@ -137,6 +137,7 @@ public: NameStr name; + void Activate(void); char *DescriptionString(void); static void AddParam(IdList *param, hParam hp, double v); diff --git a/textwin.cpp b/textwin.cpp index 36208ce..54e7b16 100644 --- a/textwin.cpp +++ b/textwin.cpp @@ -221,6 +221,10 @@ void TextWindow::Show(void) { InvalidateText(); } +void TextWindow::ScreenUnselectAll(int link, DWORD v) { + GraphicsWindow::MenuEdit(GraphicsWindow::MNU_UNSELECT_ALL); +} + void TextWindow::DescribeSelection(void) { Entity *e; Vector p; @@ -310,6 +314,12 @@ void TextWindow::DescribeSelection(void) { Printf(false, " radius = %Fi%s", SS.GW.ToString(r)); break; } + case Entity::FACE_NORMAL_PT: + case Entity::FACE_XPROD: + case Entity::FACE_N_ROT_TRANS: + Printf(false, "%FtPLANE FACE%E"); + break; + default: Printf(true, "%Ft?? ENTITY%E"); break; @@ -335,6 +345,8 @@ void TextWindow::DescribeSelection(void) { } else { Printf(true, "%FtSELECTED:%E %d item%s", gs.n, gs.n == 1 ? "" : "s"); } + + Printf(true, "%Fl%f%Ll(unselect all)%E", &TextWindow::ScreenUnselectAll); } void TextWindow::OneScreenForwardTo(int screen) { @@ -397,9 +409,11 @@ hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints), &(SS.GW.ToggleBool) ); Printf(false, "%Bt%Ft " "%Fp%Ll%D%fshaded%E " + "%Fp%Ll%D%ffaces%E " "%Fp%Ll%D%fmesh%E " "%Fp%Ll%D%fhidden-lines%E", hs(SS.GW.showShaded), (DWORD)(&SS.GW.showShaded), &(SS.GW.ToggleBool), +hs(SS.GW.showFaces), (DWORD)(&SS.GW.showFaces), &(SS.GW.ToggleBool), hs(SS.GW.showMesh), (DWORD)(&SS.GW.showMesh), &(SS.GW.ToggleBool), hs(SS.GW.showHdnLines), (DWORD)(&SS.GW.showHdnLines), &(SS.GW.ToggleBool) ); @@ -437,6 +451,7 @@ void TextWindow::ScreenActivateGroup(int link, DWORD v) { Group *g = SS.GetGroup(hg); g->visible = true; SS.GW.activeGroup.v = v; + SS.GetGroup(SS.GW.activeGroup)->Activate(); SS.GW.ClearSuper(); } void TextWindow::ReportHowGroupSolved(hGroup hg) { diff --git a/ui.h b/ui.h index a4a3b0c..70b4a7d 100644 --- a/ui.h +++ b/ui.h @@ -99,12 +99,14 @@ public: static void ScreenChangeMeshCombine(int link, DWORD v); static void ScreenColor(int link, DWORD v); + static void ScreenUnselectAll(int link, DWORD v); + + static void ScreenNavigation(int link, DWORD v); + // These ones do stuff with the edit control static void ScreenChangeExprA(int link, DWORD v); static void ScreenChangeGroupName(int link, DWORD v); - static void ScreenNavigation(int link, DWORD v); - void EditControlDone(char *s); }; @@ -297,6 +299,7 @@ public: bool showConstraints; bool showTextWindow; bool showShaded; + bool showFaces; bool showMesh; bool showHdnLines; static void ToggleBool(int link, DWORD v);