资源分享
Открыть в Telegram
This Channel follows Telegram Terms.No adult content, no violence, no spam.
БольшеСтрана не указанаКатегория не указана
1 056
Подписчики
+124 часа
+17 дней
-730 дней
Архив постов
1 056
// 滑块:纯白色,宽度为高度的 2.0 倍(thumbWMult = 2.0) float 滑块高度 = 高度 * 0.82f * sval; // thumbScaleBase = 0.82 float 滑块宽度 = 滑块高度 * 2.0f; // 宽度倍数改为 2.0 float 滑块圆角 = 滑块高度 * 0.5f; float minX = 最小坐标.x + 5.0f + 滑块宽度 * 0.5f; // padding = 5.0 float maxX = 最大坐标.x - 5.0f - 滑块宽度 * 0.5f; float 滑块中心 X = minX + (maxX - minX) * 动画数据.beg; ImVec2 滑块 Min = ImVec2(滑块中心 X - 滑块宽度 * 0.5f, 最小坐标.y + (高度 - 滑块高度) * 0.5f); ImVec2 滑块 Max = ImVec2(滑块中心 X + 滑块宽度 * 0.5f, 最大坐标.y - (高度 - 滑块高度) * 0.5f); // 先绘制微阴影(半透明黑,稍大一圈) dl->AddRectFilled(ImVec2(滑块 Min.x - 1.0f, 滑块 Min.y - 1.0f), ImVec2(滑块 Max.x + 1.0f, 滑块 Max.y + 1.0f), IM_COL32(0,0,0,15), 滑块圆角 + 1.0f, 0); // 再绘制纯白滑块(覆盖阴影中心,露出边缘阴影) ImU32 白色 = IM_COL32(255, 255, 255, 255); dl->AddRectFilled(滑块 Min, 滑块 Max, 白色, 滑块圆角, 0); // 文字(带阴影) ImGui::SetCursorPos(原始光标位置); ImVec2 文本位置 = ImGui::GetCursorScreenPos(); dl->AddText(NULL, 字体大小, ImVec2(文本位置.x + 1.0f, 文本位置.y + 1.0f), IM_COL32(0,0,0,60), 名称.c_str()); dl->AddText(NULL, 字体大小, 文本位置, ImColor(0,0,0,255), 名称.c_str()); // 更新光标位置到下一行 float textHeight = ImGui::GetFont()->CalcTextSizeA(字体大小, FLT_MAX, -1, 名称.c_str()).y; ImGui::SetCursorPosY(原始光标位置.y + ImMax(textHeight, 按钮尺寸.y) + ImGui::GetStyle().ItemSpacing.y); }搬运带名 @SunSha5201314
1 056
// 动画数据结构 struct ToggleAnimData { float beg = 0.0f; // 位置弹簧值 ImVec4 color = ImVec4(1,1,1,1); // 背景颜色 }; void Toggle(const std::string& 名称, bool& 开关状态, float 宽度 = 300, float 字体大小 = 20, ImVec2 按钮尺寸 = ImVec2(0, 0), float 动画速度 = 0.05f, ImColor 未激活颜色 = ImColor(240, 240, 245), // 淡灰白背景 ImColor 已激活颜色 = ImColor(80, 200, 120)) // 柔和绿背景 { // 尺寸:100×46(默认) if (按钮尺寸.x <= 0.0f || 按钮尺寸.y <= 0.0f) 按钮尺寸 = ImVec2(138.0f, 52.0f);// 长度 / 宽度 // 静态映射存储每个开关的动画数据 static std::map<std::string, float> springVelocity; static std::map<std::string, float> scaleVel; static std::map<std::string, float> scaleVal; static std::map<std::string, bool> lastActive; static std::map<std::string, ToggleAnimData> animDataMap; // 首次调用时初始化 if (animDataMap.find(名称) == animDataMap.end()) { springVelocity[名称] = 0.0f; scaleVel[名称] = 0.0f; scaleVal[名称] = 1.0f; lastActive[名称] = false; ToggleAnimData data; data.beg = 开关状态 ? 1.0f : 0.0f; data.color = (开关状态 ? 已激活颜色 : 未激活颜色).Value; animDataMap[名称] = data; } ToggleAnimData& 动画数据 = animDataMap[名称]; ImVec2 原始光标位置 = ImGui::GetCursorPos(); float 窗口宽度 = ImGui::GetWindowWidth(); float 边界 = 窗口宽度 * 0.10f; float 按钮右侧位置 = 窗口宽度 - 边界 - 按钮尺寸.x; ImGui::SetCursorPosX(按钮右侧位置); // 隐形按钮用于交互 if (ImGui::InvisibleButton(名称.c_str(), 按钮尺寸)) { 开关状态 = ! 开关状态; } // 果冻缩放动画触发(按下瞬间缩小) bool active = ImGui::IsItemActive(); if (active && !lastActive[名称]) { scaleVal[名称] = 0.82f; // 按下瞬间缩小 scaleVel[名称] = 0.0f; } lastActive[名称] = active; // 缩放弹簧 float& sv = scaleVel[名称]; float& sval = scaleVal[名称]; float scaleStiffness = 0.35f; float scaleDamping = 0.75f; float scaleDisplacement = 1.0f - sval; float scaleAccel = scaleDisplacement * scaleStiffness - sv * scaleDamping; sv += scaleAccel; sval += sv; if (fabs(scaleDisplacement) < 0.001f && fabs(sv) < 0.001f) { sval = 1.0f; sv = 0.0f; } ImVec2 最小坐标 = ImGui::GetItemRectMin(); ImVec2 最大坐标 = ImGui::GetItemRectMax(); float 高度 = 最大坐标.y - 最小坐标.y; float 半径 = 高度 * 0.5f; // 位置弹簧(开关切换) float target = 开关状态 ? 1.0f : 0.0f; float& vel = springVelocity[名称]; float stiffness = 0.30f; float damping = 0.72f; float displacement = target - 动画数据.beg; float acceleration = displacement * stiffness - vel * damping; vel += acceleration; 动画数据.beg += vel; if (fabs(displacement) < 0.01f && fabs(vel) < 0.01f) { 动画数据.beg = target; vel = 0.0f; } // 颜色过渡 ImVec4 目标背景色 = 开关状态 ? 已激活颜色.Value : 未激活颜色.Value; float colorSpeed = 0.18f; 动画数据.color.x += (目标背景色.x - 动画数据.color.x) * colorSpeed; 动画数据.color.y += (目标背景色.y - 动画数据.color.y) * colorSpeed; 动画数据.color.z += (目标背景色.z - 动画数据.color.z) * colorSpeed; 动画数据.color.w += (目标背景色.w - 动画数据.color.w) * colorSpeed; ImDrawList* dl = ImGui::GetWindowDrawList(); // 外阴影(柔和多层阴影,可选) const int shadowLayerCount = 4; const float shadowBaseAlpha = 0.08f; const float shadowFadeFactor = 0.5f; const float shadowSpread = 1.0f; ImVec2 shadowOffsets[] = { ImVec2(0,1), ImVec2(0,2), ImVec2(1,0), ImVec2(-1,0) }; for (int dir = 0; dir < 4; dir++) { for (int layer = shadowLayerCount; layer >= 1; layer--) { float layerSpread = shadowSpread * layer; float alpha = shadowBaseAlpha * powf(shadowFadeFactor, layer - 1); ImVec2 sMin = ImVec2(最小坐标.x + shadowOffsets[dir].x * layerSpread, 最小坐标.y + shadowOffsets[dir].y * layerSpread); ImVec2 sMax = ImVec2(最大坐标.x + shadowOffsets[dir].x * layerSpread, 最大坐标.y + shadowOffsets[dir].y * layerSpread); dl->AddRectFilled(sMin, sMax, ImColor(0, 0, 0, static_cast<int>(alpha * 255)), 半径); } } // 背景胶囊(淡色) dl->AddRectFilled(最小坐标, 最大坐标, ImGui::ColorConvertFloat4ToU32(动画数据.color), 半径, 0);
