gizmo test
This commit is contained in:
@@ -191,6 +191,7 @@ endif()
|
||||
|
||||
add_subdirectory (src/external/qt-color-widgets)
|
||||
add_subdirectory (src/external/framelesshelper)
|
||||
add_subdirectory (src/external/qtimgui)
|
||||
|
||||
# Add the found include directories to our include list.
|
||||
include_directories (SYSTEM "${CMAKE_SOURCE_DIR}/include/")
|
||||
@@ -224,6 +225,7 @@ INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/external/PNG2BLP/libpng" )
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/external/PNG2BLP/libtxc_dxtn" )
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/external/PNG2BLP/pngpp" )
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/external/PNG2BLP/zlib" )
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/external/imguizmo" )
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
COLLECT_FILES(false noggit_root_sources src/noggit .cpp)
|
||||
@@ -232,6 +234,7 @@ COLLECT_FILES(false math_sources src/math .cpp)
|
||||
COLLECT_FILES(false opengl_sources src/opengl .cpp)
|
||||
COLLECT_FILES(true red_sources src/noggit/Red .cpp)
|
||||
COLLECT_FILES(true png_blp_sources src/external/PNG2BLP ".c;.cpp;")
|
||||
COLLECT_FILES(false imguizmo_sources src/external/imguizmo ".c;.cpp;")
|
||||
set ( util_sources
|
||||
src/util/exception_to_string.cpp
|
||||
)
|
||||
@@ -242,6 +245,7 @@ COLLECT_FILES(false opengl_headers src/opengl ".h;.hpp")
|
||||
COLLECT_FILES(false shaders src/glsl .glsl)
|
||||
COLLECT_FILES(true red_headers src/noggit/Red ".hpp;.inl")
|
||||
COLLECT_FILES(true png_blp_headers src/external/PNG2BLP ".h;.hpp;")
|
||||
COLLECT_FILES(false imguizmo_headers src/external/imguizmo ".h;.hpp;")
|
||||
|
||||
IF(WIN32)
|
||||
set ( os_sources
|
||||
@@ -274,6 +278,7 @@ source_group("util" FILES ${util_sources})
|
||||
source_group("glsl" FILES ${shaders})
|
||||
source_group("noggit/Red" FILES ${red_headers} ${red_sources})
|
||||
source_group("png_blp" FILES ${png_blp_headers} ${png_blp_sources})
|
||||
source_group("imguizmo" FILES ${imguizmo_headers} ${imguizmo_sources})
|
||||
|
||||
COLLECT_FILES(false resource_files resources .qrc)
|
||||
qt5_add_resources (compiled_resource_files ${resource_files})
|
||||
@@ -293,6 +298,7 @@ ADD_EXECUTABLE ( noggit
|
||||
${util_sources}
|
||||
${red_sources}
|
||||
${png_blp_sources}
|
||||
${imguizmo_sources}
|
||||
${noggit_root_headers}
|
||||
${noggit_ui_headers}
|
||||
${opengl_headers}
|
||||
@@ -304,6 +310,7 @@ ADD_EXECUTABLE ( noggit
|
||||
${ResFiles}
|
||||
${moced}
|
||||
${red_headers}
|
||||
${imguizmo_headers}
|
||||
${compiled_resource_files}
|
||||
${compiled_ui_files}
|
||||
${shaders}
|
||||
@@ -321,6 +328,7 @@ TARGET_LINK_LIBRARIES (noggit
|
||||
Qt5::OpenGLExtensions
|
||||
ColorWidgets-qt5
|
||||
FramelessHelper
|
||||
qt_imgui_widgets
|
||||
)
|
||||
|
||||
set (_noggit_revision_output_dir "${CMAKE_BINARY_DIR}/revision_output")
|
||||
|
||||
429
src/external/imguizmo/ImCurveEdit.cpp
vendored
Normal file
429
src/external/imguizmo/ImCurveEdit.cpp
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
#include "ImCurveEdit.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include <stdint.h>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#define _malloca(x) alloca(x)
|
||||
#endif
|
||||
|
||||
namespace ImCurveEdit
|
||||
{
|
||||
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
static ImVec2 operator+(const ImVec2& a, const ImVec2& b) {
|
||||
return ImVec2(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
|
||||
static ImVec2 operator-(const ImVec2& a, const ImVec2& b) {
|
||||
return ImVec2(a.x - b.x, a.y - b.y);
|
||||
}
|
||||
|
||||
static ImVec2 operator*(const ImVec2& a, const ImVec2& b) {
|
||||
return ImVec2(a.x * b.x, a.y * b.y);
|
||||
}
|
||||
|
||||
static ImVec2 operator/(const ImVec2& a, const ImVec2& b) {
|
||||
return ImVec2(a.x / b.x, a.y / b.y);
|
||||
}
|
||||
|
||||
static ImVec2 operator*(const ImVec2& a, const float b) {
|
||||
return ImVec2(a.x * b, a.y * b);
|
||||
}
|
||||
#endif
|
||||
|
||||
static float smoothstep(float edge0, float edge1, float x)
|
||||
{
|
||||
x = ImClamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
static float distance(float x, float y, float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float A = x - x1;
|
||||
float B = y - y1;
|
||||
float C = x2 - x1;
|
||||
float D = y2 - y1;
|
||||
|
||||
float dot = A * C + B * D;
|
||||
float len_sq = C * C + D * D;
|
||||
float param = -1.f;
|
||||
if (len_sq > FLT_EPSILON)
|
||||
param = dot / len_sq;
|
||||
|
||||
float xx, yy;
|
||||
|
||||
if (param < 0.f) {
|
||||
xx = x1;
|
||||
yy = y1;
|
||||
}
|
||||
else if (param > 1.f) {
|
||||
xx = x2;
|
||||
yy = y2;
|
||||
}
|
||||
else {
|
||||
xx = x1 + param * C;
|
||||
yy = y1 + param * D;
|
||||
}
|
||||
|
||||
float dx = x - xx;
|
||||
float dy = y - yy;
|
||||
return sqrtf(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
static int DrawPoint(ImDrawList* draw_list, ImVec2 pos, const ImVec2 size, const ImVec2 offset, bool edited)
|
||||
{
|
||||
int ret = 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
static const ImVec2 localOffsets[4] = { ImVec2(1,0), ImVec2(0,1), ImVec2(-1,0), ImVec2(0,-1) };
|
||||
ImVec2 offsets[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
offsets[i] = pos * size + localOffsets[i] * 4.5f + offset;
|
||||
}
|
||||
|
||||
const ImVec2 center = pos * size + offset;
|
||||
const ImRect anchor(center - ImVec2(5, 5), center + ImVec2(5, 5));
|
||||
draw_list->AddConvexPolyFilled(offsets, 4, 0xFF000000);
|
||||
if (anchor.Contains(io.MousePos))
|
||||
{
|
||||
ret = 1;
|
||||
if (io.MouseDown[0])
|
||||
ret = 2;
|
||||
}
|
||||
if (edited)
|
||||
draw_list->AddPolyline(offsets, 4, 0xFFFFFFFF, true, 3.0f);
|
||||
else if (ret)
|
||||
draw_list->AddPolyline(offsets, 4, 0xFF80B0FF, true, 2.0f);
|
||||
else
|
||||
draw_list->AddPolyline(offsets, 4, 0xFF0080FF, true, 2.0f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Edit(Delegate& delegate, const ImVec2& size, unsigned int id, const ImRect* clippingRect, ImVector<EditPoint>* selectedPoints)
|
||||
{
|
||||
static bool selectingQuad = false;
|
||||
static ImVec2 quadSelection;
|
||||
static int overCurve = -1;
|
||||
static int movingCurve = -1;
|
||||
static bool scrollingV = false;
|
||||
static std::set<EditPoint> selection;
|
||||
static bool overSelectedPoint = false;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, 0);
|
||||
ImGui::BeginChildFrame(id, size);
|
||||
delegate.focused = ImGui::IsWindowFocused();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
if (clippingRect)
|
||||
draw_list->PushClipRect(clippingRect->Min, clippingRect->Max, true);
|
||||
|
||||
const ImVec2 offset = ImGui::GetCursorScreenPos() + ImVec2(0.f, size.y);
|
||||
const ImVec2 ssize(size.x, -size.y);
|
||||
const ImRect container(offset + ImVec2(0.f, ssize.y), offset + ImVec2(ssize.x, 0.f));
|
||||
ImVec2& min = delegate.GetMin();
|
||||
ImVec2& max = delegate.GetMax();
|
||||
|
||||
// handle zoom and VScroll
|
||||
if (container.Contains(io.MousePos))
|
||||
{
|
||||
if (fabsf(io.MouseWheel) > FLT_EPSILON)
|
||||
{
|
||||
const float r = (io.MousePos.y - offset.y) / ssize.y;
|
||||
float ratioY = ImLerp(min.y, max.y, r);
|
||||
auto scaleValue = [&](float v) {
|
||||
v -= ratioY;
|
||||
v *= (1.f - io.MouseWheel * 0.05f);
|
||||
v += ratioY;
|
||||
return v;
|
||||
};
|
||||
min.y = scaleValue(min.y);
|
||||
max.y = scaleValue(max.y);
|
||||
}
|
||||
if (!scrollingV && ImGui::IsMouseDown(2))
|
||||
{
|
||||
scrollingV = true;
|
||||
}
|
||||
}
|
||||
ImVec2 range = max - min + ImVec2(1.f, 0.f); // +1 because of inclusive last frame
|
||||
|
||||
const ImVec2 viewSize(size.x, -size.y);
|
||||
const ImVec2 sizeOfPixel = ImVec2(1.f, 1.f) / viewSize;
|
||||
const size_t curveCount = delegate.GetCurveCount();
|
||||
|
||||
if (scrollingV)
|
||||
{
|
||||
float deltaH = io.MouseDelta.y * range.y * sizeOfPixel.y;
|
||||
min.y -= deltaH;
|
||||
max.y -= deltaH;
|
||||
if (!ImGui::IsMouseDown(2))
|
||||
scrollingV = false;
|
||||
}
|
||||
|
||||
draw_list->AddRectFilled(offset, offset + ssize, delegate.GetBackgroundColor());
|
||||
|
||||
auto pointToRange = [&](ImVec2 pt) { return (pt - min) / range; };
|
||||
auto rangeToPoint = [&](ImVec2 pt) { return (pt * range) + min; };
|
||||
|
||||
draw_list->AddLine(ImVec2(-1.f, -min.y / range.y) * viewSize + offset, ImVec2(1.f, -min.y / range.y) * viewSize + offset, 0xFF000000, 1.5f);
|
||||
bool overCurveOrPoint = false;
|
||||
|
||||
int localOverCurve = -1;
|
||||
// make sure highlighted curve is rendered last
|
||||
int* curvesIndex = (int*)_malloca(sizeof(int) * curveCount);
|
||||
for (size_t c = 0; c < curveCount; c++)
|
||||
curvesIndex[c] = int(c);
|
||||
int highLightedCurveIndex = -1;
|
||||
if (overCurve != -1 && curveCount)
|
||||
{
|
||||
ImSwap(curvesIndex[overCurve], curvesIndex[curveCount - 1]);
|
||||
highLightedCurveIndex = overCurve;
|
||||
}
|
||||
|
||||
for (size_t cur = 0; cur < curveCount; cur++)
|
||||
{
|
||||
int c = curvesIndex[cur];
|
||||
if (!delegate.IsVisible(c))
|
||||
continue;
|
||||
const size_t ptCount = delegate.GetPointCount(c);
|
||||
if (ptCount < 1)
|
||||
continue;
|
||||
CurveType curveType = delegate.GetCurveType(c);
|
||||
if (curveType == CurveNone)
|
||||
continue;
|
||||
const ImVec2* pts = delegate.GetPoints(c);
|
||||
uint32_t curveColor = delegate.GetCurveColor(c);
|
||||
if ((c == highLightedCurveIndex && selection.empty() && !selectingQuad) || movingCurve == c)
|
||||
curveColor = 0xFFFFFFFF;
|
||||
|
||||
for (size_t p = 0; p < ptCount - 1; p++)
|
||||
{
|
||||
const ImVec2 p1 = pointToRange(pts[p]);
|
||||
const ImVec2 p2 = pointToRange(pts[p + 1]);
|
||||
|
||||
if (curveType == CurveSmooth || curveType == CurveLinear)
|
||||
{
|
||||
size_t subStepCount = (curveType == CurveSmooth) ? 20 : 2;
|
||||
float step = 1.f / float(subStepCount - 1);
|
||||
for (size_t substep = 0; substep < subStepCount - 1; substep++)
|
||||
{
|
||||
float t = float(substep) * step;
|
||||
|
||||
const ImVec2 sp1 = ImLerp(p1, p2, t);
|
||||
const ImVec2 sp2 = ImLerp(p1, p2, t + step);
|
||||
|
||||
const float rt1 = smoothstep(p1.x, p2.x, sp1.x);
|
||||
const float rt2 = smoothstep(p1.x, p2.x, sp2.x);
|
||||
|
||||
const ImVec2 pos1 = ImVec2(sp1.x, ImLerp(p1.y, p2.y, rt1)) * viewSize + offset;
|
||||
const ImVec2 pos2 = ImVec2(sp2.x, ImLerp(p1.y, p2.y, rt2)) * viewSize + offset;
|
||||
|
||||
if (distance(io.MousePos.x, io.MousePos.y, pos1.x, pos1.y, pos2.x, pos2.y) < 8.f && !scrollingV)
|
||||
{
|
||||
localOverCurve = int(c);
|
||||
overCurve = int(c);
|
||||
overCurveOrPoint = true;
|
||||
}
|
||||
|
||||
draw_list->AddLine(pos1, pos2, curveColor, 1.3f);
|
||||
} // substep
|
||||
}
|
||||
else if (curveType == CurveDiscrete)
|
||||
{
|
||||
ImVec2 dp1 = p1 * viewSize + offset;
|
||||
ImVec2 dp2 = ImVec2(p2.x, p1.y) * viewSize + offset;
|
||||
ImVec2 dp3 = p2 * viewSize + offset;
|
||||
draw_list->AddLine(dp1, dp2, curveColor, 1.3f);
|
||||
draw_list->AddLine(dp2, dp3, curveColor, 1.3f);
|
||||
|
||||
if ((distance(io.MousePos.x, io.MousePos.y, dp1.x, dp1.y, dp3.x, dp1.y) < 8.f ||
|
||||
distance(io.MousePos.x, io.MousePos.y, dp3.x, dp1.y, dp3.x, dp3.y) < 8.f)
|
||||
/*&& localOverCurve == -1*/)
|
||||
{
|
||||
localOverCurve = int(c);
|
||||
overCurve = int(c);
|
||||
overCurveOrPoint = true;
|
||||
}
|
||||
}
|
||||
} // point loop
|
||||
|
||||
for (size_t p = 0; p < ptCount; p++)
|
||||
{
|
||||
const int drawState = DrawPoint(draw_list, pointToRange(pts[p]), viewSize, offset, (selection.find({ int(c), int(p) }) != selection.end() && movingCurve == -1 && !scrollingV));
|
||||
if (drawState && movingCurve == -1 && !selectingQuad)
|
||||
{
|
||||
overCurveOrPoint = true;
|
||||
overSelectedPoint = true;
|
||||
overCurve = -1;
|
||||
if (drawState == 2)
|
||||
{
|
||||
if (!io.KeyShift && selection.find({ int(c), int(p) }) == selection.end())
|
||||
selection.clear();
|
||||
selection.insert({ int(c), int(p) });
|
||||
}
|
||||
}
|
||||
}
|
||||
} // curves loop
|
||||
|
||||
if (localOverCurve == -1)
|
||||
overCurve = -1;
|
||||
|
||||
// move selection
|
||||
static bool pointsMoved = false;
|
||||
static ImVec2 mousePosOrigin;
|
||||
static std::vector<ImVec2> originalPoints;
|
||||
if (overSelectedPoint && io.MouseDown[0])
|
||||
{
|
||||
if ((fabsf(io.MouseDelta.x) > 0.f || fabsf(io.MouseDelta.y) > 0.f) && !selection.empty())
|
||||
{
|
||||
if (!pointsMoved)
|
||||
{
|
||||
delegate.BeginEdit(0);
|
||||
mousePosOrigin = io.MousePos;
|
||||
originalPoints.resize(selection.size());
|
||||
int index = 0;
|
||||
for (auto& sel : selection)
|
||||
{
|
||||
const ImVec2* pts = delegate.GetPoints(sel.curveIndex);
|
||||
originalPoints[index++] = pts[sel.pointIndex];
|
||||
}
|
||||
}
|
||||
pointsMoved = true;
|
||||
ret = 1;
|
||||
auto prevSelection = selection;
|
||||
int originalIndex = 0;
|
||||
for (auto& sel : prevSelection)
|
||||
{
|
||||
const ImVec2* pts = delegate.GetPoints(sel.curveIndex);
|
||||
const ImVec2 p = rangeToPoint(pointToRange(originalPoints[originalIndex]) + (io.MousePos - mousePosOrigin) * sizeOfPixel);
|
||||
const int newIndex = delegate.EditPoint(sel.curveIndex, sel.pointIndex, p);
|
||||
if (newIndex != sel.pointIndex)
|
||||
{
|
||||
selection.erase(sel);
|
||||
selection.insert({ sel.curveIndex, newIndex });
|
||||
}
|
||||
originalIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (overSelectedPoint && !io.MouseDown[0])
|
||||
{
|
||||
overSelectedPoint = false;
|
||||
if (pointsMoved)
|
||||
{
|
||||
pointsMoved = false;
|
||||
delegate.EndEdit();
|
||||
}
|
||||
}
|
||||
|
||||
// add point
|
||||
if (overCurve != -1 && io.MouseDoubleClicked[0])
|
||||
{
|
||||
const ImVec2 np = rangeToPoint((io.MousePos - offset) / viewSize);
|
||||
delegate.BeginEdit(overCurve);
|
||||
delegate.AddPoint(overCurve, np);
|
||||
delegate.EndEdit();
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
// move curve
|
||||
|
||||
if (movingCurve != -1)
|
||||
{
|
||||
const size_t ptCount = delegate.GetPointCount(movingCurve);
|
||||
const ImVec2* pts = delegate.GetPoints(movingCurve);
|
||||
if (!pointsMoved)
|
||||
{
|
||||
mousePosOrigin = io.MousePos;
|
||||
pointsMoved = true;
|
||||
originalPoints.resize(ptCount);
|
||||
for (size_t index = 0; index < ptCount; index++)
|
||||
{
|
||||
originalPoints[index] = pts[index];
|
||||
}
|
||||
}
|
||||
if (ptCount >= 1)
|
||||
{
|
||||
for (size_t p = 0; p < ptCount; p++)
|
||||
{
|
||||
delegate.EditPoint(movingCurve, int(p), rangeToPoint(pointToRange(originalPoints[p]) + (io.MousePos - mousePosOrigin) * sizeOfPixel));
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
movingCurve = -1;
|
||||
pointsMoved = false;
|
||||
delegate.EndEdit();
|
||||
}
|
||||
}
|
||||
if (movingCurve == -1 && overCurve != -1 && ImGui::IsMouseClicked(0) && selection.empty() && !selectingQuad)
|
||||
{
|
||||
movingCurve = overCurve;
|
||||
delegate.BeginEdit(overCurve);
|
||||
}
|
||||
|
||||
// quad selection
|
||||
if (selectingQuad)
|
||||
{
|
||||
const ImVec2 bmin = ImMin(quadSelection, io.MousePos);
|
||||
const ImVec2 bmax = ImMax(quadSelection, io.MousePos);
|
||||
draw_list->AddRectFilled(bmin, bmax, 0x40FF0000, 1.f);
|
||||
draw_list->AddRect(bmin, bmax, 0xFFFF0000, 1.f);
|
||||
const ImRect selectionQuad(bmin, bmax);
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
if (!io.KeyShift)
|
||||
selection.clear();
|
||||
// select everythnig is quad
|
||||
for (size_t c = 0; c < curveCount; c++)
|
||||
{
|
||||
if (!delegate.IsVisible(c))
|
||||
continue;
|
||||
|
||||
const size_t ptCount = delegate.GetPointCount(c);
|
||||
if (ptCount < 1)
|
||||
continue;
|
||||
|
||||
const ImVec2* pts = delegate.GetPoints(c);
|
||||
for (size_t p = 0; p < ptCount; p++)
|
||||
{
|
||||
const ImVec2 center = pointToRange(pts[p]) * viewSize + offset;
|
||||
if (selectionQuad.Contains(center))
|
||||
selection.insert({ int(c), int(p) });
|
||||
}
|
||||
}
|
||||
// done
|
||||
selectingQuad = false;
|
||||
}
|
||||
}
|
||||
if (!overCurveOrPoint && ImGui::IsMouseClicked(0) && !selectingQuad && movingCurve == -1 && !overSelectedPoint && container.Contains(io.MousePos))
|
||||
{
|
||||
selectingQuad = true;
|
||||
quadSelection = io.MousePos;
|
||||
}
|
||||
if (clippingRect)
|
||||
draw_list->PopClipRect();
|
||||
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
if (selectedPoints)
|
||||
{
|
||||
selectedPoints->resize(int(selection.size()));
|
||||
int index = 0;
|
||||
for (auto& point : selection)
|
||||
(*selectedPoints)[index++] = point;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
55
src/external/imguizmo/ImCurveEdit.h
vendored
Normal file
55
src/external/imguizmo/ImCurveEdit.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "imgui.h"
|
||||
|
||||
struct ImRect;
|
||||
|
||||
namespace ImCurveEdit
|
||||
{
|
||||
enum CurveType
|
||||
{
|
||||
CurveNone,
|
||||
CurveDiscrete,
|
||||
CurveLinear,
|
||||
CurveSmooth,
|
||||
CurveBezier,
|
||||
};
|
||||
|
||||
struct EditPoint
|
||||
{
|
||||
int curveIndex;
|
||||
int pointIndex;
|
||||
bool operator <(const EditPoint& other) const
|
||||
{
|
||||
if (curveIndex < other.curveIndex)
|
||||
return true;
|
||||
if (curveIndex > other.curveIndex)
|
||||
return false;
|
||||
|
||||
if (pointIndex < other.pointIndex)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct Delegate
|
||||
{
|
||||
bool focused = false;
|
||||
virtual size_t GetCurveCount() = 0;
|
||||
virtual bool IsVisible(size_t curveIndex) { return true; }
|
||||
virtual CurveType GetCurveType(size_t curveIndex) const { return CurveLinear; }
|
||||
virtual ImVec2& GetMin() = 0;
|
||||
virtual ImVec2& GetMax() = 0;
|
||||
virtual size_t GetPointCount(size_t curveIndex) = 0;
|
||||
virtual uint32_t GetCurveColor(size_t curveIndex) = 0;
|
||||
virtual ImVec2* GetPoints(size_t curveIndex) = 0;
|
||||
virtual int EditPoint(size_t curveIndex, int pointIndex, ImVec2 value) = 0;
|
||||
virtual void AddPoint(size_t curveIndex, ImVec2 value) = 0;
|
||||
virtual unsigned int GetBackgroundColor() { return 0xFF202020; }
|
||||
// handle undo/redo thru this functions
|
||||
virtual void BeginEdit(int /*index*/) {}
|
||||
virtual void EndEdit() {}
|
||||
};
|
||||
|
||||
int Edit(Delegate& delegate, const ImVec2& size, unsigned int id, const ImRect* clippingRect = NULL, ImVector<EditPoint>* selectedPoints = NULL);
|
||||
}
|
||||
94
src/external/imguizmo/ImGradient.cpp
vendored
Normal file
94
src/external/imguizmo/ImGradient.cpp
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "ImGradient.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include <stdint.h>
|
||||
#include <set>
|
||||
|
||||
namespace ImGradient
|
||||
{
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
||||
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
||||
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
||||
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
|
||||
static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||
static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
|
||||
#endif
|
||||
|
||||
static int DrawPoint(ImDrawList* draw_list, ImVec4 color, const ImVec2 size, bool editing, ImVec2 pos)
|
||||
{
|
||||
int ret = 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImVec2 p1 = ImLerp(pos, ImVec2(pos + ImVec2(size.x - size.y, 0.f)), color.w) + ImVec2(3, 3);
|
||||
ImVec2 p2 = ImLerp(pos + ImVec2(size.y, size.y), ImVec2(pos + size), color.w) - ImVec2(3, 3);
|
||||
ImRect rc(p1, p2);
|
||||
|
||||
color.w = 1.f;
|
||||
draw_list->AddRectFilled(p1, p2, ImColor(color));
|
||||
if (editing)
|
||||
draw_list->AddRect(p1, p2, 0xFFFFFFFF, 2.f, 15, 2.5f);
|
||||
else
|
||||
draw_list->AddRect(p1, p2, 0x80FFFFFF, 2.f, 15, 1.25f);
|
||||
|
||||
if (rc.Contains(io.MousePos))
|
||||
{
|
||||
if (io.MouseClicked[0])
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Edit(Delegate& delegate, const ImVec2& size, int& selection)
|
||||
{
|
||||
bool ret = false;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::BeginChildFrame(137, size);
|
||||
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
const ImVec2 offset = ImGui::GetCursorScreenPos();
|
||||
|
||||
const ImVec4* pts = delegate.GetPoints();
|
||||
static int currentSelection = -1;
|
||||
static int movingPt = -1;
|
||||
if (currentSelection >= int(delegate.GetPointCount()))
|
||||
currentSelection = -1;
|
||||
if (movingPt != -1)
|
||||
{
|
||||
ImVec4 current = pts[movingPt];
|
||||
current.w += io.MouseDelta.x / size.x;
|
||||
current.w = ImClamp(current.w, 0.f, 1.f);
|
||||
delegate.EditPoint(movingPt, current);
|
||||
ret = true;
|
||||
if (!io.MouseDown[0])
|
||||
movingPt = -1;
|
||||
}
|
||||
for (size_t i = 0; i < delegate.GetPointCount(); i++)
|
||||
{
|
||||
int ptSel = DrawPoint(draw_list, pts[i], size, i == currentSelection, offset);
|
||||
if (ptSel == 2)
|
||||
{
|
||||
currentSelection = int(i);
|
||||
ret = true;
|
||||
}
|
||||
if (ptSel == 1 && io.MouseDown[0] && movingPt == -1)
|
||||
{
|
||||
movingPt = int(i);
|
||||
}
|
||||
}
|
||||
ImRect rc(offset, offset + size);
|
||||
if (rc.Contains(io.MousePos) && io.MouseDoubleClicked[0])
|
||||
{
|
||||
float t = (io.MousePos.x - offset.x) / size.x;
|
||||
delegate.AddPoint(delegate.GetPoint(t));
|
||||
ret = true;
|
||||
}
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
selection = currentSelection;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
19
src/external/imguizmo/ImGradient.h
vendored
Normal file
19
src/external/imguizmo/ImGradient.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
struct ImVec4;
|
||||
struct ImVec2;
|
||||
|
||||
namespace ImGradient
|
||||
{
|
||||
struct Delegate
|
||||
{
|
||||
virtual size_t GetPointCount() = 0;
|
||||
virtual ImVec4* GetPoints() = 0;
|
||||
virtual int EditPoint(int pointIndex, ImVec4 value) = 0;
|
||||
virtual ImVec4 GetPoint(float t) = 0;
|
||||
virtual void AddPoint(ImVec4 value) = 0;
|
||||
};
|
||||
|
||||
bool Edit(Delegate& delegate, const ImVec2& size, int& selection);
|
||||
}
|
||||
2593
src/external/imguizmo/ImGuizmo.cpp
vendored
Normal file
2593
src/external/imguizmo/ImGuizmo.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
187
src/external/imguizmo/ImGuizmo.h
vendored
Normal file
187
src/external/imguizmo/ImGuizmo.h
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
// https://github.com/CedricGuillemet/ImGuizmo
|
||||
// v 1.61 WIP
|
||||
//
|
||||
// The MIT License(MIT)
|
||||
//
|
||||
// Copyright(c) 2016 Cedric Guillemet
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// History :
|
||||
// 2019/11/03 View gizmo
|
||||
// 2016/09/11 Behind camera culling. Scaling Delta matrix not multiplied by source matrix scales. local/world rotation and translation fixed. Display message is incorrect (X: ... Y:...) in local mode.
|
||||
// 2016/09/09 Hatched negative axis. Snapping. Documentation update.
|
||||
// 2016/09/04 Axis switch and translation plan autohiding. Scale transform stability improved
|
||||
// 2016/09/01 Mogwai changed to Manipulate. Draw debug cube. Fixed inverted scale. Mixing scale and translation/rotation gives bad results.
|
||||
// 2016/08/31 First version
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// Future (no order):
|
||||
//
|
||||
// - Multi view
|
||||
// - display rotation/translation/scale infos in local/world space and not only local
|
||||
// - finish local/world matrix application
|
||||
// - OPERATION as bitmask
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// Example
|
||||
#if 0
|
||||
void EditTransform(const Camera& camera, matrix_t& matrix)
|
||||
{
|
||||
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
|
||||
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
|
||||
if (ImGui::IsKeyPressed(90))
|
||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
||||
if (ImGui::IsKeyPressed(69))
|
||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
||||
if (ImGui::IsKeyPressed(82)) // r Key
|
||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
||||
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
|
||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
|
||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
|
||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
||||
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
||||
ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
||||
ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
||||
ImGui::InputFloat3("Rt", matrixRotation, 3);
|
||||
ImGui::InputFloat3("Sc", matrixScale, 3);
|
||||
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);
|
||||
|
||||
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
|
||||
{
|
||||
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
|
||||
mCurrentGizmoMode = ImGuizmo::LOCAL;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
|
||||
mCurrentGizmoMode = ImGuizmo::WORLD;
|
||||
}
|
||||
static bool useSnap(false);
|
||||
if (ImGui::IsKeyPressed(83))
|
||||
useSnap = !useSnap;
|
||||
ImGui::Checkbox("", &useSnap);
|
||||
ImGui::SameLine();
|
||||
vec_t snap;
|
||||
switch (mCurrentGizmoOperation)
|
||||
{
|
||||
case ImGuizmo::TRANSLATE:
|
||||
snap = config.mSnapTranslation;
|
||||
ImGui::InputFloat3("Snap", &snap.x);
|
||||
break;
|
||||
case ImGuizmo::ROTATE:
|
||||
snap = config.mSnapRotation;
|
||||
ImGui::InputFloat("Angle Snap", &snap.x);
|
||||
break;
|
||||
case ImGuizmo::SCALE:
|
||||
snap = config.mSnapScale;
|
||||
ImGui::InputFloat("Scale Snap", &snap.x);
|
||||
break;
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
|
||||
ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
|
||||
}
|
||||
#endif
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_IMGUI_API
|
||||
#include "imconfig.h"
|
||||
#endif
|
||||
#ifndef IMGUI_API
|
||||
#define IMGUI_API
|
||||
#endif
|
||||
|
||||
namespace ImGuizmo
|
||||
{
|
||||
// call inside your own window and before Manipulate() in order to draw gizmo to that window.
|
||||
// Or pass a specific ImDrawList to draw to (e.g. ImGui::GetForegroundDrawList()).
|
||||
IMGUI_API void SetDrawlist(ImDrawList* drawlist = nullptr);
|
||||
|
||||
// call BeginFrame right after ImGui_XXXX_NewFrame();
|
||||
IMGUI_API void BeginFrame();
|
||||
|
||||
// return true if mouse cursor is over any gizmo control (axis, plan or screen component)
|
||||
IMGUI_API bool IsOver();
|
||||
|
||||
// return true if mouse IsOver or if the gizmo is in moving state
|
||||
IMGUI_API bool IsUsing();
|
||||
|
||||
// enable/disable the gizmo. Stay in the state until next call to Enable.
|
||||
// gizmo is rendered with gray half transparent color when disabled
|
||||
IMGUI_API void Enable(bool enable);
|
||||
|
||||
// helper functions for manualy editing translation/rotation/scale with an input float
|
||||
// translation, rotation and scale float points to 3 floats each
|
||||
// Angles are in degrees (more suitable for human editing)
|
||||
// example:
|
||||
// float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
||||
// ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
||||
// ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
||||
// ImGui::InputFloat3("Rt", matrixRotation, 3);
|
||||
// ImGui::InputFloat3("Sc", matrixScale, 3);
|
||||
// ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
|
||||
//
|
||||
// These functions have some numerical stability issues for now. Use with caution.
|
||||
IMGUI_API void DecomposeMatrixToComponents(const float* matrix, float* translation, float* rotation, float* scale);
|
||||
IMGUI_API void RecomposeMatrixFromComponents(const float* translation, const float* rotation, const float* scale, float* matrix);
|
||||
|
||||
IMGUI_API void SetRect(float x, float y, float width, float height);
|
||||
// default is false
|
||||
IMGUI_API void SetOrthographic(bool isOrthographic);
|
||||
|
||||
// Render a cube with face color corresponding to face normal. Usefull for debug/tests
|
||||
IMGUI_API void DrawCubes(const float* view, const float* projection, const float* matrices, int matrixCount);
|
||||
IMGUI_API void DrawGrid(const float* view, const float* projection, const float* matrix, const float gridSize);
|
||||
|
||||
// call it when you want a gizmo
|
||||
// Needs view and projection matrices.
|
||||
// matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional
|
||||
// translation is applied in world space
|
||||
enum OPERATION
|
||||
{
|
||||
TRANSLATE,
|
||||
ROTATE,
|
||||
SCALE,
|
||||
BOUNDS,
|
||||
};
|
||||
|
||||
enum MODE
|
||||
{
|
||||
LOCAL,
|
||||
WORLD
|
||||
};
|
||||
|
||||
IMGUI_API bool Manipulate(const float* view, const float* projection, OPERATION operation, MODE mode, float* matrix, float* deltaMatrix = NULL, const float* snap = NULL, const float* localBounds = NULL, const float* boundsSnap = NULL);
|
||||
//
|
||||
// Please note that this cubeview is patented by Autodesk : https://patents.google.com/patent/US7782319B2/en
|
||||
// It seems to be a defensive patent in the US. I don't think it will bring troubles using it as
|
||||
// other software are using the same mechanics. But just in case, you are now warned!
|
||||
//
|
||||
IMGUI_API void ViewManipulate(float* view, float length, ImVec2 position, ImVec2 size, ImU32 backgroundColor);
|
||||
|
||||
IMGUI_API void SetID(int id);
|
||||
|
||||
// return true if the cursor is over the operation's gizmo
|
||||
IMGUI_API bool IsOver(OPERATION op);
|
||||
IMGUI_API void SetGizmoSizeClipSpace(float value);
|
||||
};
|
||||
672
src/external/imguizmo/ImSequencer.cpp
vendored
Normal file
672
src/external/imguizmo/ImSequencer.cpp
vendored
Normal file
@@ -0,0 +1,672 @@
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "ImSequencer.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace ImSequencer
|
||||
{
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
static ImVec2 operator+(const ImVec2& a, const ImVec2& b) {
|
||||
return ImVec2(a.x + b.x, a.y + b.y);
|
||||
}
|
||||
#endif
|
||||
static bool SequencerAddDelButton(ImDrawList* draw_list, ImVec2 pos, bool add = true)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImRect delRect(pos, ImVec2(pos.x + 16, pos.y + 16));
|
||||
bool overDel = delRect.Contains(io.MousePos);
|
||||
int delColor = overDel ? 0xFFAAAAAA : 0x50000000;
|
||||
float midy = pos.y + 16 / 2 - 0.5f;
|
||||
float midx = pos.x + 16 / 2 - 0.5f;
|
||||
draw_list->AddRect(delRect.Min, delRect.Max, delColor, 4);
|
||||
draw_list->AddLine(ImVec2(delRect.Min.x + 3, midy), ImVec2(delRect.Max.x - 3, midy), delColor, 2);
|
||||
if (add)
|
||||
draw_list->AddLine(ImVec2(midx, delRect.Min.y + 3), ImVec2(midx, delRect.Max.y - 3), delColor, 2);
|
||||
return overDel;
|
||||
}
|
||||
|
||||
static int min(int a, int b) { return (a < b) ? a : b; }
|
||||
static int max(int a, int b) { return (a > b) ? a : b; }
|
||||
|
||||
bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions)
|
||||
{
|
||||
bool ret = false;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int cx = (int)(io.MousePos.x);
|
||||
int cy = (int)(io.MousePos.y);
|
||||
static float framePixelWidth = 10.f;
|
||||
static float framePixelWidthTarget = 10.f;
|
||||
int legendWidth = 200;
|
||||
|
||||
static int movingEntry = -1;
|
||||
static int movingPos = -1;
|
||||
static int movingPart = -1;
|
||||
int delEntry = -1;
|
||||
int dupEntry = -1;
|
||||
int ItemHeight = 20;
|
||||
|
||||
bool popupOpened = false;
|
||||
int sequenceCount = sequence->GetItemCount();
|
||||
if (!sequenceCount)
|
||||
return false;
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
|
||||
ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
|
||||
int firstFrameUsed = firstFrame ? *firstFrame : 0;
|
||||
|
||||
|
||||
int controlHeight = sequenceCount * ItemHeight;
|
||||
for (int i = 0; i < sequenceCount; i++)
|
||||
controlHeight += int(sequence->GetCustomHeight(i));
|
||||
int frameCount = ImMax(sequence->GetFrameMax() - sequence->GetFrameMin(), 1);
|
||||
|
||||
static bool MovingScrollBar = false;
|
||||
static bool MovingCurrentFrame = false;
|
||||
struct CustomDraw
|
||||
{
|
||||
int index;
|
||||
ImRect customRect;
|
||||
ImRect legendRect;
|
||||
ImRect clippingRect;
|
||||
ImRect legendClippingRect;
|
||||
};
|
||||
ImVector<CustomDraw> customDraws;
|
||||
ImVector<CustomDraw> compactCustomDraws;
|
||||
// zoom in/out
|
||||
int frameOverCursor = 0;
|
||||
const int visibleFrameCount = (int)floorf((canvas_size.x - legendWidth) / framePixelWidth);
|
||||
const float barWidthRatio = ImMin(visibleFrameCount / (float)frameCount, 1.f);
|
||||
const float barWidthInPixels = barWidthRatio * (canvas_size.x - legendWidth);
|
||||
|
||||
ImRect regionRect(canvas_pos, canvas_pos + canvas_size);
|
||||
|
||||
static bool panningView = false;
|
||||
static ImVec2 panningViewSource;
|
||||
static int panningViewFrame;
|
||||
if (ImGui::IsWindowFocused() && io.KeyAlt && io.MouseDown[2])
|
||||
{
|
||||
if (!panningView)
|
||||
{
|
||||
panningViewSource = io.MousePos;
|
||||
panningView = true;
|
||||
panningViewFrame = *firstFrame;
|
||||
}
|
||||
*firstFrame = panningViewFrame - int((io.MousePos.x - panningViewSource.x) / framePixelWidth);
|
||||
*firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), sequence->GetFrameMax() - visibleFrameCount);
|
||||
}
|
||||
if (panningView && !io.MouseDown[2])
|
||||
{
|
||||
panningView = false;
|
||||
}
|
||||
framePixelWidthTarget = ImClamp(framePixelWidthTarget, 0.1f, 50.f);
|
||||
|
||||
framePixelWidth = ImLerp(framePixelWidth, framePixelWidthTarget, 0.33f);
|
||||
|
||||
frameCount = sequence->GetFrameMax() - sequence->GetFrameMin();
|
||||
if (visibleFrameCount >= frameCount && firstFrame)
|
||||
*firstFrame = sequence->GetFrameMin();
|
||||
|
||||
|
||||
// --
|
||||
if (expanded && !*expanded)
|
||||
{
|
||||
ImGui::InvisibleButton("canvas", ImVec2(canvas_size.x - canvas_pos.x, (float)ItemHeight));
|
||||
draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);
|
||||
char tmps[512];
|
||||
sprintf(tmps, "%d Frames / %d entries", frameCount, sequenceCount);
|
||||
draw_list->AddText(ImVec2(canvas_pos.x + 26, canvas_pos.y + 2), 0xFFFFFFFF, tmps);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hasScrollBar(true);
|
||||
/*
|
||||
int framesPixelWidth = int(frameCount * framePixelWidth);
|
||||
if ((framesPixelWidth + legendWidth) >= canvas_size.x)
|
||||
{
|
||||
hasScrollBar = true;
|
||||
}
|
||||
*/
|
||||
// test scroll area
|
||||
ImVec2 headerSize(canvas_size.x, (float)ItemHeight);
|
||||
ImVec2 scrollBarSize(canvas_size.x, 14.f);
|
||||
ImGui::InvisibleButton("topBar", headerSize);
|
||||
draw_list->AddRectFilled(canvas_pos, canvas_pos + headerSize, 0xFFFF0000, 0);
|
||||
ImVec2 childFramePos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 childFrameSize(canvas_size.x, canvas_size.y - 8.f - headerSize.y - (hasScrollBar ? scrollBarSize.y : 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
|
||||
ImGui::BeginChildFrame(889, childFrameSize);
|
||||
sequence->focused = ImGui::IsWindowFocused();
|
||||
ImGui::InvisibleButton("contentBar", ImVec2(canvas_size.x, float(controlHeight)));
|
||||
const ImVec2 contentMin = ImGui::GetItemRectMin();
|
||||
const ImVec2 contentMax = ImGui::GetItemRectMax();
|
||||
const ImRect contentRect(contentMin, contentMax);
|
||||
const float contentHeight = contentMax.y - contentMin.y;
|
||||
|
||||
// full background
|
||||
draw_list->AddRectFilled(canvas_pos, canvas_pos + canvas_size, 0xFF242424, 0);
|
||||
|
||||
// current frame top
|
||||
ImRect topRect(ImVec2(canvas_pos.x + legendWidth, canvas_pos.y), ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + ItemHeight));
|
||||
|
||||
if (!MovingCurrentFrame && !MovingScrollBar && movingEntry == -1 && sequenceOptions & SEQUENCER_CHANGE_FRAME && currentFrame && *currentFrame >= 0 && topRect.Contains(io.MousePos) && io.MouseDown[0])
|
||||
{
|
||||
MovingCurrentFrame = true;
|
||||
}
|
||||
if (MovingCurrentFrame)
|
||||
{
|
||||
if (frameCount)
|
||||
{
|
||||
*currentFrame = (int)((io.MousePos.x - topRect.Min.x) / framePixelWidth) + firstFrameUsed;
|
||||
if (*currentFrame < sequence->GetFrameMin())
|
||||
*currentFrame = sequence->GetFrameMin();
|
||||
if (*currentFrame >= sequence->GetFrameMax())
|
||||
*currentFrame = sequence->GetFrameMax();
|
||||
}
|
||||
if (!io.MouseDown[0])
|
||||
MovingCurrentFrame = false;
|
||||
}
|
||||
|
||||
//header
|
||||
draw_list->AddRectFilled(canvas_pos, ImVec2(canvas_size.x + canvas_pos.x, canvas_pos.y + ItemHeight), 0xFF3D3837, 0);
|
||||
if (sequenceOptions & SEQUENCER_ADD)
|
||||
{
|
||||
if (SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + legendWidth - ItemHeight, canvas_pos.y + 2), true) && io.MouseReleased[0])
|
||||
ImGui::OpenPopup("addEntry");
|
||||
|
||||
if (ImGui::BeginPopup("addEntry"))
|
||||
{
|
||||
for (int i = 0; i < sequence->GetItemTypeCount(); i++)
|
||||
if (ImGui::Selectable(sequence->GetItemTypeName(i)))
|
||||
{
|
||||
sequence->Add(i);
|
||||
*selectedEntry = sequence->GetItemCount() - 1;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
popupOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
//header frame number and lines
|
||||
int modFrameCount = 10;
|
||||
int frameStep = 1;
|
||||
while ((modFrameCount * framePixelWidth) < 150)
|
||||
{
|
||||
modFrameCount *= 2;
|
||||
frameStep *= 2;
|
||||
};
|
||||
int halfModFrameCount = modFrameCount / 2;
|
||||
|
||||
auto drawLine = [&](int i, int regionHeight) {
|
||||
bool baseIndex = ((i % modFrameCount) == 0) || (i == sequence->GetFrameMax() || i == sequence->GetFrameMin());
|
||||
bool halfIndex = (i % halfModFrameCount) == 0;
|
||||
int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);
|
||||
int tiretStart = baseIndex ? 4 : (halfIndex ? 10 : 14);
|
||||
int tiretEnd = baseIndex ? regionHeight : ItemHeight;
|
||||
|
||||
if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))
|
||||
{
|
||||
draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);
|
||||
|
||||
draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)ItemHeight), ImVec2((float)px, canvas_pos.y + (float)regionHeight - 1), 0x30606060, 1);
|
||||
}
|
||||
|
||||
if (baseIndex && px > (canvas_pos.x + legendWidth))
|
||||
{
|
||||
char tmps[512];
|
||||
sprintf(tmps, "%d", i);
|
||||
draw_list->AddText(ImVec2((float)px + 3.f, canvas_pos.y), 0xFFBBBBBB, tmps);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
auto drawLineContent = [&](int i, int regionHeight) {
|
||||
int px = (int)canvas_pos.x + int(i * framePixelWidth) + legendWidth - int(firstFrameUsed * framePixelWidth);
|
||||
int tiretStart = int(contentMin.y);
|
||||
int tiretEnd = int(contentMax.y);
|
||||
|
||||
if (px <= (canvas_size.x + canvas_pos.x) && px >= (canvas_pos.x + legendWidth))
|
||||
{
|
||||
//draw_list->AddLine(ImVec2((float)px, canvas_pos.y + (float)tiretStart), ImVec2((float)px, canvas_pos.y + (float)tiretEnd - 1), 0xFF606060, 1);
|
||||
|
||||
draw_list->AddLine(ImVec2(float(px), float(tiretStart)), ImVec2(float(px), float(tiretEnd)), 0x30606060, 1);
|
||||
}
|
||||
};
|
||||
for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)
|
||||
{
|
||||
drawLine(i, ItemHeight);
|
||||
}
|
||||
drawLine(sequence->GetFrameMin(), ItemHeight);
|
||||
drawLine(sequence->GetFrameMax(), ItemHeight);
|
||||
/*
|
||||
draw_list->AddLine(canvas_pos, ImVec2(canvas_pos.x, canvas_pos.y + controlHeight), 0xFF000000, 1);
|
||||
draw_list->AddLine(ImVec2(canvas_pos.x, canvas_pos.y + ItemHeight), ImVec2(canvas_size.x, canvas_pos.y + ItemHeight), 0xFF000000, 1);
|
||||
*/
|
||||
// clip content
|
||||
|
||||
draw_list->PushClipRect(childFramePos, childFramePos + childFrameSize);
|
||||
|
||||
// draw item names in the legend rect on the left
|
||||
size_t customHeight = 0;
|
||||
for (int i = 0; i < sequenceCount; i++)
|
||||
{
|
||||
int type;
|
||||
sequence->Get(i, NULL, NULL, &type, NULL);
|
||||
ImVec2 tpos(contentMin.x + 3, contentMin.y + i * ItemHeight + 2 + customHeight);
|
||||
draw_list->AddText(tpos, 0xFFFFFFFF, sequence->GetItemLabel(i));
|
||||
|
||||
if (sequenceOptions & SEQUENCER_DEL)
|
||||
{
|
||||
bool overDel = SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight + 2 - 10, tpos.y + 2), false);
|
||||
if (overDel && io.MouseReleased[0])
|
||||
delEntry = i;
|
||||
|
||||
bool overDup = SequencerAddDelButton(draw_list, ImVec2(contentMin.x + legendWidth - ItemHeight - ItemHeight + 2 - 10, tpos.y + 2), true);
|
||||
if (overDup && io.MouseReleased[0])
|
||||
dupEntry = i;
|
||||
}
|
||||
customHeight += sequence->GetCustomHeight(i);
|
||||
}
|
||||
|
||||
// clipping rect so items bars are not visible in the legend on the left when scrolled
|
||||
//
|
||||
|
||||
// slots background
|
||||
customHeight = 0;
|
||||
for (int i = 0; i < sequenceCount; i++)
|
||||
{
|
||||
unsigned int col = (i & 1) ? 0xFF3A3636 : 0xFF413D3D;
|
||||
|
||||
size_t localCustomHeight = sequence->GetCustomHeight(i);
|
||||
ImVec2 pos = ImVec2(contentMin.x + legendWidth, contentMin.y + ItemHeight * i + 1 + customHeight);
|
||||
ImVec2 sz = ImVec2(canvas_size.x + canvas_pos.x, pos.y + ItemHeight - 1 + localCustomHeight);
|
||||
if (!popupOpened && cy >= pos.y && cy < pos.y + (ItemHeight + localCustomHeight) && movingEntry == -1 && cx>contentMin.x && cx < contentMin.x + canvas_size.x)
|
||||
{
|
||||
col += 0x80201008;
|
||||
pos.x -= legendWidth;
|
||||
}
|
||||
draw_list->AddRectFilled(pos, sz, col, 0);
|
||||
customHeight += localCustomHeight;
|
||||
}
|
||||
|
||||
draw_list->PushClipRect(childFramePos + ImVec2(float(legendWidth), 0.f), childFramePos + childFrameSize);
|
||||
|
||||
// vertical frame lines in content area
|
||||
for (int i = sequence->GetFrameMin(); i <= sequence->GetFrameMax(); i += frameStep)
|
||||
{
|
||||
drawLineContent(i, int(contentHeight));
|
||||
}
|
||||
drawLineContent(sequence->GetFrameMin(), int(contentHeight));
|
||||
drawLineContent(sequence->GetFrameMax(), int(contentHeight));
|
||||
|
||||
// selection
|
||||
bool selected = selectedEntry && (*selectedEntry >= 0);
|
||||
if (selected)
|
||||
{
|
||||
customHeight = 0;
|
||||
for (int i = 0; i < *selectedEntry; i++)
|
||||
customHeight += sequence->GetCustomHeight(i);;
|
||||
draw_list->AddRectFilled(ImVec2(contentMin.x, contentMin.y + ItemHeight * *selectedEntry + customHeight), ImVec2(contentMin.x + canvas_size.x, contentMin.y + ItemHeight * (*selectedEntry + 1) + customHeight), 0x801080FF, 1.f);
|
||||
}
|
||||
|
||||
// slots
|
||||
customHeight = 0;
|
||||
for (int i = 0; i < sequenceCount; i++)
|
||||
{
|
||||
int* start, * end;
|
||||
unsigned int color;
|
||||
sequence->Get(i, &start, &end, NULL, &color);
|
||||
size_t localCustomHeight = sequence->GetCustomHeight(i);
|
||||
|
||||
ImVec2 pos = ImVec2(contentMin.x + legendWidth - firstFrameUsed * framePixelWidth, contentMin.y + ItemHeight * i + 1 + customHeight);
|
||||
ImVec2 slotP1(pos.x + *start * framePixelWidth, pos.y + 2);
|
||||
ImVec2 slotP2(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2);
|
||||
ImVec2 slotP3(pos.x + *end * framePixelWidth + framePixelWidth, pos.y + ItemHeight - 2 + localCustomHeight);
|
||||
unsigned int slotColor = color | 0xFF000000;
|
||||
unsigned int slotColorHalf = (color & 0xFFFFFF) | 0x40000000;
|
||||
|
||||
if (slotP1.x <= (canvas_size.x + contentMin.x) && slotP2.x >= (contentMin.x + legendWidth))
|
||||
{
|
||||
draw_list->AddRectFilled(slotP1, slotP3, slotColorHalf, 2);
|
||||
draw_list->AddRectFilled(slotP1, slotP2, slotColor, 2);
|
||||
}
|
||||
if (ImRect(slotP1, slotP2).Contains(io.MousePos) && io.MouseDoubleClicked[0])
|
||||
{
|
||||
sequence->DoubleClick(i);
|
||||
}
|
||||
ImRect rects[3] = { ImRect(slotP1, ImVec2(slotP1.x + framePixelWidth / 2, slotP2.y))
|
||||
, ImRect(ImVec2(slotP2.x - framePixelWidth / 2, slotP1.y), slotP2)
|
||||
, ImRect(slotP1, slotP2) };
|
||||
|
||||
const unsigned int quadColor[] = { 0xFFFFFFFF, 0xFFFFFFFF, slotColor + (selected ? 0 : 0x202020) };
|
||||
if (movingEntry == -1 && (sequenceOptions & SEQUENCER_EDIT_STARTEND))// TODOFOCUS && backgroundRect.Contains(io.MousePos))
|
||||
{
|
||||
for (int j = 2; j >= 0; j--)
|
||||
{
|
||||
ImRect& rc = rects[j];
|
||||
if (!rc.Contains(io.MousePos))
|
||||
continue;
|
||||
draw_list->AddRectFilled(rc.Min, rc.Max, quadColor[j], 2);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
ImRect& rc = rects[j];
|
||||
if (!rc.Contains(io.MousePos))
|
||||
continue;
|
||||
if (!ImRect(childFramePos, childFramePos + childFrameSize).Contains(io.MousePos))
|
||||
continue;
|
||||
if (ImGui::IsMouseClicked(0) && !MovingScrollBar && !MovingCurrentFrame)
|
||||
{
|
||||
movingEntry = i;
|
||||
movingPos = cx;
|
||||
movingPart = j + 1;
|
||||
sequence->BeginEdit(movingEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// custom draw
|
||||
if (localCustomHeight > 0)
|
||||
{
|
||||
ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + 1 + customHeight);
|
||||
ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(ItemHeight)),
|
||||
rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(localCustomHeight + ItemHeight)));
|
||||
ImRect clippingRect(rp + ImVec2(float(legendWidth), float(ItemHeight)), rp + ImVec2(canvas_size.x, float(localCustomHeight + ItemHeight)));
|
||||
|
||||
ImRect legendRect(rp + ImVec2(0.f, float(ItemHeight)), rp + ImVec2(float(legendWidth), float(localCustomHeight)));
|
||||
ImRect legendClippingRect(canvas_pos + ImVec2(0.f, float(ItemHeight)), canvas_pos + ImVec2(float(legendWidth), float(localCustomHeight + ItemHeight)));
|
||||
customDraws.push_back({ i, customRect, legendRect, clippingRect, legendClippingRect });
|
||||
}
|
||||
else
|
||||
{
|
||||
ImVec2 rp(canvas_pos.x, contentMin.y + ItemHeight * i + customHeight);
|
||||
ImRect customRect(rp + ImVec2(legendWidth - (firstFrameUsed - sequence->GetFrameMin() - 0.5f) * framePixelWidth, float(0.f)),
|
||||
rp + ImVec2(legendWidth + (sequence->GetFrameMax() - firstFrameUsed - 0.5f + 2.f) * framePixelWidth, float(ItemHeight)));
|
||||
ImRect clippingRect(rp + ImVec2(float(legendWidth), float(0.f)), rp + ImVec2(canvas_size.x, float(ItemHeight)));
|
||||
|
||||
compactCustomDraws.push_back({ i, customRect, ImRect(), clippingRect, ImRect() });
|
||||
}
|
||||
customHeight += localCustomHeight;
|
||||
}
|
||||
|
||||
|
||||
// moving
|
||||
if (/*backgroundRect.Contains(io.MousePos) && */movingEntry >= 0)
|
||||
{
|
||||
ImGui::CaptureMouseFromApp();
|
||||
int diffFrame = int((cx - movingPos) / framePixelWidth);
|
||||
if (std::abs(diffFrame) > 0)
|
||||
{
|
||||
int* start, * end;
|
||||
sequence->Get(movingEntry, &start, &end, NULL, NULL);
|
||||
if (selectedEntry)
|
||||
*selectedEntry = movingEntry;
|
||||
int& l = *start;
|
||||
int& r = *end;
|
||||
if (movingPart & 1)
|
||||
l += diffFrame;
|
||||
if (movingPart & 2)
|
||||
r += diffFrame;
|
||||
if (l < 0)
|
||||
{
|
||||
if (movingPart & 2)
|
||||
r -= l;
|
||||
l = 0;
|
||||
}
|
||||
if (movingPart & 1 && l > r)
|
||||
l = r;
|
||||
if (movingPart & 2 && r < l)
|
||||
r = l;
|
||||
movingPos += int(diffFrame * framePixelWidth);
|
||||
}
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
// single select
|
||||
if (!diffFrame && movingPart && selectedEntry)
|
||||
{
|
||||
*selectedEntry = movingEntry;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
movingEntry = -1;
|
||||
sequence->EndEdit();
|
||||
}
|
||||
}
|
||||
|
||||
// cursor
|
||||
if (currentFrame && firstFrame && *currentFrame >= *firstFrame && *currentFrame <= sequence->GetFrameMax())
|
||||
{
|
||||
static const float cursorWidth = 8.f;
|
||||
float cursorOffset = contentMin.x + legendWidth + (*currentFrame - firstFrameUsed) * framePixelWidth + framePixelWidth / 2 - cursorWidth * 0.5f;
|
||||
draw_list->AddLine(ImVec2(cursorOffset, canvas_pos.y), ImVec2(cursorOffset, contentMax.y), 0xA02A2AFF, cursorWidth);
|
||||
char tmps[512];
|
||||
sprintf(tmps, "%d", *currentFrame);
|
||||
draw_list->AddText(ImVec2(cursorOffset + 10, canvas_pos.y + 2), 0xFF2A2AFF, tmps);
|
||||
}
|
||||
|
||||
draw_list->PopClipRect();
|
||||
draw_list->PopClipRect();
|
||||
|
||||
for (auto& customDraw : customDraws)
|
||||
sequence->CustomDraw(customDraw.index, draw_list, customDraw.customRect, customDraw.legendRect, customDraw.clippingRect, customDraw.legendClippingRect);
|
||||
for (auto& customDraw : compactCustomDraws)
|
||||
sequence->CustomDrawCompact(customDraw.index, draw_list, customDraw.customRect, customDraw.clippingRect);
|
||||
|
||||
// copy paste
|
||||
if (sequenceOptions & SEQUENCER_COPYPASTE)
|
||||
{
|
||||
ImRect rectCopy(ImVec2(contentMin.x + 100, canvas_pos.y + 2)
|
||||
, ImVec2(contentMin.x + 100 + 30, canvas_pos.y + ItemHeight - 2));
|
||||
bool inRectCopy = rectCopy.Contains(io.MousePos);
|
||||
unsigned int copyColor = inRectCopy ? 0xFF1080FF : 0xFF000000;
|
||||
draw_list->AddText(rectCopy.Min, copyColor, "Copy");
|
||||
|
||||
ImRect rectPaste(ImVec2(contentMin.x + 140, canvas_pos.y + 2)
|
||||
, ImVec2(contentMin.x + 140 + 30, canvas_pos.y + ItemHeight - 2));
|
||||
bool inRectPaste = rectPaste.Contains(io.MousePos);
|
||||
unsigned int pasteColor = inRectPaste ? 0xFF1080FF : 0xFF000000;
|
||||
draw_list->AddText(rectPaste.Min, pasteColor, "Paste");
|
||||
|
||||
if (inRectCopy && io.MouseReleased[0])
|
||||
{
|
||||
sequence->Copy();
|
||||
}
|
||||
if (inRectPaste && io.MouseReleased[0])
|
||||
{
|
||||
sequence->Paste();
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::PopStyleColor();
|
||||
if (hasScrollBar)
|
||||
{
|
||||
ImGui::InvisibleButton("scrollBar", scrollBarSize);
|
||||
ImVec2 scrollBarMin = ImGui::GetItemRectMin();
|
||||
ImVec2 scrollBarMax = ImGui::GetItemRectMax();
|
||||
|
||||
// ratio = number of frames visible in control / number to total frames
|
||||
|
||||
float startFrameOffset = ((float)(firstFrameUsed - sequence->GetFrameMin()) / (float)frameCount) * (canvas_size.x - legendWidth);
|
||||
ImVec2 scrollBarA(scrollBarMin.x + legendWidth, scrollBarMin.y - 2);
|
||||
ImVec2 scrollBarB(scrollBarMin.x + canvas_size.x, scrollBarMax.y - 1);
|
||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF222222, 0);
|
||||
|
||||
ImRect scrollBarRect(scrollBarA, scrollBarB);
|
||||
bool inScrollBar = scrollBarRect.Contains(io.MousePos);
|
||||
|
||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF101010, 8);
|
||||
|
||||
|
||||
ImVec2 scrollBarC(scrollBarMin.x + legendWidth + startFrameOffset, scrollBarMin.y);
|
||||
ImVec2 scrollBarD(scrollBarMin.x + legendWidth + barWidthInPixels + startFrameOffset, scrollBarMax.y - 2);
|
||||
draw_list->AddRectFilled(scrollBarC, scrollBarD, (inScrollBar || MovingScrollBar) ? 0xFF606060 : 0xFF505050, 6);
|
||||
|
||||
float handleRadius = (scrollBarMax.y - scrollBarMin.y) / 2;
|
||||
ImRect barHandleLeft(scrollBarC, ImVec2(scrollBarC.x + 14, scrollBarD.y));
|
||||
ImRect barHandleRight(ImVec2(scrollBarD.x - 14, scrollBarC.y), scrollBarD);
|
||||
|
||||
bool onLeft = barHandleLeft.Contains(io.MousePos);
|
||||
bool onRight = barHandleRight.Contains(io.MousePos);
|
||||
|
||||
static bool sizingRBar = false;
|
||||
static bool sizingLBar = false;
|
||||
|
||||
draw_list->AddRectFilled(barHandleLeft.Min, barHandleLeft.Max, (onLeft || sizingLBar) ? 0xFFAAAAAA : 0xFF666666, 6);
|
||||
draw_list->AddRectFilled(barHandleRight.Min, barHandleRight.Max, (onRight || sizingRBar) ? 0xFFAAAAAA : 0xFF666666, 6);
|
||||
|
||||
ImRect scrollBarThumb(scrollBarC, scrollBarD);
|
||||
static const float MinBarWidth = 44.f;
|
||||
if (sizingRBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
sizingRBar = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
float barNewWidth = ImMax(barWidthInPixels + io.MouseDelta.x, MinBarWidth);
|
||||
float barRatio = barNewWidth / barWidthInPixels;
|
||||
framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;
|
||||
int newVisibleFrameCount = int((canvas_size.x - legendWidth) / framePixelWidthTarget);
|
||||
int lastFrame = *firstFrame + newVisibleFrameCount;
|
||||
if (lastFrame > sequence->GetFrameMax())
|
||||
{
|
||||
framePixelWidthTarget = framePixelWidth = (canvas_size.x - legendWidth) / float(sequence->GetFrameMax() - *firstFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sizingLBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
sizingLBar = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fabsf(io.MouseDelta.x) > FLT_EPSILON)
|
||||
{
|
||||
float barNewWidth = ImMax(barWidthInPixels - io.MouseDelta.x, MinBarWidth);
|
||||
float barRatio = barNewWidth / barWidthInPixels;
|
||||
float previousFramePixelWidthTarget = framePixelWidthTarget;
|
||||
framePixelWidthTarget = framePixelWidth = framePixelWidth / barRatio;
|
||||
int newVisibleFrameCount = int(visibleFrameCount / barRatio);
|
||||
int newFirstFrame = *firstFrame + newVisibleFrameCount - visibleFrameCount;
|
||||
newFirstFrame = ImClamp(newFirstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));
|
||||
if (newFirstFrame == *firstFrame)
|
||||
{
|
||||
framePixelWidth = framePixelWidthTarget = previousFramePixelWidthTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
*firstFrame = newFirstFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MovingScrollBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
MovingScrollBar = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
float framesPerPixelInBar = barWidthInPixels / (float)visibleFrameCount;
|
||||
*firstFrame = int((io.MousePos.x - panningViewSource.x) / framesPerPixelInBar) - panningViewFrame;
|
||||
*firstFrame = ImClamp(*firstFrame, sequence->GetFrameMin(), ImMax(sequence->GetFrameMax() - visibleFrameCount, sequence->GetFrameMin()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scrollBarThumb.Contains(io.MousePos) && ImGui::IsMouseClicked(0) && firstFrame && !MovingCurrentFrame && movingEntry == -1)
|
||||
{
|
||||
MovingScrollBar = true;
|
||||
panningViewSource = io.MousePos;
|
||||
panningViewFrame = -*firstFrame;
|
||||
}
|
||||
if (!sizingRBar && onRight && ImGui::IsMouseClicked(0))
|
||||
sizingRBar = true;
|
||||
if (!sizingLBar && onLeft && ImGui::IsMouseClicked(0))
|
||||
sizingLBar = true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
if (regionRect.Contains(io.MousePos))
|
||||
{
|
||||
bool overCustomDraw = false;
|
||||
for (auto& custom : customDraws)
|
||||
{
|
||||
if (custom.customRect.Contains(io.MousePos))
|
||||
{
|
||||
overCustomDraw = true;
|
||||
}
|
||||
}
|
||||
if (overCustomDraw)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
frameOverCursor = *firstFrame + (int)(visibleFrameCount * ((io.MousePos.x - (float)legendWidth - canvas_pos.x) / (canvas_size.x - legendWidth)));
|
||||
//frameOverCursor = max(min(*firstFrame - visibleFrameCount / 2, frameCount - visibleFrameCount), 0);
|
||||
|
||||
/**firstFrame -= frameOverCursor;
|
||||
*firstFrame *= framePixelWidthTarget / framePixelWidth;
|
||||
*firstFrame += frameOverCursor;*/
|
||||
if (io.MouseWheel < -FLT_EPSILON)
|
||||
{
|
||||
*firstFrame -= frameOverCursor;
|
||||
*firstFrame = int(*firstFrame * 1.1f);
|
||||
framePixelWidthTarget *= 0.9f;
|
||||
*firstFrame += frameOverCursor;
|
||||
}
|
||||
|
||||
if (io.MouseWheel > FLT_EPSILON)
|
||||
{
|
||||
*firstFrame -= frameOverCursor;
|
||||
*firstFrame = int(*firstFrame * 0.9f);
|
||||
framePixelWidthTarget *= 1.1f;
|
||||
*firstFrame += frameOverCursor;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
bool overExpanded = SequencerAddDelButton(draw_list, ImVec2(canvas_pos.x + 2, canvas_pos.y + 2), !*expanded);
|
||||
if (overExpanded && io.MouseReleased[0])
|
||||
*expanded = !*expanded;
|
||||
}
|
||||
|
||||
if (delEntry != -1)
|
||||
{
|
||||
sequence->Del(delEntry);
|
||||
if (selectedEntry && (*selectedEntry == delEntry || *selectedEntry >= sequence->GetItemCount()))
|
||||
*selectedEntry = -1;
|
||||
}
|
||||
|
||||
if (dupEntry != -1)
|
||||
{
|
||||
sequence->Duplicate(dupEntry);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
51
src/external/imguizmo/ImSequencer.h
vendored
Normal file
51
src/external/imguizmo/ImSequencer.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
struct ImDrawList;
|
||||
struct ImRect;
|
||||
namespace ImSequencer
|
||||
{
|
||||
enum SEQUENCER_OPTIONS
|
||||
{
|
||||
SEQUENCER_EDIT_NONE = 0,
|
||||
SEQUENCER_EDIT_STARTEND = 1 << 1,
|
||||
SEQUENCER_CHANGE_FRAME = 1 << 3,
|
||||
SEQUENCER_ADD = 1 << 4,
|
||||
SEQUENCER_DEL = 1 << 5,
|
||||
SEQUENCER_COPYPASTE = 1 << 6,
|
||||
SEQUENCER_EDIT_ALL = SEQUENCER_EDIT_STARTEND | SEQUENCER_CHANGE_FRAME
|
||||
};
|
||||
|
||||
struct SequenceInterface
|
||||
{
|
||||
bool focused = false;
|
||||
virtual int GetFrameMin() const = 0;
|
||||
virtual int GetFrameMax() const = 0;
|
||||
virtual int GetItemCount() const = 0;
|
||||
|
||||
virtual void BeginEdit(int /*index*/) {}
|
||||
virtual void EndEdit() {}
|
||||
virtual int GetItemTypeCount() const { return 0; }
|
||||
virtual const char* GetItemTypeName(int /*typeIndex*/) const { return ""; }
|
||||
virtual const char* GetItemLabel(int /*index*/) const { return ""; }
|
||||
|
||||
virtual void Get(int index, int** start, int** end, int* type, unsigned int* color) = 0;
|
||||
virtual void Add(int /*type*/) {}
|
||||
virtual void Del(int /*index*/) {}
|
||||
virtual void Duplicate(int /*index*/) {}
|
||||
|
||||
virtual void Copy() {}
|
||||
virtual void Paste() {}
|
||||
|
||||
virtual size_t GetCustomHeight(int /*index*/) { return 0; }
|
||||
virtual void DoubleClick(int /*index*/) {}
|
||||
virtual void CustomDraw(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*legendRect*/, const ImRect& /*clippingRect*/, const ImRect& /*legendClippingRect*/) {}
|
||||
virtual void CustomDrawCompact(int /*index*/, ImDrawList* /*draw_list*/, const ImRect& /*rc*/, const ImRect& /*clippingRect*/) {}
|
||||
};
|
||||
|
||||
|
||||
// return true if selection is made
|
||||
bool Sequencer(SequenceInterface* sequence, int* currentFrame, bool* expanded, int* selectedEntry, int* firstFrame, int sequenceOptions);
|
||||
|
||||
}
|
||||
245
src/external/imguizmo/ImZoomSlider.h
vendored
Normal file
245
src/external/imguizmo/ImZoomSlider.h
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
// https://github.com/CedricGuillemet/ImGuizmo
|
||||
// ImZoomSlider v 1.0
|
||||
//
|
||||
// The MIT License(MIT)
|
||||
//
|
||||
// Copyright(c) 2020 Cedric Guillemet
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files(the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions :
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
namespace ImZoomSlider
|
||||
{
|
||||
typedef int ImGuiZoomSliderFlags;
|
||||
enum ImGuiPopupFlags_
|
||||
{
|
||||
ImGuiZoomSliderFlags_None = 0,
|
||||
ImGuiZoomSliderFlags_Vertical = 1,
|
||||
ImGuiZoomSliderFlags_NoAnchors = 2,
|
||||
ImGuiZoomSliderFlags_NoMiddleCarets = 4,
|
||||
ImGuiZoomSliderFlags_NoWheel = 8,
|
||||
};
|
||||
|
||||
template<typename T> bool ImZoomSlider(const T lower, const T higher, T& viewLower, T& viewHigher, float wheelRatio = 0.01f, ImGuiZoomSliderFlags flags = ImGuiZoomSliderFlags_None)
|
||||
{
|
||||
bool interacted = false;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
static const float handleSize = 12;
|
||||
static const float roundRadius = 3.f;
|
||||
static const char* controlName = "ImZoomSlider";
|
||||
|
||||
static bool movingScrollBarSvg = false;
|
||||
static bool sizingRBarSvg = false;
|
||||
static bool sizingLBarSvg = false;
|
||||
static ImGuiID editingId = -1;
|
||||
static float scrollingSource = 0.f;
|
||||
static float saveViewLower;
|
||||
static float saveViewHigher;
|
||||
|
||||
const bool isVertical = flags & ImGuiZoomSliderFlags_Vertical;
|
||||
const ImVec2 canvasPos = ImGui::GetCursorScreenPos();
|
||||
const ImVec2 canvasSize = ImGui::GetContentRegionAvail();
|
||||
const float canvasSizeLength = isVertical ? ImGui::GetItemRectSize().y : canvasSize.x;
|
||||
const ImVec2 scrollBarSize = isVertical ? ImVec2(14.f, canvasSizeLength) : ImVec2(canvasSizeLength, 14.f);
|
||||
|
||||
ImGui::InvisibleButton(controlName, scrollBarSize);
|
||||
const ImGuiID currentId = ImGui::GetID(controlName);
|
||||
|
||||
const bool usingEditingId = currentId == editingId;
|
||||
const bool canUseControl = usingEditingId || editingId == -1;
|
||||
const bool movingScrollBar = usingEditingId ? movingScrollBarSvg : false;
|
||||
const bool sizingRBar = usingEditingId ? sizingRBarSvg : false;
|
||||
const bool sizingLBar = usingEditingId ? sizingLBarSvg : false;
|
||||
const int componentIndex = isVertical ? 1 : 0;
|
||||
const ImVec2 scrollBarMin = ImGui::GetItemRectMin();
|
||||
const ImVec2 scrollBarMax = ImGui::GetItemRectMax();
|
||||
const ImVec2 scrollBarA = ImVec2(scrollBarMin.x, scrollBarMin.y) - (isVertical ? ImVec2(2,0) : ImVec2(0,2));
|
||||
const ImVec2 scrollBarB = isVertical ? ImVec2(scrollBarMax.x - 1.f, scrollBarMin.y + canvasSizeLength) : ImVec2(scrollBarMin.x + canvasSizeLength, scrollBarMax.y - 1.f);
|
||||
const float scrollStart = ((viewLower - lower) / (higher - lower)) * canvasSizeLength + scrollBarMin[componentIndex];
|
||||
const float scrollEnd = ((viewHigher - lower) / (higher - lower)) * canvasSizeLength + scrollBarMin[componentIndex];
|
||||
const float screenSize = scrollEnd - scrollStart;
|
||||
const ImVec2 scrollTopLeft = isVertical ? ImVec2(scrollBarMin.x, scrollStart) : ImVec2(scrollStart, scrollBarMin.y);
|
||||
const ImVec2 scrollBottomRight = isVertical ? ImVec2(scrollBarMax.x - 2.f, scrollEnd) : ImVec2(scrollEnd, scrollBarMax.y - 2.f);
|
||||
const bool inScrollBar = canUseControl && ImRect(scrollTopLeft, scrollBottomRight).Contains(io.MousePos);
|
||||
const ImRect scrollBarRect(scrollBarA, scrollBarB);
|
||||
const float deltaScreen = io.MousePos[componentIndex] - scrollingSource;
|
||||
const float deltaView = ((higher - lower) / canvasSizeLength) * deltaScreen;
|
||||
const uint32_t barColor = ImGui::GetColorU32((inScrollBar || movingScrollBar) ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
|
||||
const float middleCoord = (scrollStart + scrollEnd) * 0.5f;
|
||||
const bool insideControl = canUseControl && ImRect(scrollBarMin, scrollBarMax).Contains(io.MousePos);
|
||||
const bool hasAnchors = !(flags & ImGuiZoomSliderFlags_NoAnchors);
|
||||
const float viewMinSize = ((3.f * handleSize) / canvasSizeLength) * (higher - lower);
|
||||
const auto ClipView = [lower, higher, &viewLower, &viewHigher]() {
|
||||
if (viewLower < lower)
|
||||
{
|
||||
const float deltaClip = lower - viewLower;
|
||||
viewLower += deltaClip;
|
||||
viewHigher += deltaClip;
|
||||
}
|
||||
if (viewHigher > higher)
|
||||
{
|
||||
const float deltaClip = viewHigher - higher;
|
||||
viewLower -= deltaClip;
|
||||
viewHigher -= deltaClip;
|
||||
}
|
||||
};
|
||||
|
||||
bool onLeft = false;
|
||||
bool onRight = false;
|
||||
|
||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF101010, roundRadius);
|
||||
draw_list->AddRectFilled(scrollBarA, scrollBarB, 0xFF222222, 0);
|
||||
draw_list->AddRectFilled(scrollTopLeft, scrollBottomRight, barColor, roundRadius);
|
||||
|
||||
if (!(flags & ImGuiZoomSliderFlags_NoMiddleCarets))
|
||||
{
|
||||
for (float i = 0.5f; i < 3.f; i += 1.f)
|
||||
{
|
||||
const float coordA = middleCoord - handleSize * 0.5f;
|
||||
const float coordB = middleCoord + handleSize * 0.5f;
|
||||
ImVec2 base = scrollBarMin;
|
||||
base.x += scrollBarSize.x * 0.25f * i;
|
||||
base.y += scrollBarSize.y * 0.25f * i;
|
||||
|
||||
if (isVertical)
|
||||
{
|
||||
draw_list->AddLine(ImVec2(base.x, coordA), ImVec2(base.x, coordB), ImGui::GetColorU32(ImGuiCol_SliderGrab));
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_list->AddLine(ImVec2(coordA, base.y), ImVec2(coordB, base.y), ImGui::GetColorU32(ImGuiCol_SliderGrab));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse wheel
|
||||
if (io.MouseClicked[0] && insideControl && !inScrollBar)
|
||||
{
|
||||
const float ratio = (io.MousePos[componentIndex] - scrollBarMin[componentIndex]) / (scrollBarMax[componentIndex] - scrollBarMin[componentIndex]);
|
||||
const float size = (higher - lower);
|
||||
const float halfViewSize = (viewHigher - viewLower) * 0.5f;
|
||||
const float middle = ratio * size + lower;
|
||||
viewLower = middle - halfViewSize;
|
||||
viewHigher = middle + halfViewSize;
|
||||
ClipView();
|
||||
interacted = true;
|
||||
}
|
||||
|
||||
if (!(flags & ImGuiZoomSliderFlags_NoWheel) && inScrollBar && fabsf(io.MouseWheel) > 0.f)
|
||||
{
|
||||
const float ratio = (io.MousePos[componentIndex] - scrollStart) / (scrollEnd - scrollStart);
|
||||
const float amount = io.MouseWheel * wheelRatio * (viewHigher - viewLower);
|
||||
|
||||
viewLower -= ratio * amount;
|
||||
viewHigher += (1.f - ratio) * amount;
|
||||
ClipView();
|
||||
interacted = true;
|
||||
}
|
||||
|
||||
if (screenSize > handleSize * 2.f && hasAnchors)
|
||||
{
|
||||
const ImRect barHandleLeft(scrollTopLeft, isVertical ? ImVec2(scrollBottomRight.x, scrollTopLeft.y + handleSize) : ImVec2(scrollTopLeft.x + handleSize, scrollBottomRight.y));
|
||||
const ImRect barHandleRight(isVertical ? ImVec2(scrollTopLeft.x, scrollBottomRight.y - handleSize) : ImVec2(scrollBottomRight.x - handleSize, scrollTopLeft.y), scrollBottomRight);
|
||||
|
||||
onLeft = barHandleLeft.Contains(io.MousePos);
|
||||
onRight = barHandleRight.Contains(io.MousePos);
|
||||
|
||||
draw_list->AddRectFilled(barHandleLeft.Min, barHandleLeft.Max, ImGui::GetColorU32((onLeft || sizingLBar) ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), roundRadius);
|
||||
draw_list->AddRectFilled(barHandleRight.Min, barHandleRight.Max, ImGui::GetColorU32((onRight || sizingRBar) ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), roundRadius);
|
||||
}
|
||||
|
||||
if (sizingRBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
sizingRBarSvg = false;
|
||||
editingId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewHigher = ImMin(saveViewHigher + deltaView, higher);
|
||||
}
|
||||
}
|
||||
else if (sizingLBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
sizingLBarSvg = false;
|
||||
editingId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewLower = ImMax(saveViewLower + deltaView, lower);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (movingScrollBar)
|
||||
{
|
||||
if (!io.MouseDown[0])
|
||||
{
|
||||
movingScrollBarSvg = false;
|
||||
editingId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewLower = saveViewLower + deltaView;
|
||||
viewHigher = saveViewHigher + deltaView;
|
||||
ClipView();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inScrollBar && ImGui::IsMouseClicked(0))
|
||||
{
|
||||
movingScrollBarSvg = true;
|
||||
scrollingSource = io.MousePos[componentIndex];
|
||||
saveViewLower = viewLower;
|
||||
saveViewHigher = viewHigher;
|
||||
editingId = currentId;
|
||||
}
|
||||
if (!sizingRBar && onRight && ImGui::IsMouseClicked(0) && hasAnchors)
|
||||
{
|
||||
sizingRBarSvg = true;
|
||||
editingId = currentId;
|
||||
}
|
||||
if (!sizingLBar && onLeft && ImGui::IsMouseClicked(0) && hasAnchors)
|
||||
{
|
||||
sizingLBarSvg = true;
|
||||
editingId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// minimal size check
|
||||
if ((viewHigher - viewLower) < viewMinSize)
|
||||
{
|
||||
const float middle = (viewLower + viewHigher) * 0.5f;
|
||||
viewLower = middle - viewMinSize * 0.5f;
|
||||
viewHigher = middle + viewMinSize * 0.5f;
|
||||
ClipView();
|
||||
}
|
||||
|
||||
return movingScrollBar || sizingRBar || sizingLBar || interacted;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
21
src/external/imguizmo/LICENSE
vendored
Normal file
21
src/external/imguizmo/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Cedric Guillemet
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
167
src/external/imguizmo/README.md
vendored
Normal file
167
src/external/imguizmo/README.md
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
### ImViewGizmo
|
||||
Manipulate view orientation with 1 single line of code
|
||||
|
||||

|
||||
|
||||
### ImGuizmo
|
||||
|
||||
ImGizmo is a small (.h and .cpp) library built ontop of Dear ImGui that allow you to manipulate(Rotate & translate at the moment) 4x4 float matrices. No other dependancies. Coded with Immediate Mode (IM) philosophy in mind.
|
||||
|
||||
Built against DearImgui 1.53WIP
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
There is now a sample for Win32/OpenGL ! With a binary in bin directory.
|
||||

|
||||
|
||||
### ImSequencer
|
||||
A WIP little sequencer used to edit frame start/end for different events in a timeline.
|
||||

|
||||
Check the sample for the documentation. More to come...
|
||||
|
||||
### API doc
|
||||
|
||||
Call BeginFrame right after ImGui_XXXX_NewFrame();
|
||||
|
||||
```C++
|
||||
void BeginFrame();
|
||||
```
|
||||
|
||||
return true if mouse cursor is over any gizmo control (axis, plan or screen component)
|
||||
|
||||
```C++
|
||||
bool IsOver();**
|
||||
```
|
||||
|
||||
return true if mouse IsOver or if the gizmo is in moving state
|
||||
|
||||
```C++
|
||||
bool IsUsing();**
|
||||
```
|
||||
|
||||
enable/disable the gizmo. Stay in the state until next call to Enable. gizmo is rendered with gray half transparent color when disabled
|
||||
|
||||
```C++
|
||||
void Enable(bool enable);**
|
||||
```
|
||||
|
||||
helper functions for manualy editing translation/rotation/scale with an input float
|
||||
translation, rotation and scale float points to 3 floats each
|
||||
Angles are in degrees (more suitable for human editing)
|
||||
example:
|
||||
|
||||
```C++
|
||||
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
||||
ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
||||
ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
||||
ImGui::InputFloat3("Rt", matrixRotation, 3);
|
||||
ImGui::InputFloat3("Sc", matrixScale, 3);
|
||||
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);
|
||||
```
|
||||
|
||||
These functions have some numerical stability issues for now. Use with caution.
|
||||
|
||||
```C++
|
||||
void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale);
|
||||
void RecomposeMatrixFromComponents(const float *translation, const float *rotation, const float *scale, float *matrix);**
|
||||
```
|
||||
|
||||
Render a cube with face color corresponding to face normal. Usefull for debug/test
|
||||
|
||||
```C++
|
||||
void DrawCube(const float *view, const float *projection, float *matrix);**
|
||||
```
|
||||
|
||||
Call it when you want a gizmo
|
||||
Needs view and projection matrices.
|
||||
Matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional. snap points to a float[3] for translation and to a single float for scale or rotation. Snap angle is in Euler Degrees.
|
||||
|
||||
```C++
|
||||
enum OPERATION
|
||||
{
|
||||
TRANSLATE,
|
||||
ROTATE,
|
||||
SCALE
|
||||
};
|
||||
|
||||
enum MODE
|
||||
{
|
||||
LOCAL,
|
||||
WORLD
|
||||
};
|
||||
|
||||
void Manipulate(const float *view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix = 0, float *snap = 0);**
|
||||
```
|
||||
|
||||
### ImGui Example
|
||||
|
||||
Code for :
|
||||
|
||||

|
||||
|
||||
```C++
|
||||
void EditTransform(const Camera& camera, matrix_t& matrix)
|
||||
{
|
||||
static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
|
||||
static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
|
||||
if (ImGui::IsKeyPressed(90))
|
||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
||||
if (ImGui::IsKeyPressed(69))
|
||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
||||
if (ImGui::IsKeyPressed(82)) // r Key
|
||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
||||
if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
|
||||
mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
|
||||
mCurrentGizmoOperation = ImGuizmo::ROTATE;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
|
||||
mCurrentGizmoOperation = ImGuizmo::SCALE;
|
||||
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
||||
ImGuizmo::DecomposeMatrixToComponents(matrix.m16, matrixTranslation, matrixRotation, matrixScale);
|
||||
ImGui::InputFloat3("Tr", matrixTranslation, 3);
|
||||
ImGui::InputFloat3("Rt", matrixRotation, 3);
|
||||
ImGui::InputFloat3("Sc", matrixScale, 3);
|
||||
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);
|
||||
|
||||
if (mCurrentGizmoOperation != ImGuizmo::SCALE)
|
||||
{
|
||||
if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
|
||||
mCurrentGizmoMode = ImGuizmo::LOCAL;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
|
||||
mCurrentGizmoMode = ImGuizmo::WORLD;
|
||||
}
|
||||
static bool useSnap(false);
|
||||
if (ImGui::IsKeyPressed(83))
|
||||
useSnap = !useSnap;
|
||||
ImGui::Checkbox("", &useSnap);
|
||||
ImGui::SameLine();
|
||||
vec_t snap;
|
||||
switch (mCurrentGizmoOperation)
|
||||
{
|
||||
case ImGuizmo::TRANSLATE:
|
||||
snap = config.mSnapTranslation;
|
||||
ImGui::InputFloat3("Snap", &snap.x);
|
||||
break;
|
||||
case ImGuizmo::ROTATE:
|
||||
snap = config.mSnapRotation;
|
||||
ImGui::InputFloat("Angle Snap", &snap.x);
|
||||
break;
|
||||
case ImGuizmo::SCALE:
|
||||
snap = config.mSnapScale;
|
||||
ImGui::InputFloat("Scale Snap", &snap.x);
|
||||
break;
|
||||
}
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
|
||||
ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
|
||||
}
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
ImGuizmo is licensed under the MIT License, see LICENSE for more information.
|
||||
63
src/external/qtimgui/CMakeLists.txt
vendored
Normal file
63
src/external/qtimgui/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
cmake_minimum_required (VERSION 3.8.1)
|
||||
project(qtimgui)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
find_package(Qt5 COMPONENTS Core Quick Gui Widgets Svg REQUIRED)
|
||||
|
||||
# imgui library: imgui is build by default, but you can
|
||||
# provide your own version by setting QTIMGUI_BUILD_IMGUI to OFF
|
||||
option(QTIMGUI_BUILD_IMGUI "Use imgui provided as qtimgui submodule" ON)
|
||||
if (QTIMGUI_BUILD_IMGUI)
|
||||
add_library(imgui
|
||||
STATIC
|
||||
imgui/imconfig.h
|
||||
imgui/imgui_demo.cpp
|
||||
imgui/imgui_draw.cpp
|
||||
imgui/imgui_internal.h
|
||||
imgui/imgui_widgets.cpp
|
||||
imgui/imgui.cpp
|
||||
)
|
||||
target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui)
|
||||
endif(QTIMGUI_BUILD_IMGUI)
|
||||
|
||||
set(
|
||||
qt_imgui_sources
|
||||
ImGuiRenderer.h
|
||||
ImGuiRenderer.cpp
|
||||
QtImGui.h
|
||||
QtImGui.cpp
|
||||
)
|
||||
|
||||
# qt_imgui_quick: library with a qt renderer for Qml / QtQuick applications
|
||||
add_library(qt_imgui_quick STATIC ${qt_imgui_sources})
|
||||
target_include_directories(qt_imgui_quick PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(
|
||||
qt_imgui_quick
|
||||
PUBLIC
|
||||
imgui
|
||||
Qt5::Core Qt5::Quick Qt5::Svg
|
||||
)
|
||||
if (ANDROID)
|
||||
target_link_libraries(qt_imgui_quick PUBLIC log dl GLESv2 z)
|
||||
endif()
|
||||
|
||||
# qt_imgui_widget: library with a qt renderer for classic Qt Widget applications
|
||||
add_library(qt_imgui_widgets STATIC ${qt_imgui_sources})
|
||||
target_include_directories(qt_imgui_widgets PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(
|
||||
qt_imgui_widgets
|
||||
PUBLIC
|
||||
imgui
|
||||
Qt5::Core Qt5::Widgets Qt5::Svg
|
||||
)
|
||||
if (ANDROID)
|
||||
target_link_libraries(qt_imgui_widgets PUBLIC log dl GLESv2 z)
|
||||
endif()
|
||||
target_compile_definitions(qt_imgui_widgets PUBLIC QT_WIDGETS_LIB)
|
||||
|
||||
# Demo with Qt quick
|
||||
add_subdirectory(demo-window)
|
||||
# Demo with classic widgets
|
||||
add_subdirectory(demo-widget)
|
||||
439
src/external/qtimgui/ImGuiRenderer.cpp
vendored
Normal file
439
src/external/qtimgui/ImGuiRenderer.cpp
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
#include "ImGuiRenderer.h"
|
||||
#include <QDateTime>
|
||||
#include <QGuiApplication>
|
||||
#include <QMouseEvent>
|
||||
#include <QClipboard>
|
||||
#include <QCursor>
|
||||
#include <QDebug>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef ANDROID
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5 // Missing in android as of May 2020
|
||||
#define USE_GLSL_ES
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLSL_ES
|
||||
#define IMGUIRENDERER_GLSL_VERSION "#version 300 es\n"
|
||||
#else
|
||||
#define IMGUIRENDERER_GLSL_VERSION "#version 330\n"
|
||||
#endif
|
||||
|
||||
namespace QtImGui {
|
||||
|
||||
namespace {
|
||||
|
||||
QHash<int, ImGuiKey> keyMap = {
|
||||
{ Qt::Key_Tab, ImGuiKey_Tab },
|
||||
{ Qt::Key_Left, ImGuiKey_LeftArrow },
|
||||
{ Qt::Key_Right, ImGuiKey_RightArrow },
|
||||
{ Qt::Key_Up, ImGuiKey_UpArrow },
|
||||
{ Qt::Key_Down, ImGuiKey_DownArrow },
|
||||
{ Qt::Key_PageUp, ImGuiKey_PageUp },
|
||||
{ Qt::Key_PageDown, ImGuiKey_PageDown },
|
||||
{ Qt::Key_Home, ImGuiKey_Home },
|
||||
{ Qt::Key_End, ImGuiKey_End },
|
||||
{ Qt::Key_Delete, ImGuiKey_Delete },
|
||||
{ Qt::Key_Backspace, ImGuiKey_Backspace },
|
||||
{ Qt::Key_Enter, ImGuiKey_Enter },
|
||||
{ Qt::Key_Return, ImGuiKey_Enter },
|
||||
{ Qt::Key_Escape, ImGuiKey_Escape },
|
||||
{ Qt::Key_A, ImGuiKey_A },
|
||||
{ Qt::Key_C, ImGuiKey_C },
|
||||
{ Qt::Key_V, ImGuiKey_V },
|
||||
{ Qt::Key_X, ImGuiKey_X },
|
||||
{ Qt::Key_Y, ImGuiKey_Y },
|
||||
{ Qt::Key_Z, ImGuiKey_Z },
|
||||
};
|
||||
|
||||
QByteArray g_currentClipboardText;
|
||||
|
||||
}
|
||||
|
||||
void ImGuiRenderer::initialize(WindowWrapper *window, ImGuiContext* context) {
|
||||
m_window.reset(window);
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
_context = context;
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
for (ImGuiKey key : keyMap.values()) {
|
||||
io.KeyMap[key] = key;
|
||||
}
|
||||
|
||||
io.RenderDrawListsFn = [](ImDrawData *drawData) {
|
||||
instance(ImGui::GetCurrentContext())->renderDrawList(drawData);
|
||||
};
|
||||
io.SetClipboardTextFn = [](void *user_data, const char *text) {
|
||||
Q_UNUSED(user_data);
|
||||
QGuiApplication::clipboard()->setText(text);
|
||||
};
|
||||
io.GetClipboardTextFn = [](void *user_data) {
|
||||
Q_UNUSED(user_data);
|
||||
g_currentClipboardText = QGuiApplication::clipboard()->text().toUtf8();
|
||||
return (const char *)g_currentClipboardText.data();
|
||||
};
|
||||
|
||||
window->installEventFilter(this);
|
||||
}
|
||||
|
||||
void ImGuiRenderer::renderDrawList(ImDrawData *draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Backup GL state
|
||||
GLint last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
|
||||
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
|
||||
GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
GLint last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, &last_blend_src_rgb);
|
||||
GLint last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, &last_blend_dst_rgb);
|
||||
GLint last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, &last_blend_src_alpha);
|
||||
GLint last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, &last_blend_dst_alpha);
|
||||
GLint last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
|
||||
GLint last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
|
||||
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
|
||||
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
|
||||
GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
|
||||
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
|
||||
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
|
||||
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{-1.0f, 1.0f, 0.0f, 1.0f },
|
||||
};
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(size_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
}
|
||||
idx_buffer_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore modified GL state
|
||||
glUseProgram(last_program);
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glActiveTexture(last_active_texture);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
|
||||
glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
|
||||
glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
|
||||
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
|
||||
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
|
||||
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
|
||||
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
|
||||
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
|
||||
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
|
||||
}
|
||||
|
||||
bool ImGuiRenderer::createFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(size_t)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderer::createDeviceObjects()
|
||||
{
|
||||
// Backup GL state
|
||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
|
||||
const GLchar *vertex_shader =
|
||||
IMGUIRENDERER_GLSL_VERSION
|
||||
"uniform mat4 ProjMtx;\n"
|
||||
"in vec2 Position;\n"
|
||||
"in vec2 UV;\n"
|
||||
"in vec4 Color;\n"
|
||||
"out vec2 Frag_UV;\n"
|
||||
"out vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader =
|
||||
IMGUIRENDERER_GLSL_VERSION
|
||||
"precision mediump float;"
|
||||
"uniform sampler2D Texture;\n"
|
||||
"in vec2 Frag_UV;\n"
|
||||
"in vec4 Frag_Color;\n"
|
||||
"out vec4 Out_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
g_ShaderHandle = glCreateProgram();
|
||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
|
||||
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
|
||||
glCompileShader(g_VertHandle);
|
||||
glCompileShader(g_FragHandle);
|
||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||
glLinkProgram(g_ShaderHandle);
|
||||
|
||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||
|
||||
glGenBuffers(1, &g_VboHandle);
|
||||
glGenBuffers(1, &g_ElementsHandle);
|
||||
|
||||
glGenVertexArrays(1, &g_VaoHandle);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
||||
#undef OFFSETOF
|
||||
|
||||
createFontsTexture();
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGuiRenderer::newFrame()
|
||||
{
|
||||
ImGui::SetCurrentContext(_context);
|
||||
if (!g_FontTexture)
|
||||
createDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
io.DisplaySize = ImVec2(m_window->size().width(), m_window->size().height());
|
||||
io.DisplayFramebufferScale = ImVec2(m_window->devicePixelRatio(), m_window->devicePixelRatio());
|
||||
|
||||
// Setup time step
|
||||
double current_time = QDateTime::currentMSecsSinceEpoch() / double(1000);
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
if (m_window->isActive())
|
||||
{
|
||||
auto pos = m_window->mapFromGlobal(QCursor::pos());
|
||||
io.MousePos = ImVec2(pos.x(), pos.y()); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
}
|
||||
else
|
||||
{
|
||||
io.MousePos = ImVec2(-1,-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
io.MouseDown[i] = g_MousePressed[i];
|
||||
}
|
||||
|
||||
io.MouseWheelH = g_MouseWheelH;
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheelH = 0;
|
||||
g_MouseWheel = 0;
|
||||
|
||||
// Hide OS mouse cursor if ImGui is drawing it
|
||||
// glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void ImGuiRenderer::onMousePressedChange(QMouseEvent *event)
|
||||
{
|
||||
g_MousePressed[0] = event->buttons() & Qt::LeftButton;
|
||||
g_MousePressed[1] = event->buttons() & Qt::RightButton;
|
||||
g_MousePressed[2] = event->buttons() & Qt::MiddleButton;
|
||||
}
|
||||
|
||||
void ImGuiRenderer::onWheel(QWheelEvent *event)
|
||||
{
|
||||
// Handle horizontal component
|
||||
if(event->pixelDelta().x() != 0)
|
||||
{
|
||||
g_MouseWheelH += event->pixelDelta().x() / (ImGui::GetTextLineHeight());
|
||||
} else {
|
||||
// Magic number of 120 comes from Qt doc on QWheelEvent::pixelDelta()
|
||||
g_MouseWheelH += event->angleDelta().x() / 120;
|
||||
}
|
||||
|
||||
// Handle vertical component
|
||||
if(event->pixelDelta().y() != 0)
|
||||
{
|
||||
// 5 lines per unit
|
||||
g_MouseWheel += event->pixelDelta().y() / (5.0 * ImGui::GetTextLineHeight());
|
||||
} else {
|
||||
// Magic number of 120 comes from Qt doc on QWheelEvent::pixelDelta()
|
||||
g_MouseWheel += event->angleDelta().y() / 120;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiRenderer::onKeyPressRelease(QKeyEvent *event)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (keyMap.contains(event->key())) {
|
||||
io.KeysDown[keyMap[event->key()]] = event->type() == QEvent::KeyPress;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QString text = event->text();
|
||||
if (text.size() == 1) {
|
||||
io.AddInputCharacter(text.at(0).unicode());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
io.KeyCtrl = event->modifiers() & Qt::MetaModifier;
|
||||
io.KeyShift = event->modifiers() & Qt::ShiftModifier;
|
||||
io.KeyAlt = event->modifiers() & Qt::AltModifier;
|
||||
io.KeySuper = event->modifiers() & Qt::ControlModifier; // Comamnd key
|
||||
#else
|
||||
io.KeyCtrl = event->modifiers() & Qt::ControlModifier;
|
||||
io.KeyShift = event->modifiers() & Qt::ShiftModifier;
|
||||
io.KeyAlt = event->modifiers() & Qt::AltModifier;
|
||||
io.KeySuper = event->modifiers() & Qt::MetaModifier;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ImGuiRenderer::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
this->onMousePressedChange(static_cast<QMouseEvent *>(event));
|
||||
break;
|
||||
case QEvent::Wheel:
|
||||
this->onWheel(static_cast<QWheelEvent *>(event));
|
||||
break;
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
this->onKeyPressRelease(static_cast<QKeyEvent *>(event));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
ImGuiRenderer* ImGuiRenderer::instance(ImGuiContext* context) {
|
||||
|
||||
auto it = QtImGui::instances.find(context);
|
||||
|
||||
ImGuiRenderer* instance = nullptr;
|
||||
if (it == QtImGui::instances.end())
|
||||
{
|
||||
instance = new ImGuiRenderer();
|
||||
QtImGui::instances[context] = instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = QtImGui::instances[context];
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
ImGuiRenderer* ImGuiRenderer::instance() {
|
||||
|
||||
ImGuiContext* context = ImGui::GetCurrentContext();
|
||||
auto it = QtImGui::instances.find(context);
|
||||
|
||||
ImGuiRenderer* instance = nullptr;
|
||||
if (it == QtImGui::instances.end())
|
||||
{
|
||||
throw std::logic_error("Context was not created");
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = instances[context];
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
64
src/external/qtimgui/ImGuiRenderer.h
vendored
Normal file
64
src/external/qtimgui/ImGuiRenderer.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <imgui.h>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
class QKeyEvent;
|
||||
|
||||
namespace QtImGui {
|
||||
|
||||
class WindowWrapper {
|
||||
public:
|
||||
virtual ~WindowWrapper() {}
|
||||
virtual void installEventFilter(QObject *object) = 0;
|
||||
virtual QSize size() const = 0;
|
||||
virtual qreal devicePixelRatio() const = 0;
|
||||
virtual bool isActive() const = 0;
|
||||
virtual QPoint mapFromGlobal(const QPoint &p) const = 0;
|
||||
};
|
||||
|
||||
class ImGuiRenderer : public QObject, QOpenGLExtraFunctions {
|
||||
Q_OBJECT
|
||||
public:
|
||||
void initialize(WindowWrapper *window, ImGuiContext* context);
|
||||
void newFrame();
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
|
||||
static ImGuiRenderer *instance();
|
||||
static ImGuiRenderer *instance(ImGuiContext* context);
|
||||
|
||||
private:
|
||||
ImGuiRenderer() {}
|
||||
|
||||
void onMousePressedChange(QMouseEvent *event);
|
||||
void onWheel(QWheelEvent *event);
|
||||
void onKeyPressRelease(QKeyEvent *event);
|
||||
|
||||
void renderDrawList(ImDrawData *draw_data);
|
||||
bool createFontsTexture();
|
||||
bool createDeviceObjects();
|
||||
|
||||
std::unique_ptr<WindowWrapper> m_window;
|
||||
double g_Time = 0.0f;
|
||||
bool g_MousePressed[3] = { false, false, false };
|
||||
float g_MouseWheel;
|
||||
float g_MouseWheelH;
|
||||
GLuint g_FontTexture = 0;
|
||||
int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||
int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
|
||||
ImGuiContext* _context;
|
||||
|
||||
};
|
||||
|
||||
static std::unordered_map<ImGuiContext*, ImGuiRenderer*> instances;
|
||||
|
||||
}
|
||||
85
src/external/qtimgui/QtImGui.cpp
vendored
Normal file
85
src/external/qtimgui/QtImGui.cpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "QtImGui.h"
|
||||
#include "ImGuiRenderer.h"
|
||||
#include <QWindow>
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
namespace QtImGui {
|
||||
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
|
||||
namespace {
|
||||
|
||||
class QWidgetWindowWrapper : public WindowWrapper {
|
||||
public:
|
||||
QWidgetWindowWrapper(QWidget *w) : w(w) {}
|
||||
void installEventFilter(QObject *object) override {
|
||||
return w->installEventFilter(object);
|
||||
}
|
||||
QSize size() const override {
|
||||
return w->size();
|
||||
}
|
||||
qreal devicePixelRatio() const override {
|
||||
return w->devicePixelRatioF();
|
||||
}
|
||||
bool isActive() const override {
|
||||
return w->isActiveWindow();
|
||||
}
|
||||
QPoint mapFromGlobal(const QPoint &p) const override {
|
||||
return w->mapFromGlobal(p);
|
||||
}
|
||||
private:
|
||||
QWidget *w;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ImGuiContext* initialize(QWidget *window) {
|
||||
ImGuiContext* context = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(context);
|
||||
ImGuiRenderer::instance(context)->initialize(new QWidgetWindowWrapper(window), context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
class QWindowWindowWrapper : public WindowWrapper {
|
||||
public:
|
||||
QWindowWindowWrapper(QWindow *w) : w(w) {}
|
||||
void installEventFilter(QObject *object) override {
|
||||
return w->installEventFilter(object);
|
||||
}
|
||||
QSize size() const override {
|
||||
return w->size();
|
||||
}
|
||||
qreal devicePixelRatio() const override {
|
||||
return w->devicePixelRatio();
|
||||
}
|
||||
bool isActive() const override {
|
||||
return w->isActive();
|
||||
}
|
||||
QPoint mapFromGlobal(const QPoint &p) const override {
|
||||
return w->mapFromGlobal(p);
|
||||
}
|
||||
private:
|
||||
QWindow *w;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ImGuiContext* initialize(QWindow *window) {
|
||||
ImGuiContext* context = ImGui::CreateContext();
|
||||
ImGuiRenderer::instance(context)->initialize(new QWindowWindowWrapper(window), context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void newFrame() {
|
||||
ImGuiRenderer::instance()->newFrame();
|
||||
}
|
||||
|
||||
}
|
||||
17
src/external/qtimgui/QtImGui.h
vendored
Normal file
17
src/external/qtimgui/QtImGui.h
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
class QWidget;
|
||||
class QWindow;
|
||||
|
||||
namespace QtImGui {
|
||||
|
||||
#ifdef QT_WIDGETS_LIB
|
||||
ImGuiContext* initialize(QWidget *window);
|
||||
#endif
|
||||
|
||||
ImGuiContext* initialize(QWindow *window);
|
||||
void newFrame();
|
||||
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <noggit/Selection.h>
|
||||
#include <noggit/tool_enums.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
#include <external/qtimgui/QtImGui.h>
|
||||
#include <external/qtimgui/imgui/imgui.h>
|
||||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
@@ -38,6 +40,8 @@ void ModelViewer::initializeGL()
|
||||
gl.viewport(0.0f, 0.0f, width(), height());
|
||||
gl.clearColor (0.5f, 0.5f, 0.5f, 1.0f);
|
||||
emit resized();
|
||||
|
||||
_imgui_context = QtImGui::initialize(this);
|
||||
}
|
||||
|
||||
void ModelViewer::paintGL()
|
||||
@@ -54,6 +58,15 @@ void ModelViewer::paintGL()
|
||||
_last_update = now;
|
||||
|
||||
draw();
|
||||
|
||||
ImGui::SetCurrentContext(_imgui_context);
|
||||
QtImGui::newFrame();
|
||||
|
||||
ImGui::Text("Test");
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ModelViewer::resizeGL(int w, int h)
|
||||
@@ -119,12 +132,14 @@ void ModelViewer::mouseMoveEvent(QMouseEvent* event)
|
||||
|
||||
void ModelViewer::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
look = true;
|
||||
if (event->button() == Qt::RightButton)
|
||||
look = true;
|
||||
}
|
||||
|
||||
void ModelViewer::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
look = false;
|
||||
if (event->button() == Qt::RightButton)
|
||||
look = false;
|
||||
}
|
||||
|
||||
void ModelViewer::wheelEvent(QWheelEvent* event)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <noggit/WMO.h>
|
||||
#include <noggit/Model.h>
|
||||
#include <noggit/Red/PreviewRenderer/PreviewRenderer.hpp>
|
||||
#include <external/qtimgui/QtImGui.h>
|
||||
|
||||
|
||||
namespace noggit
|
||||
@@ -76,6 +77,8 @@ namespace noggit
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void focusOutEvent(QFocusEvent* event) override;
|
||||
|
||||
ImGuiContext* _imgui_context;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ MapCreationWizard::MapCreationWizard(QWidget* parent) : noggit::ui::widget(paren
|
||||
std::string name = i->getLocalizedString(MapDB::Name);
|
||||
int area_type = i->getUInt(MapDB::AreaType);
|
||||
|
||||
if (area_type < 0 ||area_type > 4 || !World::IsEditableWorld(map_id))
|
||||
if (area_type < 0 || area_type > 4 || !World::IsEditableWorld(map_id))
|
||||
continue;
|
||||
|
||||
_corpse_map_id->addItem(QString::number(map_id) + " - " + QString::fromUtf8 (name.c_str()));
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
#include "ModelView.hpp"
|
||||
#include <math/projection.hpp>
|
||||
#include <external/qtimgui/imgui/imgui.h>
|
||||
#include <external/imguizmo/ImGuizmo.h>
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QVector3D>
|
||||
|
||||
using namespace noggit::Red::PresetEditor;
|
||||
|
||||
ModelViewer::ModelViewer(QWidget *parent)
|
||||
: AssetBrowser::ModelViewer(parent, noggit::NoggitRenderContext::PRESET_EDITOR)
|
||||
, _world(std::make_unique<World> ("azeroth", 0, noggit::NoggitRenderContext::PRESET_EDITOR))
|
||||
, _world(nullptr)
|
||||
, _world_camera(_camera.position, _camera.yaw(), _camera.pitch())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ModelViewer::paintGL()
|
||||
@@ -24,50 +30,187 @@ void ModelViewer::paintGL()
|
||||
MinimapRenderSettings _settings_unused;
|
||||
std::map<int, misc::random_color> area_id_colors;
|
||||
|
||||
_world->draw(model_view().transposed()
|
||||
, projection().transposed()
|
||||
, math::vector_3d(0.f, 0.f, 0.f)
|
||||
, 0.f
|
||||
, math::vector_4d(1.f, 1.f, 1.f, 1.f)
|
||||
, CursorType::CIRCLE
|
||||
, 0.f
|
||||
, false
|
||||
, false
|
||||
, 0.f
|
||||
, math::vector_3d(0.f, 0.f, 0.f)
|
||||
, 0.f
|
||||
, 0.f
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, editing_mode::ground
|
||||
, math::vector_3d(0.f, 0.f, 0.f)
|
||||
, true
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, &_settings_unused
|
||||
, area_id_colors
|
||||
, false
|
||||
, eTerrainType::eTerrainType_Flat
|
||||
, 0
|
||||
, display_mode::in_3D
|
||||
if (_world)
|
||||
{
|
||||
_world->draw(world_model_view().transposed()
|
||||
, world_projection().transposed()
|
||||
, math::vector_3d(0.f, 0.f, 0.f)
|
||||
, 0.f
|
||||
, math::vector_4d(1.f, 1.f, 1.f, 1.f)
|
||||
, CursorType::CIRCLE
|
||||
, 0.f
|
||||
, false
|
||||
, false
|
||||
, 0.f
|
||||
, math::vector_3d(0.f, 0.f, 0.f)
|
||||
, 0.f
|
||||
, 0.f
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, editing_mode::ground
|
||||
, _world_camera.position
|
||||
, true
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, true
|
||||
, false
|
||||
, false
|
||||
, false
|
||||
, &_settings_unused
|
||||
, area_id_colors
|
||||
, false
|
||||
, eTerrainType::eTerrainType_Flat
|
||||
, 0
|
||||
, display_mode::in_3D
|
||||
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Sorting issues may naturally occur here due to draw order. But we can't avoid them if we want world as an underlay.
|
||||
// It is just a preview after all.
|
||||
|
||||
draw();
|
||||
|
||||
ImGui::SetCurrentContext(_imgui_context);
|
||||
QtImGui::newFrame();
|
||||
|
||||
|
||||
ImGuizmo::SetDrawlist();
|
||||
|
||||
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::BeginFrame();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
|
||||
|
||||
auto obj_mat = _wmo_instances[0].transform_matrix().transposed();
|
||||
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
|
||||
|
||||
ImGuizmo::DecomposeMatrixToComponents(obj_mat, matrixTranslation, matrixRotation, matrixScale);
|
||||
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, obj_mat);
|
||||
|
||||
auto delta_mat = math::matrix_4x4(math::matrix_4x4::unit).transposed();
|
||||
|
||||
ImGuizmo::Manipulate(static_cast<float*>(model_view().transposed()),
|
||||
static_cast<float*>(projection().transposed()),
|
||||
ImGuizmo::TRANSLATE,
|
||||
ImGuizmo::WORLD,
|
||||
obj_mat,
|
||||
delta_mat,
|
||||
NULL);
|
||||
|
||||
|
||||
std::string test;
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
test += std::to_string(static_cast<float*>(delta_mat)[i]) + " ";
|
||||
}
|
||||
|
||||
QMatrix4x4 new_mat (static_cast<float*>(delta_mat));
|
||||
QVector3D pos = {_wmo_instances[0].pos.x, _wmo_instances[0].pos.y, _wmo_instances[0].pos.z};
|
||||
QVector3D transform = pos * new_mat;
|
||||
_wmo_instances[0].pos = {transform.x(), transform.y(), transform.z()};
|
||||
_wmo_instances[0].recalcExtents();
|
||||
|
||||
test += "\n" + std::to_string(_wmo_instances[0].pos.x) + " "
|
||||
+ std::to_string(_wmo_instances[0].pos.y)
|
||||
+ " " + std::to_string(_wmo_instances[0].pos.z);
|
||||
|
||||
|
||||
|
||||
ImGui::Text(test.c_str());
|
||||
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
void ModelViewer::loadWorldUnderlay(const std::string& internal_name, int map_id)
|
||||
{
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
makeCurrent();
|
||||
|
||||
if (map_id < 0)
|
||||
{
|
||||
_world = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_world = std::make_unique<World> (internal_name, map_id,
|
||||
noggit::NoggitRenderContext::PRESET_EDITOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
math::matrix_4x4 ModelViewer::world_model_view() const
|
||||
{
|
||||
return _world_camera.look_at_matrix();
|
||||
}
|
||||
|
||||
math::matrix_4x4 ModelViewer::world_projection() const
|
||||
{
|
||||
float far_z = _settings->value("farZ", 2048).toFloat();
|
||||
return math::perspective(_world_camera.fov(), aspect_ratio(), 0.1f, far_z);
|
||||
}
|
||||
|
||||
void ModelViewer::tick(float dt)
|
||||
{
|
||||
if (_world)
|
||||
{
|
||||
_world->mapIndex.enterTile (tile_index (_world_camera.position));
|
||||
_world->mapIndex.unloadTiles (tile_index (_world_camera.position));
|
||||
}
|
||||
|
||||
AssetBrowser::ModelViewer::tick(dt);
|
||||
|
||||
if (turn)
|
||||
{
|
||||
_world_camera.add_to_yaw(math::degrees(turn));
|
||||
}
|
||||
if (lookat)
|
||||
{
|
||||
_world_camera.add_to_pitch(math::degrees(lookat));
|
||||
}
|
||||
if (moving)
|
||||
{
|
||||
_world_camera.move_forward(moving, dt);
|
||||
}
|
||||
if (strafing)
|
||||
{
|
||||
_world_camera.move_horizontal(strafing, dt);
|
||||
}
|
||||
if (updown)
|
||||
{
|
||||
_world_camera.move_vertical(updown, dt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ModelViewer::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QLineF const relative_movement (_last_mouse_pos, event->pos());
|
||||
|
||||
if (look)
|
||||
{
|
||||
_world_camera.add_to_yaw(math::degrees(relative_movement.dx() / 20.0f));
|
||||
_world_camera.add_to_pitch(math::degrees(mousedir * relative_movement.dy() / 20.0f));
|
||||
}
|
||||
|
||||
AssetBrowser::ModelViewer::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void ModelViewer::initializeGL()
|
||||
{
|
||||
AssetBrowser::ModelViewer::initializeGL();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <noggit/Red/AssetBrowser/ModelView.hpp>
|
||||
#include <noggit/World.h>
|
||||
#include <noggit/camera.hpp>
|
||||
|
||||
|
||||
|
||||
namespace noggit
|
||||
@@ -14,10 +16,26 @@ namespace noggit
|
||||
public:
|
||||
explicit ModelViewer(QWidget* parent = nullptr);
|
||||
|
||||
void loadWorldUnderlay(std::string const& internal_name, int map_id);
|
||||
World* getWorld() { return _world.get(); };
|
||||
noggit::camera* getCamera() { return &_camera; };
|
||||
noggit::camera* getWorldCamera() { return &_world_camera; };
|
||||
|
||||
private:
|
||||
std::unique_ptr<World> _world;
|
||||
|
||||
noggit::camera _world_camera;
|
||||
|
||||
void paintGL() override;
|
||||
void initializeGL() override;
|
||||
|
||||
void tick(float dt) override;
|
||||
|
||||
math::matrix_4x4 world_model_view() const;
|
||||
math::matrix_4x4 world_projection() const;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "PresetEditor.hpp"
|
||||
#include <noggit/ui/FramelessWindow.hpp>
|
||||
#include <noggit/ui/font_noggit.hpp>
|
||||
#include <noggit/DBC.h>
|
||||
|
||||
|
||||
using namespace noggit::Red::PresetEditor::Ui;
|
||||
@@ -73,6 +74,33 @@ PresetEditorWidget::PresetEditorWidget(QWidget *parent)
|
||||
|
||||
setupConnectsCommon();
|
||||
|
||||
// Fill selector combo
|
||||
ui->worldSelector->addItem("None");
|
||||
ui->worldSelector->setItemData(0, QVariant(-1));
|
||||
int count = 1;
|
||||
for (DBCFile::Iterator i = gMapDB.begin(); i != gMapDB.end(); ++i)
|
||||
{
|
||||
int map_id = i->getInt(MapDB::MapID);
|
||||
std::string name = i->getLocalizedString(MapDB::Name);
|
||||
int area_type = i->getUInt(MapDB::AreaType);
|
||||
|
||||
if (area_type < 0 || area_type > 4 || !World::IsEditableWorld(map_id))
|
||||
continue;
|
||||
|
||||
ui->worldSelector->addItem(QString::number(map_id) + " - " + QString::fromUtf8 (name.c_str()));
|
||||
ui->worldSelector->setItemData(count, QVariant(map_id), Qt::UserRole);
|
||||
|
||||
auto map_internal_name = i->getString(MapDB::InternalName);
|
||||
ui->worldSelector->setItemData(count, QVariant(QString::fromStdString(map_internal_name)), Qt::UserRole + 1);
|
||||
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
// Handle minimap widget
|
||||
ui->minimapWidget->draw_boundaries(true);
|
||||
ui->minimapWidget->camera(ui->viewport->getWorldCamera());
|
||||
|
||||
}
|
||||
|
||||
void PresetEditorWidget::setupConnectsCommon()
|
||||
@@ -85,6 +113,25 @@ void PresetEditorWidget::setupConnectsCommon()
|
||||
|
||||
);
|
||||
|
||||
connect(ui->worldUnloadButton, &QPushButton::clicked
|
||||
,[this]()
|
||||
{
|
||||
int map_id = ui->worldSelector->itemData(ui->worldSelector->currentIndex(), Qt::UserRole).toInt();
|
||||
|
||||
ui->viewport->loadWorldUnderlay(
|
||||
ui->worldSelector->itemData(ui->worldSelector->currentIndex(), Qt::UserRole + 1).toString().toStdString(), map_id);
|
||||
ui->minimapWidget->world(ui->viewport->getWorld());
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
connect(ui->minimapWidget, &minimap_widget::map_clicked
|
||||
, [this] (::math::vector_3d const& pos)
|
||||
{
|
||||
ui->viewport->getWorldCamera()->position = pos;
|
||||
}
|
||||
);
|
||||
|
||||
connect(viewport_overlay_ui->lightDirY, &QDial::valueChanged
|
||||
,[this]()
|
||||
{
|
||||
|
||||
@@ -47,6 +47,18 @@
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="minimumSize">
|
||||
@@ -63,7 +75,7 @@
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="directoryBar">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -164,7 +176,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<widget class="QWidget" name="viewportHolder" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -194,146 +206,198 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="noggit::Red::PresetEditor::ModelViewer" name="viewport">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="viewport_tab">
|
||||
<attribute name="title">
|
||||
<string>Viewport</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="noggit::Red::PresetEditor::ModelViewer" name="viewport">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="toolPanel" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>376</width>
|
||||
<height>684</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>World navigation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item alignment="Qt::AlignHCenter|Qt::AlignTop">
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QWidget" name="mapSelector_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Map:</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="worldSelector"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="worldUnloadButton">
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="noggit::ui::minimap_widget" name="minimapWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>376</width>
|
||||
<height>684</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Page 2</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="nodes_tab">
|
||||
<attribute name="title">
|
||||
<string>Nodes</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="toolPanel" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>561</width>
|
||||
<height>702</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>World navigation</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="mapSelector_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Map:</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox_3"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="noggit::ui::minimap_widget" name="minimapHolder_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>561</width>
|
||||
<height>702</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Page 2</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -468,7 +468,7 @@ QPixmap* PreviewRenderer::renderToPixmap()
|
||||
gl.clearColor(0.5f, 0.5f, 0.5f, 1.f);
|
||||
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
tick(20.f);
|
||||
tick(1.0f);
|
||||
draw();
|
||||
|
||||
auto& async_loader = AsyncLoader::instance();
|
||||
@@ -528,6 +528,8 @@ void PreviewRenderer::update_emitters(float dt)
|
||||
|
||||
void PreviewRenderer::tick(float dt)
|
||||
{
|
||||
dt = std::min(dt, 1.0f);
|
||||
|
||||
_animtime += dt * 1000.0f;
|
||||
|
||||
if (_draw_animated.get())
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace noggit
|
||||
setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
//setMouseTracking(true);
|
||||
setMaximumSize(QSize(1024, 1024));
|
||||
setMinimumSize(QSize(512, 512));
|
||||
setMinimumSize(QSize(128, 128));
|
||||
}
|
||||
|
||||
QSize minimap_widget::sizeHint() const
|
||||
|
||||
Reference in New Issue
Block a user