Browse Source

Updated ImGuizmo.

Branimir Karadžić 8 years ago
parent
commit
50647e2eb5
1 changed files with 368 additions and 272 deletions
  1. 368 272
      3rdparty/ocornut-imgui/widgets/gizmo.inl

+ 368 - 272
3rdparty/ocornut-imgui/widgets/gizmo.inl

@@ -62,6 +62,8 @@ namespace ImGuizmo
    //template <typename T> T LERP(T x, T y, float z) { return (x + (y - x)*z); }
    //template <typename T> T LERP(T x, T y, float z) { return (x + (y - x)*z); }
    template <typename T> T Clamp(T x, T y, T z) { return ((x<y) ? y : ((x>z) ? z : x)); }
    template <typename T> T Clamp(T x, T y, T z) { return ((x<y) ? y : ((x>z) ? z : x)); }
    template <typename T> T max(T x, T y) { return (x > y) ? x : y; }
    template <typename T> T max(T x, T y) { return (x > y) ? x : y; }
+   template <typename T> T min(T x, T y) { return (x < y) ? x : y; }
+   template <typename T> bool IsWithin(T x, T y, T z) { return (x>=y) && (x<=z); }
 
 
    struct matrix_t;
    struct matrix_t;
    struct vec_t
    struct vec_t
