Beispiel #1
0
TemplateInfo *BinReader::readTemplateTypes()
{
    if (!bytes->readBoolean())
    {
        return NULL;
    }

    TemplateInfo *templateInfo = lmNew(NULL) TemplateInfo;
    templateInfo->fullTypeName = readPoolString();
    templateInfo->type         = getType(templateInfo->fullTypeName.c_str());

    int numTypes = bytes->readInt();

    for (int i = 0; i < numTypes; i++)
    {
        if (!bytes->readBoolean())
        {
            TemplateInfo *t = lmNew(NULL) TemplateInfo;
            t->fullTypeName = readPoolString();
            t->type         = getType(t->fullTypeName.c_str());
            templateInfo->types.push_back(t);
        }
        else
        {
            templateInfo->types.push_back(readTemplateTypes());
        }
    }

    return templateInfo;
}
NativeDelegateCallNote *NativeDelegate::prepCallbackNote() const
{
    lmLogDebug(gNativeDelegateGroup, "Considering async callback %x", this);
    
    // Are noting currently? Just work with that.
    if(_activeNote)
    {
        lmLogDebug(gNativeDelegateGroup, " OUT due to activeNote already present");
        return _activeNote;
    }

    // See if we should try to go async.
    if(_allowAsync == false)
    {
        lmLogDebug(gNativeDelegateGroup, " OUT due to async being disallowed");
        return NULL;
    }

    if(smMainThreadID == platform_getCurrentThreadId())
        return NULL;

    // Only do this for async delegates off main thread.
    lmLogDebug(gNativeDelegateGroup, "Prepping async callback!");
    _activeNote = lmNew(NULL) NativeDelegateCallNote(this);
    return _activeNote;
}
Beispiel #3
0
    BitmapData* BitmapData::diff(const BitmapData* a, const BitmapData* b)
    {
        if (a->w != b->w || a->h != b->h)
            return NULL;

        BitmapData* result = lmNew(NULL) BitmapData(
            (size_t)a->w,
            (size_t)a->h
        );

        if (result == NULL) {
            lmLogError(gGFXLogGroup, "Unable to allocate memory for BitmapData diff result");
            return NULL;
        }

        rgba_t* pixelptr_a = reinterpret_cast<rgba_t*>(a->data);
        rgba_t* pixelptr_b = reinterpret_cast<rgba_t*>(b->data);
        rgba_t* resultptr = reinterpret_cast<rgba_t*>(result->data);

        for (size_t i = 0; i < a->w * a->h; i++)
        {
            Color ap(convertHostToBEndian(pixelptr_a[i]));
            Color bp(convertHostToBEndian(pixelptr_b[i]));
            Color rp(fabsf(ap.r - bp.r), fabsf(ap.g - bp.g), fabsf(ap.b - bp.b), 1.0f);
            rgba_t a = rp.getHex();
            resultptr[i] = convertBEndianToHost(a);
        }

        return result;
    }
Beispiel #4
0
Type *TypeReader::declareType(Module *module, json_t *json)
{
    Type *type = lmNew(NULL) Type;

    const char *stype = json_string_value(json_object_get(json, "type"));

    if (!strcmp(stype, "CLASS"))
    {
        type->attr.isClass = true;
    }
    else if (!strcmp(stype, "INTERFACE"))
    {
        type->attr.isInterface = true;
    }
    else if (!strcmp(stype, "STRUCT"))
    {
        type->attr.isStruct = true;
    }
    else if (!strcmp(stype, "DELEGATE"))
    {
        type->attr.isDelegate = true;
    }
    else if (!strcmp(stype, "ENUM"))
    {
        type->attr.isEnum = true;
    }
    else
    {
        assert(0); //, "Unknown type: %s", stype);
    }
    declareClass(type, json);

    return type;
}
Beispiel #5
0
    const BitmapData* BitmapData::fromFramebuffer()
    {
        int w = GFX::Graphics::getWidth();
        int h = GFX::Graphics::getHeight();

        // Sanity check
        if (w == 0 || h == 0) {
            lmLogError(gGFXLogGroup, "Graphics dimensions invalid %d x %d: %s", w, h, SDL_GetError());
            return NULL;
        }

        BitmapData* result = lmNew(NULL) BitmapData(w, h);

        if (result == NULL) {
            lmLogError(gGFXLogGroup, "Unable to allocate memory for screenshot pixel data buffer");
            return NULL;
        }

        GFX::GL_Context* ctx = GFX::Graphics::context();

        utByteArray tmp;
        tmp.resize(result->w * result->h * DATA_BPP);

        ctx->glPixelStorei(GL_PACK_ALIGNMENT, 1);
        ctx->glReadPixels(0, 0, result->w, result->h, GL_RGBA, GL_UNSIGNED_BYTE, tmp.getDataPtr());

        for (int i = result->h - 1; i >= 0; i--)
        {
            memcpy(result->data + (result->h - 1 - i) * result->w * DATA_BPP, (channel_t*)tmp.getDataPtr() + i * result->w * DATA_BPP, result->w * DATA_BPP);
        }

        return result;
    }
