/*         one or more fields failed to be exposed to Python.          */
bool PyFieldAccessHandler::exposeAllFieldsToPython()
{
    for(UInt32 idx = 1; idx <= _pPythonScript->getType().getNumFieldDescs(); ++idx)
    {
        FieldDescriptionBase *desc = _pPythonScript->getType().getFieldDesc(idx);
        assert(desc);

#ifdef OSGPY_DEBUG_CODEGENERATION
        std::string tmp = (desc->isDynamic()) ? "dynamic. Analyzing..." : "static. Skip...";
        std::cout << "Processing field '" << desc->getName() << "' | "
                  << tmp << std::endl;
#endif

        if(desc->isDynamic() == true)
        {
            if(exposeFieldToPython(desc->getName(), desc->getFieldId()) == true)
            {
#ifdef OSGPY_DEBUG_CODEGENERATION
                std::cout << "Successfully exposed field '" << desc->getName()
                          << "'" << std::endl << std::endl;
#endif
            }
            else
            {
                std::cerr << "Error exposing field " << desc->getName()
                          << std::endl;

                _pPyInterpreter->activate();
                _pPyInterpreter->dumpError();
                _pPyInterpreter->clearError();
                _pPyInterpreter->deactivate();

                std::cerr << "The field will not be accessible in Python!"
                          << std::endl << std::endl;
            }
        }
    }

    return true;
}
/*-------------------------------------------------------------------------*\
 -  private                                                                 -
\*-------------------------------------------------------------------------*/
void GenericFieldContainerEditor::updateFieldsPanel(FieldContainer* fc)
{
    _FieldsContainer->clearChildren();

    UInt32 NumFields(fc->getType().getNumFieldDescs());
    FieldDescriptionBase* Desc;
    FieldEditorComponentUnrecPtr TheEditor;
    LabelUnrecPtr TheLabel;
    ComponentRecPtr TheToolTip;
    GridBagLayoutConstraintsRefPtr LayoutConstraints;
    PanelRefPtr FieldPanel;
    UInt32 NumRows(0),NumRowsForField(1);

    BorderLayoutRefPtr TheBorderLayout = BorderLayout::create();
    BorderLayoutConstraintsRefPtr WestConstraint = BorderLayoutConstraints::create();
    WestConstraint->setRegion(BorderLayoutConstraints::BORDER_WEST);
    BorderLayoutConstraintsRefPtr CenterConstraint = BorderLayoutConstraints::create();
    CenterConstraint->setRegion(BorderLayoutConstraints::BORDER_CENTER);

    //Backgrounds
    ColorLayerRefPtr HeaderBgLayer = ColorLayer::create();
    HeaderBgLayer->setColor(Color4f(0.7f,0.7f,0.7f,1.0f));

    ColorLayerRefPtr LightBgLayer = ColorLayer::create();
    LightBgLayer->setColor(Color4f(0.9f,0.9f,0.9f,1.0f));
    ColorLayerRefPtr DarkBgLayer = ColorLayer::create();
    DarkBgLayer->setColor(Color4f(0.8f,0.8f,0.8f,1.0f));

    LayoutConstraints = GridBagLayoutConstraints::create();
    LayoutConstraints->setGridX(0);
    LayoutConstraints->setGridY(NumRows);
    LayoutConstraints->setGridHeight(1);
    LayoutConstraints->setGridWidth(2);
    LayoutConstraints->setFill(GridBagLayoutConstraints::FILL_BOTH);

    LabelRecPtr FieldsLabel = Label::create();
    FieldsLabel->setAlignment(Vec2f(0.5f,0.5f));
    FieldsLabel->setText("Fields");
    FieldsLabel->setBackgrounds(HeaderBgLayer);
    FieldsLabel->setConstraints(LayoutConstraints);
    FieldsLabel->setFont(_BoldFont);

    _FieldsContainer->pushToChildren(FieldsLabel);
    ++NumRows;

    if(_GenericNameAttachmentEditor->isTypeEditable(fc->getType()))
    {
        //Create the Label
        TheLabel = Label::create();
        TheLabel->setText("Name");
        TheLabel->setBackgrounds(NULL);
        TheLabel->setConstraints(WestConstraint);
        TheLabel->setPreferredSize(Vec2f(160.0f,22.0f));

        //Attach the Generic Name Editor
        _GenericNameAttachmentEditor->setCommandManager(_CmdManager);
        _GenericNameAttachmentEditor->attachContainer(fc);
        _GenericNameAttachmentEditor->setConstraints(CenterConstraint);

        //Create the Panel
        LayoutConstraints = GridBagLayoutConstraints::create();
        LayoutConstraints->setGridX(0);
        LayoutConstraints->setGridY(NumRows);
        LayoutConstraints->setGridHeight(1);
        LayoutConstraints->setGridWidth(1);
        LayoutConstraints->setFill(GridBagLayoutConstraints::FILL_BOTH);

        FieldPanel = Panel::createEmpty();
        FieldPanel->setInset(Vec4f(1.0f,1.0f,1.0f,1.0f));
        FieldPanel->pushToChildren(TheLabel);
        FieldPanel->pushToChildren(_GenericNameAttachmentEditor);
        FieldPanel->setLayout(TheBorderLayout);
        FieldPanel->setConstraints(LayoutConstraints);
        FieldPanel->setBackgrounds(LightBgLayer);

        _FieldsContainer->pushToChildren(FieldPanel);
        ++NumRows;
    }

    UInt32 UsedFieldCount(0);
    for(UInt32 i(1) ; i<=NumFields ; ++i)
    {
        Desc = fc->getFieldDescription(i);
        if(Desc != NULL &&
           !Desc->isInternal() &&
           Desc->getFieldType().getClass() != FieldType::ParentPtrField &&
           //HACK: Stop the pixel field from being editable on Images
           !(fc->getType().isDerivedFrom(Image::getClassType()) &&
             Desc->getFieldId() == Image::PixelFieldId))
        {
            //Create the Editor
            TheEditor = FieldEditorFactory::the()->createDefaultEditor(fc, Desc->getFieldId(), _CmdManager);
            if(TheEditor != NULL)
            {
                NumRowsForField = TheEditor->getNumRequestedRows();
                pushToEditors(TheEditor);
                TheEditor->setConstraints(CenterConstraint);

                //Create the Label
                TheLabel = Label::create();
                TheLabel->setText(Desc->getCName());
                TheLabel->setBackgrounds(NULL);
                TheLabel->setConstraints(WestConstraint);
                TheLabel->setPreferredSize(Vec2f(160.0f,22.0f));
                TheToolTip = createFieldToolTip(Desc);
                TheLabel->setToolTip(TheToolTip);

                //Create the Panel
                LayoutConstraints = GridBagLayoutConstraints::create();
                LayoutConstraints->setGridX(0);
                LayoutConstraints->setGridY(NumRows);
                LayoutConstraints->setGridHeight(NumRowsForField);
                LayoutConstraints->setGridWidth(1);
                LayoutConstraints->setFill(GridBagLayoutConstraints::FILL_BOTH);


                FieldPanel = Panel::createEmpty();
                FieldPanel->setInset(Vec4f(1.0f,1.0f,1.0f,1.0f));
                FieldPanel->pushToChildren(TheLabel);
                FieldPanel->pushToChildren(TheEditor);
                FieldPanel->setLayout(TheBorderLayout);
                FieldPanel->setConstraints(LayoutConstraints);
                if((UsedFieldCount%2) == 0)
                {
                    FieldPanel->setBackgrounds(DarkBgLayer);
                }
                else
                {
                    FieldPanel->setBackgrounds(LightBgLayer);
                }

                _FieldsContainer->pushToChildren(FieldPanel);
                NumRows += NumRowsForField;
                TheEditor->setPreferredSize(Vec2f(50.0f,22.0f * NumRowsForField));
                ++UsedFieldCount;
            }
        }
    }

    //Set the number of rows for the grid layout
    dynamic_cast<GridBagLayout*>(_FieldsContainer->getLayout())->setRows(NumRows);
    _FieldsContainer->setPreferredSize(Vec2f(400.0f, NumRows*24.0f));
}
Esempio n. 3
0
void
OSBGeometryElement::postReadV100(void)
{
    OSG_OSB_LOG(("OSBGeometryElement::postReadV100\n"));

    OSBRootElement  *root             = editRoot();
    Geometry        *geo              =
        dynamic_cast<Geometry*>(getContainer());
    UInt32           indexMappingSize = UInt32(_indexMapping.size());

    if(indexMappingSize <= 1)
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting single index.\n"          ));

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));
            geo->setIndices(_indices);
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting non-packed indices.\n"    ));

            // indices stored in container with id _indicesId
            // create PtrFieldInfo structure to set all entries of field
            // "propIndices" to the container with id _indicesId

            FieldDescriptionBase *indFieldDesc =
                geo->getFieldDescription("propIndices");
            UInt32                indFieldId   = indFieldDesc->getFieldId();

            root->editPtrFieldList().push_back(PtrFieldInfo(geo, indFieldId));
            PtrFieldInfo &indFieldPFI = root->editPtrFieldList().back();

            for(UInt32 i = 0; i < Geometry::MaxAttribs; ++i)
            {
                indFieldPFI.editIdStore().push_back(_indicesId);
            }
        }
    }
    else
    {
        OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                "Converting multi index.\n"          ));

        OSBGeometryHelper gh;

        if(_indicesPacked)
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                    "Converting packed indices.\n"        ));

            // create 16 bit or 32 bit indices
            if(_indices16Bit)
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
        else
        {
            OSG_OSB_LOG(("OSBGeometryElement::postReadV100: "
                         "Converting non-packed indices.\n"    ));

            FieldContainerIdMapConstIt mapIt =
                root->getIdMap().find(_indicesId);

            if(mapIt != root->getIdMap().end())
            {
                _indices = dynamic_cast<GeoIntegralProperty *>(
                    FieldContainerFactory::the()->getContainer(mapIt->second));
            }
            else
            {
                FWARNING(("OSBGeometryElement::postReadV100: "
                          "Could not find indices property.\n"));
                return;
            }

            if(_indices->getFormatSize() == sizeof(UInt16))
            {
                GeoUInt16Property *ui16Indices =
                    dynamic_pointer_cast<GeoUInt16Property>(_indices);

                gh.splitMultiIndex<GeoUInt16Property *>(
                    _indexMapping, ui16Indices, geo);
            }
            else if(_indices->getFormatSize() == sizeof(UInt32))
            {
                GeoUInt32Property *ui32Indices =
                    dynamic_pointer_cast<GeoUInt32Property>(_indices);

                gh.splitMultiIndex<GeoUInt32Property *>(
                    _indexMapping, ui32Indices, geo);
            }
        }
    }
}
Esempio n. 4
0
void
OSBGeometryElement::readV100(void)
{
    OSG_OSB_LOG(("OSBGeometryElement::readV100:\n"));

    OSBRootElement    *root = editRoot();
    BinaryReadHandler *rh   = editRoot()->getReadHandler();
    OSBGeometryHelper  gh;

    GeometryUnrecPtr geo = Geometry::create();
    setContainer(geo);

    // The "properties" mfield can be thought of the unification of the
    // "positions", "normals", etc sfields of the 1.x Geometry.
    // For the conversion the PtrFieldInfo structure for the "properties"
    // mfield is filled with the corresponding ids of the sfields from the
    // file. The remapping after postRead will fill in the right pointers.

    FieldDescriptionBase *propFieldDesc =
        geo->getFieldDescription("properties");
    UInt32                propFieldId   = propFieldDesc->getFieldId();

    root->editPtrFieldList().push_back(PtrFieldInfo(geo, propFieldId));
    PtrFieldInfo &propFieldPFI = root->editPtrFieldList().back();

    propFieldPFI.editIdStore().resize(Geometry::MaxAttribs);

    while(true)
    {
        std::string    fieldName;
        std::string    fieldTypeName;
        UInt32         fieldSize;
        PtrFieldListIt ptrFieldIt;

        if(!readFieldHeader("", fieldName, fieldTypeName, fieldSize))
        {
            OSG_OSB_LOG(("OSBGeometryElement::readV100: "
                    "Reading stopped at field: [%s].\n", fieldName.c_str()));
            break;
        }

        if(fieldName == "indexMapping")
        {
            // read into temporary field
            MField<UInt16> indexMappingField;
            indexMappingField.copyFromBin(*rh);

            // copy to member for use in postRead
            indexMappingField.getValues().swap(_indexMapping);
        }
        else if(fieldName == "indices")
        {
            // read container id of indices property
            // postRead will handle the conversion of multi indices
            rh->getValue(_indicesId);
        }
        else if(fieldName == "positions")
        {
            UInt32 positionsId;
            rh->getValue(positionsId);
            propFieldPFI.editIdStore()[Geometry::PositionsIndex] = positionsId;
        }
        else if(fieldName == "normals")
        {
            UInt32 normalsId;
            rh->getValue(normalsId);
            propFieldPFI.editIdStore()[Geometry::NormalsIndex] = normalsId;
        }
        else if(fieldName == "colors")
        {
            UInt32 colorsId;
            rh->getValue(colorsId);
            propFieldPFI.editIdStore()[Geometry::ColorsIndex] = colorsId;
        }
        else if(fieldName == "secondaryColors")
        {
            UInt32 secondaryColorsId;
            rh->getValue(secondaryColorsId);
            propFieldPFI.editIdStore()[Geometry::SecondaryColorsIndex] =
                secondaryColorsId;
        }
        else if(fieldName == "texCoords")
        {
            UInt32 texCoordsId;
            rh->getValue(texCoordsId);
            propFieldPFI.editIdStore()[Geometry::TexCoordsIndex] =
                texCoordsId;
        }
        else if(fieldName == "texCoords1")
        {
            UInt32 texCoordsId1;
            rh->getValue(texCoordsId1);
            propFieldPFI.editIdStore()[Geometry::TexCoords1Index] =
                texCoordsId1;
        }
        else if(fieldName == "texCoords2")
        {
            UInt32 texCoordsId2;
            rh->getValue(texCoordsId2);
            propFieldPFI.editIdStore()[Geometry::TexCoords2Index] =
                texCoordsId2;
        }
        else if(fieldName == "texCoords3")
        {
            UInt32 texCoordsId3;
            rh->getValue(texCoordsId3);
            propFieldPFI.editIdStore()[Geometry::TexCoords3Index] =
                texCoordsId3;
        }
        else if(fieldName == "texCoords4")
        {
            UInt32 texCoordsId4;
            rh->getValue(texCoordsId4);
            propFieldPFI.editIdStore()[Geometry::TexCoords4Index] =
                texCoordsId4;
        }
        else if(fieldName == "texCoords5")
        {
            UInt32 texCoordsId5;
            rh->getValue(texCoordsId5);
            propFieldPFI.editIdStore()[Geometry::TexCoords5Index] =
                texCoordsId5;
        }
        else if(fieldName == "texCoords6")
        {
            UInt32 texCoordsId6;
            rh->getValue(texCoordsId6);
            propFieldPFI.editIdStore()[Geometry::TexCoords6Index] =
                texCoordsId6;
        }
        else if(fieldName == "texCoords7")
        {
            UInt32 texCoordsId7;
            rh->getValue(texCoordsId7);
            propFieldPFI.editIdStore()[Geometry::TexCoords7Index] =
                texCoordsId7;
        }
        else if(fieldName == "pindices")
        {
            UInt32 maxValue;
            UInt32 propSize;
            UInt32 byteSize;

            _indicesPacked = true;

            gh.readPackedIntegralPropertyHeader(rh, maxValue,
                                                propSize, byteSize);

            if(root->getOptions().unpack16BitIndices())
            {
                if(maxValue > TypeTraits<UInt16>::getMax())
                {
                    GeoUInt32PropertyUnrecPtr ui32Indices =
                        GeoUInt32Property::create();
                    gh.readPackedIntegralProperty(rh, ui32Indices, maxValue,
                                                  propSize, byteSize        );

                    _indices16Bit = false;
                    _indices      = ui32Indices;
                }
                else
                {
                    GeoUInt16PropertyUnrecPtr ui16Indices =
                        GeoUInt16Property::create();
                    gh.readPackedIntegralProperty(rh, ui16Indices, maxValue,
                                                  propSize, byteSize        );

                    _indices16Bit = true;
                    _indices      = ui16Indices;
                }
            }
            else
            {
                GeoUInt32PropertyUnrecPtr ui32Indices =
                    GeoUInt32Property::create();
                gh.readPackedIntegralProperty(rh, ui32Indices, maxValue,
                                              propSize, byteSize        );

                _indices16Bit = false;
                _indices      = ui32Indices;
            }
        }
        else if(fieldName == "qpositions")
        {
            // Quantized positions are stored inside the geometry object, not
            // in the geo-property. They are always of type Pnt3f.
            GeoPnt3fPropertyUnrecPtr propPos    = GeoPnt3fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(rh, resolution, minValue,
                                                 maxValue, propSize       );
            gh.readQuantizedVectorProperty(rh, propPos, fieldSize, resolution,
                                           minValue, maxValue, propSize       );

            geo->setProperty(propPos, Geometry::PositionsIndex);
        }
        else if(fieldName == "qnormals")
        {
            // Quantized normals are stored inside the geometry object, not
            // in the geo-property. They are always of type Vec3f.
            GeoVec3fPropertyUnrecPtr propNorm   = GeoVec3fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(
                rh, resolution, minValue, maxValue, propSize);
            gh.readQuantizedVectorProperty(
                rh, propNorm, fieldSize, resolution,
                minValue, maxValue, propSize        );

            geo->setProperty(propNorm, Geometry::NormalsIndex);
        }
        else if(fieldName == "qtexCoords")
        {
            // Quantized texCoords are stored inside the geometry object, not
            // in the geo-property. They are always of type Vec2f.
            GeoVec2fPropertyUnrecPtr propTexCoords = GeoVec2fProperty::create();
            UInt8                    resolution;
            Real32                   minValue;
            Real32                   maxValue;
            UInt32                   propSize;

            gh.readQuantizedVectorPropertyHeader(
                rh, resolution, minValue, maxValue, propSize);
            gh.readQuantizedVectorProperty(
                rh, propTexCoords, fieldSize, resolution,
                minValue, maxValue, propSize             );

            geo->setProperty(propTexCoords, Geometry::NormalsIndex);
        }
        else
        {
            // 1.x Geometry has _sfVbo, it can be skipped

            readFieldContent(fieldName, fieldTypeName, fieldSize,
                             "'vbo'", ptrFieldIt                      );
        }
    }
}
void FieldAnimation::changed(ConstFieldMaskArg whichField, 
                             UInt32            origin,
                             BitVector         details)
{
    Inherited::changed(whichField, origin, details);

    //Do not respond to changes that have a Sync origin
    if(origin & ChangedOrigin::Sync)
    {
        return;
    }

    if(whichField & FieldNameFieldMask)
    {
        if(getContainer() != NULL)
        {

            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldName().c_str());
            if( f == NULL )
            {
                SWARNING << "Could not find Field "<< getFieldName() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
                return;
            }
            else
            {
                setFieldId(f->getFieldId());
                //commitChanges();
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
            return;
        }
    }
    else if((whichField & FieldIdFieldMask) ||
            (whichField & ContainerFieldMask))
    {
        if(getContainer() != NULL)
        {
            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldId());
            if( f == NULL )
            {
                SWARNING << "Could not find Field ID"<< getFieldId() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
                return;
            }
            else
            {
                if(getAnimator()->getDataType() == NULL)
                {
                    SWARNING << "Cannot update animation, because the animator attached to this animation does not work on any data types."  << std::endl;
                    return;
                }
                //Check if it's the right type
                if(getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType()
                   != *getAnimator()->getDataType())
                {
                    SWARNING << "The data type of the field: "
                             << getContainer()->getFieldDescription(getFieldId())->getName()
                             << " with type: "
                             << getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType().getCName()
                             << " connected to this animation is not the same data type: "
                             << getAnimator()->getDataType()->getCName()
                             << ", that the animator works on."  << std::endl;
                    return;
                }
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
            return;
        }
    }
    if(whichField & IndexFieldMask)
    {
        if(getContainer() != NULL)
        {
            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldId());
            if( f == NULL )
            {
                SWARNING << "Could not find Field ID"<< getFieldId() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
            }
            else
            {

                //Check if animator supports any types
                if(getAnimator()->getDataType() == NULL)
                {
                    SWARNING << "Cannot update animation, because the animator attached to this animation does not work on any data types."  << std::endl;
                }
                //Check if it's the right type
                if(getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType()
                   != *getAnimator()->getDataType())
                {
                    SWARNING << "The data type of the field: "
                             << getContainer()->getFieldDescription(getFieldId())->getName()
                             << " with type: "
                             << getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType().getCName()
                             << " connected to this animation is not the same data type: "
                             << getAnimator()->getDataType()->getCName()
                             << ", that the animator works on."  << std::endl;
                }
                GetFieldHandlePtr TheFieldHandle = getContainer()->getField( getFieldId() );

                if( getIndex() > 0 )
                {
                    if(TheFieldHandle->getCardinality() != FieldType::MultiField)
                    {
                        SWARNING << "Cannot attach to index: " << getIndex() 
                                 << " of field " << getContainer()->getFieldDescription(getFieldId())->getName() 
                                 << " because it has cardinality 1." << std::endl;
                    }
                    else if(getIndex() < TheFieldHandle->size())
                    {
                        SWARNING << "Cannot attach to index: " << getIndex() 
                                 << " of field " << getContainer()->getFieldDescription(getFieldId())->getName() 
                                 << " because that index is out of bounds on a field of size " << TheFieldHandle->size() << "." << std::endl;
                    }
                }
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
        }
    }
}
Action::ResultE
bindEnterDefault(NodeCore *core, Action *action)
{
    AnimBindAction     *bindAct  = dynamic_cast<AnimBindAction *>(action);
    Animation          *anim     = bindAct->getAnim    ();
    const AnimTemplate *animTmpl = bindAct->getTemplate();

    AnimTargetAttachment *targetAtt = getTargetAtt(core);

    FDEBUG(("bindEnterDefault: core [%p] targetAtt [%p]\n",
            core, targetAtt));

    if(targetAtt == NULL)
        return Action::Continue;

    Int32 srcIdx = 0;

    while((srcIdx = animTmpl->findTargetId(targetAtt->getTargetId(),
                                           srcIdx                   )) != -1)
    {
        std::string targetId;
        std::string subTargetId;

        bindAct->splitTargetId(
            animTmpl->getTargetIds(srcIdx), targetId, subTargetId);

        FDEBUG(("bindEnterDefault: targetId [%s] subTargetId [%s]\n",
                targetId.c_str(), subTargetId.c_str()));

        // create the channel

        AnimDataSource      *src     = animTmpl->getSources   (srcIdx);
        AnimChannelUnrecPtr  channel = src     ->createChannel(      );
        anim->editMFChannels()->push_back(channel);

        FieldDescriptionBase *fDesc =
            core->getType().getFieldDesc(subTargetId.c_str());

        if(fDesc == NULL)
        {
            SWARNING << "bindEnterDefault: no field for subTargetId ["
                     << subTargetId << "] found." << std::endl;
            continue;
        }

        // create the blender

        UInt32              fId     = fDesc->getFieldId();
        
        if(targetAtt->getMFBlenders()->size() <= fId)
            targetAtt->editMFBlenders()->resize(fId + 1, NULL);

        AnimBlenderUnrecPtr blender = targetAtt->getBlenders(fId);

        if(blender == NULL)
        {
            blender = src->createBlender();
            (*targetAtt->editMFBlenders())[fId] = blender;
        }

        // connect

        blender->addChannel(channel               );
        blender->connectTo (core, fDesc->getName());

        ++srcIdx;
    }

    return Action::Continue;
}
Action::ResultE
AnimBindAction::bindFields(AttachmentContainer *attCon)
{
    AnimTargetAttachment *targetAtt = getTargetAtt(attCon);

    if(targetAtt == NULL)
        return Action::Continue;

    Animation       *anim  = getAnim();
    DataSourceMapIt  dsIt  = _dsMap.begin();
    DataSourceMapIt  dsEnd = _dsMap.end  ();

    while(dsIt != dsEnd)
    {
        if(dsIt->first.find(targetAtt->getTargetId()) != 0)
        {
            ++dsIt;
            continue;
        }

        std::string targetId;
        std::string subTargetId;

        splitTargetId(dsIt->first, targetId, subTargetId);

        if(targetId != targetAtt->getTargetId())
        {
            ++dsIt;
            continue;
        }

        SINFO << "AnimBindAction::bindFields: binding source '"
              << dsIt->first << "' to '" << targetId << "' - '"
              << subTargetId << "'" << std::endl;

        FieldDescriptionBase *fDesc =
            attCon->getType().getFieldDesc(subTargetId.c_str());

        if(fDesc == NULL)
        {
            SWARNING << "AnimBindAction::bindFields: no Field for "
                     << "subTargetId [" << subTargetId << "] found."
                     << std::endl;
            ++dsIt;
            continue;
        }

        // create channel
        AnimChannelUnrecPtr channel = dsIt->second->createChannel();
        anim->editMFChannels()->push_back(channel);

         // create blender
        UInt32 fId = fDesc->getFieldId();

        if(targetAtt->getMFBlenders()->size() <= fId)
            targetAtt->editMFBlenders()->resize(fId + 1, NULL);

        AnimBlenderUnrecPtr blender = targetAtt->getBlenders(fId);

        if(blender == NULL)
        {
            blender = dsIt->second->createBlender();
            targetAtt->editMFBlenders()->replace(fId, blender);
        }

        // on create all fields are marked as changed - this causes
        // the blender to write to its destination even though
        // it has no valid input data - avoid it by committing before
        // connecting the blender to its dest
        commitChanges();

        blender->addChannel(channel                 );
        blender->connectTo (attCon, fDesc->getName());

        // remove bound data source from map
        DataSourceMapIt eraseIt = dsIt;
        ++dsIt;
        _dsMap.erase(eraseIt);
    }

    if(_dsMap.empty() == true)
    {
        return Action::Quit;
    }
    else
    {
        return Action::Continue;
    }
}
/*! Reads the contents of a field from the stream. It is intended to be used
    in conjunction with readFieldHeader and uses the information obtained
    by it (\a fieldName, \a fieldTypeName, \a fieldSize ).

    If a field is not to be read, but skipped instead, its name can be passed
    in the \a excludeFields argument. The string has the format:
    "'name1' 'name2' 'name3'", the spaces between the "'" are mandatory.

    \param[in] fieldName Name of the field.
    \param[in] fieldTypeName Type of the field.
    \param[in] fieldSize Size in bytes of the field.
    \param[in] excludeFields
    \param[out] ptrFieldIt Iterator that points to the PtrFieldInfo structure
    that was created, if this is a "pointer field" - only valid if true is
    returned.

    \return True, if the field is a "pointer field", i.e. a field holding
    pointers to other FieldContainers, false otherwise.
 */