@@ -83,7 +85,7 @@ namespace ImGuizmo
       vec_t& operator -= (const vec_t& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
       vec_t& operator -= (const vec_t& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
       vec_t& operator += (const vec_t& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
       vec_t& operator += (const vec_t& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
       vec_t& operator *= (const vec_t& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
       vec_t& operator *= (const vec_t& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
-      vec_t& operator *= (float v) { x *= v;	y *= v;	z *= v;	w *= v;	return *this; }
+      vec_t& operator *= (float v) { x *= v;    y *= v;    z *= v;    w *= v;    return *this; }
 
 
       vec_t operator * (float f) const;
       vec_t operator * (float f) const;
       vec_t operator - () const;
       vec_t operator - () const;
@@ -96,7 +98,7 @@ namespace ImGuizmo
       float LengthSq() const { return (x*x + y*y + z*z); };
       float LengthSq() const { return (x*x + y*y + z*z); };
       vec_t Normalize() { (*this) *= (1.f / Length()); return (*this); }
       vec_t Normalize() { (*this) *= (1.f / Length()); return (*this); }
       vec_t Normalize(const vec_t& v) { this->Set(v.x, v.y, v.z, v.w); this->Normalize(); return (*this); }
       vec_t Normalize(const vec_t& v) { this->Set(v.x, v.y, v.z, v.w); this->Normalize(); return (*this); }
-	  vec_t Abs() const;
+      vec_t Abs() const;
       void Cross(const vec_t& v)
       void Cross(const vec_t& v)
       {
       {
          vec_t res;
          vec_t res;
@@ -144,7 +146,6 @@ namespace ImGuizmo
    vec_t vec_t::operator + (const vec_t& v) const { return makeVect(x + v.x, y + v.y, z + v.z, w + v.w); }
    vec_t vec_t::operator + (const vec_t& v) const { return makeVect(x + v.x, y + v.y, z + v.z, w + v.w); }
    vec_t vec_t::operator * (const vec_t& v) const { return makeVect(x * v.x, y * v.y, z * v.z, w * v.w); }
    vec_t vec_t::operator * (const vec_t& v) const { return makeVect(x * v.x, y * v.y, z * v.z, w * v.w); }
    vec_t vec_t::Abs() const { return makeVect(fabsf(x), fabsf(y), fabsf(z)); }
    vec_t vec_t::Abs() const { return makeVect(fabsf(x), fabsf(y), fabsf(z)); }
-   ImVec2 operator+ (const ImVec2& a, const ImVec2& b) { return ImVec2(a.x + b.x, a.y + b.y); }
 
 
    vec_t Normalized(const vec_t& v) { vec_t res; res = v; res.Normalize(); return res; }
    vec_t Normalized(const vec_t& v) { vec_t res; res = v; res.Normalize(); return res; }
    vec_t Cross(const vec_t& v1, const vec_t& v2)
    vec_t Cross(const vec_t& v1, const vec_t& v2)
@@ -185,7 +186,7 @@ namespace ImGuizmo
          {
          {
             vec_t right, up, dir, position;
             vec_t right, up, dir, position;
          } v;
          } v;
-		 vec_t component[4];
+         vec_t component[4];
       };
       };
 
 
       matrix_t(const matrix_t& other) { memcpy(&m16[0], &other.m16[0], sizeof(float) * 16); }
       matrix_t(const matrix_t& other) { memcpy(&m16[0], &other.m16[0], sizeof(float) * 16); }
@@ -488,17 +489,13 @@ namespace ImGuizmo
       SCALE_Y,
       SCALE_Y,
       SCALE_Z,
       SCALE_Z,
       SCALE_XYZ,
       SCALE_XYZ,
-	  BOUNDS
+      BOUNDS
    };
    };
 
 
    struct Context
    struct Context
    {
    {
       Context() : mbUsing(false), mbEnable(true), mbUsingBounds(false)
       Context() : mbUsing(false), mbEnable(true), mbUsingBounds(false)
       {
       {
-	      mX=0.f;
-	      mY=0.f;
-	      mWidth=0.f;
-	      mHeight=0.f;
       }
       }
 
 
       ImDrawList* mDrawList;
       ImDrawList* mDrawList;
@@ -521,6 +518,7 @@ namespace ImGuizmo
       vec_t mRayOrigin;
       vec_t mRayOrigin;
       vec_t mRayVector;
       vec_t mRayVector;
 
 
+      float  mRadiusSquareCenter;
       ImVec2 mScreenSquareCenter;
       ImVec2 mScreenSquareCenter;
       ImVec2 mScreenSquareMin;
       ImVec2 mScreenSquareMin;
       ImVec2 mScreenSquareMax;
       ImVec2 mScreenSquareMax;
@@ -552,26 +550,25 @@ namespace ImGuizmo
       bool mBelowPlaneLimit[3];
       bool mBelowPlaneLimit[3];
       float mAxisFactor[3];
       float mAxisFactor[3];
 
 
-	  // bounds stretching
-	  vec_t mBoundsPivot;
-	  vec_t mBoundsAnchor;
-	  vec_t mBoundsPlan;
-	  vec_t mBoundsLocalPivot;
-	  int mBoundsBestAxis;
-	  int mBoundsAxis[2];
-	  bool mbUsingBounds;
-	  matrix_t mBoundsMatrix;
+      // bounds stretching
+      vec_t mBoundsPivot;
+      vec_t mBoundsAnchor;
+      vec_t mBoundsPlan;
+      vec_t mBoundsLocalPivot;
+      int mBoundsBestAxis;
+      int mBoundsAxis[2];
+      bool mbUsingBounds;
+      matrix_t mBoundsMatrix;
 
 
       //
       //
       int mCurrentOperation;
       int mCurrentOperation;
 
 
-      float mX,mY,mWidth,mHeight;
-	   /*
-	  float mX = 0.f;
-	  float mY = 0.f;
-	  float mWidth = 0.f;
-	  float mHeight = 0.f;
-	  */
+      float mX = 0.f;
+      float mY = 0.f;
+      float mWidth = 0.f;
+      float mHeight = 0.f;
+      float mXMax = 0.f;
+      float mYMax = 0.f;
    };
    };
 
 
    static Context gContext;
    static Context gContext;
@@ -581,7 +578,11 @@ namespace ImGuizmo
 
 
    static const vec_t directionUnary[3] = { makeVect(1.f, 0.f, 0.f), makeVect(0.f, 1.f, 0.f), makeVect(0.f, 0.f, 1.f) };
    static const vec_t directionUnary[3] = { makeVect(1.f, 0.f, 0.f), makeVect(0.f, 1.f, 0.f), makeVect(0.f, 0.f, 1.f) };
    static const ImU32 directionColor[3] = { 0xFF0000AA, 0xFF00AA00, 0xFFAA0000 };
    static const ImU32 directionColor[3] = { 0xFF0000AA, 0xFF00AA00, 0xFFAA0000 };
-   static const ImU32 selectionColor = 0xFF1080FF;
+
+   // Alpha: 100%: FF, 87%: DE, 70%: B3, 54%: 8A, 50%: 80, 38%: 61, 12%: 1F
+   static const ImU32 planeBorderColor[3] = { 0xFFAA0000, 0xFF0000AA, 0xFF00AA00 };
+   static const ImU32 planeColor[3] = { 0x610000AA, 0x6100AA00, 0x61AA0000 };
+   static const ImU32 selectionColor = 0x8A1080FF;
    static const ImU32 inactiveColor = 0x99999999;
    static const ImU32 inactiveColor = 0x99999999;
    static const ImU32 translationLineColor = 0xAAAAAAAA;
    static const ImU32 translationLineColor = 0xAAAAAAAA;
    static const char *translationInfoMask[] = { "X : %5.3f", "Y : %5.3f", "Z : %5.3f", "X : %5.3f Y : %5.3f", "Y : %5.3f Z : %5.3f", "X : %5.3f Z : %5.3f", "X : %5.3f Y : %5.3f Z : %5.3f" };
    static const char *translationInfoMask[] = { "X : %5.3f", "Y : %5.3f", "Z : %5.3f", "X : %5.3f Y : %5.3f", "Y : %5.3f Z : %5.3f", "X : %5.3f Z : %5.3f", "X : %5.3f Y : %5.3f Z : %5.3f" };
@@ -607,11 +608,11 @@ namespace ImGuizmo
       trans *= 0.5f / trans.w;
       trans *= 0.5f / trans.w;
       trans += makeVect(0.5f, 0.5f);
       trans += makeVect(0.5f, 0.5f);
       trans.y = 1.f - trans.y;
       trans.y = 1.f - trans.y;
-	  trans.x *= gContext.mWidth;
-	  trans.y *= gContext.mHeight;
-	  trans.x += gContext.mX;
-	  trans.y += gContext.mY;
-	  return ImVec2(trans.x, trans.y);
+      trans.x *= gContext.mWidth;
+      trans.y *= gContext.mHeight;
+      trans.x += gContext.mX;
+      trans.y += gContext.mY;
+      return ImVec2(trans.x, trans.y);
    }
    }
 
 
    static void ComputeCameraRay(vec_t &rayOrigin, vec_t &rayDir)
    static void ComputeCameraRay(vec_t &rayOrigin, vec_t &rayDir)
@@ -621,9 +622,9 @@ namespace ImGuizmo
       matrix_t mViewProjInverse;
       matrix_t mViewProjInverse;
       mViewProjInverse.Inverse(gContext.mViewMat * gContext.mProjectionMat);
       mViewProjInverse.Inverse(gContext.mViewMat * gContext.mProjectionMat);
 
 
-	  float mox = ((io.MousePos.x - gContext.mX) / gContext.mWidth) * 2.f - 1.f;
-	  float moy = (1.f - ((io.MousePos.y - gContext.mY) / gContext.mHeight)) * 2.f - 1.f;
-	  
+      float mox = ((io.MousePos.x - gContext.mX) / gContext.mWidth) * 2.f - 1.f;
+      float moy = (1.f - ((io.MousePos.y - gContext.mY) / gContext.mHeight)) * 2.f - 1.f;
+      
       rayOrigin.Transform(makeVect(mox, moy, 0.f, 1.f), mViewProjInverse);
       rayOrigin.Transform(makeVect(mox, moy, 0.f, 1.f), mViewProjInverse);
       rayOrigin *= 1.f / rayOrigin.w;
       rayOrigin *= 1.f / rayOrigin.w;
       vec_t rayEnd;
       vec_t rayEnd;
@@ -643,12 +644,24 @@ namespace ImGuizmo
       return -(numer / denom);
       return -(numer / denom);
    }
    }
 
 
