00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <math.h>
00011 #include <windows.h>
00012 #include <commctrl.h>
00013
00014 #include "struct.h"
00015 #include "dstruct.h"
00016
00017 #include "draft.h"
00018
00019 typedef struct tagMENUHELPDATA{
00020 int iCode;
00021 char *str;
00022 } MENUHELPDATA;
00023
00024
00025 #if __X__MIPS__
00026 BOOL WINAPI _CRT_INIT(HINSTANCE ,DWORD , LPVOID );
00027 #endif
00028
00029 #define PAGESIZE 2048
00030 #define BOUND(x,min,max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
00031
00032 static BOOL bSpaceDown=FALSE,bCtrlDown=FALSE;
00033 static HWND hParent,hInfo;
00034 static HINSTANCE hThisInstance;
00035 static char *szViewClass="OFX:BezierClass";
00036 static char gszDir[256],gszFile[256];
00037 static SYSTEM_INFO sys_info;
00038 static int DisplayWidth,DisplayHeight,DisplayBits,DisplayPlanes,
00039 xScreen,yScreen,WoffX=0,WoffY=0,PanX,PanY;
00040 static char Title[]="Bezier Curve Drawing";
00041 static DWORD fdwStyle = WS_POPUP | WS_CAPTION | ! WS_SYSMENU |
00042 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME |
00043 WS_VSCROLL | WS_HSCROLL;
00044
00045
00046
00047 static HCURSOR hcurArrow=NULL,hcurPen1=NULL,hcurPen2=NULL,
00048 hcurNear=NULL,hcurPen3=NULL,hcurPen4=NULL,
00049 hcurPenA=NULL,hcurPenB=NULL,hcurHand=NULL;
00050
00051 #define NMENUHELPDATA 14
00052 static MENUHELPDATA MenuHelpData[NMENUHELPDATA]={
00053 0xFFFF, " ",
00054 IDM_OPEN, "Open a file containing a Bezier curve",
00055 IDM_SAVE, "Save changes in the current Bezier curve file",
00056 IDM_SAVEAS, "Save in a named Bezier curve file",
00057 IDM_ABORT, "Finish working with a 2D Bezier curve and return to the Modeler",
00058 IDM_VERTEX, "Where appropriate tools apply to individual vertices in a Bezier path",
00059 IDM_PATH, "Where appropriate tools apply to whole paths",
00060 IDM_BUILD, "Build curve in Modeler with vertices and edges following the Bezier curve",
00061 IDM_CLEAR, "Delete everthing",
00062 IDM_MOVE, "Move point, whole curve or set angle of curve",
00063 IDM_ADD, "Draw curve, click to place point, click and drag handles to set curvature, click back on first point to close",
00064 IDM_BEND, "Click on point to make corner, click and drag to set curvature, click and drag handle to make corner",
00065 IDM_DELETE, "Delete vertex or whole curve",
00066 IDM_INSERT, "Add point, click on vertex in path to insert vertex in front or on last vertex to add more vertices to path"
00067 };
00068
00069
00070 typedef struct tagPATHPOINT {
00071 int type,hand,bent;
00072 POINT p,p1,p2;
00073 double r;
00074 } PATHPOINT;
00075
00076 typedef struct tagPTH {
00077 struct tagPATHPOINT *pts;
00078 int n,closed;
00079 } PTH;
00080
00081 static PTH *pathlist=NULL;
00082
00083 static int tracetool=1,pathtool=0,panneltool=2,lasttracetool=1,lastpathtool=0;
00084 static int Np=0, Lp= -1,Lpp= -1,LastLp= -1, LastLpp=-1;
00085
00086
00087 static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam);
00088 static PSTR FileInPath(PSTR);
00089 static BOOL GetFilename(int, HWND, char *, char *);
00090 static BOOL MenuCommand(HWND hWnd, WORD id);
00091 static BOOL Bezier(void);
00092 static void MoveWholePath(int x, int y, HWND hwnd);
00093 static void DrawAll(HWND hwnd, HDC hDC);
00094 static int IdentifyPathVertex(int x, int y, int p);
00095 static BOOL GetVertexAtCursor(int x, int y, HWND hWnd,BOOL draw);
00096 static int GetTurnID(int x, int y, HWND hWnd);
00097 static void GetBezierPoint(double t, PATHPOINT *pl, PATHPOINT *p,
00098 long *xp, long *yp);
00099 static void BuildFromTrace(HWND hWnd);
00100 static void DeleteAllPath(void);
00101 static void DeleteOnePath(int id);
00102 static void DeletePathVertex(void);
00103 static int CreatePath(void);
00104 static int CreatePathPoint(int pa,int x,int y);
00105 static void GetXtraPoints(int, PATHPOINT *, PATHPOINT *, long *, long *);
00106 static void InsertVertex(void);
00107 static void ResetScreen(HWND);
00108 static void DrawFromPathPoint(BOOL, int ,int, POINT *, HWND, HDC);
00109 static void DrawPathPoint(int, int, HWND, HDC);
00110 static void DrawBezierCurve(HDC hDC, PATHPOINT *p, PATHPOINT *pl);
00111 static void BuildBezierCurve(PATHPOINT *p, PATHPOINT *pl,
00112 long Scale, BOOL fv);
00113
00114 static void WritePaths(void);
00115 static void ReadPaths(void);
00116 static void SetDraftCursor(BOOL bNearStart);
00117
00118 #include "draft0.c"
00119 #include "draft1.c"
00120
00121 #if 0
00122 static void AppendFileExtension(char *filename, char *ext){
00123 if(strrchr(filename,'.') == NULL){
00124 strcat(filename,ext);
00125 }
00126 }
00127 #endif
00128
00129
00130 static void GetShiftedCoords(long *lplParam,int xws,int yws){
00131 int xw,yw,dx,dy,dxa,dya;
00132 xw=(int)((short)LOWORD(*lplParam))+WoffX;
00133 yw=(int)((short)HIWORD(*lplParam))+WoffY;
00134 dx=xw-xws; dy=yw-yws; dxa=abs(dx); dya=abs(dy);
00135 if (dya < dxa/2)yw=yws;
00136 else if(dxa < dya/2)xw=xws;
00137 else if(dya < dxa)yw=yws+(int)((double)dxa*(double)dy/(double)dya);
00138 else if(dxa < dya)xw=xws+(int)((double)dya*(double)dx/(double)dxa);
00139 xw -= WoffX; yw -= WoffY;
00140 *lplParam=MAKELONG((short)xw,(short)yw);
00141 }
00142
00143 static BOOL Bezier(void){
00144 int i;
00145 MSG msg;
00146 HWND hDesktopWnd,hWnd;
00147 HDC hDCcaps;
00148 WNDCLASS wndclass;
00149 pathlist=NULL; Np=0;
00150 hDesktopWnd = GetDesktopWindow();
00151 hDCcaps = GetDC(hDesktopWnd);
00152 DisplayWidth= GetDeviceCaps(hDCcaps,HORZRES);
00153 DisplayHeight= GetDeviceCaps(hDCcaps,VERTRES);
00154 DisplayBits= GetDeviceCaps(hDCcaps,BITSPIXEL);
00155 DisplayPlanes= GetDeviceCaps(hDCcaps,PLANES);
00156 ReleaseDC(hDesktopWnd,hDCcaps);
00157 GetSystemInfo(&sys_info);
00158 wndclass.style = 0;
00159 wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
00160 wndclass.cbClsExtra = 0 ;
00161 wndclass.cbWndExtra = 0 ;
00162 wndclass.hInstance = hThisInstance ;
00163 wndclass.hIcon = NULL;
00164 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
00165 wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
00166 wndclass.lpszMenuName = "tracemenu" ;
00167 wndclass.lpszClassName = szViewClass;
00168 if (!RegisterClass (&wndclass)) return FALSE ;
00169 xScreen = GetSystemMetrics (SM_CXSCREEN) ;
00170 yScreen = GetSystemMetrics (SM_CYSCREEN) ;
00171 hWnd = CreateWindow(
00172 szViewClass,
00173 Title,
00174 fdwStyle,
00175 25,
00176 25,
00177 xScreen-50,
00178 yScreen-50,
00179 hParent,
00180 NULL,
00181 hThisInstance,
00182 NULL) ;
00183 if(hWnd == NULL)return FALSE;
00184 hcurArrow=LoadCursor(NULL, IDC_ARROW) ;
00185 hcurNear=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_NEAR));
00186 hcurPenA=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PENA));
00187 hcurPen1=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN1));
00188 hcurPen2=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN2));
00189 hcurPen3=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN3));
00190 hcurPenB=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PENB));
00191 hcurPen4=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_PEN4));
00192 hcurHand=LoadCursor(hThisInstance,MAKEINTRESOURCE(IDC_HAND));
00193 ShowWindow (hWnd,SW_SHOWNA);
00194 tracetool=1;
00195 OpenDraftToolbox(hWnd,hThisInstance);
00196 panneltool=2;
00197 SelectDraftTool(panneltool);
00198 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00199 while(GetMessage (&msg,NULL,0,0)){
00200 TranslateMessage (&msg);
00201 DispatchMessage (&msg);
00202 }
00203 DestroyDraftToolbox();
00204 DestroyWindow(hWnd);
00205 DeleteAllPath();
00206 if(hcurNear != NULL)DeleteObject(hcurNear);
00207 if(hcurPen1 != NULL)DeleteObject(hcurPen1);
00208 if(hcurPenA != NULL)DeleteObject(hcurPenA);
00209 if(hcurPen2 != NULL)DeleteObject(hcurPen2);
00210 if(hcurPen3 != NULL)DeleteObject(hcurPen3);
00211 if(hcurPenB != NULL)DeleteObject(hcurPenB);
00212 if(hcurPen4 != NULL)DeleteObject(hcurPen4);
00213 if(hcurHand != NULL)DeleteObject(hcurHand);
00214 UnregisterClass(wndclass.lpszClassName,wndclass.hInstance);
00215 return TRUE;
00216 }
00217
00218 static void SetDraftCursor(BOOL bNearStart){
00219 if(bSpaceDown)SetCursor(hcurHand);
00220 else if(bCtrlDown)SetCursor(hcurPenA);
00221 else if(bNearStart)SetCursor(hcurNear);
00222 else if(tracetool == 0 && !pathtool)SetCursor(hcurPenA);
00223 else if(tracetool == 1)SetCursor(hcurPen1);
00224 else if(tracetool == 2){
00225 if(pathtool)SetCursor(hcurPenB);
00226 else SetCursor(hcurPen2);
00227 }
00228 else if(tracetool == 3)SetCursor(hcurPen3);
00229 else if(tracetool == 4)SetCursor(hcurPen4);
00230 else SetCursor(hcurArrow);
00231 }
00232
00233 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,
00234 LPARAM lParam){
00235 static int TurnID=0,lpX,lpY,lpwX,lpwY,bAddStart=FALSE;
00236 static BOOL bToolCaptured=FALSE,bMoveFlag=FALSE,bFoundFlag=FALSE,
00237 bNearStart=FALSE,bStartTrace=FALSE;
00238 static POINT LastPt;
00239 int i,iPos,iMax,iMin,dn;
00240 PAINTSTRUCT ps;
00241 HDC hDC;
00242 RECT rc;
00243 POINT pt;
00244 PATHPOINT *pp;
00245 switch (iMessage) {
00246 case WM_ACTIVATE:
00247 SendMessage(hWnd,WM_NCACTIVATE,(WPARAM)TRUE,0);
00248 break;
00249 case WM_ACTIVATEAPP:
00250 if(hwndDraftTools != NULL){
00251 if((BOOL)wParam == TRUE)ShowWindow(hwndDraftTools,SW_SHOW);
00252 else ShowWindow(hwndDraftTools,SW_HIDE);
00253 }
00254 break;
00255 case WM_SETCURSOR:
00256 if(LOWORD(lParam) != HTCLIENT)
00257 return DefWindowProc(hWnd,iMessage,wParam,lParam);
00258 SetDraftCursor(bNearStart);
00259 break;
00260 case WM_KEYDOWN:
00261 case WM_KEYUP:
00262 case WM_SETFOCUS:
00263 if(!bToolCaptured){
00264 BOOL bCtrl;
00265 if(GetKeyState(VK_SPACE) & 0x8000)bSpaceDown=TRUE; else bSpaceDown=FALSE;
00266 if(GetKeyState(VK_CONTROL) & 0x8000)bCtrl=TRUE; else bCtrl=FALSE;
00267 if(bCtrl != bCtrlDown){
00268 if(bCtrl){
00269 LastLp=Lp; LastLpp=Lpp; TurnID=0;
00270 lasttracetool=tracetool; lastpathtool=pathtool;
00271 Lp=-1; Lpp=-1; tracetool=0;
00272 }
00273 else{
00274 if(Lp >= 0 && Lpp >= 0)pathlist[Lp].pts[Lpp].hand=0;
00275 Lp=LastLp; Lpp=LastLpp; TurnID=0;
00276 tracetool=lasttracetool; pathtool=lastpathtool;
00277 }
00278 bMoveFlag=!bMoveFlag;
00279 bCtrlDown=bCtrl;
00280 InvalidateRect(hWnd,NULL,FALSE);
00281 }
00282 }
00283 SetDraftCursor(bNearStart);
00284 break;
00285 case WM_KILLFOCUS:
00286 bSpaceDown=FALSE;
00287 bCtrlDown=FALSE;
00288 SetDraftCursor(bNearStart);
00289 break;
00290 case WM_NCMOUSEMOVE:
00291 if(bMoveFlag){
00292 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00293 bMoveFlag=FALSE;
00294 }
00295 break;
00296 case WM_CREATE:
00297 SetScrollRange(hWnd, SB_VERT, 0, PAGESIZE, TRUE);
00298 SetScrollRange(hWnd, SB_HORZ, 0, PAGESIZE, TRUE);
00299 GetClientRect(hWnd,&rc);
00300 SetScrollPos(hWnd, SB_HORZ, (PAGESIZE-rc.right)/2, TRUE);
00301 SetScrollPos(hWnd, SB_VERT, (PAGESIZE-rc.bottom)/2, TRUE);
00302 WoffX=GetScrollPos(hWnd,SB_HORZ);
00303 WoffY=GetScrollPos(hWnd,SB_VERT);
00304 break;
00305 case WM_DESTROY:
00306 break;
00307 case WM_COMMAND:
00308 return MenuCommand(hWnd,LOWORD(wParam));
00309 break;
00310 case WM_RBUTTONDOWN:
00311 break;
00312 case WM_LBUTTONDOWN:
00313 if(bToolCaptured)break;
00314 if(bMoveFlag){
00315 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00316 bMoveFlag=FALSE;
00317 }
00318 if(bSpaceDown){
00319 PanX=(short)LOWORD(lParam); PanY=(short)HIWORD(lParam);
00320 }
00321 else if(tracetool == 0){
00322 if(pathtool){
00323 bFoundFlag=GetVertexAtCursor(LOWORD(lParam)+WoffX,
00324 HIWORD(lParam)+WoffY,hWnd,FALSE);
00325 }
00326 else{
00327 bFoundFlag=GetVertexAtCursor(LOWORD(lParam)+WoffX,
00328 HIWORD(lParam)+WoffY,hWnd,TRUE);
00329 if(!bFoundFlag)TurnID=GetTurnID(LOWORD(lParam)+WoffX,
00330 HIWORD(lParam)+WoffY,hWnd);
00331 }
00332 if(bFoundFlag || TurnID > 0){
00333 lpwX=pathlist[Lp].pts[Lpp].p.x;
00334 lpwY=pathlist[Lp].pts[Lpp].p.y;
00335 }
00336 }
00337 else if(tracetool == 1){
00338 if(Lp < 0){
00339 Lp=CreatePath();
00340 Lpp=CreatePathPoint(Lp,LOWORD(lParam)+WoffX,HIWORD(lParam)+WoffY);
00341 }
00342 else{
00343 if(bNearStart){
00344 Lpp=0;
00345 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00346 pathlist[Lp].closed=1;
00347 }
00348 else{
00349 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00350 Lpp=CreatePathPoint(Lp,LOWORD(lParam)+WoffX,HIWORD(lParam)+WoffY);
00351 }
00352 }
00353 bAddStart=TRUE; lpX=(short)LOWORD(lParam); lpY=(short)HIWORD(lParam);
00354 lpwX=lpX+WoffX; lpwY=lpY+WoffY;
00355 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00356 }
00357 else if(tracetool == 2){
00358 if(GetVertexAtCursor(LOWORD(lParam)+WoffX,HIWORD(lParam)+WoffY,hWnd,FALSE)){
00359 if(pathtool)DeleteOnePath(Lp);
00360 else DeletePathVertex();
00361 InvalidateRect(hWnd,NULL,FALSE);
00362 }
00363 }
00364 else if(tracetool == 3){
00365 if(GetVertexAtCursor(LOWORD(lParam)+WoffX,HIWORD(lParam)+WoffY,hWnd,FALSE)){
00366 if(pathlist[Lp].closed == 0 && Lpp == pathlist[Lp].n - 1){
00367 bStartTrace=TRUE;
00368 SetCursor(hcurPen1);
00369 }
00370 else{
00371 InsertVertex();
00372 InvalidateRect(hWnd,NULL,FALSE);
00373 }
00374 }
00375 }
00376 else if(tracetool == 4){
00377 bFoundFlag=GetVertexAtCursor(LOWORD(lParam)+WoffX,
00378 HIWORD(lParam)+WoffY,hWnd,TRUE);
00379 if(!bFoundFlag)TurnID=GetTurnID(LOWORD(lParam)+WoffX,
00380 HIWORD(lParam)+WoffY,hWnd);
00381 else{
00382 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00383 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00384 pp=(pathlist[Lp].pts + Lpp); pp->type=0; pp->hand=0;
00385 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00386 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00387 }
00388 if(bFoundFlag || TurnID > 0){
00389 lpwX=pathlist[Lp].pts[Lpp].p.x;
00390 lpwY=pathlist[Lp].pts[Lpp].p.y;
00391 }
00392 }
00393 bToolCaptured=TRUE;
00394 SetCapture(hWnd);
00395 break;
00396 case WM_MOUSEMOVE:
00397 if(bMoveFlag){
00398 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00399 bMoveFlag=FALSE;
00400 }
00401 if(bSpaceDown){
00402 int iPosx,iPosy,dnx,dny;
00403 if(!bToolCaptured)break;
00404 GetScrollRange(hWnd, SB_HORZ, &iMin, &iMax);
00405 iPosx = GetScrollPos(hWnd, SB_HORZ);
00406 dnx=PanX-(short)LOWORD(lParam);
00407 dnx=BOUND(iPosx+dnx,iMin,iMax) - iPosx;
00408 GetScrollRange(hWnd, SB_VERT, &iMin, &iMax);
00409 iPosy = GetScrollPos(hWnd, SB_VERT);
00410 dny=PanY-(short)HIWORD(lParam);
00411 dny=BOUND(iPosy+dny,iMin,iMax) - iPosy;
00412 ScrollWindow(hWnd,-dnx,-dny,NULL,NULL);
00413 SetScrollPos(hWnd, SB_HORZ, iPosx + dnx, TRUE);
00414 SetScrollPos(hWnd, SB_VERT, iPosy + dny, TRUE);
00415 WoffX=GetScrollPos(hWnd,SB_HORZ);
00416 WoffY=GetScrollPos(hWnd,SB_VERT);
00417 PanX=(short)LOWORD(lParam); PanY=(short)HIWORD(lParam);
00418 break;
00419 }
00420 else if(tracetool == 0){
00421 if(pathtool){
00422 if(bFoundFlag){
00423 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00424 MoveWholePath(LOWORD(lParam)+WoffX,HIWORD(lParam)+WoffY,hWnd);
00425 }
00426 break;
00427 }
00428 if(bFoundFlag){
00429 int dx,dy;
00430 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00431 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00432 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00433 pp=(pathlist[Lp].pts + Lpp);
00434 dx=(short)LOWORD(lParam)+WoffX - pp->p.x;
00435 dy=(short)HIWORD(lParam)+WoffY - pp->p.y;
00436 pp->p.x += dx; pp->p.y += dy;
00437 if(pp->type == 1){
00438 pp->p1.x += dx; pp->p1.y += dy;
00439 pp->p2.x += dx; pp->p2.y += dy;
00440 }
00441 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00442 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00443 }
00444 else if(TurnID > 0){
00445 int dx,dy;
00446 double xxa,yya,ra;
00447 POINT *lpPta,*lpPtb;
00448 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00449 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00450 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00451 pp=(pathlist[Lp].pts + Lpp);
00452 if(pp->bent){
00453 if(TurnID == 1)lpPta=&(pp->p1); else lpPta=&(pp->p2);
00454 dx=(short)LOWORD(lParam)+WoffX - lpPta->x;
00455 dy=(short)HIWORD(lParam)+WoffY - lpPta->y;
00456 lpPta->x += dx; lpPta->y += dy;
00457 }
00458 else{
00459 if(TurnID == 1){lpPta=&(pp->p1); lpPtb=&(pp->p2);}
00460 else {lpPta=&(pp->p2); lpPtb=&(pp->p1);}
00461 dx=(short)LOWORD(lParam)+WoffX - lpPta->x;
00462 dy=(short)HIWORD(lParam)+WoffY - lpPta->y;
00463 lpPta->x += dx; lpPta->y += dy;
00464 xxa=(double)(lpPta->x - pp->p.x);
00465 yya=(double)(lpPta->y - pp->p.y);
00466 ra=sqrt(xxa*xxa+yya*yya);
00467 if(ra < 0.001)ra=1.0;
00468 xxa /= ra; yya /= ra;
00469 lpPtb->x=pp->p.x-(long)(xxa*pp->r);
00470 lpPtb->y=pp->p.y-(long)(yya*pp->r);
00471 }
00472 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00473 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00474 }
00475 }
00476 else if(tracetool == 1){
00477 if(bToolCaptured){
00478 if(Lp < 0 || Lpp < 0)break;
00479 if(bAddStart && abs((short)LOWORD(lParam)-lpX) < 3 &&
00480 abs((short)HIWORD(lParam)-lpY) < 3)break;
00481 bAddStart=FALSE;
00482 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00483 pp=(pathlist[Lp].pts + Lpp);
00484 pp->type=1; pp->hand=1;
00485 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00486 pp->p1.x=(short)LOWORD(lParam)+WoffX;
00487 pp->p1.y=(short)HIWORD(lParam)+WoffY;
00488 pp->p2.x=pp->p.x-(pp->p1.x-pp->p.x);
00489 pp->p2.y=pp->p.y-(pp->p1.y-pp->p.y);
00490 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00491 }
00492 else{
00493 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00494 LastPt.x=(short)LOWORD(lParam)+WoffX;
00495 LastPt.y=(short)HIWORD(lParam)+WoffY;
00496 if(Lpp > 0 && IdentifyPathVertex((int)LastPt.x,(int)LastPt.y,Lp) == 0){
00497 SetCursor(hcurNear);
00498 bNearStart=TRUE;
00499 }
00500 else bNearStart=FALSE;
00501 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00502 bMoveFlag=TRUE;
00503 }
00504 }
00505 else if(tracetool == 4){
00506 if(bFoundFlag){
00507 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00508 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00509 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00510 pp=(pathlist[Lp].pts + Lpp);
00511 pp->type=1; pp->hand=1; pp->bent=0;
00512 pp->p1.x=(short)LOWORD(lParam)+WoffX;
00513 pp->p1.y=(short)HIWORD(lParam)+WoffY;
00514 pp->p2.x=pp->p.x-(pp->p1.x-pp->p.x);
00515 pp->p2.y=pp->p.y-(pp->p1.y-pp->p.y);
00516 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00517 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00518 }
00519 else if(TurnID > 0){
00520 int dx,dy,n;
00521 POINT *lpPta;
00522 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00523 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00524 if(GetKeyState(VK_SHIFT) & 0x8000)GetShiftedCoords(&lParam,lpwX,lpwY);
00525 pp=(pathlist[Lp].pts + Lpp); pp->bent=1;
00526 if(TurnID == 1)lpPta=&(pp->p1); else lpPta=&(pp->p2);
00527 dx=(short)LOWORD(lParam)+WoffX - lpPta->x;
00528 dy=(short)HIWORD(lParam)+WoffY - lpPta->y;
00529 lpPta->x += dx; lpPta->y += dy;
00530 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00531 DrawPathPoint(Lp,Lpp+1,hWnd,NULL);
00532 }
00533 }
00534 break;
00535 case WM_LBUTTONUP:
00536 if(bToolCaptured){
00537 if(tracetool == 0){
00538 bFoundFlag=FALSE;
00539 TurnID=0;
00540 }
00541 else if(tracetool == 1){
00542 if(Lp >= 0 && Lpp >= 0){
00543 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00544 pp=(pathlist[Lp].pts + Lpp);
00545 pp->hand=0;
00546 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00547 }
00548 if(bNearStart){
00549 Lp= -1; Lpp= -1;
00550 bNearStart=FALSE;
00551 }
00552 else{
00553 LastPt.x=(short)LOWORD(lParam)+WoffX;
00554 LastPt.y=(short)HIWORD(lParam)+WoffY;
00555 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00556 bMoveFlag=TRUE;
00557 }
00558 }
00559 else if(tracetool == 3){
00560 if(bStartTrace){
00561 bStartTrace=FALSE;
00562 tracetool=1;
00563 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00564 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00565 panneltool=2;
00566 SelectDraftTool(panneltool);
00567 LastPt.x=(short)LOWORD(lParam)+WoffX;
00568 LastPt.y=(short)HIWORD(lParam)+WoffY;
00569 DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,NULL);
00570 bMoveFlag=TRUE;
00571 }
00572 }
00573 else if(tracetool == 4){
00574 bFoundFlag=FALSE;
00575 TurnID=0;
00576 }
00577 }
00578 bToolCaptured=FALSE;
00579 ReleaseCapture();
00580 SendMessage(hWnd,WM_KEYDOWN,0,0);
00581 break;
00582 case WM_PAINT:
00583 hDC = BeginPaint(hWnd, &ps);
00584 GetClientRect(hWnd,&rc);
00585 PatBlt(hDC,0,0,rc.right,rc.bottom,PATCOPY);
00586 DrawAll(hWnd,hDC);
00587 if(bMoveFlag)DrawFromPathPoint(bNearStart,Lp,Lpp,&LastPt,hWnd,hDC);
00588 EndPaint(hWnd,&ps);
00589 break ;
00590 case WM_MENUSELECT:
00591 bSpaceDown=FALSE;
00592 {
00593 HMENU hmenu;
00594 UINT fuFlags,uItem,id;
00595 hmenu=(HMENU)lParam;
00596 fuFlags=(UINT)HIWORD(wParam);
00597 uItem=(UINT)LOWORD(wParam);
00598 id=0;
00599 if(fuFlags == 0xFFFF)id=0;
00600 else if(fuFlags & MF_POPUP){;}
00601 else{
00602 for(i=0;i<NMENUHELPDATA;i++){
00603 if(uItem == MenuHelpData[i].iCode){id=(UINT)i; break;}
00604 }
00605 }
00606 SendMessage(hInfo,SB_SETTEXT,(WPARAM)0,(LPARAM)MenuHelpData[id].str);
00607 }
00608 break;
00609 case WM_VSCROLL:
00610
00611 GetScrollRange(hWnd, SB_VERT, &iMin, &iMax);
00612 iPos = GetScrollPos(hWnd, SB_VERT);
00613 GetClientRect(hWnd, &rc);
00614 switch (LOWORD(wParam)) {
00615 case SB_LINEDOWN: dn = rc.bottom / 16 + 1; break;
00616 case SB_LINEUP: dn = -rc.bottom / 16 + 1; break;
00617 case SB_PAGEDOWN: dn = rc.bottom / 2 + 1; break;
00618 case SB_PAGEUP: dn = -rc.bottom / 2 + 1; break;
00619 case SB_THUMBTRACK:
00620 case SB_THUMBPOSITION: dn = HIWORD(wParam)-iPos; break;
00621 default: dn = 0;
00622 }
00623
00624 if ((dn = BOUND(iPos + dn, iMin, iMax) - iPos) != 0) {
00625 ScrollWindow(hWnd, 0, -dn, NULL, NULL);
00626 SetScrollPos(hWnd, SB_VERT, iPos + dn, TRUE);
00627 }
00628 WoffY=GetScrollPos(hWnd,SB_VERT);
00629 break;
00630 case WM_HSCROLL:
00631
00632 GetScrollRange(hWnd, SB_HORZ, &iMin, &iMax);
00633 iPos = GetScrollPos(hWnd, SB_HORZ);
00634 GetClientRect (hWnd, &rc);
00635 switch (LOWORD(wParam)) {
00636 case SB_LINEDOWN: dn = rc.right / 16 + 1; break;
00637 case SB_LINEUP: dn = -rc.right / 16 + 1; break;
00638 case SB_PAGEDOWN: dn = rc.right / 2 + 1; break;
00639 case SB_PAGEUP: dn = -rc.right / 2 + 1; break;
00640 case SB_THUMBTRACK:
00641 case SB_THUMBPOSITION: dn = HIWORD(wParam) - iPos; break;
00642 default: dn = 0;
00643 }
00644
00645 if ((dn = BOUND(iPos + dn, iMin, iMax) - iPos) != 0) {
00646 ScrollWindow(hWnd, -dn, 0, NULL, NULL);
00647 SetScrollPos(hWnd, SB_HORZ, iPos + dn, TRUE);
00648 }
00649 WoffX=GetScrollPos(hWnd,SB_HORZ);
00650 break;
00651 case WM_SIZE:
00652 WoffX=GetScrollPos(hWnd,SB_HORZ);
00653 WoffY=GetScrollPos(hWnd,SB_VERT);
00654 InvalidateRect(hWnd,NULL,FALSE);
00655 return 0;
00656 default:
00657 return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
00658 }
00659 return 0L ;
00660 }
00661
00662 BOOL MenuCommand (HWND hWnd, WORD id){
00663 int i;
00664 switch (id) {
00665 case IDM_MOVE:
00666 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00667 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_GRAYED);
00668 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00669 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00670 EnableMenuItem(GetMenu(hWnd),IDM_BEND,MF_ENABLED);
00671 ResetScreen(hWnd);
00672 tracetool=0;
00673 if(pathtool == 0)panneltool=0; else panneltool=1;
00674 SelectDraftTool(panneltool);
00675 break;
00676 case IDM_ADD:
00677 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00678 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00679 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00680 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00681 EnableMenuItem(GetMenu(hWnd),IDM_BEND,MF_ENABLED);
00682 ResetScreen(hWnd);
00683 tracetool=1;
00684 panneltool=2;
00685 SelectDraftTool(panneltool);
00686 break;
00687 case IDM_DELETE:
00688 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00689 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00690 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_GRAYED);
00691 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00692 EnableMenuItem(GetMenu(hWnd),IDM_BEND,MF_ENABLED);
00693 ResetScreen(hWnd);
00694 tracetool=2;
00695 if(pathtool == 0)panneltool=4; else panneltool=5;
00696 SelectDraftTool(panneltool);
00697 break;
00698 case IDM_INSERT:
00699 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00700 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00701 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00702 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_GRAYED);
00703 EnableMenuItem(GetMenu(hWnd),IDM_BEND,MF_ENABLED);
00704 ResetScreen(hWnd);
00705 tracetool=3;
00706 panneltool=6;
00707 SelectDraftTool(panneltool);
00708 break;
00709 case IDM_BEND:
00710 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00711 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00712 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00713 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00714 EnableMenuItem(GetMenu(hWnd),IDM_BEND,MF_GRAYED);
00715 ResetScreen(hWnd);
00716 tracetool=4;
00717 panneltool=3;
00718 SelectDraftTool(panneltool);
00719 break;
00720 case IDM_PATH:
00721 EnableMenuItem(GetMenu(hWnd),IDM_VERTEX,MF_ENABLED);
00722 EnableMenuItem(GetMenu(hWnd),IDM_PATH,MF_GRAYED);
00723 ResetScreen(hWnd);
00724 pathtool=1;
00725 if(panneltool == 0)panneltool=1;
00726 else if(panneltool == 4)panneltool=5;
00727 SelectDraftTool(panneltool);
00728 break;
00729 case IDM_VERTEX:
00730 EnableMenuItem(GetMenu(hWnd),IDM_VERTEX,MF_GRAYED);
00731 EnableMenuItem(GetMenu(hWnd),IDM_PATH,MF_ENABLED);
00732 ResetScreen(hWnd);
00733 pathtool=0;
00734 if(panneltool == 1)panneltool=0;
00735 else if(panneltool == 5)panneltool=4;
00736 SelectDraftTool(panneltool);
00737 break;
00738 case IDM_TP_0:
00739 panneltool=0;
00740 if(pathtool == 1)SendMessage(hWnd,WM_COMMAND,IDM_VERTEX,0);
00741 SendMessage(hWnd,WM_COMMAND,IDM_MOVE,0);
00742 break;
00743 case IDM_TP_1:
00744 panneltool=1;
00745 if(pathtool == 0)SendMessage(hWnd,WM_COMMAND,IDM_PATH,0);
00746 SendMessage(hWnd,WM_COMMAND,IDM_MOVE,0);
00747 break;
00748 case IDM_TP_2:
00749 SendMessage(hWnd,WM_COMMAND,IDM_ADD,0);
00750 break;
00751 case IDM_TP_3:
00752 SendMessage(hWnd,WM_COMMAND,IDM_BEND,0);
00753 break;
00754 case IDM_TP_4:
00755 panneltool=4;
00756 if(pathtool == 1)SendMessage(hWnd,WM_COMMAND,IDM_VERTEX,0);
00757 SendMessage(hWnd,WM_COMMAND,IDM_DELETE,0);
00758 break;
00759 case IDM_TP_5:
00760 panneltool=5;
00761 if(pathtool == 0)SendMessage(hWnd,WM_COMMAND,IDM_PATH,0);
00762 SendMessage(hWnd,WM_COMMAND,IDM_DELETE,0);
00763 break;
00764 case IDM_TP_6:
00765 SendMessage(hWnd,WM_COMMAND,IDM_INSERT,0);
00766 break;
00767 case IDM_CLEAR:
00768 DeleteAllPath();
00769 ResetScreen(hWnd);
00770 EnableMenuItem(GetMenu(hWnd),IDM_SAVE,MF_GRAYED);
00771 SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)Title);
00772 break;
00773 case IDM_BUILD:
00774 BuildFromTrace(hWnd);
00775 DrawModel();
00776 break;
00777 case IDM_OPEN:
00778 if(GetFilename(0,hWnd,gszDir,gszFile)){
00779 EnableMenuItem(GetMenu(hWnd),IDM_SAVE,MF_ENABLED);
00780 ReadPaths();
00781 ResetScreen(hWnd);
00782 SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)gszFile);
00783 }
00784 break;
00785 case IDM_ABORT:
00786 SetCursor(hcurArrow);
00787 PostQuitMessage(0);
00788 break;
00789 case IDM_SAVE:
00790 if(Np == 0)break;
00791 WritePaths();
00792 break;
00793 case IDM_SAVEAS:
00794 if(Np == 0)break;
00795 if(GetFilename(1,hWnd,gszDir,gszFile)){
00796 AppendFileExtension(gszFile,".bph");
00797 WritePaths();
00798 EnableMenuItem(GetMenu(hWnd),IDM_SAVE,MF_ENABLED);
00799 SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)gszFile);
00800 }
00801 break;
00802 case IDM_CLOSETBX:
00803 DestroyDraftToolbox();
00804 break;
00805 default:
00806 break;
00807 }
00808 return TRUE;
00809 }
00810
00811 static void DrawAll(HWND hWnd, HDC hDC){
00812 int i,j,n;
00813 PATHPOINT *pp;
00814 if(Np == 0 || pathlist == NULL)return;
00815 for(i=0;i<Np;i++){
00816 pp=pathlist[i].pts;
00817 if(pp != NULL)for(j=0;j<pathlist[i].n;j++){
00818 DrawPathPoint(i,j,hWnd,hDC);
00819 }
00820 }
00821 }
00822
00823 static BOOL GetVertexAtCursor(int x, int y, HWND hWnd, BOOL draw){
00824 int i,j,n;
00825 PATHPOINT *pp;
00826 if(Np == 0 || pathlist == NULL)return FALSE;
00827 for(i=0;i<Np;i++){
00828 pp=pathlist[i].pts;
00829 if(pp != NULL)for(j=0;j<pathlist[i].n;j++,pp++){
00830 if(abs(x - pp->p.x) < 3 && abs(y - pp->p.y) < 3){
00831 if(Lp >= 0 && Lpp >= 0){
00832 if(draw){
00833 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00834 pathlist[Lp].pts[Lpp].hand=0;
00835 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00836 }
00837 }
00838 Lp=i; Lpp=j;
00839 if(draw){
00840 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00841 pathlist[Lp].pts[Lpp].hand=1;
00842 DrawPathPoint(Lp,Lpp,hWnd,NULL);
00843 }
00844 return TRUE;
00845 }
00846 }
00847 }
00848 return FALSE;
00849 }
00850
00851 static int IdentifyPathVertex(int x, int y, int p){
00852 int j;
00853 PATHPOINT *pp;
00854 if(p < 0)return -1;
00855 pp=pathlist[p].pts;
00856 if(pp != NULL)for(j=0;j<pathlist[p].n;j++,pp++){
00857 if(abs(x - pp->p.x) < 3 && abs(y - pp->p.y) < 3)return j;
00858 }
00859 return -1;
00860 }
00861
00862 static int GetTurnID(int x, int y, HWND hWnd){
00863 PATHPOINT *pp;
00864 double xxb,yyb;
00865 if(Lp < 0 || Lpp < 0)return 0;
00866 pp=(pathlist[Lp].pts+Lpp);
00867 if(pp->hand == 0 || pp->type == 0)return 0;
00868 if((Lpp < pathlist[Lp].n - 1 || pathlist[Lp].closed) &&
00869 abs(x - pp->p1.x) < 3 && abs(y - pp->p1.y) < 3){
00870 xxb=(double)(pp->p2.x - pp->p.x);
00871 yyb=(double)(pp->p2.y - pp->p.y);
00872 pp->r=sqrt(xxb*xxb+yyb*yyb);
00873 return 1;
00874 }
00875 if((Lpp > 0 || pathlist[Lp].closed) &&
00876 abs(x - pp->p2.x) < 3 && abs(y - pp->p2.y) < 3){
00877 xxb=(double)(pp->p1.x - pp->p.x);
00878 yyb=(double)(pp->p1.y - pp->p.y);
00879 pp->r=sqrt(xxb*xxb+yyb*yyb);
00880 return 2;
00881 }
00882 return 0;
00883 }
00884
00885 static void ResetScreen(HWND hWnd){
00886 if(Lp >= 0 && Lpp >= 0)pathlist[Lp].pts[Lpp].hand=0;
00887 Lp= -1; Lpp= -1;
00888 InvalidateRect(hWnd,NULL,FALSE);
00889 }
00890
00891 static PSTR FileInPath(PSTR pstrPath){
00892 PSTR pstr;
00893 pstr = pstrPath + strlen(pstrPath);
00894 while (pstr > pstrPath) {
00895 pstr = (AnsiPrev(pstrPath, pstr));
00896 if (*pstr == '\\' || *pstr == ':' || *pstr == '/') {
00897 pstr = (AnsiNext(pstr));
00898 break;
00899 }
00900 }
00901 return pstr;
00902 }
00903
00904 static BOOL GetFilename(int save, HWND parent, char *szdir, char *szfile){
00905 int i;
00906 OPENFILENAME ofn;
00907 char szFilter[60],szdummy[256];
00908 szdummy[0]='\0';
00909 strcpy(szFilter,"Bezier Paths|*.bph|");
00910 i=0; while(szFilter[i] != '\0'){
00911 if(szFilter[i] == '|')szFilter[i]='\0'; i++;
00912 }
00913 memset(&ofn,0,sizeof(OPENFILENAME));
00914 ofn.lStructSize=sizeof(OPENFILENAME);
00915 ofn.hwndOwner=parent;
00916 ofn.lpstrFilter=szFilter;
00917 ofn.nFilterIndex=1;
00918 ofn.lpstrFile=szfile;
00919 ofn.nMaxFile=255;
00920 ofn.lpstrFileTitle=szdummy;
00921 ofn.nMaxFileTitle=255;
00922 ofn.lpstrInitialDir=szdir;
00923 ofn.lpstrTitle="Bezier Paths File to Open";
00924 if(save){
00925 ofn.Flags=OFN_HIDEREADONLY|OFN_PATHMUSTEXIST;
00926 i=(int)(GetSaveFileName(&ofn));
00927 }
00928 else{
00929 ofn.Flags=OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
00930 i=(int)(GetOpenFileName(&ofn));
00931 }
00932 if(i){
00933 strcpy(szdummy,szfile);
00934 *AnsiPrev(szdummy,FileInPath(szdummy)) = '\0';
00935 strcpy(szdir,szdummy);
00936 return TRUE;
00937 }
00938 return FALSE;
00939 }
00940
00941 #if __WATCOMC__
00942 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00943 #elif __BC__
00944 BOOL WINAPI DllEntryPoint(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00945 #else
00946 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00947 #endif
00948 switch (dwReason) {
00949 case DLL_PROCESS_ATTACH: {
00950 #if __X__MIPS__
00951 if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00952 #endif
00953 hThisInstance=hDLL;
00954 break;
00955 }
00956 case DLL_PROCESS_DETACH:
00957 #if __X__MIPS__
00958 if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00959 #endif
00960 break;
00961 }
00962 return TRUE;
00963 }
00964
00965
00966 BOOL _BezierModeler
00967 (HWND parent_window, HWND info_window,X__STRUCTURE *lpevi){
00968 lpEVI=lpevi;
00969 tracetool=0;
00970 hParent=parent_window;
00971 hInfo=info_window;
00972 GetModuleFileName(hThisInstance,gszDir,255);
00973 *FileInPath(gszDir) = '\0';
00974 strcat(gszDir,"objects");
00975 gszFile[0]='\0';
00976 return Bezier();
00977 }