Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rofi-app: Add configuration editor prototype #75

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 3 additions & 1 deletion tools/visualizer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ if(Qt5_FOUND)
set(CMAKE_AUTOUIC ON)

add_executable(rofi-app
rofiapp_mainWindow.cpp rofiapp.cpp rofiapp_resources.qrc Vtk.cpp ${modelResources} )
rofiapp_mainWindow.cpp rofiapp.cpp rofiapp_resources.qrc Vtk.cpp InteractorStyle.cpp ${modelResources} )

target_include_directories(rofi-app
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(rofi-app
Qt5::Widgets configuration atoms atoms-heavy cxxopts ${VTK_LIBRARIES})

Expand Down
7 changes: 7 additions & 0 deletions tools/visualizer/CompatQVTKWidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2) || VTK_MAJOR_VERSION > 8
#include "QVTKOpenGLNativeWidget.h"
#define CompatQVTKWidget QVTKOpenGLNativeWidget
#else
#include "QVTKWidget.h"
#define CompatQVTKWidget QVTKWidget
#endif
64 changes: 64 additions & 0 deletions tools/visualizer/InteractorStyle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "InteractorStyle.hpp"

InteractorStyle::InteractorStyle() {
this->lastPickedActor = nullptr;
this->lastPickedProperty = vtkProperty::New();
this->PartSelectedEvent = vtkCommand::UserEvent + 1;
}

void InteractorStyle::OnLeftButtonDown() {
this->mouseMoved = false;

// Forward events.
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}

void InteractorStyle::OnMouseMove() {
this->mouseMoved = true;

// Forward events.
vtkInteractorStyleTrackballCamera::OnMouseMove();
}

void InteractorStyle::clear() { this->lastPickedActor = nullptr; }

void InteractorStyle::OnLeftButtonUp() {
if (!this->mouseMoved) {
// vtkRenderWindowInteractor::CreateDefaultPicker defaults to vtkPropPicker.
vtkSmartPointer<vtkPropPicker> picker =
vtkPropPicker::SafeDownCast(this->GetInteractor()->GetPicker());

// We only have a single renderer.
vtkSmartPointer<vtkRenderer> renderer = this->GetInteractor()->GetRenderWindow()
->GetRenderers()
->GetFirstRenderer();

int position[2];
this->GetInteractor()->GetEventPosition(position);

picker->Pick(position[0], position[1], 0, renderer);

// If we picked something before, reset its property to original value.
if (this->lastPickedActor != nullptr) {
this->lastPickedActor->GetProperty()->DeepCopy(this->lastPickedProperty);
}

this->lastPickedActor = picker->GetActor();
if (this->lastPickedActor != nullptr) {
// Save the property of the picked actor so that we can restore it next time.
this->lastPickedProperty->DeepCopy(this->lastPickedActor->GetProperty());
// Highlight the picked actor by changing its properties.
this->lastPickedActor->GetProperty()->SetColor(VtkSupp::selectedColor[0], VtkSupp::selectedColor[1], VtkSupp::selectedColor[2]);
this->lastPickedActor->GetProperty()->SetDiffuse(1.0);
this->lastPickedActor->GetProperty()->SetSpecular(0.0);
}

vtkSmartPointer<vtkActor> pickedActor = picker->GetActor();
this->InvokeEvent(this->PartSelectedEvent, pickedActor);
}

// Forward events.
vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
}

vtkStandardNewMacro(InteractorStyle);
40 changes: 40 additions & 0 deletions tools/visualizer/InteractorStyle.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "Vtk.h"
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkPropPicker.h>
#include <vtkRendererCollection.h>

enum EditorTool {
CAMERA,
SELECTION,
};

