Merge pull request #41 from Ybalrid/pr_upgrade_imgui_imguizmo_raytrace

Upgraded dear imgui and ImGuizmo to the latest version
This commit is contained in:
Syoyo Fujita 2018-03-03 00:43:18 +09:00 committed by GitHub
commit c14616d21c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 9351 additions and 4284 deletions

View File

@ -21,7 +21,9 @@
// SOFTWARE. // SOFTWARE.
#include "imgui.h" #include "imgui.h"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "imgui_internal.h" #include "imgui_internal.h"
#include "ImGuizmo.h" #include "ImGuizmo.h"
@ -65,6 +67,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
@ -86,7 +90,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;
@ -99,7 +103,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;
@ -147,7 +151,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)
@ -188,7 +191,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); }
@ -491,7 +494,7 @@ namespace ImGuizmo
SCALE_Y, SCALE_Y,
SCALE_Z, SCALE_Z,
SCALE_XYZ, SCALE_XYZ,
BOUNDS BOUNDS
}; };
struct Context struct Context
@ -520,6 +523,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;
@ -551,23 +555,25 @@ namespace ImGuizmo
bool mBelowPlaneLimit[3]; bool mBelowPlaneLimit[3];
float mAxisFactor[3]; float mAxisFactor[3];
// bounds stretching // bounds stretching
vec_t mBoundsPivot; vec_t mBoundsPivot;
vec_t mBoundsAnchor; vec_t mBoundsAnchor;
vec_t mBoundsPlan; vec_t mBoundsPlan;
vec_t mBoundsLocalPivot; vec_t mBoundsLocalPivot;
int mBoundsBestAxis; int mBoundsBestAxis;
int mBoundsAxis[2]; int mBoundsAxis[2];
bool mbUsingBounds; bool mbUsingBounds;
matrix_t mBoundsMatrix; matrix_t mBoundsMatrix;
// //
int mCurrentOperation; int mCurrentOperation;
float mX = 0.f; float mX = 0.f;
float mY = 0.f; float mY = 0.f;
float mWidth = 0.f; float mWidth = 0.f;
float mHeight = 0.f; float mHeight = 0.f;
float mXMax = 0.f;
float mYMax = 0.f;
}; };
static Context gContext; static Context gContext;
@ -577,7 +583,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" };
@ -598,18 +608,16 @@ namespace ImGuizmo
static ImVec2 worldToPos(const vec_t& worldPos, const matrix_t& mat) static ImVec2 worldToPos(const vec_t& worldPos, const matrix_t& mat)
{ {
//ImGuiIO& io = ImGui::GetIO();
vec_t trans; vec_t trans;
trans.TransformPoint(worldPos, mat); trans.TransformPoint(worldPos, mat);
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.x *= gContext.mWidth;
trans.y *= gContext.mHeight; trans.y *= gContext.mHeight;
trans.x += gContext.mX; trans.x += gContext.mX;
trans.y += gContext.mY; trans.y += gContext.mY;
return ImVec2(trans.x, trans.y); return ImVec2(trans.x, trans.y);
} }
static void ComputeCameraRay(vec_t &rayOrigin, vec_t &rayDir) static void ComputeCameraRay(vec_t &rayOrigin, vec_t &rayDir)
@ -619,8 +627,8 @@ 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 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 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;
@ -641,23 +649,38 @@ 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.mX = x;
gContext.mY = y; gContext.mY = y;
gContext.mWidth = width; gContext.mWidth = width;
gContext.mHeight = height; 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()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui::Begin("gizmo", NULL, io.DisplaySize, 0, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus); const ImU32 flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus;
ImGui::SetNextWindowSize(io.DisplaySize);
gContext.mDrawList = ImGui::GetWindowDrawList();
ImGui::PushStyleColor(ImGuiCol_WindowBg, 0);
ImGui::Begin("gizmo", NULL, flags);
gContext.mDrawList = ImGui::GetWindowDrawList();
ImGui::End(); ImGui::End();
ImGui::PopStyleColor();
} }
bool IsUsing() bool IsUsing()
@ -673,11 +696,11 @@ namespace ImGuizmo
void Enable(bool enable) void Enable(bool enable)
{ {
gContext.mbEnable = enable; gContext.mbEnable = enable;
if (!enable) if (!enable)
{ {
gContext.mbUsing = false; gContext.mbUsing = false;
gContext.mbUsingBounds = 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)
@ -738,7 +761,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:
@ -751,8 +775,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
@ -848,7 +870,6 @@ namespace ImGuizmo
static void DrawRotationGizmo(int type) static void DrawRotationGizmo(int type)
{ {
ImDrawList* drawList = gContext.mDrawList; ImDrawList* drawList = gContext.mDrawList;
//ImGuiIO& io = ImGui::GetIO();
// colors // colors
ImU32 colors[7]; ImU32 colors[7];
@ -857,6 +878,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];
@ -870,9 +892,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);
} }
drawList->AddPolyline(circlePos, halfCircleSegmentCount, colors[3 - axis], false, 2, true);
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);
} }
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)
{ {
@ -889,8 +916,8 @@ namespace ImGuizmo
pos *= gContext.mScreenFactor; pos *= gContext.mScreenFactor;
circlePos[i] = worldToPos(pos + gContext.mModel.v.position, gContext.mViewProjection); circlePos[i] = worldToPos(pos + gContext.mModel.v.position, gContext.mViewProjection);
} }
drawList->AddConvexPolyFilled(circlePos, halfCircleSegmentCount, 0x801080FF, true); drawList->AddConvexPolyFilled(circlePos, halfCircleSegmentCount, 0x801080FF);
drawList->AddPolyline(circlePos, halfCircleSegmentCount, 0xFF1080FF, true, 2, true); drawList->AddPolyline(circlePos, halfCircleSegmentCount, 0xFF1080FF, true, 2);
ImVec2 destinationPosOnScreen = circlePos[1]; ImVec2 destinationPosOnScreen = circlePos[1];
char tmps[512]; char tmps[512];
@ -918,9 +945,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 };
@ -942,18 +966,21 @@ namespace ImGuizmo
if (gContext.mbUsing) if (gContext.mbUsing)
{ {
drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 6.f); drawList->AddLine(baseSSpace, worldDirSSpaceNoScale, 0xFF404040, 3.f);
drawList->AddCircleFilled(worldDirSSpaceNoScale, 10.f, 0xFF404040); drawList->AddCircleFilled(worldDirSSpaceNoScale, 6.f, 0xFF404040);
} }
drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 6.f); drawList->AddLine(baseSSpace, worldDirSSpace, colors[i + 1], 3.f);
drawList->AddCircleFilled(worldDirSSpace, 10.f, colors[i + 1]); 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)
{ {
//ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection); //ImVec2 sourcePosOnScreen = worldToPos(gContext.mMatrixOrigin, gContext.mViewProjection);
@ -978,21 +1005,21 @@ namespace ImGuizmo
static void DrawTranslationGizmo(int type) static void DrawTranslationGizmo(int type)
{ {
ImDrawList* drawList = gContext.mDrawList; ImDrawList* drawList = gContext.mDrawList;
if (!drawList) if (!drawList)
return; return;
// colors // colors
ImU32 colors[7]; ImU32 colors[7];
ComputeColors(colors, type, TRANSLATE); ComputeColors(colors, type, TRANSLATE);
// draw screen quad const ImVec2 origin = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
drawList->AddRectFilled(gContext.mScreenSquareMin, gContext.mScreenSquareMax, colors[0], 2.f);
// 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
@ -1001,7 +1028,19 @@ 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);
@ -1011,15 +1050,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->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4], true); drawList->AddPolyline(screenQuadPts, 4, planeBorderColor[i], true, 1.0f);
drawList->AddConvexPolyFilled(screenQuadPts, 4, colors[i + 4]);
} }
} }
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);
@ -1040,176 +1082,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(); ImGuiIO& io = ImGui::GetIO();
ImDrawList* drawList = gContext.mDrawList; ImDrawList* drawList = gContext.mDrawList;
// compute best projection axis // compute best projection axis
vec_t bestAxisWorldDirection; vec_t axesWorldDirections[3];
int bestAxis = gContext.mBoundsBestAxis; vec_t bestAxisWorldDirection = { 0.0f, 0.0f, 0.0f, 0.0f };
if (!gContext.mbUsingBounds) 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 bestDot = 0.f; float dt = fabsf( Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld) );
for (unsigned int i = 0; i < 3; i++) if ( dt >= bestDot )
{ {
vec_t dirPlaneNormalWorld; bestDot = dt;
dirPlaneNormalWorld.TransformVector(directionUnary[i], gContext.mModelSource); bestAxis = i;
dirPlaneNormalWorld.Normalize(); bestAxisWorldDirection = dirPlaneNormalWorld;
}
float dt = Dot(Normalized(gContext.mCameraEye - gContext.mModelSource.v.position), dirPlaneNormalWorld); if( dt >= 0.1f )
if (fabsf(dt) >= bestDot) {
{ axes[numAxes] = i;
bestDot = fabsf(dt); axesWorldDirections[numAxes] = dirPlaneNormalWorld;
bestAxis = i; ++numAxes;
bestAxisWorldDirection = dirPlaneNormalWorld; }
} }
} }
}
// corners if( numAxes == 0 )
vec_t aabb[4]; {
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;
}
int secondAxis = (bestAxis + 1) % 3; for (unsigned int axisIndex = 0; axisIndex < numAxes; ++axisIndex)
int thirdAxis = (bestAxis + 2) % 3; {
bestAxis = axes[axisIndex];
bestAxisWorldDirection = axesWorldDirections[axisIndex];
for (int i = 0; i < 4; i++) // corners
{ vec_t aabb[4];
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 int secondAxis = (bestAxis + 1) % 3;
unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000; int thirdAxis = (bestAxis + 2) % 3;
matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection; for (int i = 0; i < 4; i++)
for (int i = 0; i < 4;i++) {
{ aabb[i][3] = aabb[i][bestAxis] = 0.f;
ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP); aabb[i][secondAxis] = bounds[secondAxis + 3 * (i >> 1)];
ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP); aabb[i][thirdAxis] = bounds[thirdAxis + 3 * ((i >> 1) ^ (i & 1))];
float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2)); }
int stepCount = (int)(boundDistance / 10.f);
float stepLength = 1.f / (float)stepCount; // draw bounds
for (int j = 0; j < stepCount; j++) unsigned int anchorAlpha = gContext.mbEnable ? 0xFF000000 : 0x80000000;
{
float t1 = (float)j * stepLength; matrix_t boundsMVP = gContext.mModelSource * gContext.mViewProjection;
float t2 = (float)j * stepLength + stepLength * 0.5f; for (int i = 0; i < 4;i++)
ImVec2 worldBoundSS1 = ImLerp(worldBound1, worldBound2, ImVec2(t1, t1)); {
ImVec2 worldBoundSS2 = ImLerp(worldBound1, worldBound2, ImVec2(t2, t2)); ImVec2 worldBound1 = worldToPos(aabb[i], boundsMVP);
drawList->AddLine(worldBoundSS1, worldBoundSS2, 0xAAAAAA + anchorAlpha, 3.f); ImVec2 worldBound2 = worldToPos(aabb[(i+1)%4], boundsMVP);
} if( !IsInContextRect( worldBound1 ) || !IsInContextRect( worldBound2 ) )
vec_t midPoint = (aabb[i] + aabb[(i + 1) % 4] ) * 0.5f; {
ImVec2 midBound = worldToPos(midPoint, boundsMVP); continue;
static const float AnchorBigRadius = 8.f; }
static const float AnchorSmallRadius = 6.f; float boundDistance = sqrtf(ImLengthSqr(worldBound1 - worldBound2));
bool overBigAnchor = ImLengthSqr(worldBound1 - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius); int stepCount = (int)(boundDistance / 10.f);
bool overSmallAnchor = ImLengthSqr(midBound - io.MousePos) <= (AnchorBigRadius*AnchorBigRadius); 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 bigAnchorColor = overBigAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha); unsigned int smallAnchorColor = overSmallAnchor ? selectionColor : (0xAAAAAA + anchorAlpha);
drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor); drawList->AddCircleFilled(worldBound1, AnchorBigRadius, bigAnchorColor);
drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor); drawList->AddCircleFilled(midBound, AnchorSmallRadius, smallAnchorColor);
int oppositeIndex = (i + 2) % 4; int oppositeIndex = (i + 2) % 4;
// big anchor on corners // big anchor on corners
if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && io.MouseDown[0]) if (!gContext.mbUsingBounds && gContext.mbEnable && overBigAnchor && CanActivate())
{ {
gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource); gContext.mBoundsPivot.TransformPoint(aabb[(i + 2) % 4], gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource); gContext.mBoundsAnchor.TransformPoint(aabb[i], gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection); gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis; gContext.mBoundsBestAxis = bestAxis;
gContext.mBoundsAxis[0] = secondAxis; gContext.mBoundsAxis[0] = secondAxis;
gContext.mBoundsAxis[1] = thirdAxis; gContext.mBoundsAxis[1] = thirdAxis;
gContext.mBoundsLocalPivot.Set(0.f); gContext.mBoundsLocalPivot.Set(0.f);
gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis]; gContext.mBoundsLocalPivot[secondAxis] = aabb[oppositeIndex][secondAxis];
gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis]; gContext.mBoundsLocalPivot[thirdAxis] = aabb[oppositeIndex][thirdAxis];
gContext.mbUsingBounds = true; gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource; gContext.mBoundsMatrix = gContext.mModelSource;
} }
// small anchor on middle of segment // small anchor on middle of segment
if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && io.MouseDown[0]) if (!gContext.mbUsingBounds && gContext.mbEnable && overSmallAnchor && CanActivate())
{ {
vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f; vec_t midPointOpposite = (aabb[(i + 2) % 4] + aabb[(i + 3) % 4]) * 0.5f;
gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource); gContext.mBoundsPivot.TransformPoint(midPointOpposite, gContext.mModelSource);
gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource); gContext.mBoundsAnchor.TransformPoint(midPoint, gContext.mModelSource);
gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection); gContext.mBoundsPlan = BuildPlan(gContext.mBoundsAnchor, bestAxisWorldDirection);
gContext.mBoundsBestAxis = bestAxis; gContext.mBoundsBestAxis = bestAxis;
int indices[] = { secondAxis , thirdAxis }; int indices[] = { secondAxis , thirdAxis };
gContext.mBoundsAxis[0] = indices[i%2]; gContext.mBoundsAxis[0] = indices[i%2];
gContext.mBoundsAxis[1] = -1; gContext.mBoundsAxis[1] = -1;
gContext.mBoundsLocalPivot.Set(0.f); 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.mBoundsLocalPivot[gContext.mBoundsAxis[0]] = aabb[oppositeIndex][indices[i % 2]];// bounds[gContext.mBoundsAxis[0]] * (((i + 1) & 2) ? 1.f : -1.f);
gContext.mbUsingBounds = true; gContext.mbUsingBounds = true;
gContext.mBoundsMatrix = gContext.mModelSource; gContext.mBoundsMatrix = gContext.mModelSource;
} }
} }
if (gContext.mbUsingBounds) if (gContext.mbUsingBounds)
{ {
matrix_t scale; matrix_t scale;
scale.SetToIdentity(); scale.SetToIdentity();
// compute projected mouse position on plan // compute projected mouse position on plan
const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan); const float len = IntersectRayPlane(gContext.mRayOrigin, gContext.mRayVector, gContext.mBoundsPlan);
vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len; vec_t newPos = gContext.mRayOrigin + gContext.mRayVector * len;
// compute a reference and delta vectors base on mouse move // compute a reference and delta vectors base on mouse move
vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs(); vec_t deltaVector = (newPos - gContext.mBoundsPivot).Abs();
vec_t referenceVector = (gContext.mBoundsAnchor - 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 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++) for (int i = 0; i < 2; i++)
{ {
int axisIndex = gContext.mBoundsAxis[i]; int axisIndex1 = gContext.mBoundsAxis[i];
if (axisIndex == -1) if (axisIndex1 == -1)
continue; continue;
float ratioAxis = 1.f; float ratioAxis = 1.f;
vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex].Abs(); vec_t axisDir = gContext.mBoundsMatrix.component[axisIndex1].Abs();
float dtAxis = axisDir.Dot(referenceVector); float dtAxis = axisDir.Dot(referenceVector);
float boundSize = bounds[axisIndex + 3] - bounds[axisIndex]; float boundSize = bounds[axisIndex1 + 3] - bounds[axisIndex1];
if (dtAxis > FLT_EPSILON) if (dtAxis > FLT_EPSILON)
ratioAxis = axisDir.Dot(deltaVector) / dtAxis; ratioAxis = axisDir.Dot(deltaVector) / dtAxis;
if (snapValues) if (snapValues)
{ {
float length = boundSize * ratioAxis; float length = boundSize * ratioAxis;
ComputeSnap(&length, snapValues[axisIndex]); ComputeSnap(&length, snapValues[axisIndex1]);
if (boundSize > FLT_EPSILON) if (boundSize > FLT_EPSILON)
ratioAxis = length / boundSize; ratioAxis = length / boundSize;
} }
scale.component[axisIndex] *= ratioAxis; scale.component[axisIndex1] *= ratioAxis;
} }
// transform matrix // transform matrix
matrix_t preScale, postScale; matrix_t preScale, postScale;
preScale.Translation(-gContext.mBoundsLocalPivot); preScale.Translation(-gContext.mBoundsLocalPivot);
postScale.Translation(gContext.mBoundsLocalPivot); postScale.Translation(gContext.mBoundsLocalPivot);
matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix; matrix_t res = preScale * scale * postScale * gContext.mBoundsMatrix;
*matrix = res; *matrix = res;
// info text // info text
char tmps[512]; char tmps[512];
ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection); ImVec2 destinationPosOnScreen = worldToPos(gContext.mModel.v.position, gContext.mViewProjection);
ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f" ImFormatString(tmps, sizeof(tmps), "X: %.2f Y: %.2f Z:%.2f"
, (bounds[3] - bounds[0]) * gContext.mBoundsMatrix.component[0].Length() * scale.component[0].Length() , (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[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() , (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 + 15, destinationPosOnScreen.y + 15), 0xFF000000, tmps);
drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps); drawList->AddText(ImVec2(destinationPosOnScreen.x + 14, destinationPosOnScreen.y + 14), 0xFFFFFFFF, tmps);
} }
if (!io.MouseDown[0]) if (!io.MouseDown[0])
gContext.mbUsingBounds = false; gContext.mbUsingBounds = false;
if( gContext.mbUsingBounds )
break;
}
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1255,7 +1354,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};
@ -1327,6 +1426,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;
@ -1385,8 +1485,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 };
@ -1409,8 +1510,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 };
@ -1429,6 +1531,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;
@ -1498,8 +1601,9 @@ namespace ImGuizmo
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 };
@ -1523,6 +1627,7 @@ namespace ImGuizmo
// rotation // rotation
if (gContext.mbUsing) if (gContext.mbUsing)
{ {
ImGui::CaptureMouseFromApp();
gContext.mRotationAngle = ComputeAngleOnPlan(); gContext.mRotationAngle = ComputeAngleOnPlan();
if (snap) if (snap)
{ {
@ -1627,41 +1732,41 @@ namespace ImGuizmo
int type = NONE; int type = NONE;
if (gContext.mbEnable) if (gContext.mbEnable)
{ {
if (!gContext.mbUsingBounds) if (!gContext.mbUsingBounds)
{ {
switch (operation) switch (operation)
{ {
case ROTATE: case ROTATE:
HandleRotation(matrix, deltaMatrix, type, snap); HandleRotation(matrix, deltaMatrix, type, snap);
break; break;
case TRANSLATE: case TRANSLATE:
HandleTranslation(matrix, deltaMatrix, type, snap); HandleTranslation(matrix, deltaMatrix, type, snap);
break; break;
case SCALE: case SCALE:
HandleScale(matrix, deltaMatrix, type, snap); HandleScale(matrix, deltaMatrix, type, snap);
break; break;
} }
} }
} }
if (localBounds && !gContext.mbUsing) if (localBounds && !gContext.mbUsing)
HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap); HandleAndDrawLocalBounds(localBounds, (matrix_t*)matrix, boundsSnap);
if (!gContext.mbUsingBounds) if (!gContext.mbUsingBounds)
{ {
switch (operation) switch (operation)
{ {
case ROTATE: case ROTATE:
DrawRotationGizmo(type); DrawRotationGizmo(type);
break; break;
case TRANSLATE: case TRANSLATE:
DrawTranslationGizmo(type); DrawTranslationGizmo(type);
break; break;
case SCALE: case SCALE:
DrawScaleGizmo(type); DrawScaleGizmo(type);
break; break;
} }
} }
} }
void DrawCube(const float *view, const float *projection, float *matrix) void DrawCube(const float *view, const float *projection, float *matrix)
@ -1713,7 +1818,7 @@ namespace ImGuizmo
continue; continue;
// draw face with lighter color // draw face with lighter color
gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080, true); gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080);
} }
} }
}; };

