419 ImGuiIO& io = ImGui::GetIO();
420 ImGuiStyle& style = ImGui::GetStyle();
421 ImDrawList* draw_list = ImGui::GetWindowDrawList();
432 const float arrowBgn = -1.0f, arrowEnd = 1.0f;
442 ImGui::PushID(label);
445 bool value_changed =
false;
447 ImVec2 controlPos(ImGui::GetCursorScreenPos());
449 const float squareSize = size;
450 const float halfSquareSize = squareSize*.5;
451 const ImVec2 innerSize(squareSize,squareSize);
453 bool highlighted =
false;
454 ImGui::InvisibleButton(
"imguiGizmo", innerSize);
456 bool vgModsActive =
false;
469 auto getTrackball = [&] (
quat &q) {
470 ImVec2 mouse = ImGui::GetMousePos() - controlPos;
472 track.viewportSize(innerSize.x, innerSize.y);
473 track.setRotation(q);
475#ifndef IMGUIZMO_USE_ONLY_ROT
477 float screenFactor = 1.f/(io.DisplaySize.x<io.DisplaySize.y ? io.DisplaySize.x : io.DisplaySize.y);
483 track.
wheel(0.f, io.MouseWheel);
489 track.imGuIZMO_BASE_CLASS::motionImmediateMode(mouse.x, mouse.y, io.MouseDelta.x, io.MouseDelta.y, vgMods);
490 q = track.getRotation();
494 q = track.getRotation();
496 value_changed =
true;
500 if (ImGui::IsItemActive()) {
502 if(ImGui::IsMouseDragging(0)) getTrackball(
qtV);
506 ImColor col(style.Colors[ImGuiCol_FrameBgActive]);
507 col.Value.w*=ImGui::GetStyle().Alpha;
508 draw_list->AddRectFilled(controlPos, controlPos + innerSize, col, style.FrameRounding);
510 highlighted = ImGui::IsItemHovered();
512 else if(highlighted && (
drawMode&
modeDual) && ImGui::IsMouseDragging(2)) { getTrackball(
qtV); getTrackball(
qtV2); }
513#ifndef IMGUIZMO_USE_ONLY_ROT
514 else if(highlighted && io.MouseWheel!=0) getTrackball(
qtV);
517 ImColor col(highlighted ? style.Colors[ImGuiCol_FrameBgHovered]: style.Colors[ImGuiCol_FrameBg]);
518 col.Value.w*=ImGui::GetStyle().Alpha;
519 draw_list->AddRectFilled(controlPos, controlPos + innerSize, col, style.FrameRounding);
523 draw_list->PushClipRect(controlPos, controlPos + innerSize,
true);
525 const ImVec2 wpUV = ImGui::GetFontTexUvWhitePixel();
526 ImVec2 uv[4]; ImU32 col[4];
532 auto normalizeToControlSize = [&] (
float x,
float y) {
533 return controlPos + ImVec2(x,-y) * halfSquareSize + ImVec2(halfSquareSize,halfSquareSize);
536 auto returnSizeFromRatio = [&] (
float ratio) {
return squareSize * ratio; };
539 auto addTriangle = [&] ()
541 if(cross(
vec2(uv[1].x-uv[0].x, uv[1].y-uv[0].y),
542 vec2(uv[2].x-uv[0].x, uv[2].y-uv[0].y)) > 0) { uv[1] = uv[2] = uv[0]; }
544 for(
int i=0; i<3; i++) draw_list->PrimVtx(uv[i], wpUV, col[i]);
548 auto addQuad = [&] (ImU32 colLight)
550 if(cross(
vec2(uv[1].x-uv[0].x, uv[1].y-uv[0].y),
551 vec2(uv[3].x-uv[0].x, uv[3].y-uv[0].y)) > 0) { uv[3] = uv[1] = uv[2] = uv[0]; }
553 draw_list->PrimQuadUV(uv[0],uv[1],uv[2],uv[3], wpUV, wpUV, wpUV, wpUV, colLight);
557 auto drawSphere = [&] ()
562 for(
int h=0; h<3; h++, itTess++) {
565 uv[h] = normalizeToControlSize(coord.
x,coord.
y);
575 auto drawCube = [&] ()
580 vec3 norm = _q * *itNorm;
581 for(
int i = 0; i<4; ) {
583 uv[i++] = normalizeToControlSize(coord.
x,coord.
y);
590 auto drawPlane = [&] ()
595 vec3 norm = _q * *itNorm;
596 for(
int i = 0; i<4; ) {
598 uv[i++] = normalizeToControlSize(coord.
x,coord.
y);
606 auto drawAxes = [&] (
int side)
608 for(
int n = 0; n < 4; n++) {
609 for(
int arrowAxis = 0; arrowAxis < 3; arrowAxis++) {
610 vec3 arrowCoord(0.0f, 0.0f, 0.0f); arrowCoord[arrowAxis] = 1.0f;
611 const float arrowCoordZ =
vec3(_q*arrowCoord).
z;
613 const int i = (arrowCoordZ > 0) ? 3 - n : n;
617 if((side ==
backSide && arrowCoordZ > 0) || (side ==
frontSide && arrowCoordZ <= 0)) {
620 else skipCone =
false;
624 draw_list->PrimReserve(ptrVtx->size(), ptrVtx->size());
626 for(
auto itVtx = ptrVtx->begin(), itNorm = (
arrowNorm+i)->begin(); itVtx != ptrVtx->end(); ) {
627#if !defined(imguiGizmo_INTERPOLATE_NORMALS)
630 for(
int h=0; h<3; h++) {
631 vec3 coord(*itVtx++ * resizeAxes);
634 if(!skipCone && coord.
x > 0) coord.
x = -arrowStartingPoint;
635 if((skipCone && coord.
x <= 0) ||
636 (!
showFullAxes && (coord.
x < arrowStartingPoint)) ) coord.
x = arrowStartingPoint;
639 uv[h] = normalizeToControlSize(coord.
x,coord.
y);
640#ifdef imguiGizmo_INTERPOLATE_NORMALS
653 auto drawComponent = [&] (
const int idx,
const quat &q,
ptrFunc func)
656 draw_list->PrimReserve(ptrVtx->size(), ptrVtx->size());
657 for(
auto itVtx = ptrVtx->begin(), itNorm = (
arrowNorm+idx)->begin(); itVtx != ptrVtx->end(); ) {
658#if !defined(imguiGizmo_INTERPOLATE_NORMALS)
659 vec3 norm = (_q * *itNorm++);
661 for(
int h=0; h<3; h++) {
662 vec3 coord = *itVtx++;
663#ifdef imguiGizmo_INTERPOLATE_NORMALS
664 vec3 norm = (q * *itNorm++);
666 coord = q * (func(coord) * resizeAxes);
668 uv[h] = normalizeToControlSize(coord.
x,coord.
y);
678 auto dirArrow = [&] (
const quat &q,
int mode)
680 vec3 arrowCoord(_q *
vec3(1.0f, 0.0f, 0.0f));
684 if(arrowCoord.
z <= 0) {
for(
int i = 0; i < 4; i++) drawComponent(i, q, func);
if(mode &
modeDirPlane) drawPlane(); }
685 else {
if(mode &
modeDirPlane) drawPlane();
for(
int i = 3; i >= 0; i--) drawComponent(i, q, func); }
690 auto spotArrow = [&] (
const quat &q,
const float arrowCoordZ)
692 if(arrowCoordZ > 0) {
703 auto draw3DSystem = [&] ()
711#define CENTER_HELPER_X -.85f
712#define CENTER_HELPER_Y -.85f
714 auto drawRotationHelper = [&] () {
716 const float radius = returnSizeFromRatio(.05);
717 const int nSegments = 12;
722 draw_list->AddCircleFilled(center, radius, color, nSegments);
724 const float thickness = squareSize/100.f;
725 const float a_max = (IM_PI * 1.5f) * ((
float)nSegments) / (float)nSegments;
726 draw_list->PathClear();
727 draw_list->PathArcTo(center, radius - 0.5f, 0.0f, a_max, nSegments);
728 draw_list->PathStroke(color,
false, thickness);
730 const float lenLine = radius*.33f;
731 const float thickRadius = radius - thickness*.5;
732 draw_list->AddTriangleFilled(ImVec2(center.x-lenLine, center.y-(thickRadius+lenLine)),
733 ImVec2(center.x+lenLine, center.y- thickRadius),
734 ImVec2(center.x-lenLine, center.y-(thickRadius-lenLine)),
737 draw_list->AddTriangleFilled(ImVec2(center.x+(thickRadius-lenLine), center.y+lenLine),
738 ImVec2(center.x+ thickRadius , center.y-lenLine),
739 ImVec2(center.x+(thickRadius+lenLine), center.y+lenLine),
747 auto drawPanHelper = [&] () {
749 const float lenLine = returnSizeFromRatio(.05f);
750 const float halfLen = lenLine * .5f;
751 const float hhLen = halfLen * .5f;
752 const ImU32 color = 0xffffff00;
753 draw_list->AddTriangleFilled(ImVec2(center.x , center.y+lenLine+halfLen),
754 ImVec2(center.x-halfLen, center.y+lenLine-hhLen ),
755 ImVec2(center.x+halfLen, center.y+lenLine-hhLen ),
757 draw_list->AddTriangleFilled(ImVec2(center.x , center.y-lenLine-halfLen),
758 ImVec2(center.x-halfLen, center.y-lenLine+hhLen ),
759 ImVec2(center.x+halfLen, center.y-lenLine+hhLen ),
761 draw_list->AddTriangleFilled(ImVec2(center.x+lenLine+halfLen, center.y ),
762 ImVec2(center.x+lenLine-hhLen , center.y-halfLen),
763 ImVec2(center.x+lenLine-hhLen , center.y+halfLen),
765 draw_list->AddTriangleFilled(ImVec2(center.x-lenLine-halfLen, center.y ),
766 ImVec2(center.x-lenLine+hhLen , center.y-halfLen),
767 ImVec2(center.x-lenLine+hhLen , center.y+halfLen),
772 auto drawDollyHelper = [&] () {
774 const float lenLine = returnSizeFromRatio(.05f);
775 const float halfLen = lenLine * .5f;
776 const ImU32 color = 0xff00ffff;
777 draw_list->AddTriangleFilled(ImVec2(center.x , center.y+lenLine+halfLen),
778 ImVec2(center.x-lenLine, center.y+halfLen ),
779 ImVec2(center.x+lenLine, center.y+halfLen ),
781 draw_list->AddTriangleFilled(ImVec2(center.x , center.y-lenLine ),
782 ImVec2(center.x-halfLen, center.y-halfLen ),
783 ImVec2(center.x+halfLen, center.y-halfLen ),
795 if(spot.
z>0) { draw3DSystem(); spotArrow(normalize(
qtV2),spot.
z); }
796 else { spotArrow(normalize(
qtV2),spot.
z); draw3DSystem(); }
797 }
else draw3DSystem();
801 if(vgModsActive && (ImGui::IsItemHovered() && (!ImGui::IsMouseDown(0) && !ImGui::IsMouseDown(1)) )) {
802#ifndef IMGUIZMO_USE_ONLY_ROT
804 if(
panMod & vgMods) drawPanHelper();
805 else if(
dollyMod & vgMods) drawDollyHelper();
807 drawRotationHelper();
810 drawRotationHelper();
815 ImGui::SetCursorScreenPos(controlPos);
816 if(label[0]!=
'#' && label[1]!=
'#') ImGui::Text(
"%s", label);
818 draw_list->PopClipRect();
823 return value_changed;