+   static bool IsInContextRect( ImVec2 p )
+   {
+       return IsWithin( p.x, gContext.mX, gContext.mXMax ) && IsWithin(p.y, gContext.mY, gContext.mYMax );
+   }
+
    void SetRect(float x, float y, float width, float height)
    void SetRect(float x, float y, float width, float height)
    {
    {
-	   gContext.mX = x;
-	   gContext.mY = y;
-	   gContext.mWidth = width;
-	   gContext.mHeight = height;
+       gContext.mX = x;
+       gContext.mY = y;
+       gContext.mWidth = width;
+       gContext.mHeight = height;
+       gContext.mXMax = gContext.mX + gContext.mWidth;
+       gContext.mYMax = gContext.mY + gContext.mXMax;
+   }
+
+   void SetDrawlist()
+   {
+      gContext.mDrawList = ImGui::GetWindowDrawList();
    }
    }
 
 
    void BeginFrame()
    void BeginFrame()
@@ -667,7 +680,7 @@ namespace ImGuizmo
 
 
       style.Colors[bgColorIdx].w = oldAlpha;
       style.Colors[bgColorIdx].w = oldAlpha;
 
 
-	  gContext.mDrawList = ImGui::GetWindowDrawList();
+      gContext.mDrawList = ImGui::GetWindowDrawList();
 
 
       ImGui::End();
       ImGui::End();
    }
    }
@@ -685,11 +698,11 @@ namespace ImGuizmo
    void Enable(bool enable)
    void Enable(bool enable)
    {
    {
       gContext.mbEnable = enable;
       gContext.mbEnable = enable;
-	  if (!enable)
-	  {
-		  gContext.mbUsing = false;
-		  gContext.mbUsingBounds = false;
-	  }
+      if (!enable)
+      {
+          gContext.mbUsing = false;
+          gContext.mbUsingBounds = false;
+      }
    }
    }
 
 
    static float GetUniform(const vec_t& position, const matrix_t& mat)
    static float GetUniform(const vec_t& position, const matrix_t& mat)
@@ -750,7 +763,8 @@ namespace ImGuizmo
             {
             {
                int colorPlaneIndex = (i + 2) % 3;
                int colorPlaneIndex = (i + 2) % 3;
                colors[i + 1] = (type == (int)(MOVE_X + i)) ? selectionColor : directionColor[i];
                colors[i + 1] = (type == (int)(MOVE_X + i)) ? selectionColor : directionColor[i];
-               colors[i + 4] = (type == (int)(MOVE_XY + i)) ? selectionColor : directionColor[colorPlaneIndex];
+               colors[i + 4] = (type == (int)(MOVE_XY + i)) ? selectionColor : planeColor[colorPlaneIndex];
+               colors[i + 4] = (type == MOVE_SCREEN) ? selectionColor : colors[i + 4];
             }
             }
             break;
             break;
          case ROTATE:
          case ROTATE:
@@ -763,8 +777,6 @@ namespace ImGuizmo
             for (int i = 0; i < 3; i++)
             for (int i = 0; i < 3; i++)
                colors[i + 1] = (type == (int)(SCALE_X + i)) ? selectionColor : directionColor[i];
                colors[i + 1] = (type == (int)(SCALE_X + i)) ? selectionColor : directionColor[i];
             break;
             break;
-		 default:
-			 break;
          }
          }
       }
       }
       else
       else
@@ -868,6 +880,7 @@ namespace ImGuizmo
       vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
       vec_t cameraToModelNormalized = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
       cameraToModelNormalized.TransformVector(gContext.mModelInverse);
       cameraToModelNormalized.TransformVector(gContext.mModelInverse);
       
       
+      gContext.mRadiusSquareCenter = screenRotateSize * gContext.mHeight;
       for (int axis = 0; axis < 3; axis++)
       for (int axis = 0; axis < 3; axis++)
       {
       {
          ImVec2 circlePos[halfCircleSegmentCount];
          ImVec2 circlePos[halfCircleSegmentCount];
@@ -881,9 +894,14 @@ namespace ImGuizmo
             vec_t pos = makeVect(axisPos[axis], axisPos[(axis+1)%3], axisPos[(axis+2)%3]) * gContext.mScreenFactor;
             vec_t pos = makeVect(axisPos[axis], axisPos[(axis+1)%3], axisPos[(axis+2)%3]) * gContext.mScreenFactor;
             circlePos[i] = worldToPos(pos, gContext.mMVP);
             circlePos[i] = worldToPos(pos, gContext.mMVP);
          }
          }