View File

@ -112,6 +112,9 @@ void EditTransform(const Camera& camera, matrix_t& matrix)
namespace ImGuizmo namespace ImGuizmo
{ {
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
IMGUI_API void SetDrawlist();
// call BeginFrame right after ImGui_XXXX_NewFrame(); // call BeginFrame right after ImGui_XXXX_NewFrame();
IMGUI_API void BeginFrame(); IMGUI_API void BeginFrame();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include "OpenGLWindow/X11OpenGLWindow.h" #include "OpenGLWindow/X11OpenGLWindow.h"
#endif #endif
#include <imgui_internal.h>
#include <cstdio> #include <cstdio>
#define IMGUI_B3G_CONTROL (300) #define IMGUI_B3G_CONTROL (300)
@ -122,12 +123,12 @@ void ImGui_ImplBtGui_RenderDrawLists(ImDrawData* draw_data) {
(GLsizei)last_viewport[3]); (GLsizei)last_viewport[3]);
} }
static const char* ImGui_ImplBtGui_GetClipboardText() { static const char* ImGui_ImplBtGui_GetClipboardText(void* user_ctx) {
// @todo // @todo
return NULL; // glfwGetClipboardString(g_Window); return NULL; // glfwGetClipboardString(g_Window);
} }
static void ImGui_ImplBtGui_SetClipboardText(const char* text) { static void ImGui_ImplBtGui_SetClipboardText(void* user_ctx, const char* text) {
// @todo // @todo
return; return;
// glfwSetClipboardString(g_Window, text); // glfwSetClipboardString(g_Window, text);
@ -259,7 +260,7 @@ bool ImGui_ImplBtGui_Init(b3gDefaultOpenGLWindow* window) {
io.SetClipboardTextFn = ImGui_ImplBtGui_SetClipboardText; io.SetClipboardTextFn = ImGui_ImplBtGui_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplBtGui_GetClipboardText; io.GetClipboardTextFn = ImGui_ImplBtGui_GetClipboardText;
#ifdef _WIN32 #ifdef _WIN32
//io.ImeWindowHandle = glfwGetWin32Window(g_Window); // io.ImeWindowHandle = glfwGetWin32Window(g_Window);
#endif #endif
#if 0 #if 0
@ -277,7 +278,7 @@ bool ImGui_ImplBtGui_Init(b3gDefaultOpenGLWindow* window) {
void ImGui_ImplBtGui_Shutdown() { void ImGui_ImplBtGui_Shutdown() {
ImGui_ImplBtGui_InvalidateDeviceObjects(); ImGui_ImplBtGui_InvalidateDeviceObjects();
ImGui::Shutdown(); ImGui::Shutdown(ImGui::GetCurrentContext());
} }
void ImGui_ImplBtGui_NewFrame(int mouse_x, int mouse_y) { void ImGui_ImplBtGui_NewFrame(int mouse_x, int mouse_y) {

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@ THE SOFTWARE.
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <fstream>
#include <iostream> #include <iostream>
#include <limits> #include <limits>
#include <map> #include <map>
@ -338,6 +339,8 @@ void keyboardCallback(int keycode, int state) {
void mouseMoveCallback(float x, float y) { void mouseMoveCallback(float x, float y) {
if (gMouseLeftDown) { if (gMouseLeftDown) {
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) { if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
gSceneDirty = true;
// RequestRender();
} else { } else {
float w = static_cast<float>(gRenderConfig.width); float w = static_cast<float>(gRenderConfig.width);
float h = static_cast<float>(gRenderConfig.height); float h = static_cast<float>(gRenderConfig.height);
@ -376,26 +379,29 @@ void mouseButtonCallback(int button, int state, float x, float y) {
(void)y; (void)y;
ImGui_ImplBtGui_SetMouseButtonState(button, (state == 1)); ImGui_ImplBtGui_SetMouseButtonState(button, (state == 1));
if (button == 0 && !state)
gMouseLeftDown = false; // prevent sticky trackball after using gizmo
ImGuiIO &io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
if (io.WantCaptureMouse || io.WantCaptureKeyboard) { if (io.WantCaptureMouse || io.WantCaptureKeyboard) {
return; if (button == 0 && !state) {
} if (ImGuizmo::IsUsing()) {
// left button
if (button == 0) {
if (state) {
gMouseLeftDown = true;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
} else {
trackball(gPrevQuat, 0.0f, 0.0f, 0.0f, 0.0f);
}
} else {
gMouseLeftDown = false;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
gSceneDirty = true; gSceneDirty = true;
RequestRender(); RequestRender();
} }
} }
} else {
// left button
if (button == 0) {
if (state) {
gMouseLeftDown = true;
if (ImGuizmo::IsOver() || ImGuizmo::IsUsing()) {
} else {
trackball(gPrevQuat, 0.0f, 0.0f, 0.0f, 0.0f);
}
} else {
}
}
} }
} }
@ -762,10 +768,36 @@ int main(int argc, char **argv) {
} }
} }
if (textures.size() > 0) {
materials[0].diffuse_texid = 0;
}
gAsset.materials = materials; gAsset.materials = materials;
gAsset.default_material = default_material; gAsset.default_material = default_material;
gAsset.textures = textures; gAsset.textures = textures;
#ifdef _DEBUG
// output raw data as RGB ASCII PPM file
if (textures.size() > 0) {
std::ofstream output(
"./"
"debug"
".ppm");
if (output) {
output << "P3\n#sampleOutputDebug\n";
example::Texture &t = textures[0];
output << t.width << ' ' << t.height << "\n#imgSize\n255\n";
for (size_t i{0}; i < t.width * t.height * t.components;
i += t.components) {
for (size_t j{0}; j < 3; ++j)
output << size_t(t.image[i + j]) << '\n';
}
}
}
#endif
for (size_t n = 0; n < meshes.size(); n++) { for (size_t n = 0; n < meshes.size(); n++) {
size_t mesh_id = gAsset.meshes.size(); size_t mesh_id = gAsset.meshes.size();
gAsset.meshes.push_back(meshes[mesh_id]); gAsset.meshes.push_back(meshes[mesh_id]);
@ -872,6 +904,7 @@ int main(int argc, char **argv) {
window->setResizeCallback(resizeCallback); window->setResizeCallback(resizeCallback);
checkErrors("resize"); checkErrors("resize");
ImGui::CreateContext();
ImGui_ImplBtGui_Init(window); ImGui_ImplBtGui_Init(window);
ImGuiIO &io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();