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 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; }