+
+         float radiusAxis = sqrtf( (ImLengthSqr(worldToPos(gContext.mModel.v.position, gContext.mViewProjection) - circlePos[0]) ));
+         if(radiusAxis > gContext.mRadiusSquareCenter)
+           gContext.mRadiusSquareCenter = radiusAxis;
+
          drawList->AddPolyline(circlePos, halfCircleSegmentCount, colors[3 - axis], false, 2, true);
          drawList->AddPolyline(circlePos, halfCircleSegmentCount, colors[3 - axis], false, 2, true);
       }
       }
-      drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), screenRotateSize * gContext.mHeight, colors[0], 64);
+      drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), gContext.mRadiusSquareCenter, colors[0], 64, 3.f);
 
 
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
@@ -929,9 +947,6 @@ namespace ImGuizmo
       ImU32 colors[7];
       ImU32 colors[7];
       ComputeColors(colors, type, SCALE);
       ComputeColors(colors, type, SCALE);
 
 
-      // draw screen cirle
-      drawList->AddCircleFilled(gContext.mScreenSquareCenter, 12.f, colors[0], 32);
-
       // draw
       // draw
       vec_t scaleDisplay = { 1.f, 1.f, 1.f, 1.f };
       vec_t scaleDisplay = { 1.f, 1.f, 1.f, 1.f };
       
       
@@ -953,17 +968,20 @@ namespace ImGuizmo
 
 
             if (gContext.mbUsing)
             if (gContext.mbUsing)
             {
             {
-               drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 6.f);
-               drawList->AddCircleFilled(worldDirSSpaceNoScale, 10.f, 0xFF404040);
+               drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 3.f);
+               drawList->AddCircleFilled(worldDirSSpaceNoScale, 6.f, 0xFF404040);
             }
             }
             
             
-            drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 6.f);
-            drawList->AddCircleFilled(worldDirSSpace, 10.f, colors[i + 1]);
+            drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
+            drawList->AddCircleFilled(worldDirSSpace, 6.f, colors[i + 1]);
 
 
             if (gContext.mAxisFactor[i] < 0.f)
             if (gContext.mAxisFactor[i] < 0.f)
                DrawHatchedAxis(dirPlaneX * scaleDisplay[i]);
                DrawHatchedAxis(dirPlaneX * scaleDisplay[i]);
          }
          }
       }
       }
+
+      // draw screen cirle
+      drawList->AddCircleFilled(gContext.mScreenSquareCenter, 6.f, colors[0], 32);
       
       
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
@@ -989,21 +1007,21 @@ namespace ImGuizmo
    static void DrawTranslationGizmo(int type)
    static void DrawTranslationGizmo(int type)
    {
    {
       ImDrawList* drawList = gContext.mDrawList;
       ImDrawList* drawList = gContext.mDrawList;
-	  if (!drawList)
-		  return;
+      if (!drawList)
+          return;
 
 
       // colors
       // colors
       ImU32 colors[7];
       ImU32 colors[7];
       ComputeColors(colors, type, TRANSLATE);
       ComputeColors(colors, type, TRANSLATE);
 
 
-      // draw screen quad
-      drawList->AddRectFilled(gContext.mScreenSquareMin, gContext.mScreenSquareMax, colors[0], 2.f);
-
+      const ImVec2 origin = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
+      
       // draw
       // draw
-      for (unsigned int i = 0; i < 3; i++)
+      bool belowAxisLimit = false;
+      bool belowPlaneLimit = false;
+      for (unsigned int i = 0; i < 3; ++i)
       {
       {
          vec_t dirPlaneX, dirPlaneY;
          vec_t dirPlaneX, dirPlaneY;
-         bool belowAxisLimit, belowPlaneLimit;
          ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
          ComputeTripodAxisAndVisibility(i, dirPlaneX, dirPlaneY, belowAxisLimit, belowPlaneLimit);
          
          
          // draw axis
          // draw axis
@@ -1012,8 +1030,20 @@ namespace ImGuizmo
             ImVec2 baseSSpace = worldToPos(dirPlaneX * 0.1f * gContext.mScreenFactor, gContext.mMVP);
             ImVec2 baseSSpace = worldToPos(dirPlaneX * 0.1f * gContext.mScreenFactor, gContext.mMVP);
             ImVec2 worldDirSSpace = worldToPos(dirPlaneX * gContext.mScreenFactor, gContext.mMVP);
             ImVec2 worldDirSSpace = worldToPos(dirPlaneX * gContext.mScreenFactor, gContext.mMVP);
 
 
-            drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 6.f);
-            
+            drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
+
+            // Arrow head begin
+            ImVec2 dir(origin - worldDirSSpace);
+
+            float d = sqrtf(ImLengthSqr(dir));
+            dir /= d; // Normalize
+            dir *= 6.0f;
+
+            ImVec2 ortogonalDir(dir.y, -dir.x); // Perpendicular vector
+            ImVec2 a(worldDirSSpace + dir);
+            drawList->AddTriangleFilled(worldDirSSpace - dir, a + ortogonalDir, a - ortogonalDir, colors[i + 1]);
+            // Arrow head end
+
             if (gContext.mAxisFactor[i] < 0.f)
             if (gContext.mAxisFactor[i] < 0.f)
                DrawHatchedAxis(dirPlaneX);
                DrawHatchedAxis(dirPlaneX);
          }
          }
@@ -1022,15 +1052,18 @@ namespace ImGuizmo
          if (belowPlaneLimit)
          if (belowPlaneLimit)
          {
          {
             ImVec2 screenQuadPts[4];
             ImVec2 screenQuadPts[4];
-            for (int j = 0; j < 4; j++)
+            for (int j = 0; j < 4; ++j)
             {
             {
                vec_t cornerWorldPos = (dirPlaneX * quadUV[j * 2] + dirPlaneY  * quadUV[j * 2 + 1]) * gContext.mScreenFactor;
                vec_t cornerWorldPos = (dirPlaneX * quadUV[j * 2] + dirPlaneY  * quadUV[j * 2 + 1]) * gContext.mScreenFactor;
                screenQuadPts[j] = worldToPos(cornerWorldPos, gContext.mMVP);
                screenQuadPts[j] = worldToPos(cornerWorldPos, gContext.mMVP);
             }
             }
+            drawList->AddPolyline(screenQuadPts, 4, planeBorderColor[i], true, 1.0f, true);
             drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4], true);
             drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4], true);
          }
          }
       }
       }
 
 
