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

RFC: Changed mouse controls #121

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion src/PolygonBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static void initTPPLPoly(TPPLPoly& poly,
verts[3*inds[0]+1] == verts[3*inds[size-1]+1] &&
verts[3*inds[0]+2] == verts[3*inds[size-1]+2]))
{
g_logger.warning("Ignoring duplicate final vertex in explicitly closed polygon");
g_logger.warning_limited("Ignoring duplicate final vertex in explicitly closed polygon");
size -= 1;
}
// Copy into polypartition data structure
Expand Down
67 changes: 61 additions & 6 deletions src/gui/InteractiveCamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,20 +218,75 @@ class InteractiveCamera : public QObject
m_trackballInteraction = trackballInteraction;
}

/// Zoom the camera using a drag of the mouse
///
/// The previous and current positions of the mouse during the move are
/// given by prevPos and currPos. The camera position is zoomed in
/// toward the center.
void mouseZoom(QPoint prevPos, QPoint currPos)
{
// exponential zooming gives scale-independent sensitivity
qreal dy = qreal(currPos.y() - prevPos.y())/m_viewport.height();
const qreal zoomSpeed = 3.0f;
m_dist *= std::exp(zoomSpeed*dy);
emit viewChanged();
}


/// Move the camera using a drag of the mouse.
///
/// The previous and current positions of the mouse during the move are
/// given by prevPos and currPos. By default this rotates the camera
/// around the center, but if zoom is true, the camera position is
/// zoomed in toward the center instead.
void mouseDrag(QPoint prevPos, QPoint currPos, bool zoom = false)
/// around the center, but if pan is true, the camera position is
/// panned in the x-y plane (or image plane in trackball mode) instead.
void mouseDrag(QPoint prevPos, QPoint currPos, bool pan = false)
{
if(zoom)
if(pan)
{
// exponential zooming gives scale-independent sensitivity
//qreal dy = qreal(currPos.y() - prevPos.y())/m_viewport.height();
//const qreal zoomSpeed = 3.0f;
//m_dist *= std::exp(zoomSpeed*dy);

qreal dx = qreal(currPos.x() - prevPos.x())/m_viewport.height();
qreal dy = qreal(currPos.y() - prevPos.y())/m_viewport.height();
const qreal zoomSpeed = 3.0f;
m_dist *= std::exp(zoomSpeed*dy);

if (m_trackballInteraction)
{
// Trackball mode is straightforard: just rotate a
// translation in the image plane to the global coordinates
QVector3D dr(-dx, dy, 0);
dr = m_rot.inverted() * dr; // Rotate it

m_center.x += m_dist * dr.x();
m_center.y += m_dist * dr.y();
m_center.z += m_dist * dr.z();
}
else
{
// In this mode we move in the x-y plane. Need to project
// translation seperately for x and y to avoid the vertical
// drag being scaled by cos(angle from vertical).

// vertical drag
QVector3D dr_x(0, dy, 0);
dr_x = m_rot.inverted() * dr_x; // Rotate it
qreal len = dr_x.length();
qreal len_xy = sqrt(dr_x.x()*dr_x.x() + dr_x.y()*dr_x.y());
if (len_xy > 0)
{
qreal scale = len / len_xy;
m_center.x += m_dist * dr_x.x() * scale;
m_center.y += m_dist * dr_x.y() * scale;
}

// horizontal drag
QVector3D dr_y(-dx, 0, 0);
dr_y = m_rot.inverted() * dr_y; // Rotate it

m_center.x += m_dist * dr_y.x();
m_center.y += m_dist * dr_y.y();
}
}
else
{
Expand Down
10 changes: 5 additions & 5 deletions src/gui/QtLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ class QtLogger : public QObject, public Logger
public:
QtLogger(QObject* parent = 0) : QObject(parent) {}

virtual void log(LogLevel level, const std::string& msg)
{
emit logMessage(level, QString::fromUtf8(msg.c_str()));
}

signals:
/// Signal emitted every time a log message comes in
void logMessage(int logLevel, QString msg);
Expand All @@ -31,6 +26,11 @@ class QtLogger : public QObject, public Logger
void progressPercent(int percent);

protected:
virtual void logImpl(LogLevel level, const std::string& msg)
{
emit logMessage(level, QString::fromUtf8(msg.c_str()));
}

virtual void progressImpl(double progressFraction)
{
emit progressPercent(int(100*progressFraction));
Expand Down
20 changes: 19 additions & 1 deletion src/gui/guimain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "argparse.h"
#include "config.h"
#include "InterProcessLock.h"
#include "util.h"

class Geometry;

Expand Down Expand Up @@ -43,12 +44,14 @@ int main(int argc, char* argv[])
std::string lockName;
std::string lockId;
std::string socketName;
std::string serverName;

ArgParse::ArgParse ap;
ap.options(
"displaz-gui - don't use this directly, use the displaz commandline helper instead)",
"-instancelock %s %s", &lockName, &lockId, "Single instance lock name and ID to reacquire",
"-socketname %s", &socketName, "Local socket name for IPC",
"-socketname %s", &socketName, "Local socket name for IPC",
"-server %s", &serverName, "DEBUG: Compute lock file and socket name; do not inherit lock",
NULL
);

Expand Down Expand Up @@ -80,9 +83,24 @@ int main(int argc, char* argv[])
QGLFormat::setDefaultFormat(f);

PointViewerMainWindow window(f);

// Inherit instance lock (or debug: acquire it)
if (!serverName.empty())
getDisplazIpcNames(socketName, lockName, serverName);
InterProcessLock instanceLock(lockName);
if (!lockId.empty())
{
instanceLock.inherit(lockId);
}
else if (!serverName.empty())
{
if (!instanceLock.tryLock())
{
std::cerr << "ERROR: Another displaz instance has the lock\n";
return EXIT_FAILURE;
}
}

if (!socketName.empty())
window.startIpcServer(QString::fromStdString(socketName));
window.show();
Expand Down
19 changes: 18 additions & 1 deletion src/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@

#include <cmath>

//------------------------------------------------------------------------------
void Logger::log(LogLevel level, const char* fmt, tfm::FormatListRef flist, int maxMsgs)
{
if (level > m_logLevel)
return;
if (maxMsgs > 0)
{
int& count = m_logCountLimit[LogCountKey(fmt, level)];
if (count >= maxMsgs)
return;
++count;
}
std::ostringstream ss;
tfm::vformat(ss, fmt, flist);
logImpl(level, ss.str());
}


//------------------------------------------------------------------------------
StreamLogger::StreamLogger(std::ostream& outStream)
Expand All @@ -19,7 +36,7 @@ StreamLogger::~StreamLogger()
m_out << "\n";
}

void StreamLogger::log(LogLevel level, const std::string& msg)
void StreamLogger::logImpl(LogLevel level, const std::string& msg)
{
if (m_prevPrintWasProgress)
tfm::format(m_out, "\n");
Expand Down
64 changes: 42 additions & 22 deletions src/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED

#include <map>

#include "tinyformat.h"


//------------------------------------------------------------------------------
/// Logger class for log message formatting using printf-style strings
class Logger
Expand All @@ -20,8 +23,12 @@ class Logger
Progress
};

Logger(LogLevel logLevel = Info, bool logProgress = true)
: m_logLevel(logLevel), m_logProgress(logProgress) { }
Logger(LogLevel logLevel = Info, bool logProgress = true,
int logMessageLimit = 1000)
: m_logLevel(logLevel),
m_logProgress(logProgress),
m_logMessageLimit(logMessageLimit)
{ }

void setLogLevel(LogLevel logLevel) { m_logLevel = logLevel; }
void setLogProgress(bool logProgress) { m_logProgress = logProgress; }
Expand All @@ -32,50 +39,56 @@ class Logger
template<TINYFORMAT_ARGTYPES(n)> \
void progress(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
if (m_logProgress) \
log(Progress, tfm::format(fmt, TINYFORMAT_PASSARGS(n))); \
log(Progress, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)));\
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void debug(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
if (m_logLevel >= Debug) \
log(Debug, tfm::format(fmt, TINYFORMAT_PASSARGS(n))); \
log(Debug, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void info(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
if (m_logLevel >= Info) \
log(Info, tfm::format(fmt, TINYFORMAT_PASSARGS(n))); \
log(Info, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void warning(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
if (m_logLevel >= Warning) \
log(Warning, tfm::format(fmt, TINYFORMAT_PASSARGS(n))); \
log(Warning, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)));\
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void error(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
if (m_logLevel >= Error) \
log(Error, tfm::format(fmt, TINYFORMAT_PASSARGS(n))); \
log(Error, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
/* Versions of above which limit total number of messages to m_logMessageLimit */ \
template<TINYFORMAT_ARGTYPES(n)> \
void warning_limited(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Warning, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)), m_logMessageLimit); \
}

TINYFORMAT_FOREACH_ARGNUM(DISPLAZ_MAKE_LOG_FUNCS)
# undef DISPLAZ_MAKE_LOG_FUNCS

// 0-arg versions
void progress (const char* fmt) { log(Progress, tfm::format(fmt)); }
void debug (const char* fmt) { log(Debug, tfm::format(fmt)); }
void info (const char* fmt) { log(Info, tfm::format(fmt)); }
void warning (const char* fmt) { log(Warning, tfm::format(fmt)); }
void error (const char* fmt) { log(Error, tfm::format(fmt)); }

/// Log message at the given log level
virtual void log(LogLevel level, const std::string& msg) = 0;
void progress (const char* fmt) { log(Progress, fmt, tfm::makeFormatList()); }
void debug (const char* fmt) { log(Debug, fmt, tfm::makeFormatList()); }
void info (const char* fmt) { log(Info, fmt, tfm::makeFormatList()); }
void warning (const char* fmt) { log(Warning, fmt, tfm::makeFormatList()); }
void error (const char* fmt) { log(Error, fmt, tfm::makeFormatList()); }
void warning_limited (const char* fmt) { log(Warning, fmt, tfm::makeFormatList(), m_logMessageLimit); }

/// Log result of `tfm::vformat(fmt,flist)` at the given log level.
///
/// If `maxMsgs` is positive, messages with the same `(level,fmt)` key
/// will be logged at most `maxMsgs` times.
virtual void log(LogLevel level, const char* fmt, tfm::FormatListRef flist, int maxMsgs = 0);

/// Report progress of some processing step
void progress(double progressFraction)
Expand All @@ -85,11 +98,18 @@ class Logger
}

protected:
virtual void logImpl(LogLevel level, const std::string& msg) = 0;

virtual void progressImpl(double progressFraction) = 0;

private:
typedef std::pair<const char*,LogLevel> LogCountKey;

LogLevel m_logLevel;
bool m_logProgress;
int m_logMessageLimit;

std::map<LogCountKey,int> m_logCountLimit;
};


Expand All @@ -100,9 +120,9 @@ class StreamLogger : public Logger
StreamLogger(std::ostream& outStream);
~StreamLogger();

virtual void log(LogLevel level, const std::string& msg);

protected:
virtual void logImpl(LogLevel level, const std::string& msg);

virtual void progressImpl(double progressFraction);

private:
Expand Down
23 changes: 4 additions & 19 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@

//------------------------------------------------------------------------------

/// Get resource name for displaz IPC
///
/// This is a combination of the program name and user name to avoid any name
/// clashes, along with a user-defined suffix.
static std::string displazIpcName(const std::string& suffix = "")
{
std::string name = "displaz-ipc-" + currentUserUid();
if (!suffix.empty())
name += "-" + suffix;
return name;
}


/// Callback and globals for positional argument parsing
struct PositionalArg
{
Expand Down Expand Up @@ -167,10 +154,8 @@ int main(int argc, char *argv[])
serverName = QUuid::createUuid().toByteArray().constData();
}

std::string ipcResourceName = displazIpcName(serverName);
QString socketName = QString::fromStdString(ipcResourceName);

std::string lockName = ipcResourceName + ".lock";
std::string socketName, lockName;
getDisplazIpcNames(socketName, lockName, serverName);
InterProcessLock instanceLock(lockName);
bool startedGui = false;
qint64 guiPid = -1;
Expand All @@ -191,7 +176,7 @@ int main(int argc, char *argv[])
QStringList args;
args << "-instancelock" << QString::fromStdString(lockName)
<< QString::fromStdString(instanceLock.makeLockId())
<< "-socketname" << socketName;
<< "-socketname" << QString::fromStdString(socketName);
QString guiExe = QDir(QCoreApplication::applicationDirPath())
.absoluteFilePath("displaz-gui");
if (!QProcess::startDetached(guiExe, args,
Expand All @@ -206,7 +191,7 @@ int main(int argc, char *argv[])
// Remote displaz instance should now be running (either it existed
// already, or we started it above). Communicate with it via the socket
// interface to set any requested parameters, load additional files etc.
std::unique_ptr<IpcChannel> channel = IpcChannel::connectToServer(socketName);
std::unique_ptr<IpcChannel> channel = IpcChannel::connectToServer(QString::fromStdString(socketName));
if (!channel)
{
std::cerr << "ERROR: Could not open IPC channel to remote instance - exiting\n";
Expand Down
2 changes: 1 addition & 1 deletion src/render/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void Geometry::destroyBuffers()
for (auto& it: m_VAO)
{
GLuint vao = it.second;
glDeleteBuffers(1, &vao);
glDeleteVertexArrays(1, &vao);
}

m_VAO.clear();
Expand Down
Loading