| 1323 | } |
| 1324 | |
| 1325 | float CUi::DoScrollbarV(const void *pId, const CUIRect *pRect, float Current) |
| 1326 | { |
| 1327 | Current = std::clamp(Current, 0.0f, 1.0f); |
| 1328 | |
| 1329 | // layout |
| 1330 | CUIRect Rail; |
| 1331 | pRect->Margin(5.0f, &Rail); |
| 1332 | |
| 1333 | CUIRect Handle; |
| 1334 | Rail.HSplitTop(std::clamp(33.0f, Rail.w, Rail.h / 3.0f), &Handle, nullptr); |
| 1335 | Handle.y = Rail.y + (Rail.h - Handle.h) * Current; |
| 1336 | |
| 1337 | // logic |
| 1338 | const bool InsideRail = MouseHovered(&Rail); |
| 1339 | const bool InsideHandle = MouseHovered(&Handle); |
| 1340 | bool Grabbed = false; // whether to apply the offset |
| 1341 | |
| 1342 | if(CheckActiveItem(pId)) |
| 1343 | { |
| 1344 | if(MouseButton(0)) |
| 1345 | { |
| 1346 | Grabbed = true; |
| 1347 | if(Input()->ShiftIsPressed()) |
| 1348 | m_MouseSlow = true; |
| 1349 | } |
| 1350 | else |
| 1351 | { |
| 1352 | SetActiveItem(nullptr); |
| 1353 | } |
| 1354 | } |
| 1355 | else if(HotItem() == pId) |
| 1356 | { |
| 1357 | if(InsideHandle) |
| 1358 | { |
| 1359 | if(MouseButton(0)) |
| 1360 | { |
| 1361 | SetActiveItem(pId); |
| 1362 | m_ActiveScrollbarOffset = MouseY() - Handle.y; |
| 1363 | Grabbed = true; |
| 1364 | } |
| 1365 | } |
| 1366 | else if(MouseButtonClicked(0)) |
| 1367 | { |
| 1368 | SetActiveItem(pId); |
| 1369 | m_ActiveScrollbarOffset = Handle.h / 2.0f; |
| 1370 | Grabbed = true; |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1374 | if(InsideRail && !MouseButton(0)) |
| 1375 | { |
| 1376 | SetHotItem(pId); |
| 1377 | } |
| 1378 | |
| 1379 | float ReturnValue = Current; |
| 1380 | if(Grabbed) |
| 1381 | { |
| 1382 | const float Min = Rail.y; |