tview/lib/imgui_tex_inspect_internal.h

183 lines
6.4 KiB
C++

// ImGuiTexInspect, a texture inspector widget for dear imgui
#pragma once
#include "imgui.h"
#include "imgui_internal.h"
#include "imgui_tex_inspect.h"
namespace ImGuiTexInspect
{
//-------------------------------------------------------------------------
// [SECTION] UTILITIES
//-------------------------------------------------------------------------
// Returns true if a flag is set
template <typename TSet, typename TFlag>
static inline bool HasFlag(TSet set, TFlag flag)
{
return (set & flag) == flag;
}
// Set flag or flags in set
template <typename TSet, typename TFlag>
static inline void SetFlag(TSet &set, TFlag flags)
{
set = static_cast<TSet>(set | flags);
}
// Clear flag or flags in set
template <typename TSet, typename TFlag>
static inline void ClearFlag(TSet &set, TFlag flag)
{
set = static_cast<TSet>(set & ~flag);
}
static inline float ImFloorSigned(float f)
{
return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1);
}
// Proper modulus operator, as opposed to remainder as calculated by %
template <typename T>
static inline T Modulus(T a, T b)
{
return a - b * ImFloorSigned(a / b);
}
// Defined in recent versions of imgui_internal.h. Included here in case user is on older
// imgui version.
static inline float Round(float f)
{
return ImFloorSigned(f + 0.5f);
}
static inline ImVec2 Abs(ImVec2 v)
{
return ImVec2(ImAbs(v.x), ImAbs(v.y));
}
//-------------------------------------------------------------------------
// [SECTION] STRUCTURES
//-------------------------------------------------------------------------
struct ShaderOptions
{
float ColorTransform[16] = {}; // See CurrentInspector_SetColorMatrix for details
float ColorOffset[4] = {};
ImVec4 BackgroundColor = {0,0,0,0}; // Color used for alpha blending
float PremultiplyAlpha = 0; // If 1 then color will be multiplied by alpha in shader, before blend stage
float DisableFinalAlpha = 0; // If 1 then fragment shader will always output alpha = 1
bool ForceNearestSampling = false; // If true fragment shader will always sample from texel centers
ImVec2 GridWidth = {0,0}; // Width in UV coords of grid line
ImVec4 GridColor = {0,0,0,0};
void ResetColorTransform();
ShaderOptions();
};
struct Inspector
{
ImGuiID ID;
bool Initialized = false;
// Texture
ImTextureID Texture = ImTextureID{};
ImVec2 TextureSize = {0, 0}; // Size in texels of texture
float PixelAspectRatio = 1; // Values other than 1 not supported yet
// View State
bool IsDragging = false; // Is user currently dragging to pan view
ImVec2 PanPos = {0.5f, 0.5f}; // The UV value at the center of the current view
ImVec2 Scale = {1, 1}; // 1 pixel is 1 texel
ImVec2 PanelTopLeftPixel = {0, 0}; // Top left of view in ImGui pixel coordinates
ImVec2 PanelSize = {0, 0}; // Size of area allocated to drawing the image in pixels.
ImVec2 ViewTopLeftPixel = {0, 0}; // Position in ImGui pixel coordinates
ImVec2 ViewSize = {0, 0}; // Rendered size of current image. This could be smaller than panel size if user has zoomed out.
ImVec2 ViewSizeUV = {0, 0}; // Visible region of the texture in UV coordinates
/* Conversion transforms to go back and forth between screen pixels (what ImGui considers screen pixels) and texels*/
Transform2D TexelsToPixels;
Transform2D PixelsToTexels;
// Cached pixel data
bool HaveCurrentTexelData = false;
BufferDesc Buffer;
/* We don't actually access texel data through this pointer. We just
* manage its lifetime. The backend might have asked us to allocated a
* buffer, or it might not. The pointer we actually use to access texel
* data is in the Buffer object above (which depending on what the backend
* did might point to the same memory as this pointer)
*/
ImU8 *DataBuffer = nullptr;
size_t DataBufferSize = 0;
// Configuration
InspectorFlags Flags = 0;
// Background mode
InspectorAlphaMode AlphaMode = InspectorAlphaMode_ImGui;
ImVec4 CustomBackgroundColor = {0, 0, 0, 1};
// Scaling limits
ImVec2 ScaleMin = {0.02f, 0.02f};
ImVec2 ScaleMax = {500, 500};
// Grid
float MinimumGridSize = 4; // Don't draw the grid if lines would be closer than MinimumGridSize pixels
// Annotations
ImU32 MaxAnnotatedTexels = 0;
// Color transformation
ShaderOptions ActiveShaderOptions;
ShaderOptions CachedShaderOptions;
~Inspector();
};
//-------------------------------------------------------------------------
// [SECTION] INTERNAL FUNCTIONS
//-------------------------------------------------------------------------
Inspector *GetByKey(const Context *ctx, ImGuiID key);
Inspector *GetOrAddByKey(Context *ctx, ImGuiID key);
void SetPanPos(Inspector *inspector, ImVec2 pos);
void SetScale(Inspector *inspector, ImVec2 scale);
void SetScale(Inspector *inspector, float scaleY);
void RoundPanPos(Inspector *inspector);
ImU8 *GetBuffer(Inspector *inspector, size_t bytes);
/* GetTexelsToPixels
* Calculate a transform to convert from texel coordinates to screen pixel coordinates
* */
Transform2D GetTexelsToPixels(ImVec2 screenTopLeft, ImVec2 screenViewSize, ImVec2 uvTopLeft, ImVec2 uvViewSize, ImVec2 textureSize);
//-------------------------------------------------------------------------
// [SECTION] IMGUI UTILS
//-------------------------------------------------------------------------
/* TextVector
* Draws a single-column ImGui table with one row for each provided string
*/
void TextVector(const char *title, const char *const *strings, int n);
/* PushDisabled & PopDisabled
* Push and Pop and ImGui styles that disable and "grey out" ImGui elements
* by making them non interactive and transparent*/
void PushDisabled();
void PopDisabled();
//-------------------------------------------------------------------------
// [SECTION] BACKEND FUNCTIONS
//-------------------------------------------------------------------------
void BackEnd_SetShader(const ImDrawList *drawList, const ImDrawCmd *cmd, const Inspector *inspector);
bool BackEnd_GetData(Inspector *inspector, ImTextureID texture, int x, int y, int width, int height, BufferDesc *buffer);
} // namespace ImGuiTexInspect