Mode :: enum #specified { TRAD_TREE :: 0; HYPER_TREE :: 1; CELLS :: 2; } Gui_Feature :: enum_flags { TOOLTIP; } input :: () { /* ----------- * * Zoom & Drag * * ----------- */ if IsKeyDown(.LEFT_SHIFT) { dragging = false; if !selecting then SetMouseCursor(.DEFAULT); if IsMouseButtonPressed(.LEFT) { selecting = true; selection.x = mouse_world.x; selection.y = mouse_world.y; SetMouseCursor(.RESIZE_NESW); } } if IsMouseButtonPressed(.LEFT) { drag_start = mouse_screen; dragging = true; SetMouseCursor(.RESIZE_ALL); } if IsMouseButtonReleased(.LEFT) { dragging = false; SetMouseCursor(.DEFAULT); if selecting { selecting = false; zoom_to_selection(); } } if IsMouseButtonPressed(.RIGHT) { if selecting then selecting = false; } if dragging { camera.target.x -= (mouse_screen.x - drag_start.x) / camera.zoom; camera.target.y -= (mouse_screen.y - drag_start.y) / camera.zoom; drag_start = mouse_screen; } wheel := GetMouseWheelMove(); if wheel != 0.0 { before := Vector2.{ camera.target.x + (mouse_screen.x - camera.offset.x) / camera.zoom, camera.target.y + (mouse_screen.y - camera.offset.y) / camera.zoom }; camera.zoom *= (1.0 + wheel * 0.1); // TODO: Maybe lerp? //! t := 1.0 - exp(-8.0 * frame_time); //! camera.zoom *= lerp(thing1, thing2, t); camera.zoom = clamp(camera.zoom, 0.1, 5.0); camera.target.x = before.x - (mouse_screen.x - camera.offset.x) / camera.zoom; camera.target.y = before.y - (mouse_screen.y - camera.offset.y) / camera.zoom; } /* ----- * * Modes * * ----- */ if IsKeyPressed(.F1) { if mode == .TRAD_TREE { vtree_fit_zoom(); } else { mode = .TRAD_TREE; state_switch(mode); } } else if IsKeyPressed(.F2) { if mode == .HYPER_TREE { htree_fit_zoom(); } else { mode = .HYPER_TREE; state_switch(mode); } } else if IsKeyPressed(.F3) { if mode == .CELLS { cells_fit_zoom(); } else { mode = .CELLS; state_switch(mode); } } /* ---------------------- * * Context Based Features * * ---------------------- */ if mode == { case .CELLS; if IsKeyPressed(.KEY_T) then flag_toggle(.TOOLTIP); } } input_draw_selection :: () { if !selecting return; using selection; width = mouse_world.x - x; height = mouse_world.y - y; selection_normalized = normalize_selection(selection); DrawRectangleLinesEx(selection_normalized, 2.0, GREEN); } flag_has :: (flag: Gui_Feature) -> bool { return cast(bool, gui_feature & flag); } flag_add :: (flag: Gui_Feature) { gui_feature |= flag; } flag_remove :: (flag: Gui_Feature) { gui_feature &= ~flag; } flag_toggle :: (flag: Gui_Feature) { gui_feature ^= flag; } #scope_file drag_start: Vector2; dragging: bool; selection: Rectangle; selection_normalized: Rectangle; selecting: bool; normalize_selection :: (using selection: Rectangle) -> Rectangle { nx := ifx width < 0 then x + width else x; ny := ifx height < 0 then y + height else y; return { nx, ny, abs(width), abs(height) }; } zoom_to_selection :: () { using selection_normalized; center := Vector2.{ x + width / 2.0, y + height / 2.0 }; zoom_x := cast(float, GetScreenWidth() / width); zoom_y := cast(float, GetScreenHeight() / height); new_zoom := min(zoom_x, zoom_y) * 0.9; camera.offset = { GetScreenWidth() / 2.0, GetScreenHeight() / 2.0 }; camera.target = center; camera.zoom = new_zoom; }