OGITOR 探索打开场景(2)

 第一部分都是做些准备,这一部分就是主力了:int COgitorsSceneSerializer::Import(Ogre::String importfile)

采用代码加注释的方式结合具体的函数探索它。

int COgitorsSceneSerializer::Import(Ogre::String importfile)
{
    OgitorsRoot *ogRoot = OgitorsRoot::getSingletonPtr();
    OgitorsSystem *mSystem = OgitorsSystem::getSingletonPtr();

    if(importfile == "")
    {
        UTFStringVector extlist;
        //#define OTR(a) mSystem->Translate(a) 以后记住这个宏
        extlist.push_back(OTR("Ogitor Scene File"));
        extlist.push_back("*.ogscene"); //相当于过滤器
        //就是显示打开场景文件对话框,见下面 1
        importfile = mSystem->DisplayOpenDialog(OTR("Open"),extlist);
        if(importfile == "") 
            return SCF_CANCEL;
    }

    Ogre::String filePath = OgitorsUtils::ExtractFilePath(importfile);
    Ogre::String fileName = OgitorsUtils::ExtractFileName(importfile);

    PROJECTOPTIONS *pOpt = ogRoot->GetProjectOptions();
    pOpt->CreatedIn = "";

    if(filePath.find(".") == 0)
    {
        filePath = OgitorsUtils::GetExePath() + filePath;
        filePath = OgitorsUtils::QualifyPath(filePath);
    }

    pOpt->ProjectDir = filePath;
    int typepos = fileName.find_last_of(".");
    pOpt->ProjectName = fileName;
    if(typepos != -1)
        pOpt->ProjectName.erase(typepos,pOpt->ProjectName.length() - typepos);

    bool testpassed = false; //这里进行目录文件测试,防止只读目录
    try
    {
        std::ofstream test((filePath + "test.dat").c_str());
        if(test.is_open())
            testpassed = true;
        test.close();
        mSystem->DeleteFile(filePath + "test.dat");
    }
    catch(...)
    {
        testpassed = false;
    }

    if(!testpassed)
    {
        mSystem->DisplayMessageDialog("The path is Read-Only. Ogitor can not work with Read-Only Project Paths!", DLGTYPE_OK);
        return SCF_CANCEL;
    }

    //真正开始解析项目文件XML了,采用tinyXml

    TiXmlDocument docImport((filePath + fileName).c_str()); 
    Ogre::UTFString loadmsg = mSystem->Translate("Parsing Scene File");
    mSystem->UpdateLoadProgress(1, loadmsg);

    if(!docImport.LoadFile()) 
        return SCF_ERRFILE;

    TiXmlNode* node = 0;
    TiXmlElement* element = 0;
    node = docImport.FirstChild("OGITORSCENE");
    
    if(!node)
        return SCF_ERRPARSE;

    element = node->ToElement();
    int version = Ogre::StringConverter::parseInt(ValidAttr(element->Attribute("version"),"1"));
    if(version == 1) 
        return ImportV1(element); //这种版本实际OGITOR并不支持,费码

    node = node->FirstChild("PROJECT");

    if(node)
    {
        loadmsg = mSystem->Translate("Parsing project options");
        mSystem->UpdateLoadProgress(5, loadmsg);
        ogRoot->LoadProjectOptions(node->ToElement()); //项目设置数据
        ogRoot->PrepareProjectResources(); // 资源的准备
    }

    //这里开始解析Viewport Light Entity等信息
    //只是这里从头开始——OGITORSCENE,根据object_id parentnode name typename解析
    //只是object_id parentnode 是可选项,name typename 是必选项,必选项如果没有就continue
    node = docImport.FirstChild("OGITORSCENE");
    if(!node) 
        return SCF_ERRPARSE;
    element = node->FirstChildElement();

    loadmsg = mSystem->Translate("Creating scene objects");
    mSystem->UpdateLoadProgress(10, loadmsg);

    unsigned int obj_count = 0;
    Ogre::String objecttype;
    OgitorsPropertyValueMap params;
    OgitorsPropertyValue tmpPropVal;
    do
    {
        // Make sure its NON-ZERO
        if(pOpt->ObjectCount)
        {
            ++obj_count;
            mSystem->UpdateLoadProgress(10 + ((obj_count * 70) / pOpt->ObjectCount), loadmsg);
        }
        
        params.clear();

        Ogre::String objAttValue;

        objAttValue = ValidAttr(element->Attribute("object_id"), "");
        if(objAttValue != "")
        {
            tmpPropVal.propType = PROP_UNSIGNED_INT;
            tmpPropVal.val = Ogre::Any(Ogre::StringConverter::parseUnsignedInt(objAttValue));
            params.insert(OgitorsPropertyValueMap::value_type("object_id", tmpPropVal));
        }

        objAttValue = ValidAttr(element->Attribute("parentnode"),"");
        if(objAttValue != "")
        {
            tmpPropVal.propType = PROP_STRING;
            tmpPropVal.val = Ogre::Any(objAttValue);
            params.insert(OgitorsPropertyValueMap::value_type("parentnode", tmpPropVal));
        }

        objAttValue = ValidAttr(element->Attribute("name"),"");
        if(objAttValue != "")
        {
            tmpPropVal.propType = PROP_STRING;
            tmpPropVal.val = Ogre::Any(objAttValue);
            params.insert(OgitorsPropertyValueMap::value_type("name", tmpPropVal));
        }
        else
            continue;

        objAttValue = ValidAttr(element->Attribute("typename"),"");
        if(objAttValue != "")
        {
            tmpPropVal.propType = PROP_STRING;
            tmpPropVal.val = Ogre::Any(objAttValue);
            params.insert(OgitorsPropertyValueMap::value_type("typename", tmpPropVal));
        }
        else
            continue;

        TiXmlElement *properties = element->FirstChildElement();
        if(properties)
        {
            Ogre::String elementName;
            do
            {
                elementName = properties->Value();
                if(elementName != "PROPERTY")
                    continue;

                Ogre::String attID = ValidAttr(properties->Attribute("id"),"");
                int attType = Ogre::StringConverter::parseInt(ValidAttr(properties->Attribute("type"),""));
                Ogre::String attValue = ValidAttr(properties->Attribute("value"),"");

                params.insert(OgitorsPropertyValueMap::value_type(attID, OgitorsPropertyValue::createFromString((OgitorsPropertyType)attType, attValue)));
            } while(properties = properties->NextSiblingElement());
        }

        objecttype = Ogre::any_cast<Ogre::String>(params["typename"].val);
        //这里创建相关的属性,还不是太明白,探索之 见 2
        CBaseEditor *result = ogRoot->CreateEditorObject(0, objecttype, params, false, false);
        if(result)
        {
            TiXmlElement *customprop = element->FirstChildElement("CUSTOMPROPERTIES");
            if(customprop) 
            {
                OgitorsUtils::ReadCustomPropertySet(customprop, result->getCustomProperties());
            }
        }
    } while(element = element->NextSiblingElement());

    ogRoot->AfterLoadScene();

    return SCF_OK;
}



 1、 importfile = mSystem->DisplayOpenDialog(OTR("Open"),extlist); 设置打开文件对话框过滤器,并设置注册表中保存路径文件名。

         并把完整路径名保存在注册表,以备下次取出。

