Skip to content

Commit

Permalink
Construct tags inside the VM
Browse files Browse the repository at this point in the history
  • Loading branch information
alexp-sssup committed Mar 29, 2011
1 parent 1e6b518 commit 8bebf6b
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 123 deletions.
192 changes: 93 additions & 99 deletions parsing/tags.cpp
Expand Up @@ -42,6 +42,7 @@ using namespace std;
using namespace lightspark;

extern TLSDATA ParseThread* pt;
extern TLSDATA bool isVmThread;

Tag* TagFactory::readTag()
{
Expand Down Expand Up @@ -1252,138 +1253,131 @@ bool PlaceObject2Tag::list_orderer::operator ()(const std::pair<PlaceInfo, Displ
return a.first.Depth < b.first.Depth;
}

void PlaceObject2Tag::assignObjectToList(DisplayObject* obj, MovieClip* parent,
list<pair<PlaceInfo, DisplayObject*> >::iterator listIterator) const
{
//listIterator is guaranteed to be valid;
assert_and_throw(obj && PlaceFlagHasCharacter);

//TODO: move these three attributes in PlaceInfo
if(PlaceFlagHasColorTransform)
obj->ColorTransform=ColorTransform;

if(PlaceFlagHasRatio)
obj->Ratio=Ratio;

if(PlaceFlagHasClipDepth)
obj->ClipDepth=ClipDepth;

if(PlaceFlagHasName)
{
//Set a variable on the parent to link this object
LOG(LOG_NO_INFO,_("Registering ID ") << CharacterId << _(" with name ") << Name);
if(!PlaceFlagMove)
{
obj->incRef();
parent->setVariableByQName((const char*)Name,"",obj);
}
else
LOG(LOG_ERROR, _("Moving of registered objects not really supported"));
}

if(PlaceFlagMove)
{
//If we are here we have to erase the previous object at this depth
listIterator->second->decRef();
}

obj->setParent(parent);
obj->setRoot(parent->getRoot());
//Assign the object reference to the list
listIterator->second=obj;
//Invalidate the object now that all properties are correctly set
listIterator->second->requestInvalidation();
}

void PlaceObject2Tag::execute(MovieClip* parent, list < pair< PlaceInfo, DisplayObject*> >& ls)
{
//TODO: support clipping
if(ClipDepth!=0)
return;

PlaceInfo infos(Depth);
//Find if this id is already on the list
list < pair<PlaceInfo, DisplayObject*> >::iterator it=ls.begin();
for(;it!=ls.end();++it)
if(!PlaceFlagHasCharacter && !PlaceFlagMove)
{
if(it->first.Depth==Depth)
{
infos=it->first;
if(!PlaceFlagMove)
throw ParseException("Depth already used already on displaylist");
break;
}
LOG(LOG_ERROR,_("Invalid PlaceObject2Tag that does nothing"));
return;
}

if(PlaceFlagHasMatrix)
infos.Matrix=Matrix;

DisplayObject* toAdd=NULL;
if(PlaceFlagHasCharacter)
{
//As the transformation matrix can change every frame
//it is saved in a side data structure
//and assigned to the internal struture every frame
//A new character must be placed
LOG(LOG_TRACE,_("Placing ID ") << CharacterId);

PlaceInfo infos(Depth);
if(PlaceFlagHasMatrix)
infos.Matrix=Matrix;

list<pair<PlaceInfo, DisplayObject*> >::iterator it=
lower_bound< list<pair<PlaceInfo, DisplayObject*> >::iterator, int, list_orderer>
(ls.begin(),ls.end(),Depth,list_orderer());
if(it!=ls.end() && it->first.Depth!=Depth && !PlaceFlagMove)
{
LOG(LOG_ERROR,_("Invalid PlaceObject2Tag that overwrites an object without moving"));
return;
}
//Create a new entry in the list, currently initialized with NULL
it=ls.insert(it,std::pair<PlaceInfo, DisplayObject*>(infos,NULL));

RootMovieClip* localRoot=NULL;
DictionaryTag* parentDict=dynamic_cast<DictionaryTag*>(parent);
if(parentDict)
localRoot=parentDict->loadedFrom;
else
localRoot=parent->getRoot();
DictionaryTag* dict=localRoot->dictionaryLookup(CharacterId);
toAdd=dynamic_cast<DisplayObject*>(dict->instance());
assert_and_throw(toAdd);

//Object should be constructed even if not binded
if(toAdd->getPrototype() && sys->currentVm)
if(sys->currentVm)
{
//Object expect to have the matrix set when created
if(PlaceFlagHasMatrix)
toAdd->setMatrix(Matrix);
//We now ask the VM to construct this object
ConstructObjectEvent* e=new ConstructObjectEvent(toAdd,toAdd->getPrototype());
bool added=sys->currentVm->addEvent(NULL,e);
if(!added)
if(!isVmThread)
{
//The new object will be constructed and initialized in the context of the VM
ConstructTagEvent* e=new ConstructTagEvent(dict, parent, this, it);
sys->currentVm->addEvent(NULL,e);
e->decRef();
throw RunTimeException("Could not add event");
}
e->wait();
e->decRef();
}

if(PlaceFlagHasColorTransform)
toAdd->ColorTransform=ColorTransform;

if(PlaceFlagHasRatio)
toAdd->Ratio=Ratio;

if(PlaceFlagHasClipDepth)
toAdd->ClipDepth=ClipDepth;

toAdd->setRoot(parent->getRoot());
if(!PlaceFlagMove)
{
list<pair<PlaceInfo, DisplayObject*> >::iterator it=
lower_bound< list<pair<PlaceInfo, DisplayObject*> >::iterator, int, list_orderer>
(ls.begin(),ls.end(),Depth,list_orderer());
//As we are inserting the object in the list we need to incref it
toAdd->incRef();
toAdd->setParent(parent);
toAdd->setRoot(parent->getRoot());
ls.insert(it,make_pair(infos,toAdd));
else
{
DisplayObject* toAdd=dynamic_cast<DisplayObject*>(dict->instance());
assert_and_throw(toAdd);
if(toAdd->getPrototype())
toAdd->getPrototype()->handleConstruction(toAdd,NULL,0,true);
assignObjectToList(toAdd, parent, it);
}
}
}

if(PlaceFlagHasName)
{
//Set a variable on the parent to link this object
LOG(LOG_NO_INFO,_("Registering ID ") << CharacterId << _(" with name ") << Name);
if(!PlaceFlagMove)
else
{
//We can create the object right away
DisplayObject* toAdd=dynamic_cast<DisplayObject*>(dict->instance());
assert_and_throw(toAdd);
toAdd->incRef();
parent->setVariableByQName((const char*)Name,"",toAdd);
assignObjectToList(toAdd, parent, it);
}
else
LOG(LOG_ERROR, _("Moving of registered objects not really supported"));
}

//Move the object if relevant
if(PlaceFlagMove)
else
{
if(it!=ls.end())
//assert_and_throw(!PlaceFlagHasName && !PlaceFlagHasColorTransform && !PlaceFlagHasRatio && !PlaceFlagHasClipDepth);
//We're just changing the PlaceInfo
list<pair<PlaceInfo, DisplayObject*> >::iterator it=
lower_bound< list<pair<PlaceInfo, DisplayObject*> >::iterator, int, list_orderer>
(ls.begin(),ls.end(),Depth,list_orderer());
if(it==ls.end() || it->first.Depth!=Depth)
{
if(!PlaceFlagHasCharacter)
{
//if(it2->PlaceFlagHasClipAction)
if(PlaceFlagHasColorTransform)
it->second->ColorTransform=ColorTransform;

if(PlaceFlagHasRatio)
it->second->Ratio=Ratio;

if(PlaceFlagHasClipDepth)
it->second->ClipDepth=ClipDepth;
it->first=infos;
}
else
{
it->second->setParent(NULL);
it->second->setRoot(NULL);
it->second->decRef();
ls.erase(it);
list<pair<PlaceInfo, DisplayObject*> >::iterator it=lower_bound(ls.begin(),ls.end(),Depth,list_orderer());
toAdd->incRef();
toAdd->setParent(parent);
toAdd->setRoot(parent->getRoot());
ls.insert(it,make_pair(infos,toAdd));
}
LOG(LOG_ERROR,_("Invalid PlaceObject2Tag that moves a non existing object"));
return;
}
else
LOG(LOG_ERROR,_("no char to move at depth ") << Depth << _(" name ") << Name);
if(PlaceFlagHasMatrix)
it->first.Matrix=Matrix;
//The Depth cannot change when moving
}

if(toAdd)
toAdd->decRef();
}

PlaceObject2Tag::PlaceObject2Tag(RECORDHEADER h, std::istream& in):DisplayListTag(h)
Expand Down
2 changes: 2 additions & 0 deletions parsing/tags.h
Expand Up @@ -324,6 +324,8 @@ class PlaceObject2Tag: public DisplayListTag
STRING Name;
PlaceObject2Tag(RECORDHEADER h, std::istream& in);
void execute(MovieClip* parent, std::list < std::pair<PlaceInfo, DisplayObject*> >& list);
void assignObjectToList(DisplayObject* obj, MovieClip* parent,
std::list<std::pair<PlaceInfo, DisplayObject*> >::iterator listIterator) const;
};

