Skip to content

Commit

Permalink
#5805: Start working on the drag-resize operator for selected texture…
Browse files Browse the repository at this point in the history
… tool elements
  • Loading branch information
codereader committed Jun 16, 2022
1 parent 78cd19f commit b7d6be5
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 10 deletions.
2 changes: 1 addition & 1 deletion include/version.h
Expand Up @@ -4,7 +4,7 @@
#include <config.h>
#define RADIANT_VERSION PACKAGE_VERSION
#else
#define RADIANT_VERSION "3.0.0"
#define RADIANT_VERSION "3.1.0pre1"
#endif

#define RADIANT_APPNAME "DarkRadiant"
Expand Down
116 changes: 108 additions & 8 deletions radiantcore/selection/textool/TextureToolDragManipulator.cpp
Expand Up @@ -5,6 +5,7 @@
#include "pivot.h"
#include "igrid.h"
#include "selection/SelectionPool.h"
#include "selection/algorithm/Texturing.h"

namespace textool
{
Expand Down Expand Up @@ -44,8 +45,72 @@ void TextureTranslator::transform(const Matrix4& pivot2world, const VolumeTest&
_translateFunctor(diff);
}

void TextureDragResizer::beginTransformation(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint)
{
auto device2World = constructDevice2Pivot(pivot2world, view).getPremultipliedBy(pivot2world);

// Remember the starting poing of the operation
auto start = device2World.transformPoint(Vector3(devicePoint.x(), devicePoint.y(), 0));
_start = Vector2(start.x(), start.y());

// Get the selection bounds to figure out the "opposite" point we'll be using as pivot
selection::algorithm::TextureBoundsAccumulator accumulator;
GlobalTextureToolSelectionSystem().foreachSelectedNode(accumulator);

// Move the bounds to pivot space
const auto& bounds = accumulator.getBounds();

_scalePivot = FindFarthestCorner(bounds, _start);

auto boundsMin = bounds.getOrigin() - bounds.getExtents();
auto boundsMax = bounds.getOrigin() + bounds.getExtents();

_scaleMask = Vector2(
_start.x() > boundsMax.x() || _start.x() < boundsMin.x() ? 1 : 0,
_start.y() > boundsMax.y() || _start.y() < boundsMin.y() ? 1 : 0
);
}

Vector2 TextureDragResizer::FindFarthestCorner(const AABB& bounds, const Vector2& start)
{
Vector3 points[8];
bounds.getCorners(points);

Vector2 result;
Vector2::ElementType greatestDistance = -1;

for (auto i = 0; i < 8; ++i)
{
auto candidatePoint = Vector2(points[i].x(), points[i].y());
auto candidateDistance = (candidatePoint - start).getLengthSquared();

if (candidateDistance > greatestDistance)
{
greatestDistance = candidateDistance;
result = candidatePoint;
}
}

return result;
}

void TextureDragResizer::transform(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint, unsigned int constraints)
{
auto device2World = constructDevice2Pivot(pivot2world, view).getPremultipliedBy(pivot2world);

// Calculate the current point in UV space
auto currentWorldPoint = device2World.transformPoint(Vector3(devicePoint.x(), devicePoint.y(), 0));
auto current = Vector2(currentWorldPoint.x(), currentWorldPoint.y());

// TODO: calculate correct scale
auto scale = Vector2(1, 1) + (current - _start) * _scaleMask;

_scaleFunctor(scale, _scalePivot);
}

TextureToolDragManipulator::TextureToolDragManipulator() :
_translator(std::bind(&TextureToolDragManipulator::translateSelected, this, std::placeholders::_1))
_translator(std::bind(&TextureToolDragManipulator::translateSelected, this, std::placeholders::_1)),
_resizer(std::bind(&TextureToolDragManipulator::scaleSelected, this, std::placeholders::_1, std::placeholders::_2))
{}

std::size_t TextureToolDragManipulator::getId() const
Expand All @@ -65,17 +130,18 @@ selection::IManipulator::Type TextureToolDragManipulator::getType() const

selection::IManipulator::Component* TextureToolDragManipulator::getActiveComponent()
{
return &_translator;
return _translateSelectable.isSelected() ? &_translator : static_cast<Component*>(& _resizer);
}

void TextureToolDragManipulator::setSelected(bool select)
{
_selectable.setSelected(select);
_translateSelectable.setSelected(select);
_scaleSelectable.setSelected(select);
}

bool TextureToolDragManipulator::isSelected() const
{
return _selectable.isSelected();
return _translateSelectable.isSelected() || _scaleSelectable.isSelected();
}

void TextureToolDragManipulator::testSelect(SelectionTest& test, const Matrix4& pivot2world)
Expand Down Expand Up @@ -103,17 +169,23 @@ void TextureToolDragManipulator::testSelect(SelectionTest& test, const Matrix4&
return true;
});

