UI: removed vector interface

master
Martin Gerhardy 2022-05-26 17:15:03 +02:00
parent a44c21ce84
commit 384df5885b
2 changed files with 642 additions and 723 deletions

View File

@ -7,11 +7,10 @@
#include "imgui_internal.h" #include "imgui_internal.h"
#include "imgui_neo_internal.h" #include "imgui_neo_internal.h"
#include <stack>
#include <iostream>
#include <unordered_map> #include <unordered_map>
namespace ImGui { namespace ImGui {
struct ImGuiNeoSequencerInternalData { struct ImGuiNeoSequencerInternalData {
ImVec2 StartCursor = {0, 0}; // Cursor in TL corner of whole widget ImVec2 StartCursor = {0, 0}; // Cursor in TL corner of whole widget
ImVec2 TopBarStartCursor = {0, 0}; // Cursor on top, below Zoom slider ImVec2 TopBarStartCursor = {0, 0}; // Cursor on top, below Zoom slider
@ -35,11 +34,14 @@ namespace ImGui {
uint32_t CurrentFrame = 0; uint32_t CurrentFrame = 0;
bool HoldingCurrentFrame = false; // Are we draging current frame? bool HoldingCurrentFrame = false; // Are we draging current frame?
ImVec4 CurrentFrameColor; // Color of current frame, we have to save it because we render on EndNeoSequencer, but process at BeginneoSequencer ImVec4 CurrentFrameColor; // Color of current frame, we have to save it because we render on EndNeoSequencer, but
// process at BeginneoSequencer
bool HoldingZoomSlider = false; bool HoldingZoomSlider = false;
}; };
using Map = std::unordered_map<ImGuiID, ImGuiNeoSequencerInternalData>;
static ImGuiNeoSequencerStyle style; // NOLINT(cert-err58-cpp) static ImGuiNeoSequencerStyle style; // NOLINT(cert-err58-cpp)
// Global context stuff // Global context stuff
@ -57,32 +59,31 @@ namespace ImGui {
static ImVector<ImGuiColorMod> sequencerColorStack; static ImVector<ImGuiColorMod> sequencerColorStack;
// Data of all sequencers, this is main c++ part and I should create C alternative or use imgui ImVector or something // Data of all sequencers, this is main c++ part and I should create C alternative or use imgui ImVector or something
static std::unordered_map<ImGuiID, ImGuiNeoSequencerInternalData> sequencerData; static Map sequencerData;
///////////// STATIC HELPERS /////////////////////// ///////////// STATIC HELPERS ///////////////////////
static float getPerFrameWidth(ImGuiNeoSequencerInternalData &context) { static float getPerFrameWidth(ImGuiNeoSequencerInternalData &context) {
return GetPerFrameWidth(context.Size.x, context.ValuesWidth, context.EndFrame, context.StartFrame, return GetPerFrameWidth(context.Size.x, context.ValuesWidth, context.EndFrame, context.StartFrame, context.Zoom);
context.Zoom);
} }
static float getKeyframePositionX(uint32_t frame, ImGuiNeoSequencerInternalData &context) { static float getKeyframePositionX(uint32_t frame, ImGuiNeoSequencerInternalData &context) {
const auto perFrameWidth = getPerFrameWidth(context); const float perFrameWidth = getPerFrameWidth(context);
return (float)(frame - context.OffsetFrame) * perFrameWidth; return (float)(frame - context.OffsetFrame) * perFrameWidth;
} }
static float getWorkTimelineWidth(ImGuiNeoSequencerInternalData &context) { static float getWorkTimelineWidth(ImGuiNeoSequencerInternalData &context) {
const auto perFrameWidth = getPerFrameWidth(context); const float perFrameWidth = getPerFrameWidth(context);
return context.Size.x - context.ValuesWidth - perFrameWidth; return context.Size.x - context.ValuesWidth - perFrameWidth;
} }
// Dont pull frame from context, its used for dragging // Dont pull frame from context, its used for dragging
static ImRect getCurrentFrameBB(uint32_t frame, ImGuiNeoSequencerInternalData &context) { static ImRect getCurrentFrameBB(uint32_t frame, ImGuiNeoSequencerInternalData &context) {
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
const auto width = style.CurrentFramePointerSize * GetIO().FontGlobalScale; const float width = style.CurrentFramePointerSize * GetIO().FontGlobalScale;
const auto cursor = const ImVec2 cursor =
context.TopBarStartCursor + ImVec2{context.ValuesWidth + imStyle.FramePadding.x - width / 2.0f, 0}; context.TopBarStartCursor + ImVec2{context.ValuesWidth + imStyle.FramePadding.x - width / 2.0f, 0};
const auto currentFrameCursor = cursor + ImVec2{ getKeyframePositionX(frame, context), 0 }; const ImVec2 currentFrameCursor = cursor + ImVec2{getKeyframePositionX(frame, context), 0};
float pointerHeight = style.CurrentFramePointerSize * 2.5f; float pointerHeight = style.CurrentFramePointerSize * 2.5f;
ImRect rect{currentFrameCursor, currentFrameCursor + ImVec2{width, pointerHeight * GetIO().FontGlobalScale}}; ImRect rect{currentFrameCursor, currentFrameCursor + ImVec2{width, pointerHeight * GetIO().FontGlobalScale}};
@ -91,18 +92,16 @@ namespace ImGui {
} }
static void processCurrentFrame(uint32_t *frame, ImGuiNeoSequencerInternalData &context) { static void processCurrentFrame(uint32_t *frame, ImGuiNeoSequencerInternalData &context) {
auto pointerRect = getCurrentFrameBB(*frame, context); ImRect pointerRect = getCurrentFrameBB(*frame, context);
pointerRect.Min -= ImVec2{2.0f, 2.0f}; pointerRect.Min -= ImVec2{2.0f, 2.0f};
pointerRect.Max += ImVec2{2.0f, 2.0f}; pointerRect.Max += ImVec2{2.0f, 2.0f};
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
const auto timelineXmin = context.TopBarStartCursor.x + context.ValuesWidth + imStyle.FramePadding.x; const float timelineXmin = context.TopBarStartCursor.x + context.ValuesWidth + imStyle.FramePadding.x;
const ImVec2 timelineXRange = { const ImVec2 timelineXRange = {timelineXmin, // min
timelineXmin, //min timelineXmin + context.Size.x - context.ValuesWidth};
timelineXmin + context.Size.x - context.ValuesWidth
};
if (!ItemAdd(pointerRect, 0)) if (!ItemAdd(pointerRect, 0))
return; return;
@ -115,18 +114,18 @@ namespace ImGui {
if (context.HoldingCurrentFrame) { if (context.HoldingCurrentFrame) {
if (IsMouseDragging(ImGuiMouseButton_Left, 0.0f)) { if (IsMouseDragging(ImGuiMouseButton_Left, 0.0f)) {
const auto mousePosX = GetMousePos().x; const float mousePosX = GetMousePos().x;
const auto v = mousePosX - timelineXRange.x;// Subtract min const float v = mousePosX - timelineXRange.x; // Subtract min
const auto normalized = v / getWorkTimelineWidth(context); //Divide by width to remap to 0 - 1 range const float normalized = v / getWorkTimelineWidth(context); // Divide by width to remap to 0 - 1 range
const auto clamped = ImClamp(normalized, 0.0f, 1.0f); const float clamped = ImClamp(normalized, 0.0f, 1.0f);
const auto viewSize = (float)(context.EndFrame - context.StartFrame) / context.Zoom; const float viewSize = (float)(context.EndFrame - context.StartFrame) / context.Zoom;
const auto frameViewVal = (float)context.StartFrame + (clamped * (float)viewSize); const float frameViewVal = (float)context.StartFrame + (clamped * (float)viewSize);
const auto finalFrame = (uint32_t)round(frameViewVal) + context.OffsetFrame; const unsigned int finalFrame = (uint32_t)round(frameViewVal) + context.OffsetFrame;
context.CurrentFrameColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_FramePointerPressed); context.CurrentFrameColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_FramePointerPressed);
@ -153,38 +152,34 @@ namespace ImGui {
} }
static bool createKeyframe(uint32_t *frame) { static bool createKeyframe(uint32_t *frame) {
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
const auto timelineOffset = getKeyframePositionX(*frame, context); const float timelineOffset = getKeyframePositionX(*frame, context);
const auto pos = ImVec2{ context.StartValuesCursor.x + imStyle.FramePadding.x, context.ValuesCursor.y } + const ImVec2 pos = ImVec2{context.StartValuesCursor.x + imStyle.FramePadding.x, context.ValuesCursor.y} +
ImVec2{timelineOffset + context.ValuesWidth, 0}; ImVec2{timelineOffset + context.ValuesWidth, 0};
const ImVec2 bbPos = pos - ImVec2{currentTimelineHeight / 2, 0};
const auto bbPos = pos - ImVec2{ currentTimelineHeight / 2, 0 };
const ImRect bb = {bbPos, bbPos + ImVec2{currentTimelineHeight, currentTimelineHeight}}; const ImRect bb = {bbPos, bbPos + ImVec2{currentTimelineHeight, currentTimelineHeight}};
if (!ItemAdd(bb, 0)) {
if (!ItemAdd(bb, 0))
return false; return false;
}
const auto drawList = ImGui::GetWindowDrawList(); ImDrawList *drawList = ImGui::GetWindowDrawList();
drawList->AddCircleFilled(pos + ImVec2{ 0, currentTimelineHeight / 2.f }, currentTimelineHeight / 3.0f, drawList->AddCircleFilled(
IsItemHovered() ? pos + ImVec2{0, currentTimelineHeight / 2.f}, currentTimelineHeight / 3.0f,
ColorConvertFloat4ToU32( IsItemHovered() ? ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_KeyframeHovered))
GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_KeyframeHovered)) : : ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_Keyframe)),
ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_Keyframe)),
4); 4);
return true; return true;
} }
static uint32_t idCounter = 0; static uint32_t idCounter = 0;
static char idBuffer[16]; static char idBuffer[16];
const char* generateID() { static const char *generateID() {
idBuffer[0] = '#'; idBuffer[0] = '#';
idBuffer[1] = '#'; idBuffer[1] = '#';
memset(idBuffer + 2, 0, 14); memset(idBuffer + 2, 0, 14);
@ -193,45 +188,38 @@ namespace ImGui {
return &idBuffer[0]; return &idBuffer[0];
} }
void resetID() { static void resetID() {
idCounter = 0; idCounter = 0;
} }
static void renderCurrentFrame(ImGuiNeoSequencerInternalData &context) { static void renderCurrentFrame(ImGuiNeoSequencerInternalData &context) {
const auto bb = getCurrentFrameBB(context.CurrentFrame, context); const ImRect bb = getCurrentFrameBB(context.CurrentFrame, context);
const auto drawList = ImGui::GetWindowDrawList(); ImDrawList *drawList = ImGui::GetWindowDrawList();
RenderNeoSequencerCurrentFrame( RenderNeoSequencerCurrentFrame(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_FramePointerLine),
GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_FramePointerLine), context.CurrentFrameColor, bb, context.Size.y - context.TopBarSize.y,
context.CurrentFrameColor, style.CurrentFrameLineWidth, drawList);
bb,
context.Size.y - context.TopBarSize.y,
style.CurrentFrameLineWidth,
drawList
);
} }
static void processAndRenderZoom(ImGuiNeoSequencerInternalData &context, bool allowEditingLength, uint32_t *start, static void processAndRenderZoom(ImGuiNeoSequencerInternalData &context, bool allowEditingLength, uint32_t *start,
uint32_t *end) { uint32_t *end) {
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
ImGuiWindow *window = GetCurrentWindow(); ImGuiWindow *window = GetCurrentWindow();
const auto zoomHeight = GetFontSize() * style.ZoomHeightScale; const float zoomHeight = GetFontSize() * style.ZoomHeightScale;
auto* drawList = GetWindowDrawList(); ImDrawList *drawList = GetWindowDrawList();
// Input width // Input width
const auto inputWidth = CalcTextSize("123456").x; const float inputWidth = CalcTextSize("123456").x;
const auto inputWidthWithPadding = inputWidth + imStyle.ItemSpacing.x; const float inputWidthWithPadding = inputWidth + imStyle.ItemSpacing.x;
const auto cursor = allowEditingLength ? context.StartCursor + ImVec2{ inputWidthWithPadding, 0 } const ImVec2 cursor =
: context.StartCursor; allowEditingLength ? context.StartCursor + ImVec2{inputWidthWithPadding, 0} : context.StartCursor;
const auto size = allowEditingLength ? const float size = allowEditingLength ? context.Size.x - 2 * inputWidthWithPadding : context.Size.x;
context.Size.x - 2 * inputWidthWithPadding :
context.Size.x;
const ImRect bb{cursor, cursor + ImVec2{size, zoomHeight}}; const ImRect bb{cursor, cursor + ImVec2{size, zoomHeight}};
@ -240,21 +228,22 @@ namespace ImGui {
// const ImVec2 startFrameTextCursor{context.StartCursor + ImVec2{imStyle.FramePadding.x, 0}}; // const ImVec2 startFrameTextCursor{context.StartCursor + ImVec2{imStyle.FramePadding.x, 0}};
// Text number borders // Text number borders
//drawList->AddRect(startFrameTextCursor, startFrameTextCursor + frameNumberBorderSize,ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TimelineBorder))); // drawList->AddRect(startFrameTextCursor, startFrameTextCursor +
// frameNumberBorderSize,ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TimelineBorder)));
const auto zoomBarEndWithSpacing = ImVec2{ bb.Max.x + imStyle.ItemSpacing.x, context.StartCursor.y }; const ImVec2 zoomBarEndWithSpacing = ImVec2{bb.Max.x + imStyle.ItemSpacing.x, context.StartCursor.y};
/* /*
drawList->AddRect(zoomBarEndWithSpacing, drawList->AddRect(zoomBarEndWithSpacing,
zoomBarEndWithSpacing + frameNumberBorderSize,ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TimelineBorder))); zoomBarEndWithSpacing +
frameNumberBorderSize,ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TimelineBorder)));
*/ */
int32_t startFrameVal = (int32_t)*start; int32_t startFrameVal = (int32_t)*start;
int32_t endFrameVal = (int32_t)*end; int32_t endFrameVal = (int32_t)*end;
if (allowEditingLength) { if (allowEditingLength) {
ImVec2 prevWindowCursor = window->DC.CursorPos;
auto prevWindowCursor = window->DC.CursorPos;
PushItemWidth(inputWidth); PushItemWidth(inputWidth);
InputScalar("##input_start_frame", ImGuiDataType_U32, &startFrameVal, NULL, NULL, NULL, InputScalar("##input_start_frame", ImGuiDataType_U32, &startFrameVal, NULL, NULL, NULL,
@ -281,44 +270,34 @@ namespace ImGui {
*start = startFrameVal; *start = startFrameVal;
*end = endFrameVal; *end = endFrameVal;
//drawList->AddText(startFrameTextCursor + ImVec2{frameNumberBorderSize.x, 0} - ImVec2{numberTextWidth,0},IM_COL32_WHITE,numberText); // drawList->AddText(startFrameTextCursor + ImVec2{frameNumberBorderSize.x, 0} -
// ImVec2{numberTextWidth,0},IM_COL32_WHITE,numberText);
// Background // Background
drawList->AddRectFilled(bb.Min, bb.Max, drawList->AddRectFilled(
ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarBg)), bb.Min, bb.Max, ColorConvertFloat4ToU32(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarBg)), 10.0f);
10.0f);
const auto baseWidth = bb.GetSize().x - const float baseWidth =
bb.GetSize().x -
imStyle.ItemInnerSpacing.x; // There is just half spacing applied, doing it normally makes big gap on sides imStyle.ItemInnerSpacing.x; // There is just half spacing applied, doing it normally makes big gap on sides
const auto sliderHeight = bb.GetSize().y - imStyle.ItemInnerSpacing.y; const float sliderHeight = bb.GetSize().y - imStyle.ItemInnerSpacing.y;
const float sliderWidth = baseWidth / context.Zoom;
const auto sliderWidth = baseWidth / context.Zoom; const ImVec2 sliderMin = bb.Min + imStyle.ItemInnerSpacing / 2.0f;
const float sliderMaxWidth = baseWidth;
const auto sliderMin = bb.Min + imStyle.ItemInnerSpacing / 2.0f;
//const auto sliderMax = bb.Max - imStyle.ItemInnerSpacing / 2.0f;
const auto sliderMaxWidth = baseWidth;
const auto totalFrames = (*end - *start);
const auto singleFrameWidthOffset = sliderMaxWidth / (float)totalFrames;
const auto zoomSliderOffset = singleFrameWidthOffset * (float)context.OffsetFrame;
const auto sliderStart = sliderMin + ImVec2{ zoomSliderOffset, 0 };
const unsigned int totalFrames = (*end - *start);
const float singleFrameWidthOffset = sliderMaxWidth / (float)totalFrames;
const float zoomSliderOffset = singleFrameWidthOffset * (float)context.OffsetFrame;
const ImVec2 sliderStart = sliderMin + ImVec2{zoomSliderOffset, 0};
const float sideSize = sliderHeight; const float sideSize = sliderHeight;
const ImRect finalSliderBB{sliderStart, sliderStart + ImVec2{sliderWidth, sliderHeight}}; const ImRect finalSliderBB{sliderStart, sliderStart + ImVec2{sliderWidth, sliderHeight}};
const ImRect finalSliderInteractBB = {finalSliderBB.Min + ImVec2{sideSize, 0}, const ImRect finalSliderInteractBB = {finalSliderBB.Min + ImVec2{sideSize, 0},
finalSliderBB.Max - ImVec2{sideSize, 0}}; finalSliderBB.Max - ImVec2{sideSize, 0}};
const auto resBG = ItemAdd(bb, 0); const bool resBG = ItemAdd(bb, 0);
const auto viewWidth = (uint32_t)((float)totalFrames / context.Zoom); const uint32_t viewWidth = (uint32_t)((float)totalFrames / context.Zoom);
if (resBG) { if (resBG) {
if (IsItemHovered()) { if (IsItemHovered()) {
@ -326,7 +305,7 @@ namespace ImGui {
const float currentScroll = GetIO().MouseWheel; const float currentScroll = GetIO().MouseWheel;
context.Zoom = ImClamp(context.Zoom + currentScroll, 1.0f, (float)viewWidth); context.Zoom = ImClamp(context.Zoom + currentScroll, 1.0f, (float)viewWidth);
const auto newZoomWidth = (uint32_t)((float)totalFrames / context.Zoom); const uint32_t newZoomWidth = (uint32_t)((float)totalFrames / context.Zoom);
if (*start + context.OffsetFrame + newZoomWidth > *end) if (*start + context.OffsetFrame + newZoomWidth > *end)
context.OffsetFrame = ImMax(0U, totalFrames - viewWidth); context.OffsetFrame = ImMax(0U, totalFrames - viewWidth);
@ -334,28 +313,23 @@ namespace ImGui {
if (context.HoldingZoomSlider) { if (context.HoldingZoomSlider) {
if (IsMouseDragging(ImGuiMouseButton_Left, 0.01f)) { if (IsMouseDragging(ImGuiMouseButton_Left, 0.01f)) {
const auto currentX = GetMousePos().x; const float currentX = GetMousePos().x;
const float v = currentX - bb.Min.x; // Subtract min
const float normalized = v / bb.GetWidth(); // Divide by width to remap to 0 - 1 range
const float sliderWidthNormalized = 1.0f / context.Zoom;
const float singleFrameWidthOffsetNormalized = singleFrameWidthOffset / bb.GetWidth();
const auto v = currentX - bb.Min.x;// Subtract min uint32_t finalFrame =
(uint32_t)((float)(normalized - sliderWidthNormalized / 2.0f) / singleFrameWidthOffsetNormalized);
const auto normalized = v / bb.GetWidth(); //Divide by width to remap to 0 - 1 range
const auto sliderWidthNormalized = 1.0f / context.Zoom;
const auto singleFrameWidthOffsetNormalized = singleFrameWidthOffset / bb.GetWidth();
uint32_t finalFrame = (uint32_t)((float)(normalized - sliderWidthNormalized / 2.0f) / singleFrameWidthOffsetNormalized);
if (normalized - sliderWidthNormalized / 2.0f < 0.0f) { if (normalized - sliderWidthNormalized / 2.0f < 0.0f) {
finalFrame = 0; finalFrame = 0;
} }
if (normalized + sliderWidthNormalized / 2.0f > 1.0f) { if (normalized + sliderWidthNormalized / 2.0f > 1.0f) {
finalFrame = totalFrames - viewWidth; finalFrame = totalFrames - viewWidth;
} }
context.OffsetFrame = finalFrame; context.OffsetFrame = finalFrame;
} }
@ -369,14 +343,13 @@ namespace ImGui {
} }
} }
const auto res = ItemAdd(finalSliderInteractBB, 0); const bool res = ItemAdd(finalSliderInteractBB, 0);
const unsigned int viewStart = *start + (uint32_t)context.OffsetFrame;
const auto viewStart = *start + (uint32_t)context.OffsetFrame; const unsigned int viewEnd = viewStart + viewWidth;
const auto viewEnd = viewStart + viewWidth;
if (res) { if (res) {
auto sliderColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarSlider); ImVec4 sliderColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarSlider);
if (IsItemHovered()) { if (IsItemHovered()) {
sliderColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarSliderHovered); sliderColor = GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_ZoomBarSliderHovered);
@ -385,18 +358,14 @@ namespace ImGui {
// Render bar // Render bar
drawList->AddRectFilled(finalSliderBB.Min, finalSliderBB.Max, ColorConvertFloat4ToU32(sliderColor), 10.0f); drawList->AddRectFilled(finalSliderBB.Min, finalSliderBB.Max, ColorConvertFloat4ToU32(sliderColor), 10.0f);
const auto sliderCenter = finalSliderBB.GetCenter(); const ImVec2 sliderCenter = finalSliderBB.GetCenter();
char overlayTextBuffer[128]; char overlayTextBuffer[128];
snprintf(overlayTextBuffer, sizeof(overlayTextBuffer), "%d - %d", viewStart, viewEnd); snprintf(overlayTextBuffer, sizeof(overlayTextBuffer), "%d - %d", viewStart, viewEnd);
const auto overlaySize = CalcTextSize(overlayTextBuffer); const ImVec2 overlaySize = CalcTextSize(overlayTextBuffer);
drawList->AddText(sliderCenter - overlaySize / 2.0f, IM_COL32_WHITE, overlayTextBuffer); drawList->AddText(sliderCenter - overlaySize / 2.0f, IM_COL32_WHITE, overlayTextBuffer);
} }
} }
////////////////////////////////////
const ImVec4 &GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol idx) { const ImVec4 &GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol idx) {
return GetNeoSequencerStyle().Colors[idx]; return GetNeoSequencerStyle().Colors[idx];
@ -406,17 +375,13 @@ namespace ImGui {
return style; return style;
} }
bool BeginNeoSequencer(const char *idin, uint32_t *frame, uint32_t *startFrame, uint32_t *endFrame, const ImVec2 &size,
bool
BeginNeoSequencer(const char* idin, uint32_t* frame, uint32_t* startFrame, uint32_t* endFrame, const ImVec2& size,
ImGuiNeoSequencerFlags flags) { ImGuiNeoSequencerFlags flags) {
IM_ASSERT(!inSequencer && "Called when while in other NeoSequencer, that won't work, call End!"); IM_ASSERT(!inSequencer && "Called when while in other NeoSequencer, that won't work, call End!");
IM_ASSERT(*startFrame < *endFrame && "Start frame must be smaller than end frame"); IM_ASSERT(*startFrame < *endFrame && "Start frame must be smaller than end frame");
//ImGuiContext &g = *GImGui;
ImGuiWindow *window = GetCurrentWindow(); ImGuiWindow *window = GetCurrentWindow();
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
//auto &neoStyle = GetNeoSequencerStyle();
if (inSequencer) if (inSequencer)
return false; return false;
@ -424,22 +389,19 @@ namespace ImGui {
if (window->SkipItems) if (window->SkipItems)
return false; return false;
const auto drawList = GetWindowDrawList(); ImDrawList *drawList = GetWindowDrawList();
const auto cursor = GetCursorScreenPos(); const ImVec2 cursor = GetCursorScreenPos();
const auto area = ImGui::GetContentRegionAvail(); const ImVec2 area = ImGui::GetContentRegionAvail();
//const auto cursorBasePos = GetCursorScreenPos() + window->Scroll;
//const ImRect clip = { cursorBasePos, cursorBasePos + window->ContentRegionRect.GetSize() };
PushID(idin); PushID(idin);
const auto id = window->IDStack[window->IDStack.size() - 1]; const unsigned int id = window->IDStack[window->IDStack.size() - 1];
inSequencer = true; inSequencer = true;
auto& context = sequencerData[id]; Map::mapped_type &context = sequencerData[id];
auto realSize = ImFloor(size); ImVec2 realSize = ImFloor(size);
if (realSize.x <= 0.0f) if (realSize.x <= 0.0f)
realSize.x = ImMax(4.0f, area.x); realSize.x = ImMax(4.0f, area.x);
if (realSize.y <= 0.0f) if (realSize.y <= 0.0f)
@ -449,32 +411,28 @@ namespace ImGui {
context.StartCursor = cursor; context.StartCursor = cursor;
// If Zoom is shown, we offset it by height of Zoom bar + padding // If Zoom is shown, we offset it by height of Zoom bar + padding
context.TopBarStartCursor = showZoom ? cursor + context.TopBarStartCursor =
ImVec2{ 0, GetFontSize() * style.ZoomHeightScale + imStyle.FramePadding.y } showZoom ? cursor + ImVec2{0, GetFontSize() * style.ZoomHeightScale + imStyle.FramePadding.y} : cursor;
: cursor;
context.StartFrame = *startFrame; context.StartFrame = *startFrame;
context.EndFrame = *endFrame; context.EndFrame = *endFrame;
context.Size = realSize; context.Size = realSize;
currentSequencer = window->IDStack[window->IDStack.size() - 1]; currentSequencer = window->IDStack[window->IDStack.size() - 1];
RenderNeoSequencerBackground(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_Bg), context.StartCursor, RenderNeoSequencerBackground(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_Bg), context.StartCursor,
context.Size, context.Size, drawList, style.SequencerRounding);
drawList, style.SequencerRounding);
RenderNeoSequencerTopBarBackground(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TopBarBg), RenderNeoSequencerTopBarBackground(GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_TopBarBg),
context.TopBarStartCursor, context.TopBarSize, context.TopBarStartCursor, context.TopBarSize, drawList,
drawList, style.SequencerRounding); style.SequencerRounding);
RenderNeoSequencerTopBarOverlay(context.Zoom, context.ValuesWidth, context.StartFrame, context.EndFrame, RenderNeoSequencerTopBarOverlay(context.Zoom, context.ValuesWidth, context.StartFrame, context.EndFrame,
context.OffsetFrame, context.OffsetFrame, context.TopBarStartCursor, context.TopBarSize, drawList,
context.TopBarStartCursor, context.TopBarSize, drawList,
style.TopBarShowFrameLines, style.TopBarShowFrameTexts); style.TopBarShowFrameLines, style.TopBarShowFrameTexts);
if (showZoom) if (showZoom) {
processAndRenderZoom(context, flags & ImGuiNeoSequencerFlags_AllowLengthChanging, startFrame, endFrame); processAndRenderZoom(context, flags & ImGuiNeoSequencerFlags_AllowLengthChanging, startFrame, endFrame);
}
context.TopBarSize = ImVec2(context.Size.x, style.TopBarHeight); context.TopBarSize = ImVec2(context.Size.x, style.TopBarHeight);
@ -499,8 +457,7 @@ namespace ImGui {
IM_ASSERT(inSequencer && "Called end sequencer when BeginSequencer didnt return true or wasn't called at all!"); IM_ASSERT(inSequencer && "Called end sequencer when BeginSequencer didnt return true or wasn't called at all!");
IM_ASSERT(sequencerData.count(currentSequencer) != 0 && "Ended sequencer has no context!"); IM_ASSERT(sequencerData.count(currentSequencer) != 0 && "Ended sequencer has no context!");
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
//auto &imStyle = GetStyle();
renderCurrentFrame(context); renderCurrentFrame(context);
@ -508,7 +465,7 @@ namespace ImGui {
const ImVec2 min = {0, 0}; const ImVec2 min = {0, 0};
context.Size.y = context.FilledHeight; context.Size.y = context.FilledHeight;
const auto max = context.Size; const ImVec2 max = context.Size;
ItemSize({min, max}); ItemSize({min, max});
PopID(); PopID();
@ -524,58 +481,49 @@ namespace ImGui {
} }
static bool groupBehaviour(const ImGuiID id, bool *open, const ImVec2 labelSize) { static bool groupBehaviour(const ImGuiID id, bool *open, const ImVec2 labelSize) {
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
ImGuiWindow *window = GetCurrentWindow(); ImGuiWindow *window = GetCurrentWindow();
const bool closable = open != nullptr; const bool closable = open != nullptr;
auto drawList = ImGui::GetWindowDrawList(); ImDrawList *drawList = ImGui::GetWindowDrawList();
const float arrowWidth = drawList->_Data->FontSize; const float arrowWidth = drawList->_Data->FontSize;
const ImVec2 arrowSize = {arrowWidth, arrowWidth}; const ImVec2 arrowSize = {arrowWidth, arrowWidth};
const ImRect arrowBB = { const ImRect arrowBB = {context.ValuesCursor, context.ValuesCursor + arrowSize};
context.ValuesCursor,
context.ValuesCursor + arrowSize
};
const ImVec2 groupBBMin = {context.ValuesCursor + ImVec2{arrowSize.x, 0.0f}}; const ImVec2 groupBBMin = {context.ValuesCursor + ImVec2{arrowSize.x, 0.0f}};
const ImRect groupBB = { const ImRect groupBB = {groupBBMin, groupBBMin + labelSize};
groupBBMin,
groupBBMin + labelSize
};
const ImGuiID arrowID = window->GetID(generateID()); const ImGuiID arrowID = window->GetID(generateID());
const auto addArrowRes = ItemAdd(arrowBB, arrowID); const bool addArrowRes = ItemAdd(arrowBB, arrowID);
if (addArrowRes) { if (addArrowRes) {
if (IsItemClicked() && closable) if (IsItemClicked() && closable)
(*open) = !(*open); (*open) = !(*open);
} }
const auto addGroupRes = ItemAdd(groupBB, id); const bool addGroupRes = ItemAdd(groupBB, id);
if (addGroupRes) { if (addGroupRes) {
if (IsItemClicked()) { if (IsItemClicked()) {
context.SelectedTimeline = context.SelectedTimeline == id ? 0 : id; context.SelectedTimeline = context.SelectedTimeline == id ? 0 : id;
} }
} }
const float width = groupBB.Max.x - arrowBB.Min.x; const float width = groupBB.Max.x - arrowBB.Min.x;
context.ValuesWidth = std::max(context.ValuesWidth, width); // Make left panel wide enough context.ValuesWidth = core_max(context.ValuesWidth, width); // Make left panel wide enough
return addGroupRes && addArrowRes; return addGroupRes && addArrowRes;
} }
static bool timelineBehaviour(const ImGuiID id, const ImVec2 labelSize) { static bool timelineBehaviour(const ImGuiID id, const ImVec2 labelSize) {
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
// ImGuiWindow *window = GetCurrentWindow(); // ImGuiWindow *window = GetCurrentWindow();
const ImRect groupBB = { const ImRect groupBB = {context.ValuesCursor, context.ValuesCursor + labelSize};
context.ValuesCursor,
context.ValuesCursor + labelSize
};
const auto addGroupRes = ItemAdd(groupBB, id); const bool addGroupRes = ItemAdd(groupBB, id);
if (addGroupRes) { if (addGroupRes) {
if (IsItemClicked()) { if (IsItemClicked()) {
context.SelectedTimeline = context.SelectedTimeline == id ? 0 : id; context.SelectedTimeline = context.SelectedTimeline == id ? 0 : id;
} }
} }
const float width = groupBB.Max.x - groupBB.Min.x; const float width = groupBB.Max.x - groupBB.Min.x;
context.ValuesWidth = std::max(context.ValuesWidth, width); // Make left panel wide enough context.ValuesWidth = core_max(context.ValuesWidth, width); // Make left panel wide enough
return addGroupRes; return addGroupRes;
} }
@ -586,24 +534,22 @@ namespace ImGui {
const bool closable = open != nullptr; const bool closable = open != nullptr;
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
const auto& imStyle = GetStyle(); const ImGuiStyle &imStyle = GetStyle();
ImGuiWindow *window = GetCurrentWindow(); ImGuiWindow *window = GetCurrentWindow();
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
auto labelSize = CalcTextSize(label); ImVec2 labelSize = CalcTextSize(label);
labelSize.y += imStyle.FramePadding.y * 2 + style.ItemSpacing.y * 2; labelSize.y += imStyle.FramePadding.y * 2 + style.ItemSpacing.y * 2;
labelSize.x += imStyle.FramePadding.x * 2 + style.ItemSpacing.x * 2 + labelSize.x +=
(float)currentTimelineDepth * style.DepthItemSpacing; imStyle.FramePadding.x * 2 + style.ItemSpacing.x * 2 + (float)currentTimelineDepth * style.DepthItemSpacing;
bool isGroup = flags & ImGuiNeoTimelineFlags_Group && closable; bool isGroup = flags & ImGuiNeoTimelineFlags_Group && closable;
bool addRes = false; bool addRes = false;
if (isGroup) { if (isGroup) {
labelSize.x += imStyle.ItemSpacing.x + GetFontSize(); labelSize.x += imStyle.ItemSpacing.x + GetFontSize();
addRes = groupBehaviour(id, open, labelSize); addRes = groupBehaviour(id, open, labelSize);
} } else {
else {
addRes = timelineBehaviour(id, labelSize); addRes = timelineBehaviour(id, labelSize);
} }
@ -615,21 +561,18 @@ namespace ImGui {
context.FilledHeight += currentTimelineHeight; context.FilledHeight += currentTimelineHeight;
if (addRes) { if (addRes) {
RenderNeoTimelane(id == context.SelectedTimeline, RenderNeoTimelane(id == context.SelectedTimeline, context.ValuesCursor + ImVec2{context.ValuesWidth, 0},
context.ValuesCursor + ImVec2{ context.ValuesWidth, 0 },
ImVec2{context.Size.x - context.ValuesWidth, currentTimelineHeight}, ImVec2{context.Size.x - context.ValuesWidth, currentTimelineHeight},
GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_SelectedTimeline)); GetStyleNeoSequencerColorVec4(ImGuiNeoSequencerCol_SelectedTimeline));
ImVec4 color = GetStyleColorVec4(ImGuiCol_Text); ImVec4 color = GetStyleColorVec4(ImGuiCol_Text);
if (IsItemHovered()) color.w *= 0.7f; if (IsItemHovered())
color.w *= 0.7f;
RenderNeoTimelineLabel(label, RenderNeoTimelineLabel(label,
context.ValuesCursor + imStyle.FramePadding + context.ValuesCursor + imStyle.FramePadding +
ImVec2{(float)currentTimelineDepth * style.DepthItemSpacing, 0}, ImVec2{(float)currentTimelineDepth * style.DepthItemSpacing, 0},
labelSize, labelSize, color, isGroup, isGroup && (*open));
color,
isGroup,
isGroup && (*open));
} }
for (uint32_t i = 0; i < keyframeCount; i++) { for (uint32_t i = 0; i < keyframeCount; i++) {
@ -639,40 +582,26 @@ namespace ImGui {
context.ValuesCursor.x += imStyle.FramePadding.x + (float)currentTimelineDepth * style.DepthItemSpacing; context.ValuesCursor.x += imStyle.FramePadding.x + (float)currentTimelineDepth * style.DepthItemSpacing;
context.ValuesCursor.y += currentTimelineHeight; context.ValuesCursor.y += currentTimelineHeight;
const auto result = !closable || (*open); const bool result = !closable || (*open);
if (result) { if (result) {
currentTimelineDepth++; currentTimelineDepth++;
} } else {
else {
finishPreviousTimeline(context); finishPreviousTimeline(context);
} }
return result; return result;
} }
void EndNeoTimeLine() { void EndNeoTimeLine() {
auto& context = sequencerData[currentSequencer]; Map::mapped_type &context = sequencerData[currentSequencer];
finishPreviousTimeline(context); finishPreviousTimeline(context);
currentTimelineDepth--; currentTimelineDepth--;
} }
bool NeoBeginCreateKeyframe(uint32_t *frame) { bool NeoBeginCreateKeyframe(uint32_t *frame) {
return false; return false;
} }
#ifdef __cplusplus
bool BeginNeoTimeline(const char* label, std::vector<uint32_t>& keyframes, bool* open) {
std::vector<uint32_t*> c_keyframes{ keyframes.size() };
for (uint32_t i = 0; i < keyframes.size(); i++)
c_keyframes[i] = &keyframes[i];
return BeginNeoTimeline(label, c_keyframes.data(), c_keyframes.size(), open);
}
#endif
void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, ImU32 col) { void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, ImU32 col) {
ImGuiColorMod backup; ImGuiColorMod backup;
backup.Col = idx; backup.Col = idx;
@ -698,7 +627,7 @@ namespace ImGui {
} }
} }
} } // namespace ImGui
ImGuiNeoSequencerStyle::ImGuiNeoSequencerStyle() { ImGuiNeoSequencerStyle::ImGuiNeoSequencerStyle() {
Colors[ImGuiNeoSequencerCol_Bg] = ImVec4{0.31f, 0.31f, 0.31f, 1.00f}; Colors[ImGuiNeoSequencerCol_Bg] = ImVec4{0.31f, 0.31f, 0.31f, 1.00f};
@ -722,5 +651,4 @@ ImGuiNeoSequencerStyle::ImGuiNeoSequencerStyle() {
Colors[ImGuiNeoSequencerCol_ZoomBarSliderHovered] = ImVec4{0.98f, 0.98f, 0.98f, 0.80f}; Colors[ImGuiNeoSequencerCol_ZoomBarSliderHovered] = ImVec4{0.98f, 0.98f, 0.98f, 0.80f};
Colors[ImGuiNeoSequencerCol_ZoomBarSliderEnds] = ImVec4{0.59f, 0.59f, 0.59f, 0.90f}; Colors[ImGuiNeoSequencerCol_ZoomBarSliderEnds] = ImVec4{0.59f, 0.59f, 0.59f, 0.90f};
Colors[ImGuiNeoSequencerCol_ZoomBarSliderEndsHovered] = ImVec4{0.93f, 0.93f, 0.93f, 0.93f}; Colors[ImGuiNeoSequencerCol_ZoomBarSliderEndsHovered] = ImVec4{0.93f, 0.93f, 0.93f, 0.93f};
} }

View File

@ -2,19 +2,16 @@
// Created by Matty on 2022-01-28. // Created by Matty on 2022-01-28.
// //
#ifndef IMGUI_NEO_SEQUENCER_H #pragma once
#define IMGUI_NEO_SEQUENCER_H
#include "imgui.h" #include "imgui.h"
#include <vector>
typedef int ImGuiNeoSequencerFlags; typedef int ImGuiNeoSequencerFlags;
typedef int ImGuiNeoSequencerCol; typedef int ImGuiNeoSequencerCol;
typedef int ImGuiNeoTimelineFlags; typedef int ImGuiNeoTimelineFlags;
// Flags for ImGui::BeginNeoSequencer() // Flags for ImGui::BeginNeoSequencer()
enum ImGuiNeoSequencerFlags_ enum ImGuiNeoSequencerFlags_ {
{
ImGuiNeoSequencerFlags_None = 0, ImGuiNeoSequencerFlags_None = 0,
ImGuiNeoSequencerFlags_AllowLengthChanging = 1 << 0, ImGuiNeoSequencerFlags_AllowLengthChanging = 1 << 0,
ImGuiNeoSequencerFlags_AllowSelection = 1 << 1, ImGuiNeoSequencerFlags_AllowSelection = 1 << 1,
@ -24,15 +21,13 @@ enum ImGuiNeoSequencerFlags_
}; };
// Flags for ImGui::BeginNeoTimeline() // Flags for ImGui::BeginNeoTimeline()
enum ImGuiNeoTimelineFlags_ enum ImGuiNeoTimelineFlags_ {
{
ImGuiNeoTimelineFlags_None = 0, ImGuiNeoTimelineFlags_None = 0,
ImGuiNeoTimelineFlags_AllowFrameChanging = 1 << 0, ImGuiNeoTimelineFlags_AllowFrameChanging = 1 << 0,
ImGuiNeoTimelineFlags_Group = 1 << 1, ImGuiNeoTimelineFlags_Group = 1 << 1,
}; };
enum ImGuiNeoSequencerCol_ enum ImGuiNeoSequencerCol_ {
{
ImGuiNeoSequencerCol_Bg, ImGuiNeoSequencerCol_Bg,
ImGuiNeoSequencerCol_TopBarBg, ImGuiNeoSequencerCol_TopBarBg,
ImGuiNeoSequencerCol_SelectedTimeline, ImGuiNeoSequencerCol_SelectedTimeline,
@ -80,22 +75,18 @@ namespace ImGui {
IMGUI_API void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, const ImVec4 &col); IMGUI_API void PushNeoSequencerStyleColor(ImGuiNeoSequencerCol idx, const ImVec4 &col);
IMGUI_API void PopNeoSequencerStyleColor(int count = 1); IMGUI_API void PopNeoSequencerStyleColor(int count = 1);
IMGUI_API bool BeginNeoSequencer(const char* id, uint32_t * frame, uint32_t * startFrame, uint32_t * endFrame,const ImVec2& size = ImVec2(0, 0),ImGuiNeoSequencerFlags flags = ImGuiNeoSequencerFlags_None); IMGUI_API bool BeginNeoSequencer(const char *id, uint32_t *frame, uint32_t *startFrame, uint32_t *endFrame,
const ImVec2 &size = ImVec2(0, 0),
ImGuiNeoSequencerFlags flags = ImGuiNeoSequencerFlags_None);
IMGUI_API void EndNeoSequencer(); // Call only when BeginNeoSequencer() returns true!! IMGUI_API void EndNeoSequencer(); // Call only when BeginNeoSequencer() returns true!!
IMGUI_API bool BeginNeoGroup(const char *label, bool *open = nullptr); IMGUI_API bool BeginNeoGroup(const char *label, bool *open = nullptr);
IMGUI_API void EndNeoGroup(); IMGUI_API void EndNeoGroup();
IMGUI_API bool BeginNeoTimeline(const char* label,uint32_t ** keyframes, uint32_t keyframeCount, bool * open = nullptr, ImGuiNeoTimelineFlags flags = ImGuiNeoTimelineFlags_None); IMGUI_API bool BeginNeoTimeline(const char *label, uint32_t **keyframes, uint32_t keyframeCount, bool *open = nullptr,
ImGuiNeoTimelineFlags flags = ImGuiNeoTimelineFlags_None);
IMGUI_API void EndNeoTimeLine(); // Call only when BeginNeoTimeline() returns true!! IMGUI_API void EndNeoTimeLine(); // Call only when BeginNeoTimeline() returns true!!
IMGUI_API bool NeoBeginCreateKeyframe(uint32_t *frame); IMGUI_API bool NeoBeginCreateKeyframe(uint32_t *frame);
#ifdef __cplusplus } // namespace ImGui
// C++ helper
IMGUI_API bool BeginNeoTimeline(const char* label,std::vector<uint32_t> & keyframes ,bool * open = nullptr);
#endif
}
#endif //IMGUI_NEO_SEQUENCER_H