/* Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd. All rights reserved. Copyright (C) 2007-2010, Gabriel Dos Reis. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of The Numerical Algorithms Group Ltd. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define _PROCESS3D_C #include "openaxiom-c-macros.h" #include #include #include #include #include #include #include "header.h" #include "cpanel.h" #include "volume.h" #include "mode.h" #include "process.h" #include "draw.h" #include "sockio.h" #include "com.h" #include "util.H1" #include "Gfun.H1" #include "pixmap.h" #include "XShade.H1" #include "XSpadFill.H1" #include "all_3d.H1" #include "cfuns.h" #define inside(A,B) (((XButtonEvent *)event)->x >= A && \ ((XButtonEvent *)event)->x <= B) void buttonAction (int bKey) { char *s1, *s2; int strL, strL1, strL2, offShade=14; /* Button colors which are offColor, RED, are turned off, and those which are onColor, GREEN, indicate the mode is in effect. */ switch (bKey) { case hideControl: if (viewport->haveControl) { viewport->haveControl = no; XUnmapWindow(dsply,control->controlWindow); } break; case region3D: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); if (viewport->regionOn) { viewport->regionOn = no; (control->buttonQueue[region3D]).textColor = offColor; viewData.box = 0; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[region3D]).buttonX, (control->buttonQueue[region3D]).buttonY, (control->buttonQueue[region3D]).buttonWidth, (control->buttonQueue[region3D]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[region3D]).buttonX, (control->buttonQueue[region3D]).buttonY, (control->buttonQueue[region3D]).buttonWidth, (control->buttonQueue[region3D]).buttonHeight,Xoption); } } else { /* inverted color for region off */ viewport->regionOn = yes; viewData.box = 1; (control->buttonQueue[region3D]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[region3D]).buttonX, (control->buttonQueue[region3D]).buttonY, (control->buttonQueue[region3D]).buttonWidth, (control->buttonQueue[region3D]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[region3D]).buttonX, (control->buttonQueue[region3D]).buttonY, (control->buttonQueue[region3D]).buttonWidth, (control->buttonQueue[region3D]).buttonHeight,Xoption); } } s = (control->buttonQueue[region3D]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[region3D]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[region3D]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[region3D]).buttonWidth), (control->buttonQueue[region3D]).buttonY + centerY(processGC, (control->buttonQueue[region3D]).buttonHeight), s,strL,Xoption); redoSmooth = yes; drawViewport(Xoption); break; case bwColor: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); if (!mono) { if (viewport->monoOn) { viewport->monoOn = no; if (viewport->hueTop == viewport->hueOffset) redoColor = yes; else redoDither = yes; (control->buttonQueue[bwColor]).textColor = offColor; (control->buttonQueue[bwColor]).text = "BW"; } else { viewport->monoOn = yes; maxGreyShade = XInitShades(dsply,scrn); if (viewport->hueTop == viewport->hueOffset) redoColor = yes; else redoDither = yes; (control->buttonQueue[bwColor]).textColor = onColor; (control->buttonQueue[bwColor]).text = "BW"; GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[bwColor]).buttonX, (control->buttonQueue[bwColor]).buttonY, (control->buttonQueue[bwColor]).buttonWidth, (control->buttonQueue[bwColor]).buttonHeight); GSetForeground(globalGC1,(float)monoColor(buttonColor),Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[bwColor]).buttonX, (control->buttonQueue[bwColor]).buttonY, (control->buttonQueue[bwColor]).buttonWidth, (control->buttonQueue[bwColor]).buttonHeight,Xoption); } s = (control->buttonQueue[bwColor]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[bwColor]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[bwColor]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[bwColor]).buttonWidth), (control->buttonQueue[bwColor]).buttonY + centerY(processGC, (control->buttonQueue[bwColor]).buttonHeight), s,strL,Xoption); drawColorMap(); redoSmooth = yes; writeTitle(); drawViewport(Xoption); } break; case outlineOnOff: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); if (viewData.outlineRenderOn) { viewData.outlineRenderOn = 0; (control->buttonQueue[outlineOnOff]).textColor = offColor; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[outlineOnOff]).buttonX, (control->buttonQueue[outlineOnOff]).buttonY, (control->buttonQueue[outlineOnOff]).buttonWidth, (control->buttonQueue[outlineOnOff]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[outlineOnOff]).buttonX, (control->buttonQueue[outlineOnOff]).buttonY, (control->buttonQueue[outlineOnOff]).buttonWidth, (control->buttonQueue[outlineOnOff]).buttonHeight,Xoption); } } else { viewData.outlineRenderOn = 1; (control->buttonQueue[outlineOnOff]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[outlineOnOff]).buttonX, (control->buttonQueue[outlineOnOff]).buttonY, (control->buttonQueue[outlineOnOff]).buttonWidth, (control->buttonQueue[outlineOnOff]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[outlineOnOff]).buttonX, (control->buttonQueue[outlineOnOff]).buttonY, (control->buttonQueue[outlineOnOff]).buttonWidth, (control->buttonQueue[outlineOnOff]).buttonHeight,Xoption); } } s = (control->buttonQueue[outlineOnOff]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[outlineOnOff]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[outlineOnOff]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[outlineOnOff]).buttonWidth), (control->buttonQueue[outlineOnOff]).buttonY + centerY(processGC, (control->buttonQueue[outlineOnOff]).buttonHeight), s,strL,Xoption); if (viewData.style == render) { drawViewport(Xoption); } break; case lighting: if (saveFlag) { doingPanel = CONTROLpanel; XUnmapWindow(dsply,saveWindow); } doingPanel = LIGHTpanel; tempLightPointer[0] = viewport->lightVector[0]; tempLightPointer[1] = viewport->lightVector[1]; tempLightPointer[2] = viewport->lightVector[2]; tempLightIntensity = lightIntensity; XMapWindow(dsply,lightingWindow); break; case viewVolume: if (saveFlag) { doingPanel = CONTROLpanel; XUnmapWindow(dsply,saveWindow); } doingPanel = VOLUMEpanel; XMapWindow(dsply,volumeWindow); redrawView = yes; drawViewport(Xoption); /* draw it with doingVolume set to yes */ break; case volumeReturn: doingPanel = CONTROLpanel; redoSmooth = yes; redrawView = yes; XUnmapWindow(dsply,volumeWindow); break; case volumeAbort: doingPanel = CONTROLpanel; redrawView = yes; XUnmapWindow(dsply,volumeWindow); break; case lightReturn: doingPanel = CONTROLpanel; viewport->lightVector[0] = lightPointer[0] = tempLightPointer[0]; viewport->lightVector[1] = lightPointer[1] = tempLightPointer[1]; viewport->lightVector[2] = lightPointer[2] = tempLightPointer[2]; lightIntensity = tempLightIntensity; normalizeVector(viewport->lightVector); redrawView = ((viewData.style == render) || (viewData.style == smooth)); if (movingLight || changedIntensity) redoSmooth = yes; XUnmapWindow(dsply,lightingWindow); break; case lightAbort: movingLight = no; changedIntensity = no; doingPanel = CONTROLpanel; XUnmapWindow(dsply,lightingWindow); break; case resetView: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); viewport->axesOn = yes; viewport->regionOn = no; viewData.box = 0; viewData.outlineRenderOn = 0; viewport->monoOn = no; viewport->zoomXOn = viewport->zoomYOn = viewport->zoomZOn = yes; viewport->originrOn = yes; viewport->objectrOn = no; viewport->originFlag = no; viewport->xyOn = viewport->xzOn = viewport->yzOn = no; viewport->lightVector[0] = -0.5; viewport->lightVector[1] = 0.5; viewport->lightVector[2] = 0.5; viewport->translucency = viewData.translucency; viewport->deltaX = viewport->deltaX0; viewport->deltaY = viewport->deltaY0; viewport->deltaY = viewport->deltaZ0; viewport->scale = viewport->scale0; viewport->scaleX = viewport->scaleY = viewport->scaleZ = 1.0; if (!equal(viewport->theta,viewport->theta0) || !equal(viewport->phi,viewport->phi0)) rotated = yes; viewport->theta = viewport->axestheta = viewport->theta0 = viewData.theta; viewport->phi = viewport->axesphi = viewport->phi0 = viewData.phi; viewport->thetaObj = 0.0; viewport->phiObj = 0.0; redoSmooth = yes; drawViewport(Xoption); if (viewport->haveControl) drawControlPanel(); writeTitle(); break; case axesOnOff: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); if (viewport->axesOn) { viewport->axesOn = no; (control->buttonQueue[axesOnOff]).textColor = offColor; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[axesOnOff]).buttonX, (control->buttonQueue[axesOnOff]).buttonY, (control->buttonQueue[axesOnOff]).buttonWidth, (control->buttonQueue[axesOnOff]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[axesOnOff]).buttonX, (control->buttonQueue[axesOnOff]).buttonY, (control->buttonQueue[axesOnOff]).buttonWidth, (control->buttonQueue[axesOnOff]).buttonHeight,Xoption); } } else { /* draw invert-color button */ viewport->axesOn = yes; (control->buttonQueue[axesOnOff]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[axesOnOff]).buttonX, (control->buttonQueue[axesOnOff]).buttonY, (control->buttonQueue[axesOnOff]).buttonWidth, (control->buttonQueue[axesOnOff]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[axesOnOff]).buttonX, (control->buttonQueue[axesOnOff]).buttonY, (control->buttonQueue[axesOnOff]).buttonWidth, (control->buttonQueue[axesOnOff]).buttonHeight,Xoption); } } s = (control->buttonQueue[axesOnOff]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[axesOnOff]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[axesOnOff]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[axesOnOff]).buttonWidth), (control->buttonQueue[axesOnOff]).buttonY + centerY(processGC, (control->buttonQueue[axesOnOff]).buttonHeight), s,strL,Xoption); if (viewData.style == smooth) { if (multiColorFlag) redoDither = yes; else redoColor = yes; } drawViewport(Xoption); break; case zoomx: if (viewport->zoomXOn) { viewport->zoomXOn = no; (control->buttonQueue[zoomx]).textColor = offColor; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[zoomx]).buttonX, (control->buttonQueue[zoomx]).buttonY, (control->buttonQueue[zoomx]).buttonWidth, (control->buttonQueue[zoomx]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomx]).buttonX, (control->buttonQueue[zoomx]).buttonY, (control->buttonQueue[zoomx]).buttonWidth, (control->buttonQueue[zoomx]).buttonHeight,Xoption); } } else { viewport->zoomXOn = yes; (control->buttonQueue[zoomx]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[zoomx]).buttonX, (control->buttonQueue[zoomx]).buttonY, (control->buttonQueue[zoomx]).buttonWidth, (control->buttonQueue[zoomx]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomx]).buttonX, (control->buttonQueue[zoomx]).buttonY, (control->buttonQueue[zoomx]).buttonWidth, (control->buttonQueue[zoomx]).buttonHeight,Xoption); } } s = (control->buttonQueue[zoomx]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[zoomx]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[zoomx]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[zoomx]).buttonWidth), (control->buttonQueue[zoomx]).buttonY + centerY(processGC, (control->buttonQueue[zoomx]).buttonHeight), s,strL,Xoption); clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); break; case zoomy: if (viewport->zoomYOn) { viewport->zoomYOn = no; (control->buttonQueue[zoomy]).textColor = offColor; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[zoomy]).buttonX, (control->buttonQueue[zoomy]).buttonY, (control->buttonQueue[zoomy]).buttonWidth, (control->buttonQueue[zoomy]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomy]).buttonX, (control->buttonQueue[zoomy]).buttonY, (control->buttonQueue[zoomy]).buttonWidth, (control->buttonQueue[zoomy]).buttonHeight,Xoption); } } else { viewport->zoomYOn = yes; (control->buttonQueue[zoomy]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[zoomy]).buttonX, (control->buttonQueue[zoomy]).buttonY, (control->buttonQueue[zoomy]).buttonWidth, (control->buttonQueue[zoomy]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomy]).buttonX, (control->buttonQueue[zoomy]).buttonY, (control->buttonQueue[zoomy]).buttonWidth, (control->buttonQueue[zoomy]).buttonHeight,Xoption); } } s = (control->buttonQueue[zoomy]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[zoomy]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[zoomy]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[zoomy]).buttonWidth), (control->buttonQueue[zoomy]).buttonY + centerY(processGC, (control->buttonQueue[zoomy]).buttonHeight), s,strL,Xoption); clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); break; case zoomz: if (viewport->zoomZOn) { viewport->zoomZOn = no; (control->buttonQueue[zoomz]).textColor = offColor; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[zoomz]).buttonX, (control->buttonQueue[zoomz]).buttonY, (control->buttonQueue[zoomz]).buttonWidth, (control->buttonQueue[zoomz]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomz]).buttonX, (control->buttonQueue[zoomz]).buttonY, (control->buttonQueue[zoomz]).buttonWidth, (control->buttonQueue[zoomz]).buttonHeight,Xoption); } } else { viewport->zoomZOn = yes; (control->buttonQueue[zoomz]).textColor = onColor; if (mono) { GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[zoomz]).buttonX, (control->buttonQueue[zoomz]).buttonY, (control->buttonQueue[zoomz]).buttonWidth, (control->buttonQueue[zoomz]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[zoomz]).buttonX, (control->buttonQueue[zoomz]).buttonY, (control->buttonQueue[zoomz]).buttonWidth, (control->buttonQueue[zoomz]).buttonHeight,Xoption); } } s = (control->buttonQueue[zoomz]).text; strL = strlen(s); GSetForeground(processGC, (float)monoColor((control->buttonQueue[zoomz]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[zoomz]).buttonX + centerX(processGC,s,strL, (control->buttonQueue[zoomz]).buttonWidth), (control->buttonQueue[zoomz]).buttonY + centerY(processGC, (control->buttonQueue[zoomz]).buttonHeight), s,strL,Xoption); clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); break; case originr: viewport->originrOn = yes; (control->buttonQueue[originr]).textColor = onColor; viewport->objectrOn = no; (control->buttonQueue[objectr]).textColor = offColor; viewport->originFlag = yes; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[objectr]).buttonX, (control->buttonQueue[objectr]).buttonY, (control->buttonQueue[objectr]).buttonWidth, (control->buttonQueue[objectr]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[objectr]).buttonX, (control->buttonQueue[objectr]).buttonY, (control->buttonQueue[objectr]).buttonWidth, (control->buttonQueue[objectr]).buttonHeight,Xoption); GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[originr]).buttonX, (control->buttonQueue[originr]).buttonY, (control->buttonQueue[originr]).buttonWidth, (control->buttonQueue[originr]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[originr]).buttonX, (control->buttonQueue[originr]).buttonY, (control->buttonQueue[originr]).buttonWidth, (control->buttonQueue[originr]).buttonHeight,Xoption); } s1 = (control->buttonQueue[objectr]).text; strL1 = strlen(s1); s2 = (control->buttonQueue[originr]).text; strL2 = strlen(s2); GSetForeground(processGC, (float)monoColor((control->buttonQueue[objectr]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[objectr]).buttonX + centerX(processGC,s1,strL1, (control->buttonQueue[objectr]).buttonWidth), (control->buttonQueue[objectr]).buttonY + centerY(processGC, (control->buttonQueue[objectr]).buttonHeight), s1,strL1,Xoption); GSetForeground(processGC, (float)monoColor((control->buttonQueue[originr]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[originr]).buttonX + centerX(processGC,s2,strL2, (control->buttonQueue[originr]).buttonWidth), (control->buttonQueue[originr]).buttonY + centerY(processGC, (control->buttonQueue[originr]).buttonHeight), s2,strL2,Xoption); clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); break; case objectr: viewport->objectrOn = yes; (control->buttonQueue[objectr]).textColor = onColor; viewport->originrOn = no; (control->buttonQueue[originr]).textColor = offColor; viewport->originFlag = no; if (mono) { XChangeShade(dsply,offShade); XShadeRectangle(dsply,control->controlWindow, (control->buttonQueue[originr]).buttonX, (control->buttonQueue[originr]).buttonY, (control->buttonQueue[originr]).buttonWidth, (control->buttonQueue[originr]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[originr]).buttonX, (control->buttonQueue[originr]).buttonY, (control->buttonQueue[originr]).buttonWidth, (control->buttonQueue[originr]).buttonHeight,Xoption); GSetForeground(globalGC1,(float)backgroundColor,Xoption); XFillRectangle(dsply, control->controlWindow, globalGC1, (control->buttonQueue[objectr]).buttonX, (control->buttonQueue[objectr]).buttonY, (control->buttonQueue[objectr]).buttonWidth, (control->buttonQueue[objectr]).buttonHeight); GSetForeground(globalGC1,(float)foregroundColor,Xoption); GDrawRectangle(globalGC1, control->controlWindow, (control->buttonQueue[objectr]).buttonX, (control->buttonQueue[objectr]).buttonY, (control->buttonQueue[objectr]).buttonWidth, (control->buttonQueue[objectr]).buttonHeight,Xoption); } s1 = (control->buttonQueue[objectr]).text; strL1 = strlen(s1); s2 = (control->buttonQueue[originr]).text; strL2 = strlen(s2); GSetForeground(processGC, (float)monoColor((control->buttonQueue[objectr]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[objectr]).buttonX + centerX(processGC,s1,strL1, (control->buttonQueue[objectr]).buttonWidth), (control->buttonQueue[objectr]).buttonY + centerY(processGC, (control->buttonQueue[objectr]).buttonHeight), s1,strL1,Xoption); GSetForeground(processGC, (float)monoColor((control->buttonQueue[originr]).textColor),Xoption); GDrawImageString(processGC,control->controlWindow, (control->buttonQueue[originr]).buttonX + centerX(processGC,s2,strL2, (control->buttonQueue[originr]).buttonWidth), (control->buttonQueue[originr]).buttonY + centerY(processGC, (control->buttonQueue[originr]).buttonHeight), s2,strL2,Xoption); clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); break; case ps: strcpy(control->message," Creating postscript file ... "); writeControlMessage(); if (PSInit(viewport->viewWindow, viewport->titleWindow) == psError) { strcpy(control->message," Aborted: PSInit error. "); writeControlMessage(); return; /* make new tmpnam for new file */ } redoSmooth = yes; drawViewport(PSoption); /* draw picture in PS; create ps script file */ if (PSCreateFile(viewBorderWidth, viewport->viewWindow, viewport->titleWindow, viewport->title) == psError) { strcpy(control->message," Aborted: PSCreateFile error. "); writeControlMessage(); return; } clearControlMessage(); strcpy(control->message,PSfilename); strcat(control->message," in working dir "); writeControlMessage(); break; case pixmap: strcpy(control->message," Creating axiom3D.xpm now ... "); writeControlMessage(); XGetWindowAttributes(dsply,viewport->viewWindow,&vwInfo); write_pixmap_file(dsply,scrn,"axiom3D.xpm", viewport->titleWindow,0,0,vwInfo.width, vwInfo.height+titleHeight); clearControlMessage(); strcpy(control->message," axiom3D.xpm in working dir "); writeControlMessage(); break; case transparent: case opaqueMesh: case render: case smooth: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); viewData.style = bKey; drawViewport(Xoption); /* draw picture in viewWindow with X routines */ break; case closeAll: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); doingPanel = QUITpanel; viewport->closing = yes; XMapWindow(dsply,quitWindow); break; case quitReturn: XUnmapWindow(dsply,quitWindow); break; case quitAbort: doingPanel = CONTROLpanel; XUnmapWindow(dsply,quitWindow); break; case saveit: clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); saveFlag = yes; doingPanel = SAVEpanel; XMapWindow(dsply,saveWindow); break; case saveExit: saveFlag = no; doingPanel = CONTROLpanel; XUnmapWindow(dsply,saveWindow); break; case xy: viewport->theta = pi; viewport->phi = 0.0; viewport->axestheta = pi; viewport->axesphi = 0.0; rotated = yes; viewport->yzOn = viewport->xzOn = no; viewport->xyOn = yes; drawViewport(Xoption); break; case xz: viewport->theta = pi; viewport->phi = -pi_half; viewport->axestheta = pi; viewport->axesphi = -pi_half; rotated = yes; viewport->yzOn = viewport->xyOn = no; viewport->xzOn = yes; drawViewport(Xoption); break; case yz: viewport->theta = pi_half; viewport->phi = -pi_half; viewport->axestheta = pi_half; viewport->axesphi = -pi_half; rotated = yes; viewport->xzOn = viewport->xyOn = no; viewport->yzOn = yes; drawViewport(Xoption); break; default: fprintf(stderr,"Received a non-functioning button request: %d \n",bKey); break; } /* switch (action) */ } /* processEvents() */ /************************** X Event Processing *****************************/ void processEvents(void) { XEvent *event, tempEvent; Window whichWindow; buttonStruct *controlButton; mouseCoord mouseXY, linearMouseXY; int someInt, mouseW4, mouseH4; int toggleReady =yes; int checkButton = no; int first_time = yes; int changingColor = yes; int gotEvent = 0, exposeView = no; int tempTW, tempTH, tempVW, tempVH; int buttonTablePtr; float f1, f2; int px, py, lx, ly; unsigned int lbuttons; Window dummy; int Xcon,externalControl,len; fd_set rd; externalControl = 0; Xcon = ConnectionNumber(dsply); /** assign lightPointer for light panel **/ lightPointer[0] = tempLightPointer[0] = viewport->lightVector[0]; lightPointer[1] = tempLightPointer[1] = viewport->lightVector[1]; lightPointer[2] = tempLightPointer[2] = viewport->lightVector[2]; if (!(event = (XEvent *)saymem("process.c",1,sizeof(XEvent)))) { fprintf(stderr,"Ran out of memory initializing event processing.\n"); exitWithAck(RootWindow(dsply,scrn),Window,-1); } controlButton = 0; while(1) { /* Store old viewport window size attributes for resizing comparison. */ XGetWindowAttributes(dsply,viewport->titleWindow,&graphWindowAttrib); tempTW = graphWindowAttrib.width; tempTH = graphWindowAttrib.height; XGetWindowAttributes(dsply,viewport->viewWindow,&graphWindowAttrib); tempVW = graphWindowAttrib.width; tempVH = graphWindowAttrib.height; /* Get the next X event. The check for pending events is so that a held down mouse button is interpreted as an event even if nothing is pending. */ len=0; while(len<=0) { FD_ZERO(&rd); if (externalControl==0) FD_SET(0, &rd); FD_SET(Xcon,&rd); if (XEventsQueued(dsply, QueuedAlready)) { len=1; break; } if (!followMouse) len=select(FD_SETSIZE,(void *)&rd,0,0,0); else len=1; } if (FD_ISSET(Xcon,&rd)|| XEventsQueued(dsply, QueuedAfterFlush) || followMouse) { if (followMouse) { if (XPending(dsply)) XNextEvent(dsply,event); gotEvent++; } else { XNextEvent(dsply,event); gotEvent++; } if (gotToggle || !followMouse) checkButton = no; if (gotEvent) { whichWindow = ((XButtonEvent *)event)->window; first_time = no; switch(((XEvent *)event)->type) { case ClientMessage: if (event->xclient.data.l[0] == wm_delete_window) { goodbye(-1); } else { fprintf(stderr,"Unknown Client Message ...\n"); } break; case Expose: if (whichWindow == viewport->titleWindow) { exposeView = yes; followMouse = no; XSync(dsply,0); /* get rid of redundant exposure events */ XCheckWindowEvent(dsply,viewport->titleWindow, ExposureMask,&tempEvent); writeTitle(); XGetWindowAttributes(dsply,viewport->titleWindow, &graphWindowAttrib); if ((graphWindowAttrib.width!=tempTW) || ((graphWindowAttrib.height)!=tempTH)) { XResizeWindow(dsply,viewport->viewWindow, graphWindowAttrib.width, graphWindowAttrib.height); redoSmooth = yes; /* recompute smooth image pixmap if resized */ } } else if (whichWindow == viewport->viewWindow) { exposeView = yes; followMouse = no; XSync(dsply,0); XCheckWindowEvent(dsply,viewport->viewWindow,ExposureMask, &tempEvent); XGetWindowAttributes(dsply,viewport->viewWindow,&graphWindowAttrib); if ((graphWindowAttrib.width!=tempVW) || ((graphWindowAttrib.height)!=tempVH)) { XResizeWindow(dsply,viewport->viewWindow,graphWindowAttrib.width, graphWindowAttrib.height); redoSmooth = yes; /* recompute smooth image pixmap if resized */ } drawViewport(Xoption); XMapWindow(dsply,whichWindow); } else if (whichWindow == lightingWindow) { XGetWindowAttributes(dsply,control->controlWindow, &graphWindowAttrib); /* do not allow resizing of control panel */ if ((graphWindowAttrib.width!=controlWidth) || (graphWindowAttrib.height!=controlHeight)) { XResizeWindow(dsply,control->controlWindow,controlWidth, controlHeight); } drawLightingPanel(); } else if (whichWindow == volumeWindow) { XGetWindowAttributes(dsply,control->controlWindow, &graphWindowAttrib); /* do not allow resizing of control panel */ if ((graphWindowAttrib.width!=controlWidth) || (graphWindowAttrib.height!=controlHeight)) { XResizeWindow(dsply,control->controlWindow,controlWidth, controlHeight); } drawVolumePanel(); if (redrawView) { redrawView = no; drawViewport(Xoption); } } else if (whichWindow == quitWindow) { XGetWindowAttributes(dsply,control->controlWindow, &graphWindowAttrib); /* do not allow resizing of control panel */ if ((graphWindowAttrib.width!=controlWidth) || (graphWindowAttrib.height!=controlHeight)) { XResizeWindow(dsply,control->controlWindow,controlWidth, controlHeight); } drawQuitPanel(); } else if (whichWindow == saveWindow) { XGetWindowAttributes(dsply,control->controlWindow, &graphWindowAttrib); /* do not allow resizing of control panel */ if ((graphWindowAttrib.width!=controlWidth) || (graphWindowAttrib.height!=controlHeight)) { XResizeWindow(dsply,control->controlWindow,controlWidth, controlHeight); } drawSavePanel(); } else if (whichWindow == control->controlWindow) { XGetWindowAttributes(dsply,control->controlWindow, &graphWindowAttrib); /* do not allow resizing of control panel */ if ((graphWindowAttrib.width != controlWidth) || (graphWindowAttrib.height != controlHeight)) { XResizeWindow(dsply,control->controlWindow, controlWidth,controlHeight); } if (viewport->haveControl) drawControlPanel(); followMouse = no; if (redrawView || exposeView) { redrawView = no; drawViewport(Xoption); } exposeView = no; } else { fprintf(stderr,"Not a valid window.\n"); } XFlush(dsply); while(XCheckTypedWindowEvent(dsply, whichWindow, Expose, &tempEvent)); break; case MotionNotify: exposeView = no; if (followMouse) { if (whichWindow == control->colormapWindow) { while (XCheckMaskEvent(dsply,ButtonMotionMask,event)); first_time = checkButton = followMouse = changingColor = yes; gotToggle = no; } else if (whichWindow != control->controlWindow) { if (controlButton->pot) { while (XCheckMaskEvent(dsply,ButtonMotionMask,event)); mouseXY = getPotValue(((XButtonEvent *)event)->x, ((XButtonEvent *)event)->y, controlButton->xHalf, controlButton->yHalf); linearMouseXY = getLinearPotValue(((XButtonEvent *)event)->x, ((XButtonEvent *)event)->y, controlButton->xHalf, controlButton->yHalf); first_time = checkButton = followMouse = yes; gotToggle = no; } } } break; case ButtonRelease: exposeView = followMouse = no; toggleReady = yes; gotToggle = yes; break; case LeaveNotify: XQueryPointer(dsply,rtWindow,&dummy,&dummy,&px,&py,&lx,&ly,&lbuttons); if ( (controlButton) && ((whichWindow == control->colormapWindow) || (controlButton->pot)) && (lbuttons & Button1Mask || lbuttons & Button2Mask || lbuttons & Button3Mask)) { followMouse = yes; if (whichWindow == control->colormapWindow) changingColor = yes; } else { followMouse = no; changingColor = no; } toggleReady = yes; checkButton = exposeView = no; break; case ButtonPress: exposeView = no; changingColor = no; if (whichWindow == viewport->viewWindow) { /* find out where the mouse button is pressed on the viewport, this determines where to put the control panel */ XGetWindowAttributes(dsply,whichWindow,&graphWindowAttrib); mouseW4 = graphWindowAttrib.width/4; if (((XButtonEvent *)event)->x > (graphWindowAttrib.width-mouseW4)) someInt = 1; else { mouseH4 = graphWindowAttrib.height/4; if (((XButtonEvent *)event)->y > (graphWindowAttrib.height - mouseH4)) someInt = 2; else if (((XButtonEvent *)event)->x < mouseW4) someInt = 3; else if (((XButtonEvent *)event)->y < mouseH4) someInt = 4; else someInt = 0; } if (viewport->haveControl) { XUnmapWindow(dsply,control->controlWindow); } putControlPanelSomewhere(someInt); writeControlMessage(); XSync(dsply,0); } else if (whichWindow == control->colormapWindow) { gotToggle = no; first_time = checkButton = followMouse = changingColor = yes; } else if (whichWindow != control->controlWindow) { /* mouse clicked on one of the buttons */ if (!controlButton || (controlButton->self != whichWindow)) { buttonTablePtr = *((int *)XLookUpAssoc(dsply,table,whichWindow)); /** lighting buttons have indices greater than 100 **/ /** all buttons share the same array now **/ controlButton = &(control->buttonQueue[buttonTablePtr]); } if (controlButton->pot) { /* figure out [x,y] for this button in the range [-1..1,-1..1] */ mouseXY = getPotValue(((XButtonEvent *)event)->x, ((XButtonEvent *)event)->y, controlButton->xHalf,controlButton->yHalf); linearMouseXY = getLinearPotValue(((XButtonEvent *)event)->x, ((XButtonEvent *)event)->y, controlButton->xHalf, controlButton->yHalf); followMouse = yes; gotToggle = no; } else { followMouse = no; gotToggle = yes; /* auto-repeat of toggle buttons not allowed */ if (toggleReady) toggleReady = no; } checkButton = yes; first_time = yes; } break; default: toggleReady = gotToggle = yes; exposeView = changingColor = checkButton = followMouse = no; break; } /* switch */ gotEvent--; } /* if gotEvent */ /* Allow a pressed mouse button on a potentiometer to poll repeatedly. */ if (followMouse && !first_time && (followMouse++ > mouseWait)) { /* reset for next timing loop */ followMouse = yes; checkButton = yes; } if (checkButton) { if (viewport->closing && (controlButton->buttonKey == quitReturn)) { goodbye(-1); } else if (changingColor) { viewport->closing = no; /* moving top color map pointer */ if (((XButtonEvent *)event)->y < colorOffsetY) { if (((XButtonEvent *)event)->x < (colorOffset+colorWidth)) { /* decreasing top hue number */ if (viewport->hueTop > 0) viewport->hueTop--; } else if (((XButtonEvent *)event)->x >= (colorOffsetX + totalHues*colorWidth + colorWidth)) { if (viewport->hueTop < totalHues) viewport->hueTop++; } else { viewport->hueTop = (((XButtonEvent *)event)->x - colorOffsetX + colorWidth/2 - 13) / colorWidth; } } else if (((XButtonEvent *)event)->y > (colorOffsetY + colorHeight)) { /* moving bottom color map pointer */ if (((XButtonEvent *)event)->x < (colorOffset+colorWidth)) { /* decreasing offset number */ if (viewport->hueOffset > 0) viewport->hueOffset--; } else if (((XButtonEvent *)event)->x >= (colorOffsetX + totalHues*colorWidth + colorWidth)) { if (viewport->hueOffset < totalHues) viewport->hueOffset++; } else { viewport->hueOffset = (((XButtonEvent *)event)->x - colorOffsetX + colorWidth/2 - 13) / colorWidth; } } /* color map pointer does not wrap around */ if (viewport->hueOffset < 0) viewport->hueOffset = 0; if (viewport->hueTop < 0) viewport->hueTop = 0; if (viewport->hueOffset >= totalHues) viewport->hueOffset = totalHues-1; if (viewport->hueTop >= totalHues) viewport->hueTop = totalHues-1; viewport->numberOfHues = viewport->hueTop - viewport->hueOffset; if ((viewport->hueTop == viewport->hueOffset) && !viewport->monoOn) { redoColor = yes; redoDither = no; } else { redoColor = no; redoDither = yes; } /* update color map changes on control panel */ drawColorMap(); } else { viewport->closing = no; clearControlMessage(); /* reset all the things that might affect a recalculation for redrawing removing hidden surfaces */ /* determine what type of button has been pressed */ switch(controlButton->buttonKey) { /*** Potentiometers ***/ case rotate: if (!((viewport->originrOn) && (viewport->objectrOn))) { /* update the amount of rotation around the object center of volume */ if (viewport->objectrOn) { viewport->thetaObj += mouseXY.x * rotateFactor; viewport->phiObj -= mouseXY.y * rotateFactor; while (viewport->thetaObj >= two_pi) { viewport->thetaObj -= two_pi; } while (viewport->thetaObj < 0.0) { viewport->thetaObj += two_pi; } while (viewport->phiObj > pi) { viewport->phiObj -= two_pi; } while (viewport->phiObj <= -pi) { viewport->phiObj += two_pi; } } /* update amount of rotation around the world space origin */ if (viewport->originrOn) { viewport->theta += mouseXY.x * rotateFactor; viewport->phi -= mouseXY.y * rotateFactor; while (viewport->theta >= two_pi) { viewport->theta -= two_pi; } while (viewport->theta < 0.0) { viewport->theta += two_pi; } while (viewport->phi > pi) { viewport->phi -= two_pi; } while (viewport->phi <= -pi) { viewport->phi += two_pi; } viewport->axestheta += mouseXY.x * rotateFactor; viewport->axesphi -= mouseXY.y * rotateFactor; while (viewport->axestheta >= two_pi) { viewport->axestheta -= two_pi; } while (viewport->axestheta < 0.0) { viewport->axestheta += two_pi; } while (viewport->axesphi > pi) { viewport->axesphi -= two_pi; } while (viewport->axesphi <= -pi) { viewport->axesphi += two_pi; } } rotated = yes; viewport->yzOn = viewport->xzOn = viewport->xyOn = no; clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); drawViewport(Xoption); } break; case zoom: /* if uniform scaling */ if ((viewport->zoomXOn) && (viewport->zoomYOn) && (viewport->zoomZOn)) { viewport->scale *= 1 - mouseXY.y * scaleFactor; } else { /* else scale axes independently */ if (viewport->zoomXOn) viewport->scaleX *= (1 - mouseXY.y); if (viewport->zoomYOn) viewport->scaleY *= (1 - mouseXY.y); if (viewport->zoomZOn) viewport->scaleZ *= (1 - mouseXY.y); } if (viewport->scale > maxScale) viewport->scale = maxScale; else if (viewport->scale < minScale) viewport->scale = minScale; if (viewport->scaleX > maxScale) viewport->scaleX = maxScale; else if (viewport->scaleX < minScale) viewport->scaleX = minScale; if (viewport->scaleY > maxScale) viewport->scaleY = maxScale; else if (viewport->scaleY < minScale) viewport->scaleY = minScale; if (viewport->scaleZ > maxScale) viewport->scaleZ = maxScale; else if (viewport->scaleZ < minScale) viewport->scaleZ = minScale; zoomed = yes; clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); if ((viewport->zoomXOn) || (viewport->zoomYOn) || (viewport->zoomZOn)) drawViewport(Xoption); break; case translate: viewport->deltaX += mouseXY.x * translateFactor; viewport->deltaY += mouseXY.y * translateFactor; if (viewport->deltaX > maxDeltaX) viewport->deltaX = maxDeltaX; else if (viewport->deltaX < -maxDeltaX) viewport->deltaX = -maxDeltaX; if (viewport->deltaY > maxDeltaY) viewport->deltaY = maxDeltaY; else if (viewport->deltaY < -maxDeltaY) viewport->deltaY = -maxDeltaY; translated = yes; clearControlMessage(); strcpy(control->message,viewport->title); writeControlMessage(); drawViewport(Xoption); break; /*** Lighting panel ***/ case lightMoveXY: tempLightPointer[0] = linearMouseXY.x; tempLightPointer[1] = linearMouseXY.y; if (tempLightPointer[0] > 1) tempLightPointer[0] = 1; else if (tempLightPointer[0] < -1) tempLightPointer[0] = -1; if (tempLightPointer[1] > 1) tempLightPointer[1] = 1; else if (tempLightPointer[1] < -1) tempLightPointer[1] = -1; movingLight = yes; drawLightingAxes(); break; case lightMoveZ: tempLightPointer[2] = linearMouseXY.y; /* linearMouse => no checking necessary */ if (tempLightPointer[2] > 1) tempLightPointer[2] = 1; else if (tempLightPointer[2] < -1) tempLightPointer[2] = -1; movingLight = yes; drawLightingAxes(); break; /* changes the light intensity */ case lightTranslucent: tempLightIntensity = (linearMouseXY.y+1)/2; if (tempLightIntensity > 1) tempLightIntensity = 1; else if (tempLightIntensity < 0) tempLightIntensity = 0; changedIntensity = yes; drawLightTransArrow(); break; /*** volume panel ***/ case frustrumBut: screenX = ((XButtonEvent *)event)->x; if inside(eyeMinX,eyeMaxX) { /* object coordinate */ f2 = mouseXY.x * (maxEyeDistance - minEyeDistance) + minEyeDistance; if (f2 != viewData.eyeDistance) { doingVolume = 2; /* flag for using screenX */ changedEyeDistance = yes; viewData.eyeDistance = f2; drawFrustrum(); drawViewport(Xoption); } } else if inside(hitherMinX,hitherMaxX) { f1 = ((float)hitherMaxX - ((XButtonEvent *)event)->x) / (hitherMaxX - hitherMinX); /* object coordinate */ f2 = f1 * (clipPlaneMax - clipPlaneMin) + clipPlaneMin; if (f2 != viewData.clipPlane) { doingVolume = 3; /* flag for using screenX */ viewData.clipPlane = f2; drawFrustrum(); drawViewport(Xoption); } } else { doingVolume = 1; /* check out doingVolume */ doingPanel = VOLUMEpanel; } break; case clipXBut: /* this is a horizontal button */ clipValue = linearMouseXY.x * 0.5 + 0.5; /* normalize to 0..1 */ if (lessThan(clipValue,0.0)) clipValue = 0.0; if (greaterThan(clipValue,1.0)) clipValue = 1.0; if (lessThan(linearMouseXY.y,0.0)) { if (!equal(xClipMinN,clipValue)) { if (greaterThan(xClipMaxN-clipValue,minDistXY)) xClipMinN = clipValue; else xClipMinN = xClipMaxN - minDistXY; viewData.clipXmin = xClipMinN * (viewData.xmax - viewData.xmin) + viewData.xmin; drawClipXBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } else { if (!equal(xClipMaxN,clipValue)) { if (greaterThan(clipValue-xClipMinN,minDistXY)) xClipMaxN = clipValue; else xClipMaxN = xClipMinN + minDistXY; viewData.clipXmax = xClipMaxN * (viewData.xmax - viewData.xmin) + viewData.xmin; drawClipXBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } break; case clipYBut: /* this is a vertical button */ /* normalize to 0..1, bottom up */ clipValue = 1 - (linearMouseXY.y * 0.5 + 0.5); if (lessThan(clipValue,0.0)) clipValue = 0.0; if (greaterThan(clipValue,1.0)) clipValue = 1.0; if (lessThan(linearMouseXY.x,0.0)) { if (!equal(yClipMinN,clipValue)) { if (greaterThan(yClipMaxN-clipValue,minDistXY)) yClipMinN = clipValue; else yClipMinN = yClipMaxN - minDistXY; viewData.clipYmin = yClipMinN * (viewData.ymax - viewData.ymin) + viewData.ymin; drawClipYBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } else { if (!equal(yClipMaxN,clipValue)) { if (greaterThan(clipValue-yClipMinN,minDistXY)) yClipMaxN = clipValue; else yClipMaxN = yClipMinN + minDistXY; viewData.clipYmax = yClipMaxN * (viewData.ymax - viewData.ymin) + viewData.ymin; drawClipYBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } break; case clipZBut: /* this is a diagonally aligned button! */ /* f1 is the distance from the center of the button along the diagonal line with a slope of -1. If f1 is negative, the direction is downward from the center, if f1 is positive, the direction is upward from the center. Note that there ought to be a constant factor, namely cos(45), multiplied by f1 for the correct normalized value; however, we exploit this by foreshortening the length of the diagonal by that same factor (so instead of normalizing the numbers to, the line we normalize the line to the numbers) since we need to shorten the line at some point anyway (both to match the length of the diagonal side of the box and to allow more area for mouse input. */ /* cos(45), etc => 0.4 */ f1 = (linearMouseXY.x - linearMouseXY.y) * 0.4 + 0.5; if (lessThan(f1,0.0)) f1 = 0.0; if (greaterThan(f1,1.0)) f1 = 1.0; /* note that x moving upward */ if (lessThan(-linearMouseXY.x,linearMouseXY.y)) { if (!equal(zClipMaxN,f1)) { if (greaterThan(f1-zClipMinN,minDistZ)) zClipMaxN = f1; else zClipMaxN = zClipMinN + minDistZ; viewData.clipZmax = zClipMaxN * (viewData.zmax - viewData.zmin) + viewData.zmin; drawClipZBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } else { if (!equal(zClipMinN,f1)) { if (greaterThan(zClipMaxN-f1,minDistZ)) zClipMinN = f1; else zClipMinN = zClipMaxN - minDistZ; viewData.clipZmin = zClipMinN * (viewData.zmax - viewData.zmin) + viewData.zmin; drawClipZBut(); drawClipVolume(); if (viewData.clipbox) drawViewport(Xoption); } } /* if lessThan(x,y) */ break; case perspectiveBut: if ((viewData.perspective = !viewData.perspective)) { switchedPerspective = yes; GSetForeground(volumeGC, (float)monoColor((control->buttonQueue[perspectiveBut]).textColor),Xoption); GDrawString(volumeGC,volumeWindow, controlButton->buttonX + centerX(volumeGC,"x",1,controlButton->buttonWidth), controlButton->buttonY + centerY(volumeGC,controlButton->buttonHeight), "x",1,Xoption); } else XClearArea(dsply,volumeWindow, controlButton->buttonX+1, controlButton->buttonY+1, controlButton->buttonHeight-2, controlButton->buttonWidth-2, False); drawViewport(Xoption); break; case clipRegionBut: if ((viewData.clipbox = !viewData.clipbox)) { GSetForeground(volumeGC, (float)monoColor((control->buttonQueue[clipRegionBut]).textColor),Xoption); GDrawString(volumeGC,volumeWindow, controlButton->buttonX + centerX(volumeGC,"x",1,controlButton->buttonWidth), controlButton->buttonY + centerY(volumeGC,controlButton->buttonHeight), "x",1,Xoption); } else XClearArea(dsply,volumeWindow, controlButton->buttonX+1, controlButton->buttonY+1, controlButton->buttonWidth-2, controlButton->buttonHeight-2, False); drawViewport(Xoption); break; case clipSurfaceBut: if ((viewData.clipStuff = !viewData.clipStuff)) { GSetForeground(volumeGC, (float)monoColor((control->buttonQueue[clipSurfaceBut]).textColor),Xoption); GDrawString(volumeGC,volumeWindow, controlButton->buttonX + centerX(volumeGC,"x",1,controlButton->buttonWidth), controlButton->buttonY + centerY(volumeGC,controlButton->buttonHeight), "x",1,Xoption); } else XClearArea(dsply,volumeWindow, controlButton->buttonX+1, controlButton->buttonY+1, controlButton->buttonWidth-2, controlButton->buttonHeight-2, False); break; default: buttonAction(controlButton->buttonKey); } /* switch on buttonKey */ } /* else - not closing */ } /* if checkButton */ } /* if FD_ISSET(Xcon,.. */ else if (FD_ISSET(0,&rd)) { externalControl = spadAction(); if (spadDraw && (externalControl==0)) drawViewport(Xoption); } } /* for (until closed) */ } /* processEvents() */