|
|
- #include "pie-menu.hpp"
- #include <cmath>
-
- PieMenu::PieMenu(Tweener* tweener):
- tweener(tweener),
- scaleUpTween(nullptr),
- scaleDownTween(nullptr),
- scale(1.0f),
- selectionIndex(0),
- dragging(false),
- dragStart(0.0f)
- {
- // Setup fullscreen container
- fullscreenContainer.addChild(&croppedContainer);
- fullscreenContainer.setMouseMovedCallback(std::bind(&PieMenu::mouseMoved, this, std::placeholders::_1, std::placeholders::_2));
- fullscreenContainer.setMousePressedCallback(std::bind(&PieMenu::mouseButtonPressed, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
- fullscreenContainer.setMouseReleasedCallback(std::bind(&PieMenu::mouseButtonReleased, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
-
- // Setup cropped container
- croppedContainer.addChild(&scalingContainer);
-
- // Setup scaling container
- scalingContainer.setAnchor(Vector2(0.5f));
-
- // Create tweens
- scaleUpTween = new Tween<float>(EaseFunction::OUT_SINE, 0.0f, 0.1f, 0.0f, 1.0f);
- scaleUpTween->setUpdateCallback(std::bind(&PieMenu::setScale, this, std::placeholders::_1));
- scaleDownTween = new Tween<float>(EaseFunction::IN_SINE, 0.0f, 0.1f, 1.0f, -1.0f);
- scaleDownTween->setUpdateCallback(std::bind(&PieMenu::setScale, this, std::placeholders::_1));
-
- // Add tweens
- tweener->addTween(scaleUpTween);
- tweener->addTween(scaleDownTween);
- }
-
- void PieMenu::resize()
- {
- float iconDistance = 0.0f;
-
- if (fullscreenContainer.getParent() == nullptr)
- {
- return;
- }
-
- // Resize fullscreen container
- fullscreenContainer.setDimensions(fullscreenContainer.getParent()->getDimensions());
-
- // Resize cropped container
- croppedContainer.setDimensions(Vector2(options[0]->getTexture()->getWidth(), options[0]->getTexture()->getHeight()));
-
- // Place options
- for (std::size_t i = 0; i < options.size(); ++i)
- {
- float angle = glm::radians(360.0f) / static_cast<float>(i + 1) / static_cast<float>(options.size());
-
- options[i]->setAnchor(Vector2(0.5f, 0.5f));
- options[i]->setTranslation(Vector2(0.0f, 0.0f));
-
- icons[i]->setAnchor(Vector2(0.5f, 0.5f));
- icons[i]->setTranslation(Vector2(0.0f, 0.0f));
- }
- }
-
- void PieMenu::setScale(float scale)
- {
- for (std::size_t i = 0; i < options.size(); ++i)
- {
- options[i]->setDimensions(Vector2(options[i]->getTexture()->getWidth(), options[i]->getTexture()->getHeight()) * scale);
- icons[i]->setDimensions(Vector2(icons[i]->getTexture()->getWidth(), icons[i]->getTexture()->getHeight()) * scale);
- }
- }
-
- void PieMenu::addOption(Texture* backgroundTexture, Texture* iconTexture, std::function<void()> selectedCallback, std::function<void()> deselectedCallback)
- {
- // Allocate new option
- UIImage* option = new UIImage();
- option->setTexture(backgroundTexture);
- option->setDimensions(Vector2(backgroundTexture->getWidth(), backgroundTexture->getHeight()));
- option->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.50f));
- options.push_back(option);
-
- UIImage* icon = new UIImage();
- icon->setTexture(iconTexture);
- icon->setDimensions(Vector2(iconTexture->getWidth(), iconTexture->getHeight()));
- icon->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.50f));
- icons.push_back(icon);
-
- // Add icon to option
- scalingContainer.addChild(icon);
-
- // Add option to menu
- scalingContainer.addChild(option);
-
- // Setup callbacks
- selectedCallbacks.push_back(selectedCallback);
- deselectedCallbacks.push_back(deselectedCallback);
- }
-
- void PieMenu::select(std::size_t index)
- {
- if (index != selectionIndex && selectionIndex < options.size())
- {
- deselect(selectionIndex);
- }
-
- selectionIndex = index;
- selectedCallbacks[index]();
- }
-
- void PieMenu::deselect(std::size_t index)
- {
- deselectedCallbacks[index]();
- }
-
- void PieMenu::highlight(std::size_t index)
- {
- options[index]->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
- icons[index]->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 1.0f));
- }
-
- void PieMenu::unhighlight(std::size_t index)
- {
- options[index]->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.50f));
- icons[index]->setTintColor(Vector4(1.0f, 1.0f, 1.0f, 0.50f));
- }
-
- void PieMenu::mouseMoved(int x, int y)
- {
- if (dragging)
- {
- Vector2 direction = Vector2(x, y) - dragStart;
- if (direction.x != 0.0f || direction.y != 0.0f)
- {
- direction = glm::normalize(direction);
-
- // Calculate arc length
- float arcLength = glm::radians(360.0f) / static_cast<float>(options.size());
-
- // Calculate angle between cursor and pie menu
- float angle = std::atan2(direction.y, direction.x) + glm::radians(90.0f) + arcLength * 0.5f;
- while (angle < 0.0f) angle += glm::radians(360.0f);
-
- // Determine option index from angle
- std::size_t index = static_cast<std::size_t>(angle / arcLength);
-
- if (index != highlightedIndex)
- {
- if (highlightedIndex < options.size())
- {
- unhighlight(highlightedIndex);
- }
-
- highlight(index);
- highlightedIndex = index;
- }
- }
- }
- }
-
- void PieMenu::mouseButtonPressed(int button, int x, int y)
- {
- if (button == 3)
- {
- // Start dragging
- dragging = true;
- dragStart.x = x;
- dragStart.y = y;
-
- // Set pie menu position
- Vector2 halfDimensions = croppedContainer.getDimensions() * 0.5f;
- croppedContainer.setTranslation(Vector2(x - halfDimensions.x, y - halfDimensions.y));
-
- // Clear highlights
- for (std::size_t i = 0; i < options.size(); ++i)
- {
- unhighlight(i);
- }
-
- // Reset highlighted index
- highlightedIndex = options.size();
-
- // Show pie menu
- fullscreenContainer.setVisible(true);
-
- // Start scale-up tween
- scaleDownTween->stop();
- scaleUpTween->start();
- }
- }
-
- void PieMenu::mouseButtonReleased(int button, int x, int y)
- {
- if (button == 3)
- {
- // Stop dragging
- dragging = false;
-
- // Select highlighted index
- if (highlightedIndex != selectionIndex && highlightedIndex < options.size())
- {
- select(highlightedIndex);
- }
-
- // Clear highlights
- for (std::size_t i = 0; i < options.size(); ++i)
- {
- unhighlight(i);
- }
-
- // Reset highlighted index
- highlightedIndex = options.size();
-
- // Start scale-down tween
- scaleUpTween->stop();
- scaleDownTween->start();
- //fullscreenContainer.setVisible(false);
- }
- }
|