Working on health bar
This commit is contained in:
parent
8552725dfc
commit
22b0e1992f
@ -89,15 +89,21 @@
|
|||||||
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "Slider",
|
||||||
"name": "healthBarBorder",
|
"name": "healthBarFill",
|
||||||
"width": 151.2,
|
"width": 151.2,
|
||||||
"height": 22.8,
|
"height": 22.8,
|
||||||
"y": 49.8,
|
"y": 49.8,
|
||||||
"x": 100.6,
|
"x": 100.6,
|
||||||
"horizontal_gravity": "left",
|
"horizontal_gravity": "left",
|
||||||
"vertical_align": "top",
|
"vertical_gravity": "top",
|
||||||
"texture": "resources/w/ui/img/HealthBarFill001.png"
|
"orientation": "horizontal",
|
||||||
|
"value": 1.0,
|
||||||
|
"fillMode": true,
|
||||||
|
"interactive": false,
|
||||||
|
"textures": {
|
||||||
|
"track": "resources/w/ui/img/HealthBarFill001.png"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextView",
|
"type": "TextView",
|
||||||
|
|||||||
@ -89,15 +89,21 @@
|
|||||||
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "Slider",
|
||||||
"name": "healthBarBorder",
|
"name": "healthBarFill",
|
||||||
"width": 151.2,
|
"width": 151.2,
|
||||||
"height": 22.8,
|
"height": 22.8,
|
||||||
"y": 49.8,
|
"y": 49.8,
|
||||||
"x": 100.6,
|
"x": 100.6,
|
||||||
"horizontal_gravity": "left",
|
"horizontal_gravity": "left",
|
||||||
"vertical_align": "top",
|
"vertical_gravity": "top",
|
||||||
"texture": "resources/w/ui/img/HealthBarFill001.png"
|
"orientation": "horizontal",
|
||||||
|
"value": 1.0,
|
||||||
|
"fillMode": true,
|
||||||
|
"interactive": false,
|
||||||
|
"textures": {
|
||||||
|
"track": "resources/w/ui/img/HealthBarFill001.png"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextView",
|
"type": "TextView",
|
||||||
|
|||||||
@ -99,32 +99,6 @@
|
|||||||
"horizontal_gravity": "center",
|
"horizontal_gravity": "center",
|
||||||
"vertical_align": "top",
|
"vertical_align": "top",
|
||||||
"texture": "resources/w/ui/img/Location_uni_int.png"
|
"texture": "resources/w/ui/img/Location_uni_int.png"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "StaticImage",
|
|
||||||
"name": "hint_darklands001",
|
|
||||||
"width": 470,
|
|
||||||
"height": 156,
|
|
||||||
"x": 630,
|
|
||||||
"y": 200,
|
|
||||||
"texture": "resources/w/ui/img/Hint_darklands001.png",
|
|
||||||
"pulse": {
|
|
||||||
"minScale": 0.92,
|
|
||||||
"maxScale": 1.08,
|
|
||||||
"periodMs": 1500
|
|
||||||
},
|
|
||||||
"fadeIn": {
|
|
||||||
"durationMs": 600
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "StaticImage",
|
|
||||||
"name": "hint_darklands001_arrow",
|
|
||||||
"width": 24,
|
|
||||||
"height": 118,
|
|
||||||
"x": 860,
|
|
||||||
"y": 110,
|
|
||||||
"texture": "resources/w/ui/img/hint_arrow_up.png"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -115,15 +115,21 @@
|
|||||||
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "Slider",
|
||||||
"name": "healthBarFill",
|
"name": "healthBarFill",
|
||||||
"width": 151.2,
|
"width": 151.2,
|
||||||
"height": 22.8,
|
"height": 22.8,
|
||||||
"y": 49.8,
|
"y": 49.8,
|
||||||
"x": 100.6,
|
"x": 100.6,
|
||||||
"horizontal_gravity": "left",
|
"horizontal_gravity": "left",
|
||||||
"vertical_align": "top",
|
"vertical_gravity": "top",
|
||||||
"texture": "resources/w/ui/img/HealthBarFill001.png"
|
"orientation": "horizontal",
|
||||||
|
"value": 1.0,
|
||||||
|
"fillMode": true,
|
||||||
|
"interactive": false,
|
||||||
|
"textures": {
|
||||||
|
"track": "resources/w/ui/img/HealthBarFill001.png"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextView",
|
"type": "TextView",
|
||||||
|
|||||||
@ -98,15 +98,21 @@
|
|||||||
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
"texture": "resources/w/ui/img/HealthBarBack001.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "StaticImage",
|
"type": "Slider",
|
||||||
"name": "healthBarFill",
|
"name": "healthBarFill",
|
||||||
"width": 151.2,
|
"width": 151.2,
|
||||||
"height": 22.8,
|
"height": 22.8,
|
||||||
"y": 49.8,
|
"y": 49.8,
|
||||||
"x": 100.6,
|
"x": 100.6,
|
||||||
"horizontal_gravity": "left",
|
"horizontal_gravity": "left",
|
||||||
"vertical_align": "top",
|
"vertical_gravity": "top",
|
||||||
"texture": "resources/w/ui/img/HealthBarFill001.png"
|
"orientation": "horizontal",
|
||||||
|
"value": 1.0,
|
||||||
|
"fillMode": true,
|
||||||
|
"interactive": false,
|
||||||
|
"textures": {
|
||||||
|
"track": "resources/w/ui/img/HealthBarFill001.png"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "TextView",
|
"type": "TextView",
|
||||||
|
|||||||
@ -922,6 +922,8 @@ void Character::applyDamage(float damageAmount, const Eigen::Vector3f& attackDir
|
|||||||
hp = hp - damageAmount;
|
hp = hp - damageAmount;
|
||||||
if (hp < 0) hp = 0;
|
if (hp < 0) hp = 0;
|
||||||
|
|
||||||
|
if (onHpChanged) onHpChanged(hp, initialHp);
|
||||||
|
|
||||||
if (!hitSparkEmitter.isConfigured()) return;
|
if (!hitSparkEmitter.isConfigured()) return;
|
||||||
|
|
||||||
Eigen::Vector3f emitPos = position + Eigen::Vector3f(0.f, 1.f, 0.f);
|
Eigen::Vector3f emitPos = position + Eigen::Vector3f(0.f, 1.f, 0.f);
|
||||||
@ -973,7 +975,7 @@ void Character::drawHealthBar(Renderer& renderer,
|
|||||||
const Eigen::Matrix4f& cameraViewMatrix,
|
const Eigen::Matrix4f& cameraViewMatrix,
|
||||||
const Eigen::Matrix4f& projectionMatrix)
|
const Eigen::Matrix4f& projectionMatrix)
|
||||||
{
|
{
|
||||||
if (!isPlayer && !canAttack) return;
|
if (isPlayer || !canAttack) return;
|
||||||
if (!enabled) return;
|
if (!enabled) return;
|
||||||
if (hp <= 0.f) return;
|
if (hp <= 0.f) return;
|
||||||
if (initialHp <= 0.f) return;
|
if (initialHp <= 0.f) return;
|
||||||
|
|||||||
@ -160,6 +160,9 @@ public:
|
|||||||
// Called once when the death animation finishes and the character enters DEATH_IDLE.
|
// Called once when the death animation finishes and the character enters DEATH_IDLE.
|
||||||
std::function<void()> onDeathAnimComplete;
|
std::function<void()> onDeathAnimComplete;
|
||||||
|
|
||||||
|
// Called whenever hp changes (e.g. on damage). Arguments: current hp, max hp.
|
||||||
|
std::function<void(float hp, float maxHp)> onHpChanged;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::map<AnimationState, BoneAnimationDataNew> animations;
|
std::map<AnimationState, BoneAnimationDataNew> animations;
|
||||||
|
|||||||
10
src/Game.cpp
10
src/Game.cpp
@ -131,7 +131,6 @@ namespace ZL
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Game::setupPart2()
|
void Game::setupPart2()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -461,6 +460,15 @@ namespace ZL
|
|||||||
std::cerr << "Failed to load UI: " << e.what() << std::endl;
|
std::cerr << "Failed to load UI: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wire HP-change callbacks so all player instances update the health bar HUD.
|
||||||
|
for (auto& [name, loc] : locations) {
|
||||||
|
if (loc->player) {
|
||||||
|
loc->player->onHpChanged = [this](float hp, float maxHp) {
|
||||||
|
menuManager.updateHealthBar(hp, maxHp);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadingCompleted = true;
|
loadingCompleted = true;
|
||||||
|
|
||||||
if (audioPlayer->init()) {
|
if (audioPlayer->init()) {
|
||||||
|
|||||||
@ -110,6 +110,7 @@ namespace ZL {
|
|||||||
void MenuManager::enterGameplay() {
|
void MenuManager::enterGameplay() {
|
||||||
state = GameState::Gameplay;
|
state = GameState::Gameplay;
|
||||||
uiManager.replaceRoot(hudRoot);
|
uiManager.replaceRoot(hudRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
/*
|
/*
|
||||||
uiManager.setTextButtonCallback("inventory_button", [this](const std::string&) {
|
uiManager.setTextButtonCallback("inventory_button", [this](const std::string&) {
|
||||||
openInventory();
|
openInventory();
|
||||||
@ -366,12 +367,14 @@ namespace ZL {
|
|||||||
|
|
||||||
if (locationName == "uni_exterior") {
|
if (locationName == "uni_exterior") {
|
||||||
uiManager.replaceRoot(currentIsDarklands_ ? hudUniExtDarkRoot : hudUniExtRoot);
|
uiManager.replaceRoot(currentIsDarklands_ ? hudUniExtDarkRoot : hudUniExtRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
setupGameplayHudCallbacks();
|
setupGameplayHudCallbacks();
|
||||||
} else if (locationName == "uni_interior") {
|
} else if (locationName == "uni_interior") {
|
||||||
applyUniIntHud();
|
applyUniIntHud();
|
||||||
} else {
|
} else {
|
||||||
// Returning to dorm: reuse step5ab, suppress already-completed hints
|
// Returning to dorm: reuse step5ab, suppress already-completed hints
|
||||||
uiManager.replaceRoot(hudStep5abRoot);
|
uiManager.replaceRoot(hudStep5abRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
setupStep5Callbacks();
|
setupStep5Callbacks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,6 +405,7 @@ namespace ZL {
|
|||||||
|
|
||||||
if (state == GameState::Gameplay && nextRoot) {
|
if (state == GameState::Gameplay && nextRoot) {
|
||||||
uiManager.replaceRoot(nextRoot);
|
uiManager.replaceRoot(nextRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
|
|
||||||
uiManager.setButtonCallback("inventoryButton", [this](const std::string&) {
|
uiManager.setButtonCallback("inventoryButton", [this](const std::string&) {
|
||||||
openInventory();
|
openInventory();
|
||||||
@ -450,6 +454,7 @@ namespace ZL {
|
|||||||
|
|
||||||
if (nextRoot) {
|
if (nextRoot) {
|
||||||
uiManager.replaceRoot(nextRoot);
|
uiManager.replaceRoot(nextRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
// Register item-screen buttons and re-apply any already-completed hint visibility.
|
// Register item-screen buttons and re-apply any already-completed hint visibility.
|
||||||
setupStep5Callbacks();
|
setupStep5Callbacks();
|
||||||
}
|
}
|
||||||
@ -628,6 +633,7 @@ namespace ZL {
|
|||||||
} else if (currentLocationName_ == "uni_exterior") {
|
} else if (currentLocationName_ == "uni_exterior") {
|
||||||
if (state == GameState::Gameplay) {
|
if (state == GameState::Gameplay) {
|
||||||
uiManager.replaceRoot(enabled ? hudUniExtDarkRoot : hudUniExtRoot);
|
uiManager.replaceRoot(enabled ? hudUniExtDarkRoot : hudUniExtRoot);
|
||||||
|
applyCurrentHealthBar();
|
||||||
setupGameplayHudCallbacks();
|
setupGameplayHudCallbacks();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -654,6 +660,7 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
uiManager.replaceRoot(root);
|
uiManager.replaceRoot(root);
|
||||||
|
applyCurrentHealthBar();
|
||||||
setupGameplayHudCallbacks();
|
setupGameplayHudCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,4 +691,20 @@ namespace ZL {
|
|||||||
applyUniIntHud();
|
applyUniIntHud();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuManager::updateHealthBar(float hp, float maxHp) {
|
||||||
|
currentPlayerHp_ = hp;
|
||||||
|
currentPlayerMaxHp_ = maxHp;
|
||||||
|
applyCurrentHealthBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::applyCurrentHealthBar() {
|
||||||
|
if (currentPlayerMaxHp_ <= 0.f) return;
|
||||||
|
const float fraction = std::clamp(currentPlayerHp_ / currentPlayerMaxHp_, 0.f, 1.f);
|
||||||
|
uiManager.setSliderValue("healthBarFill", fraction);
|
||||||
|
std::string hpText = std::to_string(static_cast<int>(currentPlayerHp_)) + "/" +
|
||||||
|
std::to_string(static_cast<int>(currentPlayerMaxHp_));
|
||||||
|
if (hpText.size() < 7) hpText.insert(0, 7 - hpText.size(), ' ');
|
||||||
|
uiManager.setText("healthValue", hpText);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZL
|
} // namespace ZL
|
||||||
|
|||||||
@ -67,6 +67,9 @@ namespace ZL {
|
|||||||
void advanceUniIntDarklandsHud();
|
void advanceUniIntDarklandsHud();
|
||||||
void onPlayerStartedWalking();
|
void onPlayerStartedWalking();
|
||||||
|
|
||||||
|
// Called by Game when the player's HP changes. Stores values and updates HUD.
|
||||||
|
void updateHealthBar(float hp, float maxHp);
|
||||||
|
|
||||||
TutorialStep tutorialStep = TutorialStep::Step0;
|
TutorialStep tutorialStep = TutorialStep::Step0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -130,6 +133,10 @@ namespace ZL {
|
|||||||
std::shared_ptr<Texture> texItemSelected_;
|
std::shared_ptr<Texture> texItemSelected_;
|
||||||
std::shared_ptr<Texture> texItemTransparent_;
|
std::shared_ptr<Texture> texItemTransparent_;
|
||||||
|
|
||||||
|
float currentPlayerHp_ = 200.f;
|
||||||
|
float currentPlayerMaxHp_ = 200.f;
|
||||||
|
void applyCurrentHealthBar();
|
||||||
|
|
||||||
int selectedQuestIndex = -1;
|
int selectedQuestIndex = -1;
|
||||||
std::vector<std::string> visibleQuestIds;
|
std::vector<std::string> visibleQuestIds;
|
||||||
|
|
||||||
|
|||||||
@ -284,9 +284,22 @@ namespace ZL {
|
|||||||
|
|
||||||
float x0 = rect.x;
|
float x0 = rect.x;
|
||||||
float y0 = rect.y;
|
float y0 = rect.y;
|
||||||
float x1 = rect.x + rect.w;
|
|
||||||
float y1 = rect.y + rect.h;
|
float y1 = rect.y + rect.h;
|
||||||
|
|
||||||
|
float x1, u1;
|
||||||
|
if (fillMode) {
|
||||||
|
const float clamped = std::clamp(value, 0.0f, 1.0f);
|
||||||
|
if (clamped <= 0.0f) {
|
||||||
|
trackMesh.RefreshVBO();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
x1 = rect.x + rect.w * clamped;
|
||||||
|
u1 = clamped;
|
||||||
|
} else {
|
||||||
|
x1 = rect.x + rect.w;
|
||||||
|
u1 = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
trackMesh.data.PositionData.push_back({ x0, y0, 0 });
|
trackMesh.data.PositionData.push_back({ x0, y0, 0 });
|
||||||
trackMesh.data.TexCoordData.push_back({ 0, 0 });
|
trackMesh.data.TexCoordData.push_back({ 0, 0 });
|
||||||
|
|
||||||
@ -294,16 +307,16 @@ namespace ZL {
|
|||||||
trackMesh.data.TexCoordData.push_back({ 0, 1 });
|
trackMesh.data.TexCoordData.push_back({ 0, 1 });
|
||||||
|
|
||||||
trackMesh.data.PositionData.push_back({ x1, y1, 0 });
|
trackMesh.data.PositionData.push_back({ x1, y1, 0 });
|
||||||
trackMesh.data.TexCoordData.push_back({ 1, 1 });
|
trackMesh.data.TexCoordData.push_back({ u1, 1 });
|
||||||
|
|
||||||
trackMesh.data.PositionData.push_back({ x0, y0, 0 });
|
trackMesh.data.PositionData.push_back({ x0, y0, 0 });
|
||||||
trackMesh.data.TexCoordData.push_back({ 0, 0 });
|
trackMesh.data.TexCoordData.push_back({ 0, 0 });
|
||||||
|
|
||||||
trackMesh.data.PositionData.push_back({ x1, y1, 0 });
|
trackMesh.data.PositionData.push_back({ x1, y1, 0 });
|
||||||
trackMesh.data.TexCoordData.push_back({ 1, 1 });
|
trackMesh.data.TexCoordData.push_back({ u1, 1 });
|
||||||
|
|
||||||
trackMesh.data.PositionData.push_back({ x1, y0, 0 });
|
trackMesh.data.PositionData.push_back({ x1, y0, 0 });
|
||||||
trackMesh.data.TexCoordData.push_back({ 1, 0 });
|
trackMesh.data.TexCoordData.push_back({ u1, 0 });
|
||||||
|
|
||||||
trackMesh.RefreshVBO();
|
trackMesh.RefreshVBO();
|
||||||
}
|
}
|
||||||
@ -566,6 +579,8 @@ namespace ZL {
|
|||||||
std::transform(orient.begin(), orient.end(), orient.begin(), ::tolower);
|
std::transform(orient.begin(), orient.end(), orient.begin(), ::tolower);
|
||||||
s->vertical = (orient != "horizontal");
|
s->vertical = (orient != "horizontal");
|
||||||
}
|
}
|
||||||
|
if (j.contains("fillMode")) s->fillMode = j["fillMode"].get<bool>();
|
||||||
|
if (j.contains("interactive")) s->interactive = j["interactive"].get<bool>();
|
||||||
|
|
||||||
node->slider = s;
|
node->slider = s;
|
||||||
}
|
}
|
||||||
@ -1162,6 +1177,7 @@ namespace ZL {
|
|||||||
value = std::clamp(value, 0.0f, 1.0f);
|
value = std::clamp(value, 0.0f, 1.0f);
|
||||||
if (fabs(s->value - value) < 1e-6f) return true;
|
if (fabs(s->value - value) < 1e-6f) return true;
|
||||||
s->value = value;
|
s->value = value;
|
||||||
|
s->buildTrackMesh();
|
||||||
s->buildKnobMesh();
|
s->buildKnobMesh();
|
||||||
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
||||||
return true;
|
return true;
|
||||||
@ -1634,6 +1650,7 @@ namespace ZL {
|
|||||||
auto it = pressedSliders.find(fingerId);
|
auto it = pressedSliders.find(fingerId);
|
||||||
if (it != pressedSliders.end()) {
|
if (it != pressedSliders.end()) {
|
||||||
auto s = it->second;
|
auto s = it->second;
|
||||||
|
if (s->interactive) {
|
||||||
float t;
|
float t;
|
||||||
if (s->vertical) {
|
if (s->vertical) {
|
||||||
t = (y - s->rect.y) / s->rect.h;
|
t = (y - s->rect.y) / s->rect.h;
|
||||||
@ -1644,10 +1661,12 @@ namespace ZL {
|
|||||||
if (t < 0.0f) t = 0.0f;
|
if (t < 0.0f) t = 0.0f;
|
||||||
if (t > 1.0f) t = 1.0f;
|
if (t > 1.0f) t = 1.0f;
|
||||||
s->value = t;
|
s->value = t;
|
||||||
|
s->buildTrackMesh();
|
||||||
s->buildKnobMesh();
|
s->buildKnobMesh();
|
||||||
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void UiManager::onTouchDown(int64_t fingerId, int x, int y) {
|
void UiManager::onTouchDown(int64_t fingerId, int x, int y) {
|
||||||
@ -1676,6 +1695,7 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& s : sliders) {
|
for (auto& s : sliders) {
|
||||||
|
if (!s->interactive) continue;
|
||||||
if (s->rect.contains((float)x, (float)y)) {
|
if (s->rect.contains((float)x, (float)y)) {
|
||||||
pressedSliders[fingerId] = s;
|
pressedSliders[fingerId] = s;
|
||||||
float t;
|
float t;
|
||||||
@ -1688,6 +1708,7 @@ namespace ZL {
|
|||||||
if (t < 0.0f) t = 0.0f;
|
if (t < 0.0f) t = 0.0f;
|
||||||
if (t > 1.0f) t = 1.0f;
|
if (t > 1.0f) t = 1.0f;
|
||||||
s->value = t;
|
s->value = t;
|
||||||
|
s->buildTrackMesh();
|
||||||
s->buildKnobMesh();
|
s->buildKnobMesh();
|
||||||
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
if (s->onValueChanged) s->onValueChanged(s->name, s->value);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -129,6 +129,8 @@ namespace ZL {
|
|||||||
|
|
||||||
float value = 0.0f;
|
float value = 0.0f;
|
||||||
bool vertical = true;
|
bool vertical = true;
|
||||||
|
bool fillMode = false; // track width = value * rect.w (display-only bar)
|
||||||
|
bool interactive = true; // false = ignore touch events
|
||||||
|
|
||||||
std::function<void(const std::string&, float)> onValueChanged;
|
std::function<void(const std::string&, float)> onValueChanged;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user