solvespace/request.cpp
Jonathan Westhues 9723f4e44f Add support for a clipboard, with cut, copy, and paste. This works
only in a workplane; but this means that plane sketches are
conveniently transformed from one plane to another.

Also tweak snap to grid to ignore unsnappable entities instead of
triggering an error, and to remove arbitrary limit on the number of
entities / comments that will be snapped.

[git-p4: depot-paths = "//depot/solvespace/": change = 2084]
2009-12-04 00:08:41 -08:00

192 lines
6.1 KiB
C++

#include "solvespace.h"
const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 };
const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 };
const EntReqTable::TableEntry EntReqTable::Table[] = {
// request type entity type pts xtra? norml dist description
{ Request::WORKPLANE, Entity::WORKPLANE, 1, false, true, false, "workplane" },
{ Request::DATUM_POINT, 0, 1, false, false, false, "datum-point" },
{ Request::LINE_SEGMENT, Entity::LINE_SEGMENT, 2, false, false, false, "line-segment" },
{ Request::CUBIC, Entity::CUBIC, 4, true, false, false, "cubic-bezier" },
{ Request::CUBIC_PERIODIC, Entity::CUBIC_PERIODIC, 3, true, false, false, "periodic-cubic" },
{ Request::CIRCLE, Entity::CIRCLE, 1, false, true, true, "circle" },
{ Request::ARC_OF_CIRCLE, Entity::ARC_OF_CIRCLE, 3, false, true, false, "arc-of-circle" },
{ Request::TTF_TEXT, Entity::TTF_TEXT, 2, false, true, false, "ttf-text" },
{ 0 },
};
char *EntReqTable::DescriptionForRequest(int req) {
for(int i = 0; Table[i].reqType; i++) {
if(req == Table[i].reqType) {
return Table[i].description;
}
}
return "???";
}
void EntReqTable::CopyEntityInfo(const TableEntry *te, int extraPoints,
int *ent, int *req, int *pts, bool *hasNormal, bool *hasDistance)
{
int points = te->points;
if(te->useExtraPoints) points += extraPoints;
if(ent) *ent = te->entType;
if(req) *req = te->reqType;
if(pts) *pts = points;
if(hasNormal) *hasNormal = te->hasNormal;
if(hasDistance) *hasDistance = te->hasDistance;
}
bool EntReqTable::GetRequestInfo(int req, int extraPoints,
int *ent, int *pts, bool *hasNormal, bool *hasDistance)
{
for(int i = 0; Table[i].reqType; i++) {
const TableEntry *te = &(Table[i]);
if(req == te->reqType) {
CopyEntityInfo(te, extraPoints,
ent, NULL, pts, hasNormal, hasDistance);
return true;
}
}
return false;
}
bool EntReqTable::GetEntityInfo(int ent, int extraPoints,
int *req, int *pts, bool *hasNormal, bool *hasDistance)
{
for(int i = 0; Table[i].reqType; i++) {
const TableEntry *te = &(Table[i]);
if(ent == te->entType) {
CopyEntityInfo(te, extraPoints,
NULL, req, pts, hasNormal, hasDistance);
return true;
}
}
return false;
}
int EntReqTable::GetRequestForEntity(int ent) {
int req;
GetEntityInfo(ent, 0, &req, NULL, NULL, NULL);
return req;
}
void Request::Generate(IdList<Entity,hEntity> *entity,
IdList<Param,hParam> *param)
{
int points = 0;
int et = 0;
bool hasNormal = false;
bool hasDistance = false;
int i;
Entity e;
ZERO(&e);
EntReqTable::GetRequestInfo(type, extraPoints,
&et, &points, &hasNormal, &hasDistance);
// Generate the entity that's specific to this request.
e.type = et;
e.extraPoints = extraPoints;
e.group = group;
e.style = style;
e.workplane = workplane;
e.construction = construction;
e.str.strcpy(str.str);
e.font.strcpy(font.str);
e.h = h.entity(0);
// And generate entities for the points
for(i = 0; i < points; i++) {
Entity p;
memset(&p, 0, sizeof(p));
p.workplane = workplane;
// points start from entity 1, except for datum point case
p.h = h.entity(i+(et ? 1 : 0));
p.group = group;
p.style = style;
if(workplane.v == Entity::FREE_IN_3D.v) {
p.type = Entity::POINT_IN_3D;
// params for x y z
p.param[0] = AddParam(param, h.param(16 + 3*i + 0));
p.param[1] = AddParam(param, h.param(16 + 3*i + 1));
p.param[2] = AddParam(param, h.param(16 + 3*i + 2));
} else {
p.type = Entity::POINT_IN_2D;
// params for u v
p.param[0] = AddParam(param, h.param(16 + 3*i + 0));
p.param[1] = AddParam(param, h.param(16 + 3*i + 1));
}
entity->Add(&p);
e.point[i] = p.h;
}
if(hasNormal) {
Entity n;
memset(&n, 0, sizeof(n));
n.workplane = workplane;
n.h = h.entity(32);
n.group = group;
n.style = style;
if(workplane.v == Entity::FREE_IN_3D.v) {
n.type = Entity::NORMAL_IN_3D;
n.param[0] = AddParam(param, h.param(32+0));
n.param[1] = AddParam(param, h.param(32+1));
n.param[2] = AddParam(param, h.param(32+2));
n.param[3] = AddParam(param, h.param(32+3));
} else {
n.type = Entity::NORMAL_IN_2D;
// and this is just a copy of the workplane quaternion,
// so no params required
}
if(points < 1) oops();
// The point determines where the normal gets displayed on-screen;
// it's entirely cosmetic.
n.point[0] = e.point[0];
entity->Add(&n);
e.normal = n.h;
}
if(hasDistance) {
Entity d;
memset(&d, 0, sizeof(d));
d.workplane = workplane;
d.h = h.entity(64);
d.group = group;
d.style = style;
d.type = Entity::DISTANCE;
d.param[0] = AddParam(param, h.param(64));
entity->Add(&d);
e.distance = d.h;
}
if(et) entity->Add(&e);
}
char *Request::DescriptionString(void) {
char *s;
if(h.v == Request::HREQUEST_REFERENCE_XY.v) {
s = "#XY";
} else if(h.v == Request::HREQUEST_REFERENCE_YZ.v) {
s = "#YZ";
} else if(h.v == Request::HREQUEST_REFERENCE_ZX.v) {
s = "#ZX";
} else {
s = EntReqTable::DescriptionForRequest(type);
}
static char ret[100];
sprintf(ret, "r%03x-%s", h.v, s);
return ret;
}
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
Param pa;
memset(&pa, 0, sizeof(pa));
pa.h = hp;
param->Add(&pa);
return hp;
}