Exemple #1
0
void loom_asset_registerType(unsigned int type, LoomAssetDeserializeCallback deserializer, LoomAssetRecognizerCallback recognizer)
{
    lmAssert(gAssetDeserializerMap.find(type) == UT_NPOS, "Asset type already registered!");

    gAssetDeserializerMap.insert(type, deserializer);
    gRecognizerList.push_back(recognizer);
}
Exemple #2
0
void loom_asset_reload(const char *name)
{
    loom_mutex_lock(gAssetLock);

    loom_asset_t *asset = loom_asset_getAssetByName(name, 1);

    // Put it in the queue, this will trigger a new blob to be loaded.
    gAssetLoadQueue.push_back(asset);

    loom_mutex_unlock(gAssetLock);
}
void akMeshLoaderUtils_getVertexGroups(Blender::Mesh* bmesh, Blender::Object* bobj, utArray<utString>& vgroups)
{
    if(bmesh->dvert)
    {
        Blender::bDeformGroup* dg = (Blender::bDeformGroup*)bobj->defbase.first;
        while(dg)
        {
            vgroups.push_back(dg->name);
            dg = dg->next;
        }
    }
}
void NativeDelegate::postNativeDelegateCallNote(NativeDelegateCallNote *ndcn)
{
    ensureQueueInit();
    loom_mutex_lock(gCallNoteMutex);

    // Prep for reading.
    ndcn->rewind();

    // Store for later access.
    gNDCallNoteQueue.push_back(ndcn);

    loom_mutex_unlock(gCallNoteMutex);
}
Exemple #5
0
void Type::findMembers(const MemberTypes& memberTypes,
                       utArray<MemberInfo *>& membersOut, bool includeBases, bool includePropertyGetterSetters)
{
    if (!includeBases)
    {
        membersOut.clear();
    }

    for (size_t i = 0; i < members.size(); i++)
    {
        MemberInfo *m = members.at((int)i);

        if (m->isConstructor() && memberTypes.constructor)
        {
            membersOut.push_back(m);
        }

        if (m->isMethod() && memberTypes.method)
        {
            membersOut.push_back(m);
        }

        if (m->isField() && memberTypes.field)
        {
            membersOut.push_back(m);
        }

        if (m->isProperty() && memberTypes.property)
        {
            membersOut.push_back(m);

            if (includePropertyGetterSetters)
            {
                PropertyInfo *p = (PropertyInfo *)m;

                if (p->getter && (p->getter->getDeclaringType() == p->getDeclaringType()))
                {
                    membersOut.push_back(p->getter);
                }

                if (p->setter && (p->setter->getDeclaringType() == p->getDeclaringType()))
                {
                    membersOut.push_back(p->setter);
                }
            }
        }
    }

    if (baseType && includeBases)
    {
        baseType->findMembers(memberTypes, membersOut, true, includePropertyGetterSetters);
    }
}
Exemple #6
0
void loom_asset_preload(const char *name)
{
    loom_mutex_lock(gAssetLock);

    // Look 'er up.
    loom_asset_t *asset = loom_asset_getAssetByName(name, 1);

    // If it's not pending load, then stick it in the queue.
    if (loom_asset_isOnTrackToLoad(asset))
    {
        loom_mutex_unlock(gAssetLock);
        return;
    }

    asset->state = loom_asset_t::QueuedForDownload;
    gAssetLoadQueue.push_back(asset);

    loom_mutex_unlock(gAssetLock);
}
Exemple #7
0
/**
 * Post all known files to all clients, or if specified, a single client.
 *
 * Useful for fully synching client with the current asset state.
 *
 * TODO: Optimize to use hashes to only transmit modified data, based on
 * client's starting assets.
 */