Beispiel #6
0
static void *loom_asset_binaryDeserializer(void *ptr, size_t size, LoomAssetCleanupCallback *dtor)
{
    utByteArray *bytes = lmNew(NULL) utByteArray();
    bytes->allocateAndCopy(ptr, (int)size);
    *dtor = loom_asset_binaryDtor;
    return bytes;
}
Beispiel #7
0
FieldInfo *BinReader::readField(Type *type)
{
    FieldInfo *field = lmNew(NULL) FieldInfo();

    readMemberInfo(field);

    field->memberType.field = true;
    field->declaringType    = type;

    // handle attr
    int numAttr = bytes->readInt();

    for (int i = 0; i < numAttr; i++)
    {
        const char *attr = readPoolString();

        if (!strcmp(attr, "static"))
        {
            field->attr.isStatic = true;
        }
        else if (!strcmp(attr, "public"))
        {
            field->attr.isPublic = true;
        }
        else if (!strcmp(attr, "private"))
        {
            field->attr.isPrivate = true;
        }
        else if (!strcmp(attr, "protected"))
        {
            field->attr.isProtected = true;
        }
        else if (!strcmp(attr, "native"))
        {
            field->attr.isNative = true;
        }
        else if (!strcmp(attr, "const"))
        {
            field->attr.isConst = true;
        }
    }

    Type *fieldType = NULL;

    if (bytes->readBoolean())
    {
        fieldType = getType(readPoolString());
    }

    field->type = fieldType;

    if (bytes->readBoolean())
    {
        field->setTemplateInfo(readTemplateTypes());
    }

    return field;
}
Beispiel #8
0
static void enqueueLogCallback(const char *msg)
{
    CallbackQueueNote *cqn = lmNew(NULL) CallbackQueueNote();

    cqn->type = QNT_Log;
    cqn->text = utString(msg);

    loom_mutex_lock(gCallbackLock);
    gCallbackQueue.push_back(cqn);
    loom_mutex_unlock(gCallbackLock);
}
Beispiel #9
0
static void enqueueFileChangeCallback(const char *path)
{
    CallbackQueueNote *cqn = lmNew(NULL) CallbackQueueNote();

    cqn->type = QNT_Change;
    cqn->text = utString(path);

    loom_mutex_lock(gCallbackLock);
    gCallbackQueue.push_back(cqn);
    loom_mutex_unlock(gCallbackLock);
}
Beispiel #10
0
ConstructorInfo *BinReader::readConstructor(Type *type)
{
    ConstructorInfo *cinfo = lmNew(NULL) ConstructorInfo();

    cinfo->declaringType = type;

    readMethodBase(cinfo);

    cinfo->memberType.constructor = true;
    cinfo->type = getType("system.Function");
    cinfo->defaultConstructor = bytes->readBoolean();

    return cinfo;
}
Beispiel #11
0
void BinWriter::writeType(json_t *jtype)
{
    TypeIndex *tindex = lmNew(NULL) TypeIndex;

    typeIndexes.push_back(tindex);

    tindex->position = bytes.getPosition();

    utString package = json_string_value(json_object_get(jtype, "package"));
    utString name    = json_string_value(json_object_get(jtype, "name"));

    utString fullname = package;
    fullname += ".";
    fullname += name;

    tindex->iFullName = poolString(fullname.c_str());

    int itype        = poolJString(json_object_get(jtype, "type"));
    int ipackagename = poolString(package.c_str());
    int iname        = poolString(name.c_str());

    json_t *jtypeid = json_object_get(jtype, "typeid");
    assert(jtypeid && json_is_number(jtypeid));

    int itypeid = (int)json_number_value(jtypeid);

    int isource     = -1;
    int ilinenumber = -1;

    json_t *jsource = json_object_get(jtype, "source");

    if (jsource && json_is_string(jsource))
    {
        isource     = poolString(json_string_value(jsource));
        ilinenumber = (int)json_integer_value(json_object_get(jtype, "line"));
    }

    bytes.writeInt(itype);
    bytes.writeInt(ipackagename);
    bytes.writeInt(iname);
    bytes.writeInt(itypeid);
    bytes.writeInt(isource);
    bytes.writeInt(ilinenumber);

    writeClass(jtype);

    tindex->length = bytes.getPosition() - tindex->position;
}
Beispiel #12
0
static loom_asset_t *loom_asset_getAssetByName(const char *name, int create)
{
    utHashedString key        = platform_normalizePath(name);
    loom_asset_t   **assetPtr = gAssetHash.get(key);
    loom_asset_t   *asset     = assetPtr ? *assetPtr : NULL;

    if ((asset == NULL) && create)
    {
        // Create one.
        asset       = lmNew(gAssetAllocator) loom_asset_t;
        asset->name = strdup(name);
        gAssetHash.insert(key, asset);
    }

    return asset;
}
Beispiel #13
0
JSON* JSON::getObjectNew(const char *key)
{
    if (!_json)
    {
        return NULL;
    }

    json_t *jobject = json_object_get(_json, key);

    if (!jobject || !json_is_object(jobject))
    {
        return NULL;
    }

    return lmNew(NULL) JSON(jobject);
}
Beispiel #14
0
JSON* JSON::getArrayArrayNew(int index)
{
    if (!isArray())
    {
        return NULL;
    }

    json_t *object = json_array_get(_json, index);

    if (!object || !json_is_array(object))
    {
        return NULL;
    }

    return lmNew(NULL) JSON(object);
}
Beispiel #15
0
JSON* JSON::getArrayNew(const char *key)
{
    if (!_json)
    {
        return NULL;
    }

    json_t *jarray = json_object_get(_json, key);

    if (!jarray || !json_is_array(jarray))
    {
        return NULL;
    }

    return lmNew(NULL) JSON(jarray);
}
Beispiel #16
0
   // Instate new bits/type to the asset.
   void instate(int _type, void *bits, LoomAssetCleanupCallback dtor)
   {
      // Swap in a new blob.
      if(blob)
         blob->decRef();
      blob = lmNew(gAssetAllocator) loom_assetBlob_t();
      blob->incRef();

      blob->bits = bits;
      blob->dtor = dtor;

      // Update the type.
      type = _type;

      // We're by definition loaded at this point.
      state = loom_asset_t::Loaded;

      // Fire subscribers.
      loom_asset_notifySubscribers(name.c_str());
   }