class InteractorStyle : public vtkInteractorStyleTrackballCamera {
public:
static InteractorStyle *New();

int PartSelectedEvent;

InteractorStyle();

vtkTypeMacro(InteractorStyle, vtkInteractorStyleTrackballCamera);

virtual void OnLeftButtonDown() override;

virtual void OnMouseMove() override;

virtual void OnLeftButtonUp() override;

/**
* Clear actor state.
* Needs to be called when actors are destroyed.
*/
void clear();

private:
bool mouseMoved = false;

vtkSmartPointer<vtkActor> lastPickedActor = nullptr;
vtkSmartPointer<vtkProperty> lastPickedProperty;
};
50 changes: 39 additions & 11 deletions tools/visualizer/Vtk.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
#include "Vtk.h"

std::filesystem::path getModel( const std::string& model ) {
namespace VtkSupp {
vtkInformationIntegerKey* partTypeKey = new vtkInformationIntegerKey(PART_TYPE, ROFI_KEY_LOCATION);
vtkInformationIntegerKey* moduleIdKey = new vtkInformationIntegerKey(MODULE_ID, ROFI_KEY_LOCATION);
vtkInformationIntegerKey* shoeIdKey = new vtkInformationIntegerKey(SHOE_ID, ROFI_KEY_LOCATION);
vtkInformationIntegerKey* connectorIdKey = new vtkInformationIntegerKey(CONNECTOR_ID, ROFI_KEY_LOCATION);
}

std::filesystem::path getModel(ModelPartType model) {
static ResourceFile body = LOAD_RESOURCE_FILE( model_body_obj );
static ResourceFile shoe = LOAD_RESOURCE_FILE( model_shoe_obj );
static ResourceFile connector = LOAD_RESOURCE_FILE( model_connector_obj );

if ( model == "body" )
switch (model) {
case ModelPartType::BODY:
return body.name();
if ( model == "shoe" )
case ModelPartType::SHOE:
return shoe.name();
if ( model == "connector" )
case ModelPartType::CONNECTOR:
return connector.name();
throw std::runtime_error( "Invalid model '" + model + "' requested" );
}
throw std::runtime_error("Invalid model '" + std::to_string(model) + "' requested");
}


void addActor(const std::string &model, const Matrix &matrix, int color, vtkSmartPointer<vtkRenderer> &renderer)
{
vtkSmartPointer<vtkActor> addActor(ModelPartType model, const Matrix &matrix, int id, int color, vtkSmartPointer<vtkRenderer> &renderer) {

// vtkOBJReader is locale sensitive!
std::locale currentLocale;
Expand Down Expand Up @@ -45,7 +52,18 @@ void addActor(const std::string &model, const Matrix &matrix, int color, vtkSmar
frameActor->SetPosition( matrix(0,3), matrix(1,3), matrix(2,3) );
frameActor->SetScale( 1 / 95.0 );

// Store information about what the actor corresponds to in the configuration.
vtkSmartPointer<vtkInformation> info = frameActor->GetPropertyKeys();
if (!info) {
info.TakeReference(vtkInformation::New());
frameActor->SetPropertyKeys(info);
}
info->Set(VtkSupp::partTypeKey, model);
info->Set(VtkSupp::moduleIdKey, id);

renderer->AddActor( frameActor );

return frameActor;
}

void VtkSupp::buildScene(Configuration* current_cfg, vtkSmartPointer<vtkRenderer> &renderer )
Expand All @@ -58,14 +76,24 @@ void VtkSupp::buildScene(Configuration* current_cfg, vtkSmartPointer<vtkRenderer
for (ShoeId s : {A, B})
{
Joint j = s == A ? Alpha : Beta;
addActor("shoe", matrices[s] * shoeMatrix(), color, renderer);
addActor("body", matrices[s] * bodyMatrix(mod.getJoint(j)), color, renderer);

vtkSmartPointer<vtkActor> shoeActor = addActor(ModelPartType::SHOE, matrices[s] * shoeMatrix(), id, color, renderer);
vtkSmartPointer<vtkInformation> shoeInfo = shoeActor->GetPropertyKeys();
shoeInfo->Set(VtkSupp::shoeIdKey, s);

vtkSmartPointer<vtkActor> bodyActor = addActor(ModelPartType::BODY, matrices[s] * bodyMatrix(mod.getJoint(j)), id, color, renderer);
vtkSmartPointer<vtkInformation> bodyInfo = bodyActor->GetPropertyKeys();
bodyInfo->Set(VtkSupp::shoeIdKey, s);

for (ConnectorId dock : {XPlus, XMinus, ZMinus})
{
bool on = edges[s * 3 + dock].has_value();
double onCoeff = on ? edges[s * 3 + dock].value().onCoeff() : 0;
addActor("connector", matrices[s] * dockMatrix(dock, on, onCoeff), color, renderer);

vtkSmartPointer<vtkActor> connectorActor = addActor(ModelPartType::CONNECTOR, matrices[s] * dockMatrix(dock, on, onCoeff), id, color, renderer);
vtkSmartPointer<vtkInformation> connectorInfo = connectorActor->GetPropertyKeys();
connectorInfo->Set(VtkSupp::shoeIdKey, s);
connectorInfo->Set(VtkSupp::connectorIdKey, dock);
}
}
}
Expand Down
29 changes: 28 additions & 1 deletion tools/visualizer/Vtk.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#pragma once

// #include <vtkGenericOpenGLRenderWindow.h> // VTK 8.2 and newer
#include <vtkVersion.h>

#if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2) || VTK_MAJOR_VERSION > 8
#include <vtkGenericOpenGLRenderWindow.h>
#endif

#include <vtkInformation.h>
#include <vtkInformationIntegerKey.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
Expand Down Expand Up @@ -88,6 +94,10 @@ const int colors[10][3] = { {255, 255, 255},
{250, 176, 162},
{234, 110, 111}};

/**
* Color for highlighting selected part of a module.
*/
const int selectedColor[3] = {255, 0, 255};

/**
* @brief buildScene
Expand All @@ -98,5 +108,22 @@ const int colors[10][3] = { {255, 255, 255},
* Colors of individual models circulate among VtkSupp:colors.
*/
void buildScene(Configuration* current_cfg, vtkSmartPointer<vtkRenderer> &renderer );

static const char* ROFI_KEY_LOCATION = "rofi";
static const char* PART_TYPE = "part_type";
static const char* MODULE_ID = "module_id";
static const char* SHOE_ID = "shoe_id";
static const char* CONNECTOR_ID = "connector_id";

// HACK: Needs to be the same object in all uses.
extern vtkInformationIntegerKey* partTypeKey;
extern vtkInformationIntegerKey* moduleIdKey;
extern vtkInformationIntegerKey* shoeIdKey;
extern vtkInformationIntegerKey* connectorIdKey;
}

enum ModelPartType {
BODY,
SHOE,
CONNECTOR,
};
17 changes: 13 additions & 4 deletions tools/visualizer/rofiapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,26 @@ int main(int argc, char *argv[])
{


// VTK 8.2 and newer
// QSurfaceFormat::setDefaultFormat(QVTKOpenGLWidget::defaultFormat()); // VTK 8.2 and newer

// VTK 7.1 and older
#if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2) || VTK_MAJOR_VERSION > 8
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
#else
auto format = QSurfaceFormat::defaultFormat();
format.setStencilBufferSize(8);
QSurfaceFormat::setDefaultFormat(format);
#endif

QApplication a(argc, argv);
Rofiapp_MainWindow w;

if (QApplication::arguments().size() == 2) {
QString fileName = QApplication::arguments().at(1);
QFile file(fileName);
w.loadConfFile(file);
} else if (QApplication::arguments().size() > 2) {
qDebug("Too many arguments.");
qDebug("usage: rofi-app <configuration.in>");
std::exit(EXIT_FAILURE);
}

w.show();

Expand Down
Loading