+      drawList->AddCircleFilled(gContext.mScreenSquareCenter, 6.f, colors[0], 32);
+
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
          ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);
          ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);
@@ -1051,176 +1084,233 @@ namespace ImGuizmo
       }
       }
    }
    }
 
 
+   static bool CanActivate()
+   {
+      if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && !ImGui::IsAnyItemActive())
+         return true;
+      return false;
+   }
+
    static void HandleAndDrawLocalBounds(float *bounds, matrix_t *matrix, float *snapValues)
    static void HandleAndDrawLocalBounds(float *bounds, matrix_t *matrix, float *snapValues)
    {
    {
-	   ImGuiIO& io = ImGui::GetIO();
-	   ImDrawList* drawList = gContext.mDrawList;
-
-	   // compute best projection axis
-	   vec_t bestAxisWorldDirection;
-	   int bestAxis = gContext.mBoundsBestAxis;
-	   if (!gContext.mbUsingBounds)
-	   {
-		   
-		   float bestDot = 0.f;
-		   for (unsigned int i = 0; i < 3; i++)
-		   {
-			   vec_t dirPlaneNormalWorld;
-			   dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource);
-			   dirPlaneNormalWorld.Normalize();
-
-			   float dt = Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld);
-			   if (fabsf(dt) >= bestDot)
-			   {
-				   bestDot = fabsf(dt);
-				   bestAxis = i;
-				   bestAxisWorldDirection = dirPlaneNormalWorld;
-			   }
-		   }
-	   }
-
-	   // corners
-	   vec_t aabb[4];
-
-	   int secondAxis = (bestAxis + 1) % 3;
-	   int thirdAxis = (bestAxis + 2) % 3;
-
-	   for (int i = 0; i < 4; i++)
-	   {
-		   aabb[i][3] = aabb[i][bestAxis] = 0.f;
-		   aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];
-		   aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];
-	   }
-
-	   // draw bounds
-	   unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000;
-
-	   matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;
-	   for (int i = 0; i < 4;i++)
-	   {
-		   ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);
-		   ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP);
-		   float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));
-		   int stepCount = (int)(boundDistance / 10.f);
-		   float stepLength = 1.f / (float)stepCount;
-		   for (int j = 0; j < stepCount; j++)
-		   {
-			   float t1 = (float)j * stepLength;
-			   float t2 = (float)j * stepLength + stepLength * 0.5f;
-			   ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));
-			   ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));
-			   drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f);
-		   }
-		   vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f;
-		   ImVec2 midBound = worldToPos(midPoint, boundsMVP);
-		   static const float AnchorBigRadius = 8.f;
-		   static const float AnchorSmallRadius = 6.f;
-		   bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
-		   bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
-
-		   
-		   unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
-		   unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
-		   
-		   drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
-		   drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
-		   int oppositeIndex = (i + 2) % 4;
-		   // big anchor on corners
-		   if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && io.MouseDown[0])
-		   {
-			   gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);
-			   gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);
-			   gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
-			   gContext.mBoundsBestAxis = bestAxis;
-			   gContext.mBoundsAxis[0] = secondAxis;
-			   gContext.mBoundsAxis[1] = thirdAxis;
-
-			   gContext.mBoundsLocalPivot.Set(0.f);
-			   gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];
-			   gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];
-
-			   gContext.mbUsingBounds = true;
-			   gContext.mBoundsMatrix = gContext.mModelSource;
-		   }
-		   // small anchor on middle of segment
-		   if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && io.MouseDown[0])
-		   {
-			   vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;
-			   gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);
-			   gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);
-			   gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
-			   gContext.mBoundsBestAxis = bestAxis;
-			   int indices[] = { secondAxis , thirdAxis };
-			   gContext.mBoundsAxis[0] = indices[i%2];
-			   gContext.mBoundsAxis[1] = -1;
-
-			   gContext.mBoundsLocalPivot.Set(0.f);
-			   gContext.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);
-
-			   gContext.mbUsingBounds = true;
-			   gContext.mBoundsMatrix = gContext.mModelSource;
-		   }
-	   }
-	   
-	   if (gContext.mbUsingBounds)
-	   {
-		   matrix_t scale;
-		   scale.SetToIdentity();
-
-		   // compute projected mouse position on plan
-		   const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);
-		   vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
-
-		   // compute a reference and delta vectors base on mouse move
-		   vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();
-		   vec_t referenceVector = (gContext.mBoundsAnchor - gContext.mBoundsPivot).Abs();
-
-		   // for 1 or 2 axes, compute a ratio that's used for scale and snap it based on resulting length
-		   for (int i = 0; i < 2; i++)
-		   {
-			   int axisIndex = gContext.mBoundsAxis[i];
-			   if (axisIndex == -1)
-				   continue;
-
-			   float ratioAxis = 1.f;
-			   vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex].Abs();
-
-			   float dtAxis = axisDir.Dot(referenceVector);
-			   float boundSize = bounds[axisIndex + 3] - bounds[axisIndex];
-			   if (dtAxis > FLT_EPSILON)
-				   ratioAxis = axisDir.Dot(deltaVector) / dtAxis;
-
-			   if (snapValues)
-			   {
-				   float length = boundSize * ratioAxis;
-				   ComputeSnap(&length, snapValues[axisIndex]);
-				   if (boundSize > FLT_EPSILON)
-					   ratioAxis = length / boundSize;
-			   }
-			   scale.component[axisIndex] *= ratioAxis;
-		   }
-
-		   // transform matrix
-		   matrix_t preScale, postScale;
-		   preScale.Translation(-gContext.mBoundsLocalPivot);
-		   postScale.Translation(gContext.mBoundsLocalPivot);
-		   matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;
-		   *matrix = res;
-
-		   // info text
-		   char tmps[512];
-		   ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
-		   ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f"
-			   , (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length()
-			   , (bounds[4] - bounds[1]) * gContext.mBoundsMatrix.component[1].Length() * scale.component[1].Length()
-			   , (bounds[5] - bounds[2]) * gContext.mBoundsMatrix.component[2].Length() * scale.component[2].Length()
-		   );
-		   drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), 0xFF000000, tmps);
-		   drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps);
- 	   }
-
-	   if (!io.MouseDown[0])
-		   gContext.mbUsingBounds = false;
+       ImGuiIO& io = ImGui::GetIO();
+       ImDrawList* drawList = gContext.mDrawList;
+
+       // compute best projection axis
+       vec_t axesWorldDirections[3];
+       vec_t bestAxisWorldDirection;
+       int axes[3];
+       unsigned int numAxes = 1;
+       axes[0] = gContext.mBoundsBestAxis;
+       int bestAxis = axes[0];
+       if (!gContext.mbUsingBounds)
+       {
+           numAxes = 0;
+           float bestDot = 0.f;
+           for (unsigned int i = 0; i < 3; i++)
+           {
+               vec_t dirPlaneNormalWorld;
+               dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource);
+               dirPlaneNormalWorld.Normalize();
+
+               float dt = fabsf( Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld) );
+               if ( dt >= bestDot )
+               {
+                   bestDot = dt;
+                   bestAxis = i;
+                   bestAxisWorldDirection = dirPlaneNormalWorld;
+               }
+
+               if( dt >= 0.1f )
+               {
+                   axes[numAxes] = i;
+                   axesWorldDirections[numAxes] = dirPlaneNormalWorld;
+                   ++numAxes;
+               }
+           }
+       }
+
+       if( numAxes == 0 )
+       {
+            axes[0] = bestAxis;
+            axesWorldDirections[0] = bestAxisWorldDirection;
+            numAxes = 1;
+       }
+       else if( bestAxis != axes[0] )
+       {
+          unsigned int bestIndex = 0;
+          for (unsigned int i = 0; i < numAxes; i++)
+          {
+              if( axes[i] == bestAxis )
+              {
+                  bestIndex = i;
+                  break;
+              }
+          }
+          int tempAxis = axes[0];
+          axes[0] = axes[bestIndex];
+          axes[bestIndex] = tempAxis;
+          vec_t tempDirection = axesWorldDirections[0];
+          axesWorldDirections[0] = axesWorldDirections[bestIndex];
+          axesWorldDirections[bestIndex] = tempDirection;
+       }
+
+       for (unsigned int axisIndex = 0; axisIndex < numAxes; ++axisIndex)
+       {
+           bestAxis = axes[axisIndex];
+           bestAxisWorldDirection = axesWorldDirections[axisIndex];
+
+           // corners
+           vec_t aabb[4];
+
+           int secondAxis = (bestAxis + 1) % 3;
+           int thirdAxis = (bestAxis + 2) % 3;
+
+           for (int i = 0; i < 4; i++)
+           {
+               aabb[i][3] = aabb[i][bestAxis] = 0.f;
+               aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];
+               aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];
+           }
+
+           // draw bounds
+           unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000;
+
+           matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;
+           for (int i = 0; i < 4;i++)
+           {
+               ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);
+               ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP);
+               if( !IsInContextRect( worldBound1 ) || !IsInContextRect( worldBound2 ) )
+               {
+                   continue;
+               }
+               float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));
+               int stepCount = (int)(boundDistance / 10.f);
+               stepCount = min( stepCount, 1000 );
+               float stepLength = 1.f / (float)stepCount;
+               for (int j = 0; j < stepCount; j++)
+               {
+                   float t1 = (float)j * stepLength;
+                   float t2 = (float)j * stepLength + stepLength * 0.5f;
+                   ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1));
+                   ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2));
+                   drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f);
+               }
+               vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f;
+               ImVec2 midBound = worldToPos(midPoint, boundsMVP);
+               static const float AnchorBigRadius = 8.f;
+               static const float AnchorSmallRadius = 6.f;
+               bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
+               bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius);
+
+           
+               unsigned int bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
+               unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
+           
+               drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
+               drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
+               int oppositeIndex = (i + 2) % 4;
+               // big anchor on corners
+               if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && CanActivate())
+               {
+                   gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);
+                   gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);
+                   gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
+                   gContext.mBoundsBestAxis = bestAxis;
+                   gContext.mBoundsAxis[0] = secondAxis;
+                   gContext.mBoundsAxis[1] = thirdAxis;
+
+                   gContext.mBoundsLocalPivot.Set(0.f);
+                   gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];
+                   gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];
+
+                   gContext.mbUsingBounds = true;
+                   gContext.mBoundsMatrix = gContext.mModelSource;
+               }
+               // small anchor on middle of segment
+               if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && CanActivate())
+               {
+                   vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;
+                   gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);
+                   gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);
+                   gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
+                   gContext.mBoundsBestAxis = bestAxis;
+                   int indices[] = { secondAxis , thirdAxis };
+                   gContext.mBoundsAxis[0] = indices[i%2];
+                   gContext.mBoundsAxis[1] = -1;
+
+                   gContext.mBoundsLocalPivot.Set(0.f);
+                   gContext.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);
+
+                   gContext.mbUsingBounds = true;
+                   gContext.mBoundsMatrix = gContext.mModelSource;
+               }
+           }
+       
+           if (gContext.mbUsingBounds)
+           {
+               matrix_t scale;
+               scale.SetToIdentity();
+
+               // compute projected mouse position on plan
+               const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);
+               vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
+
+               // compute a reference and delta vectors base on mouse move
+               vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();
+               vec_t referenceVector = (gContext.mBoundsAnchor - gContext.mBoundsPivot).Abs();
+
+               // for 1 or 2 axes, compute a ratio that's used for scale and snap it based on resulting length
+               for (int i = 0; i < 2; i++)
+               {
+                   int axisIndex1 = gContext.mBoundsAxis[i];
+                   if (axisIndex1 == -1)
+                       continue;
+
+                   float ratioAxis = 1.f;
+                   vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex1].Abs();
+
+                   float dtAxis = axisDir.Dot(referenceVector);
+                   float boundSize = bounds[axisIndex1 + 3] - bounds[axisIndex1];
+                   if (dtAxis > FLT_EPSILON)
+                       ratioAxis = axisDir.Dot(deltaVector) / dtAxis;
+
+                   if (snapValues)
+                   {
+                       float length = boundSize * ratioAxis;
+                       ComputeSnap(&length, snapValues[axisIndex1]);
+                       if (boundSize > FLT_EPSILON)
+                           ratioAxis = length / boundSize;
+                   }
+                   scale.component[axisIndex1] *= ratioAxis;
+               }
+
+               // transform matrix
+               matrix_t preScale, postScale;
+               preScale.Translation(-gContext.mBoundsLocalPivot);
+               postScale.Translation(gContext.mBoundsLocalPivot);
+               matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;
+               *matrix = res;
+
+               // info text
+               char tmps[512];
+               ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
+               ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f"
+                   , (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length()
+                   , (bounds[4] - bounds[1]) * gContext.mBoundsMatrix.component[1].Length() * scale.component[1].Length()
+                   , (bounds[5] - bounds[2]) * gContext.mBoundsMatrix.component[2].Length() * scale.component[2].Length()
+               );
+               drawList->AddText(ImVec2(destinationPosOnScreen.x + 15, destinationPosOnScreen.y + 15), 0xFF000000, tmps);
+               drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps);
+            }
+
+           if (!io.MouseDown[0])
+               gContext.mbUsingBounds = false;
+
+           if( gContext.mbUsingBounds )
+               break;
+       }
    }
    }
 
 
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1266,7 +1356,7 @@ namespace ImGuizmo
 
 
       vec_t deltaScreen = { io.MousePos.x - gContext.mScreenSquareCenter.x, io.MousePos.y - gContext.mScreenSquareCenter.y, 0.f, 0.f };
       vec_t deltaScreen = { io.MousePos.x - gContext.mScreenSquareCenter.x, io.MousePos.y - gContext.mScreenSquareCenter.y, 0.f, 0.f };
       float dist = deltaScreen.Length();
       float dist = deltaScreen.Length();