class PlaceObject3Tag: public PlaceObject2Tag
Expand Down
22 changes: 9 additions & 13 deletions scripting/abc.cpp
Expand Up @@ -1192,21 +1192,17 @@ void ABCVm::handleEvent(std::pair<EventDispatcher*, Event*> e)
ev->context->exec();
break;
}
case CONSTRUCT_OBJECT:
case CONSTRUCT_TAG:
{
ConstructObjectEvent* ev=static_cast<ConstructObjectEvent*>(e.second);
LOG(LOG_CALLS,_("Building instance traits"));
try
ConstructTagEvent* ev=static_cast<ConstructTagEvent*>(e.second);
DisplayObject* toAdd=dynamic_cast<DisplayObject*>(ev->tag->instance());
assert_and_throw(toAdd);
toAdd->setMatrix(ev->listIterator->first.Matrix);
if(toAdd->getPrototype())
{
ev->_class->handleConstruction(ev->_obj,NULL,0,true);
toAdd->getPrototype()->handleConstruction(toAdd,NULL,0,true);
}
catch(LightsparkException& e)
{
//Sync anyway and rethrow
ev->sync();
throw;
}
ev->sync();
ev->placeTag->assignObjectToList(toAdd, ev->parent, ev->listIterator);
break;
}
case CHANGE_FRAME:
Expand Down Expand Up @@ -1239,7 +1235,7 @@ bool ABCVm::addEvent(EventDispatcher* obj ,Event* ev)
return false;
//If the event is a synchronization and we are running in the VM context
//we should handle it immidiately to avoid deadlock
if(isVmThread && (ev->getEventType()==SYNC || ev->getEventType()==CONSTRUCT_OBJECT))
if(isVmThread && (ev->getEventType()==SYNC))
{
assert(obj==NULL);
ev->incRef();
Expand Down
32 changes: 28 additions & 4 deletions scripting/flashdisplay.cpp
Expand Up @@ -814,6 +814,12 @@ void MovieClip::advanceFrame()
//Should initialize all the frames from the current to the next
for(uint32_t i=(state.FP+1);i<=state.next_FP;i++)
frames[i].init(this,frames[i-1].displayList);

//Before actually changing the frame verify that it's constructed
//If it's not delay the advancement
if(!frames[state.next_FP].isConstructed())
return;

bool frameChanging=(state.FP!=state.next_FP);
state.FP=state.next_FP;
if(!state.stop_FP && framesLoaded>0)
Expand All @@ -827,8 +833,17 @@ void MovieClip::advanceFrame()
funcEvent->decRef();
}

