Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Fix movable keyboard for multiwindow
Browse files Browse the repository at this point in the history
  • Loading branch information
MortimerGoro committed Aug 2, 2019
1 parent e322d5b commit 6e0abae
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 46 deletions.
43 changes: 43 additions & 0 deletions app/src/main/cpp/Cylinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,49 @@ float Cylinder::DistanceToBackPlane(const vrb::Vector &aStartPoint, const vrb::V
return result;
}

// Returns the circle angle of a local point in a cylinder
float
Cylinder::GetCylinderAngle(const vrb::Vector& aLocalPoint) const {
return atan2f(-aLocalPoint.z(), aLocalPoint.x());
}

vrb::Vector
Cylinder::ProjectPointToQuad(const vrb::Vector& aWorldPoint, const float aAnchorX, const float aCylinderDensity, const vrb::Vector& aMin, const vrb::Vector& aMax) const {
// For cylinders we want to map the position in the cylinder to the position it would have on a quad.
// This way we can reuse the same resize logic between quads and cylinders.
// First Convert to world point to local point in the cylinder.
vrb::Matrix modelView = GetTransformNode()->GetWorldTransform().AfineInverse();
vrb::Vector localPoint = modelView.MultiplyPosition(aWorldPoint);
const float pointAngle = GetCylinderAngle(localPoint);

// Ratio used to convert arc length to quad width.
const float thetaRatio = aCylinderDensity * 0.5f / ((float) M_PI * kWorldDensityRatio);

float x;

// Handle different anchor points.
if (aAnchorX == 1.0f) {
// Difference between pointer angle and the right anchor point.
const float initialTheta = (aMax.x() - aMin.x()) / thetaRatio;
const float initialAngle = (float)M_PI * 0.5f - initialTheta * 0.5f;
const float arc = fabsf(pointAngle - initialAngle);
x = aMax.x() - arc * thetaRatio;
} else if (aAnchorX == 0.0f) {
// Difference between pointer angle and the left anchor point.
const float initialTheta = (aMax.x() - aMin.x()) / thetaRatio;
const float initialAngle = (float)M_PI * 0.5f + initialTheta * 0.5f;
const float arc = fabsf(initialAngle - pointAngle);
x = aMin.x() + arc * thetaRatio;
} else { // Anchor 0.5f
// The center of the cylinder is 90º.
x = ((float) M_PI * 0.5f - pointAngle) * thetaRatio;
}

// The mapped position on a quad.
const float y = (aMax.y() - aMin.y()) * localPoint.y() * 0.5f;
return vrb::Vector(x, y, 0.0f);
}