_selectable.setSelected(false);
_translateSelectable.setSelected(false);

// The drag manipulator returns positive if we our test hit a selected node
for (const auto& pair : selectionPool)
{
if (pair.second->isSelected())
{
_selectable.setSelected(true);
break;
_translateSelectable.setSelected(true);
return; // done here
}
}

// No selectable has been directly hit, check if the mouse is on any side of the selection AABB
if (GlobalTextureToolSelectionSystem().getSelectionMode() == SelectionMode::Surface)
{
testSelectDragResize(test, pivot2world);
}
}

void TextureToolDragManipulator::renderComponents(const render::IRenderView& view, const Matrix4& pivot2World)
Expand All @@ -125,7 +197,7 @@ void TextureToolDragManipulator::translateSelected(const Vector2& translation)

if (GlobalTextureToolSelectionSystem().getSelectionMode() == SelectionMode::Surface)
{
GlobalTextureToolSelectionSystem().foreachSelectedNode([&](const textool::INode::Ptr& node)
GlobalTextureToolSelectionSystem().foreachSelectedNode([&](const INode::Ptr& node)
{
node->revertTransformation();
node->transform(transform);
Expand All @@ -149,4 +221,32 @@ void TextureToolDragManipulator::translateSelected(const Vector2& translation)
}
}

void TextureToolDragManipulator::scaleSelected(const Vector2& scale, const Vector2& pivot)
{
if (GlobalTextureToolSelectionSystem().getSelectionMode() == SelectionMode::Surface)
{
selection::algorithm::TextureScaler scaler(pivot, scale);
GlobalTextureToolSelectionSystem().foreachSelectedNode(scaler);
}
}

void TextureToolDragManipulator::testSelectDragResize(SelectionTest& test, const Matrix4& pivot2world)
{
// Get the selection bounds to get the sides
selection::algorithm::TextureBoundsAccumulator accumulator;
GlobalTextureToolSelectionSystem().foreachSelectedNode(accumulator);

const auto& bounds = accumulator.getBounds();

// If nothing is selected, the bounds will remain invalid
if (!bounds.isValid()) return;

// Get the point in texture space the test is pointing at
auto hitPoint = pivot2world.transformPoint(test.getNear());

// If the hit point is outside the bounds, the selection test has passed
auto pointIsOutsideBounds = !bounds.contains(AABB::createFromMinMax(hitPoint, hitPoint));
_scaleSelectable.setSelected(pointIsOutsideBounds);
}

}
35 changes: 34 additions & 1 deletion radiantcore/selection/textool/TextureToolDragManipulator.h
Expand Up @@ -25,14 +25,45 @@ class TextureTranslator :
void transform(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint, unsigned int constraints) override;
};

class TextureDragResizer :
public selection::ManipulatorComponentBase
{
private:
// Starting point in UV space
Vector2 _start;

// The pivot point for the scale operation
Vector2 _scalePivot;

// Multiplicative factor to apply before scaling
// Every scaled dimension has 1.0 in the corresponding component
Vector2 _scaleMask;

std::function<void(const Vector2&, const Vector2&)> _scaleFunctor;

public:
TextureDragResizer(const std::function<void(const Vector2&, const Vector2&)>& scaleFunctor) :
_scaleFunctor(scaleFunctor)
{}

void beginTransformation(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint) override;

void transform(const Matrix4& pivot2world, const VolumeTest& view, const Vector2& devicePoint, unsigned int constraints) override;

private:
static Vector2 FindFarthestCorner(const AABB& bounds, const Vector2& start);
};

class TextureToolDragManipulator :
public selection::ITextureToolManipulator
{
private:
std::size_t _id;

selection::BasicSelectable _selectable;
selection::BasicSelectable _translateSelectable;
selection::BasicSelectable _scaleSelectable;
TextureTranslator _translator;
TextureDragResizer _resizer;

public:
TextureToolDragManipulator();
Expand All @@ -50,6 +81,8 @@ class TextureToolDragManipulator :

private:
void translateSelected(const Vector2& translation);
void scaleSelected(const Vector2& scale, const Vector2& pivot);
void testSelectDragResize(SelectionTest& test, const Matrix4& pivot2world);
};

}

0 comments on commit b7d6be5

Please sign in to comment.