Ogre::String QtOgitorSystem::DisplayOpenDialog(Ogre::UTFString title, Ogitors::UTFStringVector ExtensionList)
{
    QSettings settings;
    QString theList;
    QString selectedFilter;
    QString oldOpenPath;
    for(unsigned int i = 0; i < ExtensionList.size(); i+=2)
    {
        if(i) 
            theList += QString(";;");
        theList += ConvertToQString(ExtensionList[i]) + QString(" (") + ConvertToQString(ExtensionList[i + 1]) + QString(")");
    }

    settings.beginGroup("OgitorSystem");
    if( theList.contains("xml", Qt::CaseInsensitive) || theList.contains(".scene", Qt::CaseInsensitive) )
    {
        oldOpenPath = settings.value("oldDotsceneOpenPath", mProjectsDirectory).toString();
        selectedFilter = settings.value("selectedDotsceneOpenFilter", "").toString();
    }
    else
    {
        oldOpenPath = settings.value("oldOpenPath", mProjectsDirectory).toString();
    }
    settings.endGroup();

    //oldOpenPath: 是路径,但是实际上是完整的目录文件名。如:F:/ogre173/ogitorTest/second/test2.ogscene
    //QT帮助文档:The file dialog's working directory will be set to dir. 
    //If dir includes a file name, the file will be selected
    //theList:是输入的选择过滤器,例如:Ogitor场景文件 (*.ogscene)
    //selectedFilter: 是输出的过滤器,在此例中和 theList 一样,应该是在多选过滤器之后返回的选择过滤器(估计)
    QString path = QFileDialog::getOpenFileName(QApplication::activeWindow(), ConvertToQString(title), oldOpenPath, theList , &selectedFilter
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
    , QFileDialog::DontUseNativeDialog );
#else
    );
#endif

    if(path != "")
    {
        settings.beginGroup("OgitorSystem");
        if((theList.contains("xml", Qt::CaseInsensitive))&&(theList.contains(".scene", Qt::CaseInsensitive)))
        {
            settings.setValue("oldDotsceneOpenPath", path); 

            settings.setValue("selectedDotsceneOpenFilter", selectedFilter);
        }
        else
        {
            settings.setValue("oldOpenPath", path);
        }
        settings.endGroup();
    }

    return path.toStdString();
}




