mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 09:33:29 +02:00
Merge branch 'master' of git://github.com/highfidelity/hifi into entity-tools-polish-2
This commit is contained in:
commit
5c5c66b265
16 changed files with 177 additions and 160 deletions
15
BUILD.md
15
BUILD.md
|
@ -96,12 +96,13 @@ Currently building on Windows has been tested using the following compilers:
|
|||
|
||||
#####Windows SDK 7.1
|
||||
|
||||
Whichever version of Visual Studio you use, you will need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279).
|
||||
If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279).
|
||||
|
||||
NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK.
|
||||
|
||||
######Windows 8.1
|
||||
You may have already downloaded the Windows 8 SDK (e.g. if you have previously installed Visual Studio 2013). If so, change CMAKE_PREFIX_PATH in %HIFI_DIR%\CMakeLists.txt to point to the Windows 8 SDK binaries. The default path is `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`
|
||||
######Windows SDK 8.1
|
||||
|
||||
If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`.
|
||||
|
||||
#####Visual Studio C++ 2010 Express
|
||||
|
||||
|
@ -123,9 +124,11 @@ Some of the build instructions will ask you to start a Visual Studio Command Pro
|
|||
|
||||
#####Visual Studio 2013
|
||||
|
||||
This product must be purchased separately.
|
||||
You can use the Community or Professional editions of Visual Studio 2013.
|
||||
|
||||
Visual Studio 2013 doesn't have a shortcut to start a Visual Studio Command Prompt. Instead, start a regular command prompt and then run:
|
||||
You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013.
|
||||
|
||||
Or you can start a regular command prompt and then run:
|
||||
|
||||
"%VS120COMNTOOLS%\vsvars32.bat"
|
||||
|
||||
|
@ -146,6 +149,8 @@ Once Qt is installed, you need to manually configure the following:
|
|||
* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`.
|
||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory.
|
||||
|
||||
If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead.
|
||||
|
||||
####External Libraries
|
||||
|
||||
CMake will need to know where the headers and libraries for required external dependencies are.
|
||||
|
|
|
@ -48,8 +48,13 @@ elseif (UNIX)
|
|||
select_library_configurations(XINERAMA)
|
||||
|
||||
elseif (WIN32)
|
||||
find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
if (MSVC10)
|
||||
find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
elseif (MSVC12)
|
||||
find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS})
|
||||
endif ()
|
||||
find_package(ATL)
|
||||
endif ()
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
int const DomainServer::EXIT_CODE_REBOOT = 234923;
|
||||
|
||||
const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io";
|
||||
|
||||
DomainServer::DomainServer(int argc, char* argv[]) :
|
||||
QCoreApplication(argc, argv),
|
||||
_shutdownEventListener(this),
|
||||
|
@ -52,7 +54,8 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_webAuthenticationStateSet(),
|
||||
_cookieSessionHash(),
|
||||
_automaticNetworkingSetting(),
|
||||
_settingsManager()
|
||||
_settingsManager(),
|
||||
_iceServerSocket(ICE_SERVER_DEFAULT_HOSTNAME, ICE_SERVER_DEFAULT_PORT)
|
||||
{
|
||||
LogUtils::init();
|
||||
|
||||
|
@ -337,57 +340,67 @@ bool DomainServer::optionallySetupAssignmentPayment() {
|
|||
|
||||
void DomainServer::setupAutomaticNetworking() {
|
||||
|
||||
if (!didSetupAccountManagerWithAccessToken()) {
|
||||
qDebug() << "Cannot setup domain-server automatic networking without an access token.";
|
||||
qDebug() << "Please add an access token to your config file or via the web interface.";
|
||||
|
||||
return;
|
||||
}
|
||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
|
||||
const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000;
|
||||
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
|
||||
|
||||
// setup our timer to check our IP via stun every X seconds
|
||||
QTimer* dynamicIPTimer = new QTimer(this);
|
||||
connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN);
|
||||
|
||||
_automaticNetworkingSetting =
|
||||
_settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString();
|
||||
|
||||
if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
|
||||
dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS);
|
||||
|
||||
// setup a timer to heartbeat with the ice-server every so often
|
||||
QTimer* iceHeartbeatTimer = new QTimer(this);
|
||||
connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates);
|
||||
iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
|
||||
|
||||
// call our sendHeartbeatToIceServer immediately anytime a local or public socket changes
|
||||
connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
|
||||
connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
|
||||
|
||||
// attempt to update our public socket now, this will send a heartbeat once we get public socket
|
||||
requestCurrentPublicSocketViaSTUN();
|
||||
|
||||
// in case the STUN lookup is still happening we should re-request a public socket once we get that address
|
||||
connect(&nodeList->getSTUNSockAddr(), &HifiSockAddr::lookupCompleted,
|
||||
this, &DomainServer::requestCurrentPublicSocketViaSTUN);
|
||||
|
||||
}
|
||||
|
||||
if (!didSetupAccountManagerWithAccessToken()) {
|
||||
qDebug() << "Cannot send heartbeat to data server without an access token.";
|
||||
qDebug() << "Add an access token to your config file or via the web interface.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE ||
|
||||
_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
|
||||
|
||||
LimitedNodeList* nodeList = LimitedNodeList::getInstance();
|
||||
const QUuid& domainID = nodeList->getSessionUUID();
|
||||
|
||||
if (!domainID.isNull()) {
|
||||
qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID"
|
||||
<< uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString();
|
||||
|
||||
const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000;
|
||||
const int STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS = 10 * 1000;
|
||||
|
||||
// setup our timer to check our IP via stun every X seconds
|
||||
QTimer* dynamicIPTimer = new QTimer(this);
|
||||
connect(dynamicIPTimer, &QTimer::timeout, this, &DomainServer::requestCurrentPublicSocketViaSTUN);
|
||||
|
||||
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE) {
|
||||
dynamicIPTimer->start(STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS);
|
||||
|
||||
// send public socket changes to the data server so nodes can find us at our new IP
|
||||
connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::performIPAddressUpdate);
|
||||
|
||||
// attempt to update our sockets now
|
||||
requestCurrentPublicSocketViaSTUN();
|
||||
} else {
|
||||
dynamicIPTimer->start(STUN_REFLEXIVE_KEEPALIVE_INTERVAL_MSECS);
|
||||
|
||||
// setup a timer to heartbeat with the ice-server every so often
|
||||
QTimer* iceHeartbeatTimer = new QTimer(this);
|
||||
connect(iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::performICEUpdates);
|
||||
iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
|
||||
|
||||
// call our sendHeartbeaToIceServer immediately anytime a local or public socket changes
|
||||
connect(nodeList, &LimitedNodeList::localSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
|
||||
connect(nodeList, &LimitedNodeList::publicSockAddrChanged, this, &DomainServer::sendHeartbeatToIceServer);
|
||||
|
||||
// send our heartbeat to data server so it knows what our network settings are
|
||||
sendHeartbeatToDataServer();
|
||||
}
|
||||
|
||||
// attempt to update our sockets now
|
||||
requestCurrentPublicSocketViaSTUN();
|
||||
|
||||
} else {
|
||||
qDebug() << "Cannot enable domain-server automatic networking without a domain ID."
|
||||
<< "Please add an ID to your config file or via the web interface.";
|
||||
|
@ -1164,8 +1177,7 @@ void DomainServer::performICEUpdates() {
|
|||
}
|
||||
|
||||
void DomainServer::sendHeartbeatToIceServer() {
|
||||
static HifiSockAddr ICE_SERVER_SOCK_ADDR = HifiSockAddr("ice.highfidelity.io", ICE_SERVER_DEFAULT_PORT);
|
||||
LimitedNodeList::getInstance()->sendHeartbeatToIceServer(ICE_SERVER_SOCK_ADDR);
|
||||
LimitedNodeList::getInstance()->sendHeartbeatToIceServer(_iceServerSocket);
|
||||
}
|
||||
|
||||
void DomainServer::sendICEPingPackets() {
|
||||
|
|
|
@ -154,6 +154,8 @@ private:
|
|||
QString _automaticNetworkingSetting;
|
||||
|
||||
DomainServerSettingsManager _settingsManager;
|
||||
|
||||
HifiSockAddr _iceServerSocket;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -245,10 +245,12 @@ function handleGrabBehavior(deltaTime) {
|
|||
}
|
||||
|
||||
// Update for joysticks and move button
|
||||
var THRUST_DEAD_ZONE = 0.1;
|
||||
var ROTATE_DEAD_ZONE = 0.1;
|
||||
function flyWithHydra(deltaTime) {
|
||||
var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER);
|
||||
|
||||
if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) {
|
||||
if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) {
|
||||
if (thrustMultiplier < MAX_THRUST_MULTIPLIER) {
|
||||
thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE);
|
||||
}
|
||||
|
@ -270,7 +272,7 @@ function flyWithHydra(deltaTime) {
|
|||
|
||||
// View Controller
|
||||
var viewJoystickPosition = Controller.getJoystickPosition(VIEW_CONTROLLER);
|
||||
if (viewJoystickPosition.x != 0 || viewJoystickPosition.y != 0) {
|
||||
if (Math.abs(viewJoystickPosition.x) > ROTATE_DEAD_ZONE || Math.abs(viewJoystickPosition.y) > ROTATE_DEAD_ZONE) {
|
||||
|
||||
// change the body yaw based on our x controller
|
||||
var orientation = MyAvatar.orientation;
|
||||
|
|
|
@ -842,7 +842,7 @@ bool Application::event(QEvent* event) {
|
|||
QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
|
||||
|
||||
if (!fileEvent->url().isEmpty()) {
|
||||
AddressManager::getInstance().handleLookupString(fileEvent->url().toLocalFile());
|
||||
AddressManager::getInstance().handleLookupString(fileEvent->url().toString());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1574,7 +1574,9 @@ void Application::setFullscreen(bool fullscreen) {
|
|||
}
|
||||
_window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) :
|
||||
(_window->windowState() & ~Qt::WindowFullScreen));
|
||||
_window->show();
|
||||
if (!_aboutToQuit) {
|
||||
_window->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::setEnable3DTVMode(bool enable3DTVMode) {
|
||||
|
@ -4013,26 +4015,23 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
return _scriptEnginesHash[scriptURLString];
|
||||
}
|
||||
|
||||
ScriptEngine* scriptEngine;
|
||||
if (scriptFilename.isNull()) {
|
||||
scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
|
||||
} else {
|
||||
// start the script on a new thread...
|
||||
scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface);
|
||||
|
||||
if (!scriptEngine->hasScript()) {
|
||||
qDebug() << "Application::loadScript(), script failed to load...";
|
||||
QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
UserActivityLogger::getInstance().loadedScript(scriptURLString);
|
||||
}
|
||||
ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface);
|
||||
scriptEngine->setUserLoaded(isUserLoaded);
|
||||
|
||||
registerScriptEngineWithApplicationServices(scriptEngine);
|
||||
if (scriptFilename.isNull()) {
|
||||
// this had better be the script editor (we should de-couple so somebody who thinks they are loading a script
|
||||
// doesn't just get an empty script engine)
|
||||
|
||||
// we can complete setup now since there isn't a script we have to load
|
||||
registerScriptEngineWithApplicationServices(scriptEngine);
|
||||
} else {
|
||||
// connect to the appropriate signals of this script engine
|
||||
connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded);
|
||||
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError);
|
||||
|
||||
// get the script engine object to load the script at the designated script URL
|
||||
scriptEngine->loadURL(scriptUrl);
|
||||
}
|
||||
|
||||
// restore the main window's active state
|
||||
if (activateMainWindow && !loadScriptFromEditor) {
|
||||
|
@ -4043,6 +4042,22 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
|
|||
return scriptEngine;
|
||||
}
|
||||
|
||||
void Application::handleScriptEngineLoaded(const QUrl& scriptURL) {
|
||||
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
||||
|
||||
_scriptEnginesHash.insertMulti(scriptURL.toString(), scriptEngine);
|
||||
_runningScriptsWidget->setRunningScripts(getRunningScripts());
|
||||
UserActivityLogger::getInstance().loadedScript(scriptURL.toString());
|
||||
|
||||
// register our application services and set it off on its own thread
|
||||
registerScriptEngineWithApplicationServices(scriptEngine);
|
||||
}
|
||||
|
||||
void Application::handleScriptLoadError(const QUrl& scriptURL) {
|
||||
qDebug() << "Application::loadScript(), script failed to load...";
|
||||
QMessageBox::warning(getWindow(), "Error Loading Script", scriptURL.toString() + " failed to load.");
|
||||
}
|
||||
|
||||
void Application::scriptFinished(const QString& scriptName) {
|
||||
const QString& scriptURLString = QUrl(scriptName).toString();
|
||||
QHash<QString, ScriptEngine*>::iterator it = _scriptEnginesHash.find(scriptURLString);
|
||||
|
|
|
@ -393,6 +393,9 @@ private slots:
|
|||
void timer();
|
||||
void idle();
|
||||
void aboutToQuit();
|
||||
|
||||
void handleScriptEngineLoaded(const QUrl& scriptURL);
|
||||
void handleScriptLoadError(const QUrl& scriptURL);
|
||||
|
||||
void connectedToDomain(const QString& hostname);
|
||||
|
||||
|
|
|
@ -835,11 +835,16 @@ void GeometryReader::run() {
|
|||
fbxgeo = readSVO(_reply->readAll());
|
||||
} else {
|
||||
bool grabLightmaps = true;
|
||||
float lightmapLevel = 1.0f;
|
||||
// HACK: For monday 12/01/2014 we need to kill lighmaps loading in starchamber...
|
||||
if (_url.path().toLower().endsWith("loungev4_11-18.fbx")) {
|
||||
grabLightmaps = false;
|
||||
} else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) {
|
||||
lightmapLevel = 4.0f;
|
||||
} else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) {
|
||||
lightmapLevel = 3.5f;
|
||||
}
|
||||
fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps);
|
||||
fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel);
|
||||
}
|
||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, fbxgeo));
|
||||
|
||||
|
|
|
@ -571,8 +571,6 @@ void ApplicationOverlay::renderControllerPointers() {
|
|||
static quint64 pressedTime[NUMBER_OF_MAGNIFIERS] = { 0ULL, 0ULL, 0ULL };
|
||||
static bool isPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false };
|
||||
static bool stateWhenPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false };
|
||||
static bool triggerPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false };
|
||||
static bool bumperPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false };
|
||||
|
||||
const HandData* handData = Application::getInstance()->getAvatar()->getHandData();
|
||||
|
||||
|
@ -613,30 +611,6 @@ void ApplicationOverlay::renderControllerPointers() {
|
|||
}
|
||||
}
|
||||
|
||||
//Check for UI active toggle
|
||||
if (palmData->getTrigger() == 1.0f) {
|
||||
if (!triggerPressed[index]) {
|
||||
if (bumperPressed[index]) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface,
|
||||
!Menu::getInstance()->isOptionChecked(MenuOption::UserInterface));
|
||||
}
|
||||
triggerPressed[index] = true;
|
||||
}
|
||||
} else {
|
||||
triggerPressed[index] = false;
|
||||
}
|
||||
if ((controllerButtons & BUTTON_FWD)) {
|
||||
if (!bumperPressed[index]) {
|
||||
if (triggerPressed[index]) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface,
|
||||
!Menu::getInstance()->isOptionChecked(MenuOption::UserInterface));
|
||||
}
|
||||
bumperPressed[index] = true;
|
||||
}
|
||||
} else {
|
||||
bumperPressed[index] = false;
|
||||
}
|
||||
|
||||
//if we have the oculus, we should make the cursor smaller since it will be
|
||||
//magnified
|
||||
if (OculusManager::isConnected()) {
|
||||
|
|
|
@ -1194,7 +1194,7 @@ int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const Q
|
|||
}
|
||||
}
|
||||
|
||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps) {
|
||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
|
||||
QHash<QString, ExtractedMesh> meshes;
|
||||
QHash<QString, QString> modelIDsToNames;
|
||||
QHash<QString, int> meshIDsToMeshIndices;
|
||||
|
@ -1954,6 +1954,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
|
|||
|
||||
FBXTexture emissiveTexture;
|
||||
glm::vec2 emissiveParams(0.f, 1.f);
|
||||
emissiveParams.y = lightmapLevel;
|
||||
QString emissiveTextureID = emissiveTextures.value(childID);
|
||||
QString ambientTextureID = ambientTextures.value(childID);
|
||||
if (!emissiveTextureID.isNull() || !ambientTextureID.isNull()) {
|
||||
|
@ -2372,10 +2373,10 @@ QByteArray writeMapping(const QVariantHash& mapping) {
|
|||
return buffer.data();
|
||||
}
|
||||
|
||||
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps) {
|
||||
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps, float lightmapLevel) {
|
||||
QBuffer buffer(const_cast<QByteArray*>(&model));
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps);
|
||||
return extractFBXGeometry(parseFBX(&buffer), mapping, loadLightmaps, lightmapLevel);
|
||||
}
|
||||
|
||||
bool addMeshVoxelsOperation(OctreeElement* element, void* extraData) {
|
||||
|
|
|
@ -253,7 +253,7 @@ QByteArray writeMapping(const QVariantHash& mapping);
|
|||
|
||||
/// Reads FBX geometry from the supplied model and mapping data.
|
||||
/// \exception QString if an error occurs in parsing
|
||||
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true);
|
||||
FBXGeometry readFBX(const QByteArray& model, const QVariantHash& mapping, bool loadLightmaps = true, float lightmapLevel = 1.0f);
|
||||
|
||||
/// Reads SVO geometry from the supplied model data.
|
||||
FBXGeometry readSVO(const QByteArray& model);
|
||||
|
|
|
@ -86,6 +86,7 @@ bool HifiSockAddr::operator==(const HifiSockAddr& rhsSockAddr) const {
|
|||
void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) {
|
||||
if (hostInfo.error() != QHostInfo::NoError) {
|
||||
qDebug() << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString();
|
||||
emit lookupFailed();
|
||||
}
|
||||
|
||||
foreach(const QHostAddress& address, hostInfo.addresses()) {
|
||||
|
@ -94,6 +95,7 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) {
|
|||
_address = address;
|
||||
qDebug() << "QHostInfo lookup result for"
|
||||
<< hostInfo.hostName() << "with lookup ID" << hostInfo.lookupId() << "is" << address.toString();
|
||||
emit lookupCompleted();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ public:
|
|||
friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr);
|
||||
private slots:
|
||||
void handleLookupResult(const QHostInfo& hostInfo);
|
||||
signals:
|
||||
void lookupCompleted();
|
||||
void lookupFailed();
|
||||
private:
|
||||
QHostAddress _address;
|
||||
quint16 _port;
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket);
|
||||
|
||||
const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; }
|
||||
const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; }
|
||||
|
||||
void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet);
|
||||
void processKillNode(const QByteArray& datagram);
|
||||
|
|
|
@ -100,71 +100,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
|||
{
|
||||
}
|
||||
|
||||
ScriptEngine::ScriptEngine(const QUrl& scriptURL,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface) :
|
||||
_scriptContents(),
|
||||
_isFinished(false),
|
||||
_isRunning(false),
|
||||
_isInitialized(false),
|
||||
_isAvatar(false),
|
||||
_avatarIdentityTimer(NULL),
|
||||
_avatarBillboardTimer(NULL),
|
||||
_timerFunctionMap(),
|
||||
_isListeningToAudioStream(false),
|
||||
_avatarSound(NULL),
|
||||
_numAvatarSoundSentBytes(0),
|
||||
_controllerScriptingInterface(controllerScriptingInterface),
|
||||
_avatarData(NULL),
|
||||
_scriptName(),
|
||||
_fileNameString(),
|
||||
_quatLibrary(),
|
||||
_vec3Library(),
|
||||
_uuidLibrary(),
|
||||
_animationCache(this),
|
||||
_isUserLoaded(false),
|
||||
_arrayBufferClass(new ArrayBufferClass(this))
|
||||
{
|
||||
QString scriptURLString = scriptURL.toString();
|
||||
_fileNameString = scriptURLString;
|
||||
|
||||
QUrl url(scriptURL);
|
||||
|
||||
// if the scheme length is one or lower, maybe they typed in a file, let's try
|
||||
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
||||
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
||||
url = QUrl::fromLocalFile(scriptURLString);
|
||||
}
|
||||
|
||||
// ok, let's see if it's valid... and if so, load it
|
||||
if (url.isValid()) {
|
||||
if (url.scheme() == "file") {
|
||||
QString fileName = url.toLocalFile();
|
||||
QFile scriptFile(fileName);
|
||||
if (scriptFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||
qDebug() << "Loading file:" << fileName;
|
||||
QTextStream in(&scriptFile);
|
||||
_scriptContents = in.readAll();
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << fileName;
|
||||
emit errorMessage("ERROR Loading file:" + fileName);
|
||||
}
|
||||
} else {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
|
||||
qDebug() << "Downloading script at" << url;
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
|
||||
_scriptContents = reply->readAll();
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << url.toString();
|
||||
emit errorMessage("ERROR Loading file:" + url.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::setIsAvatar(bool isAvatar) {
|
||||
_isAvatar = isAvatar;
|
||||
|
||||
|
@ -217,6 +152,56 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin
|
|||
return true;
|
||||
}
|
||||
|
||||
void ScriptEngine::loadURL(const QUrl& scriptURL) {
|
||||
if (_isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString scriptURLString = scriptURL.toString();
|
||||
_fileNameString = scriptURLString;
|
||||
|
||||
QUrl url(scriptURL);
|
||||
|
||||
// if the scheme length is one or lower, maybe they typed in a file, let's try
|
||||
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
||||
if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
||||
url = QUrl::fromLocalFile(scriptURLString);
|
||||
}
|
||||
|
||||
// ok, let's see if it's valid... and if so, load it
|
||||
if (url.isValid()) {
|
||||
if (url.scheme() == "file") {
|
||||
QString fileName = url.toLocalFile();
|
||||
QFile scriptFile(fileName);
|
||||
if (scriptFile.open(QFile::ReadOnly | QFile::Text)) {
|
||||
qDebug() << "Loading file:" << fileName;
|
||||
QTextStream in(&scriptFile);
|
||||
_scriptContents = in.readAll();
|
||||
emit scriptLoaded(url);
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << fileName;
|
||||
emit errorLoadingScript(url);
|
||||
}
|
||||
} else {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, this, &ScriptEngine::handleScriptDownload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::handleScriptDownload() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
|
||||
_scriptContents = reply->readAll();
|
||||
emit scriptLoaded(reply->url());
|
||||
} else {
|
||||
qDebug() << "ERROR Loading file:" << reply->url().toString();
|
||||
emit errorLoadingScript(reply->url());
|
||||
}
|
||||
}
|
||||
|
||||
Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString)
|
||||
|
||||
void ScriptEngine::init() {
|
||||
|
|
|
@ -40,9 +40,6 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10
|
|||
class ScriptEngine : public QScriptEngine {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEngine(const QUrl& scriptURL,
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
||||
ScriptEngine(const QString& scriptContents = NO_SCRIPT,
|
||||
const QString& fileNameString = QString(""),
|
||||
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL);
|
||||
|
@ -94,6 +91,7 @@ public:
|
|||
bool isUserLoaded() const { return _isUserLoaded; }
|
||||
|
||||
public slots:
|
||||
void loadURL(const QUrl& scriptURL);
|
||||
void stop();
|
||||
|
||||
QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
|
||||
|
@ -109,6 +107,8 @@ public slots:
|
|||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
signals:
|
||||
void scriptLoaded(const QUrl& scriptURL);
|
||||
void errorLoadingScript(const QUrl& scriptURL);
|
||||
void update(float deltaTime);
|
||||
void scriptEnding();
|
||||
void finished(const QString& fileNameString);
|
||||
|
@ -155,6 +155,8 @@ private:
|
|||
ArrayBufferClass* _arrayBufferClass;
|
||||
|
||||
QHash<QUuid, quint16> _outgoingScriptAudioSequenceNumbers;
|
||||
private slots:
|
||||
void handleScriptDownload();
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptEngine_h
|
||||
|
|
Loading…
Reference in a new issue