Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 1 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 1 2 #ifndef _global_h 3 # include "global.h" 9153 #endif 9154 9155 #include 9311 #ifndef VMS X 9312 #include X 9313 #else 9314 #include 9532 #endif 9533 9534 #ifndef _mat2_h 9535 # include "mat2.h" 10135 #endif 10136 #ifndef _objects_h 10137 # include "objects.H" 10743 #endif 10744 #ifndef _gifx_image_h 10745 # include "gifx_image.H" 10905 #endif 10906 #ifndef _imgbuff_h 10907 # include "imgbuff.H" 10950 #endif 10951 #ifndef _vec2_h X 10952 # include "vec2.h" X 10953 #endif 10954 #ifndef _vec2list_h X 10955 # include "vec2list.h" X 10956 #endif 10957 #ifndef _color_mapper_h 10958 # include "color_mapper.H" 10999 #endif 11000 #ifndef _puzzle_h 11001 # include "puzzle.H" 11068 #endif 11069 11070 11071 /****************************************************************************** 11072 11073 PieceFrame - corner, edge and pin-data of the piece including polygon-spline 11074 Vec2List *vl 11075 RotatedFrame - position-data including 11076 window-position, upward-angle and rotated polygin spline 11077 Vec2 winpos 11078 Real windir 11079 Vec2List *tvl 11080 BitmapPiece - pixmap with mask of the rotated Piece 11081 Pixmap tilemask 11082 PixmapPiece - pixmap with Puzzle-Image of the rotated Piece 11083 Pixmap tilemap 11084 ShadowPiece - pixmap with Puzzle-Image and ShadowFrame of the rotated Piece 11085 Pixmap shadowmask 11086 Pixmap shadowmap 11087 PieceObject - object subclass to be stack-controlled 11088 DBPieceObject - double buffered moves and turns 11089 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 2 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11090 ******************************************************************************/ 11091 11092 // . . . . + . . . . + . . . . + . . . . 11093 // . . . . . . . . . . . . . . . . . . . 11094 // . * . . . . . . . . . . . . . . . . . 11095 // . . . . . . . . . . . . . . . . . . . 11096 // . . . . . . . . . . . . . . . . . . . 11097 // . . . . + . . . . + . . . . + . . . . 11098 // . . . . . . . . . . . . . . . . . . . 11099 // . * . . . . . . . . . . . . . . . . . 11100 // . . . . . . . . . * . . * . . . . . . 11101 // . . * . . . . . . . . . . . . . . . . 11102 // . . . . * . * . . + . . . . + * . . . 11103 // . . . . . . . . . . . . . . . . . . . 11104 // . . . . . . . . . . . . . . . . . . . 11105 // . . . . . . . . . . . . . . . . . . . 11106 // . . . . . . . . . . . . . . . . . * . 11107 // . . . . + . . . . + . . . . + . . . . 11108 // . . . . . . . . . . . . . . . . . * . 11109 11110 double PieceFrameSetup::spx[] = { 1, 2.5, 5, 7, 7, 5, 5, 6, 8,13 }; 11111 double PieceFrameSetup::spy[] = { 13,12.5,11, 8, 5, 2, 0,-2,-3,-3 }; 11112 11113 11114 PieceFrameSetup::PieceFrameSetup() { 11115 } 11116 11117 PieceFrameSetup::~PieceFrameSetup() { 11118 } 11119 11120 void PieceFrameSetup::Init( const Vec2 &tl, const Vec2 &tr, const Vec2 &br, const Vec2 &bl ) { 11121 center = (tl+tr+br+bl)/4; 11122 v[0] = tl-center; 11123 v[1] = tr-center; 11124 v[2] = br-center; 11125 v[3] = bl-center; 11126 pin[0] = pin[1] = pin[2] = pin[3] = 0; 11127 11128 #if (0) X 11129 printf( "%g %g %g %g\n", (double)tl.X(), (double)tl.Y(), (double)tr.X(), (double)tr.Y() ); X 11130 printf( "center: %g %g\n", (double)center.X(), (double)center.Y() ); X 11131 printf( "%g %g %g %g\n", (double)bl.X(), (double)bl.Y(), (double)br.X(), (double)br.Y() ); X 11132 #endif 11133 } 11134 11135 void PieceFrame::PositionChanged() {} 11136 void PieceFrame::DirectionChanged() {} 11137 11138 PieceFrame::PieceFrame() { 11139 vl = 0; 11140 join_count=1; 11141 } 11142 11143 PieceFrame::~PieceFrame() { 11144 if (vl) delete vl; 11145 } 11146 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 3 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11147 const Vec2List &PieceFrame::Init( const PieceFrameSetup &pfs ) { 11148 11149 center=pfs.center; 11150 vl = new Vec2List(MaxSplineLen); 11151 11152 for (int i=0;i<4;i++) { 11153 Vec2 s(pfs.v[i]); 11154 11155 if (pfs.pin[i]) { 11156 int j; 11157 Vec2 e(pfs.v[(i+1)%4]); // end of segment 11158 Vec2 d=e-s; // edge vector 11159 11160 Vec2 m1=s+pfs.pin[i]*d; // medium point for pin 11161 Vec2 bw=(s-m1)/24.0; // backstep vector to startpoint 11162 Vec2 fw=(e-m1)/24.0; // forward vector to endpoint 11163 11164 Vec2 n=d/44; 11165 Vec2 o=(pfs.left[i]?n.TurnLeft():n.TurnRight()); 11166 11167 *vl |= s; 11168 for (j=1;j<=HalfSplineLen;j++) { 11169 *vl |= m1 + pfs.spx[HalfSplineLen-j]*bw + pfs.spy[HalfSplineLen-j]*o; 11170 } 11171 for (j=0;jwindir; 11214 11215 // check for correct page 11216 if (page!=obj->page) return 0; 11217 11218 // check for an angle between -10 and +10 degrees 11219 if (fmod(windir_delta+380.0,360.0)>40) return 0; 11220 11221 11222 Vec2 v1(center - obj->center); 11223 Vec2 v2(winpos - obj->winpos); 11224 Real help=fabs(windir-obj->windir); 11225 Real mid_angle; 11226 if (help>180.0) mid_angle=fmod((windir+obj->windir+360.0)/2,360.0); 11227 else mid_angle=fmod((windir+obj->windir)/2,360.0); 11228 Vec2 erg; 11229 v2=v2.TurnAngleDeg( -mid_angle ); 11230 11231 if (page) { erg=Vec2(v1.X()+v2.X(),v1.Y()-v2.Y()); 11232 } 11233 else erg=Vec2(v1.X()-v2.X(),v1.Y()-v2.Y()); 11234 11235 11236 #ifdef DEBUG X 11237 v2=v2.TurnAngleDeg( mid_angle ); X 11238 X 11239 printf( "ImageA: %6.2f %6.2f WindowA: %6.2f %6.2f at angle: %6.2f\n", X 11240 (double)center.X(), (double)center.Y(), (double)winpos.X(), (double)winpos.Y(), (double)windir ); X 11241 printf( "ImageB: %6.2f %6.2f WindowB: %6.2f %6.2f at angle: %6.2f\n", X 11242 (double)obj->center.X(), (double)obj->center.Y(), (double)obj->winpos.X(), (double)obj->winpos.Y(), X 11242 (double)obj->windir ); X 11243 printf( " %6.2f %6.2f %6.2f %6.2f\n", X 11244 (double)v1.X(), (double)v1.Y(), (double)v2.X(), (double)v2.Y() ); X 11245 X 11246 v2=v2.TurnAngleDeg( -mid_angle ); X 11247 X 11248 printf( " angle: %6.2f %6.2f %6.2f\n", X 11249 mid_angle, (double)v2.X(), (double)v2.Y() ); X 11250 printf( " %6.2f %6.2f\n", X 11251 (double)erg.X(), (double)erg.Y() ); X 11252 #endif 11253 11254 11255 if (erg.Norm()Len()); 11271 for (int i=0;iLen();i++) { 11272 tvl->AddAt(i,Vec2( -(*vl)[i].X(), (*vl)[i].Y() )); 11273 } 11274 } 11275 tvl->TurnAngleDeg(windir); 11276 } 11277 11278 // DoJoin: 11279 // A Joined segment in both polylines has to be found. When found 11280 // the points out of that segment are added from the second to the first 11281 // polyline, which will result into the merge of the two outlines. 11282 // 11283 // vl: +----+----+----+----+----+----+----+---- 11284 // 1 2 3 4 s j e 7 8 11285 // obj->vl: +----+----+----+---- 11286 // 1' e i s 4' 11287 // result: +----+----+----+----+----+----+----+----+----+---- 11288 // 1 2 3 4 s 4' 1' e 7 8 11289 // 11290 // special cases: 11291 // obj->vl: +----+----+----+---- 11292 // 1' 2' i s 4' 11293 // e 11294 11295 int RotatedFrame::FindStartForJoin( class PieceFrame *obj ) { 11296 int i,j; 11297 11298 for (i=0;ivl->Len();i++) { 11299 for (j=0;jLen();j++) { 11300 if (same_point(j,obj,i)) return i; 11301 } 11302 } 11303 return -1; 11304 } 11305 11306 int RotatedFrame::DoJoin( class RotatedFrame *obj, int i, int swap ) { 11307 int j,k; 11308 11309 for (j=0;jLen();j++) { 11310 if (same_point(j,obj,i)) { 11311 // found intersecting point: now find start and end of intersection 11312 int s,e; 11313 int sj; 11314 int ej; 11315 int c=1; 11316 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 6 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11317 for (s=1;svl->Len();s++) { 11318 int si=(i+s)%obj->vl->Len(); 11319 sj=((j-s)+vl->Len())%vl->Len(); 11320 if (!same_point(sj,obj,si)) break; 11321 c++; 11322 } 11323 s--; 11324 sj=((j-s)+vl->Len())%vl->Len(); 11325 for (e=1;evl->Len();e++) { 11326 int ei=((i-e)+obj->vl->Len())%obj->vl->Len(); 11327 ej=(j+e)%vl->Len(); 11328 if (!same_point(ej,obj,ei)) break; 11329 c++; 11330 } 11331 e--; 11332 ej=(j+e)%vl->Len(); 11333 11334 // found start and end of intersection as in shown in diagramm 11335 // now the points have to be moved to the destination polygon 11336 DBG2( "*** Range: %d %d\n", sj, ej ); 11337 if ((sj==ej)&&(c>1)) { 11338 // 11339 // when a surrounding tile is moved onto of the inner tile, the 11340 // problem arise that the whole inner tile and the partial surrounding 11341 // tile has to be deleted. Since this usually happens the other way round: 11342 // "The hole is filled with the inner tile.", this special case is reversed 11343 // by swapping both tiles and redoing the join, in which the partial list 11344 // of the surrounding tile will be found in sj - ej 11345 // 11346 DBG0( "*** special inner case: do reverse join\n" ); 11347 Vec2 help_center=center; 11348 center=obj->center; 11349 obj->center=help_center; 11350 11351 Vec2List *help_list=vl; 11352 vl=obj->vl; 11353 obj->vl=help_list; 11354 11355 return DoJoin(obj,j,1); 11356 } 11357 join_count+=obj->join_count; 11358 11359 vl->DelRange(sj,ej,&sj); 11360 11361 k=(-e+obj->vl->Len())%obj->vl->Len(); 11362 if ( k!=s || (sj==ej&&c==1) ) { 11363 DBG1( "*** Insert at: %d -", sj ); 11364 do { 11365 DBG1( " %d", (i+k)%obj->vl->Len() ); 11366 vl->AddAt(sj+1,(*obj->vl)(i+k)+obj->center-center); 11367 k=(k-1+obj->vl->Len())%obj->vl->Len(); 11368 } 11369 while( k!=s ); 11370 DBG0( "\n" ); 11371 } 11372 else { 11373 // an inner tile was removed from the polyline and therefore Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 7 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11374 // some kind of one way trail to the inner tile remained in the 11375 // polyline which should be removed with a tiny "garbage" collector. 11376 DBG1( "*** Garbage Deleted (from: %d)", vl->Len() ); 11377 for (j=0;jLen()-2;j++) { 11378 while (same_point(j,this,j+2)) { 11379 DBG1( "%d ", j ); 11380 vl->DelRange(j,j+2,&j); 11381 if (j>0) j--; 11382 } 11383 } 11384 DBG1( " (to: %d)\n", vl->Len() ); 11385 } 11386 11387 // the new extend has to be queried to setup the center 11388 Vec2 tl, br; 11389 vl->GetExtent( &tl, &br ); 11390 Vec2 new_center( center+((tl+br)/2) ); 11391 11392 #if (0) X 11393 printf( " center: %g %g\n", center.X(), center.Y() ); X 11394 printf( " from: %g %g\n", tl.X(), tl.Y() ); X 11395 printf( " to: %g %g\n", br.X(), br.Y() ); X 11396 printf( "new center: %g %g\n", new_center.X(), new_center.Y() ); X 11397 #endif 11398 11399 if (swap) { 11400 // this time the second objects position should be remained 11401 winpos = obj->winpos-(obj->center-new_center).ScaleX(page?-1:1).TurnAngleDeg 11401 (obj->windir); 11402 } 11403 else winpos -= (center-new_center).ScaleX(page?-1:1).TurnAngleDeg(windir); 11404 11405 *vl += (center-new_center); 11406 center=new_center; 11407 11408 PositionChanged(); 11409 DirectionChanged(); 11410 return 1; 11411 } 11412 } 11413 return 0; 11414 } 11415 11416 // =========================================================================== 11417 11418 FlipFrame::FlipFrame() { 11419 ftvl=0; 11420 itm=0; 11421 } 11422 11423 FlipFrame::~FlipFrame() { 11424 if (ftvl) delete ftvl; 11425 if (itm) delete itm; 11426 } 11427 11428 void FlipFrame::StartFlip( const Real &angle ) { 11429 mangle = angle; Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 8 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11430 } 11431 void FlipFrame::StopFlip() { 11432 if (ftvl) delete ftvl; 11433 ftvl=0; 11434 if (itm) delete itm; 11435 itm=0; 11436 } 11437 11438 void FlipFrame::SetFlip( const Real ¤t ) { 11439 if (ftvl) delete ftvl; 11440 if (itm) delete itm; 11441 11442 itm = new Mat2(); // set up transformation 11443 if (page) *itm = (*itm).ScaleX( -1 ); 11444 *itm = (*itm).RotateDeg( -windir ) 11445 .Rotate( mangle ) 11446 .ScaleX( current ) 11447 .Rotate( -mangle ); 11448 11449 11450 ftvl = new Vec2List(RotatedFrame::GetPolyLine(),*itm); 11451 *itm = !*itm; // reverse transformation for texture-mapping 11452 DirectionChanged(); 11453 } 11454 11455 Vec2List &FlipFrame::GetTPolyLine() { 11456 if (!ftvl) return *tvl; 11457 else return *ftvl; 11458 } 11459 11460 // =========================================================================== 11461 11462 GC BitmapPiece::gcb = 0; 11463 11464 BitmapPiece::BitmapPiece() { 11465 tilemask = 0; 11466 } 11467 BitmapPiece::~BitmapPiece() { 11468 DropBitmap(); 11469 } 11470 void BitmapPiece::DropBitmap() { 11471 if (tilemask) { 11472 XFreePixmap(dpy,tilemask); 11473 tilemask=0; 11474 } 11475 } 11476 11477 void BitmapPiece::PositionChanged() { 11478 winx = XPix(winpos.X())-offx; 11479 winy = YPix(winpos.Y())-offy; 11480 } 11481 11482 void BitmapPiece::DirectionChanged() { 11483 11484 DropBitmap(); 11485 FlipFrame::DirectionChanged(); 11486 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 9 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 11487 Vec2 tl,br; 11488 int x1,y1,x2,y2; 11489 const Vec2List &poly( GetTPolyLine() ); 11490 11491 poly.GetExtent( &tl, &br ); 11492 x1 = XPix(tl.X()); 11493 y1 = YPix(tl.Y()); 11494 x2 = XPix(br.X()); 11495 y2 = YPix(br.Y()); 11496 11497 offx = -x1; 11498 offy = -y1; 11499 winx = XPix(winpos.X())-offx; 11500 winy = YPix(winpos.Y())-offy; 11501 width = x2-x1+1; 11502 height = y2-y1+1; 11503 #if (0) X 11504 printf( "%g %g (%d %d)\n", (double)tl.X(), (double)tl.Y(), offx, offy ); X 11505 printf( "center: %g %g\n", (double)center.X(), (double)center.Y() ); X 11506 printf( " %g %g\n", (double)br.X(), (double)br.Y() ); X 11507 #endif 11508 11509 tilemask=XCreatePixmap(dpy,RootWindow(dpy,scr),width,height,1); 11510 if (!gcb) gcb=XCreateGC(dpy,tilemask,0,0); 11511 11512 XSetForeground(dpy,gcb,0); // clear the new bit 11512 map 11513 XFillRectangle(dpy,tilemask,gcb,0,0,width,height); 11514 11515 XSetForeground(dpy,gcb,1); // draw the polyline 11516 XPoint xpts[MaxSplineLen]; 11517 XPoint *xpts_p; 11518 if ((unsigned)poly.Len()>(sizeof(xpts)/sizeof(XPoint))) { 11519 xpts_p=new XPoint[poly.Len()]; // create buffer when necessary 11520 } 11521 else xpts_p=xpts; 11522 11523 for (int i=0;iIsTwinPixmap()) 12253 wcenter=Vec2( center.X(), pm->XHeight()+center.Y() ); 12254 else wcenter=center; 12255 12256 XCopyArea(dpy,pm->GetPixmap(),tilemap,gcp, 12257 XPix(wcenter.X())-offx, YPix(wcenter.Y())-offy, width, height, 0, 0 ); 12258 } 12259 else { 12260 switch(texture_mode) { 12261 case 1: CreateTilemap8(); break; 12262 case 2: CreateTilemap16(); break; 12263 case 3: CreateTilemap32(); break; 12264 } 12265 } 12266 } 12267 12268 void PixmapPiece::Redraw() { 12269 // printf( "winpos: %g %g\n", (double)winpos.X(), (double)winpos.Y() ); 12270 // printf( "offx: %d %d\n", offx, offy ); 12271 12272 XSetClipMask(dpy,gc,GetBitmap()); 12273 XSetClipOrigin(dpy,gc,winx,winy); 12274 12275 GetPixmap(); 12276 XCopyArea(dpy,tilemap,win,gc, 12277 0, 0, width, height, winx, winy ); 12278 } 12279 12280 // =========================================================================== 12281 12282 ShadowedPiece::ShadowedPiece() { 12283 shadowmap = 0; 12284 if (!gcp) gcp=XCreateGC(dpy,RootWindow(dpy,scr),0,0); 12285 12286 } 12287 ShadowedPiece::~ShadowedPiece() { 12288 DropPixmap(); 12289 } 12290 void ShadowedPiece::DropPixmap() { 12291 if (shadowmap) { 12292 XFreePixmap(dpy,shadowmap); 12293 shadowmap=0; 12294 XFreePixmap(dpy,shadowmask); 12295 } 12296 } 12297 12298 void ShadowedPiece::DirectionChanged() { 12299 int x; 12300 12301 DropPixmap(); 12302 PixmapPiece::DirectionChanged(); 12303 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 12 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12304 swidth = width + 2*ShadowSize(); 12305 sheight = height + 2*ShadowSize(); 12306 12307 // create mask of the shadowed tile 12308 shadowmask=XCreatePixmap(dpy,RootWindow(dpy,scr),swidth,sheight,1); 12309 12310 XSetForeground(dpy,gcb,0); 12311 XFillRectangle(dpy,shadowmask,gcb,0,0,swidth,sheight); 12312 12313 XSetFunction(dpy,gcb,GXor); 12314 for (x=0;x<=2*ShadowSize();x++) { 12315 XCopyArea(dpy,tilemask,shadowmask,gcb,0,0,width,height,x,x); 12316 } 12317 XSetFunction(dpy,gcb,GXcopy); 12318 12319 // create the tile 12320 shadowmap=XCreatePixmap(dpy,RootWindow(dpy,scr),swidth,sheight,DefaultDepth(dpy,scr)); 12321 12322 XSetForeground(dpy,gc,WhitePixel(dpy,scr)); 12323 XSetClipMask(dpy,gc,tilemask); 12324 for (x=0;x=swidth || y >=sheight) return 0; 12353 12354 help_image=XGetImage(dpy,shadowmask,x,y,1,1,1,XYPixmap); 12355 unsigned long erg=XGetPixel(help_image,0,0); 12356 XDestroyImage(help_image); 12357 return (int)erg; 12358 } 12359 12360 // =========================================================================== Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 13 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12361 12362 WindowPiece::WindowPiece() { 12363 swin=0; 12364 12365 } 12366 WindowPiece::~WindowPiece() { 12367 if (swin) XDestroyWindow( dpy, swin ); 12368 } 12369 12370 void WindowPiece::CreateWindow() { 12371 XSetWindowAttributes attrib; 12372 12373 swin=XCreateSimpleWindow(dpy,RootWindow(dpy,scr), 12374 winx,winy,swidth,sheight,0,WhitePixel(dpy,scr), port->AllocNamedColor( "grey50" ) ); 12375 attrib.bit_gravity=StaticGravity; 12376 attrib.override_redirect = True; 12377 XChangeWindowAttributes( dpy, swin, CWBitGravity|CWOverrideRedirect, &attrib ); 12378 XSelectInput(dpy,swin, ExposureMask|KeyPressMask|EnterWindowMask|ButtonPressMask|ButtonReleaseMask|ButtonMot 12378 ionMask); 12379 } 12380 12381 void WindowPiece::PositionChanged() { 12382 ShadowedPiece::PositionChanged(); 12383 12384 if (shapes) { 12385 if (swin) XMoveWindow( dpy, swin, winx, winy ); 12386 } 12387 } 12388 12389 void WindowPiece::DirectionChanged() { 12390 12391 ShadowedPiece::DirectionChanged(); 12392 12393 if (shapes) { 12394 if (!swin) { 12395 CreateWindow(); 12396 XShapeCombineMask(dpy,swin,0 /*Bounding*/,0,0,shadowmask,0 /*Set*/); 12397 XMapRaised(dpy,swin); 12398 } 12399 else { 12400 XMoveResizeWindow(dpy,swin,winx,winy,swidth,sheight); 12401 XShapeCombineMask(dpy,swin,0 /* Bounding */,0,0,shadowmask,0 /* Set */); 12402 } 12403 Redraw(); 12404 } 12405 } 12406 12407 void WindowPiece::Redraw() { 12408 XSetClipMask(dpy,gc,shadowmask); 12409 XSetClipOrigin(dpy,gc,0,0); 12410 12411 XCopyArea(dpy,shadowmap,swin,gc, 0, 0, swidth, sheight, 0, 0 ); 12412 } 12413 12414 // =========================================================================== 12415 12416 PieceObject::PieceObject() { Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 14 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12417 } 12418 12419 PieceObject::~PieceObject() { 12420 } 12421 12422 int PieceObject::Intersects(int x,int y,int w,int h) { 12423 if ( (x>winx+swidth) || (winx>x+w) 12424 || (y>winy+sheight) || (winy>y+h) ) return 0; 12425 else retu 12425 rn 1; 12426 } 12427 12428 int PieceObject::IsInside(int x,int y) { 12429 if ((x>=winx)&&(x=winy)&&(ydbmap,gc, 12440 0, 0, swidth, sheight, winx-x, winy-y ); 12441 } 12442 12443 void PieceObject::ExposeWindowRegion(Window w,int /*x*/,int /*y*/,int /*width*/,int /*height*/) { 12444 if (w==swin) { 12445 XSetClipMask(dpy,gc,shadowmask); 12446 XSetClipOrigin(dpy,gc,0,0); 12447 12448 XCopyArea(dpy,shadowmap,swin,gc, 0, 0, swidth, sheight, 0, 0 ); 12449 } 12450 } 12451 12452 void PieceObject::PanView( int ox, int oy ) { 12453 winpos-=Vec2(ox,oy); 12454 PositionChanged(); 12455 } 12456 12457 void PieceObject::ZoomView( int midx, int midy, int chg ) { 12458 double factor=((double)(zoom_factor+chg))/zoom_factor; 12459 12460 center = center * factor; 12461 *vl = *vl * factor; 12462 winpos = (winpos-Vec2(midx,midy)) * factor + Vec2(midx,midy); 12463 PositionChanged(); 12464 DirectionChanged(); 12465 } 12466 12467 // =========================================================================== 12468 12469 int DBPieceObject::x1; 12470 int DBPieceObject::y1; Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 15 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12471 int DBPieceObject::x2; 12472 int DBPieceObject::y2; 12473 12474 DBPieceObject::DBPieceObject() { 12475 } 12476 12477 DBPieceObject::~DBPieceObject() { 12478 } 12479 12480 void DBPieceObject::TurnOver( const Real &d ) { 12481 XDefineCursor( dpy, win, no_cursor ); 12482 XFlush(dpy); 12483 12484 Real a; 12485 Real start_windir=windir; 12486 12487 a=fmod(d-start_windir+360,360); 12488 if (a>180.0) a=a-360.0; 12489 12490 if (join_count<=maxturntiles) { 12491 double turnstart=GetCurrentTime()-0.1; 12492 double turntime=turntimebase+join_count*turntimedelta; 12493 double loop; 12494 for ( loop=0.1; loop<0.9; loop=(GetCurrentTime()-turnstart)/turntime) { 12495 StoreExtent(); 12496 SetDir( start_windir+loop*a ); 12497 UpdateExtent(); 12498 XSync(dpy,0); 12499 } 12500 } 12501 StoreExtent(); 12502 SetDir(d); 12503 UpdateExtent(); 12504 } 12505 12506 void DBPieceObject::FlipOver( const Vec2 &pos ) { 12507 XDefineCursor( dpy, win, no_cursor ); 12508 XFlush(dpy); 12509 12510 Vec2 wpos=pos; // button position after probable adjustment 12511 Real wa=winpos.AngleDeg(pos); // angle to button position 12512 12513 if (fmod(windir+5,90)<10) { // close to straight -> adjusted flip 12514 12515 // Probably round position for exact flips 12516 // int quart=(int)(fmod(wa+22,360)/45)&3; 12517 int quart=(int)(fmod(wa+45,360)/45)&2; 12518 12519 switch(quart) { 12520 case 0: { 12521 wpos=Vec2( pos.X(), winpos.Y() ); // horizontal flip 12522 break; 12523 } 12524 case 1: { 12525 Vec2 erg; 12525 // diagonal flip 1 12526 (pos-winpos).Split( Vec2(1,-1), &erg ); // project to diagonal Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 16 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12527 wpos=winpos+erg; 12528 break; 12529 } 12530 case 2: { 12531 wpos=Vec2( winpos.X(), pos.Y() ); // vertival flip 12532 break; 12533 } 12534 case 3: { 12535 Vec2 erg; 12535 // diagonal flip 2 12536 (pos-winpos).Split( Vec2(1,1), &erg ); // project to diagonal 12537 wpos=winpos+erg; 12538 break; 12539 } 12540 } 12541 wa=winpos.AngleDeg(wpos); // angle to (adjusted position) 12542 } 12543 12544 12545 Vec2 mdir=wpos-winpos; // move distance to center of flip 12546 Vec2 newpos=mdir+wpos; // destination on other side of the flip 12547 Real a=wa+90; // angle of mirror 12548 Real newdir=a-(windir-a)+180; // new windir after the flip 12549 12550 DBG1( "*** Mirror Angle: %g\n", (double)a ); 12551 DBG2( "*** Windir: %g -> New Angle: %g\n", (double)wa, (double)newdir ); 12552 12553 if (join_count<=maxfliptiles) { 12554 // do tiny animation, if there are less than 5 tiles combined 12555 12556 Real flipstart=GetCurrentTime(); 12557 Real loop; // current state of the flip 12558 12559 double fliptime=fliptimebase+join_count*fliptimedelta; 12560 StartFlip( Vec2Zero.AngleRadial(mdir) );// start flipping up 12561 for (loop=0.9;loop>=flipsave;loop=1.0-(GetCurrentTime()-flipstart)/fliptime) { 12562 StoreExtent(); 12563 SetPos( wpos-loop*mdir ); 12564 SetFlip( loop ); 12565 UpdateExtent(); 12566 XSync(dpy,0); 12567 } 12568 12569 StoreExtent(); // swap to other sid 12569 e 12570 FlipPage(); 12571 SetDir(newdir); 12572 12573 loop=flipsave; // first frame on ba 12573 ck side 12574 flipstart=GetCurrentTime(); 12575 StartFlip( Vec2Zero.AngleRadial(wpos-newpos) ); 12576 SetPos( wpos+loop*mdir ); 12577 SetFlip(loop); 12578 UpdateExtent(); 12579 XSync(dpy,0); 12580 loop=flipsave+(GetCurrentTime()-flipstart)/fliptime; Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 17 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12581 12582 for (;loop<1.0-0.1;loop=flipsave+(GetCurrentTime()-flipstart)/fliptime) { 12583 StoreExtent(); 12584 SetPos( wpos+loop*mdir ); 12585 SetFlip( loop ); 12586 UpdateExtent(); 12587 XSync(dpy,0); 12588 } 12589 12590 StoreExtent(); // last frame on bac 12590 k side 12591 SetPos(newpos); 12592 StopFlip(); 12593 DirectionChanged(); // trigger for a last update 12594 UpdateExtent(); 12595 } 12596 else { 12597 StoreExtent(); // just flip and sho 12597 w 12598 FlipPage(); 12599 SetPos(newpos); 12600 SetDir(newdir); 12601 UpdateExtent(); 12602 } 12603 } 12604 12605 void DBPieceObject::StoreExtent() { 12606 x1 = winx; // store old frame 12607 y1 = winy; 12608 x2 = x1+swidth; 12609 y2 = y1+sheight; 12610 } 12611 12612 int DBPieceObject::JoinExtent( int *xx1, int *yy1, int *xx2, int *yy2 ) { 12613 if (winx<*xx1) *xx1 = winx; 12614 if (winy<*yy1) *yy1 = winy; 12615 if (winx+swidth>*xx2) *xx2 = winx+swidth; 12616 if (winy+sheight>*yy2) *yy2 = winy+sheight; 12617 return 1; 12618 } 12619 12620 int DBPieceObject::GetExtent( int *xx1, int *yy1, int *xx2, int *yy2 ) { 12621 *xx1 = winx; 12622 *yy1 = winy; 12623 *xx2 = winx+swidth; 12624 *yy2 = winy+sheight; 12625 return 1; 12626 } 12627 12628 void DBPieceObject::JoinExtent() { 12629 if (winxx2) x2=winx+swidth; 12631 if (winyy2) y2=winy+sheight; 12633 } 12634 12635 void DBPieceObject::UpdateExtent() { Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 18 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12636 JoinExtent(); 12637 mystack->ExposeRegion(x1,y1,x2-x1,y2-y1); 12638 } 12639 12640 // =========================================================================== 12641 12642 int MoveablePiece::turnflag; // flag about direction of turn 12643 Time MoveablePiece::start_time; // event time of button press 12644 Real MoveablePiece::start_angle; // angle at the start of turn 12645 Vec2 MoveablePiece::start; 12646 Vec2 MoveablePiece::poffset; // offset of pointer from center 12647 Real MoveablePiece::poffset_len; // length of offset of pointer from center 12648 12649 MoveablePiece::MoveablePiece() { 12650 } 12651 12652 MoveablePiece::~MoveablePiece() { 12653 } 12654 12655 void MoveablePiece::DispatchPress( XButtonEvent * xbutton ) { 12656 if (xbutton->state&ControlMask) { 12657 // printf( "doing the flip ...\n" ); 12658 mystack->Raise(this); 12659 FlipOver( Vec2(xbutton->x,xbutton->y) ); 12660 start_time=0; 12661 } 12662 else { 12663 start_time=xbutton->time; 12664 } 12665 12666 start_angle=GetDir(); 12667 if (xbutton->state&AnyButtonMask) { 12668 // there is already a button pressed ... 12669 if (xbutton->button==Button1) { 12670 // second button in addition to middle button -> turn around center 12671 turnflag=2*(xbutton->button-Button1-1); 12672 } 12673 else { 12674 // start non-rotating motion on multiple press 12675 turnflag=0; 12676 } 12677 } 12678 else { 12679 // first button - start normal drag 12680 mystack->Raise(this); 12681 start=Vec2( xbutton->x, xbutton->y ); 12682 poffset=(start-winpos); 12683 poffset_len=poffset.Norm(); 12684 12685 // when too close to the center of the tile - move it off a bit ... 12686 while (poffset_len<2) { 12687 // printf( "*** very close hit - moving start\n" ); 12688 start+=Vec2(1,1); 12689 poffset=(start-winpos); 12690 poffset_len=poffset.Norm(); 12691 } 12692 Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 19 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12693 turnflag=xbutton->button-Button1-1; 12694 12695 if (poffset_lenx,xmotion->y); 12713 Vec2 new_offset=newpos-(start-poffset); 12714 12715 if (fabs(new_offset.X())+fabs(new_offset.Y())<2) { 12716 DBG0( "#### skipping event near center of tile\n" ); 12717 return; 12718 } 12719 12720 switch (turnflag) { 12721 case 2: 12722 case -2: { 12723 // new style for turning around center 12724 Real a1=Vec2Zero.AngleDeg(poffset); 12725 Real a2=Vec2Zero.AngleDeg(new_offset); 12726 poffset=new_offset; 12727 MoveTurn(newpos-poffset,GetDir()-a1+a2); 12728 break; 12729 } 12730 case -1: { 12731 // new style for pulling corners 12732 new_offset=(new_offset).Norm1()*poffset_len; 12733 Real a1=Vec2Zero.AngleDeg(poffset); 12734 Real a2=Vec2Zero.AngleDeg(new_offset); 12735 poffset=new_offset; 12736 MoveTurn(newpos-poffset,GetDir()-a1+a2); 12737 break; 12738 } 12739 case 1: 12740 default: 12741 Move( newpos-poffset ); 12742 break; 12743 } 12744 start=newpos; 12745 } 12746 12747 void MoveablePiece::DispatchRelease( XButtonEvent * xbutton ) { 12748 if (xbutton->button!=Button2&&(xbutton->button==Button1||!(xbutton->state&Button1Mask))) { 12749 if (xbutton->time-start_time<150) { Source Listing 30-DEC-1997 18:01:25 DEC C++ V5.2-003 Page 20 30-DEC-1997 18:01:21 SUB2:[DECW_PORT.XJIG-2_4]OBJECTS.C;4 12750 switch(xbutton->button) { 12751 case Button1: TurnOver(start_angle+90.0); break; 12752 case Button3: TurnOver(start_angle-90.0); break; 12753 } 12754 } 12755 turnflag=0; 12756 } 12757 else if (xbutton->time-start_time<150&&xbutton->button==Button2&&!(xbutton->state&~Button2Mask)) { 12758 FlipOver(Vec2(xbutton->x,xbutton->y)); 12759 } 12760 else if (xbutton->state&Button1Mask) 12761 turnflag=-1; // restart rotatable drag 12762 12763 if (!((xbutton->state&AnyButtonMask)&~(Button1Mask<<(xbutton->button-1)))) { 12764 XDefineCursor( dpy, win, idle_cursor ); 12765 XFlush(dpy); 12766 // no more buttons pressed -> check against other pieces 12767 if (p->CheckForJoin( (Piece*)this )) { 12768 /* don't use THIS in this case since it's already deleted !!! */ 12769 } 12770 else { 12771 AdjustDirection(); 12772 } 12773 } 12774 else XDefineCursor( dpy, win, (turnflag)?pull_cursor:move_cursor ); 12775 } 12776 Command Line ------- ---- CXX/ANSI_ALIAS/ANALYSIS_DATA/ASSUME=(ACCURACY_SENSITIVE,ALIGNED_OBJECTS,NOWRITABLE_STRING_LITERALS) /COMMENTS=SPACE/DIAGNOSTICS/DEBUG=(TRACEBACK)/ENDIAN=LITTLE/EXTERN_MODEL=RELAXED_REFDEF /FLOAT=(G_FLOAT)/GRANULARITY=QUADWORD/INSTRUCTION_SET=FLOATING_POINT/LINE_CONTROL /L_DOUBLE_SIZE=64/LINE_DIRECTIVES/LIST/NOMACHINE_CODE/MEMBER_ALIGNMENT /NAMES=UPPERCASE/NESTED_INCLUDE_DIRECTORY=INCLUDE_FILE/OBJECT/OPTIMIZE=(LEVEL=4,TUNE=GENERIC,UNROLL=0) /PREFIX=(ALL_ENTRIES)/PSECT_MODEL=NOMULTILANGUAGE/ROUNDING_MODE=NEAREST /SHOW=(HEADER,SOURCE)/SIGNED_CHAR/STANDARD=ARM/STACK_CHECK/REENTRANCY=TOLERANT /WARNINGS/DEFINE=(VMS)