2、原始注释 Creates an editor object using registered factory,不明白,探索之


 

CBaseEditor *OgitorsRoot::CreateEditorObject(CBaseEditor *parent, const Ogre::String objecttypestring, OgitorsPropertyValueMap ¶ms,bool addtotreelist, bool display)
{
    if(parent == 0)
    {
        OgitorsPropertyValueMap::const_iterator ni;

        if ((ni = params.find("parentnode")) != params.end())
        {
            parent = FindObject(Ogre::any_cast<Ogre::String>(ni->second.val));
        }

        if(!parent)
        {
            if(GetSceneManager() == 0)
                parent = mRootEditor; //第一次打开文件的时候, CBaseEditor是SceneManager的parent
            else
                parent = GetSceneManagerEditor();
        }
    }
    //这里应该是工厂模式了,获取相应的EditorFactory
    CBaseEditorFactory *factory = GetEditorObjectFactory(objecttypestring);
    if(!factory)
        return 0;
    //对应的工厂创建需要的Editor。见下面2.1
    CBaseEditor *object = factory->CreateObject(&parent, params);

    if(!object) 
        return 0;

    if(object->getObjectID() == 0)
        object->setObjectID(GetUniqueObjectID(object));
    else
        AddObjectID(object->getObjectID(), object);

    RegisterObjectName(object->getName(), object);
 
    parent->_addChild(object);

    if(addtotreelist)
    {
        mSystem->InsertTreeItem(parent,object,object->getTypeID(),object->getTextColourInt());
    }

    if(parent->getLocked())
        object->setLocked(true);

    if(display)
    {
        object->load();
        mMultiSelection->setSelection(object);
    }

    object->getProperties()->addListener(&GlobalOgitorsRootPropertySetListener);
    object->getCustomProperties()->addListener(&GlobalOgitorsRootPropertySetListener);
    object->getProperties()->addListener(mUndoManager);
    object->getCustomProperties()->addListener(mUndoManager);

    if(mLoadState == LS_LOADED)
        mUndoManager->AddUndo(OGRE_NEW ObjectCreationUndo(object));

    SetSceneModified(true);

    if(mPagingEditor)
        mPagingEditor->addObject(object);

    return object;
}


2.1 CreateObject(CBaseEditor **parent, OgitorsPropertyValueMap &params)

CBaseEditor *CSceneManagerEditorFactory::CreateObject(CBaseEditor **parent, OgitorsPropertyValueMap &params)
    CSceneManagerEditor *object = OGRE_NEW CSceneManagerEditor(this);

    object->createProperties(params); //似乎是创建编辑器的参量
    object->mParentEditor->init(*parent);

    object->load(); //见2.1.1
    mInstanceCount++;
    return object;
}

2.1.1 bool CSceneManagerEditor::load(bool async) 这里创建相关的OGRE量,比如创建场景管理器,并设置相关的参量等。

bool CSceneManagerEditor::load(bool async)
{
    if(mLoaded->get()) //是否已经load.
        return true;
    
    if(!getParent()->load()) 
        return false;
    //转了千山万水,在这里创建了场景管理器。注意createSceneManager有2种创建方法
    //第一种方法输入字符串,需要提前在插件中输入(是吗?不确定)。第二种输入一个SceneTypeMask类型,比较保险
    mHandle = Ogre::Root::getSingletonPtr()->createSceneManager(mSceneManagerType->get(),mName->get());
    if(mSkyBoxActive->get())
    {
        if(Ogre::MaterialManager::getSingletonPtr()->getByName(mSkyBoxMaterial->get()).isNull())
            mSkyBoxActive->set(false);
        else
            mHandle->setSkyBox(mSkyBoxActive->get(),mSkyBoxMaterial->get(),mSkyBoxDistance->get());    
    }
    else if(mSkyDomeActive->get())
    {
        if(Ogre::MaterialManager::getSingletonPtr()->getByName(mSkyDomeMaterial->get()).isNull())
            mSkyDomeActive->set(false);
        else
            mHandle->setSkyDome(mSkyDomeActive->get(),mSkyDomeMaterial->get());
    }

    mHandle->setFog((Ogre::FogMode)mFogMode->get(),mFogColour->get(),mFogDensity->get(),mFogStart->get(),mFogEnd->get());
    mHandle->setAmbientLight(mAmbient->get());

    mRaySceneQuery = mHandle->createRayQuery(Ogre::Ray()); //创建查询体,注意在 unload 中进行了释放:destroyQuery
    mSphereSceneQuery = mHandle->createSphereQuery(Ogre::Sphere());

    configureShadows(); //配置阴影参数

    registerForUpdates(); //这里把场景管理器在ROOT进行注册,这样以后每帧就可以调用。

    mLoaded->set(true); //设置已经加载标志
    return true;
}




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值