-	  if (dist >= (screenRotateSize - 0.002f) * gContext.mHeight && dist < (screenRotateSize + 0.002f) * gContext.mHeight)
+      if (dist >= (gContext.mRadiusSquareCenter - 1.0f) && dist < (gContext.mRadiusSquareCenter + 1.0f))
          type = ROTATE_SCREEN;
          type = ROTATE_SCREEN;
 
 
       const vec_t planNormals[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir};
       const vec_t planNormals[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir};
@@ -1338,6 +1428,7 @@ namespace ImGuizmo
       // move
       // move
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
+         ImGui::CaptureMouseFromApp();
          const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
          const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
          vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
          vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
 
 
@@ -1396,8 +1487,9 @@ namespace ImGuizmo
          // find new possible way to move
          // find new possible way to move
          vec_t gizmoHitProportion;
          vec_t gizmoHitProportion;
          type = GetMoveType(&gizmoHitProportion);
          type = GetMoveType(&gizmoHitProportion);
-         if (io.MouseDown[0] && type != NONE)
+         if (CanActivate() && type != NONE)
          {
          {
+            ImGui::CaptureMouseFromApp();
             gContext.mbUsing = true;
             gContext.mbUsing = true;
             gContext.mCurrentOperation = type;
             gContext.mCurrentOperation = type;
             const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.up, -gContext.mCameraDir };
             const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.up, -gContext.mCameraDir };