bool
OSBCommonElement::readFieldContent(
    const std::string    &fieldName,
    const std::string    &fieldTypeName,
    const UInt32          fieldSize,
    const std::string    &excludeFields,
          PtrFieldListIt &ptrFieldIt    )
{
    OSG_OSB_LOG(("OSBCommonElement::readFieldContent: [%s] [%s] [%u]\n",
            fieldName.c_str(), fieldTypeName.c_str(), fieldSize));

    BinaryReadHandler    *rh         = editRoot()->getReadHandler();
    bool                  isPtrField = false;
    FieldDescriptionBase *fieldDesc  =
        getContainer()->getFieldDescription(fieldName.c_str());

    if((!excludeFields.empty()                                        ) &&
       (excludeFields.find("'" + fieldName + "'") != std::string::npos)   )
    {
        OSG_OSB_LOG(("OSBCommonElement::readFieldContent: "
                "Skipping excluded field [%s] [%s]\n",
                fieldName.c_str(), fieldTypeName.c_str()));

        rh->skip(fieldSize);
        return false;
    }

    if(fieldDesc == 0)
    {
        DynFieldContainerInterface *pIf = 
            dynamic_cast<DynFieldContainerInterface *>(getContainer());

        if(pIf != NULL)
        {
            pIf->addField(fieldTypeName.c_str(), fieldName.c_str());

            fieldDesc = getContainer()->getFieldDescription(fieldName.c_str());
        }
    }

    if(fieldDesc == 0)
    {
        FWARNING(("OSBCommonElement::readFieldContent: "
                  "Skipping unknown field [%s] [%s].\n",
                  fieldName.c_str(), fieldTypeName.c_str()));

        rh->skip(fieldSize);
        return false;
    }

    const FieldType &fieldType  = fieldDesc->getFieldType();
    UInt32           fieldId    = fieldDesc->getFieldId  ();
    BitVector        fieldMask  = fieldDesc->getFieldMask();

    if(fieldType.getContentType().isDerivedFrom(
        FieldTraits<FieldContainer *>::getMapType()) == true)
    {
        ptrFieldIt = readAttachmentMapField(fieldId, fieldSize);
        isPtrField = true;
    }
    else if(fieldType.getContentType().isDerivedFrom(
        FieldTraits<FieldContainer *>::getType()) == true)
    {
        if(fieldType.getClass() == FieldType::ParentPtrField)
        {
            rh->skip(fieldSize);
            isPtrField = false;
        }
        else
        {
            if(fieldType.getCardinality() == FieldType::SingleField)
            {
                ptrFieldIt = readPtrSingleField(fieldId);
                isPtrField = true;
            }
            else if(fieldType.getCardinality() == FieldType::MultiField)
            {
                ptrFieldIt = readPtrMultiField(fieldId, fieldSize);
                isPtrField = true;
            }
        }
    }
    else
    {
        getContainer()->copyFromBin(*rh, fieldMask);
        isPtrField = false;
    }

    return isPtrField;
}
void FieldAnimation::changed(ConstFieldMaskArg whichField,
                             UInt32            origin,
                             BitVector         details)
{
    Inherited::changed(whichField, origin, details);

    if(whichField & FieldNameFieldMask)
    {
        if(getContainer() != NULL)
        {

            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldName().c_str());
            if( f == NULL )
            {
                SWARNING << "Could not find Field "<< getFieldName() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
                return;
            }
            else
            {
                setFieldId(f->getFieldId());
                commitChanges();
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
            return;
        }
    }
    else if((whichField & FieldIdFieldMask) ||
            (whichField & ContainerFieldMask))
    {
        if(getContainer() != NULL)
        {
            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldId());
            if( f == NULL )
            {
                SWARNING << "Could not find Field ID"<< getFieldId() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
                return;
            }
            else
            {
                //Check if it's the right type
                if(getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType() != getAnimator()->getDataType())
                {
                    SWARNING << "The data type of the field: " << getContainer()->getFieldDescription(getFieldId())->getName() << " with type: "  << getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType().getCName() << " connected to this animation is not the same data type: " << getAnimator()->getDataType().getCName() << ", that the animator works on."  << std::endl;
                    return;
                }
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
            return;
        }
    }
    if(whichField & IndexFieldMask)
    {
        if(getContainer() != NULL)
        {
            FieldDescriptionBase * f = getContainer()->getFieldDescription(getFieldId());
            if( f == NULL )
            {
                SWARNING << "Could not find Field ID"<< getFieldId() << " in Field Container " << getContainer()->getTypeName()  << std::endl;
                return;
            }
            else
            {

                //Check if it's the right type
                if(getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType() != getAnimator()->getDataType())
                {
                    SWARNING << "The data type of the field: " << getContainer()->getFieldDescription(getFieldId())->getName() << " with type: "  << getContainer()->getFieldDescription(getFieldId())->getFieldType().getContentType().getCName() << " connected to this animation is not the same data type: " << getAnimator()->getDataType().getCName() << ", that the animator works on."  << std::endl;
                    return;
                }
                const Field* TheField = getContainer()->getField( getFieldId() )->getField();

                if( getIndex() >= 0 &&
                        TheField->getCardinality() != FieldType::MultiField &&
                        getIndex() < TheField->getSize())
                {
                    SWARNING << "If the Index for the field animation is > 0 then the animated field must be a multi field and the index must be less than the size of this field." << getAnimator()->getDataType().getCName() << "."  << std::endl;
                    return;
                }
                else if( getIndex() < 0 &&
                         TheField->getCardinality() != FieldType::SingleField)
                {
                    SWARNING << "If the Index for the field animation is < 0 then the animated field must be a single field." << getAnimator()->getDataType().getCName()  << std::endl;
                }
            }
        }
        else
        {
            SWARNING << "There is no Field Container defined to Animate"  << std::endl;
            return;
        }
    }
}