Files
leocad/common/lc_context.h
T
Leonardo Zide c9f473b1bf Add fading outlines for new-piece highlights
Highlight newly added pieces with the configured highlight color in outline
mode, and widen outlines with an outward opacity falloff. Keep highlight
coverage independent of selection in the existing mask so overlap preserves
selection and focus priority, and limit the obscured fill to selection.
Skip selection visibility and occluder draws in highlight-only scenes while
retaining colored-edge fallback for line meshes and unsupported views.

Rename the shared preference to Highlight Style throughout the UI, renderer,
and persisted settings without migrating the previous key. Update contextual
help and translation catalogs, preserving existing translations and leaving
new text unfinished. Name the selection-only mask draw DrawSelectionMask.

Validation: macOS debug build; desktop OpenGL checks for fading, focus colors,
selection/highlight overlap, occlusion, transparency, MSAA, and edge fallback;
preference round trips; compilation of all nine translation catalogs.

Fixes #461
2026-10-23 23:49:46 -07:00

343 lines
8.5 KiB
C++

#pragma once
#include "lc_math.h"
#include "lc_mesh.h"
#include "lc_result.h"
class lcVertexBuffer
{
public:
constexpr lcVertexBuffer()
: Pointer(nullptr)
{
}
bool IsValid() const
{
return Pointer != nullptr;
}
union
{
GLuint Object;
void* Pointer;
};
};
class lcIndexBuffer
{
public:
constexpr lcIndexBuffer()
: Pointer(nullptr)
{
}
bool IsValid() const
{
return Pointer != nullptr;
}
union
{
GLuint Object;
void* Pointer;
};
};
enum class lcMaterialType
{
UnlitColor,
UnlitColorConditional,
UnlitTextureModulate,
TextSDF,
UnlitTextureDecal,
UnlitVertexColor,
UnlitViewSphere,
FakeLitColor,
FakeLitTextureDecal,
OutlineComposite,
Count
};
enum class lcProgramAttrib
{
Position,
Normal,
TexCoord,
Color,
Count,
ControlPoint1 = Position,
ControlPoint2 = Normal,
ControlPoint3 = TexCoord,
ControlPoint4 = Color
};
struct lcProgram
{
GLuint Object;
GLint WorldViewProjectionMatrixLocation;
GLint WorldMatrixLocation;
GLint MaterialColorLocation;
GLint LightPositionLocation;
GLint EyePositionLocation;
GLint HighlightParamsLocation;
GLint OutlineParamsLocation;
GLint TextHaloColorLocation;
};
enum class lcPolygonOffset
{
None,
Opaque,
Translucent
};
enum class lcDepthFunction
{
LessEqual,
Always
};
struct lcVertexAttribState
{
GLint Size = 0;
GLenum Type = 0;
GLboolean Normalized = 0;
bool Enabled = 0;
GLsizei Stride = 0;
const void* Pointer = nullptr;
GLuint VertexBufferObject = 0;
};
// Restores caller state after temporary rendering, including a caller with no current context.
class lcScopedGLContextState
{
public:
lcScopedGLContextState();
~lcScopedGLContextState();
lcScopedGLContextState(const lcScopedGLContextState&) = delete;
lcScopedGLContextState& operator=(const lcScopedGLContextState&) = delete;
private:
QOpenGLContext* mContext;
QSurface* mSurface;
GLint mDrawFramebuffer = 0;
GLint mReadFramebuffer = 0;
bool mSeparateFramebuffers = false;
};
class lcContext : public QOpenGLFunctions
{
public:
lcContext();
~lcContext();
lcContext(const lcContext&) = delete;
lcContext(lcContext&&) = delete;
lcContext& operator=(const lcContext&) = delete;
lcContext& operator=(lcContext&&) = delete;
static lcResult<void> InitializeRenderer(bool CreateRenderResources);
static void ShutdownRenderer();
static lcContext* GetGlobalOffscreenContext();
lcResult<void> CreateResources();
void DestroyResources();
void SetDefaultState();
void ClearResources();
void MakeCurrent();
QOpenGLContext* GetGLContext() const { return mContext; }
void SetGLContext(QOpenGLContext* GLContext, QOpenGLWidget* Widget);
void SetOffscreenContext();
bool IsOffscreen() const
{
return mWidget == nullptr;
}
void ClearColorAndDepth(const lcVector4& ClearColor);
void ClearDepth();
static bool SupportsMaterial(lcMaterialType MaterialType)
{
return mPrograms[static_cast<int>(MaterialType)].Object != 0;
}
static bool SupportsDefaultLights()
{
return SupportsMaterial(lcMaterialType::FakeLitColor) && SupportsMaterial(lcMaterialType::FakeLitTextureDecal);
}
static bool SupportsSelectionOutline();
int GetMaxTextureSize();
std::unique_ptr<QOpenGLFramebufferObject> CreateFramebuffer(int Width, int Height);
bool GenerateOutlineMasks(const lcScene& Scene, QOpenGLFramebufferObject& FullFramebuffer, QOpenGLFramebufferObject& VisibleFramebuffer);
void DrawOutline(QOpenGLFramebufferObject& FullFramebuffer, QOpenGLFramebufferObject& VisibleFramebuffer, float DeviceScale);
void SetWorldMatrix(const lcMatrix44& WorldMatrix)
{
mWorldMatrix = WorldMatrix;
mWorldMatrixDirty = true;
}
void SetViewMatrix(const lcMatrix44& ViewMatrix)
{
mViewMatrix = ViewMatrix;
mViewMatrixDirty = true;
mViewProjectionMatrixDirty = true;
}
void SetProjectionMatrix(const lcMatrix44& ProjectionMatrix)
{
mProjectionMatrix = ProjectionMatrix;
mProjectionMatrixDirty = true;
mViewProjectionMatrixDirty = true;
}
const lcMatrix44& GetProjectionMatrix()
{
return mProjectionMatrix;
}
void SetMaterial(lcMaterialType MaterialType);
void SetViewport(int x, int y, int Width, int Height);
void SetPolygonOffset(lcPolygonOffset PolygonOffset);
void SetDepthWrite(bool Enable);
void SetDepthFunction(lcDepthFunction DepthFunction);
void EnableDepthTest(bool Enable);
void EnableColorWrite(bool Enable);
void EnableColorBlend(bool Enable);
void EnableCullFace(bool Enable);
void SetLineWidth(float LineWidth);
void BindTexture2D(const lcTexture* Texture);
void BindTextureCubeMap(const lcTexture* Texture);
void ClearTexture2D();
void ClearTextureCubeMap();
bool UploadTexture(lcTexture* Texture);
void SetColor(const lcVector4& Color)
{
mColor = Color;
mColorDirty = true;
}
void SetTextHaloColor(const lcVector4& Color)
{
mTextHaloColor = Color;
mTextHaloColorDirty = true;
}
void SetHighlightParams(const lcVector4& HighlightPosition, const lcVector4& TextColor, const lcVector4& BackgroundColor, const lcVector4& HighlightColor)
{
mHighlightParams[0] = HighlightPosition;
mHighlightParams[1] = TextColor;
mHighlightParams[2] = BackgroundColor;
mHighlightParams[3] = HighlightColor;
mHighlightParamsDirty = true;
}
void SetOutlineParams(const lcVector4& PixelSizeRadiusOpacity, const lcVector4& SelectedColor, const lcVector4& FocusedColor, const lcVector4& HighlightedColor)
{
mOutlineParams[0] = PixelSizeRadiusOpacity;
mOutlineParams[1] = SelectedColor;
mOutlineParams[2] = FocusedColor;
mOutlineParams[3] = HighlightedColor;
mOutlineParamsDirty = true;
}
void SetColor(float Red, float Green, float Blue, float Alpha);
void SetColorIndex(int ColorIndex);
void SetColorIndexTinted(int ColorIndex, const lcVector4& Tint, float Weight);
void SetColorIndexTinted(int ColorIndex, const lcVector4& Tint);
void SetEdgeColorIndex(int ColorIndex);
void SetEdgeColorIndexTinted(int ColorIndex, const lcVector4& Tint);
lcVertexBuffer CreateVertexBuffer(int Size, const void* Data);
void DestroyVertexBuffer(lcVertexBuffer& VertexBuffer);
lcIndexBuffer CreateIndexBuffer(int Size, const void* Data);
void DestroyIndexBuffer(lcIndexBuffer& IndexBuffer);
void ClearVertexBuffer();
void SetVertexBuffer(lcVertexBuffer VertexBuffer);
void SetVertexBufferPointer(const void* VertexBuffer);
void ClearIndexBuffer();
void SetIndexBuffer(lcIndexBuffer IndexBuffer);
void SetIndexBufferPointer(const void* IndexBuffer);
void SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals);
void SetVertexFormatPosition(int PositionSize);
void SetVertexFormatConditional(int BufferOffset);
void DrawPrimitives(GLenum Mode, GLint First, GLsizei Count);
void DrawIndexedPrimitives(GLenum Mode, GLsizei Count, GLenum Type, int Offset);
void BindMesh(const lcMesh* Mesh);
protected:
static lcResult<void> CreateOffscreenContext();
static void DestroyOffscreenContext();
lcResult<void> CreateShaderPrograms();
void UploadTextureImage(GLenum Target, int Level, GLenum Format, const QImage& Image);
void FlushState();
bool TryShareDepthAttachment(GLuint SourceFramebuffer, QOpenGLFramebufferObject& TargetFramebuffer);
void SetVertexAttribPointer(lcProgramAttrib Attrib, GLint Size, GLenum Type, GLboolean Normalized, GLsizei Stride, const void* Pointer);
void EnableVertexAttrib(lcProgramAttrib Attrib);
void DisableVertexAttrib(lcProgramAttrib Attrib);
QOpenGLWidget* mWidget = nullptr;
QOpenGLContext* mContext = nullptr;
GLuint mVertexBufferObject;
GLuint mIndexBufferObject;
const char* mVertexBufferPointer;
const char* mIndexBufferPointer;
lcMaterialType mMaterialType;
lcVertexAttribState mVertexAttribState[static_cast<int>(lcProgramAttrib::Count)];
GLuint mTexture2D;
GLuint mTextureCubeMap;
lcPolygonOffset mPolygonOffset;
bool mDepthWrite;
lcDepthFunction mDepthFunction;
bool mDepthTest;
bool mColorWrite;
bool mColorBlend;
bool mCullFace;
float mLineWidth;
lcVector4 mColor;
lcVector4 mTextHaloColor;
lcMatrix44 mWorldMatrix;
lcMatrix44 mViewMatrix;
lcMatrix44 mProjectionMatrix;
lcMatrix44 mViewProjectionMatrix;
lcVector4 mHighlightParams[4];
lcVector4 mOutlineParams[4];
bool mColorDirty;
bool mTextHaloColorDirty;
bool mWorldMatrixDirty;
bool mViewMatrixDirty;
bool mProjectionMatrixDirty;
bool mViewProjectionMatrixDirty;
bool mHighlightParamsDirty;
bool mOutlineParamsDirty;
static std::unique_ptr<QOpenGLContext> mOffscreenContext;
static std::unique_ptr<QOffscreenSurface> mOffscreenSurface;
static std::unique_ptr<lcContext> mGlobalOffscreenContext;
static bool mRenderResourcesCreated;
static lcProgram mPrograms[static_cast<int>(lcMaterialType::Count)];
Q_DECLARE_TR_FUNCTIONS(lcContext);
};