Beispiel #17
0
static loom_asset_t *loom_asset_getAssetByName(const char *name, int create)
{
    loom_mutex_lock(gAssetLock);
    static char normalized[4096];
    strncpy(normalized, name, sizeof(normalized));
    platform_normalizePath(normalized);
    utHashedString key        = normalized;
    loom_mutex_unlock(gAssetLock);
    loom_asset_t   **assetPtr = gAssetHash.get(key);
    loom_asset_t   *asset     = assetPtr ? *assetPtr : NULL;

    if ((asset == NULL) && create)
    {
        // Create one.
        asset       = lmNew(gAssetAllocator) loom_asset_t;
        asset->name = name;
        gAssetHash.insert(key, asset);
    }

    return asset;
}
Beispiel #18
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);
}
Beispiel #19
0
// Take a snapshot of the state of all our tracked files. This snapshot can
// then be compared to identify changes.
static utArray<FileEntry> *generateFileState(const char *root)
{
    utArray<FileEntry> *list = lmNew(NULL) utArray<FileEntry>();

    // Walk files in assets and src.
    char buffer[2048];

    sprintf(buffer, "%s%s%s", root, platform_getFolderDelimiter(), "assets");
    platform_walkFiles(buffer, handleFileStateWalkCallback, list);

    sprintf(buffer, "%s%s%s", root, platform_getFolderDelimiter(), "src");
    platform_walkFiles(buffer, handleFileStateWalkCallback, list);

    sprintf(buffer, "%s%s%s", root, platform_getFolderDelimiter(), "bin");
    platform_walkFiles(buffer, handleFileStateWalkCallback, list);

    // Sort the list into canonical order.
    list->sort(compareFileEntryBool);

    // Return the list.
    return list;
}
Beispiel #20
0
    const BitmapData* BitmapData::fromAsset(const char* name)
    {
        loom_asset_image_t* img = static_cast<loom_asset_image_t*>(loom_asset_lock(name, LATImage, 1));
        loom_asset_unlock(name);

        if (img == NULL)
            return NULL;

        BitmapData* result = lmNew(NULL) BitmapData(
            (size_t)img->width,
            (size_t)img->height
        );

        if (result == NULL) {
            lmLogError(gGFXLogGroup, "Unable to allocate memory for BitmapData asset data");
            return NULL;
        }

        memcpy(result->data, img->bits, img->width * img->height * DATA_BPP);

        return result;
    }