Cylinder::Cylinder(State& aState, vrb::CreationContextPtr& aContext) : m(aState) {
m.context = aContext;
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/cpp/Cylinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class Cylinder {
void ConvertToQuadCoordinates(const vrb::Vector& point, float& aX, float& aY, bool aClamp) const;
void ConvertFromQuadCoordinates(const float aX, const float aY, vrb::Vector& aWorldPoint, vrb::Vector& aNormal);
float DistanceToBackPlane(const vrb::Vector& aStartPoint, const vrb::Vector& aDirection) const;
float GetCylinderAngle(const vrb::Vector& aLocalPoint) const;
vrb::Vector ProjectPointToQuad(const vrb::Vector& aWorldPoint, const float aAnchorX, const float aDensity, const vrb::Vector& aMin, const vrb::Vector& aMax) const;
protected:
struct State;
Cylinder(State& aState, vrb::CreationContextPtr& aContext);
Expand Down
31 changes: 25 additions & 6 deletions app/src/main/cpp/WidgetMover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#include "Widget.h"
#include "WidgetPlacement.h"
#include "VRBrowser.h"
#include "Cylinder.h"
#include "vrb/ConcreteClass.h"
#include "vrb/Matrix.h"
#include "vrb/Transform.h"

namespace crow {

Expand Down Expand Up @@ -37,18 +39,29 @@ struct WidgetMover::State {
, endRotation(0)
{}

vrb::Vector ProjectPoint(const vrb::Vector& aWorldPoint) const {
if (widget->GetCylinder()) {
vrb::Vector min, max;
widget->GetWidgetMinAndMax(min, max);
vrb::Vector point = widget->GetCylinder()->ProjectPointToQuad(aWorldPoint, 0.5f, widget->GetCylinderDensity(), min, max);
return widget->GetTransformNode()->GetWorldTransform().MultiplyPosition(point);
} else {
return aWorldPoint;
}
}

WidgetPlacementPtr& HandleKeyboardMove(const vrb::Vector& aDelta) {
float x = initialPlacement->translation.x() * WidgetPlacement::kWorldDPIRatio;
float y = initialPlacement->translation.y() * WidgetPlacement::kWorldDPIRatio;
const float windowZ = -4.2f; // Must match window_world_z in dimen.xml
const float maxX = 4.0f; // Relative to 0.5f anchor point.
const float minX = -maxX;
const float maxY = 2.0f; // Relative to 0.0f anchor point.
const float minY = -1.1f; // Relative to 0.0f anchor point.
const float maxY = 1.8f; // Relative to 0.0f anchor point.
const float minY = -1.3f; // Relative to 0.0f anchor point.
const float maxAngle = -35.0f * (float)M_PI / 180.0f;
const float angleStartY = 0.8f;
const float minZ = -2.5f;
const float maxZ = -3.2f;
const float minZ = -2.5f - windowZ;
const float maxZ = -3.2f - windowZ;
const float thresholdZ = 1.45f;
x += aDelta.x();
y += aDelta.y();
Expand Down Expand Up @@ -108,8 +121,14 @@ WidgetMover::HandleMove(const vrb::Vector& aStart, const vrb::Vector& aDirection
if (hitDistance < 0) {
return nullptr;
};
hitPoint = m.ProjectPoint(hitPoint);

const vrb::Vector delta = hitPoint - m.initialPoint;
vrb::Vector delta = hitPoint - m.initialPoint;
delta.y() = hitPoint.y() - m.initialPoint.y();
delta.x() = vrb::Vector(hitPoint.x() - m.initialPoint.x(), 0.0f, hitPoint.z() - m.initialPoint.z()).Magnitude();
if (hitPoint.x() < m.initialPoint.x()) {
delta.x() *= -1.0f;
}

if (m.moveBehaviour == WidgetMoveBehaviour::KEYBOARD) {
return m.HandleKeyboardMove(delta);
Expand All @@ -131,7 +150,7 @@ WidgetMover::StartMoving(const WidgetPtr& aWidget, const int32_t aMoveBehaviour,
m.widget = aWidget;
m.attachedController = aControllerIndex;
m.initialTransform = aWidget->GetTransform();
m.initialPoint = aHitPoint;
m.initialPoint = m.ProjectPoint(aHitPoint);
m.anchorPoint = aAnchorPoint;
m.initialPlacement = aWidget->GetPlacement();
m.movePlacement = WidgetPlacement::Create(*m.initialPlacement);
Expand Down
41 changes: 1 addition & 40 deletions app/src/main/cpp/WidgetResizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,48 +450,9 @@ struct WidgetResizer::State {
return max.y() - min.y();
}

// Returns the circle angle of a local point in a cylinder
float GetCylinderAngle(const vrb::Vector& aLocalPoint) const {
return atan2f(-aLocalPoint.z(), aLocalPoint.x());
}

vrb::Vector ProjectPoint(const vrb::Vector& aWorldPoint) const {
if (widget->GetCylinder()) {
// For cylinders we want to map the position in the cylinder to the position it would have on a quad.
// This way we can reuse the same resize logic between quads and cylinders.
// First Convert to world point to local point in the cylinder.
vrb::Matrix modelView = widget->GetCylinder()->GetTransformNode()->GetWorldTransform().AfineInverse();
vrb::Vector localPoint = modelView.MultiplyPosition(aWorldPoint);
const float pointAngle = GetCylinderAngle(localPoint);

// Ratio used to convert arc length to quad width.
const float thetaRatio = widget->GetCylinderDensity() * 0.5f / ((float) M_PI * Cylinder::kWorldDensityRatio);

float x;

// Handle different anchor points.
const float anchorX = GetAnchorX();
if (anchorX == 1.0f) {
// Difference between pointer angle and the right anchor point.
const float initialTheta = (max.x() - min.x()) / thetaRatio;
const float initialAngle = (float)M_PI * 0.5f - initialTheta * 0.5f;
const float arc = fabsf(pointAngle - initialAngle);
x = max.x() - arc * thetaRatio;
} else if (anchorX == 0.0f) {
// Difference between pointer angle and the left anchor point.
const float initialTheta = (max.x() - min.x()) / thetaRatio;
const float initialAngle = (float)M_PI * 0.5f + initialTheta * 0.5f;
const float arc = fabsf(initialAngle - pointAngle);
x = min.x() + arc * thetaRatio;
} else { // Anchor 0.5f
// The center of the cylinder is 90º.
x = ((float) M_PI * 0.5f - pointAngle) * thetaRatio;
}


// The mapped position on a quad.
const float y = WorldHeight() * localPoint.y() * 0.5f;
return vrb::Vector(x, y, 0.0f);
return widget->GetCylinder()->ProjectPointToQuad(aWorldPoint, GetAnchorX(), widget->GetCylinderDensity(), min, max);
} else {
// For quads just convert to world point to local point.
vrb::Matrix modelView = widget->GetTransformNode()->GetWorldTransform().AfineInverse();
Expand Down

0 comments on commit 6e0abae

Please sign in to comment.