jimm@amiga.UUCP (James D. Mackraz) (11/03/86)
:: The following is an example of using a dual-playfield screen. Contrary to what it says in the Intuition Manual, the way to do this is to open a normal, single-playfiled screen and then to mutate it into a dual-playfield, providing your own bit map and planes, and auxilliary data structures. The example given performs this mutation on the workbench screen, but such intrusive behavior is not recommended for any purpose other than demonstration and playing around. (And perhaps the odd subliminal message.) There are certain constraints which must be understood as to the number of bitplanes in the two playfields which are allowed, and the formulas for color mapping the two playfields are only hinted at in this example, so you must still consult the manuals. Note the constant FANCYVERSION, which if defined non-zero results in a more exciting demo than the version of this program supplied in the Intuition Revision notes (which are to be distributed to developers). Note also that like most of my previous examples, this program was produced under GreenHills C, and come with no guarantee to compile and run under any other system. Although I am no longer an employee of Commodore-Amiga, Inc., it is my pleasure to continue to support and be a member of the Amiga developers community. See you at the Developer's Conference. Jim Mackraz (amiga!jimm) /** wbdualpf.c **/ /* Turn the workbench into dual playfield. * * You can use the same trick for your own screens, * which is the recommended method for creating dual-playfield * screens. * * -Start with a new, single-playfield screen * (don't set DUALPF in NewScreen.ViewModes) * -Allocate a second playfield, set up a rastport for * rendering into it, and install it into your open screen * as shown here. Intuition will never know about or use your * second playfield for its rendering (menus, gadgets, etc.). * -Be sure to remove evidence of your deed before CloseScreen(). */ #include <exec/types.h> #include <exec/memory.h> #include <intuition/intuition.h> #define printf kprintf struct Remember *rememberkey = NULL; struct Window *getNewWind(); struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; ULONG flg = ACTIVATE | WINDOWCLOSE | NOCAREREFRESH | WINDOWDRAG | WINDOWDEPTH | SIMPLE_REFRESH; ULONG iflg = CLOSEWINDOW | INTUITICKS ; #define FANCYVERSION 1 #ifdef FANCYVERSION #define VISUALTICKS 30 /* intuiticks per frame */ #define CYCLETICKS 5 /* intuiticks per pen color */ #endif main() { struct IntuiMessage *msg; struct Window *window = NULL; WORD exitval = 0; /* hold data from *msg */ ULONG class; /* specific for this test */ struct Screen *wbscreen; struct RasInfo *rinfo2 = NULL; /* second playfield rasinfo ... */ struct BitMap *bmap2 = NULL; /* ... and bitmap */ struct RastPort *rport2 = NULL; /* for rendering into bmap2 */ BOOL it_is_done = FALSE; /* success flag */ int counter = 0; /* for timing the visuals */ if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0))) { printf("NO INTUITION LIBRARY\n"); exitval = 1; goto EXITING; } if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0))) { printf("NO GRAPHICS LIBRARY\n"); exitval = 2; goto EXITING; } /* get a window on the workbench */ window = getNewWind(320, 20, 300, 50, flg, iflg); if (window == NULL) { printf("test: can't get window.\n"); exitval = 1; goto EXITING; } /* ------ Add a second playfield for Workbench ------------ */ wbscreen = window->WScreen; /* find it */ /* allocate second playfield's rasinfo, bitmap, and bitplane */ if (!(rinfo2 = (struct RasInfo *) AllocMem(sizeof(struct RasInfo), MEMF_PUBLIC|MEMF_CLEAR))) { printf("alloc rasinfo failed\n"); goto EXITING; } if (!(bmap2 = (struct BitMap *) AllocMem(sizeof(struct BitMap), MEMF_PUBLIC|MEMF_CLEAR))) { printf("alloc bitmap failed\n"); goto EXITING; } InitBitMap(bmap2, 1, wbscreen->Width, wbscreen->Height); /* we'll use 1 plane. */ if (!(bmap2->Planes[0] = (UWORD *) AllocRaster(wbscreen->Width, wbscreen->Height))) { printf("alloc raster failed\n"); goto EXITING; } /* get a rastport, and set it up for rendering into bmap2 */ if (!(rport2 = (struct RastPort *) AllocMem(sizeof (struct RastPort), MEMF_PUBLIC))) { printf("alloc rastport failed\n"); goto EXITING; } InitRastPort(rport2); rport2->BitMap = bmap2; SetRast(rport2, 0); /* manhandle viewport: install second playfield and change modes */ Forbid(); rinfo2->BitMap = bmap2; /* install my bitmap in my rasinfo */ wbscreen->ViewPort.RasInfo->Next = rinfo2; /* install rinfo for viewport's second playfield */ wbscreen->ViewPort.Modes |= DUALPF; /* convert viewport */ it_is_done = TRUE; Permit(); /* set my foreground color */ SetRGB4(&wbscreen->ViewPort, 9, 0, 0xF, 0); /* color 9 is color 1 for second playfield of hi-res viewport */ /* put viewport changed into effect */ MakeScreen(wbscreen); RethinkDisplay(); drawSomething(rport2); printf("test program ok\n"); FOREVER { if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL) { Wait(1<<window->UserPort->mp_SigBit); continue; } class = msg->Class; ReplyMsg(msg); switch (class) { case INTUITICKS: #ifdef FANCYVERSION setPrimary(&wbscreen->ViewPort); /* cycles colors */ if (counter++ > VISUALTICKS) { counter = 0; SetRast(rport2, 0); drawSomething(); } #endif break; case CLOSEWINDOW: printf("event CLOSEWINDOW\n"); goto EXITING; default: printf("unknown event: class %lx\n", class); } } EXITING: /* clean up dual-playfield trick */ if (it_is_done) { Forbid(); wbscreen->ViewPort.RasInfo->Next = NULL; wbscreen->ViewPort.Modes &= ~DUALPF; Permit(); MakeScreen(wbscreen); RethinkDisplay(); } if (rport2) FreeMem(rport2, sizeof (struct RastPort)); if (bmap2) { if (bmap2->Planes[0]) { FreeRaster(bmap2->Planes[0], wbscreen->Width, wbscreen->Height); } FreeMem(bmap2, sizeof (struct BitMap)); } if (rinfo2) FreeMem(rinfo2, sizeof (struct RasInfo)); if (window) CloseWindow(window); if (GfxBase) CloseLibrary(GfxBase); if (IntuitionBase) CloseLibrary(IntuitionBase); exit (exitval); } #ifdef FANCYVERSION /* cycle pen 1's color */ setPrimary(vp) struct ViewPort *vp; { static int current = 0; /* pen 1 is color 9 for second playfield in hires */ /* feel free too do this elegantly */ if (!(current++ % CYCLETICKS)) return; switch ((current/CYCLETICKS)%3) { case 0: SetRGB4(vp, 9, 0xF, 0, 0); break; case 1: SetRGB4(vp, 9, 0, 0xF, 0); break; case 2: SetRGB4(vp, 9, 0, 0, 0xF); break; } } struct pt_st { int x; int y; }; typedef struct pt_st Pt; drawSomething(rp) struct RastPort *rp; { int width, height; int i; Pt start, vertex, end; /* random reference lines */ Pt p0, p1; /* endpoints to be drawn */ width = rp->BitMap->BytesPerRow * 8; height = rp->BitMap->Rows; /* set up two random reference lines */ start.x = RangeRand(width); vertex.x = RangeRand(width); end.x = RangeRand(width); start.y = RangeRand(height); vertex.y = RangeRand(height); end.y = RangeRand(height); SetAPen(rp, 1); /* draw lines connecting intermediate points */ for (i = 0; i <= 0x100; i += 0x10) { /* point between start and vertex */ p0.x = (start.x * (0xFF - i) + vertex.x * i) >> 8; p0.y = (start.y * (0xFF - i) + vertex.y * i) >> 8; /* point between vertex and end */ p1.x = (vertex.x * (0xFF - i) + end.x * i) >> 8; p1.y = (vertex.y * (0xFF - i) + end.y * i) >> 8; Move(rp, p0.x, p0.y); Draw(rp, p1.x, p1.y); } } #else drawSomething(rp) struct RastPort *rp; { int width, height; int r, c; width = rp->BitMap->BytesPerRow * 8; height = rp->BitMap->Rows; SetAPen(rp, 1); for (r = 0; r < height; r += 40) for (c = 0; c < width; c += 40) { Move(rp, 0, r); Draw(rp, c, 0); } } #endif struct Window * getNewWind(left, top, width, height, flg, iflg) SHORT left, top, width, height; ULONG flg, iflg; { struct Window *OpenWindow(); struct NewWindow nw; nw.LeftEdge = (SHORT) left; nw.TopEdge = (SHORT) top; nw.Width = (SHORT) width; nw.Height = (SHORT) height; nw.DetailPen = (UBYTE) -1; nw.BlockPen = (UBYTE) -1; nw.IDCMPFlags = (ULONG) iflg; nw.Flags = (ULONG) flg; nw.FirstGadget = (struct Gadget *) NULL; nw.CheckMark = (struct Image *) NULL; nw.Title = (UBYTE *) " Dual Playfield Mole "; nw.Screen = (struct Screen *) NULL; nw.BitMap = (struct BitMap *) NULL; nw.MinWidth = (SHORT) 50; nw.MinHeight= (SHORT) 30; /* work around bug */ nw.MaxWidth = (SHORT) nw.Width; nw.MaxHeight = (SHORT) nw.Height; nw.Type = (USHORT) WBENCHSCREEN; return ((struct Window *) OpenWindow(&nw)); }