Advertisement
BloodknightStudios

fxguisnooper.cpp

Dec 23rd, 2014
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.14 KB | None | 0 0
  1. #include "sceneGraph/sceneGraph.h"
  2. #include "T3D/gamebase/gameConnection.h"
  3. #include "console/consoleTypes.h"
  4. #include "gui/3d/guiTSControl.h"
  5. #include "gui/core/guiControl.h"
  6. #include "renderInstance/renderPassManager.h"
  7. #include "gfx/gfxDevice.h"
  8.  
  9. #include "gfx/gfxDrawUtil.h"
  10.  
  11.  
  12. class fxGuiSnooper : public GuiTSCtrl
  13. {
  14. private:
  15.     typedef GuiTSCtrl Parent;
  16.  
  17.     Point3F             mRotateView;                    // View Rotation.
  18.     Point3F             mOffsetView;                    // Offset Distance.
  19.     F32                 mFov;                           // Field of View.
  20.     Point3F             mSweepAmplitude;                // Sweep Amplitude.
  21.     Point3F             mSweepTime;                     // Sweep Time.
  22.  
  23.     bool                mUseOverlayBitmap;              // Use Overlay Bitmap Flag.
  24.     bool                mUseOverlayColour;              // Use Overlay Colour Flag.
  25.     bool                mOverlayTile;                   // Overlay Tile Flag.
  26.     ColorF              mOverlayColor;                  // Filter Colour Vector.
  27.     bool                mOverlayRedMask;                // Overlay Red Mask Flag.
  28.     bool                mOverlayGreenMask;              // Overlay Green Mask Flag.
  29.     bool                mOverlayBlueMask;               // Overlay Blue Mask Flag.
  30.  
  31.     StringTableEntry    mObjectName;                    // Attached Object Name.
  32.     SceneObject*        mAttachedObject;                // Attached Object.
  33.  
  34.     U32                 mLastTimeStamp;                 // Last Time Stamp.
  35.     Point3F             mCurrentSweepMagnitude;         // Current Sweep Phase.
  36.     StringTableEntry    mOverlayBitmapName;             // Overlay Bitmap Name.
  37.     GFXTexHandle        mOverlayTextureHandle;          // Overlay Texture Handle.
  38.  
  39.     GFXStateBlockRef mSnooperClearSB;
  40.     GFXStateBlockRef mDzEnableSB;
  41.     GFXStateBlockRef mEcwSB;
  42.     GFXStateBlockRef mEcwResetSB;
  43.  
  44.     void renderWorld(const RectI & updateRect);
  45.     void onRender(Point2I offset, const RectI &updateRect);
  46.  
  47. public:
  48.     fxGuiSnooper();
  49.  
  50.     static void initPersistFields();
  51.     static void consoleInit();
  52.  
  53.     bool processCameraQuery(CameraQuery * query);
  54.  
  55.     void setViewObject(const char* ObjectName);
  56.     void setViewRotation(Point3F Rotation);
  57.     void setOverlayBitmap(const char *name);
  58.     void setOverlayColor(ColorF OverlayColor);
  59.     void setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask);
  60.  
  61.     bool onWake();
  62.     void onSleep();
  63.  
  64.     DECLARE_CONOBJECT(fxGuiSnooper);
  65. };
  66.  
  67. //------------------------------------------------------------------------------
  68.  
  69. IMPLEMENT_CONOBJECT(fxGuiSnooper);
  70.  
  71. //------------------------------------------------------------------------------
  72.  
  73.  
  74. fxGuiSnooper::fxGuiSnooper() :
  75. mRotateView(0,0,0),
  76. mOffsetView(0,0,0),
  77. mFov(60.0),
  78. mSweepAmplitude(0,0,60),
  79. mSweepTime(5000,5000,5000),
  80. mCurrentSweepMagnitude(0,0,0),
  81. mAttachedObject(NULL),
  82. mOverlayRedMask(true),
  83. mOverlayGreenMask(true),
  84. mOverlayBlueMask(true),
  85. mOverlayTile(false),
  86. mUseOverlayBitmap(false),
  87. mUseOverlayColour(false),
  88. mLastTimeStamp(Platform::getRealMilliseconds())
  89. {
  90.     // Create Empty Attached Object Name.
  91.     mObjectName = StringTable->insert("");
  92.  
  93.     // Create Empty Overlay Bitmap Name.
  94.     mOverlayBitmapName = StringTable->insert("");
  95.  
  96.     // Set Default Overlay Colour.
  97.     mOverlayColor.set(1, 1, 1, 0.5f);
  98. };
  99.  
  100. //------------------------------------------------------------------------------
  101.  
  102. void fxGuiSnooper::initPersistFields()
  103. {
  104.     // Initialise parents' persistent fields.
  105.     Parent::initPersistFields();
  106.  
  107.     // Add out own persistent fields.
  108.     addField( "ViewRotation", TypePoint3F, Offset( mRotateView, fxGuiSnooper ) );
  109.     addField( "ViewOffset", TypePoint3F, Offset( mOffsetView, fxGuiSnooper ) );
  110.     addField( "FOV", TypeF32, Offset( mFov, fxGuiSnooper ) );
  111.     addField( "SweepAmplitude", TypePoint3F, Offset( mSweepAmplitude, fxGuiSnooper ) );
  112.     addField( "SweepTime", TypePoint3F, Offset( mSweepTime, fxGuiSnooper ) );
  113.     addField( "AttachedObject", TypeString, Offset( mObjectName, fxGuiSnooper ) );
  114.     addField( "OverlayBitmap", TypeBool, Offset( mUseOverlayBitmap, fxGuiSnooper ) );
  115.     addField( "OverlayTile", TypeBool, Offset( mOverlayTile, fxGuiSnooper ) );
  116.     addField( "OverlayColour", TypeBool, Offset( mUseOverlayColour, fxGuiSnooper ) );
  117.     addField( "BitmapOverlay", TypeFilename, Offset(mOverlayBitmapName, fxGuiSnooper));
  118.     addField( "ColorOverlay", TypeColorF, Offset( mOverlayColor, fxGuiSnooper ) );
  119.     addField( "RedMask", TypeBool, Offset( mOverlayRedMask, fxGuiSnooper ) );
  120.     addField( "GreenMask", TypeBool, Offset( mOverlayGreenMask, fxGuiSnooper ) );
  121.     addField( "BlueMask", TypeBool, Offset( mOverlayBlueMask, fxGuiSnooper ) );
  122. }
  123.  
  124. //------------------------------------------------------------------------------
  125.  
  126. bool fxGuiSnooper::onWake()
  127. {
  128.     // Wake-up Parent.
  129.     if (!Parent::onWake()) return false;
  130.  
  131.     // Set Active.
  132.     setActive(true);
  133.  
  134.     // Have we an Attached Object Name?
  135.     if (mObjectName)
  136.     {
  137.         // Yes, so attach to it.
  138.         setViewObject(mObjectName);
  139.     }
  140.  
  141.     // Set Overlay Bitmap.
  142.     setOverlayBitmap(mOverlayBitmapName);
  143.  
  144.     // Return OK.
  145.     return true;
  146. }
  147.  
  148. //------------------------------------------------------------------------------
  149.  
  150. void fxGuiSnooper::onSleep()
  151. {
  152.     // Reset Overlay Texture Handle.
  153.     mOverlayTextureHandle = NULL;
  154.     // Call Parent.
  155.     Parent::onSleep();
  156. }
  157.  
  158. //------------------------------------------------------------------------------
  159.  
  160. void fxGuiSnooper::setViewRotation(Point3F Rotation)
  161. {
  162.     // Set the Rotation internally.
  163.     mRotateView = Rotation;
  164. }
  165.  
  166. //------------------------------------------------------------------------------
  167.  
  168. void fxGuiSnooper::setViewObject(const char* ObjectName)
  169. {
  170.     // Get Root Group.
  171.     SimGroup* SG = Sim::getRootGroup();
  172.  
  173.     // Interate Sim Group.
  174.     for (SimSetIterator itr(SG); *itr; ++itr)
  175.     {
  176.         // Is this our Type?
  177.         if ((*itr)->getTypeMask() & STATIC_COLLISION_MASK)
  178.         {
  179.             // Yes, so cast our Object.
  180.             SceneObject* SceneObj = static_cast<SceneObject*>(*itr);
  181.             // Check that it's a Server Object.
  182.             if (SceneObj->isServerObject())
  183.             {
  184.                 const char* getName;
  185.  
  186.                 getName = SceneObj->getName();
  187.  
  188.                 // Yes, so is this our Object?
  189.                 if (getName && dStrcmp(getName, ObjectName) == 0)
  190.                 {
  191.                     // Store Scene Object.
  192.                     mAttachedObject = SceneObj;
  193.  
  194.                     // Return OK.
  195.                     return;
  196.                 }
  197.             }
  198.         }
  199.     }
  200.  
  201.     // Reset Object.
  202.     mAttachedObject = NULL;
  203.  
  204. }
  205.  
  206. //------------------------------------------------------------------------------
  207.  
  208. void fxGuiSnooper::setOverlayBitmap(const char *name)
  209. {
  210.     // Set Overlay Bitmap Name.
  211.     mOverlayBitmapName = StringTable->insert(name);
  212.  
  213.     if (*mOverlayBitmapName)
  214.         // Yes, so get Texture Handle.
  215.         mOverlayTextureHandle.set( mOverlayBitmapName, &GFXDefaultGUIProfile, "" );
  216.     else
  217.         // No, so reset Texture Handle.
  218.         mOverlayTextureHandle = NULL;
  219.  
  220.     // Update.
  221.     setUpdate();
  222. }  
  223.  
  224. //------------------------------------------------------------------------------
  225.  
  226. void fxGuiSnooper::setOverlayColor(ColorF OverlayColor)
  227. {
  228.     // Set the Overlay Colour internally.
  229.     mOverlayColor = OverlayColor;
  230. }
  231.  
  232. //------------------------------------------------------------------------------
  233.  
  234. void fxGuiSnooper::setOverlayMask(bool RedMask, bool GreenMask, bool BlueMask)
  235. {
  236.     // Set the Overlay Masks internally.
  237.     mOverlayRedMask     = RedMask;
  238.     mOverlayGreenMask   = GreenMask;
  239.     mOverlayBlueMask    = BlueMask;
  240. }
  241.  
  242. //------------------------------------------------------------------------------
  243.  
  244. ConsoleMethod(fxGuiSnooper,setViewRotation,void,5,5,"Sets View Rotation.")
  245. {
  246.     Point3F     Rotation;
  247.  
  248.     // Fetch the fxGuiSnooper object.
  249.     fxGuiSnooper *Viewport = static_cast<fxGuiSnooper*>(object);
  250.  
  251.     // Fetch Rotation.
  252.     Rotation.set(   mDegToRad(dAtof(argv[2])),
  253.         mDegToRad(dAtof(argv[3])),
  254.         mDegToRad(dAtof(argv[4])));
  255.  
  256.     // Set Rotation.
  257.     Viewport->setViewRotation(Rotation);
  258. }
  259.  
  260. //------------------------------------------------------------------------------
  261.  
  262. ConsoleMethod(fxGuiSnooper,setViewObject,void,3,3,"Sets View to Object.")
  263. {
  264.     F32     Rotation;
  265.  
  266.     // Fetch the fxGuiSnooper object.
  267.     fxGuiSnooper *Viewport = static_cast<fxGuiSnooper*>(object);
  268.  
  269.     // Set the GuiFilter Filter Colour.
  270.     Viewport->setViewObject(argv[2]);
  271. }
  272.  
  273. //------------------------------------------------------------------------------
  274.  
  275. ConsoleMethod(fxGuiSnooper,setOverlayBitmap,void,3,3,"Sets Overlay Bitmap.")
  276. {
  277.     // Fetch the fxGuiSnooper object.
  278.     fxGuiSnooper *Viewport = static_cast<fxGuiSnooper*>(object);
  279.  
  280.     // Set Overlay Bitmap.
  281.     Viewport->setOverlayBitmap(argv[2]);
  282. }
  283.  
  284. //------------------------------------------------------------------------------
  285.  
  286. ConsoleMethod(fxGuiSnooper,setOverlayColor,void,5,6,"Sets Overlay Color.")
  287. {
  288.     F32     r,g,b,a;
  289.     ColorF  TempColor;
  290.  
  291.     // Fetch the fxGuiSnooper object.
  292.     fxGuiSnooper *Viewport = static_cast<fxGuiSnooper*>(object);
  293.  
  294.     // Convert RGB Ascii parms to float.
  295.     r = dAtof(argv[2]);
  296.     g = dAtof(argv[3]);
  297.     b = dAtof(argv[4]);
  298.  
  299.     // Did we get an alpha param?
  300.     if (argc == 6)
  301.         // Yep, so convert it.
  302.         a = dAtof(argv[5]);
  303.     else
  304.         // Nope, so default to 1.
  305.         a = 1;
  306.  
  307.     // Setup our temporary colour vector.
  308.     TempColor.set(r,g,b,a);
  309.  
  310.     // Set the fxGuiSnooper Overlay Colour.
  311.     Viewport->setOverlayColor(TempColor);
  312. }
  313.  
  314. //------------------------------------------------------------------------------
  315.  
  316. ConsoleMethod(fxGuiSnooper,setOverlayMask,void,5,5,"Sets Overlay Masks.")
  317. {
  318.     F32     r,g,b;
  319.  
  320.     // Fetch the fxGuiSnooper object.
  321.     fxGuiSnooper *Viewport = static_cast<fxGuiSnooper*>(object);
  322.  
  323.     // Convert RGB Ascii parms to float.
  324.     r = dAtof(argv[2]);
  325.     g = dAtof(argv[3]);
  326.     b = dAtof(argv[4]);
  327.  
  328.     // Set the fxGuiSnooper Masks.
  329.     Viewport->setOverlayMask(r,g,b);
  330. }
  331.  
  332. //------------------------------------------------------------------------------
  333.  
  334. static void cfxGuiBitmapSetOverlayBitmap(SimObject *obj, S32, const char **argv)
  335. {
  336.     // Fetch HUD Control.
  337.     fxGuiSnooper *ctrl = static_cast<fxGuiSnooper*>(obj);
  338.  
  339.     // Set Overlay Bitmap.
  340.     ctrl->setOverlayBitmap(argv[2]);
  341. }
  342.  
  343. //------------------------------------------------------------------------------
  344.  
  345. void fxGuiSnooper::consoleInit()
  346. {
  347.     Con::addCommand("fxGuiSnooper", "setOverlayBitmap",  cfxGuiBitmapSetOverlayBitmap, "fxGuiSnooper.setOverlayBitmap(Bitmap)", 3, 3);
  348. }
  349.  
  350. //------------------------------------------------------------------------------
  351.  
  352. void fxGuiSnooper::renderWorld(const RectI & updateRect)
  353. {
  354.     /* proj = FGX->getProjectionMatrix();
  355.  
  356.     myShaderConstBuffer->set(mModelViewProjSC, &proj);
  357.     myShaderConstBuffer->set(mOpacityMapSC, (S32) 0);
  358.     myShaderConstBuffer->set(mLightMapSC, (S32) 1);
  359.  
  360.     GFX->setShaderConstBuffer(myShaderConstBuffer);
  361.     */
  362.  
  363.     GFX->clear(GFXClearZBuffer, ColorI(0,0,0), 1.0f, 0);
  364.     /*
  365.     GFX->setZEnable(true);
  366.     GFX->setZWriteEnable(true);
  367.     GFX->setZFunc(GFXCmpLessEqual);
  368.     GFX->setCullMode(GFXCullNone);
  369.     */
  370.  
  371.     GFXStateBlockDesc snooperClear;
  372.     snooperClear.zEnable = true;
  373.     snooperClear.zWriteEnable = true;
  374.     snooperClear.zFunc = GFXCmpLessEqual;
  375.     snooperClear.cullMode = GFXCullNone;
  376.  
  377.     mSnooperClearSB = GFX->createStateBlock(snooperClear);
  378.  
  379.     GFXStateBlockDesc dzEnable;
  380.     dzEnable.zEnable = false;
  381.     mDzEnableSB = GFX->createStateBlock(dzEnable);
  382.  
  383.  
  384.     GFX->setStateBlock(mSnooperClearSB);
  385.     // Render Client Scene Graph.
  386.     gClientSceneGraph->renderScene(SPT_Diffuse);
  387.  
  388.     //GFX->setZEnable(false);
  389.  
  390.     GFX->setStateBlock(mDzEnableSB);
  391. }
  392.  
  393. //------------------------------------------------------------------------------
  394.  
  395. void fxGuiSnooper::onRender(Point2I offset, const RectI &updateRect)
  396. {
  397.  
  398.     // Declare StateBlocks
  399.  
  400.  
  401.     // Call Parent Render.
  402.     Parent::onRender(offset, updateRect);
  403.  
  404.     // Set Clipping Rectangle to GUI Bounds.
  405.     GFX->setClipRect(getBounds());
  406.  
  407.     // Do we have an attached Object?
  408.     if (!mAttachedObject)
  409.     {
  410.         // No, so signal to user this problem ...
  411.         ColorF ErrorColor(1,0,0);
  412.         GFX->getDrawUtil()->drawRectFill(updateRect, ErrorColor);
  413.         ErrorColor.set(1,1,1);
  414.         char buf[256];
  415.         dSprintf(buf, sizeof(buf), "*** Object not selected ***");
  416.         GFX->getDrawUtil()->setBitmapModulation(ErrorColor);
  417.         GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf);
  418.         GFX->getDrawUtil()->clearBitmapModulation();
  419.  
  420.         // Return Error.
  421.         return;
  422.     }
  423.  
  424.     // Are we using the Overlay Bitmap?
  425.     if (mUseOverlayBitmap)
  426.     {
  427.         // Yes, so do we have a texture Handle?
  428.         if (mOverlayTextureHandle)
  429.         {
  430.             // Yes, so clear Bitmap Modulation.
  431.             GFX->getDrawUtil()->clearBitmapModulation();
  432.  
  433.             // Are we tiling the Overlay Bitmap?
  434.             if(mOverlayTile)
  435.             {
  436.                 RectI SrcRegion;
  437.                 RectI DstRegion;
  438.  
  439.                 // Yes, so fetch texture object.
  440.                 GFXTextureObject* TextureObj = mOverlayTextureHandle;
  441.  
  442.                 // Calculate Tesselation Count.
  443.                 float XTess = ((float)getWidth()/(float)TextureObj->mBitmapSize.x)+1;
  444.                 float YTess = ((float)getHeight()/(float)TextureObj->mBitmapSize.y)+1;
  445.  
  446.                 for(int y = 0; y < YTess; ++y)
  447.                 {
  448.                     for(int x = 0; x < XTess; ++x)
  449.                     {
  450.                         // Calculate Source Region.
  451.                         SrcRegion.set(0,0,TextureObj->mBitmapSize.x, TextureObj->mBitmapSize.y);
  452.  
  453.                         // Calculate Destination Region.
  454.                         DstRegion.set(((TextureObj->mBitmapSize.x*x)+offset.x),
  455.                             ((TextureObj->mBitmapSize.y*y)+offset.y),
  456.                             TextureObj->mBitmapSize.x
  457.                             TextureObj->mBitmapSize.y);
  458.  
  459.                         // Draw Tiled Bitmap.
  460.                         GFX->getDrawUtil()->drawBitmapStretchSR(TextureObj, DstRegion, SrcRegion);
  461.                     }
  462.                 }
  463.             }
  464.             else
  465.             {
  466.                 // No, so draw stretched Bitmap.
  467.                 GFX->getDrawUtil()->drawBitmapStretch(mOverlayTextureHandle, getBounds());
  468.             }
  469.         }
  470.     }
  471.  
  472.     // Are we using the Overlay Colour?
  473.     if (mUseOverlayColour)
  474.     {
  475.         // Set Colour Mask.
  476.  
  477.         //GFX->enableColorWrites(mOverlayRedMask, mOverlayGreenMask, mOverlayBlueMask, true);
  478.  
  479.         // Declare StateBlocks
  480.         GFXStateBlockDesc ecw;
  481.         ecw.colorWriteRed   |= ( mOverlayRedMask ? GFXCOLORWRITEENABLE_RED      : 0 );
  482.         ecw.colorWriteGreen |= ( mOverlayGreenMask ? GFXCOLORWRITEENABLE_GREEN  : 0 );
  483.         ecw.colorWriteBlue  |= ( mOverlayBlueMask ? GFXCOLORWRITEENABLE_BLUE    : 0 );
  484.         ecw.colorWriteAlpha = GFXCOLORWRITEENABLE_ALPHA;
  485.         mEcwSB = GFX->createStateBlock(ecw);
  486.  
  487.         GFXStateBlockDesc ecwReset;
  488.         ecwReset.colorWriteRed   = GFXCOLORWRITEENABLE_RED;
  489.         ecwReset.colorWriteGreen = GFXCOLORWRITEENABLE_GREEN;
  490.         ecwReset.colorWriteBlue  = GFXCOLORWRITEENABLE_BLUE;
  491.         ecwReset.colorWriteAlpha = GFXCOLORWRITEENABLE_ALPHA;
  492.         mEcwResetSB = GFX->createStateBlock(ecwReset);
  493.  
  494.         GFX->setStateBlock(mEcwSB);
  495.  
  496.         // Draw our filled rectangle with the Filter Colour.
  497.         GFX->getDrawUtil()->drawRectFill(updateRect, mOverlayColor);
  498.  
  499.         // Reset the Colour Mask.
  500.         GFX->setStateBlock(mEcwResetSB);
  501.         //GFX->enableColorWrites(true, true, true, true);
  502.     }
  503. }
  504.  
  505. //------------------------------------------------------------------------------
  506.  
  507. bool fxGuiSnooper::processCameraQuery(CameraQuery * query)
  508. {
  509.     Point3F     CameraRotation;                         // Rotated View.
  510.     float       VisibleDistance = 1100.0f;              // Visible Distance.
  511.  
  512.  
  513.     // Get Game Connection.
  514.     GameConnection* pConnection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer());
  515.  
  516.     // Did we get the connection?
  517.     if (pConnection)
  518.     {
  519.         // Have we got an Attached Object?
  520.         if (mAttachedObject)
  521.         {
  522.             // Current Sweep.
  523.             EulerF mCurrentSweep;
  524.  
  525.             // Create Camera Matrix.
  526.             MatrixF Camera(true);
  527.  
  528.             // Craete Rotation Quaternion.
  529.             QuatF   QRotation;
  530.  
  531.             // Get Time Elapsed.
  532.             U32 CurrentTime = Platform::getRealMilliseconds();
  533.             U32 TimeElapsed = CurrentTime - mLastTimeStamp;
  534.             mLastTimeStamp = CurrentTime;
  535.  
  536.             // Calculate new Sweep.
  537.             Point3F NewSweep(   (U32)(360.0f / mSweepTime[0] * TimeElapsed) % 360,
  538.                 (U32)(360.0f / mSweepTime[1] * TimeElapsed) % 360,
  539.                 (U32)(360.0f / mSweepTime[2] * TimeElapsed) % 360);
  540.  
  541.             // Add to Current Sweep.
  542.             mCurrentSweepMagnitude += NewSweep;
  543.  
  544.             // Calculate Current Sweep Angle.
  545.             mCurrentSweep.set(  mDegToRad((mSweepAmplitude[0] * mCos(mDegToRad(mCurrentSweepMagnitude[0])))/2 + mRotateView[0]),
  546.                 mDegToRad((mSweepAmplitude[1] * mCos(mDegToRad(mCurrentSweepMagnitude[1])))/2 + mRotateView[1]),
  547.                 mDegToRad((mSweepAmplitude[2] * mCos(mDegToRad(mCurrentSweepMagnitude[2])))/2 + mRotateView[2]));
  548.  
  549.             // Set-up Quaternion Rotation.
  550.             QRotation.set(mCurrentSweep);
  551.  
  552.             // Set Camera Matrix to new Rotation.
  553.             QRotation.setMatrix(&Camera);
  554.  
  555.             // Set Position @ Attached Object.
  556.             Camera.setColumn(3, mAttachedObject->getBoxCenter() + mOffsetView);
  557.  
  558.             // Set Camera Matrix.
  559.             query->cameraMatrix = Camera;
  560.  
  561.             // Set Near/Far Planes.
  562.             query->nearPlane = 0.1;
  563.             query->farPlane = getMax(VisibleDistance, 50.f);
  564.  
  565.             // Set FOV.
  566.             query->fov = mDegToRad(mFov);
  567.  
  568.             // Return OK.
  569.             return(true);
  570.         }
  571.     }
  572.  
  573.     // Return Error.
  574.     return(false);
  575. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement