bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my, bool paint, Command *menuHit) { int i; int x = 17, y = (int)(height - 52); int fudge = 8; int h = 32*16 + 3*16 + fudge; int aleft = 0, aright = 66, atop = y+16+fudge/2, abot = y+16-h; bool withinToolbar = (mx >= aleft && mx <= aright && my <= atop && my >= abot); if(!paint && !withinToolbar) { // This gets called every MouseMove event, so return quickly. return false; } if(paint) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glTranslated(-1, -1, 0); glScaled(2.0/width, 2.0/height, 0); glDisable(GL_LIGHTING); double c = 30.0/255; glColor4d(c, c, c, 1.0); ssglAxisAlignedQuad(aleft, aright, atop, abot); } struct { bool show; const char *str; } toolTip = { false, NULL }; bool leftpos = true; for(ToolIcon &icon : Toolbar) { if(icon.name == "") { // spacer if(!leftpos) { leftpos = true; y -= 32; x -= 32; } y -= 16; if(paint) { // Draw a separator bar in a slightly different color. int divw = 30, divh = 2; glColor4d(0.17, 0.17, 0.17, 1); x += 16; y += 24; ssglAxisAlignedQuad(x+divw, x-divw, y+divh, y-divh); x -= 16; y -= 24; } continue; } if(icon.pixmap.IsEmpty()) { icon.pixmap = LoadPNG("icons/graphics-window/" + icon.name + ".png"); } if(paint) { glColor4d(0, 0, 0, 1.0); Point2d o = { (double)(x - icon.pixmap.width / 2), (double)(y - icon.pixmap.height / 2) }; ssglDrawPixmap(icon.pixmap, o, /*flip=*/true); if(toolbarHovered == icon.command || (pending.operation == Pending::COMMAND && pending.command == icon.command)) { // Highlight the hovered or pending item. glColor4d(1, 1, 0, 0.3); int boxhw = 15; ssglAxisAlignedQuad(x+boxhw, x-boxhw, y+boxhw, y-boxhw); } if(toolbarTooltipped == icon.command) { // Display the tool tip for this item; postpone till later // so that no one draws over us. Don't need position since // that's just wherever the mouse is. toolTip.show = true; toolTip.str = icon.tooltip.c_str(); } } else { int boxhw = 16; if(mx < (x+boxhw) && mx > (x - boxhw) && my < (y+boxhw) && my > (y - boxhw)) { if(menuHit) *menuHit = icon.command; } } if(leftpos) { x += 32; leftpos = false; } else { x -= 32; y -= 32; leftpos = true; } } if(paint) { // Do this last so that nothing can draw over it. if(toolTip.show) { ssglInitializeBitmapFont(); std::string str = toolTip.str; for(i = 0; SS.GW.menu[i].level >= 0; i++) { if(toolbarTooltipped == SS.GW.menu[i].id) { std::string accel = MakeAcceleratorLabel(SS.GW.menu[i].accel); if(!accel.empty()) { str += ssprintf(" (%s)", accel.c_str()); } break; } } int tw = str.length() * (SS.TW.CHAR_WIDTH - 1) + 10, th = SS.TW.LINE_HEIGHT + 2; double ox = toolbarMouseX + 3, oy = toolbarMouseY + 3; glLineWidth(1); glColor4d(1.0, 1.0, 0.6, 1.0); ssglAxisAlignedQuad(ox, ox+tw, oy, oy+th); glColor4d(0.0, 0.0, 0.0, 1.0); ssglAxisAlignedLineLoop(ox, ox+tw, oy, oy+th); glColor4d(0, 0, 0, 1); glPushMatrix(); glTranslated(ox+5, oy+3, 0); glScaled(1, -1, 1); ssglBitmapText(str, Vector::From(0, 0, 0)); glPopMatrix(); } ssglDepthRangeLockToFront(false); } return withinToolbar; }
bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my, bool paint, int *menuHit) { int i; int x = 17, y = (int)(height - 52); int fudge = 8; int h = 32*15 + 3*16 + fudge; int aleft = 0, aright = 66, atop = y+16+fudge/2, abot = y+16-h; bool withinToolbar = (mx >= aleft && mx <= aright && my <= atop && my >= abot); if(!paint && !withinToolbar) { // This gets called every MouseMove event, so return quickly. return false; } if(paint) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glTranslated(-1, -1, 0); glScaled(2.0/width, 2.0/height, 0); glDisable(GL_LIGHTING); double c = 30.0/255; glColor4d(c, c, c, 1.0); ssglAxisAlignedQuad(aleft, aright, atop, abot); } struct { bool show; const char *str; } toolTip = { false, NULL }; bool leftpos = true; for(i = 0; Toolbar[i].image; i++) { if(Toolbar[i].image == SPACER) { if(!leftpos) { leftpos = true; y -= 32; x -= 32; } y -= 16; if(paint) { // Draw a separator bar in a slightly different color. int divw = 30, divh = 2; glColor4d(0.17, 0.17, 0.17, 1); x += 16; y += 24; ssglAxisAlignedQuad(x+divw, x-divw, y+divh, y-divh); x -= 16; y -= 24; } continue; } if(paint) { glRasterPos2i(x - 12, y - 12); glDrawPixels(24, 24, GL_RGB, GL_UNSIGNED_BYTE, Toolbar[i].image); if(toolbarHovered == Toolbar[i].menu) { // Highlight the hovered or pending item. glColor4d(1, 1, 0, 0.3); int boxhw = 15; ssglAxisAlignedQuad(x+boxhw, x-boxhw, y+boxhw, y-boxhw); } if(toolbarTooltipped == Toolbar[i].menu) { // Display the tool tip for this item; postpone till later // so that no one draws over us. Don't need position since // that's just wherever the mouse is. toolTip.show = true; toolTip.str = Toolbar[i].tip; } } else { int boxhw = 16; if(mx < (x+boxhw) && mx > (x - boxhw) && my < (y+boxhw) && my > (y - boxhw)) { if(menuHit) *menuHit = Toolbar[i].menu; } } if(leftpos) { x += 32; leftpos = false; } else { x -= 32; y -= 32; leftpos = true; } } if(paint) { // Do this last so that nothing can draw over it. if(toolTip.show) { ssglCreateBitmapFont(); char str[1024]; if(strlen(toolTip.str) >= 200) oops(); strcpy(str, toolTip.str); for(i = 0; SS.GW.menu[i].level >= 0; i++) { if(toolbarTooltipped == SS.GW.menu[i].id) { char accelbuf[40]; if(MakeAcceleratorLabel(SS.GW.menu[i].accel, accelbuf)) { sprintf(str+strlen(str), " (%s)", accelbuf); } break; } } int tw = (int)strlen(str)*SS.TW.CHAR_WIDTH + 10, th = SS.TW.LINE_HEIGHT + 2; double ox = toolbarMouseX + 3, oy = toolbarMouseY + 3; glLineWidth(1); glColor4d(1.0, 1.0, 0.6, 1.0); ssglAxisAlignedQuad(ox, ox+tw, oy, oy+th); glColor4d(0.0, 0.0, 0.0, 1.0); ssglAxisAlignedLineLoop(ox, ox+tw, oy, oy+th); glColor4d(0, 0, 0, 1); glPushMatrix(); glTranslated(ox+5, oy+3, 0); glScaled(1, -1, 1); ssglBitmapText(str, Vector::From(0, 0, 0)); glPopMatrix(); } ssglDepthRangeLockToFront(false); } return withinToolbar; }
void Entity::DrawOrGetDistance(void) { if(!IsVisible()) return; Group *g = SK.GetGroup(group); switch(type) { case POINT_N_COPY: case POINT_N_TRANS: case POINT_N_ROT_TRANS: case POINT_N_ROT_AA: case POINT_IN_3D: case POINT_IN_2D: { Vector v = PointGetNum(); dogd.refp = v; if(dogd.drawing) { double s = 3.5; Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale); Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale); ssglColorRGB(Style::Color(Style::DATUM)); ssglDepthRangeOffset(6); glBegin(GL_QUADS); ssglVertex3v(v.Plus (r).Plus (d)); ssglVertex3v(v.Plus (r).Minus(d)); ssglVertex3v(v.Minus(r).Minus(d)); ssglVertex3v(v.Minus(r).Plus (d)); glEnd(); ssglDepthRangeOffset(0); } else { Point2d pp = SS.GW.ProjectPoint(v); dogd.dmin = pp.DistanceTo(dogd.mp) - 6; } break; } case NORMAL_N_COPY: case NORMAL_N_ROT: case NORMAL_N_ROT_AA: case NORMAL_IN_3D: case NORMAL_IN_2D: { int i; for(i = 0; i < 2; i++) { if(i == 0 && !SS.GW.showNormals) { // When the normals are hidden, we will continue to show // the coordinate axes at the bottom left corner, but // not at the origin. continue; } hRequest hr = h.request(); // Always draw the x, y, and z axes in red, green, and blue; // brighter for the ones at the bottom left of the screen, // dimmer for the ones at the model origin. int f = (i == 0 ? 100 : 255); if(hr.v == Request::HREQUEST_REFERENCE_XY.v) { ssglColorRGB(RGBi(0, 0, f)); } else if(hr.v == Request::HREQUEST_REFERENCE_YZ.v) { ssglColorRGB(RGBi(f, 0, 0)); } else if(hr.v == Request::HREQUEST_REFERENCE_ZX.v) { ssglColorRGB(RGBi(0, f, 0)); } else { ssglColorRGB(Style::Color(Style::NORMALS)); if(i > 0) break; } Quaternion q = NormalGetNum(); Vector tail; if(i == 0) { tail = SK.GetEntity(point[0])->PointGetNum(); glLineWidth(1); } else { // Draw an extra copy of the x, y, and z axes, that's // always in the corner of the view and at the front. // So those are always available, perhaps useful. double s = SS.GW.scale; double h = 60 - SS.GW.height/2; double w = 60 - SS.GW.width/2; tail = SS.GW.projRight.ScaledBy(w/s).Plus( SS.GW.projUp. ScaledBy(h/s)).Minus(SS.GW.offset); ssglDepthRangeLockToFront(true); glLineWidth(2); } Vector v = (q.RotationN()).WithMagnitude(50/SS.GW.scale); Vector tip = tail.Plus(v); LineDrawOrGetDistance(tail, tip); v = v.WithMagnitude(12/SS.GW.scale); Vector axis = q.RotationV(); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis, 0.6))); LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis,-0.6))); } ssglDepthRangeLockToFront(false); break; } case DISTANCE: case DISTANCE_N_COPY: // These are used only as data structures, nothing to display. break; case WORKPLANE: { Vector p; p = SK.GetEntity(point[0])->PointGetNum(); Vector u = Normal()->NormalU(); Vector v = Normal()->NormalV(); double s = (min(SS.GW.width, SS.GW.height))*0.45/SS.GW.scale; Vector us = u.ScaledBy(s); Vector vs = v.ScaledBy(s); Vector pp = p.Plus (us).Plus (vs); Vector pm = p.Plus (us).Minus(vs); Vector mm = p.Minus(us).Minus(vs), mm2 = mm; Vector mp = p.Minus(us).Plus (vs); glLineWidth(1); ssglColorRGB(Style::Color(Style::NORMALS)); glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0x1111); if(!h.isFromRequest()) { mm = mm.Plus(v.ScaledBy(60/SS.GW.scale)); mm2 = mm2.Plus(u.ScaledBy(60/SS.GW.scale)); LineDrawOrGetDistance(mm2, mm); } LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pm, mm2); LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mp, pp); glDisable(GL_LINE_STIPPLE); char *str = DescriptionString()+5; double th = DEFAULT_TEXT_HEIGHT; if(dogd.drawing) { ssglWriteText(str, th, mm2, u, v, NULL, NULL); } else { Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus( v.ScaledBy(ssglStrHeight(th)/2)); Point2d pp = SS.GW.ProjectPoint(pos); dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10); // If a line lies in a plane, then select the line, not // the plane. dogd.dmin += 3; } break; } case LINE_SEGMENT: case CIRCLE: case ARC_OF_CIRCLE: case CUBIC: case CUBIC_PERIODIC: case TTF_TEXT: // Nothing but the curve(s). break; case FACE_NORMAL_PT: case FACE_XPROD: case FACE_N_ROT_TRANS: case FACE_N_TRANS: case FACE_N_ROT_AA: // Do nothing; these are drawn with the triangle mesh break; default: oops(); } // And draw the curves; generate the rational polynomial curves for // everything, then piecewise linearize them, and display those. SEdgeList sel; ZERO(&sel); GenerateEdges(&sel, true); int i; for(i = 0; i < sel.l.n; i++) { SEdge *se = &(sel.l.elem[i]); LineDrawOrGetDistance(se->a, se->b, true); } sel.Clear(); }