Beispiel #21
0
MethodInfo *BinReader::readMethodInfo(Type *type)
{
    MethodInfo *methodInfo = lmNew(NULL) MethodInfo();

    methodInfo->declaringType = type;

    readMethodBase(methodInfo);

    Type *retType = NULL;
    if (bytes->readBoolean())
    {
        retType = getType(readPoolString());
    }

    methodInfo->memberType.method = true;
    methodInfo->type = getType("system.Function");

    if (retType)
    {
        methodInfo->setReturnType(retType);
    }

    return methodInfo;
}
Beispiel #22
0
Assembly *BinReader::loadExecutable(LSLuaState *_vm, utByteArray *byteArray)
{
    sBytes = byteArray;
    vm     = _vm;

    // load up the string pool
    readStringPool();

    // read the type table

    int numTypes = sBytes->readInt();

    for (UTsize i = 0; i < (UTsize)numTypes; i++)
    {
        TypeIndex *tindex = lmNew(NULL) TypeIndex;
        tindex->type     = NULL;
        tindex->refIdx   = sBytes->readInt();
        tindex->fullName = readPoolString();

        // within the ref
        tindex->position = sBytes->readInt();
        tindex->length   = sBytes->readInt();
        types.insert(utHashedString(tindex->fullName), tindex);
    }

    // load up reference assemblies
    // write out the number of references
    int numRefs = sBytes->readInt();

    for (int i = 0; i < numRefs; i++)
    {
        Reference *ref = lmNew(NULL) Reference;
        ref->name     = readPoolString();

        lmAssert(ref->name[0] != 0, "Assembly reference name is empty, try recompiling the .loom executable");

        ref->length   = sBytes->readInt();
        ref->position = sBytes->readInt();
        ref->loaded   = false;
        ref->assembly = NULL;
        
        references.insert(utHashedString(ref->name), ref);

        // offset the types to global position
        for (UTsize j = 0; j < types.size(); j++)
        {
            TypeIndex *tindex = types.at(j);

            if (tindex->refIdx == (int)i)
            {
                tindex->position += ref->position;
            }
        }
    }

    Assembly *assembly = NULL;

    // declare types
    for (UTsize i = 0; i < types.size(); i++)
    {
        TypeIndex *tindex = types.at(i);
        tindex->type = lmNew(NULL) Type();
    }

    for (UTsize i = 0; i < references.size(); i++)
    {
        Reference *ref = references.at(i);
        if (ref->loaded)
        {
            continue;
        }

        sBytes->setPosition(ref->position);
        BinReader reader;
        Assembly  *rassembly = reader.readAssembly(vm, sBytes);
        ref->assembly = rassembly;
        if (!assembly)
        {
            assembly = rassembly;
        }
    }

    // cleanup
    for (UTsize i = 0; i < references.size(); i++)
    {
        Reference *ref = references.at(i);
        if (!ref->assembly)
            continue;
        ref->assembly->freeByteCode();
    }
    
    sBytes = NULL;
    
	if (stringBuffer)
    {
        lmFree(NULL, (void*)stringBuffer);
		stringBuffer = NULL;
	}
    
	stringPool.clear();
    references.clear();
    types.clear();
    
	vm = NULL;

    return assembly;
}
PropertyInfo *PropertyInfoReader::deserializePropertyInfo(Type   *declaringType,
                                                          json_t *json)
{
    PropertyInfo *pi = lmNew(NULL) PropertyInfo();

    MemberInfoReader::deserialize(pi, json);

    // handle attr
    json_t *marray = json_object_get(json, "propertyattributes");

    for (size_t i = 0; i < json_array_size(marray); i++)
    {
        utString modifier = json_string_value(json_array_get(marray, i));

        if (modifier == "static")
        {
            pi->attr.isStatic = true;
        }
        else if (modifier == "public")
        {
            pi->attr.isPublic = true;
        }
        else if (modifier == "private")
        {
            pi->attr.isPrivate = true;
        }
        else if (modifier == "protected")
        {
            pi->attr.isProtected = true;
        }
        else if (modifier == "native")
        {
            pi->attr.isNative = true;
        }
    }

    utString stype = json_string_value(json_object_get(json, "type"));
    if (stype.size() > 0)
    {
        // a shortcut?
        pi->type =
            declaringType->getModule()->getAssembly()->getLuaState()->getType(
                stype.c_str());
        assert(pi->type);
    }

    json_t *getter = json_object_get(json, "getter");
    json_t *setter = json_object_get(json, "setter");

    if (getter)
    {
        MethodBase *m = NULL;
        m = MethodReader::deserializeMethodInfo(declaringType, getter);
        assert(m->isMethod());
        pi->getter = (MethodInfo *)m;

        m->setPropertyInfo(pi);
    }

    if (setter)
    {
        MethodBase *m = NULL;
        m = MethodReader::deserializeMethodInfo(declaringType, setter);
        assert(m->isMethod());
        pi->setter = (MethodInfo *)m;

        m->setPropertyInfo(pi);
    }

    json_t *ttypes = json_object_get(json, "templatetypes");
    if (ttypes && json_is_object(ttypes))
    {
        TemplateInfo *info = MemberInfoReader::readTemplateTypeInfo(ttypes);
        assert(info);
        info->resolveTypes(Assembly::getAssembly(declaringType)->getLuaState());
        pi->setTemplateInfo(info);
    }


    return pi;
}
Beispiel #24
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;
}
Beispiel #25
0
void DisplayObject::render(lua_State *L) {
    // Disable reentrancy for this function (read: don't cache to texture while caching to a texture)
    if (cacheAsBitmapInProgress) return;

    // Clear and free the cached image if the conditions apply
    if ((!cacheAsBitmap || !cacheAsBitmapValid) && cachedImage != NULL) {
        Quad* quad = static_cast<Quad*>(cachedImage);

        lmAssert(quad != NULL, "Cached image is invalid");

        GFX::Texture::dispose(quad->getNativeTextureID());
        quad->setNativeTextureID(-1);

        lmDelete(NULL, quad);
        cachedImage = NULL;
        cacheAsBitmapValid = false;
    }

    // Cache the contents into an image if the conditions apply
    if (cacheAsBitmap && !cacheAsBitmapValid && cachedImage == NULL) {
        cacheAsBitmapInProgress = true;
        
        // Used for displaying the texture
        Quad* quad = lmNew(NULL) Quad();
        
        // Setup for getmember
        lualoom_pushnative<DisplayObject>(L, this);
        
        // Push function and arguments
        lualoom_getmember(L, -1, "getBounds");
        lualoom_pushnative<DisplayObject>(L, this);
        lua_pushnil(L);
        // Call getBounds
        lua_call(L, 2, 1);
        
        // Returned result
        Loom2D::Rectangle *bounds = (Loom2D::Rectangle*) lualoom_getnativepointer(L, -1);
        cacheAsBitmapOffsetX = bounds->x;
        cacheAsBitmapOffsetY = bounds->y;
        lmscalar fracWidth = bounds->width;
        lmscalar fracHeight = bounds->height;

        // pop bounds Rectangle and the DisplayObject at the top
        lua_pop(L, 1+1);

        if (cacheApplyScale)
        {
            fracWidth *= scaleX;
            fracHeight *= scaleY;
        }

        // Convert to integers for the following math
        int texWidthI = static_cast<int>(ceil(fracWidth));
        int texHeightI = static_cast<int>(ceil(fracHeight));

        // Calculate power of 2 sizes
        if (cacheUseTexturesPot)
        {
            _UT_UTHASHTABLE_POW2(texWidthI);
            _UT_UTHASHTABLE_POW2(texHeightI);
        }

        // Calculate the resulting scale (as a consequence of pow2 sizes)
        // Used for 'trans' matrix
        lmscalar calcScaleX = texWidthI / bounds->width;
        lmscalar calcScaleY = texHeightI / bounds->height;

        // Setup texture
        TextureInfo *tinfo = Texture::initEmptyTexture(texWidthI, texHeightI);
        Texture::clear(tinfo->id, 0x000000, 0);
        tinfo->smoothing = TEXTUREINFO_SMOOTHING_BILINEAR;
        tinfo->wrapU = TEXTUREINFO_WRAP_CLAMP;
        tinfo->wrapV = TEXTUREINFO_WRAP_CLAMP;
        TextureID id = tinfo->id;

        // Setup quad for rendering the texture
        quad->setNativeTextureID(id);
        
        VertexPosColorTex* qv;

        qv = &quad->quadVertices[0];  qv->x =                    0;  qv->y =                     0;  qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 0; qv->v = 0;
        qv = &quad->quadVertices[1];  qv->x = (float)bounds->width;  qv->y =                     0;  qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 1; qv->v = 0;
        qv = &quad->quadVertices[2];  qv->x =                    0;  qv->y = (float)bounds->height;  qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 0; qv->v = 1;
        qv = &quad->quadVertices[3];  qv->x = (float)bounds->width;  qv->y = (float)bounds->height;  qv->z = 0; qv->abgr = 0xFFFFFFFF; qv->u = 1; qv->v = 1;
        quad->setNativeVertexDataInvalid(false);

        lmAssert(Texture::getRenderTarget() == -1, "Unsupported render target state: %d", Texture::getRenderTarget());

        // Set render target to texture
        Texture::setRenderTarget(id);
        
        // Shift the contents down and to the right so that the elements extending
        // past the left and top edges don't get cut off, ignore other existing transforms
        Matrix trans;
        trans.translate(-cacheAsBitmapOffsetX, -cacheAsBitmapOffsetY);

        trans.scale(calcScaleX, calcScaleY);

        // Setup for Graphics::render
        lualoom_pushnative<DisplayObject>(L, this);
        lualoom_pushnative<Matrix>(L, &trans);
        lua_pushnumber(L, 1);

        // Render the contents into the texture
        Graphics::render(L);

        // Pop previous arguments
        lua_pop(L, 3);

        // Restore render target
        Texture::setRenderTarget(-1);

        // Set valid cached state
        cachedImage = quad;
        cacheAsBitmapValid = true;
        cacheAsBitmapInProgress = false;
    }
}
Beispiel #26
0
void TypeReader::deserializeClass(Type *type, json_t *classJSON)
{
    utString sbaseType = json_string_value(
        json_object_get(classJSON, "baseType"));

    if (sbaseType.size() > 0)
    {
        Type *baseType =
            type->getModule()->getAssembly()->getLuaState()->getType(
                sbaseType.c_str());
        lmAssert(baseType != NULL, "Unable to resolve type '%s' referenced as base of type '%s'",
                 sbaseType.c_str(), type->getFullName().c_str());
        type->setBaseType(baseType);
    }

    json_t *jinterfaces = json_object_get(classJSON, "interfaces");

    for (size_t i = 0; i < json_array_size(jinterfaces); i++)
    {
        json_t   *o     = json_array_get(jinterfaces, i);
        utString sface  = json_string_value(o);
        Type     *itype = type->getModule()->getAssembly()->getLuaState()->getType(
            sface.c_str());
        assert(itype);
        type->addInterface(itype);
    }

    json_t *jdelegateTypes = json_object_get(classJSON, "delegateTypes");

    for (size_t i = 0; i < json_array_size(jdelegateTypes); i++)
    {
        json_t   *o     = json_array_get(jdelegateTypes, i);
        utString stype  = json_string_value(o);
        Type     *itype = type->getModule()->getAssembly()->getLuaState()->getType(
            stype.c_str());
        assert(itype);
        type->addDelegateType(itype);
    }

    utString sdelegateReturnType = json_string_value(
        json_object_get(classJSON, "delegateReturnType"));

    if (sdelegateReturnType.size() > 0)
    {
        Type *delegateReturnType =
            type->getModule()->getAssembly()->getLuaState()->getType(
                sdelegateReturnType.c_str());
        assert(delegateReturnType);
        type->setDelegateReturnType(delegateReturnType);
    }

    // meta data

    MemberInfoReader::deserializeMetaInfo(type, json_object_get(classJSON, "metainfo"));

    // handle imports
    json_t *iarray = json_object_get(classJSON, "imports");
    for (size_t i = 0; i < json_array_size(iarray); i++)
    {
        json_t   *jimport = json_array_get(iarray, i);
        utString import   = json_string_value(jimport);

        Type *timport =
            type->getModule()->getAssembly()->getLuaState()->getType(
                import.c_str());
        type->addImport(timport);
    }

    json_t *jconstructor = json_object_get(classJSON, "constructor");
    if (jconstructor)
    {
        MethodBase *m = NULL;
        m = MethodReader::deserializeConstructorInfo(type, jconstructor);
        type->addMember(m);
    }

    // handle fields
    json_t *farray = json_object_get(classJSON, "fields");
    for (size_t i = 0; i < json_array_size(farray); i++)
    {
        json_t    *fo = json_array_get(farray, i);
        FieldInfo *f  = FieldInfoReader::deserializeFieldInfo(type, fo);
        type->addMember(f);
    }

    // handle properties

    json_t *parray = json_object_get(classJSON, "properties");
    for (size_t i = 0; i < json_array_size(parray); i++)
    {
        json_t       *po = json_array_get(parray, i);
        PropertyInfo *p  = PropertyInfoReader::deserializePropertyInfo(type, po);
        type->addMember(p);
    }

    // handle methods
    farray = json_object_get(classJSON, "methods");
    for (size_t i = 0; i < json_array_size(farray); i++)
    {
        json_t *fo = json_array_get(farray, i);

        MethodBase *m = NULL;
        m = MethodReader::deserializeMethodInfo(type, fo);
        type->addMember(m);
    }

    ByteCode *byteCode;

    byteCode = lmNew(NULL) ByteCode();
    byteCode->setBase64(utString(json_string_value(json_object_get(classJSON, "bytecode_staticinitializer"))));
#if LOOM_ENABLE_JIT
    byteCode->setBase64(utString(json_string_value(json_object_get(classJSON, "bytecode_staticinitializer_fr2"))));
#endif
    type->setBCStaticInitializer(byteCode);


    byteCode = lmNew(NULL) ByteCode();
    byteCode->setBase64(utString(json_string_value(json_object_get(classJSON, "bytecode_instanceinitializer"))));
#if LOOM_ENABLE_JIT
    byteCode->setBase64(utString(json_string_value(json_object_get(classJSON, "bytecode_instanceinitializer_fr2"))));
#endif
    type->setBCInstanceInitializer(byteCode);
}
Beispiel #27
0
void BinWriter::writeAssembly(json_t *json)
{
    // reserve 32 megs
    bytes.reserve(1024 * 1024 * 32);

    int itype = poolJString(json_object_get(json, "type"));

    const char *uid = json_string_value(json_object_get(json, "uid"));

    binWriters.insert(utHashedString(uid), this);

    int iname       = poolJString(json_object_get(json, "name"));
    int iversion    = poolJString(json_object_get(json, "version"));
    int iuid        = poolString(uid);
    int iloomconfig = 0;

    bool executable = false;
    if (json_object_get(json, "executable") && json_is_true(json_object_get(json, "executable")))
    {
        executable = true;
    }

    iloomconfig = poolJString(json_object_get(json, "loomconfig"));

    bool jit = false;
    if (json_object_get(json, "jit") && json_is_true(json_object_get(json, "jit")))
    {
        jit = true;
    }

    bool debugbuild = false;
    if (json_object_get(json, "debugbuild") && json_is_true(json_object_get(json, "debugbuild")))
    {
        debugbuild = true;
    }

    // basic info
    bytes.writeInt(itype);
    bytes.writeInt(iname);
    bytes.writeInt(iversion);
    bytes.writeInt(iuid);
    bytes.writeInt(iloomconfig);

    // write out flags
    bytes.writeBoolean(executable);
    bytes.writeBoolean(jit);
    bytes.writeBoolean(debugbuild);

    // recursively write references

    json_t *ref_array = json_object_get(json, "references");
    lmAssert(ref_array, "Error with executable assembly, missing references section");

    // write number of references
    bytes.writeInt((int)json_array_size(ref_array));

    for (size_t j = 0; j < json_array_size(ref_array); j++)
    {
        json_t     *jref    = json_array_get(ref_array, j);
        json_t     *jbinary = json_object_get(jref, "binary");
        const char *refname = json_string_value(json_object_get(jref, "name"));
        const char *refuid = json_string_value(json_object_get(jref, "uid"));

        bytes.writeInt(poolString(refname));
        bytes.writeInt(poolString(refuid));

        // already referenced
        if (binWriters.get(utHashedString(refuid)))
        {
            continue;
        }

        if (executable)
        {
            lmAssert(jbinary, "Error with linked assembly %s, missing binary section", refname);
            utString  refjson  = (const char *)utBase64::decode64(json_string_value(jbinary)).getData().ptr();
            BinWriter *bwriter = lmNew(NULL) BinWriter(refname);
            lmAssert(refjson.length() > 0, "Refjson should not be empty! %s", json_string_value(jbinary));
            bwriter->writeAssembly(refjson.c_str(), (int)refjson.length());
        }
    }

    writeModules(json);
}
Beispiel #28
0
// Service our connection to the asset agent.
static void loom_asset_serviceServer()
{
    loom_mutex_lock(gAssetServerSocketLock);

    // Try to connect to the asset server if we aren't already, and it is set.
    if ((gAssetServerSocket == NULL) &&
        ((ASSET_STREAM_HOST != NULL) && (strlen(ASSET_STREAM_HOST) > 0)) &&
        ((platform_getMilliseconds() - gAssetServerLastConnectTryTime) > gAssetServerConnectTryInterval))
    {
        lmLog(gAssetLogGroup, "Attempting to stream assets from %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT);
        gAssetServerLastConnectTryTime = platform_getMilliseconds();
        gAssetServerSocket             = loom_net_openTCPSocket(ASSET_STREAM_HOST, ASSET_STREAM_PORT, 0);
        gAssetConnectionOpen           = false;
        loom_asset_notifyPendingCountChange();

        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    if ((gAssetServerSocket != NULL) && (gAssetConnectionOpen == false))
    {
        // We are waiting on the connection, see if it's writable... If not, return.
        if (loom_net_isSocketWritable(gAssetServerSocket) == 0)
        {
            loom_mutex_unlock(gAssetServerSocketLock);
            return;
        }

        if (loom_net_isSocketDead(gAssetServerSocket) == 1)
        {
            // Might be DOA, ie, connect failed.
            lmLog(gAssetLogGroup, "Failed to connect to asset server %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT);

            loom_net_closeTCPSocket(gAssetServerSocket);

            gAssetServerSocket = NULL;
            lmSafeDelete(NULL, gAssetProtocolHandler);
            gAssetConnectionOpen = false;
            loom_asset_notifyPendingCountChange();
            loom_mutex_unlock(gAssetServerSocketLock);
            return;
        }

        lmLog(gAssetLogGroup, "Successfully connected to asset server %s:%d!", ASSET_STREAM_HOST, ASSET_STREAM_PORT);

        // Do this now to avoid clobbering error state and seeing the socket as
        // "open" when it is really dead.
        loom_net_enableSocketKeepalive(gAssetServerSocket);
        gAssetConnectionOpen = true;
        loom_asset_notifyPendingCountChange();

        // Make sure we have a protocol handler.
        if (!gAssetProtocolHandler)
        {
            gAssetProtocolHandler = lmNew(NULL) AssetProtocolHandler(gAssetServerSocket);
            gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolFileMessageListener());
            gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolCommandListener());
        }

        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // See if the socket is dead, and if so, clean up.
    if ((gAssetServerSocket != NULL) && (loom_net_isSocketDead(gAssetServerSocket) == 1))
    {
        lmLog(gAssetLogGroup, "Lost connection to asset server.");
        loom_net_closeTCPSocket(gAssetServerSocket);
        gAssetServerSocket = NULL;
        lmSafeDelete(NULL, gAssetProtocolHandler);
        gAssetConnectionOpen = false;
        loom_asset_notifyPendingCountChange();
        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // Bail if we don't have a connection.
    if (!gAssetServerSocket || !gAssetConnectionOpen)
    {
        loom_mutex_unlock(gAssetServerSocketLock);
        return;
    }

    // Ping if we need to.
    if (platform_getMilliseconds() - gAssetServerLastPingTime > gAssetServerPingInterval)
    {
        gAssetProtocolHandler->sendPing();
        gAssetServerLastPingTime = platform_getMilliseconds();
    }

    // Service the asset server connection.
    gAssetProtocolHandler->process();

    loom_mutex_unlock(gAssetServerSocketLock);
}
Beispiel #29
0
// Compare two snapshots of file state from the above function and return a
// description of any changes.
static utArray<FileEntryDelta> *compareFileEntries(utArray<FileEntry> *oldList, utArray<FileEntry> *newList)
{
    UTsize oldIndex = 0, newIndex = 0;

    utArray<FileEntryDelta> *deltaList = lmNew(NULL) utArray<FileEntryDelta>();

    // If we have no lists, it's a trivial case.
    if (!oldList && !newList)
    {
        return deltaList;
    }

    // If we only have one list, then it's either all adds or all removes.
    if (oldList && !newList)
    {
        for (UTsize i = 0; i < oldList->size(); i++)
        {
            FileEntryDelta fed;
            fed.action = FileEntryDelta::Removed;
            fed.path   = oldList->at(i).path;
            deltaList->push_back(fed);
        }

        return deltaList;
    }

    if (!oldList && newList)
    {
        for (UTsize i = 0; i < newList->size(); i++)
        {
            FileEntryDelta fed;
            fed.action = FileEntryDelta::Added;
            fed.path   = newList->at(i).path;
            deltaList->push_back(fed);
        }

        return deltaList;
    }


    // Walk the two lists (which are ordered) and generate FED's based on
    // mismatches.
    for ( ; ; )
    {
        // If we run off the end of either list, deal with the tail of the
        // other list after this block.
        if ((oldIndex >= oldList->size()) || (newIndex >= newList->size()))
        {
            break;
        }

        // Do the comparison...
        const FileEntry& oldEntry      = oldList->at(oldIndex);
        const FileEntry& newEntry      = newList->at(newIndex);
        int              compareResult = compareFileEntry(oldEntry, newEntry);

        FileEntryDelta deltaItem;

        if (compareResult < 0)
        {
            deltaItem.action = FileEntryDelta::Removed;
            deltaItem.path   = oldEntry.path;
            deltaList->push_back(deltaItem);

            oldIndex++;
            continue;
        }
        else if (compareResult > 0)
        {
            deltaItem.action = FileEntryDelta::Added;
            deltaItem.path   = newEntry.path;
            deltaList->push_back(deltaItem);

            newIndex++;
            continue;
        }
        else
        {
            // Match on path, check for other kinds of change.
            if (oldEntry.modifiedTime != newEntry.modifiedTime)
            {
                // TODO: check hash.

                // Report a change.
                deltaItem.action = FileEntryDelta::Modified;
                deltaItem.path   = newEntry.path;
                deltaList->push_back(deltaItem);
            }

            // Advance both.
            oldIndex++, newIndex++;
            continue;
        }
    }

    // Make sure we emit deletions for all remaining old items.
    while (oldIndex < oldList->size())
    {
        FileEntryDelta deltaItem;
        deltaItem.action = FileEntryDelta::Removed;
        deltaItem.path   = oldList->at(oldIndex).path;

        deltaList->push_back(deltaItem);

        oldIndex++;
    }

    // And emit additions for all remaining new items.
    while (newIndex < newList->size())
    {
        FileEntryDelta deltaItem;
        deltaItem.action = FileEntryDelta::Added;
        deltaItem.path   = newList->at(newIndex).path;

        deltaList->push_back(deltaItem);

        newIndex++;
    }

    // If the delta list needed to be canonical, we would sort by path here.

    // Return it!
    return deltaList;
}
Beispiel #30
0
void BinWriter::writeExecutable(const char *path, json_t *sjson)
{
    stringPool.clear();
    binWriters.clear();

    utByteArray bytes;
    // reserve 32 megs
    bytes.reserve(1024 * 1024 * 32);

    const char *name = json_string_value(json_object_get(sjson, "name"));
    BinWriter *bexec = lmNew(NULL) BinWriter(name);
    bexec->writeAssembly(sjson);

    // write string pool
    bytes.writeInt((int)stringPool.size());

    // calculate entire buffer size of string pool
    int stringBufferSize = 0;
    for (UTsize i = 0; i < stringPool.size(); i++)
    {
        stringBufferSize += sizeof(int);                               // length
        stringBufferSize += (int)strlen(stringPool.keyAt(i).str().c_str()); // characters
    }

    // length of entire string buffer
    bytes.writeInt(stringBufferSize);

    for (UTsize i = 0; i < stringPool.size(); i++)
    {
        bytes.writeString(stringPool.keyAt(i).str().c_str());
    }

    // generate the type table
    utArray<TypeIndex *> types;
    for (UTsize i = 0; i < binWriters.size(); i++)
    {
        BinWriter *bref = binWriters.at(i);

        for (UTsize j = 0; j < bref->typeIndexes.size(); j++)
        {
            TypeIndex *tindex = bref->typeIndexes.at(j);
            tindex->refIdx = (int)i;
            types.push_back(tindex);
        }
    }

    // write the type table

    bytes.writeInt((int)types.size());

    for (UTsize i = 0; i < types.size(); i++)
    {
        TypeIndex *tindex = types.at(i);
        bytes.writeInt(tindex->refIdx);
        bytes.writeInt(tindex->iFullName);
        bytes.writeInt(tindex->position);
        bytes.writeInt(tindex->length);
    }

    // write out the number of references
    bytes.writeInt((int)binWriters.size());

    // write out reference table (which will allow random access if we want/need it)
    int position = bytes.getPosition() + (binWriters.size() * (sizeof(int) * 4));

    for (UTsize i = 0; i < binWriters.size(); i++)
    {
        BinWriter *bref = binWriters.at(i);
        // (interned) name
        utHashedString uid = binWriters.keyAt(i);
        bytes.writeInt(poolString(binWriters.at(i)->name.c_str()));
        // uid
        bytes.writeInt(poolString(binWriters.keyAt(i).str().c_str()));


        // length
        int length = bref->bytes.getPosition();
        bytes.writeInt(length);
        // position (offset from reference table)
        bytes.writeInt(position);
        position += length;
    }

    for (UTsize i = 0; i < binWriters.size(); i++)
    {
        BinWriter *bref = binWriters.at(i);
        bytes.writeBytes(&bref->bytes);
    }

    int dataLength = bytes.getPosition();

    Bytef *compressed = (Bytef *) lmAlloc(gBinWriterAllocator, dataLength);
    uLongf length = (uLongf) dataLength;
    int ok = compress(compressed, &length, (Bytef *) bytes.getDataPtr(), (uLong) dataLength);
    lmAssert(ok == Z_OK, "problem compressing executable assemby");

    bytes.clear();
    bytes.writeUnsignedInt(LOOM_BINARY_ID);
    bytes.writeUnsignedInt(LOOM_BINARY_VERSION_MAJOR);
    bytes.writeUnsignedInt(LOOM_BINARY_VERSION_MINOR);
    bytes.writeUnsignedInt((unsigned int)dataLength);

    utFileStream binStream;
    binStream.open(path, utStream::SM_WRITE);
    // write header
    binStream.write(bytes.getDataPtr(), sizeof(unsigned int) * 4);
    // write compressed data
    binStream.write(compressed, length);

    binStream.close();

    lmFree(gBinWriterAllocator, compressed);
}