Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Skinny3DSources ƒ/3DAppSpecific.c
#include <Printing.h> |
#include <AppleEvents.h> |
#include <Windows.h> |
#include <Fonts.h> |
#include <ToolUtils.h> |
#include <TextUtils.h> |
#include <LowMem.h> |
#include <SegLoad.h> |
#include <Devices.h> |
#include <Quickdraw.h> |
#include "SkinnyMain.h" |
#include "3DAppSpecific.h" |
#include "ValueControls.h" |
#include "BoxModel.h" |
#include "Cameras.h" |
#include "Lights.h" |
/* |
prototypes of QD3DFunctions called from the application (in "3DAppSpecific.h"): |
OSErr InitializeApplication(void); |
void Cleanup(void); |
Boolean PreflightNew(void); // return TRUE if "New" will work |
void DoNew(void); |
void DoOpen(void); |
void DoClose(void); // FrontWindow() only |
void DoSave(void); |
void DoSaveAs(void); |
void DoPrint(void); |
void DoClickInContent(EventRecord *evt, WindowPtr theWindow); |
void ActivateWindow(WindowPtr newFrontWindow, Boolean active); |
void DoAppSpecificMenu(long menuNumber, long itemNumber); |
void UpdateAppMenus(void); |
void DrawAppSpecificContent(WindowPtr theWindow); |
*/ |
enum { windowID = 128 }; // resource ID |
#define kWidth 600 |
#define kHeight 400 |
#define kCntrlWdth 200 |
typedef enum DirectionType { |
none, left, right, up, down, reset |
} DirectionType; |
// data structure tied to a window (handle into wRefCon) |
struct WindowInfo { |
TQ3ViewObject view; |
TQ3GroupObject model; |
TQ3TransformObject rotation; |
TQ3StyleObject interpolation; |
TQ3StyleObject backfacing; |
TQ3StyleObject fillstyle; |
TQ3ShaderObject shader; |
VccPtr vcc; |
}; |
typedef struct WindowInfo WindowInfo, **WinfoH; |
// local prototypes |
void AddHierarchMenu(long parentMenuID, long item, long subMenuID); |
static WinfoH Make3Dinfo(WindowPtr theWindow); |
static void Dispose3Dinfo(WinfoH wInfoH); |
static void Draw3DPart(WinfoH wInfo); |
static void DrawDirections(void); |
static void DrawTriangle(Point p, DirectionType e); |
static void DrawControlPart(WinfoH wInfo); |
static Boolean ControlClick(Point pt, WindowPtr theWindow); |
static DirectionType RotationClick(Point pt, WindowPtr theWindow); |
static TQ3DrawContextObject MakeDrawContext(WindowPtr theWindow); |
static void SetRotation(WinfoH wInfo, DirectionType direction); |
static void ChooseDebug(long item); |
static void ChooseRenderer (TQ3ViewObject view, long item); |
static void ChooseBackfacing (WinfoH wInfo, long item); |
static void ChooseInterpolation (WinfoH wInfo, long item); |
static void ChooseFillStyle (WinfoH wInfo, long item); |
static void MakeGeometry (WinfoH wInfo, long selector); |
static void UpdateGeometry (WinfoH wInfo); |
static void MakeDataControl (WinfoH wInfo); |
static void MakeNewCamera (WinfoH wInfo, long selector); |
static void MakeCameraControl (WinfoH wInfo); |
static void MakeLightControl (WinfoH wInfo, long selector); |
static Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo); |
void CheckMenuItem(short menuID, short checkItem); |
static Rect gWindowRect; |
static Rect g3DViewRect; |
Rect gContrlRect; // needed to make VCC |
static long curGeometry; |
static long curCamera; |
static long curLight; |
static long curRenderer; |
static long curBackfacing; |
static long curInterpol; |
static long curFillStyle; |
extern THPrint gPrintH; |
extern CursHandle gWatchCursor; |
//--------------------------------- |
OSErr InitializeApplication(void) |
{ |
MenuHandle mh; |
Handle menuBar = GetNewMBar(128); |
TQ3Status status; |
if (!menuBar) { |
return -30000; |
} |
SetMenuBar(menuBar); |
AppendResMenu(GetMenuHandle(mApple),'DRVR'); |
DrawMenuBar(); |
DisposeHandle(menuBar); |
AddHierarchMenu(mControl, iCamera, mCameras); |
AddHierarchMenu(mControl, iLight, mLight); |
AddHierarchMenu(mControl, iRenderer, mRenderer); |
AddHierarchMenu(mStyle, iBackfacing, mBackfacing); |
AddHierarchMenu(mStyle, iInterpol, mInterpolation); |
AddHierarchMenu(mStyle, iFillStyle, mFillStyle); |
gPrintH = (THPrint)NewHandle(sizeof(TPrint)); |
if (gPrintH == nil) |
return -30001; |
status = Q3Initialize(); |
if ( status == kQ3Failure ) |
return ( -30002 ); |
SetRect(&gWindowRect, 0, 0, kWidth, kHeight); |
SetRect(&g3DViewRect, 0, 0, kWidth - kCntrlWdth, kHeight); |
SetRect(&gContrlRect, kWidth - kCntrlWdth, 0, kWidth, kHeight); |
InsetRect(&gContrlRect, 1, 1); |
return ( noErr ); |
} |
//--------------------------------------------------------------- |
void AddHierarchMenu(long parentMenuID, long item, long subMenuID) |
{ |
MenuHandle mh; |
mh = GetMenu(subMenuID); |
InsertMenu(mh, -1); |
mh = GetMenuHandle(parentMenuID); |
SetItemCmd(mh, item, 0x1B); |
SetItemMark(mh, item, (char)subMenuID); |
} |
//------------------------ |
void Cleanup(void) |
//------------------------ |
{ |
TQ3Status status = Q3Exit(); |
// don't worry - the application heap disappears anyway, |
// and we can't do anything about any failure of Q3Exit(). |
} |
//------------------------------------ |
Boolean PreflightNew(void) |
{ |
long maxm, grow; |
maxm = MaxMem(&grow); |
return (maxm > 1000000); // that's what our new QD3D window roughly needs! |
} |
//------------------------------------ |
void DoNew(void) |
{ |
WindowPtr myWindow; |
WinfoH intoRefCon; |
myWindow = GetNewCWindow(windowID, nil, (WindowPtr)(-1)); |
if ( myWindow == nil ) { |
ErrMsg("\pGetNewCWindow failed."); |
return; |
} |
SizeWindow(myWindow, kWidth, kHeight, false); |
ShowWindow(myWindow); |
SetPort(myWindow); |
intoRefCon = Make3Dinfo(myWindow); |
if (intoRefCon != nil) { |
SetWRefCon(myWindow, (long)intoRefCon ); |
DoAppSpecificMenu(mGeometry, iBox); |
} |
else { |
ErrMsg("\pMake3Dinfo failed"); |
DisposeWindow(myWindow); |
} |
} |
//------------------------------------ |
void DoOpen(void) |
{ |
} |
//------------------------------------ |
void DoClose(void) |
{ |
WindowPtr theWindow; |
WinfoH theWinfo; |
if (GoodFrontWindow(&theWindow, &theWinfo)) |
Dispose3Dinfo(theWinfo); |
CloseWindow(theWindow); |
} |
//------------------------------------ |
void DoSave(void) |
{ |
} |
//------------------------------------ |
void DoSaveAs(void) |
{ |
} |
//------------------------------------ |
void DoPrint( void ) |
{ |
SysBeep(50); |
} |
//---------------------------------------------------------------------- |
void DoClickInContent(EventRecord *evt, WindowPtr theWindow) |
{ |
WinfoH wInfo; |
ControlHandle ctlh; |
Point pt; |
Rect frame; |
DirectionType direction; |
int part; |
wInfo = (WinfoH)GetWRefCon(theWindow); |
if (wInfo == nil) return; |
pt = evt->where; |
GlobalToLocal(&pt); |
if ((part = FindControl(pt, theWindow, &ctlh)) != kControlNoPart) { |
/* TrackControl Goes Here */ |
} |
if (ControlClick(pt, theWindow)) { // our special ValueControl panel |
InvalRect(&g3DViewRect); |
return; |
} |
if ((direction = RotationClick(pt, theWindow)) != none) { |
SetRotation(wInfo, direction); |
InvalRect(&g3DViewRect); |
} |
} |
//------------------------------------ |
static void SetRotation(WinfoH wInfo, DirectionType direction) |
{ |
TQ3Status status; |
TQ3BoundingBox bBox; |
TQ3Point3D center, tmpPt; |
TQ3Axis axis; |
float angle; |
TQ3Matrix4x4 previousMatrix, matrix, newMatrix, *tmp; |
TQ3TransformObject transform; |
TQ3RotateAboutPointTransformData tData; |
TQ3GroupObject group; |
TQ3GroupPosition position; |
TQ3ObjectType type; |
TQ3Object theObj; |
TQ3BoxData boxData; |
if (direction == reset) { |
Q3Matrix4x4_SetIdentity(&matrix); |
status = Q3MatrixTransform_Set((**wInfo).rotation, &matrix); |
return; |
} |
// Q3View_StartBounds((**wInfo).view); |
// status = Q3DisplayGroup_BoundingBox((**wInfo).model, |
// &bBox, |
// kQ3ComputeBoundsApproximate, |
// (**wInfo).view); |
// Q3View_EndBounds((**wInfo).view); |
// Cannot link with the above, for some temporary reason. |
// Temporary workaround: |
group = (**wInfo).model; |
type = kQ3ShapeTypeGeometry; |
status = Q3Group_GetFirstPositionOfType(group, type, &position); |
if (status == kQ3Failure) |
return; |
status = Q3Group_GetPositionObject ( group, position, &theObj); |
type = Q3Geometry_GetType ( theObj ); |
switch (type) { |
case kQ3GeometryTypeBox: |
status = Q3Box_GetData( theObj, &boxData ); |
bBox.min = boxData.origin; |
Q3Point3D_Vector3D_Add(&bBox.min, &boxData.orientation, &tmpPt); |
Q3Point3D_Vector3D_Add(&tmpPt, &boxData.majorAxis, &tmpPt); |
Q3Point3D_Vector3D_Add(&tmpPt, &boxData.minorAxis, &bBox.max); |
break; |
// add here the cases of other geometries, if required |
default: |
Q3Point3D_Set(&bBox.min, -1.0, -1.0, -1.0); |
Q3Point3D_Set(&bBox.max, 1.0, 1.0, 1.0); |
return; |
} |
Q3Point3D_RRatio(&bBox.min, &bBox.max, 1.0, 1.0, ¢er); // mid-point |
status = Q3MatrixTransform_Get((**wInfo).rotation, &previousMatrix); |
if ((direction == up) || (direction == down)) |
axis = kQ3AxisX; |
else |
axis = kQ3AxisY; |
if ((direction == right) || (direction == down)) |
angle = 0.1; |
else |
angle = -0.1; |
tData.axis = axis; |
tData.radians = angle; |
tData.about = center; |
transform = Q3RotateAboutPointTransform_New(&tData); |
if (transform == NULL) |
return; |
tmp = Q3Transform_GetMatrix(transform, &matrix); |
Q3Matrix4x4_Multiply(&previousMatrix, &matrix, &newMatrix); |
status = Q3MatrixTransform_Set((**wInfo).rotation, &newMatrix); |
} |
//------------------------------------ |
void ActivateWindow(WindowPtr newFrontWindow, Boolean active) |
{ |
if (active) |
;// This window is now active. Controls should be enabled, etc. |
else |
; |
// do anyting necessary to deactivate your windows here. |
// controls should be dimmed, etc. |
} |
//------------------------------------ |
void DoAppSpecificMenu(long menuNumber, long item) |
{ |
WindowPtr theWindow; |
WinfoH wInfo; |
if (menuNumber == mDebug) { |
ChooseDebug(item); return; |
} |
if (!GoodFrontWindow(&theWindow, &wInfo)) { |
// ErrMsg("\pBad FrontWindow"); |
return; |
} |
switch (menuNumber) { |
case mGeometry: MakeGeometry(wInfo, item); |
MakeDataControl(wInfo); |
curGeometry = item; |
break; |
case mControl: if (item == iData) |
MakeDataControl(wInfo); |
break; |
case mCameras: if (item != curCamera) { |
MakeNewCamera(wInfo, item); |
curCamera = item; |
} |
MakeCameraControl(wInfo); |
break; |
case mLight: MakeLightControl(wInfo, item); |
curLight = item; |
break; |
case mRenderer: ChooseRenderer((**wInfo).view, item); |
break; |
case mBackfacing: |
ChooseBackfacing(wInfo, item); |
curBackfacing = item; |
break; |
case mInterpolation: |
ChooseInterpolation(wInfo, item); |
curInterpol = item; |
break; |
case mFillStyle: |
ChooseFillStyle(wInfo, item); |
curFillStyle = item; |
break; |
default: |
break; |
} |
InvalRect(&theWindow->portRect); |
} |
//------------------------------------ |
void UpdateAppMenus(void) |
{ |
long free, maxm, grow; |
Str255 freeItem = "\pFreeMem = "; |
Str255 maxmItem = "\pMaxMem = "; |
Str255 s; |
WindowPtr theWindow; |
WinfoH wInfo; |
MenuHandle menu = GetMenuHandle(mDebug); |
free = FreeMem(); |
NumToString(free, s); |
pcat(freeItem, s); |
SetMenuItemText(menu, iFreeMem, freeItem); |
maxm = MaxMem(&grow); |
NumToString(maxm, s); |
pcat(maxmItem, s); |
SetMenuItemText(menu, iMaxMem, maxmItem); |
CheckMenuItem(mGeometry, curGeometry); |
CheckMenuItem(mCameras, curCamera); |
CheckMenuItem(mLight, curLight); |
CheckMenuItem(mRenderer, curRenderer); |
CheckMenuItem(mBackfacing, curBackfacing); |
CheckMenuItem(mInterpolation, curInterpol); |
CheckMenuItem(mFillStyle, curFillStyle); |
if (!GoodFrontWindow(&theWindow, &wInfo)) { |
DisableItem(GetMenuHandle(mGeometry), 0); |
DisableItem(GetMenuHandle(mControl), 0); |
DisableItem(GetMenuHandle(mStyle), 0); |
} |
else { |
EnableItem(GetMenuHandle(mGeometry), 0); |
EnableItem(GetMenuHandle(mControl), 0); |
EnableItem(GetMenuHandle(mStyle), 0); |
} |
DrawMenuBar(); |
} |
void CheckMenuItem(short menuID, short checkItem) |
{ |
MenuHandle menu = GetMenuHandle(menuID); |
short n = CountMItems(menu); |
short i; |
for (i = 1; i <= n; i++) |
CheckItem(menu, i, (i == checkItem)); |
} |
//------------------------------------ |
static void ChooseRenderer(TQ3ViewObject view, long item) |
{ |
TQ3Status status; |
TQ3ObjectType rType; |
TQ3RendererObject renderer; |
switch (item) { |
case iWireFrame: rType = kQ3RendererTypeWireFrame; break; |
case iZBuffer: rType = kQ3RendererTypeInteractive; break; |
} |
// status = Q3View_SetRendererByType(view, rType); |
// alternatively: |
renderer = Q3Renderer_NewFromType(rType); |
if (renderer == nil) |
return; |
status = Q3View_SetRenderer(view, renderer); |
if (status == kQ3Failure ) |
return; |
Q3Object_Dispose(renderer) ; |
curRenderer = item; |
} |
//------------------------------------ |
static void ChooseBackfacing(WinfoH wInfo, long item) |
{ |
TQ3Status status; |
TQ3BackfacingStyle bfStyle; |
switch (item) { |
case iBoth: bfStyle = kQ3BackfacingStyleBoth; break; |
case iRemove: bfStyle = kQ3BackfacingStyleRemove; break; |
case iFlip: bfStyle = kQ3BackfacingStyleFlip; break; |
} |
if ((**wInfo).backfacing != nil) |
status = Q3Object_Dispose((**wInfo).backfacing); |
(**wInfo).backfacing = Q3BackfacingStyle_New(bfStyle); |
} |
//------------------------------------ |
static void ChooseInterpolation(WinfoH wInfo, long item) |
{ |
TQ3Status status; |
TQ3InterpolationStyle ipStyle; |
switch (item) { |
case iNone: ipStyle = kQ3InterpolationStyleNone; break; |
case iVertex: ipStyle = kQ3InterpolationStyleVertex; break; |
case iPixel: ipStyle = kQ3InterpolationStylePixel; break; |
} |
if ((**wInfo).interpolation != nil) |
status = Q3Object_Dispose((**wInfo).interpolation); |
(**wInfo).interpolation = Q3InterpolationStyle_New(ipStyle); |
} |
//------------------------------------ |
static void ChooseFillStyle(WinfoH wInfo, long item) |
{ |
TQ3Status status; |
TQ3FillStyle flStyle; |
switch (item) { |
case iFilled: flStyle = kQ3FillStyleFilled; break; |
case iEdges: flStyle = kQ3FillStyleEdges; break; |
case iPoints: flStyle = kQ3FillStylePoints; break; |
} |
if ((**wInfo).fillstyle != nil) |
status = Q3Object_Dispose((**wInfo).fillstyle); |
(**wInfo).fillstyle = Q3FillStyle_New(flStyle); |
} |
//------------------------------------ |
static void ChooseDebug(long item) |
{ |
} |
////////////////////////////////////////////////////////// |
//=========================================== |
WinfoH Make3Dinfo(WindowPtr theWindow) |
{ |
WinfoH wInfo; |
TQ3DrawContextObject drawContext; |
TQ3RendererObject renderer; |
TQ3GroupObject lightGroup; |
TQ3Matrix4x4 matrix; |
TQ3Status status; |
wInfo = (WinfoH) NewHandleClear(sizeof(WindowInfo)); |
if (wInfo == nil) { |
ErrMsg("\pNewHandle(WindowInfo) failed"); |
return nil; |
} |
(**wInfo).view = Q3View_New(); // Escher View |
if ( (**wInfo).view == nil ) goto fail; |
// Set DrawContext, Camera, lightGroup and Renderer |
drawContext = MakeDrawContext(theWindow); |
if ( drawContext == nil ) goto fail; |
status = Q3View_SetDrawContext((**wInfo).view, drawContext); |
if ( status == kQ3Failure ) goto fail; |
status = Q3Object_Dispose(drawContext); |
MakeNewCamera(wInfo, iAspectRatio); |
lightGroup = MakeLights(); |
if ( lightGroup == nil ) goto fail; |
status = Q3View_SetLightGroup((**wInfo).view, lightGroup); |
if ( status == kQ3Failure ) goto fail; |
// decrease reference count (was increased by Q3View_SetLightGroup |
Q3Object_Dispose(lightGroup); |
curLight = 0; // selector for valuecontrol initially undefined |
ChooseRenderer((**wInfo).view, iWireFrame); |
(**wInfo).shader = Q3LambertIllumination_New() ; |
// Create model to display. |
(**wInfo).model = Q3OrderedDisplayGroup_New(); |
if ( (**wInfo).model == nil ) goto fail; |
// Set identity transform |
Q3Matrix4x4_SetIdentity(&matrix); |
(**wInfo).rotation = Q3MatrixTransform_New(&matrix); |
// Configure the drawing styles. |
ChooseInterpolation (wInfo, iNone); curInterpol = iNone; |
ChooseBackfacing (wInfo, iBoth); curBackfacing = iBoth; |
ChooseFillStyle (wInfo, iFilled); curFillStyle = iFilled; |
return wInfo; |
fail: |
Dispose3Dinfo(wInfo); |
return nil; |
} |
// --------------------------------------------------------------------- |
void Dispose3Dinfo(WinfoH wInfoH) |
{ |
TQ3Status status; |
if (wInfoH == nil) return; |
if ((**wInfoH).view != nil) |
status = Q3Object_Dispose((**wInfoH).view); |
if ((**wInfoH).model != nil) { |
// need to dispose properly of everything ... |
status = Q3Object_Dispose((**wInfoH).model); |
} |
if ((**wInfoH).interpolation != nil) |
status = Q3Object_Dispose((**wInfoH).interpolation); |
if ((**wInfoH).backfacing != nil) |
status = Q3Object_Dispose((**wInfoH).backfacing); |
if ((**wInfoH).fillstyle != nil) |
status = Q3Object_Dispose((**wInfoH).fillstyle); |
DisposeHandle((Handle) wInfoH); |
} |
// -------------------------------------------------------------------- |
TQ3DrawContextObject MakeDrawContext(WindowPtr theWindow) |
{ |
TQ3DrawContextData drawContextData; |
TQ3MacDrawContextData macDrawContextData; |
TQ3ColorARGB ClearColor; |
// Set the background color. |
ClearColor.a = 1.0; /* Solid alpha */ |
ClearColor.r = 1.0; |
ClearColor.g = 1.0; |
ClearColor.b = 1.0; |
// Fill in draw context data. |
drawContextData.clearImageMethod = kQ3ClearMethodWithColor; |
drawContextData.clearImageColor = ClearColor; |
drawContextData.pane.min.x = (theWindow->portRect).left; |
drawContextData.pane.max.x = (theWindow->portRect).right; |
drawContextData.pane.min.y = (theWindow->portRect).top; |
drawContextData.pane.max.y = (theWindow->portRect).bottom; |
drawContextData.paneState = kQ3True; |
drawContextData.maskState = kQ3False; |
drawContextData.doubleBufferState = kQ3True; |
macDrawContextData.drawContextData = drawContextData; |
macDrawContextData.window = (CWindowPtr) theWindow; |
macDrawContextData.library = kQ3Mac2DLibraryQuickDraw; |
macDrawContextData.viewPort = nil; |
macDrawContextData.grafPort = (CGrafPtr) theWindow; |
// Create draw context. |
return Q3MacDrawContext_New(&macDrawContextData); |
} |
//---------------------------------------------------------------------------------- |
void DrawAppSpecificContent(WindowPtr theWindow) |
{ |
WinfoH wInfo; |
wInfo = (WinfoH)GetWRefCon(theWindow); |
if (wInfo == nil) |
return; |
Draw3DPart(wInfo); |
DrawControlPart(wInfo); |
} |
//---------------------------------------------------------------------------------- |
static void Draw3DPart(WinfoH wInfo) |
{ |
TQ3Status status; |
//TQ3DrawContextObject myDrawContext; |
TQ3ViewStatus myViewStatus; |
WindowInfo wI = **wInfo; |
TQ3RendererObject myRenderer ; |
status = Q3View_StartRendering(wI.view); |
if ( status == kQ3Failure ) goto bail; |
if (curInterpol == iPixel) |
SetCursor(*gWatchCursor); |
do { |
if (curFillStyle == iFilled) { |
status = Q3Shader_Submit(wI.shader, wI.view); |
if ( status == kQ3Failure ) goto bail; |
} |
status = Q3Style_Submit(wI.interpolation, wI.view); |
if ( status == kQ3Failure ) goto bail; |
status = Q3Style_Submit(wI.backfacing, wI.view); |
if ( status == kQ3Failure ) goto bail; |
status = Q3Style_Submit(wI.fillstyle, wI.view); |
if ( status == kQ3Failure ) goto bail; |
status = Q3Transform_Submit( wI.rotation, wI.view); |
if ( status == kQ3Failure ) goto bail; |
status = Q3DisplayGroup_Submit(wI.model, wI.view); |
if ( status == kQ3Failure ) goto bail; |
myViewStatus = Q3View_EndRendering(wI.view); |
} while ( myViewStatus == kQ3ViewStatusRetraverse ); |
// get the renderer from the view |
status = Q3View_GetRenderer( wI.view, &myRenderer ) ; |
if ( status == kQ3Failure ) goto bail; |
// call sync 'cos we are going to draw over it. This is needed since if we are running with |
// hardware (which is asynchronous) then we need to ensure that the HW has finished drawing |
// before drawing the controls. |
Q3View_Sync( wI.view ) ; |
status = Q3Object_Dispose(myRenderer); |
DrawDirections(); |
InitCursor(); |
return; |
bail: |
SysBeep(50); |
} |
//------------------------------------ |
static void DrawDirections(void) |
{ |
Point p; |
short d = 4; // distance from border |
p.h = (g3DViewRect.right - g3DViewRect.left) / 2; |
p.v = g3DViewRect.top + d; |
DrawTriangle(p, up); |
p.v = g3DViewRect.bottom - d; |
DrawTriangle(p, down); |
p.h = g3DViewRect.left + d; |
p.v = (g3DViewRect.bottom - g3DViewRect.top) / 2; |
DrawTriangle(p, left); |
p.h = g3DViewRect.right - d; |
DrawTriangle(p, right); |
MoveTo(g3DViewRect.right - 20, g3DViewRect.top + 14); |
TextFont(geneva); TextSize(12); TextFace(0); |
DrawString("\p(R)"); |
} |
//------------------------------------ |
static void DrawTriangle(Point p, DirectionType e) |
{ |
#define k 10 |
short x1, y1, x2, y2, x3, y3; |
switch (e) { |
case up: x1 = y1 = x3 = k; y3 = -k; x2 = - k - k; y2 = 0; break; |
case down: x1 = y1 = x3 = -k; y3 = k; x2 = k + k; y2 = 0; break; |
case left: x1 = y1 = y3 = k; x3 = -k; x2 = 0; y2 = - k - k; break; |
case right: x1 = y1 = y3 = -k; x3 = k; x2 = 0; y2 = k + k; break; |
} |
MoveTo(p.h, p.v); |
Line(x1, y1); Line(x2, y2); Line(x3, y3); |
} |
//------------------------------------ |
static void DrawControlPart(WinfoH wInfo) |
{ |
EraseRect(&gContrlRect); |
FrameRect(&gContrlRect); |
if ((**wInfo).vcc != nil) |
DrawVCluster((**wInfo).vcc); |
} |
//------------------------------------ |
static Boolean ControlClick(Point pt, WindowPtr theWindow) |
{ |
WinfoH wInfo; |
OSType tag; |
TQ3Status status; |
wInfo = (WinfoH)GetWRefCon(theWindow); |
if (wInfo == nil) |
return false; |
if ( TakeHit(pt, (**wInfo).vcc) ) { |
tag = GetIdTag((**wInfo).vcc); |
switch (tag) { |
case kQ3GeometryTypeBox: |
UpdateGeometry(wInfo); |
break; |
case kQ3CameraTypeOrthographic: |
case kQ3CameraTypeViewPlane: |
case kQ3CameraTypeViewAngleAspect: |
{ |
TQ3CameraObject camera; |
status = Q3View_GetCamera((**wInfo).view, &camera); |
VCCtoCameraData((**wInfo).vcc, camera); |
status = Q3View_SetCamera((**wInfo).view, camera); |
status = Q3Object_Dispose(camera); |
} |
break; |
case kQ3LightTypeAmbient: |
case kQ3LightTypeDirectional: |
case kQ3LightTypePoint: |
case kQ3LightTypeSpot: |
{ |
TQ3CameraObject camera; |
TQ3GroupObject lightGroup; |
status = Q3View_GetLightGroup((**wInfo).view, &lightGroup); |
VCCtoLight((**wInfo).vcc, lightGroup); |
} |
break; |
// add here other types of valueControls |
} |
return true; |
} |
else |
return false; |
} |
//---------------------------------------------------------------------------------- |
static DirectionType RotationClick(Point pt, WindowPtr theWindow) |
{ |
Rect leftRect, rightRect, upRect, downRect, resetRect; |
Rect r = g3DViewRect; // shorthand notation |
short h3 = (g3DViewRect.right - g3DViewRect.left) / 3; |
short v3 = (g3DViewRect.bottom - g3DViewRect.top) / 3; |
SetRect(&leftRect, r.left, r.top + v3, r.left + h3, r.bottom - v3); |
SetRect(&rightRect, r.right - h3, r.top + v3, r.right, r.bottom - v3); |
SetRect(&upRect, r.left + h3, r.top, r.right - h3, r.top + v3); |
SetRect(&downRect, r.left + h3, r.bottom - v3, r.right - h3, r.bottom); |
SetRect(&resetRect, r.right - 32, r.top, r.right, r.top + 32); |
if (PtInRect(pt, &leftRect)) return left; |
if (PtInRect(pt, &rightRect)) return right; |
if (PtInRect(pt, &upRect)) return up; |
if (PtInRect(pt, &downRect)) return down; |
if (PtInRect(pt, &resetRect)) return reset; |
return none; |
} |
//---------------------------------------------------------------------------------- |
void MakeGeometry(WinfoH wInfo, long selector) |
{ |
if ((**wInfo).model != NULL) { |
// ¥¥¥ need to release memory allocated in attributes! |
Q3Group_EmptyObjects((**wInfo).model); |
Q3Object_Dispose((**wInfo).model); |
} |
switch (selector) { |
case iBox: (**wInfo).model = MakeBox(); |
break; |
case iEllipsoid:// aGeometry = MakeEllipsoid(); |
SysBeep(10); |
break; |
case iCylinder: // aGeometry = MakeCylinder(); |
SysBeep(10); |
break; |
case iCone: // aGeometry = MakeCone(); |
SysBeep(10); |
break; |
case iTorus: // aGeometry = MakeTorus(); |
SysBeep(10); |
break; |
default: |
break; |
} |
} |
//---------------------------------------------------------------------------------- |
void MakeDataControl(WinfoH wInfo) |
{ |
TQ3GroupObject group; |
TQ3GroupPosition position; |
TQ3ObjectType type; |
TQ3Status status; |
TQ3Object theObj; |
if ((**wInfo).vcc != nil) { |
DisposeVCluster((**wInfo).vcc); |
(**wInfo).vcc = nil; |
} |
group = (**wInfo).model; |
type = kQ3ShapeTypeGeometry; |
status = Q3Group_GetFirstPositionOfType(group, type, &position); |
if (status == kQ3Failure) |
return; |
status = Q3Group_GetPositionObject ( group, position, &theObj); |
type = Q3Geometry_GetType ( theObj ); |
switch (type) { |
case kQ3GeometryTypeBox: |
(**wInfo).vcc = BoxDataToVCC(theObj); |
break; |
// add here data of other geometries |
default: |
return; |
} |
} |
//---------------------------------------------------------------------------------- |
static void MakeNewCamera (WinfoH wInfo, long selector) |
{ |
TQ3CameraObject camera; |
TQ3Status status; |
camera = MakeCamera(selector); |
status = Q3View_SetCamera((**wInfo).view, camera); |
if ( status != kQ3Success ) |
ErrMsg("\pSetCamera failed"); |
status = Q3Object_Dispose(camera); |
curCamera = selector; |
} |
//---------------------------------------------------------------------------------- |
static void MakeCameraControl(WinfoH wInfo) |
{ |
TQ3CameraObject camera; |
TQ3Status status; |
if ((**wInfo).vcc != nil) { |
DisposeVCluster((**wInfo).vcc); |
(**wInfo).vcc = nil; |
} |
status = Q3View_GetCamera((**wInfo).view, &camera); |
if (status != kQ3Success) |
return; |
(**wInfo).vcc = CameraDataToVCC(camera); |
status = Q3Object_Dispose(camera); |
} |
//---------------------------------------------------------------------------------- |
static void MakeLightControl (WinfoH wInfo, long selector) |
{ |
TQ3Status status; |
TQ3GroupObject lightGroup; |
if ((**wInfo).vcc != nil) { |
DisposeVCluster((**wInfo).vcc); |
(**wInfo).vcc = nil; |
} |
status = Q3View_GetLightGroup((**wInfo).view, &lightGroup); |
(**wInfo).vcc = LightToVCC(lightGroup, selector); |
} |
//---------------------------------------------------------------------------------- |
static void UpdateGeometry(WinfoH wInfo) |
{ |
TQ3GroupObject group; |
TQ3GroupPosition position; |
TQ3ObjectType type; |
TQ3Status status; |
TQ3Object theObj; |
group = (**wInfo).model; |
type = kQ3ShapeTypeGeometry; |
status = Q3Group_GetFirstPositionOfType(group, type, &position); |
if (status == kQ3Failure) |
return; |
status = Q3Group_GetPositionObject( group, position, &theObj); |
type = Q3Geometry_GetType( theObj ); |
switch (type) { |
case kQ3GeometryTypeBox: { |
TQ3BoxData boxData; |
status = Q3Box_GetData(theObj, &boxData); |
if (status == kQ3Failure) |
return; |
VCCtoBoxData((**wInfo).vcc, &boxData); |
status = Q3Box_SetData(theObj, &boxData); |
// Q3Box_EmptyData(&boxData); |
} |
break; |
// add here data of other geometries |
default: |
return; |
} |
status = Q3Group_SetPositionObject( group, position, theObj); |
status = Q3Object_Dispose(theObj); |
} |
//---------------------------------------------------------------------------------- |
static Boolean GoodFrontWindow(WindowPtr *theWindow, WinfoH *wInfo) |
{ |
WindowPtr w; |
Boolean isGood = true; |
w = FrontWindow(); |
if (w == nil) // menu item should be disabled! |
isGood = false; |
if ( (*(WindowRecord *)w).windowKind != userKind ) |
isGood = false; |
*theWindow = w; |
*wInfo = (WinfoH)GetWRefCon(w); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14