@@ -1420,8 +1512,9 @@ namespace ImGuizmo
       {
       {
          // find new possible way to scale
          // find new possible way to scale
          type = GetScaleType();
          type = GetScaleType();
-         if (io.MouseDown[0] && type != NONE)
+         if (CanActivate() && type != NONE)
          {
          {
+            ImGui::CaptureMouseFromApp();
             gContext.mbUsing = true;
             gContext.mbUsing = true;
             gContext.mCurrentOperation = type;
             gContext.mCurrentOperation = type;
             const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.up, gContext.mModel.v.right, -gContext.mCameraDir };
             const vec_t movePlanNormal[] = { gContext.mModel.v.up, gContext.mModel.v.dir, gContext.mModel.v.right, gContext.mModel.v.dir, gContext.mModel.v.up, gContext.mModel.v.right, -gContext.mCameraDir };
@@ -1440,6 +1533,7 @@ namespace ImGuizmo
       // scale
       // scale
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
+         ImGui::CaptureMouseFromApp();
          const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
          const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mTranslationPlan);
          vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
          vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
          vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;
          vec_t newOrigin = newPos - gContext.mRelativeOrigin * gContext.mScreenFactor;
@@ -1459,7 +1553,7 @@ namespace ImGuizmo
             gContext.mScale[axisIndex] = max(ratio, 0.001f);
             gContext.mScale[axisIndex] = max(ratio, 0.001f);
          }
          }
          else
          else
