////////////////////////////////////////////////////////////////////// /* z_volumes.sch */ /* Author: DJ Jones */ /* By including this file and calling UPDATE_ZVOLUME_WIDGETS each */ /* frame, you will find a set of widgets called Script/Z-Aligned */ /* Volumes. Here, you can draw a variety of volumetric shapes and */ /* grab the data for use with ANGLED_AREA checks or other collision */ /* functionality. */ ////////////////////////////////////////////////////////////////////// // This file contains debug-only functionality. #IF IS_DEBUG_BUILD USING "commands_debug.sch" USING "commands_camera.sch" USING "commands_object.sch" USING "script_maths.sch" USING "script_player.sch" CONST_INT iMAX_ZVC_VERTS 80 // A volume that rotates freely on the z axis. // Can be interpreted as a rectangular prism, elliptic cylinder, or elliptoid. // Does not support negative dimensions. // fWidth = x, fDepth = y, fHeight = z; fRotation is rotation on z-axis in degrees. STRUCT zVolume VECTOR vCenter FLOAT fWidth FLOAT fDepth FLOAT fHeight FLOAT fRotation ENDSTRUCT // A triangle with three vertices. //STRUCT zTriangle // VECTOR p1, p2, p3 //ENDSTRUCT // Control variables for widgets. FLOAT zvw_fPosX // Center position x FLOAT zvw_fPosY // Center position y FLOAT zvw_fPosZ // Center position z FLOAT zvw_fDimX // Width FLOAT zvw_fDimY // Depth FLOAT zvw_fDimZ // Height FLOAT zvw_fRotZ // Rot on z axis in deg BOOL zvw_bPosSnapPlr // Snap volume pos to player BOOL zvw_bRotSnapPlr // Snap volume rot to player BOOL zvw_bPosSnapCam // Snap volume pos to cam BOOL zvw_bRotSnapCam // Snap volume rot to cam BOOL zvw_bPosSnapOrg // Snap volume pos to origin BOOL zvw_bRotSnapOrg // Snap volume rot to zero BOOL zvw_bDefaultDim // Back to default dims BOOL zvw_bDrawMaster // Master draw control BOOL zvw_bDrawAsRec // Consider as rect prism BOOL zvw_bDrawAsCyl // Consider as ellip cyl BOOL zvw_bDrawAsEld // Consider as elliptoid INT zvw_iSubdiv // Subdivisions (pie pieces) BOOL zvw_bDrawWire // Wireframe draw control INT zvw_iAlphaWire // Wireframe alpha BOOL zvw_bDrawFace // Face draw control INT zvw_iAlphaFace // Face alpha BOOL zvw_bDoCollision // Perform collision checks BOOL zvw_bVolCheckPlr // Player in volume status BOOL zvw_bVolCheckCam // Camera in volume status VECTOR zvw_vAngMidpt1 // Midpt 1 for angled area VECTOR zvw_vAngMidpt2 // Midpt 2 for angled area FLOAT zvw_fAngMidpt1x // Angled area midpt 1 x FLOAT zvw_fAngMidpt1y // Angled area midpt 1 y FLOAT zvw_fAngMidpt1z // Angled area midpt 1 z FLOAT zvw_fAngMidpt2x // Angled area midpt 2 x FLOAT zvw_fAngMidpt2y // Angled area midpt 2 y FLOAT zvw_fAngMidpt2z // Angled area midpt 2 z FLOAT zvw_fAngWidth // Width for angled area // Do not touch WIDGET_GROUP_ID zvw_zVolumeWidgets WIDGET_GROUP_ID zvw_posDimGroup WIDGET_GROUP_ID zvw_renderingGroup WIDGET_GROUP_ID zvw_collisionGroup WIDGET_GROUP_ID zvw_angledAreaGroup INT zvw_iMode BOOL zvw_bInit zVolume zvw_Volume //zTriangle zvw_Triangles[512] // Get the zVolume equivalent of an area check (as in IS_ENTITY_IN_AREA) PROC GET_ZVOLUME_FROM_AREA(zVolume &vol, VECTOR vCorner1, VECTOR vCorner2, BOOL bDo3DCheck) vol.vCenter = <<0.5 * (vCorner1.x + vCorner2.x), 0.5 * (vCorner1.y + vCorner2.y), 0.5 * (vCorner1.z + vCorner2.z)>> vol.fWidth = ABSF(vCorner2.x - vCorner1.x) vol.fDepth = ABSF(vCorner2.y - vCorner1.y) vol.fHeight = PICK_FLOAT(bDo3DCheck, ABSF(vCorner2.z - vCorner1.z), 10000.0) vol.fRotation = 0.0 ENDPROC // Get the midpoints and width of an angled area based on a z-volume. PROC GET_ANGLED_AREA_FROM_ZVOLUME(zVolume vol, VECTOR& vMidpt1, VECTOR& vMidpt2, FLOAT& fWidth) VECTOR vProj FLOAT fSin = SIN(vol.fRotation) FLOAT fCos = COS(vol.fRotation) FLOAT fHalfWidth = 0.5 * vol.fWidth vProj.x = fCos * fHalfWidth vProj.y = fSin * fHalfWidth vMidpt1 = vol.vCenter + vProj vMidpt2 = vol.vCenter - vProj fWidth = vol.fDepth ENDPROC // Get the bottom center point of a zVolume, usually for a cylinder. //FUNC VECTOR GET_ZVOLUME_BOTTOM(zVolume vol) // vol.vCenter.z -= 0.5 * vol.fHeight // RETURN vol.vCenter //ENDFUNC // Debug draw for rectangular prism. PROC DRAW_ZVOLUME_REC(zVolume vol, BOOL bDrawWire, BOOL bDrawFace) VECTOR vUNE, vUNW, vUSW, vUSE, vLNE, vLNW, vLSW, vLSE VECTOR vNProj, vSProj, vWProj, vEProj, vUProj, vDProj // Quit if there's nothing to do. IF NOT bDrawWire AND NOT bDrawFace EXIT ENDIF // Create projection vectors. vEProj = <> vNProj = <<-vEProj.y, vEProj.x, 0.0>> vEProj *= vol.fWidth * 0.5 vWProj = -vEProj vNProj *= vol.fDepth * 0.5 vSProj = -vNProj vUProj = <<0.0, 0.0, 0.5 * vol.fHeight>> vDProj = <<0.0, 0.0, -0.5 * vol.fHeight>> // Create vertices. vUNE = vol.vCenter + vUProj + vNProj + vEProj vUNW = vol.vCenter + vUProj + vNProj + vWProj vUSW = vol.vCenter + vUProj + vSProj + vWProj vUSE = vol.vCenter + vUProj + vSProj + vEProj vLNE = vol.vCenter + vDProj + vNProj + vEProj vLNW = vol.vCenter + vDProj + vNProj + vWProj vLSW = vol.vCenter + vDProj + vSProj + vWProj vLSE = vol.vCenter + vDProj + vSProj + vEProj // Draw wireframe. IF bDrawWire DRAW_DEBUG_LINE(vUNE, vUNW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUNW, vUSW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUSW, vUSE, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUSE, vUNE, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vLNE, vLNW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vLNW, vLSW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vLSW, vLSE, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vLSE, vLNE, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUNE, vLNE, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUNW, vLNW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUSW, vLSW, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vUSE, vLSE, 0, 255, 0, zvw_iAlphaWire) ENDIF // Draw faces. IF bDrawFace DRAW_DEBUG_POLY(vUNE, vUNW, vUSE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vUNW, vUSW, vUSE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNW, vLNE, vLSW, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNE, vLSE, vLSW, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNE, vLNW, vUNE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNW, vUNW, vUNE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNW, vLSW, vUNW, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLSW, vUSW, vUNW, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLSE, vLNE, vUSE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLNE, vUNE, vUSE, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLSW, vLSE, vUSW, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vLSE, vUSE, vUSW, 0, 0, 127, zvw_iAlphaFace) ENDIF ENDPROC // Debug draw for elliptic cylinder. PROC DRAW_ZVOLUME_CYL(zVolume vol, BOOL bDrawWire, BOOL bDrawFace, INT iSubdivisions) VECTOR vUProj VECTOR vOffset VECTOR vNegOffset VECTOR vVertices[iMAX_ZVC_VERTS] VECTOR vTopVertexCenter VECTOR vBottomVertexCenter VECTOR vTopVertexCur VECTOR vBottomVertexCur VECTOR vTopVertexNext VECTOR vBottomVertexNext FLOAT fLocalAngle FLOAT fSubdivisions = TO_FLOAT(iSubdivisions) INT iHalfSubdivisions = iSubdivisions / 2 INT i // Quit if there's nothing to do. IF NOT bDrawWire AND NOT bDrawFace EXIT ENDIF // Check for valid subdivisions. IF iSubdivisions < 3 SCRIPT_ASSERT("Can't draw a cylinder with less than three subdivisions!") EXIT ELIF iSubdivisions > iMAX_ZVC_VERTS / 2 SCRIPT_ASSERT("Too many subdivisions! Check iMAX_ZVC_VERTS and divide by two!") EXIT ENDIF // Create projection vector. vUProj = <<0.0, 0.0, 0.5 * vol.fHeight>> // Generate vertices. REPEAT iHalfSubdivisions i fLocalAngle = (TO_FLOAT(i) / fSubdivisions) * 360.0 vOffset = <> vOffset = ROTATE_VECTOR_ABOUT_Z(vOffset, vol.fRotation) vNegOffset = -vOffset vOffset += vol.vCenter vNegOffset += vol.vCenter vVertices[i*2 ] = vOffset + vUProj vVertices[i*2+1 ] = vOffset - vUProj vVertices[i*2+iSubdivisions ] = vNegOffset + vUProj vVertices[i*2+iSubdivisions+1] = vNegOffset - vUProj ENDREPEAT vTopVertexCenter = vol.vCenter + vUProj vBottomVertexCenter = vol.vCenter - vUProj // Iterate through pie slices and draw wireframe. IF bDrawWire REPEAT iSubdivisions i vTopVertexCur = vVertices[i*2] vBottomVertexCur = vVertices[i*2+1] IF i < iSubdivisions - 1 vTopVertexNext = vVertices[i*2+2] vBottomVertexNext = vVertices[i*2+3] ELSE vTopVertexNext = vVertices[0] vBottomVertexNext = vVertices[1] ENDIF // Draw wireframe for this pie piece. DRAW_DEBUG_LINE(vTopVertexCenter, vTopVertexCur, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vBottomVertexCenter, vBottomVertexCur, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vTopVertexCur, vBottomVertexCur, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vTopVertexCur, vTopVertexNext, 0, 255, 0, zvw_iAlphaWire) DRAW_DEBUG_LINE(vBottomVertexCur, vBottomVertexNext, 0, 255, 0, zvw_iAlphaWire) ENDREPEAT ENDIF // Iterate through pie slices and draw faces. // Do a separate loop so wireframe does not get culled out. IF bDrawFace REPEAT iSubdivisions i vTopVertexCur = vVertices[i*2] vBottomVertexCur = vVertices[i*2+1] IF i < iSubdivisions - 1 vTopVertexNext = vVertices[i*2+2] vBottomVertexNext = vVertices[i*2+3] ELSE vTopVertexNext = vVertices[0] vBottomVertexNext = vVertices[1] ENDIF // Draw faces for this pie piece. DRAW_DEBUG_POLY(vTopVertexCenter, vTopVertexCur, vTopVertexNext, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vBottomVertexCenter, vBottomVertexNext, vBottomVertexCur, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vTopVertexCur, vBottomVertexCur, vBottomVertexNext, 0, 0, 127, zvw_iAlphaFace) DRAW_DEBUG_POLY(vTopVertexCur, vBottomVertexNext, vTopVertexNext, 0, 0, 127, zvw_iAlphaFace) ENDREPEAT ENDIF ENDPROC // Debug draw for ellipsoid. /*PROC DRAW_ZVOLUME_ELD(zVolume vol, BOOL bDrawWire, BOOL bDrawFace) zTriangle curTriangle FLOAT fSin = SIN(vol.fRotation) FLOAT fCos = COS(vol.fRotation) INT i // Iterate through triangles to draw wireframe. IF bDrawWire REPEAT 512 i // Scale vertices. curTriangle.p1.x = zvw_Triangles[i].p1.x * vol.fWidth curTriangle.p1.y = zvw_Triangles[i].p1.y * vol.fDepth curTriangle.p1.z = zvw_Triangles[i].p1.z * vol.fHeight curTriangle.p2.x = zvw_Triangles[i].p2.x * vol.fWidth curTriangle.p2.y = zvw_Triangles[i].p2.y * vol.fDepth curTriangle.p2.z = zvw_Triangles[i].p2.z * vol.fHeight curTriangle.p3.x = zvw_Triangles[i].p3.x * vol.fWidth curTriangle.p3.y = zvw_Triangles[i].p3.y * vol.fDepth curTriangle.p3.z = zvw_Triangles[i].p3.z * vol.fHeight // Rotate vertices. curTriangle.p1 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p1, fSin, fCos) curTriangle.p2 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p2, fSin, fCos) curTriangle.p3 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p3, fSin, fCos) // Translate vertices. curTriangle.p1 += vol.vCenter curTriangle.p2 += vol.vCenter curTriangle.p3 += vol.vCenter // Draw wireframe. DRAW_DEBUG_LINE(curTriangle.p1, curTriangle.p2, 0, 255, 0, 210) DRAW_DEBUG_LINE(curTriangle.p2, curTriangle.p3, 0, 255, 0, 210) DRAW_DEBUG_LINE(curTriangle.p3, curTriangle.p1, 0, 255, 0, 210) ENDREPEAT ENDIF // Iterate through triangles to draw faces. // Do this in a separate loop so wireframe doesn't get culled out. IF bDrawFace REPEAT 512 i // Scale vertices. curTriangle.p1.x = zvw_Triangles[i].p1.x * vol.fWidth curTriangle.p1.y = zvw_Triangles[i].p1.y * vol.fDepth curTriangle.p1.z = zvw_Triangles[i].p1.z * vol.fHeight curTriangle.p2.x = zvw_Triangles[i].p2.x * vol.fWidth curTriangle.p2.y = zvw_Triangles[i].p2.y * vol.fDepth curTriangle.p2.z = zvw_Triangles[i].p2.z * vol.fHeight curTriangle.p3.x = zvw_Triangles[i].p3.x * vol.fWidth curTriangle.p3.y = zvw_Triangles[i].p3.y * vol.fDepth curTriangle.p3.z = zvw_Triangles[i].p3.z * vol.fHeight // Rotate vertices. curTriangle.p1 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p1, fSin, fCos) curTriangle.p2 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p2, fSin, fCos) curTriangle.p3 = ROTATE_VECTOR_ABOUT_Z_PRECOMPUTE(curTriangle.p3, fSin, fCos) // Translate vertices. curTriangle.p1 += vol.vCenter curTriangle.p2 += vol.vCenter curTriangle.p3 += vol.vCenter // Draw face. DRAW_DEBUG_POLY(curTriangle.p1, curTriangle.p2, curTriangle.p3, 0, 0, 127, 127) ENDREPEAT ENDIF ENDPROC */ // Draw the endpoints for an angled area. PROC DRAW_ANGAREA_ENDPOINTS() DRAW_DEBUG_SPHERE(zvw_vAngMidpt1, 0.3, 255, 0, 0) DRAW_DEBUG_SPHERE(zvw_vAngMidpt2, 0.3, 255, 0, 0) ENDPROC // Generate base vertices to use for ellipsoid drawing. /*PROC GENERATE_NSPHERE() VECTOR vOctahedron[6] VECTOR vMidpt1, vMidpt2, vMidpt3 INT iIteration, i, iTriangles, iTrianglesLast // Start with a uniform octahedron. vOctahedron[0] = << 0.0, 0.0, 0.5>> vOctahedron[1] = << 0.0, 0.0, -0.5>> vOctahedron[2] = << 0.0, -0.5, 0.0>> vOctahedron[3] = << 0.5, 0.0, 0.0>> vOctahedron[4] = << 0.0, 0.5, 0.0>> vOctahedron[5] = <<-0.5, 0.0, 0.0>> // Assign verts to the triangles. zvw_Triangles[0].p1 = vOctahedron[0] zvw_Triangles[0].p2 = vOctahedron[3] zvw_Triangles[0].p3 = vOctahedron[4] zvw_Triangles[1].p1 = vOctahedron[0] zvw_Triangles[1].p2 = vOctahedron[4] zvw_Triangles[1].p3 = vOctahedron[5] zvw_Triangles[2].p1 = vOctahedron[0] zvw_Triangles[2].p2 = vOctahedron[5] zvw_Triangles[2].p3 = vOctahedron[2] zvw_Triangles[3].p1 = vOctahedron[0] zvw_Triangles[3].p2 = vOctahedron[2] zvw_Triangles[3].p3 = vOctahedron[3] zvw_Triangles[4].p1 = vOctahedron[1] zvw_Triangles[4].p2 = vOctahedron[4] zvw_Triangles[4].p3 = vOctahedron[3] zvw_Triangles[5].p1 = vOctahedron[1] zvw_Triangles[5].p2 = vOctahedron[5] zvw_Triangles[5].p3 = vOctahedron[4] zvw_Triangles[6].p1 = vOctahedron[1] zvw_Triangles[6].p2 = vOctahedron[2] zvw_Triangles[6].p3 = vOctahedron[5] zvw_Triangles[7].p1 = vOctahedron[1] zvw_Triangles[7].p2 = vOctahedron[3] zvw_Triangles[7].p3 = vOctahedron[2] iTriangles = 8 // Perform three additional subdivisions. REPEAT 3 iIteration iTrianglesLast = iTriangles // Iterate through our current triangles. REPEAT iTrianglesLast i // Generate midpoints along edges and place them on the sphere's surface. vMidpt1 = (zvw_Triangles[i].p1 + zvw_Triangles[i].p2) / 2.0 vMidpt2 = (zvw_Triangles[i].p2 + zvw_Triangles[i].p3) / 2.0 vMidpt3 = (zvw_Triangles[i].p3 + zvw_Triangles[i].p1) / 2.0 vMidpt1 = GET_VECTOR_OF_LENGTH(vMidpt1, 0.5) vMidpt2 = GET_VECTOR_OF_LENGTH(vMidpt2, 0.5) vMidpt3 = GET_VECTOR_OF_LENGTH(vMidpt3, 0.5) // Assign verts to triangles. zvw_Triangles[iTriangles].p1 = zvw_Triangles[i].p1 zvw_Triangles[iTriangles].p2 = vMidpt1 zvw_Triangles[iTriangles].p3 = vMidpt3 ++iTriangles zvw_Triangles[iTriangles].p1 = vMidpt1 zvw_Triangles[iTriangles].p2 = zvw_Triangles[i].p2 zvw_Triangles[iTriangles].p3 = vMidpt2 ++iTriangles zvw_Triangles[iTriangles].p1 = vMidpt2 zvw_Triangles[iTriangles].p2 = zvw_Triangles[i].p3 zvw_Triangles[iTriangles].p3 = vMidpt3 ++iTriangles zvw_Triangles[i].p1 = vMidpt1 zvw_Triangles[i].p2 = vMidpt2 zvw_Triangles[i].p3 = vMidpt3 ENDREPEAT ENDREPEAT ENDPROC */ // Set up the widgets for editing volumes. PROC INIT_ZVOLUME_WIDGETS() IF zvw_bInit EXIT ENDIF zvw_bInit = TRUE zvw_fPosX = 0.0 zvw_fPosY = 0.0 zvw_fPosZ = 0.0 zvw_fDimX = 5.0 zvw_fDimY = 5.0 zvw_fDimZ = 4.0 zvw_fRotZ = 0.0 zvw_bPosSnapPlr = FALSE zvw_bRotSnapPlr = FALSE zvw_bPosSnapCam = FALSE zvw_bRotSnapCam = FALSE zvw_bPosSnapOrg = FALSE zvw_bRotSnapOrg = FALSE zvw_bDefaultDim = FALSE zvw_bDrawMaster = FALSE zvw_bDrawAsRec = TRUE zvw_bDrawAsCyl = FALSE zvw_bDrawAsEld = FALSE zvw_iSubdiv = 20 zvw_bDrawWire = TRUE zvw_iAlphaWire = 210 zvw_bDrawFace = TRUE zvw_iAlphaFace = 127 zvw_bDoCollision = FALSE zvw_bVolCheckPlr = FALSE zvw_bVolCheckCam = FALSE zvw_iMode = 0 zvw_Volume.vCenter.x = zvw_fPosX zvw_Volume.vCenter.y = zvw_fPosY zvw_Volume.vCenter.z = zvw_fPosZ zvw_Volume.fWidth = zvw_fDimX zvw_Volume.fDepth = zvw_fDimY zvw_Volume.fHeight = zvw_fDimZ zvw_Volume.fRotation = zvw_fRotZ zvw_zVolumeWidgets = START_WIDGET_GROUP("Z-Aligned Volumes") zvw_posDimGroup = START_WIDGET_GROUP("Position and Dimensions") ADD_WIDGET_FLOAT_SLIDER("Position x" , zvw_fPosX, -3300.0, 4300.0, 100.0) ADD_WIDGET_FLOAT_SLIDER("Position y" , zvw_fPosY, -3800.0, 4200.0, 100.0) ADD_WIDGET_FLOAT_SLIDER("Position z" , zvw_fPosZ, -200.0, 600.0, 15.0) ADD_WIDGET_FLOAT_SLIDER("Width (x)" , zvw_fDimX, 0.0, 1000.0, 10.0) ADD_WIDGET_FLOAT_SLIDER("Depth (y)" , zvw_fDimY, 0.0, 1000.0, 10.0) ADD_WIDGET_FLOAT_SLIDER("Height (z)" , zvw_fDimZ, 0.0, 600.0, 6.0) ADD_WIDGET_FLOAT_SLIDER("Rotation (z)", zvw_fRotZ, 0.0, 360.0, 3.6) ADD_WIDGET_BOOL("Snap position to player", zvw_bPosSnapPlr) ADD_WIDGET_BOOL("Snap rotation to player", zvw_bRotSnapPlr) ADD_WIDGET_BOOL("Snap position to camera", zvw_bPosSnapCam) ADD_WIDGET_BOOL("Snap rotation to camera", zvw_bRotSnapCam) ADD_WIDGET_BOOL("Snap position to origin", zvw_bPosSnapOrg) ADD_WIDGET_BOOL("Snap rotation to origin", zvw_bRotSnapOrg) ADD_WIDGET_BOOL("Reset to default dimensions", zvw_bDefaultDim) STOP_WIDGET_GROUP() zvw_renderingGroup = START_WIDGET_GROUP("Rendering") ADD_WIDGET_BOOL("Draw (master)" , zvw_bDrawMaster) ADD_WIDGET_BOOL("Render as rectangular prism" , zvw_bDrawAsRec) ADD_WIDGET_BOOL("Render as elliptic cylinder (not supported)" , zvw_bDrawAsCyl) ADD_WIDGET_BOOL("Render as elliptoid (not supported)" , zvw_bDrawAsEld) ADD_WIDGET_INT_SLIDER("Subdivisions (cyl)", zvw_iSubdiv, 4, iMAX_ZVC_VERTS / 2, 2) ADD_WIDGET_BOOL("Draw wireframe", zvw_bDrawWire) ADD_WIDGET_INT_SLIDER("Wireframe alpha", zvw_iAlphaWire, 0, 255, 2) ADD_WIDGET_BOOL("Draw faces", zvw_bDrawFace) ADD_WIDGET_INT_SLIDER("Face alpha", zvw_iAlphaFace, 0, 255, 2) STOP_WIDGET_GROUP() zvw_collisionGroup = START_WIDGET_GROUP("Collision Checks") ADD_WIDGET_BOOL("Peform collision checks", zvw_bDoCollision) ADD_WIDGET_BOOL("Player in volume", zvw_bVolCheckPlr) ADD_WIDGET_BOOL("Camera in volume", zvw_bVolCheckCam) STOP_WIDGET_GROUP() zvw_angledAreaGroup = START_WIDGET_GROUP("Angled Area") ADD_WIDGET_FLOAT_READ_ONLY("Point 1 x", zvw_fAngMidpt1x) ADD_WIDGET_FLOAT_READ_ONLY("Point 1 y", zvw_fAngMidpt1y) ADD_WIDGET_FLOAT_READ_ONLY("Point 1 z", zvw_fAngMidpt1z) ADD_WIDGET_FLOAT_READ_ONLY("Point 2 x", zvw_fAngMidpt2x) ADD_WIDGET_FLOAT_READ_ONLY("Point 2 y", zvw_fAngMidpt2y) ADD_WIDGET_FLOAT_READ_ONLY("Point 2 z", zvw_fAngMidpt2z) ADD_WIDGET_FLOAT_READ_ONLY("Width", zvw_fAngWidth) STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() // Generate base triangles for ellipsoids. //GENERATE_NSPHERE() ENDPROC // Use to destroy widgets. PROC CLEANUP_ZVOLUME_WIDGETS() IF DOES_WIDGET_GROUP_EXIST(zvw_angledAreaGroup) DELETE_WIDGET_GROUP(zvw_angledAreaGroup) ENDIF IF DOES_WIDGET_GROUP_EXIST(zvw_collisionGroup) DELETE_WIDGET_GROUP(zvw_collisionGroup) ENDIF IF DOES_WIDGET_GROUP_EXIST(zvw_renderingGroup) DELETE_WIDGET_GROUP(zvw_renderingGroup) ENDIF IF DOES_WIDGET_GROUP_EXIST(zvw_posDimGroup) DELETE_WIDGET_GROUP(zvw_posDimGroup) ENDIF IF DOES_WIDGET_GROUP_EXIST(zvw_zVolumeWidgets) DELETE_WIDGET_GROUP(zvw_zVolumeWidgets) ENDIF ENDPROC // Call once per frame so widgets work. PROC UPDATE_ZVOLUME_WIDGETS() VECTOR vPlayerPos VECTOR vCameraPos VECTOR vCameraRot FLOAT fPlayerHeading CAMERA_INDEX curCam // Perform one-time init. IF NOT zvw_bInit INIT_ZVOLUME_WIDGETS() ENDIF IF NOT IS_PED_INJURED(PLAYER_PED_ID()) vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) fPlayerHeading = GET_ENTITY_HEADING(PLAYER_PED_ID()) ENDIF curCam = GET_RENDERING_CAM() IF DOES_CAM_EXIST(curCam) vCameraPos = GET_CAM_COORD(curCam) vCameraRot = GET_CAM_ROT(curCam) ELSE vCameraPos = GET_GAMEPLAY_CAM_COORD() vCameraRot = GET_GAMEPLAY_CAM_ROT() ENDIF // Snap to player position. IF zvw_bPosSnapPlr zvw_fPosX = vPlayerPos.x zvw_fPosY = vPlayerPos.y zvw_fPosZ = vPlayerPos.z zvw_bPosSnapPlr = FALSE ENDIF // Snap to player rotation. IF zvw_bRotSnapPlr zvw_fRotZ = fPlayerHeading zvw_bRotSnapPlr = FALSE ENDIF // Snap to camera position. IF zvw_bPosSnapCam zvw_fPosX = vCameraPos.x zvw_fPosY = vCameraPos.y zvw_fPosZ = vCameraPos.z zvw_bPosSnapCam = FALSE ENDIF // Snap to camera rotation. IF zvw_bRotSnapCam zvw_fRotZ = vCameraRot.z zvw_bRotSnapCam = FALSE ENDIF // Snap to origin. IF zvw_bPosSnapOrg zvw_fPosX = 0.0 zvw_fPosY = 0.0 zvw_fPosZ = 0.0 zvw_bPosSnapOrg = FALSE ENDIF // Zero out rotation. IF zvw_bRotSnapOrg zvw_fRotZ = 0.0 zvw_bRotSnapOrg = FALSE ENDIF // Back to default dimensions. IF zvw_bDefaultDim zvw_fDimX = 5.0 zvw_fDimY = 5.0 zvw_fDimZ = 4.0 zvw_bDefaultDim = FALSE ENDIF // Switch to rectangular prism mode. IF zvw_bDrawAsRec IF zvw_iMode <> 0 zvw_iMode = 0 zvw_bDrawAsCyl = FALSE zvw_bDrawAsEld = FALSE ENDIF ENDIF // Switch to elliptic cylinder mode. IF zvw_bDrawAsCyl IF zvw_iMode <> 1 zvw_iMode = 1 zvw_bDrawAsRec = FALSE zvw_bDrawAsEld = FALSE ENDIF ENDIF // Switch to elliptoid mode. IF zvw_bDrawAsEld zvw_bDrawAsEld = FALSE IF zvw_iMode <> 2 zvw_iMode = 2 zvw_bDrawAsRec = FALSE zvw_bDrawAsCyl = FALSE ENDIF ENDIF // Make sure one mode is selected. IF NOT zvw_bDrawAsRec AND NOT zvw_bDrawAsCyl AND NOT zvw_bDrawAsEld IF zvw_iMode = 0 zvw_bDrawAsRec = TRUE ELIF zvw_iMode = 1 zvw_bDrawAsCyl = TRUE ELSE zvw_bDrawAsEld = TRUE ENDIF ENDIF // Clamp subdivisions to an even number. IF IS_BIT_SET(zvw_iSubdiv, 0) zvw_iSubdiv = IMAX(zvw_iSubdiv - 1, 4) ENDIF // Update internal volume. zvw_Volume.vCenter.x = zvw_fPosX zvw_Volume.vCenter.y = zvw_fPosY zvw_Volume.vCenter.z = zvw_fPosZ zvw_Volume.fWidth = zvw_fDimX zvw_Volume.fDepth = zvw_fDimY zvw_Volume.fHeight = zvw_fDimZ zvw_Volume.fRotation = zvw_fRotZ // Update angled area stats. IF zvw_bDrawAsRec GET_ANGLED_AREA_FROM_ZVOLUME(zvw_Volume, zvw_vAngMidpt1, zvw_vAngMidpt2, zvw_fAngWidth) zvw_fAngMidpt1x = zvw_vAngMidpt1.x zvw_fAngMidpt1y = zvw_vAngMidpt1.y zvw_fAngMidpt1z = zvw_vAngMidpt1.z zvw_fAngMidpt2x = zvw_vAngMidpt2.x zvw_fAngMidpt2y = zvw_vAngMidpt2.y zvw_fAngMidpt2z = zvw_vAngMidpt2.z ELSE zvw_vAngMidpt1 = <<0.0,0.0,0.0>> zvw_vAngMidpt2 = <<0.0,0.0,0.0>> zvw_fAngMidpt1x = 0.0 zvw_fAngMidpt1y = 0.0 zvw_fAngMidpt1z = 0.0 zvw_fAngMidpt2x = 0.0 zvw_fAngMidpt2y = 0.0 zvw_fAngMidpt2z = 0.0 zvw_fAngWidth = 0.0 ENDIF // Perform collision checks. IF zvw_bDoCollision IF zvw_bDrawAsRec zvw_bVolCheckPlr = IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), zvw_vAngMidpt1, zvw_vAngMidpt2, zvw_fAngWidth, TRUE, FALSE) zvw_bVolCheckCam = IS_POINT_IN_ANGLED_AREA(vCameraPos, zvw_vAngMidpt1, zvw_vAngMidpt2, zvw_fAngWidth, FALSE, FALSE) // ELIF zvw_bDrawAsCyl // zvw_bVolCheckPlr = IS_ENTITY_IN_CYLINDER(PLAYER_PED_ID(), GET_ZVOLUME_BOTTOM(zvw_Volume), zvw_Volume.fWidth, zvw_Volume.fDepth, zvw_Volume.fHeight, zvw_Volume.fRotation, TRUE) // zvw_bVolCheckCam = IS_POINT_IN_CYLINDER(vCameraPos, GET_ZVOLUME_BOTTOM(zvw_Volume), zvw_Volume.fWidth, zvw_Volume.fDepth, zvw_Volume.fHeight, zvw_Volume.fRotation, TRUE) ELSE zvw_bVolCheckPlr = FALSE zvw_bVolCheckCam = FALSE // zvw_bVolCheckPlr = IS_ENTITY_IN_ELLIPSOID(PLAYER_PED_ID(), zvw_Volume.vCenter, zvw_Volume.fWidth, zvw_Volume.fDepth, zvw_Volume.fHeight, zvw_Volume.fRotation) // zvw_bVolCheckCam = IS_POINT_IN_ELLIPSOID(vCameraPos, zvw_Volume.vCenter, zvw_Volume.fWidth, zvw_Volume.fDepth, zvw_Volume.fHeight, zvw_Volume.fRotation) ENDIF ELSE zvw_bVolCheckPlr = FALSE zvw_bVolCheckCam = FALSE ENDIF // Check the master draw switch. IF NOT zvw_bDrawMaster EXIT ENDIF // Perform draw. IF zvw_bDrawAsRec DRAW_ANGAREA_ENDPOINTS() DRAW_ZVOLUME_REC(zvw_Volume, zvw_bDrawWire, zvw_bDrawFace) ELIF zvw_bDrawAsCyl DRAW_ZVOLUME_CYL(zvw_Volume, zvw_bDrawWire, zvw_bDrawFace, zvw_iSubdiv) ELSE //DRAW_ZVOLUME_ELD(zvw_Volume, zvw_bDrawWire, zvw_bDrawFace) ENDIF ENDPROC #ENDIF // IS_DEBUG_BUILD