void Vm::getMethodProp(const SObject &instance, const SObject &propName) { if (instance->getType() == Type::MODULE) { auto ob = Module::getProperty(instance, propName); assert(ob != nullptr && "Property does not exist"); VM_PUSH(ob); return; // do something about it } auto clsObj = std::dynamic_pointer_cast<ClassObject>(instance); auto classCo = clsObj->getCodeObject(); auto value = classCo->getValue(propName->toString()); assert(value != nullptr); VM_PUSH(value); }
void Contact::setData(SObject data) { SObject oldData = mData; mData = data; if (firstName() != oldData.value("firstName")) emit firstNameChanged(); if (lastName() != oldData.value("lastName")) emit lastNameChanged(); if (phoneNumber() != oldData.value("phoneNumber")) emit phoneNumberChanged(); // update avatar serial so QML reloads the image setAvatarSerial(avatarSerial() + 1); }
void DisplayList::DoRemove(SObject** link) { SObject* obj = *link; FLASHASSERT(obj); // Remove the contents of the old object if ( obj->drawn ) InvalidateRect(&obj->devBounds); obj->FreeChildren(); obj->Free(); // Remove from list if ( obj == button ) button = 0; *link = obj->above; FreeObject(obj); }
SObject* DisplayList::MoveObject(SObject* parent, PlaceInfo* info) { // See if there is already an object at this depth or find the insertion point SObject* obj = parent->bottomChild; while ( obj ) { if ( obj->depth >= info->depth ) break; obj = obj->above; } if ( obj ) { // We found an object at this depth if ( obj->depth != info->depth ) { FLASHASSERT(false); return 0; // don't move the wrong object } if (obj->puppet) return 0; // don't move the object if it's puppeted // Move the proper fields of the object obj->Modify(); if ( info->flags & splaceCharacter ) { // The type of sprite or button objects must never change if ( obj->character->type != info->character->type && (obj->character->type == spriteChar || info->character->type == spriteChar || obj->character->type == buttonChar || info->character->type == buttonChar) ) { FLASHASSERT(false); // this should never happen, there was a beta build where we did export like this, so prevent the crash } else { obj->character = info->character; } } if ( info->flags & splaceMatrix ) obj->xform.mat = info->mat; if ( info->flags & splaceColorTransform ) obj->xform.cxform = info->cxform; if ( info->flags & splaceRatio ) obj->ratio = info->ratio; } return obj; }
void Vm::callMethod(const SObject &instance, const SObject &funcName) { if (instance->getType() == Type::MODULE) { Vm::callModule(instance, funcName); return; } auto clsObj = std::dynamic_pointer_cast<ClassObject>(instance); assert(clsObj != nullptr); auto clsCo = clsObj->getCodeObject(); auto fnObj = clsCo->getValue(funcName->toString()); assert(fnObj != nullptr && "No function with such name!"); auto fn = std::dynamic_pointer_cast<FunctionObject>(fnObj); auto fnCo = fn->getCodeObject(clsCo); if (fn->isInit()) { assert(!clsObj->isInstance()); auto initCo = std::make_shared<CodeObject>(*clsCo); fnCo->setParent(initCo); } else { assert(clsObj->isInstance()); } pushCodeObject(fnCo); }
bool SObject::equal(const SObject &o) const { ASSERT(this != &o); ASSERT(getType() == o.getType()); switch (getType()) { case SDouble::TYPE: return staticCast<SDouble>()->_equal(*o.staticCast<SDouble>()); case SString::TYPE: return staticCast<SString>()->_equal(*o.staticCast<SString>()); case SPair::TYPE: return staticCast<SPair>()->_equal(*o.staticCast<SPair>()); case SEnv::TYPE: return staticCast<SEnv>()->_equal(*o.staticCast<SEnv>()); case SScriptFunction::TYPE: return staticCast<SScriptFunction>()->_equal(*o.staticCast<SScriptFunction>()); default: ASSERT(0); return false; } }
void DisplayList::FinishHold() // Compare the old and the new list // If an old object matches a new object, replace the new object with the old object { FLASHASSERT(holdParent); SObject** oldLink = &holdList; SObject** newLink = &holdParent->bottomChild; for (;;) { SObject* oldObj = *oldLink; SObject* newObj = *newLink; if ( !oldObj ) break; // we are done if ( !newObj || oldObj->depth < newObj->depth ) { if ( oldObj->depth >= 0x4000 ) { // This is a cloned object, it always gets copied to the new list FLASHASSERT(!newObj); // none of the new obj's should have a depth > 4000 *oldLink = oldObj->above; // remove from old list oldObj->above = *newLink; // place on new list *newLink = oldObj; } else { // Get rid of the old object DoRemove(oldLink); } } else if ( oldObj->depth == newObj->depth ) { // Compare these objects BOOL remove = true; if (oldObj->character == newObj->character && oldObj->ratio == newObj->ratio && oldObj->clipDepth == newObj->clipDepth) { // Check the matrix and cxform and ratio BOOL moved = !Equal(&oldObj->xform, &newObj->xform); if (!moved || oldObj->character->type == spriteChar) { if ( moved && !oldObj->puppet) { oldObj->Modify(); oldObj->xform = newObj->xform; //oldObj->ratio = newObj->ratio; } if ( button == newObj ) { FLASHASSERT(oldObj->state == buttonState); button = oldObj; //UpdateButton(obj, state); } remove = false; } } else if ( oldObj->ratio == newObj->ratio && (oldObj->character->type == spriteExternalChar || oldObj->character->type == spriteChar) && (newObj->character->type == spriteChar || newObj->character->type == spriteExternalChar)) { // we are dealing with externally loaded sprite // or an empty placeholder. It inherits the // sprite ratio of the sprite we are replacing. // This means that it goes away when the same // time the replaced sprite should have gone away if (!Equal(&oldObj->xform, &newObj->xform)) { if (!oldObj->puppet) { oldObj->Modify(); oldObj->xform = newObj->xform; } } remove = false; } if (!remove) { DoRemove(newLink); // delete the new obj *oldLink = oldObj->above; // remove from old list oldObj->above = *newLink; // place on new list *newLink = oldObj; continue; } newLink = &newObj->above; DoRemove(oldLink); } else { // Just look at the next new object FLASHASSERT(oldObj->depth > newObj->depth); newLink = &newObj->above; } } #ifdef EDITTEXT // Update edit texts on hold list SObject* obj = holdParent->bottomChild; while (obj) { if (obj->character && obj->character->type == editTextChar) { obj->editText->UpdateFromVariable(); } obj = obj->above; } #endif holdParent = 0; }
SObject* DisplayList::PlaceObject(SObject* parent, PlaceInfo* info) { // Find the insertion point SObject** link = &parent->bottomChild; for (;;) { SObject* obj = *link; if ( !obj ) break; if ( obj->depth >= info->depth ) { FLASHASSERT(obj->depth != info->depth); break; } link = &obj->above; } // Create a new object SObject* obj = CreateObject(); if ( !obj ) return 0; // Add to list obj->parent = parent; obj->above = *link; *link = obj; // Set up object obj->character = info->character; obj->xform = *info; obj->depth = info->depth; obj->ratio = info->ratio; obj->puppet = info->puppet; obj->drawn = false; obj->visible = true; obj->dragCenter = false; RectSetEmpty(&obj->dragConstraint); obj->dropTarget = NULL; obj->display = this; obj->bottomChild = 0; obj->edges = 0; obj->colors = 0; obj->state = 0; #ifdef EDITTEXT obj->editText = 0; #endif // If this is a movie clip and it has no name, // generate a default name if (obj->character->type == spriteChar && !info->name) { URLBuilder ub; ub.AppendString("instance"); ub.AppendInt(++instanceNameCount); obj->name = CreateStr(ub.buf); } else { // Regular processing: copy name if present obj->name = CreateStr(info->name); } obj->thread = parent ? parent->thread : 0; obj->clipDepth = info->flags & splaceDefineClip ? info->clipDepth : 0;//(info->flags & splaceDefineClip) != 0; obj->Modify(); switch ( obj->character->type ) { case buttonChar: { // Set up the button state int state = bsIdle; if ( obj->depth == buttonDepth && obj->parent == buttonParent && buttonCharacter == obj->character && obj->ratio == buttonRatio ) { // The button is currently being tracked FLASHASSERT(obj->character->type == buttonChar); button = obj; state = buttonState; } UpdateButton(obj, state); } break; #ifdef EDITTEXT case editTextChar: { obj->editText = new EditText(obj); if (holdParent != obj->parent) { // Not doing a hold... update value immediately obj->editText->UpdateFromVariable(); } // If there is a holdParent, the edit text's value will // be updated later. } break; #endif case spriteExternalChar: { ScriptThread *thread = 0; ScriptPlayer *player = obj->character->player; int startPos = 0; int len = 0; int numFrames = 0; if (info->flags & splaceCloneExternalSprite) { // means we are cloning an existing // external sprite if (player->len >= player->scriptLen) { // we only clone the external // sprite if it has been completely loaded // allocate full player instead of thread // it is easier to delete the external // sprite if it has its own player thread = new ScriptPlayer; startPos = player->startPos; len = player->len; numFrames = player->numFrames; thread->script = player->script; ((ScriptPlayer *) thread)->numFramesComplete = player->numFramesComplete; player = (ScriptPlayer *) thread; player->gotHeader = true; // add a ref count to the script // we don't want to duplicate it // so we want to make sure it's // protected from deletion for // cloned external sprites player->scriptRefCount = obj->character->player->scriptRefCount; player->ScriptAddRefCount(); } } else { // note that it's ok to have some of the // initial values of the len, etc. set // to zero. they will be set during pushdata thread = player; // add a ref count to the script // we don't want to duplicate it // so we want to make sure it's // protected from deletion for // cloned external sprites player->ScriptAddRefCount(); } if ( thread ) { thread->ClearState(); obj->thread = thread; thread->player = player; thread->layerDepth = obj->depth; thread->rootObject = obj; thread->SetDisplay(obj->display); thread->Attach(obj->character->player->script, startPos); thread->len = len; thread->startPos = startPos; thread->numFrames = numFrames; // for non cloned sprite this won't draw the frame // untill we push data into the script (this is ok) thread->DrawFrame(0, false); } } break; case spriteChar: { // Create a sprite thread ScriptThread* thread = new ScriptThread(); if ( thread ) { thread->ClearState(); obj->thread = thread; thread->player = obj->character->player; thread->layerDepth = obj->depth; thread->rootObject = obj; thread->SetDisplay(obj->display); thread->Attach(obj->character->data, 0); thread->len = obj->character->sprite.length; thread->startPos = 0; thread->numFrames = obj->character->sprite.numFrames; thread->DrawFrame(0, false); } } break; } return obj; }
void SObject::Arrive() { SObject *truedest = destination->Represents(); if(!truedest) { system = destination->Sys(); orbit = destination->OrbitDist(); period = destination->Period(); startpos = destination->OrbitPhase(); arrive_turn = destination->ArriveTurn(); depart_turn = destination->DepartTurn(); Trash(location); location = destination->Location(); Trash(destination); destination = destination->Destination(); Trash(target); target = NULL; distance = 0; } else if(truedest->SType() == SOBJECT_PLANET) { system = destination->system; orbit = destination->orbit; period = destination->period; startpos = destination->startpos; Trash(location); location = destination; truedest->See(Owner()); truedest->Know(Owner()); destination = NULL; } else if(truedest->SType() == SOBJECT_SYSTEM) { orbit = 6600; period = int(sqrt(double(orbit)*double(orbit)*double(orbit))); int xp = system->gxpos - destination->system->gxpos; int yp = system->gypos - destination->system->gypos; double tang = double(cur_game->turn) * double(256*256*256) / double(period); double nang = double(65536) * atan2(double(yp), double(xp)) / 2.0 / M_PIl; startpos = int(nang - tang); system->FleetLeaves((Fleet*)this); system = destination->system; system->FleetArrives((Fleet*)this); Trash(location); location = NULL; truedest->Know(Owner()); Trash(destination); destination = NULL; } else if(truedest->SType() == SOBJECT_FLEET && SType() == SOBJECT_FLEET && Owner() == truedest->Owner()) { Fleet *flt = (Fleet *)this; for(int shp=0; shp < flt->NumShips(); ++shp) ((Fleet*)truedest)->AddShip(flt->GetShip(shp)); if(cur_object == this) cur_object = truedest; panel_draw(); RemapPositions(flt, truedest); flt->RemoveShips(0); } else if(truedest->SType() == SOBJECT_FLEET && SType() == SOBJECT_FLEET) { Fleet *flt = (Fleet*)this; flt->Attack((Fleet*)truedest); system = destination->system; orbit = destination->orbit; period = destination->period; startpos = destination->startpos; Trash(location); location = destination->location; Trash(destination); destination = destination->destination; //FIXME! Two attacking each other! } else if(truedest->SType() == SOBJECT_FLEET) { system = destination->system; orbit = destination->orbit; period = destination->period; startpos = destination->startpos; Trash(location); location = destination->location; Trash(destination); destination = destination->destination; } }
void Vm::execCode(const SCodeObject &c) { Vm::pushCodeObject(c); // TODO, if coStack_ is empty, push a NIL object // This is in case the user tries to assign a value to a void function call while (!coStack_.empty()) { if (*opId_ >= static_cast<int>(vecOp_->size())) { popCodeObject(); continue; } SObject i; SObject j; Op op = (*vecOp_)[*opId_]; Opc opc = op.opc_; switch (opc) { case Opc::ADD: DEBUG("OP::ADD"); BIN_OP(+); break; case Opc::SUB: DEBUG("OP::SUB"); BIN_OP(-); break; case Opc::UNARY_SUB: DEBUG("OP::UNARY_SUB"); i = VM_POP(); j = std::make_shared<IntegerObject>(0); VM_PUSH(*j - i); break; case Opc::MOD: DEBUG("OP::MOD"); BIN_OP(% ); break; case Opc::LT: DEBUG("OP::LT"); BIN_OP(< ); break; case Opc::GT: DEBUG("OP::GT"); BIN_OP(> ); break; case Opc::LEQ: DEBUG("OP::LEQ"); BIN_OP(<= ); break; case Opc::GEQ: DEBUG("OP::GEQ"); BIN_OP(>= ); break; case Opc::EQ: DEBUG("OP::EQ"); BIN_OP(== ); break; case Opc::AND: DEBUG("OP::AND"); BIN_OP(&&); break; case Opc::OR: DEBUG("OP::OR"); BIN_OP(|| ); break; case Opc::NEQ: DEBUG("OP::NEQ"); BIN_OP(!= ); break; case Opc::MULT: DEBUG("OP::MULT"); BIN_OP(*); break; case Opc::DIV: DEBUG("OP::DIV"); BIN_OP(/ ); break; case Opc::POWER: DEBUG("OP::POWER"); j = VM_POP(); i = VM_POP(); VM_PUSH(std::make_shared<DoubleObject>(pow(i->getDouble(), j->getDouble()))); break; case Opc::WHILE: { DEBUG("OP::WHILE"); assert(op.hasArgA()); SCodeObject co = codeObject_->getChild(op.getArgA()); co->setParent(codeObject_); pushCodeObject(co); continue; } /*TODO, Better to not have BREAK and CONTINUE in the vm. */ case Opc::BREAK: DEBUG("OP::BREAK") while (codeObject_->getBlockType() != BlockType::WHILE) { popCodeObject(); } popCodeObject(); break; case Opc::CONTINUE: DEBUG("OP::CONTINUE") while (codeObject_->getBlockType() != BlockType::WHILE) { popCodeObject(); } opId_ = 0; continue; case Opc::LOAD_CONSTANT: DEBUG("OP::PUSH_CONSTANT"); assert(op.hasArgA()); i = codeObject_->getConst(op.getArgA()); VM_PUSH(i); break; case Opc::LOAD_VALUE: DEBUG("OP::LOAD_VALUE"); assert(op.hasStr()); i = codeObject_->getValue(op.getStr()); assert(i != nullptr); VM_PUSH(i); break; case Opc::STORE_VALUE: DEBUG("OP::STORE_VALUE"); assert(op.hasStr()); i = VM_POP(); codeObject_->storeValue(op.getStr(), i); break; case Opc::JMP_IF_ELSE: { DEBUG("OP::JMP_IF_ELSE"); INCR_OP(); assert(op.hasArgA()); auto v = VM_POP(); if (v->isTrue()) { SCodeObject ic = codeObject_->getChild(op.getArgA()); ic->setParent(codeObject_); pushCodeObject(ic); } else { if (op.hasArgB()) { SCodeObject ec = codeObject_->getChild(op.getArgB()); ec->setParent(codeObject_); pushCodeObject(ec); } } continue; } case Opc::INIT_INSTANCE: { auto classCo = codeObject_->getParent(); auto classO = std::make_shared<ClassObject>(classCo); VM_PUSH(classO); INCR_OP(); continue; } case Opc::CALL_METHOD: { DEBUG("OP::CALL_METHOD"); INCR_OP(); auto method = VM_POP(); auto instance = VM_POP(); Vm::callMethod(instance, method); continue; } case Opc::DOT: { DEBUG("OP::DOT"); i = VM_POP(); j = VM_POP(); Vm::getMethodProp(j, i); break; } case Opc::CALL: { DEBUG("OP::CALL"); assert(op.hasStr()); auto fnob = codeObject_->getValue(op.getStr()); assert(fnob != nullptr); INCR_OP(); Vm::callFunc(fnob); continue; } case Opc::RETURN: { // TODO, clean the stack assert(op.hasArgA()); DEBUG("OP::RETURN"); while (codeObject_->getBlockType() != BlockType::FUNCTION) { popCodeObject(); } popCodeObject(); continue; } default: assert(false && "Not Implemented Yet!"); break; } INCR_OP(); // increment the op } // end switch, end for }
SObject IntegerObject::operator/(const SObject &rhs) { return std::make_shared<DoubleObject>(getInt() / rhs->getDouble()); }
SObject IntegerObject::operator%(const SObject &rhs) { return std::make_shared<IntegerObject>(getInt() % rhs->getInt()); }