Get rid of the command line from the text window; we'll say that's
just for display, and any text entry will happen via some floating text box, same as entering a dimension on the sketch. Add the hover and selection mechanism, which now seems to work. Still not clear how to do imported parts, for assemblies and hierarchy. The handle formats may still have to change. [git-p4: depot-paths = "//depot/solvespace/": change = 1662]
This commit is contained in:
parent
bf8ef7b196
commit
6c63d9c8cb
184
cmdline.cpp
184
cmdline.cpp
|
@ -1,20 +1,27 @@
|
|||
#include "solvespace.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#define COLOR_BG_HEADER RGB(50, 20, 50)
|
||||
const TextWindow::Color TextWindow::colors[] = {
|
||||
{ COLOR_FG_DEFAULT, COLOR_BG_DEFAULT, }, // 0
|
||||
{ RGB(170, 0, 0), COLOR_BG_DEFAULT, }, // 1
|
||||
{ RGB( 40, 255, 40), COLOR_BG_DEFAULT, }, // 2
|
||||
{ RGB(200, 200, 0), COLOR_BG_DEFAULT, }, // 3
|
||||
{ RGB(255, 200, 40), COLOR_BG_DEFAULT, }, // 4
|
||||
{ RGB(255, 40, 40), COLOR_BG_DEFAULT, }, // 5
|
||||
{ RGB( 0, 255, 255), COLOR_BG_DEFAULT, }, // 6
|
||||
{ RGB(255, 0, 255), COLOR_BG_DEFAULT, }, // 7
|
||||
{ RGB(255, 255, 255), COLOR_BG_DEFAULT, }, // 0
|
||||
|
||||
{ RGB(170, 0, 0), COLOR_BG_HEADER, }, // 1 hidden label
|
||||
{ RGB( 40, 255, 40), COLOR_BG_HEADER, }, // 2 shown label
|
||||
{ RGB(200, 200, 0), COLOR_BG_HEADER, }, // 3 mixed label
|
||||
{ RGB(255, 200, 40), COLOR_BG_HEADER, }, // 4 header text
|
||||
{ RGB( 0, 0, 0), COLOR_BG_DEFAULT, }, // 5
|
||||
{ RGB( 0, 0, 0), COLOR_BG_DEFAULT, }, // 6
|
||||
{ RGB( 0, 0, 0), COLOR_BG_DEFAULT, }, // 7
|
||||
|
||||
{ RGB(255, 255, 255), COLOR_BG_DEFAULT, }, // 8 title
|
||||
{ RGB(100, 100, 255), COLOR_BG_DEFAULT, }, // 9 link
|
||||
};
|
||||
|
||||
void TextWindow::Init(void) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
shown = &(showns[shownIndex]);
|
||||
|
||||
ClearScreen();
|
||||
ClearCommand();
|
||||
}
|
||||
|
||||
void TextWindow::ClearScreen(void) {
|
||||
|
@ -22,7 +29,7 @@ void TextWindow::ClearScreen(void) {
|
|||
for(i = 0; i < MAX_ROWS; i++) {
|
||||
for(j = 0; j < MAX_COLS; j++) {
|
||||
text[i][j] = ' ';
|
||||
meta[i][j].color = COLOR_NORMAL;
|
||||
meta[i][j].color = COLOR_DEFAULT;
|
||||
meta[i][j].link = NOT_A_LINK;
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +51,7 @@ void TextWindow::Printf(char *fmt, ...) {
|
|||
meta[r][c].link = NOT_A_LINK;
|
||||
}
|
||||
|
||||
int color = COLOR_NORMAL;
|
||||
int color = COLOR_DEFAULT;
|
||||
int link = NOT_A_LINK;
|
||||
DWORD data = 0;
|
||||
LinkFunction *f = NULL;
|
||||
|
@ -74,7 +81,7 @@ void TextWindow::Printf(char *fmt, ...) {
|
|||
break;
|
||||
}
|
||||
case 'E':
|
||||
color = COLOR_NORMAL;
|
||||
color = COLOR_DEFAULT;
|
||||
link = NOT_A_LINK;
|
||||
data = 0;
|
||||
f = NULL;
|
||||
|
@ -126,64 +133,69 @@ void TextWindow::Printf(char *fmt, ...) {
|
|||
|
||||
fmt++;
|
||||
}
|
||||
while(c < MAX_COLS) {
|
||||
meta[r][c].color = color;
|
||||
c++;
|
||||
}
|
||||
|
||||
done:
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void TextWindow::ClearCommand(void) {
|
||||
int j;
|
||||
for(j = 0; j < MAX_COLS; j++) {
|
||||
cmd[j] = ' ';
|
||||
}
|
||||
memcpy(cmd, "+> ", 3);
|
||||
cmdLen = 0;
|
||||
cmdInsert = 3;
|
||||
}
|
||||
|
||||
void TextWindow::ProcessCommand(char *cmd)
|
||||
{
|
||||
Printf("%C2command:%E '%s' done %C3(green)%E %C5%LaLink%E", cmd);
|
||||
}
|
||||
|
||||
void TextWindow::KeyPressed(int c) {
|
||||
if(cmdLen >= MAX_COLS - 10) {
|
||||
ClearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
if(c == '\n' || c == '\r') {
|
||||
cmd[cmdLen+3] = '\0';
|
||||
ProcessCommand(cmd+3);
|
||||
|
||||
ClearCommand();
|
||||
return;
|
||||
} else if(c == 27) {
|
||||
ClearCommand();
|
||||
} else if(c == 'l' - 'a' + 1) {
|
||||
ClearScreen();
|
||||
} else if(c == '\b') {
|
||||
// backspace, delete from insertion point
|
||||
if(cmdInsert <= 3) return;
|
||||
memmove(cmd+cmdInsert-1, cmd+cmdInsert, MAX_COLS-cmdInsert);
|
||||
cmdLen--;
|
||||
cmdInsert--;
|
||||
} else {
|
||||
cmd[cmdInsert] = c;
|
||||
cmdInsert++;
|
||||
cmdLen++;
|
||||
}
|
||||
}
|
||||
|
||||
void TextWindow::Show(void) {
|
||||
ShowRequestList();
|
||||
ShowHeader();
|
||||
switch(shown->screen) {
|
||||
default:
|
||||
shown->screen = SCREEN_GROUP_LIST;
|
||||
// fall through
|
||||
case SCREEN_GROUP_LIST:
|
||||
ShowGroupList();
|
||||
break;
|
||||
|
||||
case SCREEN_REQUEST_LIST:
|
||||
ShowRequestList();
|
||||
break;
|
||||
}
|
||||
InvalidateText();
|
||||
}
|
||||
|
||||
void TextWindow::OneScreenForward(void) {
|
||||
SS.TW.shownIndex++;
|
||||
if(SS.TW.shownIndex >= HISTORY_LEN) SS.TW.shownIndex = 0;
|
||||
SS.TW.shown = &(SS.TW.showns[SS.TW.shownIndex]);
|
||||
history++;
|
||||
}
|
||||
|
||||
void TextWindow::ScreenNavigaton(int link, DWORD v) {
|
||||
switch(link) {
|
||||
default:
|
||||
case 'h':
|
||||
SS.TW.OneScreenForward();
|
||||
SS.TW.shown->screen = SCREEN_GROUP_LIST;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if(SS.TW.history > 0) {
|
||||
SS.TW.shownIndex--;
|
||||
if(SS.TW.shownIndex < 0) SS.TW.shownIndex = (HISTORY_LEN-1);
|
||||
SS.TW.shown = &(SS.TW.showns[SS.TW.shownIndex]);
|
||||
SS.TW.history--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
SS.TW.OneScreenForward();
|
||||
break;
|
||||
}
|
||||
SS.TW.Show();
|
||||
}
|
||||
void TextWindow::ShowHeader(void) {
|
||||
ClearScreen();
|
||||
|
||||
Printf(" %Lb%f<<%E %Lh%fhome%E",
|
||||
(DWORD)(&TextWindow::ScreenNavigaton),
|
||||
(DWORD)(&TextWindow::ScreenNavigaton));
|
||||
|
||||
int datumColor;
|
||||
if(SS.GW.show2dCsyss && SS.GW.showAxes && SS.GW.showPoints) {
|
||||
datumColor = COLOR_MEANS_SHOWN;
|
||||
|
@ -194,19 +206,19 @@ void TextWindow::ShowHeader(void) {
|
|||
}
|
||||
|
||||
#define hs(b) ((b) ? COLOR_MEANS_SHOWN : COLOR_MEANS_HIDDEN)
|
||||
Printf("show: "
|
||||
"%Cp%Ll%D%f2d-csys%E "
|
||||
"%Cp%Ll%D%faxes%E "
|
||||
"%Cp%Ll%D%fpoints%E "
|
||||
"%Cp%Ll%fany-datum%E",
|
||||
Printf("%C4show: "
|
||||
"%Cp%Ll%D%f2d-csys%E%C4 "
|
||||
"%Cp%Ll%D%faxes%E%C4 "
|
||||
"%Cp%Ll%D%fpoints%E%C4 "
|
||||
"%Cp%Ll%fany-datum%E%C4",
|
||||
hs(SS.GW.show2dCsyss), (DWORD)&(SS.GW.show2dCsyss), &(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showAxes), (DWORD)&(SS.GW.showAxes), &(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showPoints), (DWORD)&(SS.GW.showPoints), &(SS.GW.ToggleBool),
|
||||
datumColor, &(SS.GW.ToggleAnyDatumShown)
|
||||
);
|
||||
Printf(" "
|
||||
"%Cp%Ll%D%fall-groups%E "
|
||||
"%Cp%Ll%D%fconstraints%E",
|
||||
Printf("%C4 "
|
||||
"%Cp%Ll%D%fall-groups%E%C4 "
|
||||
"%Cp%Ll%D%fconstraints%E%C4",
|
||||
hs(SS.GW.showAllGroups), (DWORD)(&SS.GW.showAllGroups),
|
||||
&(SS.GW.ToggleBool),
|
||||
hs(SS.GW.showConstraints), (DWORD)(&SS.GW.showConstraints),
|
||||
|
@ -215,32 +227,46 @@ void TextWindow::ShowHeader(void) {
|
|||
}
|
||||
|
||||
void TextWindow::ShowGroupList(void) {
|
||||
ShowHeader();
|
||||
|
||||
Printf("%C4[[all groups in sketch]]%E");
|
||||
Printf("%C8[[click group to view requests]]%E");
|
||||
int i;
|
||||
for(i = 0; i < SS.group.elems; i++) {
|
||||
Group *g = &(SS.group.elem[i].t);
|
||||
if(g->name.str[0]) {
|
||||
Printf(" %s", g->name.str);
|
||||
for(i = 0; i <= SS.group.elems; i++) {
|
||||
DWORD v;
|
||||
char *s;
|
||||
if(i == SS.group.elems) {
|
||||
s = "all requests from all groups";
|
||||
v = 0;
|
||||
} else {
|
||||
Printf(" unnamed");
|
||||
Group *g = &(SS.group.elem[i].t);
|
||||
s = g->DescriptionString();
|
||||
v = g->h.v;
|
||||
}
|
||||
Printf(" %C9%Ll%D%f%s%E", v, (DWORD)(&TextWindow::ScreenSelectGroup), s);
|
||||
}
|
||||
}
|
||||
void TextWindow::ScreenSelectGroup(int link, DWORD v) {
|
||||
SS.TW.OneScreenForward();
|
||||
|
||||
SS.TW.shown->screen = SCREEN_REQUEST_LIST;
|
||||
SS.TW.shown->group.v = v;
|
||||
|
||||
SS.TW.Show();
|
||||
}
|
||||
|
||||
void TextWindow::ShowRequestList(void) {
|
||||
ShowHeader();
|
||||
if(shown->group.v == 0) {
|
||||
Printf("%C8[[requests in all groups]]%E");
|
||||
} else {
|
||||
Group *g = SS.group.FindById(shown->group);
|
||||
Printf("%C8[[requests in group %s]]%E", g->DescriptionString());
|
||||
}
|
||||
|
||||
Printf("%C4[[all requests in sketch]]%E");
|
||||
int i;
|
||||
for(i = 0; i < SS.request.elems; i++) {
|
||||
Request *r = &(SS.request.elem[i].t);
|
||||
|
||||
if(r->name.str[0]) {
|
||||
Printf(" %s", r->name.str);
|
||||
} else {
|
||||
Printf(" unnamed");
|
||||
if(r->group.v == shown->group.v || shown->group.v == 0) {
|
||||
char *s = r->DescriptionString();
|
||||
Printf(" %s", s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
8
dsc.h
8
dsc.h
|
@ -19,7 +19,7 @@ public:
|
|||
Vector Normal(int which);
|
||||
Vector RotatedAbout(Vector axis, double theta);
|
||||
double Magnitude(void);
|
||||
Vector ScaledBy(double v);
|
||||
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
|
||||
|
@ -31,6 +31,12 @@ public:
|
|||
class Point2d {
|
||||
public:
|
||||
double x, y;
|
||||
|
||||
Point2d Plus(Point2d b);
|
||||
Point2d Minus(Point2d b);
|
||||
Point2d ScaledBy(double s);
|
||||
double DistanceTo(Point2d p);
|
||||
double DistanceToLine(Point2d p0, Point2d dp, bool segment);
|
||||
};
|
||||
|
||||
template <class T, class H>
|
||||
|
|
67
entity.cpp
67
entity.cpp
|
@ -1,13 +1,36 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
void Entity::LineDrawHitTest(Vector a, Vector b) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glxVertex3v(a);
|
||||
glxVertex3v(b);
|
||||
glEnd();
|
||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
if(dogd.drawing) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glxVertex3v(a);
|
||||
glxVertex3v(b);
|
||||
glEnd();
|
||||
} else {
|
||||
Point2d ap = SS.GW.ProjectPoint(a);
|
||||
Point2d bp = SS.GW.ProjectPoint(b);
|
||||
|
||||
double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true);
|
||||
dogd.dmin = min(dogd.dmin, d);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::Draw(void) {
|
||||
dogd.drawing = true;
|
||||
DrawOrGetDistance();
|
||||
}
|
||||
|
||||
double Entity::GetDistance(Point2d mp) {
|
||||
dogd.drawing = false;
|
||||
dogd.mp = mp;
|
||||
dogd.dmin = 1e12;
|
||||
|
||||
DrawOrGetDistance();
|
||||
|
||||
return dogd.dmin;
|
||||
}
|
||||
|
||||
void Entity::DrawOrGetDistance(void) {
|
||||
switch(type) {
|
||||
case CSYS_2D: {
|
||||
if(!SS.GW.show2dCsyss) break;
|
||||
|
@ -15,7 +38,7 @@ void Entity::Draw(void) {
|
|||
Vector p;
|
||||
double a, b, c, d;
|
||||
|
||||
SS.point.FindById(point(16))->GetInto(&p);
|
||||
p = SS.point.FindById(point(16))->GetCoords();
|
||||
a = SS.param.FindById(param(0))->val;
|
||||
b = SS.param.FindById(param(1))->val;
|
||||
c = SS.param.FindById(param(2))->val;
|
||||
|
@ -26,28 +49,28 @@ void Entity::Draw(void) {
|
|||
|
||||
double s = (min(SS.GW.width, SS.GW.height))*0.4;
|
||||
|
||||
Vector pp = (p.Plus(u)).Plus(v);
|
||||
Vector pm = (p.Plus(u)).Minus(v);
|
||||
Vector mm = (p.Minus(u)).Minus(v);
|
||||
Vector mp = (p.Minus(u)).Plus(v);
|
||||
Vector pp = p.Plus (u).Plus (v);
|
||||
Vector pm = p.Plus (u).Minus(v);
|
||||
Vector mm = p.Minus(u).Minus(v);
|
||||
Vector mp = p.Minus(u).Plus (v);
|
||||
pp = pp.ScaledBy(s);
|
||||
pm = pm.ScaledBy(s);
|
||||
mm = mm.ScaledBy(s);
|
||||
mp = mp.ScaledBy(s);
|
||||
|
||||
LineDrawHitTest(pp, pm);
|
||||
LineDrawHitTest(pm, mm);
|
||||
LineDrawHitTest(mm, mp);
|
||||
LineDrawHitTest(mp, pp);
|
||||
LineDrawOrGetDistance(pp, pm);
|
||||
LineDrawOrGetDistance(pm, mm);
|
||||
LineDrawOrGetDistance(mm, mp);
|
||||
LineDrawOrGetDistance(mp, pp);
|
||||
|
||||
Request *r = SS.request.FindById(this->request());
|
||||
glPushMatrix();
|
||||
glxTranslatev(mm);
|
||||
glxOntoCsys(u, v);
|
||||
glxWriteText(r->name.str);
|
||||
glPopMatrix();
|
||||
|
||||
glEnd();
|
||||
if(dogd.drawing) {
|
||||
Request *r = SS.request.FindById(this->request());
|
||||
glPushMatrix();
|
||||
glxTranslatev(mm);
|
||||
glxOntoCsys(u, v);
|
||||
glxWriteText(r->DescriptionString());
|
||||
glPopMatrix();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
27
expr.h
27
expr.h
|
@ -12,16 +12,21 @@ public:
|
|||
// if we know that the param table won't move around)
|
||||
static const int PARAM_PTR = 1;
|
||||
|
||||
static const int CONSTANT = 10;
|
||||
static const int PLUS = 21;
|
||||
static const int MINUS = 22;
|
||||
static const int TIMES = 23;
|
||||
static const int DIV = 24;
|
||||
static const int NEGATE = 25;
|
||||
static const int SQRT = 26;
|
||||
static const int SQUARE = 27;
|
||||
static const int SIN = 28;
|
||||
static const int COS = 29;
|
||||
// These are used only for user-entered expressions.
|
||||
static const int POINT = 10;
|
||||
static const int ENTITY = 11;
|
||||
|
||||
static const int CONSTANT = 20;
|
||||
|
||||
static const int PLUS = 100;
|
||||
static const int MINUS = 101;
|
||||
static const int TIMES = 102;
|
||||
static const int DIV = 103;
|
||||
static const int NEGATE = 104;
|
||||
static const int SQRT = 105;
|
||||
static const int SQUARE = 106;
|
||||
static const int SIN = 107;
|
||||
static const int COS = 108;
|
||||
|
||||
int op;
|
||||
Expr *a;
|
||||
|
@ -29,6 +34,8 @@ public:
|
|||
union {
|
||||
hParam parh;
|
||||
double *parp;
|
||||
hPoint point;
|
||||
hEntity entity;
|
||||
double v;
|
||||
} x;
|
||||
};
|
||||
|
|
109
graphicswin.cpp
109
graphicswin.cpp
|
@ -35,7 +35,9 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
};
|
||||
|
||||
void GraphicsWindow::Init(void) {
|
||||
offset.x = offset.y = offset.z = 0.9;
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
offset.x = offset.y = offset.z = 0;
|
||||
scale = 1;
|
||||
projRight.x = 1; projRight.y = projRight.z = 0;
|
||||
projDown.y = 1; projDown.z = projDown.x = 0;
|
||||
|
@ -55,10 +57,23 @@ void GraphicsWindow::NormalizeProjectionVectors(void) {
|
|||
projRight = projRight.ScaledBy(1/projRight.Magnitude());
|
||||
}
|
||||
|
||||
Point2d GraphicsWindow::ProjectPoint(Vector p) {
|
||||
p = p.Plus(offset);
|
||||
|
||||
Point2d r;
|
||||
r.x = p.Dot(projRight) * scale;
|
||||
r.y = p.Dot(projDown) * scale;
|
||||
return r;
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||
bool middleDown, bool rightDown, bool shiftDown, bool ctrlDown)
|
||||
{
|
||||
Point2d mp = { x, y };
|
||||
|
||||
if(middleDown) {
|
||||
hover.Clear();
|
||||
|
||||
double dx = (x - orig.mouse.x) / scale;
|
||||
double dy = (y - orig.mouse.y) / scale;
|
||||
|
||||
|
@ -90,6 +105,57 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|||
orig.mouse.y = y;
|
||||
|
||||
InvalidateGraphics();
|
||||
} else {
|
||||
// No mouse buttons are pressed. We just need to do our usual hit
|
||||
// testing, to see if anything ought to be hovered.
|
||||
Selection s;
|
||||
HitTestMakeSelection(mp, &s);
|
||||
if(!s.Equals(&hover)) {
|
||||
hover = s;
|
||||
InvalidateGraphics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsWindow::Selection::Equals(Selection *b) {
|
||||
if(point.v != b->point.v) return false;
|
||||
if(entity.v != b->entity.v) return false;
|
||||
return true;
|
||||
}
|
||||
bool GraphicsWindow::Selection::IsEmpty(void) {
|
||||
if(point.v) return false;
|
||||
if(entity.v) return false;
|
||||
return true;
|
||||
}
|
||||
void GraphicsWindow::Selection::Clear(void) {
|
||||
point.v = entity.v = 0;
|
||||
}
|
||||
void GraphicsWindow::Selection::Draw(void) {
|
||||
if(point.v) SS.point. FindById(point )->Draw();
|
||||
if(entity.v) SS.entity.FindById(entity)->Draw();
|
||||
}
|
||||
|
||||
void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
||||
int i;
|
||||
double d, dmin = 1e12;
|
||||
|
||||
dest->point.v = 0;
|
||||
dest->entity.v = 0;
|
||||
|
||||
for(i = 0; i < SS.entity.elems; i++) {
|
||||
d = SS.entity.elem[i].t.GetDistance(mp);
|
||||
if(d < 10 && d < dmin) {
|
||||
dest->point.v = 0;
|
||||
dest->entity = SS.entity.elem[i].t.h;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < SS.point.elems; i++) {
|
||||
d = SS.point.elem[i].t.GetDistance(mp);
|
||||
if(d < 10 && d < dmin) {
|
||||
dest->entity.v = 0;
|
||||
dest->point = SS.point.elem[i].t.h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +168,27 @@ void GraphicsWindow::MouseMiddleDown(double x, double y) {
|
|||
}
|
||||
|
||||
void GraphicsWindow::MouseLeftDown(double x, double y) {
|
||||
// Make sure the hover is up to date.
|
||||
MouseMoved(x, y, false, false, false, false, false);
|
||||
|
||||
if(!hover.IsEmpty()) {
|
||||
int i;
|
||||
for(i = 0; i < MAX_SELECTED; i++) {
|
||||
if(selection[i].Equals(&hover)) {
|
||||
selection[i].Clear();
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < MAX_SELECTED; i++) {
|
||||
if(selection[i].IsEmpty()) {
|
||||
selection[i] = hover;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
// I guess we ran out of slots, oh well.
|
||||
done:
|
||||
InvalidateGraphics();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseScroll(double x, double y, int delta) {
|
||||
|
@ -176,11 +263,29 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glColor3f(1, 1, 1);
|
||||
|
||||
int i;
|
||||
|
||||
// First, draw the entire scene.
|
||||
glColor3f(1, 1, 1);
|
||||
for(i = 0; i < SS.entity.elems; i++) {
|
||||
SS.entity.elem[i].t.Draw();
|
||||
}
|
||||
glColor3f(0, 0.8f, 0);
|
||||
for(i = 0; i < SS.point.elems; i++) {
|
||||
SS.point.elem[i].t.Draw();
|
||||
}
|
||||
|
||||
// Then redraw whatever the mouse is hovering over, highlighted. Have
|
||||
// to disable the depth test, so that we can overdraw.
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glColor3f(1, 1, 0);
|
||||
hover.Draw();
|
||||
|
||||
// And finally draw the selection, same mechanism.
|
||||
glColor3f(1, 0, 0);
|
||||
for(i = 0; i < MAX_SELECTED; i++) {
|
||||
selection[i].Draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
53
sketch.cpp
53
sketch.cpp
|
@ -7,6 +7,16 @@ const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
|
|||
const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 };
|
||||
const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 };
|
||||
|
||||
char *Group::DescriptionString(void) {
|
||||
static char ret[100];
|
||||
if(name.str[0]) {
|
||||
sprintf(ret, "g%03x-%s", h.v, name.str);
|
||||
} else {
|
||||
sprintf(ret, "g%03x-(unnamed)", h.v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Request::AddParam(Entity *e, int index) {
|
||||
Param pa;
|
||||
memset(&pa, 0, sizeof(pa));
|
||||
|
@ -67,6 +77,16 @@ c: {
|
|||
}
|
||||
}
|
||||
|
||||
char *Request::DescriptionString(void) {
|
||||
static char ret[100];
|
||||
if(name.str[0]) {
|
||||
sprintf(ret, "r%03x-%s", h.v, name.str);
|
||||
} else {
|
||||
sprintf(ret, "r%03x-(unnamed)", h.v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Param::ForceTo(double v) {
|
||||
val = v;
|
||||
known = true;
|
||||
|
@ -85,16 +105,41 @@ void Point::ForceTo(Vector v) {
|
|||
}
|
||||
}
|
||||
|
||||
void Point::GetInto(Vector *v) {
|
||||
Vector Point::GetCoords(void) {
|
||||
Vector v;
|
||||
switch(type) {
|
||||
case IN_FREE_SPACE:
|
||||
v->x = SS.param.FindById(param(0))->val;
|
||||
v->y = SS.param.FindById(param(1))->val;
|
||||
v->z = SS.param.FindById(param(2))->val;
|
||||
v.x = SS.param.FindById(param(0))->val;
|
||||
v.y = SS.param.FindById(param(1))->val;
|
||||
v.z = SS.param.FindById(param(2))->val;
|
||||
break;
|
||||
|
||||
default:
|
||||
oops();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void Point::Draw(void) {
|
||||
Vector v = GetCoords();
|
||||
|
||||
double s = 4;
|
||||
Vector r = SS.GW.projRight.ScaledBy(4/SS.GW.scale);
|
||||
Vector d = SS.GW.projDown.ScaledBy(4/SS.GW.scale);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glxVertex3v(v.Plus (r).Plus (d));
|
||||
glxVertex3v(v.Plus (r).Minus(d));
|
||||
glxVertex3v(v.Minus(r).Minus(d));
|
||||
glxVertex3v(v.Minus(r).Plus (d));
|
||||
glEnd();
|
||||
}
|
||||
|
||||
double Point::GetDistance(Point2d mp) {
|
||||
Vector v = GetCoords();
|
||||
Point2d pp = SS.GW.ProjectPoint(v);
|
||||
|
||||
return pp.DistanceTo(mp);
|
||||
}
|
||||
|
||||
|
|
22
sketch.h
22
sketch.h
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
hEntity csys; // or Entity::NO_CSYS, if it's not locked in a 2d csys
|
||||
NameStr name;
|
||||
|
||||
char *DescriptionString(void);
|
||||
};
|
||||
|
||||
// A user request for some primitive or derived operation; for example a
|
||||
|
@ -83,6 +85,8 @@ public:
|
|||
|
||||
void AddParam(Entity *e, int index);
|
||||
void Generate(void);
|
||||
|
||||
char *DescriptionString(void);
|
||||
};
|
||||
|
||||
class Entity {
|
||||
|
@ -104,8 +108,15 @@ public:
|
|||
inline hPoint point(int i)
|
||||
{ hPoint r; r.v = ((this->h.v) << 8) | i; return r; }
|
||||
|
||||
void LineDrawHitTest(Vector a, Vector b);
|
||||
struct {
|
||||
bool drawing;
|
||||
Point2d mp;
|
||||
double dmin;
|
||||
} dogd; // state for drawing or getting distance (for hit testing)
|
||||
void LineDrawOrGetDistance(Vector a, Vector b);
|
||||
void DrawOrGetDistance(void);
|
||||
void Draw(void);
|
||||
double GetDistance(Point2d mp);
|
||||
};
|
||||
|
||||
class Param {
|
||||
|
@ -137,12 +148,13 @@ public:
|
|||
// The point, in base coordinates. This may be a single parameter, or
|
||||
// it may be a more complex expression if our point is locked in a
|
||||
// 2d csys.
|
||||
Expr *x(void);
|
||||
Expr *y(void);
|
||||
Expr *z(void);
|
||||
void GetExprs(Expr **x, Expr **y, Expr **z);
|
||||
Vector GetCoords(void);
|
||||
|
||||
void ForceTo(Vector v);
|
||||
void GetInto(Vector *v);
|
||||
|
||||
void Draw(void);
|
||||
double GetDistance(Point2d mp);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,8 +23,8 @@ void dbp(char *str, ...);
|
|||
|
||||
class Expr;
|
||||
#include "dsc.h"
|
||||
#include "ui.h"
|
||||
#include "sketch.h"
|
||||
#include "ui.h"
|
||||
#include "expr.h"
|
||||
|
||||
// From the platform-specific code.
|
||||
|
|
55
ui.h
55
ui.h
|
@ -11,9 +11,6 @@ public:
|
|||
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16))
|
||||
#endif
|
||||
static const int COLOR_BG_DEFAULT = RGB( 15, 15, 0);
|
||||
static const int COLOR_FG_DEFAULT = RGB(255, 255, 255);
|
||||
static const int COLOR_BG_CMDLINE = RGB( 0, 20, 80);
|
||||
static const int COLOR_FG_CMDLINE = RGB(255, 255, 255);
|
||||
|
||||
typedef struct {
|
||||
int fg;
|
||||
|
@ -25,18 +22,11 @@ public:
|
|||
static const int COLOR_MEANS_SHOWN = 2;
|
||||
static const int COLOR_MEANS_MIXED = 3;
|
||||
|
||||
// The line with the user-typed command, that is currently being edited.
|
||||
char cmd[MAX_COLS];
|
||||
int cmdInsert;
|
||||
int cmdLen;
|
||||
|
||||
// The rest of the window, text displayed in response to typed commands;
|
||||
// some of this might do something if you click on it.
|
||||
|
||||
static const int NOT_A_LINK = 0;
|
||||
|
||||
static const int COLOR_NORMAL = 0;
|
||||
|
||||
BYTE text[MAX_ROWS][MAX_COLS];
|
||||
typedef void LinkFunction(int link, DWORD v);
|
||||
struct {
|
||||
|
@ -52,21 +42,29 @@ public:
|
|||
void Printf(char *fmt, ...);
|
||||
void ClearScreen(void);
|
||||
|
||||
void ClearCommand(void);
|
||||
|
||||
void ProcessCommand(char *cmd);
|
||||
|
||||
// These are called by the platform-specific code.
|
||||
void KeyPressed(int c);
|
||||
bool IsHyperlink(int width, int height);
|
||||
|
||||
void Show(void);
|
||||
|
||||
// State for the screen that we are showing in the text window.
|
||||
static const int SCREEN_GROUP_LIST = 0;
|
||||
static const int SCREEN_REQUEST_LIST = 1;
|
||||
typedef struct {
|
||||
int screen;
|
||||
hGroup group;
|
||||
} ShownState;
|
||||
static const int HISTORY_LEN = 16;
|
||||
ShownState showns[HISTORY_LEN];
|
||||
int shownIndex;
|
||||
int history;
|
||||
ShownState *shown;
|
||||
|
||||
void ShowHeader(void);
|
||||
// These are self-contained screens, that show some information about
|
||||
// the sketch.
|
||||
void ShowGroupList(void);
|
||||
void ShowRequestList(void);
|
||||
void OneScreenForward(void);
|
||||
static void ScreenSelectGroup(int link, DWORD v);
|
||||
static void ScreenNavigaton(int link, DWORD v);
|
||||
};
|
||||
|
||||
class GraphicsWindow {
|
||||
|
@ -81,6 +79,8 @@ public:
|
|||
} MenuEntry;
|
||||
static const MenuEntry menu[];
|
||||
|
||||
void Init(void);
|
||||
|
||||
// The width and height (in pixels) of the window.
|
||||
double width, height;
|
||||
// These parameters define the map from 2d screen coordinates to the
|
||||
|
@ -97,9 +97,26 @@ public:
|
|||
Point2d mouse;
|
||||
} orig;
|
||||
|
||||
void Init(void);
|
||||
void NormalizeProjectionVectors(void);
|
||||
Point2d ProjectPoint(Vector p);
|
||||
|
||||
// The current selection.
|
||||
class Selection {
|
||||
public:
|
||||
hPoint point;
|
||||
hEntity entity;
|
||||
|
||||
void Draw(void);
|
||||
|
||||
void Clear(void);
|
||||
bool IsEmpty(void);
|
||||
bool Equals(Selection *b);
|
||||
};
|
||||
Selection hover;
|
||||
static const int MAX_SELECTED = 32;
|
||||
Selection selection[MAX_SELECTED];
|
||||
void HitTestMakeSelection(Point2d mp, Selection *dest);
|
||||
|
||||
// This sets what gets displayed.
|
||||
bool show2dCsyss;
|
||||
bool showAxes;
|
||||
|
|
45
util.cpp
45
util.cpp
|
@ -160,4 +160,49 @@ Vector Vector::ScaledBy(double v) {
|
|||
return r;
|
||||
}
|
||||
|
||||
Point2d Point2d::Plus(Point2d b) {
|
||||
Point2d r;
|
||||
r.x = x + b.x;
|
||||
r.y = y + b.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
Point2d Point2d::Minus(Point2d b) {
|
||||
Point2d r;
|
||||
r.x = x - b.x;
|
||||
r.y = y - b.y;
|
||||
return r;
|
||||
}
|
||||
|
||||
Point2d Point2d::ScaledBy(double s) {
|
||||
Point2d r;
|
||||
r.x = x*s;
|
||||
r.y = y*s;
|
||||
return r;
|
||||
}
|
||||
|
||||
double Point2d::DistanceTo(Point2d p) {
|
||||
double dx = x - p.x;
|
||||
double dy = y - p.y;
|
||||
return sqrt(dx*dx + dy*dy);
|
||||
}
|
||||
|
||||
double Point2d::DistanceToLine(Point2d p0, Point2d dp, bool segment) {
|
||||
double m = dp.x*dp.x + dp.y*dp.y;
|
||||
if(m < 0.05) return 1e12;
|
||||
|
||||
// Let our line be p = p0 + t*dp, for a scalar t from 0 to 1
|
||||
double t = (dp.x*(x - p0.x) + dp.y*(y - p0.y))/m;
|
||||
|
||||
if((t < 0 || t > 1) && segment) {
|
||||
// The closest point is one of the endpoints; determine which.
|
||||
double d0 = DistanceTo(p0);
|
||||
double d1 = DistanceTo(p0.Plus(dp));
|
||||
|
||||
return min(d1, d0);
|
||||
} else {
|
||||
Point2d closest = p0.Plus(dp.ScaledBy(t));
|
||||
return DistanceTo(closest);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,11 +58,9 @@ static void PaintTextWnd(HDC hdc)
|
|||
FillRect(backDc, &rect, hbr);
|
||||
|
||||
SelectObject(backDc, FixedFont);
|
||||
SetTextColor(backDc, SS.TW.COLOR_FG_DEFAULT);
|
||||
SetBkColor(backDc, SS.TW.COLOR_BG_DEFAULT);
|
||||
|
||||
int rows = height / TEXT_HEIGHT;
|
||||
rows--;
|
||||
TextWndRows = rows;
|
||||
|
||||
TextWndScrollPos = min(TextWndScrollPos, SS.TW.rows - rows);
|
||||
|
@ -101,21 +99,10 @@ static void PaintTextWnd(HDC hdc)
|
|||
}
|
||||
}
|
||||
|
||||
SetTextColor(backDc, SS.TW.COLOR_FG_CMDLINE);
|
||||
SetBkColor(backDc, SS.TW.COLOR_BG_CMDLINE);
|
||||
TextOut(backDc, 4, rows*TEXT_HEIGHT+1, SS.TW.cmd, SS.TW.MAX_COLS);
|
||||
|
||||
HPEN cpen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
|
||||
SelectObject(backDc, cpen);
|
||||
int y = (rows+1)*TEXT_HEIGHT - 3;
|
||||
MoveToEx(backDc, 4+(SS.TW.cmdInsert*TEXT_WIDTH), y, NULL);
|
||||
LineTo(backDc, 4+(SS.TW.cmdInsert*TEXT_WIDTH)+TEXT_WIDTH, y);
|
||||
|
||||
// And commit the back buffer
|
||||
BitBlt(hdc, 0, 0, width, height, backDc, 0, 0, SRCCOPY);
|
||||
DeleteObject(backBitmap);
|
||||
DeleteObject(hbr);
|
||||
DeleteObject(cpen);
|
||||
DeleteDC(backDc);
|
||||
}
|
||||
|
||||
|
@ -232,18 +219,13 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_CHAR:
|
||||
SS.TW.KeyPressed(wParam);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_SIZE: {
|
||||
RECT r;
|
||||
GetWindowRect(TextWndScrollBar, &r);
|
||||
int sw = r.right - r.left;
|
||||
GetClientRect(hwnd, &r);
|
||||
MoveWindow(TextWndScrollBar, r.right - sw, r.top, sw,
|
||||
(r.bottom - r.top) - TEXT_HEIGHT, TRUE);
|
||||
(r.bottom - r.top), TRUE);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
}
|
||||
|
@ -300,12 +282,6 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||
LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_CHAR:
|
||||
SS.TW.KeyPressed(wParam);
|
||||
SetForegroundWindow(TextWnd);
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
break;
|
||||
|
||||
|
@ -433,7 +409,8 @@ static void CreateMainWindows(void)
|
|||
if(!RegisterClassEx(&wc)) oops();
|
||||
|
||||
HMENU top = CreateGraphicsWindowMenus();
|
||||
GraphicsWnd = CreateWindowEx(0, "GraphicsWnd", "SolveSpace (View Sketch)",
|
||||
GraphicsWnd = CreateWindowEx(0, "GraphicsWnd",
|
||||
"SolveSpace (Graphics Window)",
|
||||
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX | WS_CLIPSIBLINGS,
|
||||
600, 300, 200, 200, NULL, top, Instance, NULL);
|
||||
|
@ -452,7 +429,7 @@ static void CreateMainWindows(void)
|
|||
// We get the desired Alt+Tab behaviour by specifying that the text
|
||||
// window is a child of the graphics window.
|
||||
TextWnd = CreateWindowEx(0,
|
||||
"TextWnd", "SolveSpace (Command Line)",
|
||||
"TextWnd", "SolveSpace (Text Window)",
|
||||
WS_THICKFRAME | WS_CLIPCHILDREN,
|
||||
10, 10, 600, 300, GraphicsWnd, (HMENU)NULL, Instance, NULL);
|
||||
if(!TextWnd) oops();
|
||||
|
|
Loading…
Reference in New Issue
Block a user