// Functions only used when setting up an RC mission USING "rage_builtins.sch" USING "globals.sch" USING "RC_Helper_Functions.sch" CONST_INT TEST_POLY_MAX_VERTS 15 STRUCT TEST_POLY // Poly points VECTOR v[TEST_POLY_MAX_VERTS] INT iVertCount // Bounding sphere VECTOR vCentre FLOAT fRadius BOOL bIsOpen ENDSTRUCT #IF IS_DEBUG_BUILD USING "shared_debug.sch" #ENDIF //#IF IS_DEBUG_BUILD // WIDGET_GROUP_ID m_RCAreaWidgetGroup // VECTOR vDebugMousePosition // VECTOR vDebugPolyPoints[TEST_POLY_MAX_VERTS] // BOOL bResetPoint[TEST_POLY_MAX_VERTS] // BOOL bEditPoint[TEST_POLY_MAX_VERTS] // BOOL bRecalculateDebugPoly = FALSE // BOOL bShowDebugPolyPoints = TRUE // BOOL bShowDebugPoly = FALSE // BOOL bPrintDebugPoly = FALSE // INT iActivePoint = -1 // TEST_POLY m_DebugPoly //#ENDIF /// PURPOSE: /// Check if a poly is valid - Needs to have at least 3 points for this to be the case. /// PARAMS: /// poly - the poly to be setup FUNC BOOL IS_TEST_POLY_VALID(TEST_POLY& poly) RETURN (poly.iVertCount >= 3) ENDFUNC /// PURPOSE: /// Resets a polygon to have no vertices, so user can add some /// PARAMS: /// poly - the poly to be setup PROC OPEN_TEST_POLY(TEST_POLY& poly) IF poly.bIsOpen SCRIPT_ASSERT("OPEN_TEST_POLY() - Trying to open poly for setup, when it is already open") ENDIF poly.iVertCount = 0 poly.vCentre = << 0,0,0 >> poly.fRadius = 0.0 poly.bIsOpen = TRUE ENDPROC /// PURPOSE: /// Adds a vertex to a polygon, needs to be called at least 3 times for a polygon to be usable. /// Vertices can be added clockwise or anti-clockwise, but must be added in order. /// Poly must be opened with OPEN_TEST_POLY() before adding verts, and closed with CLOSE_TEST_POLY() after. /// PARAMS: /// poly - the poly to be added to /// vert - the vertex to add PROC ADD_TEST_POLY_VERT(TEST_POLY& poly, VECTOR vert) IF poly.bIsOpen = FALSE SCRIPT_ASSERT("ADD_TEST_POLY_VERT() - Trying to add vert to poly when it is not open") ENDIF IF poly.iVertCount >= TEST_POLY_MAX_VERTS SCRIPT_ASSERT("Tried to add too many verts to a test poly.") ENDIF poly.v[poly.iVertCount] = vert poly.iVertCount++ ENDPROC /// PURPOSE: /// Finishes the setup process for a poly, and calculates a bounding sphere for it /// PARAMS: /// poly - the poly to be finalised PROC CLOSE_TEST_POLY(TEST_POLY& poly) IF poly.bIsOpen = FALSE SCRIPT_ASSERT("CLOSE_TEST_POLY() - Trying to close poly when it is not open") ENDIF IF poly.iVertCount < 3 SCRIPT_ASSERT("CLOSE_TEST_POLY() - Trying to close poly with less than 3 vertices") ENDIF // Find bounding sphere of poly INT i REPEAT poly.iVertCount i poly.vCentre += poly.v[i] ENDREPEAT poly.vCentre /= TO_FLOAT(i) REPEAT poly.iVertCount i FLOAT fDist = VDIST2(poly.vCentre, poly.v[i]) IF fDist > poly.fRadius poly.fRadius = fDist ENDIF ENDREPEAT poly.fRadius = SQRT(poly.fRadius) poly.bIsOpen = FALSE ENDPROC /// PURPOSE: /// This is useful for debugging the shape of your poly. /// It draws a marker on every vertex of the poly. You will need to call it every frame. /// PARAMS: /// poly - the poly to draw /// r, g, b - red/green/blue values (max 255) /// a - alpha value (max 255) PROC DISPLAY_POLY(TEST_POLY& poly, INT r = 255, INT g = 100, INT b = 100, INT a = 100) INT i REPEAT poly.iVertCount i DRAW_MARKER(MARKER_CYLINDER, poly.v[i], <<1,0,0>>, <<0,0,0>>, <<1,1,10>>, r, g, b, a) ENDREPEAT ENDPROC /// PURPOSE: /// This is useful for debugging the shape of your poly. /// It draws a marker on every vertex of the poly. You will need to call it every frame. /// It draws each vertex a different colour so you can check none of the vertices are out of order (it colours the first vertex blue and the last one red, with gradient in between) /// PARAMS: /// poly - the poly to draw /// r, g, b - red/green/blue values (max 255) /// a - alpha value (max 255) PROC DISPLAY_POLY2(TEST_POLY& poly, INT a = 100) INT i REPEAT poly.iVertCount i DRAW_MARKER(MARKER_CYLINDER, poly.v[i], <<1,0,0>>, <<0,0,0>>, <<1,1,10>>, (255 * i) / poly.iVertCount, 0, 255 - ((255*i) / poly.iVertCount), a) ENDREPEAT ENDPROC /// PURPOSE: /// Checks if the point is enclosed within the polygon when looking down from above (the test is only 2D and is in the X,Y plane). Returns true if it is. /// PARAMS: /// poly - the poly to test /// vert - the point to test (if this point is inside the poly, returns true) FUNC BOOL IS_POINT_IN_POLY_2D(TEST_POLY& poly, VECTOR point) // Check poly has enough sides IF poly.iVertCount < 3 SCRIPT_ASSERT("IS_POINT_IN_POLY_2D: A poly must have at least 3 vertices before doing a point test") ENDIF BOOL bAreNodesOdd = FALSE INT i = 0 INT j = poly.iVertCount - 1 // j is always the point that comes before i (usually i - 1). - On the first loop, i is 0, so j is poly.iVertCount - 1. // Loop through each edge of poly WHILE (i < poly.iVertCount) // If an odd number of edges are to the left of the point, the point is inside the poly, otherwise it is outside IF poly.v[i].y < point.y AND poly.v[j].y >= point.y OR poly.v[j].y < point.y AND poly.v[i].y >= point.y IF poly.v[i].x + (point.y-poly.v[i].y) / (poly.v[j].y-poly.v[i].y) * (poly.v[j].x-poly.v[i].x) < point.x bAreNodesOdd = NOT bAreNodesOdd ENDIF ENDIF j = i i++ ENDWHILE RETURN bAreNodesOdd ENDFUNC /// PURPOSE: /// Makes a copy of a polygon, expanding each vertex outwards by the distance specified. /// This is useful for warning the player they have left an area, then generating a larger, encapsulating area to fail the player for having gone too far from that original area. /// Please note - if a coder saw this function they would cry. It is very inefficient. Only call this once at the start of your mission. DEFINITELY NOT EVERY FRAME!! /// and be careful in the case of concave polygons, who knows what could happen /// PARAMS: /// in - the poly to copy /// out - where to copy to /// fMargin - how much further out each vertex should be (negative numbers here won't produce a smaller poly, it will always be bigger) PROC COPY_EXPANDED_POLY(TEST_POLY& out, TEST_POLY& in, FLOAT fMargin) // Check poly has enough sides IF in.iVertCount < 3 SCRIPT_ASSERT("EXPAND_POLY: A poly must have at least 3 vertices to be valid") ENDIF INT i = in.iVertCount - 1 INT j = 0 INT k = 1 VECTOR edge0 VECTOR edge1 VECTOR normal out.iVertCount = in.iVertCount // Loop through each edge of poly WHILE (j < in.iVertCount) edge0 = in.v[j] - in.v[i] edge1 = in.v[k] - in.v[j] edge0 /= SQRT((edge0.x*edge0.x) + (edge0.y*edge0.y)) edge1 /= SQRT((edge1.x*edge1.x) + (edge1.y*edge1.y)) normal = edge0 - edge1 normal /= SQRT((normal.x*normal.x) + (normal.y*normal.y)) IF IS_POINT_IN_POLY_2D(in, in.v[j] + normal) normal = -normal ENDIF out.v[j] = in.v[j] + (normal * fMargin) i = j j++ k = (k + 1) % in.iVertCount ENDWHILE ENDPROC /*PROC COPY_SCALED_POLY(TEST_POLY& out, TEST_POLY& in, FLOAT fScale = 1.0) IF in.iVertCount >= TEST_POLY_MAX_VERTS SCRIPT_ASSERT("COPY_SCALED_POLY: poly has too many vertices") ENDIF INT i IF fScale = 1.0 // Copy all verts REPEAT in.iVertCount i out.v[i] += in.v[i] ENDREPEAT out.iVertCount = in.iVertCount ELSE // Find centre VECTOR vCentre = <<0, 0, 0>> REPEAT in.iVertCount i vCentre += in.v[i] ENDREPEAT vCentre.x /= TO_FLOAT(in.iVertCount) vCentre.y /= TO_FLOAT(in.iVertCount) // Scale each vertex from the centre point REPEAT in.iVertCount i out.v[i] = vCentre + ((in.v[i] - vCentre) * fScale) ENDREPEAT out.iVertCount = in.iVertCount ENDIF ENDPROC*/ //---------------------- // DEBUG FUNCTIONS //---------------------- //#IF IS_DEBUG_BUILD // /////------------------------------------------------------------------------------ ///// FUNCTION: ///// SETUP_TEST_POLY_WIDGETS() ///// PURPOSE: ///// SETS UP WIDGET SO WE CAN DISPLAY TEST POLYS /////------------------------------------------------------------------------------ //PROC SETUP_TEST_POLY_WIDGETS() // INT i // TEXT_LABEL sLabel // // iActivePoint = -1 // m_RCAreaWidgetGroup = START_WIDGET_GROUP("Test Poly Editor") // // ADD_WIDGET_BOOL("Show Points", bShowDebugPolyPoints) // ADD_WIDGET_BOOL("Show Final Polygon", bShowDebugPoly) // ADD_WIDGET_BOOL("Recalculate Polygon", bRecalculateDebugPoly) // // START_WIDGET_GROUP("Points") // REPEAT COUNT_OF(vDebugPolyPoints) i // sLabel = "Point" // sLabel += i // START_WIDGET_GROUP(sLabel) // ADD_WIDGET_BOOL("Edit Point", bEditPoint[i]) // ADD_WIDGET_VECTOR_SLIDER("Position", vDebugPolyPoints[i], -5000.0, 5000.0, 10.0) // ADD_WIDGET_BOOL("Reset Point", bResetPoint[i]) // STOP_WIDGET_GROUP() // ENDREPEAT // STOP_WIDGET_GROUP() // // ADD_WIDGET_BOOL("Dump Polygon To Debug", bPrintDebugPoly) // ADD_WIDGET_INT_READ_ONLY("Current Point", iActivePoint) // STOP_WIDGET_GROUP() //ENDPROC // /////------------------------------------------------------------------------------ ///// FUNCTION: ///// SETUP_TEST_POLY_WIDGETS() ///// PURPOSE: ///// SETS UP WIDGET SO WE CAN DISPLAY TEST POLYS /////------------------------------------------------------------------------------ //PROC COPY_TO_DEBUG_TEST_POLY(TEST_POLY& src) // INT i // OPEN_TEST_POLY(m_DebugPoly) // REPEAT COUNT_OF(src.v) i // IF NOT IS_VECTOR_ZERO(src.v[i]) // ADD_TEST_POLY_VERT(m_DebugPoly, src.v[i]) // ENDIF // ENDREPEAT // CLOSE_TEST_POLY(m_DebugPoly) //ENDPROC // /////------------------------------------------------------------------------------ ///// FUNCTION: ///// UPDATE_TEST_POLY_WIDGETS() ///// PURPOSE: ///// CALL THIS EVERY FRAME SO THE WIDGETS WORK /////------------------------------------------------------------------------------ //PROC UPDATE_TEST_POLY_WIDGETS() // INT i // INT i2 // INT iLastPoint // VECTOR tmp // FLOAT sx, sy // // /* handles selecting points in real time // // */ // // i = 0 // REPEAT COUNT_OF(vDebugPolyPoints) i // IF (bEditPoint[i]) // iActivePoint = i // bEditPoint[i] = FALSE // ENDIF // ENDREPEAT // // // right button cycles active point // IF IS_MOUSE_BUTTON_JUST_PRESSED(MB_RIGHT_BTN) // iActivePoint ++ // IF (iActivePoint >= COUNT_OF(vDebugPolyPoints)) // iActivePoint = 0 // ENDIF // // IF IS_VECTOR_ZERO(vDebugPolyPoints[iActivePoint]) // iActivePoint = 0 // ENDIF // ENDIF // // // // handles dragging active point in real time // IF (iActivePoint <> -1) // IF IS_MOUSE_BUTTON_JUST_PRESSED(MB_LEFT_BTN) // // IF IS_MOUSE_BUTTON_PRESSED(MB_RIGHT_BTN) AND NOT IS_VECTOR_ZERO(vDebugMousePosition) // vDebugPolyPoints[iActivePoint] = vDebugMousePosition // ELSE // i = 0 // i2 = -1 // // // check to see if we are near any points // REPEAT COUNT_OF(vDebugPolyPoints) i // IF (GET_DISTANCE_BETWEEN_COORDS(vDebugMousePosition, vDebugPolyPoints[i], FALSE) < 4.0) // i2 = i // ENDIF // ENDREPEAT // // // if so make that point the active point - else create a new point // IF (i2 <> -1) // iActivePoint = i2 // ELSE // i = 0 // REPEAT COUNT_OF(vDebugPolyPoints) i // IF IS_VECTOR_ZERO(vDebugPolyPoints[i]) AND NOT IS_VECTOR_ZERO(vDebugMousePosition) // vDebugPolyPoints[i] = vDebugMousePosition // iActivePoint = i // i = 999999 // ENDIF // ENDREPEAT // ENDIF // ENDIF // ELIF IS_MOUSE_BUTTON_PRESSED(MB_LEFT_BTN) // IF IS_MOUSE_BUTTON_PRESSED(MB_RIGHT_BTN) AND NOT IS_VECTOR_ZERO(vDebugMousePosition) // vDebugPolyPoints[iActivePoint] = vDebugMousePosition // ENDIF // ENDIF // ENDIF // // // // // handles rendering debug poly // IF (bShowDebugPolyPoints) // SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) // // // renders points of poly while editing // i = 0 // REPEAT COUNT_OF(vDebugPolyPoints) i // i2 = i + 1 // IF (i2 >= (COUNT_OF(vDebugPolyPoints) - 1)) // i2 = 0 // ENDIF // // // draw a sphere at the point and a line going up just incase points are buried. // tmp = vDebugPolyPoints[i] + <<0, 0, 10.0>> // // IF (iActivePoint = i) // DRAW_DEBUG_SPHERE(vDebugPolyPoints[i], 1.0, 0, 255, 0, 255) // ELSE // DRAW_DEBUG_SPHERE(vDebugPolyPoints[i], 1.0) // ENDIF // // DRAW_DEBUG_LINE(vDebugPolyPoints[i], tmp) // DRAW_DEBUG_LINE(vDebugPolyPoints[i], vDebugPolyPoints[i2]) // // // show point number // IF NOT IS_VECTOR_ZERO(vDebugPolyPoints[i]) // IF GET_SCREEN_COORD_FROM_WORLD_COORD(vDebugPolyPoints[i], sx, sy) // SET_TEXT_SCALE(0.25, 0.25) // DISPLAY_TEXT_WITH_NUMBER(sx, sy, "NUMBER", i) // ENDIF // iLastPoint = i // ENDIF // // ENDREPEAT // // DRAW_DEBUG_LINE(vDebugPolyPoints[0], vDebugPolyPoints[iLastPoint]) // ENDIF // // // // // handle resetting the poly points if the buttons are clicked // // force recalculate if poly point is clicked // i = 0 // REPEAT COUNT_OF(vDebugPolyPoints) i // IF (bResetPoint[i]) // bResetPoint[i] = FALSE // vDebugPolyPoints[i] = <<0, 0, 0>> // bRecalculateDebugPoly = TRUE // ENDIF // ENDREPEAT // // // recalculate the poly // IF (bRecalculateDebugPoly) // i = 0 // OPEN_TEST_POLY(m_DebugPoly) // REPEAT COUNT_OF(vDebugPolyPoints) i // IF NOT IS_VECTOR_ZERO(vDebugPolyPoints[i]) // ADD_TEST_POLY_VERT(m_DebugPoly, vDebugPolyPoints[i]) // ENDIF // ENDREPEAT // CLOSE_TEST_POLY(m_DebugPoly) // bRecalculateDebugPoly = FALSE // ENDIF // // // actually display the poly using sam's routine // IF IS_TEST_POLY_VALID(m_DebugPoly) AND (bShowDebugPoly) // DISPLAY_POLY2(m_DebugPoly) // ENDIF // // // handle writing debug poly to TTY // IF (bPrintDebugPoly) // bPrintDebugPoly = FALSE // // SAVE_NEWLINE_TO_DEBUG_FILE() // SAVE_STRING_TO_DEBUG_FILE("-------------- TEST POLY SCRIPT OUTPUT ---------------------") // SAVE_NEWLINE_TO_DEBUG_FILE() // // SAVE_STRING_TO_DEBUG_FILE("OPEN_TEST_POLY(m_DebugPoly)") // SAVE_NEWLINE_TO_DEBUG_FILE() // // REPEAT COUNT_OF(vDebugPolyPoints) i // IF NOT IS_VECTOR_ZERO(vDebugPolyPoints[i]) // SAVE_STRING_TO_DEBUG_FILE("ADD_TEST_POLY_VERT(m_DebugPoly, ") // SAVE_VECTOR_TO_DEBUG_FILE(vDebugPolyPoints[i]) // SAVE_STRING_TO_DEBUG_FILE(")") // SAVE_NEWLINE_TO_DEBUG_FILE() // ENDIF // ENDREPEAT // // SAVE_STRING_TO_DEBUG_FILE("CLOSE_TEST_POLY(m_DebugPoly)") // SAVE_NEWLINE_TO_DEBUG_FILE() // // SAVE_STRING_TO_DEBUG_FILE("-------------- END TEST POLY SCRIPT OUTPUT -----------------") // SAVE_NEWLINE_TO_DEBUG_FILE() // ENDIF // // // get mouse position and use that // vDebugMousePosition = GET_SCRIPT_MOUSE_POINTER_IN_WORLD_COORDS() //ENDPROC // /////------------------------------------------------------------------------------ ///// FUNCTION: ///// CLEANUP_TEST_POLY_WIDGETS() ///// PURPOSE: ///// TIDY UP THE TEST POLY WIDGETS /////------------------------------------------------------------------------------ //PROC CLEANUP_TEST_POLY_WIDGETS() // IF DOES_WIDGET_GROUP_EXIST(m_RCAreaWidgetGroup) // DELETE_WIDGET_GROUP(m_RCAreaWidgetGroup) // ENDIF //ENDPROC //#ENDIF