//Invalidate the current frame if needed
Frame& curFrame=frames[state.FP];

//Set the object on stage
if(isOnStage())
{
list<std::pair<PlaceInfo, DisplayObject*> >::const_iterator it=curFrame.displayList.begin();
for(;it!=curFrame.displayList.end();it++)
it->second->setOnStage(true);
}

//Invalidate the current frame if needed
if(curFrame.isInvalid())
{
list<std::pair<PlaceInfo, DisplayObject*> >::const_iterator it=curFrame.displayList.begin();
Expand All @@ -854,7 +869,10 @@ void MovieClip::requestInvalidation()
Frame& curFrame=frames[state.FP];
list<std::pair<PlaceInfo, DisplayObject*> >::const_iterator it=curFrame.displayList.begin();
for(;it!=curFrame.displayList.end();it++)
it->second->requestInvalidation();
{
if(it->second)
it->second->requestInvalidation();
}
curFrame.setInvalid(false);
}
}
Expand All @@ -869,7 +887,10 @@ void MovieClip::setOnStage(bool staged)
{
list<std::pair<PlaceInfo, DisplayObject*> >::const_iterator it=frames[i].displayList.begin();
for(;it!=frames[i].displayList.end();it++)
it->second->setOnStage(staged);
{
if(it->second)
it->second->setOnStage(staged);
}
}
}
}
Expand All @@ -886,7 +907,10 @@ void MovieClip::setRoot(RootMovieClip* r)
{
list<std::pair<PlaceInfo, DisplayObject*> >::const_iterator it=frames[i].displayList.begin();
for(;it!=frames[i].displayList.end();it++)
it->second->setRoot(root);
{
if(it->second)
it->second->setRoot(root);
}
}
if(root)
root->registerChildClip(this);
Expand Down
19 changes: 12 additions & 7 deletions scripting/flashevents.h
Expand Up @@ -31,9 +31,11 @@
namespace lightspark
{

enum EVENT_TYPE { EVENT=0, BIND_CLASS, SHUTDOWN, SYNC, MOUSE_EVENT, FUNCTION, CONTEXT_INIT, CONSTRUCT_OBJECT, CHANGE_FRAME, CONSTRUCT_FRAME };
enum EVENT_TYPE { EVENT=0, BIND_CLASS, SHUTDOWN, SYNC, MOUSE_EVENT, FUNCTION, CONTEXT_INIT, CONSTRUCT_TAG, CHANGE_FRAME, CONSTRUCT_FRAME };

class ABCContext;
class DictionaryTag;
class PlaceObject2Tag;

class Event: public ASObject
{
Expand Down Expand Up @@ -324,17 +326,20 @@ friend class ABCVm;
EVENT_TYPE getEventType() const { return CONTEXT_INIT; }
};

//This event is also synchronous
class ConstructObjectEvent: public SynchronizationEvent
class ConstructTagEvent: public Event
{
friend class ABCVm;
private:
Class_base* _class;
ASObject* _obj;
DictionaryTag* tag;
MovieClip* parent;
PlaceObject2Tag* placeTag;
std::list<std::pair<PlaceInfo, DisplayObject*> >::iterator listIterator;
static void sinit(Class_base*);
public:
ConstructObjectEvent(ASObject* o, Class_base* c):SynchronizationEvent("ConstructObjectEvent"),_class(c),_obj(o){}
EVENT_TYPE getEventType() const { return CONSTRUCT_OBJECT; }
ConstructTagEvent(DictionaryTag* d, MovieClip* p, PlaceObject2Tag* t,
std::list<std::pair<PlaceInfo, DisplayObject*> >::iterator& i):
Event("ConstructTagEvent"),tag(d),parent(p),placeTag(t),listIterator(i){}
EVENT_TYPE getEventType() const { return CONSTRUCT_TAG; }
};

//Event to change the current frame
Expand Down

0 comments on commit 8bebf6b

Please sign in to comment.