static void postAllFiles(int clientId = -1)
{
    lmLog(gAssetAgentLogGroup, "Queueing all files for client %d.", clientId);

    loom_mutex_lock(gFileScannerLock);

    // Walk all the files.
    utArray<FileEntry> *list = lmNew(NULL) utArray<FileEntry>();
    platform_walkFiles(".", handleFileStateWalkCallback, list);

    // Queue them all to be sent.
    for (UTsize i = 0; i < list->size(); i++)
    {
        FileModificationNote note;
        note.path          = stringtable_insert((*list)[i].path.c_str());
        note.lastSeenTime  = 0;
        note.onlyForClient = clientId;
        gPendingModifications.push_back(note);
    }

    loom_mutex_unlock(gFileScannerLock);
}
void akMeshLoaderUtils_getShapeKeys(Blender::Mesh* bmesh, utArray<utString>& shapes)
{
    Blender::Key* bk = bmesh->key;
    if(bk)
    {
        Blender::KeyBlock* bkb = (Blender::KeyBlock*)bk->block.first;

        // skip first shape key (basis)
        if(bkb) bkb = bkb->next;
        while(bkb)
        {
            if(bkb->type == KEY_RELATIVE)
            {
                Blender::KeyBlock* basis = (Blender::KeyBlock*)bk->block.first;
                for(int i=0; basis && i<bkb->relative; i++)
                    basis = basis->next;

                if(basis)
                    shapes.push_back(bkb->name);
            }
            bkb = bkb->next;
        }
    }
}
Exemple #9
0
// Entry point for the socket thread. Listen for connections and incoming data,
// and route it to the protocol handlers.
static int socketListeningThread(void *payload)
{
    // Listen for incoming connections.
    int listenPort = 12340;

    gListenSocket = (loom_socketId_t)-1;
    for ( ; ; )
    {
        gListenSocket = loom_net_listenTCPSocket(listenPort);

        if (gListenSocket != (loom_socketId_t)-1)
        {
            break;
        }

        lmLogWarn(gAssetAgentLogGroup, "   - Failed to acquire port %d, trying port %d", listenPort, listenPort + 1);
        listenPort++;
    }

    lmLog(gAssetAgentLogGroup, "Listening on port %d", listenPort);

    while (loom_socketId_t acceptedSocket = loom_net_acceptTCPSocket(gListenSocket))
    {
        // Check to see if we got anybody...
        if (!acceptedSocket || ((int)(long)acceptedSocket == -1))
        {
            // Process the connections.
            loom_mutex_lock(gActiveSocketsMutex);
            
            for (UTsize i = 0; i < gActiveHandlers.size(); i++)
            {
                AssetProtocolHandler* aph = gActiveHandlers[i];
                aph->process();

                // Check for ping timeout
                int msSincePing = loom_readTimer(aph->lastActiveTime);
                if (msSincePing > socketPingTimeoutMs)
                {
                    gActiveHandlers.erase(i);
                    i--;
                    lmLog(gAssetAgentLogGroup, "Client timed out (%x)", aph->socket);
                    loom_net_closeTCPSocket(aph->socket);
                    lmDelete(NULL, aph);
                }
            }

            loom_mutex_unlock(gActiveSocketsMutex);

            loom_thread_sleep(10);
            continue;
        }

        lmLog(gAssetAgentLogGroup, "Client connected (%x)", acceptedSocket);

        loom_mutex_lock(gActiveSocketsMutex);
        gActiveHandlers.push_back(lmNew(NULL) AssetProtocolHandler(acceptedSocket));

        AssetProtocolHandler *handler = gActiveHandlers.back();
        handler->registerListener(lmNew(NULL) TelemetryListener());
        if (TelemetryServer::isRunning()) handler->sendCommand("telemetryEnable");

        // Send it all of our files.
        // postAllFiles(gActiveHandlers[gActiveHandlers.size()-1]->getId());

        loom_mutex_unlock(gActiveSocketsMutex);
    }

    return 0;
}
Exemple #10
0
// Take a difference report from compareFileEntries and issue appropriate
// file modification notes, and check whether they have settled. If so,
// transmit updates to clients.
static void processFileEntryDeltas(utArray<FileEntryDelta> *deltas)
{
    int curTime = platform_getMilliseconds();

    loom_mutex_lock(gFileScannerLock);

    // Update the pending list with all the stuff we've seen.
    for (UTsize i = 0; i < deltas->size(); i++)
    {
        // Get the delta.
        const FileEntryDelta& fed = deltas->at(i);

        // If it's removal, we don't currently send a notification.
        if (fed.action == FileEntryDelta::Removed)
        {
            continue;
        }

        // If it's not whitelisted, ignore it.
        if (!checkInWhitelist(fed.path))
        {
            continue;
        }

        // Note it in the pending modification list.
        bool sawInList = false;
        for (UTsize i = 0; i < gPendingModifications.size(); i++)
        {
            FileModificationNote& fmn = gPendingModifications.at(i);
            if (strcmp(fmn.path, fed.path.c_str()))
            {
                continue;
            }

            // Match - update time.
            lmLogDebug(gAssetAgentLogGroup, "FILE CHANGING - '%s'", fed.path.c_str());
            fmn.lastSeenTime = curTime;
            sawInList        = true;
        }

        if (!sawInList)
        {
            FileModificationNote fmn;
            fmn.path         = stringtable_insert(fed.path.c_str());
            fmn.lastSeenTime = curTime;
            gPendingModifications.push_back(fmn);
            lmLogDebug(gAssetAgentLogGroup, "FILE CHANGED  - '%s'", fed.path.c_str());
        }
    }

    // Now, walk the pending list and send everyone who hasn't been touched for the settling period.

    // See how many files we're sending and note that state.
    const int settleTimeMs = 750;

    int transferStartTime     = platform_getMilliseconds();
    int totalPendingTransfers = 0;
    for (UTsize i = 0; i < gPendingModifications.size(); i++)
    {
        // Only consider pending items that have aged out.
        FileModificationNote& fmn = gPendingModifications.at(i);
        if (curTime - fmn.lastSeenTime < settleTimeMs)
        {
            continue;
        }

        totalPendingTransfers++;
    }

    bool didWeNotifyUserAboutPending = false;

    for (UTsize i = 0; i < gPendingModifications.size(); i++)
    {
        // Only consider pending items that have aged out.
        FileModificationNote& fmn = gPendingModifications.at(i);
        if (curTime - fmn.lastSeenTime < settleTimeMs)
        {
            continue;
        }

        // Make the path canonical.
        utString filename = fmn.path;
        char     canonicalFile[MAXPATHLEN];
        makeAssetPathCanonical(filename.c_str(), canonicalFile);

        // Note: we don't deal with deleted files properly (by uploading new state) because realpath
        // only works right when the file exists. So we just skip doing anything about it.
        // Note we are using gActiveHandlers.size() outside of a lock, but this is ok as it's a word.
        if ((strstr(canonicalFile, ".loom") || strstr(canonicalFile, ".ls")) && (gActiveHandlers.size() > 0))
        {
            lmLog(gAssetAgentLogGroup, "Changed '%s'", canonicalFile);
        }

        if (canonicalFile[0] == 0)
        {
            lmLog(gAssetAgentLogGroup, "   o Ignoring file missing from the asset folder!");

            // Remove from the pending list.
            gPendingModifications.erase(i);
            i--;

            continue;
        }

        // Queue the callback.
        enqueueFileChangeCallback(canonicalFile);

        // Map the file.
        void *fileBits      = NULL;
        long fileBitsLength = 0;
        if (!platform_mapFile(canonicalFile, &fileBits, &fileBitsLength))
        {
            lmLog(gAssetAgentLogGroup, "   o Skipping due to file failing to map.");
            continue;
        }

        // Loop over the active sockets.
        loom_mutex_lock(gActiveSocketsMutex);

        // Blast it out to all clients.
        for (UTsize j = 0; j < gActiveHandlers.size(); j++)
        {
            // If it's for a specific client then only send to that client.
            if ((fmn.onlyForClient != -1) && (fmn.onlyForClient != gActiveHandlers[j]->getId()))
            {
                continue;
            }

            gActiveHandlers[j]->sendFile(canonicalFile, fileBits, fileBitsLength, totalPendingTransfers);

            // If it has been more than a second, note that we are still working.
            const int remainingTransferCount = (totalPendingTransfers * gActiveHandlers.size()) - j;
            if (((platform_getMilliseconds() - transferStartTime) > 2000) && (remainingTransferCount > 1))
            {
                transferStartTime = platform_getMilliseconds();
                lmLog(gAssetAgentLogGroup, "Still transferring files. %d to go!", remainingTransferCount - 1);
                didWeNotifyUserAboutPending = true;
            }
        }

        loom_mutex_unlock(gActiveSocketsMutex);

        totalPendingTransfers--;

        // Unmap the file.
        platform_unmapFile(fileBits);

        // Remove from the pending list.
        gPendingModifications.erase(i);
        i--;
    }

    loom_mutex_unlock(gFileScannerLock);

    if (didWeNotifyUserAboutPending)
    {
        lmLog(gAssetAgentLogGroup, "Done transferring files!");
    }
}
    void addVertex(unsigned int fi, unsigned int bindex, const akMeshLoader::TempVert& ref)
    {
        utArray<float> uvs;
        for(int j=0; j<AK_UV_MAX; j++)
        {
            uvs.push_back(ref.uv[j][0]);
            uvs.push_back(ref.uv[j][1]);
        }
        UTuint32 id = item->addVertex(ref.co, ref.no, ref.vcol, uvs);
        idxmap.push_back(bindex);

        // vgroups
        if(m_bmesh->dvert)
        {
            Blender::MDeformVert& dv = m_bmesh->dvert[bindex];
            for(int j=0; j<dv.totweight; j++)
            {
                UTuint32 vgi = dv.dw[j].def_nr;
                if( vgi < item->getNumVertexGroups() )
                {
                    akVertexGroup* vg = item->getVertexGroup(vgi);
                    vg->add(id, dv.dw[j].weight);
                }
            }
        }

        // morphtargets
        if(m_bmesh->key)
        {
            Blender::KeyBlock* bkb = (Blender::KeyBlock*)m_bmesh->key->block.first;

            // skip first shape key (basis)
            int mti=0;
            if(bkb) bkb = bkb->next;
            while(bkb)
            {
                if(bkb->type == KEY_RELATIVE)
                {
                    Blender::KeyBlock* basis = (Blender::KeyBlock*)m_bmesh->key->block.first;
                    for(int i=0; basis && i<bkb->relative; i++)
                        basis = basis->next;

                    if(basis)
                    {
                        //akMorphTarget* mt = item->getMorphTarget(bkb->name);
                        akMorphTarget* mt = item->getMorphTarget(mti);

                        float* kpos = (float*)bkb->data;
                        float* bpos = (float*)basis->data;

                        akVector3 k(kpos[3*bindex+0], kpos[3*bindex+1], kpos[3*bindex+2]);
                        akVector3 b(bpos[3*bindex+0], bpos[3*bindex+1], bpos[3*bindex+2]);
                        k = k-b;

                        btAlignedObjectArray<akVector3>& norms = shapekeysnormals->at(mti);
                        akVector3 normal(0,0,0);

                        const Blender::MFace& bface = m_bmesh->mface[fi];

                        if(bface.flag & ME_SMOOTH)
                        {
                            utArray<UTuint32>& smoothfaces = smoothfacesarray->at(bindex);
                            for (int j = 0; j< smoothfaces.size(); j++)
                            {
                                UTuint32 bface2id = smoothfaces[j];
                                normal += norms.at(bface2id);

                            }
                            normal = normalize(normal);
                        }
                        else
                        {
                            normal = norms.at(fi);
                        }
                        normal = normal - ref.no;

                        if(!akFuzzyT(lengthSqr(k), 1e-10f) || !akFuzzyT(lengthSqr(normal), 1e-10f))
                            mt->add(id, k, normal);

                        mti++;
                    }
                }
                bkb = bkb->next;
            }
        }
    }
Exemple #12
0
void loom_asset_registerType(unsigned int type, LoomAssetDeserializeCallback deserializer, LoomAssetRecognizerCallback recognizer)
{
    gAssetDeserializerMap.insert(type, deserializer);
    gRecognizerList.push_back(recognizer);
}