-         {			
+         {            
             float scaleDelta = (io.MousePos.x - gContext.mSaveMousePosx)  * 0.01f;
             float scaleDelta = (io.MousePos.x - gContext.mSaveMousePosx)  * 0.01f;
             gContext.mScale.Set(max(1.f + scaleDelta, 0.001f));
             gContext.mScale.Set(max(1.f + scaleDelta, 0.001f));
          }
          }
@@ -1503,14 +1597,15 @@ namespace ImGuizmo
       if (!gContext.mbUsing)
       if (!gContext.mbUsing)
       {
       {
          type = GetRotateType();
          type = GetRotateType();
-      
+
          if (type == ROTATE_SCREEN)
          if (type == ROTATE_SCREEN)
          {
          {
             applyRotationLocaly = true;
             applyRotationLocaly = true;
          }
          }
             
             
-         if (io.MouseDown[0] && type != NONE)
+         if (CanActivate() && type != NONE)
          {
          {
+            ImGui::CaptureMouseFromApp();
             gContext.mbUsing = true;
             gContext.mbUsing = true;
             gContext.mCurrentOperation = type;
             gContext.mCurrentOperation = type;
             const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };
             const vec_t rotatePlanNormal[] = { gContext.mModel.v.right, gContext.mModel.v.up, gContext.mModel.v.dir, -gContext.mCameraDir };
@@ -1534,6 +1629,7 @@ namespace ImGuizmo
       // rotation
       // rotation
       if (gContext.mbUsing)
       if (gContext.mbUsing)
       {
       {
+         ImGui::CaptureMouseFromApp();
          gContext.mRotationAngle = ComputeAngleOnPlan();
          gContext.mRotationAngle = ComputeAngleOnPlan();
          if (snap)
          if (snap)
          {
          {
@@ -1638,41 +1734,41 @@ namespace ImGuizmo
       int type = NONE;
       int type = NONE;
       if (gContext.mbEnable)
       if (gContext.mbEnable)
       {
       {
-		  if (!gContext.mbUsingBounds)
-		  {
-			  switch (operation)
-			  {
-			  case ROTATE:
-				  HandleRotation(matrix, deltaMatrix, type, snap);
-				  break;
-			  case TRANSLATE:
-				  HandleTranslation(matrix, deltaMatrix, type, snap);
-				  break;
-			  case SCALE:
-				  HandleScale(matrix, deltaMatrix, type, snap);
-				  break;
-			  }
-		  }
+          if (!gContext.mbUsingBounds)
+          {
+              switch (operation)
+              {
+              case ROTATE:
+                  HandleRotation(matrix, deltaMatrix, type, snap);
+                  break;
+              case TRANSLATE:
+                  HandleTranslation(matrix, deltaMatrix, type, snap);
+                  break;
+              case SCALE:
+                  HandleScale(matrix, deltaMatrix, type, snap);
+                  break;
+              }
+          }
       }
       }
 
 
-	  if (localBounds && !gContext.mbUsing)
-		  HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
-
-	  if (!gContext.mbUsingBounds)
-	  {
-		  switch (operation)
-		  {
-		  case ROTATE:
-			  DrawRotationGizmo(type);
-			  break;
-		  case TRANSLATE:
-			  DrawTranslationGizmo(type);
-			  break;
-		  case SCALE:
-			  DrawScaleGizmo(type);
-			  break;
-		  }
-	  }
+      if (localBounds && !gContext.mbUsing)
+          HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
+
+      if (!gContext.mbUsingBounds)
+      {
+          switch (operation)
+          {
+          case ROTATE:
+              DrawRotationGizmo(type);
+              break;
+          case TRANSLATE:
+              DrawTranslationGizmo(type);
+              break;
+          case SCALE:
+              DrawScaleGizmo(type);
+              break;
+          }
+      }
    }
    }
 
 
    void DrawCube(const float *view, const float *projection, float *matrix)
    void DrawCube(const float *view, const float *projection, float *matrix)