feat: Add texture support to UI widgets and update gitignore
UI Widget Enhancements: - Add texture support to UICheckbox (box and checkmark textures) - Add texture support to UISlider (track and handle textures) - Add texture support to UIPanel (background texture) - Add texture support to UIProgressBar (background and fill textures) - Add texture support to UIScrollPanel (background and scrollbar textures) - All widgets now support textureId with tint color for flexible styling BgfxRenderer: - Add texture loading helpers for widget texturing - Update RHI device for texture management - Add ResourceCache texture ID support Maintenance: - Add tmpclaude-* to .gitignore (temporary Claude Code directories) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0441a9d648
commit
b39854cf2c
1
.gitignore
vendored
1
.gitignore
vendored
@ -44,3 +44,4 @@ desktop.ini
|
|||||||
*.swp
|
*.swp
|
||||||
*~
|
*~
|
||||||
nul
|
nul
|
||||||
|
tmpclaude-*
|
||||||
|
|||||||
@ -23,6 +23,14 @@ namespace grove {
|
|||||||
BgfxRendererModule::BgfxRendererModule() = default;
|
BgfxRendererModule::BgfxRendererModule() = default;
|
||||||
BgfxRendererModule::~BgfxRendererModule() = default;
|
BgfxRendererModule::~BgfxRendererModule() = default;
|
||||||
|
|
||||||
|
ResourceCache* BgfxRendererModule::getResourceCache() const {
|
||||||
|
return m_resourceCache.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
rhi::IRHIDevice* BgfxRendererModule::getDevice() const {
|
||||||
|
return m_device.get();
|
||||||
|
}
|
||||||
|
|
||||||
void BgfxRendererModule::setConfiguration(const IDataNode& config, IIO* io, ITaskScheduler* scheduler) {
|
void BgfxRendererModule::setConfiguration(const IDataNode& config, IIO* io, ITaskScheduler* scheduler) {
|
||||||
m_io = io;
|
m_io = io;
|
||||||
|
|
||||||
|
|||||||
@ -45,6 +45,13 @@ public:
|
|||||||
std::string getType() const override { return "bgfx_renderer"; }
|
std::string getType() const override { return "bgfx_renderer"; }
|
||||||
bool isIdle() const override { return true; }
|
bool isIdle() const override { return true; }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// Public API for external access
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
ResourceCache* getResourceCache() const;
|
||||||
|
rhi::IRHIDevice* getDevice() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Logger
|
// Logger
|
||||||
std::shared_ptr<spdlog::logger> m_logger;
|
std::shared_ptr<spdlog::logger> m_logger;
|
||||||
|
|||||||
@ -205,9 +205,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
UniformHandle createUniform(const char* name, uint8_t numVec4s) override {
|
UniformHandle createUniform(const char* name, uint8_t numVec4s) override {
|
||||||
|
// Detect sampler uniforms by name prefix (bgfx convention: s_*)
|
||||||
|
bool isSampler = (name[0] == 's' && name[1] == '_');
|
||||||
|
|
||||||
bgfx::UniformHandle uniform = bgfx::createUniform(
|
bgfx::UniformHandle uniform = bgfx::createUniform(
|
||||||
name,
|
name,
|
||||||
numVec4s == 1 ? bgfx::UniformType::Vec4 : bgfx::UniformType::Mat4
|
isSampler ? bgfx::UniformType::Sampler :
|
||||||
|
(numVec4s == 1 ? bgfx::UniformType::Vec4 : bgfx::UniformType::Mat4)
|
||||||
);
|
);
|
||||||
|
|
||||||
UniformHandle result;
|
UniformHandle result;
|
||||||
@ -557,6 +561,15 @@ public:
|
|||||||
if (hasTexture) {
|
if (hasTexture) {
|
||||||
bgfx::TextureHandle tex = { pendingTexture.id };
|
bgfx::TextureHandle tex = { pendingTexture.id };
|
||||||
bgfx::UniformHandle sampler = { pendingSampler.id };
|
bgfx::UniformHandle sampler = { pendingSampler.id };
|
||||||
|
|
||||||
|
static int submitCount = 0;
|
||||||
|
if (submitCount < 10) {
|
||||||
|
spdlog::info("[Submit #{}] BgfxDevice::submit() - pendingTexture.id={}, tex.idx={}, sampler.idx={}, slot={}",
|
||||||
|
submitCount, pendingTexture.id, tex.idx, sampler.idx, pendingTextureSlot);
|
||||||
|
spdlog::info(" bgfx::isValid(tex): {}", bgfx::isValid(tex));
|
||||||
|
submitCount++;
|
||||||
|
}
|
||||||
|
|
||||||
bgfx::setTexture(pendingTextureSlot, sampler, tex);
|
bgfx::setTexture(pendingTextureSlot, sampler, tex);
|
||||||
}
|
}
|
||||||
bgfx::ProgramHandle program = { cmd.submit.shader.id };
|
bgfx::ProgramHandle program = { cmd.submit.shader.id };
|
||||||
|
|||||||
@ -31,6 +31,10 @@ public:
|
|||||||
// Loading (called from main thread) - returns texture ID
|
// Loading (called from main thread) - returns texture ID
|
||||||
uint16_t loadTextureWithId(rhi::IRHIDevice& device, const std::string& path);
|
uint16_t loadTextureWithId(rhi::IRHIDevice& device, const std::string& path);
|
||||||
|
|
||||||
|
// Register an already-created texture (for runtime/procedural textures)
|
||||||
|
// Returns the assigned texture ID
|
||||||
|
uint16_t registerTexture(rhi::TextureHandle handle, const std::string& name = "");
|
||||||
|
|
||||||
// Legacy loading (returns handle directly)
|
// Legacy loading (returns handle directly)
|
||||||
rhi::TextureHandle loadTexture(rhi::IRHIDevice& device, const std::string& path);
|
rhi::TextureHandle loadTexture(rhi::IRHIDevice& device, const std::string& path);
|
||||||
rhi::ShaderHandle loadShader(rhi::IRHIDevice& device, const std::string& name,
|
rhi::ShaderHandle loadShader(rhi::IRHIDevice& device, const std::string& name,
|
||||||
|
|||||||
@ -86,6 +86,9 @@ void UITree::registerDefaultWidgets() {
|
|||||||
style.borderRadius = static_cast<float>(styleNode->getDouble("borderRadius", style.borderRadius));
|
style.borderRadius = static_cast<float>(styleNode->getDouble("borderRadius", style.borderRadius));
|
||||||
style.textureId = styleNode->getInt("textureId", 0);
|
style.textureId = styleNode->getInt("textureId", 0);
|
||||||
style.useTexture = style.textureId > 0;
|
style.useTexture = style.textureId > 0;
|
||||||
|
if (style.textureId > 0) {
|
||||||
|
spdlog::info("UIButton style parsed: textureId={}, useTexture={}", style.textureId, style.useTexture);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse style (const_cast safe for read-only operations)
|
// Parse style (const_cast safe for read-only operations)
|
||||||
|
|||||||
@ -34,22 +34,42 @@ void UICheckbox::render(UIRenderer& renderer) {
|
|||||||
// Box background (retained mode)
|
// Box background (retained mode)
|
||||||
int boxLayer = renderer.nextLayer();
|
int boxLayer = renderer.nextLayer();
|
||||||
uint32_t currentBoxColor = isHovered ? 0x475569FF : boxColor;
|
uint32_t currentBoxColor = isHovered ? 0x475569FF : boxColor;
|
||||||
renderer.updateRect(m_renderId, boxX, boxY, boxSize, boxSize, currentBoxColor, boxLayer);
|
|
||||||
|
if (useBoxTexture && boxTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_renderId, boxX, boxY, boxSize, boxSize, boxTextureId, boxTintColor, boxLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_renderId, boxX, boxY, boxSize, boxSize, currentBoxColor, boxLayer);
|
||||||
|
}
|
||||||
|
|
||||||
// Check mark if checked (retained mode)
|
// Check mark if checked (retained mode)
|
||||||
int checkLayer = renderer.nextLayer();
|
int checkLayer = renderer.nextLayer();
|
||||||
if (checked) {
|
if (checked) {
|
||||||
// Draw a smaller filled rect as checkmark
|
|
||||||
float checkPadding = boxSize * 0.25f;
|
float checkPadding = boxSize * 0.25f;
|
||||||
renderer.updateRect(
|
|
||||||
m_checkRenderId,
|
if (useCheckTexture && checkTextureId > 0) {
|
||||||
boxX + checkPadding,
|
// Draw checkmark texture
|
||||||
boxY + checkPadding,
|
renderer.updateSprite(
|
||||||
boxSize - checkPadding * 2,
|
m_checkRenderId,
|
||||||
boxSize - checkPadding * 2,
|
boxX + checkPadding,
|
||||||
checkColor,
|
boxY + checkPadding,
|
||||||
checkLayer
|
boxSize - checkPadding * 2,
|
||||||
);
|
boxSize - checkPadding * 2,
|
||||||
|
checkTextureId,
|
||||||
|
checkTintColor,
|
||||||
|
checkLayer
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Draw a smaller filled rect as checkmark
|
||||||
|
renderer.updateRect(
|
||||||
|
m_checkRenderId,
|
||||||
|
boxX + checkPadding,
|
||||||
|
boxY + checkPadding,
|
||||||
|
boxSize - checkPadding * 2,
|
||||||
|
boxSize - checkPadding * 2,
|
||||||
|
checkColor,
|
||||||
|
checkLayer
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Hide checkmark when unchecked (zero-size rect)
|
// Hide checkmark when unchecked (zero-size rect)
|
||||||
renderer.updateRect(m_checkRenderId, 0, 0, 0, 0, 0x00000000, checkLayer);
|
renderer.updateRect(m_checkRenderId, 0, 0, 0, 0, 0x00000000, checkLayer);
|
||||||
|
|||||||
@ -49,6 +49,15 @@ public:
|
|||||||
float fontSize = 16.0f;
|
float fontSize = 16.0f;
|
||||||
float spacing = 8.0f; // Space between box and text
|
float spacing = 8.0f; // Space between box and text
|
||||||
|
|
||||||
|
// Texture support
|
||||||
|
int boxTextureId = 0; // Box texture ID (0 = solid color)
|
||||||
|
bool useBoxTexture = false; // Use texture for box
|
||||||
|
uint32_t boxTintColor = 0xFFFFFFFF; // Tint for box texture
|
||||||
|
|
||||||
|
int checkTextureId = 0; // Checkmark texture ID (0 = solid rect)
|
||||||
|
bool useCheckTexture = false; // Use texture for checkmark
|
||||||
|
uint32_t checkTintColor = 0xFFFFFFFF; // Tint for checkmark texture
|
||||||
|
|
||||||
// State
|
// State
|
||||||
bool isHovered = false;
|
bool isHovered = false;
|
||||||
bool isPressed = false;
|
bool isPressed = false;
|
||||||
|
|||||||
@ -31,7 +31,16 @@ void UIPanel::render(UIRenderer& renderer) {
|
|||||||
|
|
||||||
// Retained mode: only publish if changed
|
// Retained mode: only publish if changed
|
||||||
int layer = renderer.nextLayer();
|
int layer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, layer);
|
|
||||||
|
// Check if fully transparent (alpha channel = 0)
|
||||||
|
bool isFullyTransparent = (bgColor & 0xFF) == 0;
|
||||||
|
|
||||||
|
// Render background (texture or solid color) - skip if fully transparent
|
||||||
|
if (useTexture && textureId > 0) {
|
||||||
|
renderer.updateSprite(m_renderId, absX, absY, width, height, textureId, tintColor, layer);
|
||||||
|
} else if (!isFullyTransparent) {
|
||||||
|
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, layer);
|
||||||
|
}
|
||||||
|
|
||||||
// Render children on top
|
// Render children on top
|
||||||
renderChildren(renderer);
|
renderChildren(renderer);
|
||||||
|
|||||||
@ -25,6 +25,11 @@ public:
|
|||||||
float borderRadius = 0.0f; // For future use
|
float borderRadius = 0.0f; // For future use
|
||||||
float borderWidth = 0.0f;
|
float borderWidth = 0.0f;
|
||||||
uint32_t borderColor = 0x000000FF;
|
uint32_t borderColor = 0x000000FF;
|
||||||
|
|
||||||
|
// Texture support
|
||||||
|
int textureId = 0; // Texture ID (0 = solid color)
|
||||||
|
bool useTexture = false; // Use texture instead of solid color
|
||||||
|
uint32_t tintColor = 0xFFFFFFFF; // RGBA tint for texture (white = no tint)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace grove
|
} // namespace grove
|
||||||
|
|||||||
@ -30,16 +30,28 @@ void UIProgressBar::render(UIRenderer& renderer) {
|
|||||||
|
|
||||||
// Retained mode: only publish if changed
|
// Retained mode: only publish if changed
|
||||||
int bgLayer = renderer.nextLayer();
|
int bgLayer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, bgLayer);
|
if (useBgTexture && bgTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_renderId, absX, absY, width, height, bgTextureId, bgTintColor, bgLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, bgLayer);
|
||||||
|
}
|
||||||
|
|
||||||
// Render fill based on progress
|
// Render fill based on progress
|
||||||
int fillLayer = renderer.nextLayer();
|
int fillLayer = renderer.nextLayer();
|
||||||
if (horizontal) {
|
if (horizontal) {
|
||||||
float fillWidth = progress * width;
|
float fillWidth = progress * width;
|
||||||
renderer.updateRect(m_fillRenderId, absX, absY, fillWidth, height, fillColor, fillLayer);
|
if (useFillTexture && fillTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_fillRenderId, absX, absY, fillWidth, height, fillTextureId, fillTintColor, fillLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_fillRenderId, absX, absY, fillWidth, height, fillColor, fillLayer);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
float fillHeight = progress * height;
|
float fillHeight = progress * height;
|
||||||
renderer.updateRect(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillColor, fillLayer);
|
if (useFillTexture && fillTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillTextureId, fillTintColor, fillLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillColor, fillLayer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render percentage text if enabled
|
// Render percentage text if enabled
|
||||||
|
|||||||
@ -42,6 +42,15 @@ public:
|
|||||||
uint32_t textColor = 0xFFFFFFFF;
|
uint32_t textColor = 0xFFFFFFFF;
|
||||||
float fontSize = 14.0f;
|
float fontSize = 14.0f;
|
||||||
|
|
||||||
|
// Texture support
|
||||||
|
int bgTextureId = 0; // Background texture ID (0 = solid color)
|
||||||
|
bool useBgTexture = false; // Use texture for background
|
||||||
|
uint32_t bgTintColor = 0xFFFFFFFF; // Tint for background texture
|
||||||
|
|
||||||
|
int fillTextureId = 0; // Fill texture ID (0 = solid color)
|
||||||
|
bool useFillTexture = false; // Use texture for fill
|
||||||
|
uint32_t fillTintColor = 0xFFFFFFFF; // Tint for fill texture
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Retained mode render IDs
|
// Retained mode render IDs
|
||||||
uint32_t m_fillRenderId = 0; // Separate ID for fill bar element
|
uint32_t m_fillRenderId = 0; // Separate ID for fill bar element
|
||||||
|
|||||||
@ -72,7 +72,11 @@ void UIScrollPanel::render(UIRenderer& renderer) {
|
|||||||
|
|
||||||
// Render background
|
// Render background
|
||||||
int bgLayer = renderer.nextLayer();
|
int bgLayer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, bgLayer);
|
if (useBgTexture && bgTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_renderId, absX, absY, width, height, bgTextureId, bgTintColor, bgLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_renderId, absX, absY, width, height, bgColor, bgLayer);
|
||||||
|
}
|
||||||
|
|
||||||
// Render border if needed
|
// Render border if needed
|
||||||
if (borderWidth > 0.0f) {
|
if (borderWidth > 0.0f) {
|
||||||
@ -225,7 +229,12 @@ void UIScrollPanel::renderScrollbar(UIRenderer& renderer) {
|
|||||||
// Render scrollbar background track
|
// Render scrollbar background track
|
||||||
float trackX = absX + width - scrollbarWidth;
|
float trackX = absX + width - scrollbarWidth;
|
||||||
int trackLayer = renderer.nextLayer();
|
int trackLayer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_scrollTrackId, trackX, absY, scrollbarWidth, height, scrollbarBgColor, trackLayer);
|
|
||||||
|
if (useScrollbarTrackTexture && scrollbarTrackTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_scrollTrackId, trackX, absY, scrollbarWidth, height, scrollbarTrackTextureId, scrollbarTrackTintColor, trackLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_scrollTrackId, trackX, absY, scrollbarWidth, height, scrollbarBgColor, trackLayer);
|
||||||
|
}
|
||||||
|
|
||||||
// Render scrollbar thumb
|
// Render scrollbar thumb
|
||||||
float sbX, sbY, sbW, sbH;
|
float sbX, sbY, sbW, sbH;
|
||||||
@ -233,7 +242,12 @@ void UIScrollPanel::renderScrollbar(UIRenderer& renderer) {
|
|||||||
|
|
||||||
// Use hover color if hovered (would need ctx passed to render, simplified for now)
|
// Use hover color if hovered (would need ctx passed to render, simplified for now)
|
||||||
int thumbLayer = renderer.nextLayer();
|
int thumbLayer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_scrollThumbId, sbX, sbY, sbW, sbH, scrollbarColor, thumbLayer);
|
|
||||||
|
if (useScrollbarThumbTexture && scrollbarThumbTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_scrollThumbId, sbX, sbY, sbW, sbH, scrollbarThumbTextureId, scrollbarThumbTintColor, thumbLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_scrollThumbId, sbX, sbY, sbW, sbH, scrollbarColor, thumbLayer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIScrollPanel::updateScrollInteraction(UIContext& ctx) {
|
void UIScrollPanel::updateScrollInteraction(UIContext& ctx) {
|
||||||
|
|||||||
@ -48,6 +48,19 @@ public:
|
|||||||
float borderWidth = 1.0f;
|
float borderWidth = 1.0f;
|
||||||
uint32_t borderColor = 0x444444FF;
|
uint32_t borderColor = 0x444444FF;
|
||||||
|
|
||||||
|
// Texture support
|
||||||
|
int bgTextureId = 0; // Background texture ID (0 = solid color)
|
||||||
|
bool useBgTexture = false; // Use texture for background
|
||||||
|
uint32_t bgTintColor = 0xFFFFFFFF; // Tint for background texture
|
||||||
|
|
||||||
|
int scrollbarTrackTextureId = 0; // Scrollbar track texture ID (0 = solid color)
|
||||||
|
bool useScrollbarTrackTexture = false; // Use texture for scrollbar track
|
||||||
|
uint32_t scrollbarTrackTintColor = 0xFFFFFFFF; // Tint for scrollbar track texture
|
||||||
|
|
||||||
|
int scrollbarThumbTextureId = 0; // Scrollbar thumb texture ID (0 = solid color)
|
||||||
|
bool useScrollbarThumbTexture = false; // Use texture for scrollbar thumb
|
||||||
|
uint32_t scrollbarThumbTintColor = 0xFFFFFFFF; // Tint for scrollbar thumb texture
|
||||||
|
|
||||||
// Interaction state
|
// Interaction state
|
||||||
bool isDraggingContent = false;
|
bool isDraggingContent = false;
|
||||||
bool isDraggingScrollbar = false;
|
bool isDraggingScrollbar = false;
|
||||||
|
|||||||
@ -38,16 +38,28 @@ void UISlider::render(UIRenderer& renderer) {
|
|||||||
|
|
||||||
// Render track (background)
|
// Render track (background)
|
||||||
int trackLayer = renderer.nextLayer();
|
int trackLayer = renderer.nextLayer();
|
||||||
renderer.updateRect(m_renderId, absX, absY, width, height, trackColor, trackLayer);
|
if (useTrackTexture && trackTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_renderId, absX, absY, width, height, trackTextureId, trackTintColor, trackLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_renderId, absX, absY, width, height, trackColor, trackLayer);
|
||||||
|
}
|
||||||
|
|
||||||
// Render fill (progress)
|
// Render fill (progress)
|
||||||
int fillLayer = renderer.nextLayer();
|
int fillLayer = renderer.nextLayer();
|
||||||
if (horizontal) {
|
if (horizontal) {
|
||||||
float fillWidth = (value - minValue) / (maxValue - minValue) * width;
|
float fillWidth = (value - minValue) / (maxValue - minValue) * width;
|
||||||
renderer.updateRect(m_fillRenderId, absX, absY, fillWidth, height, fillColor, fillLayer);
|
if (useFillTexture && fillTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_fillRenderId, absX, absY, fillWidth, height, fillTextureId, fillTintColor, fillLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_fillRenderId, absX, absY, fillWidth, height, fillColor, fillLayer);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
float fillHeight = (value - minValue) / (maxValue - minValue) * height;
|
float fillHeight = (value - minValue) / (maxValue - minValue) * height;
|
||||||
renderer.updateRect(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillColor, fillLayer);
|
if (useFillTexture && fillTextureId > 0) {
|
||||||
|
renderer.updateSprite(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillTextureId, fillTintColor, fillLayer);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(m_fillRenderId, absX, absY + height - fillHeight, width, fillHeight, fillColor, fillLayer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render handle
|
// Render handle
|
||||||
@ -57,15 +69,29 @@ void UISlider::render(UIRenderer& renderer) {
|
|||||||
// Handle is a small square
|
// Handle is a small square
|
||||||
int handleLayer = renderer.nextLayer();
|
int handleLayer = renderer.nextLayer();
|
||||||
float halfHandle = handleSize * 0.5f;
|
float halfHandle = handleSize * 0.5f;
|
||||||
renderer.updateRect(
|
|
||||||
m_handleRenderId,
|
if (useHandleTexture && handleTextureId > 0) {
|
||||||
handleX - halfHandle,
|
renderer.updateSprite(
|
||||||
handleY - halfHandle,
|
m_handleRenderId,
|
||||||
handleSize,
|
handleX - halfHandle,
|
||||||
handleSize,
|
handleY - halfHandle,
|
||||||
handleColor,
|
handleSize,
|
||||||
handleLayer
|
handleSize,
|
||||||
);
|
handleTextureId,
|
||||||
|
handleTintColor,
|
||||||
|
handleLayer
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
renderer.updateRect(
|
||||||
|
m_handleRenderId,
|
||||||
|
handleX - halfHandle,
|
||||||
|
handleY - halfHandle,
|
||||||
|
handleSize,
|
||||||
|
handleSize,
|
||||||
|
handleColor,
|
||||||
|
handleLayer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Render children on top
|
// Render children on top
|
||||||
renderChildren(renderer);
|
renderChildren(renderer);
|
||||||
|
|||||||
@ -61,6 +61,19 @@ public:
|
|||||||
uint32_t handleColor = 0xecf0f1FF;
|
uint32_t handleColor = 0xecf0f1FF;
|
||||||
float handleSize = 16.0f;
|
float handleSize = 16.0f;
|
||||||
|
|
||||||
|
// Texture support
|
||||||
|
int trackTextureId = 0; // Track texture ID (0 = solid color)
|
||||||
|
bool useTrackTexture = false; // Use texture for track
|
||||||
|
uint32_t trackTintColor = 0xFFFFFFFF; // Tint for track texture
|
||||||
|
|
||||||
|
int fillTextureId = 0; // Fill texture ID (0 = solid color)
|
||||||
|
bool useFillTexture = false; // Use texture for fill
|
||||||
|
uint32_t fillTintColor = 0xFFFFFFFF; // Tint for fill texture
|
||||||
|
|
||||||
|
int handleTextureId = 0; // Handle texture ID (0 = solid color)
|
||||||
|
bool useHandleTexture = false; // Use texture for handle
|
||||||
|
uint32_t handleTintColor = 0xFFFFFFFF; // Tint for handle texture
|
||||||
|
|
||||||
// State
|
// State
|
||||||
bool isDragging = false;
|
bool isDragging = false;
|
||||||
bool isHovered = false;
|
bool isHovered = false;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user