mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-26 02:35:38 +08:00
#31 Squashed merge of commits relating to the plugin system and IContext redesign, from the 'interconnect' branch.
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
#include <blackmisc/context.h>
|
||||
#include <blackmisc/debug.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "blackcore/fsd_client.h"
|
||||
#include "blackcore/fsd_messages.h"
|
||||
#include <blackmisc/context.h>
|
||||
#include <blackmisc/debug.h>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
namespace FSD
|
||||
{
|
||||
@@ -13,8 +11,8 @@ namespace FSD
|
||||
using namespace BlackMisc;
|
||||
|
||||
|
||||
CFSDClient::CFSDClient()
|
||||
: m_tcp_socket(NULL), m_port(0), m_simType(FSD::SIM_UNKNOWN)
|
||||
CFSDClient::CFSDClient(IContext &context)
|
||||
: m_context(context), m_tcp_socket(NULL), m_port(0), m_simType(FSD::SIM_UNKNOWN)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -27,14 +25,14 @@ namespace FSD
|
||||
if ( isConnected() )
|
||||
return;
|
||||
|
||||
bDebug << "Connecting to FSD server: " << m_host << ":" << m_port;
|
||||
bDebug(m_context) << "Connecting to FSD server: " << m_host << ":" << m_port;
|
||||
|
||||
m_tcp_socket->connectToHost(m_host, m_port);
|
||||
}
|
||||
|
||||
void CFSDClient::disconnectFrom()
|
||||
{
|
||||
bDebug << "Disconnecting from host.";
|
||||
bDebug(m_context) << "Disconnecting from host.";
|
||||
|
||||
m_tcp_socket->disconnectFromHost();
|
||||
m_port = 0;
|
||||
@@ -69,8 +67,8 @@ namespace FSD
|
||||
|
||||
void CFSDClient::onConnected()
|
||||
{
|
||||
bDebug << "Connected successfully to remote host.";
|
||||
bDebug << "Sending #AP now...";
|
||||
bDebug(m_context) << "Connected successfully to remote host.";
|
||||
bDebug(m_context) << "Sending #AP now...";
|
||||
|
||||
QString line;
|
||||
|
||||
@@ -92,7 +90,7 @@ namespace FSD
|
||||
|
||||
void CFSDClient::onDisconnected()
|
||||
{
|
||||
bDebug << "Disconnected successfully from remote host.";
|
||||
bDebug(m_context) << "Disconnected successfully from remote host.";
|
||||
emit doDisconnected();
|
||||
}
|
||||
|
||||
@@ -101,7 +99,7 @@ namespace FSD
|
||||
|
||||
if ( error != 0 )
|
||||
{
|
||||
bError << "Received socket error: " << error << " - Disconnecting...";
|
||||
bError(m_context) << "Received socket error: " << error << " - Disconnecting...";
|
||||
}
|
||||
|
||||
disconnectFrom();
|
||||
@@ -125,7 +123,7 @@ namespace FSD
|
||||
{
|
||||
if (!isConnected())
|
||||
{
|
||||
bError << "Cannot send data in disconnected state!";
|
||||
bError(m_context) << "Cannot send data in disconnected state!";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -134,7 +132,7 @@ namespace FSD
|
||||
qint64 bytes = m_tcp_socket->write(message.toAscii());
|
||||
if (bytes < 0 || bytes != message_size)
|
||||
{
|
||||
bWarning << "Error writing to socket!";
|
||||
bWarning(m_context) << "Error writing to socket!";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -144,13 +142,13 @@ namespace FSD
|
||||
void CFSDClient::init()
|
||||
{
|
||||
m_tcp_socket = new QTcpSocket(this);
|
||||
bAssert(m_tcp_socket);
|
||||
Q_ASSERT(m_tcp_socket);
|
||||
|
||||
bAssert ( QObject::connect( m_tcp_socket, SIGNAL( connected() ), this, SLOT( onConnected() ) ) );
|
||||
bAssert ( QObject::connect( m_tcp_socket, SIGNAL( disconnected() ), this, SLOT( onDisconnected() ) ) );
|
||||
bAssert ( QObject::connect( m_tcp_socket, SIGNAL( error(QAbstractSocket::SocketError) ), this, SLOT( onError(QAbstractSocket::SocketError) ) ) );
|
||||
Q_ASSERT ( QObject::connect( m_tcp_socket, SIGNAL( connected() ), this, SLOT( onConnected() ) ) );
|
||||
Q_ASSERT ( QObject::connect( m_tcp_socket, SIGNAL( disconnected() ), this, SLOT( onDisconnected() ) ) );
|
||||
Q_ASSERT ( QObject::connect( m_tcp_socket, SIGNAL( error(QAbstractSocket::SocketError) ), this, SLOT( onError(QAbstractSocket::SocketError) ) ) );
|
||||
|
||||
bAssert ( QObject::connect( m_tcp_socket, SIGNAL( readyRead() ), this, SLOT( onReceivingData() ) ) );
|
||||
Q_ASSERT ( QObject::connect( m_tcp_socket, SIGNAL( readyRead() ), this, SLOT( onReceivingData() ) ) );
|
||||
|
||||
registerMessages();
|
||||
}
|
||||
@@ -178,7 +176,7 @@ namespace FSD
|
||||
|
||||
QTextStream stream(&line);
|
||||
IMessage* fsd_message = CMessageFactory::getInstance().create(header);
|
||||
bAssert(fsd_message);
|
||||
Q_ASSERT(fsd_message);
|
||||
*fsd_message << stream;
|
||||
|
||||
CMessageDispatcher::getInstance().append(fsd_message);
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
#ifndef FSD_CLIENT_H
|
||||
#define FSD_CLIENT_H
|
||||
|
||||
#include <blackcore/fsd_protocol.h>
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include <blackcore/fsd_protocol.h>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
class IContext;
|
||||
}
|
||||
|
||||
namespace FSD
|
||||
{
|
||||
@@ -32,7 +35,7 @@ class CFSDClient : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CFSDClient();
|
||||
CFSDClient(BlackMisc::IContext &context);
|
||||
|
||||
void connectTo(const QString &host, quint16 port);
|
||||
void disconnectFrom();
|
||||
@@ -107,6 +110,8 @@ private:
|
||||
|
||||
void processLine(QString &line);
|
||||
|
||||
BlackMisc::IContext& m_context;
|
||||
|
||||
QTcpSocket* m_tcp_socket;
|
||||
|
||||
QString m_host;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "blackmisc/debug.h"
|
||||
|
||||
#include "blackcore/fsd_messages.h"
|
||||
#include "blackmisc/debug.h"
|
||||
|
||||
using namespace BlackMisc;
|
||||
|
||||
@@ -27,7 +26,7 @@ namespace FSD
|
||||
}
|
||||
else
|
||||
{
|
||||
bError << "Cannot split message. Vector is to small";
|
||||
bAppError << "Cannot split message. Vector is to small";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +83,7 @@ namespace FSD
|
||||
{
|
||||
QString message = in.readAll();
|
||||
qint32 size = unpack(message, m_message_tokens);
|
||||
bAssert ( size == 10 );
|
||||
Q_ASSERT ( size == 10 );
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace FSD
|
||||
QString m_textmessage;
|
||||
for ( int ii = 2; ii < tokens.size(); ++ii)
|
||||
m_textmessage += tokens.at(ii);
|
||||
bInfo << m_textmessage;
|
||||
bAppInfo << m_textmessage;
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <iostream>
|
||||
#include "blackmisc/debug.h"
|
||||
#include "blackcore/vector_3d.h"
|
||||
#include "blackcore/matrix_3d.h"
|
||||
#include "blackcore/vector_3d.h"
|
||||
#include "blackmisc/debug.h"
|
||||
#include <iostream>
|
||||
|
||||
/* TODO
|
||||
*
|
||||
@@ -112,14 +112,14 @@ void CMatrix3D::print()
|
||||
|
||||
double CMatrix3D::getElement(qint8 row, qint8 column) const
|
||||
{
|
||||
bAssert (row < 3 || column < 3);
|
||||
Q_ASSERT (row < 3 || column < 3);
|
||||
|
||||
return m[row][column];
|
||||
}
|
||||
|
||||
void CMatrix3D::setElement(qint8 row, qint8 column, double value)
|
||||
{
|
||||
bAssert (row < 3 || column < 3);
|
||||
Q_ASSERT (row < 3 || column < 3);
|
||||
|
||||
m[row][column] = value;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "blackcore/plane.h"
|
||||
#include "blackcore/interpolator.h"
|
||||
#include "blackcore/simulator.h"
|
||||
#include "blackmisc/debug.h"
|
||||
#include "blackcore/plane.h"
|
||||
|
||||
namespace BlackCore {
|
||||
|
||||
@@ -15,13 +15,13 @@ namespace BlackCore {
|
||||
{
|
||||
m_interpolator = new CInterpolator();
|
||||
|
||||
bAssert(m_interpolator);
|
||||
bAssert(driver);
|
||||
Q_ASSERT(m_interpolator);
|
||||
Q_ASSERT(driver);
|
||||
}
|
||||
|
||||
void CPlane::addPosition(const CVectorGeo &position, double groundVelocity, double heading, double pitch, double bank)
|
||||
{
|
||||
bAssert(m_interpolator);
|
||||
Q_ASSERT(m_interpolator);
|
||||
|
||||
m_interpolator->pushUpdate(position, groundVelocity, heading, pitch, bank);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace BlackCore {
|
||||
|
||||
class ISimulator;
|
||||
class CInterpolator;
|
||||
class CVectorGeo;
|
||||
|
||||
class CPlane
|
||||
{
|
||||
|
||||
104
src/blackcore/pluginmgr.cpp
Normal file
104
src/blackcore/pluginmgr.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / authors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "blackcore/pluginmgr.h"
|
||||
#include "blackmisc/plugins.h"
|
||||
#include "blackmisc/context.h"
|
||||
#include <QDirIterator>
|
||||
#include <iostream>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
|
||||
CPluginManager::~CPluginManager()
|
||||
{
|
||||
for (QVector<PluginEntry>::iterator it = m_plugins.begin(); it != m_plugins.end(); ++it)
|
||||
{
|
||||
Q_ASSERT_X(it->loader, "Plugin manager", "Previously loaded plugin's loader ptr is null");
|
||||
|
||||
it->loader->unload();
|
||||
}
|
||||
}
|
||||
|
||||
void CPluginManager::loadAllPlugins(const QString &pluginsPath)
|
||||
{
|
||||
//TODO should we use a custom extension, so we don't attempt to load non-plugin .dll/.so files?
|
||||
#ifdef Q_OS_WIN
|
||||
static const QStringList pluginsFilter("*.dll");
|
||||
#else
|
||||
static const QStringList pluginsFilter("*.so");
|
||||
#endif
|
||||
|
||||
QDirIterator iter (pluginsPath, pluginsFilter, QDir::Files);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
QString filename = iter.next();
|
||||
|
||||
QSharedPointer<QPluginLoader> loader (new QPluginLoader (filename));
|
||||
try
|
||||
{
|
||||
if (! loader->load())
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
PluginEntry entry;
|
||||
entry.loader = loader;
|
||||
entry.factory = qobject_cast<BlackMisc::IPluginFactory*>(loader->instance());
|
||||
|
||||
if (! entry.factory)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
m_plugins.push_back(entry);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
//TODO warning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CPluginManager::PluginEntry &CPluginManager::getEntry(size_t index) const
|
||||
{
|
||||
Q_ASSERT_X(index < getPluginCount(), "Plugin manager", "Plugin index out of bounds");
|
||||
|
||||
const PluginEntry &entry = m_plugins[index];
|
||||
|
||||
Q_ASSERT_X(entry.factory, "Plugin manager", "Previously loaded plugin's factory ptr is null");
|
||||
Q_ASSERT_X(entry.loader, "Plugin manager", "Previously loaded plugin's loader ptr is null");
|
||||
|
||||
if (! entry.loader->isLoaded())
|
||||
{
|
||||
//TODO throw plugin loader unexpectedly unloaded
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
const QString CPluginManager::getName(size_t index) const
|
||||
{
|
||||
return getFactory(index)->getName();
|
||||
}
|
||||
|
||||
const QString CPluginManager::getDescription(size_t index) const
|
||||
{
|
||||
return getFactory(index)->getDescription();
|
||||
}
|
||||
|
||||
BlackMisc::IPlugin *CPluginManager::constructPlugin(size_t index)
|
||||
{
|
||||
BlackMisc::IPlugin *plugin = getFactory(index)->create(BlackMisc::IContext::getInstance());
|
||||
if (! plugin->isValid())
|
||||
{
|
||||
delete plugin;
|
||||
plugin = 0;
|
||||
//TODO throw plugin construction failed
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
} // namespace BlackCore
|
||||
136
src/blackcore/pluginmgr.h
Normal file
136
src/blackcore/pluginmgr.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / authors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*!
|
||||
\file
|
||||
*/
|
||||
|
||||
#ifndef BLACKCORE_PLUGINMGR_H
|
||||
#define BLACKCORE_PLUGINMGR_H
|
||||
|
||||
#include <QPluginLoader>
|
||||
#include <QVector>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace BlackMisc
|
||||
{
|
||||
class IPlugin;
|
||||
class IPluginFactory;
|
||||
}
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
|
||||
/*!
|
||||
Plugin manager.
|
||||
Loads plugins and allows them to be queried and instantiated.
|
||||
*/
|
||||
class CPluginManager
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
Destructor.
|
||||
*/
|
||||
virtual ~CPluginManager();
|
||||
|
||||
/*!
|
||||
Attempt to load all plugins found at the given path.
|
||||
\param pluginsPath
|
||||
*/
|
||||
void loadAllPlugins(const QString &pluginsPath);
|
||||
|
||||
/*!
|
||||
Return the total number of plugins loaded so far.
|
||||
\return
|
||||
*/
|
||||
size_t getPluginCount() const
|
||||
{
|
||||
return m_plugins.size();
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the name of a plugin.
|
||||
\param index the plugin's index in the vector of plugins.
|
||||
\return
|
||||
*/
|
||||
const QString getName(size_t index) const;
|
||||
|
||||
/*!
|
||||
Return the description of a plugin.
|
||||
\param index the plugin's index in the vector of plugins.
|
||||
\return
|
||||
*/
|
||||
const QString getDescription(size_t index) const;
|
||||
|
||||
/*!
|
||||
Construct a plugin.
|
||||
\param index the plugin's index in the vector of plugins.
|
||||
\return a pointer to the newly created plugin.
|
||||
\warning You must release this pointer with IPluginFactory::destroy().
|
||||
*/
|
||||
BlackMisc::IPlugin *constructPlugin(size_t index);
|
||||
|
||||
/*!
|
||||
Direct access to the factory. You don't usually need this.
|
||||
\param index
|
||||
\return
|
||||
*/
|
||||
BlackMisc::IPluginFactory *getFactory(size_t index)
|
||||
{
|
||||
return const_cast<BlackMisc::IPluginFactory*>(static_cast<const CPluginManager*>(this)->getFactory(index));
|
||||
}
|
||||
|
||||
/*!
|
||||
Direct access to the factory. You don't usually need this.
|
||||
\param index
|
||||
\return
|
||||
*/
|
||||
const BlackMisc::IPluginFactory *getFactory(size_t index) const
|
||||
{
|
||||
return getEntry(index).factory;
|
||||
}
|
||||
|
||||
/*!
|
||||
Direct access to the QPluginLoader. You don't usually need this.
|
||||
\param index
|
||||
\return
|
||||
*/
|
||||
QPluginLoader *getLoader(size_t index)
|
||||
{
|
||||
return const_cast<QPluginLoader*>(static_cast<const CPluginManager*>(this)->getLoader(index));
|
||||
}
|
||||
|
||||
/*!
|
||||
Direct access to the QPluginLoader. You don't usually need this.
|
||||
\param index
|
||||
\return
|
||||
*/
|
||||
const QPluginLoader *getLoader(size_t index) const
|
||||
{
|
||||
return getEntry(index).loader.data();
|
||||
}
|
||||
|
||||
private:
|
||||
class PluginEntry
|
||||
{
|
||||
public:
|
||||
PluginEntry() : factory(0) {}
|
||||
BlackMisc::IPluginFactory *factory;
|
||||
QSharedPointer<QPluginLoader> loader;
|
||||
};
|
||||
|
||||
QVector<PluginEntry> m_plugins;
|
||||
|
||||
PluginEntry &getEntry(size_t index)
|
||||
{
|
||||
return const_cast<PluginEntry&>(static_cast<const CPluginManager*>(this)->getEntry(index));
|
||||
}
|
||||
|
||||
const PluginEntry &getEntry(size_t index) const;
|
||||
};
|
||||
|
||||
} // namespace BlackCore
|
||||
|
||||
#endif //BLACKCORE_PLUGINMGR_H
|
||||
@@ -52,18 +52,24 @@ namespace BlackCore {
|
||||
case FS9:
|
||||
{
|
||||
myLib.setFileName(SHARED_LIBRARY_NAME_FS9);
|
||||
bAssertstr(myLib.load(), myLib.errorString());
|
||||
driverVersionMajor = (getDriverVersionMajor) myLib.resolve(DRIVER_VERSION_MAJOR);
|
||||
if (! myLib.load())
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
|
||||
if (driverVersionMajor != NULL)
|
||||
driverVersionMajor = (getDriverVersionMajor) myLib.resolve(DRIVER_VERSION_MAJOR);
|
||||
if (driverVersionMajor)
|
||||
{
|
||||
bAssertstr(driverVersionMajor() == ISimulator::InterfaceVersionMajor, QString("Wrong version of the driver. Try to reinstall!"));
|
||||
if (driverVersionMajor() != ISimulator::InterfaceVersionMajor)
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
}
|
||||
|
||||
createDriver = (createISimulatorInstance) myLib.resolve(IDRV_CREATE_SIM_INTERFACE);
|
||||
if (createDriver)
|
||||
{
|
||||
bInfo << "Loaded successfully shared library 'bb_driver_fs9'";
|
||||
bAppInfo << "Loaded successfully shared library 'bb_driver_fs9'";
|
||||
result = createDriver();
|
||||
}
|
||||
}
|
||||
@@ -71,38 +77,48 @@ namespace BlackCore {
|
||||
|
||||
case FSX:
|
||||
myLib.setFileName(SHARED_LIBRARY_NAME_FSX);
|
||||
bAssertstr(myLib.load(), myLib.errorString());
|
||||
if (! myLib.load())
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
|
||||
driverVersionMajor = (getDriverVersionMajor) myLib.resolve(DRIVER_VERSION_MAJOR);
|
||||
|
||||
if (driverVersionMajor != NULL)
|
||||
if (driverVersionMajor)
|
||||
{
|
||||
bAssertstr(driverVersionMajor() == ISimulator::InterfaceVersionMajor, QString("Wrong version of the driver. Try to reinstall!"));
|
||||
if (driverVersionMajor() != ISimulator::InterfaceVersionMajor)
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
}
|
||||
|
||||
createDriver = (createISimulatorInstance) myLib.resolve(IDRV_CREATE_SIM_INTERFACE);
|
||||
if (createDriver)
|
||||
{
|
||||
bInfo << "Loaded successfully shared library 'bb_driver_fsx'";
|
||||
bAppInfo << "Loaded successfully shared library 'bb_driver_fsx'";
|
||||
result = createDriver();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case XPLANE:
|
||||
myLib.setFileName(SHARED_LIBRARY_NAME_XPLANE);
|
||||
bAssertstr(myLib.load(), myLib.errorString());
|
||||
if (! myLib.load())
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
|
||||
driverVersionMajor = (getDriverVersionMajor) myLib.resolve(DRIVER_VERSION_MAJOR);
|
||||
|
||||
if (driverVersionMajor != NULL)
|
||||
if (driverVersionMajor)
|
||||
{
|
||||
bAssertstr(driverVersionMajor() == ISimulator::InterfaceVersionMajor, QString("Wrong version of the driver. Try to reinstall!"));
|
||||
if (driverVersionMajor() != ISimulator::InterfaceVersionMajor)
|
||||
{
|
||||
//TODO throw
|
||||
}
|
||||
}
|
||||
|
||||
createDriver = (createISimulatorInstance) myLib.resolve(IDRV_CREATE_SIM_INTERFACE);
|
||||
if (createDriver)
|
||||
{
|
||||
bInfo << "Loaded successfully shared library 'bb_driver_xplane'";
|
||||
bAppInfo << "Loaded successfully shared library 'bb_driver_xplane'";
|
||||
result = createDriver();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
|
||||
#include "blackcore/vector_3d.h"
|
||||
#include "blackcore/matrix_3d.h"
|
||||
#include "blackcore/vector_geo.h"
|
||||
#include "blackcore/constants.h"
|
||||
#include "blackmisc/debug.h"
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#include "blackmisc/debug.h"
|
||||
|
||||
#include "blackcore/matrix_3d.h"
|
||||
#include "blackcore/vector_3d.h"
|
||||
#include "blackcore/vector_geo.h"
|
||||
|
||||
#include "blackcore/constants.h"
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
|
||||
@@ -59,7 +57,7 @@ double CVector3D::magnitude()
|
||||
|
||||
double CVector3D::getElement(qint8 row) const
|
||||
{
|
||||
bAssert(row < 3);
|
||||
Q_ASSERT(row < 3);
|
||||
|
||||
return v[row];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user