void WebFrameLoaderClient::dispatchDidFirstLayout()
{
    SharedPtr<WebFrameLoadDelegate> frameLoadDelegate = m_webFrame->webView()->webFrameLoadDelegate();
    if (frameLoadDelegate)
        frameLoadDelegate->dispatchDidFirstLayout(m_webFrame);
}
CLOCKWORK_EXPORT_API int clockworksharp_initialize()
{
    sContext = new Clockwork::Context();
    sApplication = new ClockworkPlayer::ClockworkPlayerApp(sContext);
    return sApplication->Initialize();
}
Beispiel #3
0
bool TextureCube::Load(CubeMapFace face, SharedPtr<Image> image, bool useAlpha)
{
    if (!image)
    {
        LOGERROR("Null image, can not load texture");
        return false;
    }
    
    unsigned memoryUse = 0;
    
    int quality = QUALITY_HIGH;
    Renderer* renderer = GetSubsystem<Renderer>();
    if (renderer)
        quality = renderer->GetTextureQuality();
    
    if (!image->IsCompressed())
    {
        unsigned char* levelData = image->GetData();
        int levelWidth = image->GetWidth();
        int levelHeight = image->GetHeight();
        unsigned components = image->GetComponents();
        unsigned format = 0;
        
        if (levelWidth != levelHeight)
        {
            LOGERROR("Cube texture width not equal to height");
            return false;
        }
        
        // Discard unnecessary mip levels
        for (unsigned i = 0; i < mipsToSkip_[quality]; ++i)
        {
            image = image->GetNextLevel();
            levelData = image->GetData();
            levelWidth = image->GetWidth();
            levelHeight = image->GetHeight();
        }
        
        switch (components)
        {
        case 1:
            format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat();
            break;
            
        case 2:
            format = Graphics::GetLuminanceAlphaFormat();
            break;
            
        case 3:
            format = Graphics::GetRGBFormat();
            break;
            
        case 4:
            format = Graphics::GetRGBAFormat();
            break;
        }
        
        // Create the texture when face 0 is being loaded, check that rest of the faces are same size & format
        if (!face)
        {
            // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size
            if (IsCompressed() && requestedLevels_ > 1)
                requestedLevels_ = 0;
            SetSize(levelWidth, format);
        }
        else
        {
            if (!object_)
            {
                LOGERROR("Cube texture face 0 must be loaded first");
                return false;
            }
            if (levelWidth != width_ || format != format_)
            {
                LOGERROR("Cube texture face does not match size or format of face 0");
                return false;
            }
        }
        
        for (unsigned i = 0; i < levels_; ++i)
        {
            SetData(face, i, 0, 0, levelWidth, levelHeight, levelData);
            memoryUse += levelWidth * levelHeight * components;
            
            if (i < levels_ - 1)
            {
                image = image->GetNextLevel();
                levelData = image->GetData();
                levelWidth = image->GetWidth();
                levelHeight = image->GetHeight();
            }
        }
    }
    else
    {
        int width = image->GetWidth();
        int height = image->GetHeight();
        unsigned levels = image->GetNumCompressedLevels();
        unsigned format = graphics_->GetFormat(image->GetCompressedFormat());
        bool needDecompress = false;
        
        if (width != height)
        {
            LOGERROR("Cube texture width not equal to height");
            return false;
        }
        
        if (!format)
        {
            format = Graphics::GetRGBAFormat();
            needDecompress = true;
        }
        
        unsigned mipsToSkip = mipsToSkip_[quality];
        if (mipsToSkip >= levels)
            mipsToSkip = levels - 1;
        while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4))
            --mipsToSkip;
        width /= (1 << mipsToSkip);
        height /= (1 << mipsToSkip);
        
        // Create the texture when face 0 is being loaded, assume rest of the faces are same size & format
        if (!face)
        {
            SetNumLevels(Max((int)(levels - mipsToSkip), 1));
            SetSize(width, format);
        }
        else
        {
            if (!object_)
            {
                LOGERROR("Cube texture face 0 must be loaded first");
                return false;
            }
            if (width != width_ || format != format_)
            {
                LOGERROR("Cube texture face does not match size or format of face 0");
                return false;
            }
        }
        
        for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i)
        {
            CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip);
            if (!needDecompress)
            {
                SetData(face, i, 0, 0, level.width_, level.height_, level.data_);
                memoryUse += level.rows_ * level.rowSize_;
            }
            else
            {
                unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4];
                level.Decompress(rgbaData);
                SetData(face, i, 0, 0, level.width_, level.height_, rgbaData);
                memoryUse += level.width_ * level.height_ * 4;
                delete[] rgbaData;
            }
        }
    }
    
    faceMemoryUse_[face] = memoryUse;
    unsigned totalMemoryUse = sizeof(TextureCube);
    for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
        totalMemoryUse += faceMemoryUse_[i];
    SetMemoryUse(totalMemoryUse);
    
    return true;
}
Node* buildSimpleMechanicExample()
{
  SharedPtr<Group> group = new Group("G");

  MobileRootJoint* mobileRootJoint = new MobileRootJoint("Root Joint");
  group->addChild(mobileRootJoint);

  RigidBody *rigidBody = new RigidBody("Rigid Body");
  rigidBody->addLink("link2");
  rigidBody->addLink("externalInteractLink");
  rigidBody->addLink("internalInteractLink");
  rigidBody->addLink("internalInteractLink2");
  group->addChild(rigidBody);
  InertiaMatrix inertia(1, 0, 0, 1, 0, 1);
  Mass* mass = new Mass("Mass", 1, inertia);
  group->addChild(mass);
  RevoluteJoint* revoluteJoint = new RevoluteJoint("Revolute Joint");
  revoluteJoint->setEnableExternalForce(true);
  group->addChild(revoluteJoint);
  RigidBody *rigidBody2 = new RigidBody("Rigid Body 2");
  rigidBody2->addLink("externalInteractLink");
  rigidBody2->addLink("internalInteractLink");
  rigidBody2->addLink("internalInteractLink2");
  group->addChild(rigidBody2);
  Mass* mass2 = new Mass("Mass 2", 1, inertia);
  group->addChild(mass2);

  ExternalInteract* externalInteract = new ExternalInteract("ExternalInteract");
  externalInteract->setPosition(mass->getPosition());
  externalInteract->setEnableAllOutputs(true);
  group->addChild(externalInteract);

  ExternalInteract* externalInteract2 = new ExternalInteract("ExternalInteract 2");
  externalInteract2->setPosition(mass2->getPosition());
  externalInteract2->setEnableAllOutputs(true);
  group->addChild(externalInteract2);

  group->connect(mobileRootJoint->getPort("link"), rigidBody->getPort("link0"));
  group->connect(rigidBody->getPort("link1"), mass->getPort("link"));
  group->connect(rigidBody->getPort("link2"), revoluteJoint->getPort("link0"));
  group->connect(revoluteJoint->getPort("link1"), rigidBody2->getPort("link0"));
  group->connect(rigidBody2->getPort("link1"), mass2->getPort("link"));
  group->connect(rigidBody->getPort("externalInteractLink"), externalInteract->getPort("link"));
  group->connect(rigidBody2->getPort("externalInteractLink"), externalInteract2->getPort("link"));

  ConstModel* jointForce = new ConstModel("Joint Force", 1);
  group->addChild(jointForce);

  group->connect(jointForce->getPort("output"),
                 revoluteJoint->getPort("force"));

  InternalInteract* internalInteract = new InternalInteract("InternalInteract");
  internalInteract->setPosition0(Vector3(0, 0, 1));
  internalInteract->setPosition1(Vector3(0, 0, 0.8));
  internalInteract->setEnableAllOutputs(true);
  internalInteract->setEnableForce(true);
  group->addChild(internalInteract);
  group->connect(internalInteract->getPort("link0"),
                 rigidBody->getPort("internalInteractLink"));
  group->connect(internalInteract->getPort("link1"),
                 rigidBody2->getPort("internalInteractLink"));


  InternalInteract* internalInteract2 = new InternalInteract("InternalInteract2");
  internalInteract2->setPosition0(Vector3(0, 0, 0.8));
  internalInteract2->setPosition1(Vector3(0, 0, 1));
  internalInteract2->setEnableAllOutputs(true);
  group->addChild(internalInteract2);
  group->connect(internalInteract2->getPort("link1"),
                 rigidBody->getPort("internalInteractLink2"));
  group->connect(internalInteract2->getPort("link0"),
                 rigidBody2->getPort("internalInteractLink2"));

  LinearSpringDamper* damper = new LinearSpringDamper("LinearSpringDamper");
  damper->setSpringConstant(0.5);
  damper->setDamperConstant(1);
  group->addChild(damper);
  group->connect(damper->getPort("velocity"),
                 internalInteract->getPort("velocity"));
  group->connect(damper->getPort("position"),
                 internalInteract->getPort("distance"));
  group->connect(damper->getPort("force"),
                 internalInteract->getPort("force"));

  return group.release();
}
Beispiel #5
0
bool Shader::ProcessSource(SharedArrayPtr<char>& dest, unsigned& length, const String& fileName)
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    if (!cache)
        return false;
    
    // Allow to define only a vertex shader or only a pixel shader
    if (!cache->Exists(fileName))
        return true;
    
    cache->StoreResourceDependency(this, fileName);
    
    Vector<String> glslCode;
    
    // Load the shader source code
    SharedPtr<File> glslFile = cache->GetFile(fileName);
    if (!glslFile)
        return false;
    
    while (!glslFile->IsEof())
        glslCode.Push(glslFile->ReadLine());
    
    // Process the code for includes
    for (unsigned i = 0; i < glslCode.Size(); ++i)
    {
        if (glslCode[i].StartsWith("#include"))
        {
            String includeFileName = GetPath(fileName) + glslCode[i].Substring(9).Replaced("\"", "").Trimmed();
            
            SharedPtr<File> glslIncludeFile = cache->GetFile(includeFileName);
            if (!glslIncludeFile)
                return false;
            
            // Remove the #include line, then include the code
            glslCode.Erase(i);
            unsigned pos = i;
            while (!glslIncludeFile->IsEof())
            {
                glslCode.Insert(pos, glslIncludeFile->ReadLine());
                ++pos;
            }
            // Finally insert an empty line to mark the space between files
            glslCode.Insert(pos, "");
        }
    }
    
    // Copy the final code into one memory block
    length = 0;
    for (unsigned i = 0; i < glslCode.Size(); ++i)
        length += glslCode[i].Length() + 1;
    
    dest = new char[length];
    char* destPtr = dest.Get();
    for (unsigned i = 0; i < glslCode.Size(); ++i)
    {
        memcpy(destPtr, glslCode[i].CString(), glslCode[i].Length());
        destPtr += glslCode[i].Length();
        *destPtr++ = '\n';
    }
    
    return true;
}
void NetworkModule::Stop ()
{
    SharedPtr<NetworkBinding> b = this->variables.cast<NetworkBinding>();
    b->Shutdown();
}
Beispiel #7
0
void bar(SharedPtr<Foo> ptr)
{
    int i = ptr->Get();
    assert(i == 1);
}
Beispiel #8
0
void TerrySpawner::HandleNodeCollisionStart(StringHash eventType, VariantMap& eventData)
{
	using namespace NodeCollisionStart;

	SharedPtr<Node> otherNode = SharedPtr<Node>(static_cast<Node*>(eventData[P_OTHERNODE].GetPtr()));
	RigidBody* rb = static_cast<RigidBody*>(eventData[P_BODY].GetPtr());

	Node* noed = rb->GetNode();

	if (otherNode->GetName() == "safetyNet")
	{
		RespawnTerry(noed);
		return;
	}

	if (!otherNode->HasComponent<Health>())
	{
		return;
	}

	if (otherNode->GetVar("npcType").GetInt() == 0)//hero
	{
		MoveByTouch* mbt = noed->GetComponent<MoveByTouch>();
		mbt->MoveTo(otherNode->GetWorldPosition(),
				mbt->moveToSpeed_,mbt->speedRamp_,mbt->gravity_,mbt->gravityRamp_,false,true,true);

		int collisionCount = noed->GetVar("collisionCount").GetInt();
		collisionCount++;
		noed->SetVar("collisionCount", collisionCount);

		if (collisionCount == 1)
		{
			VariantMap vm;
			vm[AnimateSceneNode::P_NODE] = noed;

			if (noed->GetVar("sex").GetBool())
			{
				vm[AnimateSceneNode::P_ANIMATION] = "attackF";
			}
			else
			{
				vm[AnimateSceneNode::P_ANIMATION] = "attackM";
			}

			vm[AnimateSceneNode::P_LOOP] = false;
			vm[AnimateSceneNode::P_LAYER] = 0;
			SendEvent(E_ANIMATESCENENODE, vm);
		}

		if (noed->GetComponent<Blind>() || noed->GetComponent<Stunned>())
		{
			return;
		}

		int healthMod = noed->GetVar("attack").GetInt();

		if (otherNode->HasComponent<Armor>())
		{
			healthMod = noed->GetVar("attack").GetInt() - otherNode->GetComponent<Armor>()->armor_;

			if (healthMod < 0)
			{
				healthMod = 0;
			}
		}

		otherNode->GetComponent<Health>()->ModifyHealth(healthMod, -1, false);

		if (otherNode->GetComponent<Health>()->health_ <= 0)
		{
			if (otherNode->GetName() != "tent")
			{
				if (!otherNode->HasComponent<Dead>())
				{
					otherNode->AddComponent(new Dead(context_, main_, -1.0f), 0, LOCAL);
				}
			}
			else
			{
				SpriteSheetPlayer* ssp = main_->mySceneNode_->GetComponent<SpriteSheetPlayer>();
				for (int x = 0; x < ssp->sprites_.Size(); x++)
				{
					if (!ssp->sprites_[x]->noed_->HasComponent<Dead>())
					{
						ssp->sprites_[x]->noed_->AddComponent(new Dead(context_, main_, -1.0f), 0, LOCAL);

						Node* particleStartNode_ = ssp->sprites_[x]->noed_->GetScene()->CreateChild(0,LOCAL);
						particleStartNode_->SetPosition(ssp->sprites_[x]->noed_->GetPosition());

						particleStartNode_->AddComponent(new TimedRemove(context_, main_, 2.0f), 0, LOCAL);

						particleStartNode_->AddComponent(new SoundSource3D(context_), 0, LOCAL);
						particleStartNode_->GetComponent<SoundSource3D>()->SetGain(0.1f);
						particleStartNode_->GetComponent<SoundSource3D>()->Play(main_->cache_->GetResource<Sound>("Sounds/319071__mishicu__v8.ogg"));

					}
				}
			}

			//otherNode->GetComponent<Health>()->ModifyHealth(100, 0, false);
			//otherNode->GetScene()->GetComponent<TerrySpawner>()->RespawnTerry(otherNode);
			return;
		}

		/*if (!noed->HasComponent<Stunned>())
		{
			noed->AddComponent(new Stunned(context_, main_, 2.0f), 0, LOCAL);
		}*/
	}
}
Beispiel #9
0
void TerrySpawner::HandleNodeCollision(StringHash eventType, VariantMap& eventData)
{
	using namespace NodeCollision;

	RigidBody* rb = static_cast<RigidBody*>(eventData[P_BODY].GetPtr());

	Node* noed = rb->GetNode();

	if (!noed->GetVar("canAttack").GetBool())
	{
		return;
	}

	if (noed->GetComponent<Blind>())
	{
		return;
	}

	noed->SetVar("canAttack", false);

	SharedPtr<Node> otherNode = SharedPtr<Node>(static_cast<Node*>(eventData[P_OTHERNODE].GetPtr()));

	if (!otherNode->HasComponent<Health>())
	{
		return;
	}

	bool enemy = false;

	if (otherNode->GetVar("npcType").GetInt() == 0)//hero
	{
		enemy = true;
	}

	if (enemy || noed->HasComponent<Enchanted>())
	{
		int healthMod = noed->GetVar("attack").GetInt();

		if (otherNode->HasComponent<Armor>())
		{
			healthMod = noed->GetVar("attack").GetInt() - otherNode->GetComponent<Armor>()->armor_;

			if (healthMod < 0)
			{
				healthMod = 0;
			}
		}

		otherNode->GetComponent<Health>()->ModifyHealth(healthMod, -1, false);

		if (otherNode->GetComponent<Health>()->health_ <= 0)
		{
			if (!enemy && noed->HasComponent<Enchanted>())
			{
				otherNode->GetComponent<Health>()->ModifyHealth(100, 0, false);
				otherNode->GetScene()->GetComponent<TerrySpawner>()->RespawnTerry(otherNode);
			}
			else if (otherNode->GetName() != "tent")
			{
				if (!otherNode->HasComponent<Dead>())
				{
					otherNode->AddComponent(new Dead(context_, main_, -1.0f), 0, LOCAL);
				}
			}
			else
			{
				SpriteSheetPlayer* ssp = main_->mySceneNode_->GetComponent<SpriteSheetPlayer>();
				for (int x = 0; x < ssp->sprites_.Size(); x++)
				{
					if (!ssp->sprites_[x]->noed_->HasComponent<Dead>())
					{
						ssp->sprites_[x]->noed_->AddComponent(new Dead(context_, main_, -1.0f), 0, LOCAL);

						Node* particleStartNode_ = ssp->sprites_[x]->noed_->GetScene()->CreateChild(0,LOCAL);
						particleStartNode_->SetPosition(ssp->sprites_[x]->noed_->GetPosition());

						particleStartNode_->AddComponent(new TimedRemove(context_, main_, 2.0f), 0, LOCAL);

						particleStartNode_->AddComponent(new SoundSource3D(context_), 0, LOCAL);
						particleStartNode_->GetComponent<SoundSource3D>()->SetGain(0.1f);
						particleStartNode_->GetComponent<SoundSource3D>()->Play(main_->cache_->GetResource<Sound>("Sounds/319071__mishicu__v8.ogg"));

					}
				}
			}

			return;
		}

		/*if (!noed->HasComponent<Stunned>())
		{
			noed->AddComponent(new Stunned(context_, main_, 2.0f), 0, LOCAL);
		}*/
	}
}
//
// main
//
int main(int argc, char **argv) {
#ifdef __unix__
   // Load wxWindows Stub (for pop-up dialogues)
   (void)dlopen(WXSTUB_DLL_NAME, RTLD_NOW|RTLD_NODELETE);
#endif

#ifdef LOG
   char buff[1000];
   if (getUserDataDir(buff, sizeof(buff)) != 0) {
      strcpy(buff, "c:");
   }
   strcat(buff, "/gdbServer.log");
   FILE *errorLog = fopen(buff, "wt");
   Logging::setLogFileHandle(errorLog);
#endif
   Logging::setLoggingLevel(100);
   LOGGING;

#ifdef LOG
   Logging::print("Args = ");
   for (int index=0; index<argc; index++) {
      Logging::printq("%s ", argv[index]);
   }
   Logging::printq("\n");
#endif
   if (signal(SIGINT, signalHandler) == SIG_IGN) {
      (void)signal(SIGINT, SIG_IGN);
   }

   shared = SharedPtr(new Shared(TARGET_TYPE));

   USBDM_ErrorCode rc = doArgs(argc, argv);
   if (rc != BDM_RC_OK) {
      Logging::print("Error %s\n", USBDM_GetErrorString(rc));
      exit (-1);
   }
   Logging::print("After doArgs\n");

   rc = shared->initBdm();
   if (rc != BDM_RC_OK) {
      Logging::print("Error %s\n", USBDM_GetErrorString(rc));
      exit (-1);
   }
   Logging::print("After shared->initBdm()\n");
   //   setDefaultWindowParent(FindEclipseWindowHwnd());

   GdbInOutPipe  *gdbInOut  = GdbInOutPipe::getGdbInOut();
   Logging::print("After GdbInOutPipe::getGdbInOut()\n");

   // Redirect stdout to stderr
   dup2(2,1);

   if (gdbInOut == NULL) {
      Logging::print("Error gdbInOut() creation failed\n");
      exit (-1);
   }
   Logging::print("After gdbInOut()\n");

   // Now do the actual processing of GDB messages
   gdbHandlerInit(gdbInOut, *shared->getCurrentDevice(), callBack);
   gdbLoop(gdbInOut);

   gdbInOut->finish();
   delete gdbInOut;

   return 0;
}
Beispiel #11
0
bool Texture3D::Load(Deserializer& source)
{
    PROFILE(LoadTexture3D);
    
    // In headless mode, do not actually load the texture, just return success
    if (!graphics_)
        return true;
    
    // If device is lost, retry later
    if (graphics_->IsDeviceLost())
    {
        LOGWARNING("Texture load while device is lost");
        dataPending_ = true;
        return true;
    }
    
    // If over the texture budget, see if materials can be freed to allow textures to be freed
    CheckTextureBudget(GetTypeStatic());

    // Before actually loading the texture, get optional parameters from an XML description file
    LoadParameters();

    String texPath, texName, texExt;
    SplitPath(GetName(), texPath, texName, texExt);
    
    SharedPtr<XMLFile> xml(new XMLFile(context_));
    if (!xml->Load(source))
        return false;

    XMLElement textureElem = xml->GetRoot();
    XMLElement volumeElem = textureElem.GetChild("volume");
    XMLElement colorlutElem = textureElem.GetChild("colorlut");

    if (volumeElem)
    {
        String name = volumeElem.GetAttribute("name");
        
        String volumeTexPath, volumeTexName, volumeTexExt;
        SplitPath(name, volumeTexPath, volumeTexName, volumeTexExt);
        // If path is empty, add the XML file path
        if (volumeTexPath.Empty())
            name = texPath + name;

        SharedPtr<Image> image(GetSubsystem<ResourceCache>()->GetResource<Image>(name));
        return Load(image);
    }
    else if (colorlutElem)
    {
        String name = colorlutElem.GetAttribute("name");
        
        String colorlutTexPath, colorlutTexName, colorlutTexExt;
        SplitPath(name, colorlutTexPath, colorlutTexName, colorlutTexExt);
        // If path is empty, add the XML file path
        if (colorlutTexPath.Empty())
            name = texPath + name;

        SharedPtr<File> file = GetSubsystem<ResourceCache>()->GetFile(name);
        SharedPtr<Image> image(new Image(context_));
        if (!image->LoadColorLUT(*(file.Get())))
            return false;

        return Load(image);
    }

    return false;
}
void DotsNetCrits::AttachLogicComponents(SharedPtr<Node> sceneNode)
{
	sceneNode->AddComponent(new ModelPlayer(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new TopDownCamera(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new ThirdPersonCamera(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Speed(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Gravity(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new MoveByTouch(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new RotateTo(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Silence(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Teleport(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Sprint(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Snare(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Blind(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Melee(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Health(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Mute(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Armor(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Shield(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new DPSHeal(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new BlindingFlash(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Crit(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new DOT(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new DOTHeal(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new AOE(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new AOEHeal(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Cloak(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Cleanse(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new Knockback(context_, main_), 0, LOCAL);

	sceneNode->AddComponent(new SoundPlayer(context_, main_), 0, LOCAL);
}
void WebFrameLoaderClient::setTitle(const String& title, const KURL& url)
{
#if OS(AMIGAOS4)
    if (!m_webFrame->parentFrame()) {
        BalWidget* viewWindow = m_webFrame->webView()->viewWindow();
        if (viewWindow && viewWindow->window) {
            extern char* utf8ToAmiga(const char* utf8);

            char *titlestr = utf8ToAmiga(title.utf8().data());
            if (titlestr && titlestr[0])
                snprintf(viewWindow->title, sizeof(viewWindow->title), viewWindow->clickTabNode ? "%s" : "OWB: %s", titlestr);
            else
                strcpy(viewWindow->title, "Origyn Web Browser");
            free(titlestr);

            if (amigaConfig.tabs) {
                IIntuition->SetGadgetAttrs(viewWindow->gad_clicktab, viewWindow->window, NULL,
                                           CLICKTAB_Labels, ~0,
                                           TAG_DONE);

                IClickTab->SetClickTabNodeAttrs(viewWindow->clickTabNode, TNA_Text, viewWindow->title, TAG_DONE);

                IIntuition->RefreshSetGadgetAttrs(viewWindow->gad_clicktab, viewWindow->window, NULL,
                                                  CLICKTAB_Labels, viewWindow->clickTabList,
                                                  TAG_DONE);
            }
            else
                IIntuition->SetWindowTitles(viewWindow->window, viewWindow->title, (STRPTR)~0UL);

            CString urlLatin1 = url.prettyURL().latin1();
            const char *urlstr = urlLatin1.data();
            if (urlstr && urlstr[0] && viewWindow->gad_url) {
                snprintf(viewWindow->url, sizeof(viewWindow->url), "%s", urlstr);
                if (ILayout->SetPageGadgetAttrs(viewWindow->gad_url, viewWindow->page,
                                                viewWindow->window, NULL,
                                                STRINGA_TextVal, viewWindow->url,
                                                TAG_DONE))
                    ILayout->RefreshPageGadget(viewWindow->gad_url, viewWindow->page, viewWindow->window, NULL);
            }
        }
    }
#endif
    WebView* webView = m_webFrame->webView();
    SharedPtr<WebHistoryDelegate> historyDelegate = webView->historyDelegate();
    if (historyDelegate) {
        historyDelegate->updateHistoryTitle(webView, title.utf8().data(), url.string().utf8().data());
        return;
    }
    bool privateBrowsingEnabled = false;
    WebPreferences* preferences = m_webFrame->webView()->preferences();
    if (preferences)
        privateBrowsingEnabled = preferences->privateBrowsingEnabled();
    if (privateBrowsingEnabled)
        return;

    // update title in global history
    WebHistory* history = webHistory();
    if (!history)
        return;

    WebHistoryItem* item = history->itemForURL(strdup(url.string().utf8().data()));
    if (!item)
        return;

    item->setTitle(title.utf8().data());
}
void WebFrameLoaderClient::postProgressEstimateChangedNotification()
{
    SharedPtr<WebNotificationDelegate> webNotificationDelegate = m_webFrame->webView()->webNotificationDelegate();
    if (webNotificationDelegate)
        webNotificationDelegate->progressNotification(m_webFrame);
}
Beispiel #15
0
void AnimatedModel::CloneGeometries()
{
    const Vector<SharedPtr<VertexBuffer> >& originalVertexBuffers = model_->GetVertexBuffers();
    HashMap<VertexBuffer*, SharedPtr<VertexBuffer> > clonedVertexBuffers;
    morphVertexBuffers_.Resize(originalVertexBuffers.Size());

    for (unsigned i = 0; i < originalVertexBuffers.Size(); ++i)
    {
        VertexBuffer* original = originalVertexBuffers[i];
        if (model_->GetMorphRangeCount(i))
        {
            SharedPtr<VertexBuffer> clone(new VertexBuffer(context_));
            clone->SetShadowed(true);
            clone->SetSize(original->GetVertexCount(), morphElementMask_ & original->GetElementMask(), true);
            void* dest = clone->Lock(0, original->GetVertexCount());
            if (dest)
            {
                CopyMorphVertices(dest, original->GetShadowData(), original->GetVertexCount(), clone, original);
                clone->Unlock();
            }
            clonedVertexBuffers[original] = clone;
            morphVertexBuffers_[i] = clone;
        }
        else
            morphVertexBuffers_[i].Reset();
    }

    // Geometries will always be cloned fully. They contain only references to buffer, so they are relatively light
    for (unsigned i = 0; i < geometries_.Size(); ++i)
    {
        for (unsigned j = 0; j < geometries_[i].Size(); ++j)
        {
            SharedPtr<Geometry> original = geometries_[i][j];
            SharedPtr<Geometry> clone(new Geometry(context_));

            // Add an additional vertex stream into the clone, which supplies only the morphable vertex data, while the static
            // data comes from the original vertex buffer(s)
            const Vector<SharedPtr<VertexBuffer> >& originalBuffers = original->GetVertexBuffers();
            unsigned totalBuf = originalBuffers.Size();
            for (unsigned k = 0; k < originalBuffers.Size(); ++k)
            {
                VertexBuffer* originalBuffer = originalBuffers[k];
                if (clonedVertexBuffers.Contains(originalBuffer))
                    ++totalBuf;
            }
            clone->SetNumVertexBuffers(totalBuf);

            unsigned l = 0;
            for (unsigned k = 0; k < originalBuffers.Size(); ++k)
            {
                VertexBuffer* originalBuffer = originalBuffers[k];

                if (clonedVertexBuffers.Contains(originalBuffer))
                {
                    VertexBuffer* clonedBuffer = clonedVertexBuffers[originalBuffer];
                    clone->SetVertexBuffer(l++, originalBuffer);
                    // Specify the morph buffer at a greater index to override the model's original positions/normals/tangents
                    clone->SetVertexBuffer(l++, clonedBuffer);
                }
                else
                    clone->SetVertexBuffer(l++, originalBuffer);
            }

            clone->SetIndexBuffer(original->GetIndexBuffer());
            clone->SetDrawRange(original->GetPrimitiveType(), original->GetIndexStart(), original->GetIndexCount());
            clone->SetLodDistance(original->GetLodDistance());

            geometries_[i][j] = clone;
        }
    }

    // Make sure the rendering batches use the new cloned geometries
    ResetLodLevels();
    MarkMorphsDirty();
}
Beispiel #16
0
	void FileStream::WriteLine(const ValueList& args, SharedValue result)
	{
		if(! this->stream)
		{
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			SharedKObject b = args.at(0)->ToObject();
			SharedPtr<Blob> blob = b.cast<Blob>();
			if (!blob.isNull())
			{
				text = (char*)blob->Get();
				size = (int)blob->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		std::string astr = text;
#ifdef OS_WIN32
		astr += "\r\n";
#else
		astr += "\n";
#endif
		Write((char*)astr.c_str(),astr.length());
		result->SetBool(true);
	}
void DynamicGeometry::CreateScene()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();

    scene_ = new Scene(context_);

    // Create the Octree component to the scene so that drawable objects can be rendered. Use default volume
    // (-1000, -1000, -1000) to (1000, 1000, 1000)
    scene_->CreateComponent<Octree>();

    // Create a Zone for ambient light & fog control
    Node* zoneNode = scene_->CreateChild("Zone");
    Zone* zone = zoneNode->CreateComponent<Zone>();
    zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f));
    zone->SetFogColor(Color(0.2f, 0.2f, 0.2f));
    zone->SetFogStart(200.0f);
    zone->SetFogEnd(300.0f);

    // Create a directional light
    Node* lightNode = scene_->CreateChild("DirectionalLight");
    lightNode->SetDirection(Vector3(-0.6f, -1.0f, -0.8f)); // The direction vector does not need to be normalized
    Light* light = lightNode->CreateComponent<Light>();
    light->SetLightType(LIGHT_DIRECTIONAL);
    light->SetColor(Color(0.4f, 1.0f, 0.4f));
    light->SetSpecularIntensity(1.5f);

    // Get the original model and its unmodified vertices, which are used as source data for the animation
    Model* originalModel = cache->GetResource<Model>("Models/Box.mdl");
    if (!originalModel)
    {
        ATOMIC_LOGERROR("Model not found, cannot initialize example scene");
        return;
    }
    // Get the vertex buffer from the first geometry's first LOD level
    VertexBuffer* buffer = originalModel->GetGeometry(0, 0)->GetVertexBuffer(0);
    const unsigned char* vertexData = (const unsigned char*)buffer->Lock(0, buffer->GetVertexCount());
    if (vertexData)
    {
        unsigned numVertices = buffer->GetVertexCount();
        unsigned vertexSize = buffer->GetVertexSize();
        // Copy the original vertex positions
        for (unsigned i = 0; i < numVertices; ++i)
        {
            const Vector3& src = *reinterpret_cast<const Vector3*>(vertexData + i * vertexSize);
            originalVertices_.Push(src);
        }
        buffer->Unlock();

        // Detect duplicate vertices to allow seamless animation
        vertexDuplicates_.Resize(originalVertices_.Size());
        for (unsigned i = 0; i < originalVertices_.Size(); ++i)
        {
            vertexDuplicates_[i] = i; // Assume not a duplicate
            for (unsigned j = 0; j < i; ++j)
            {
                if (originalVertices_[i].Equals(originalVertices_[j]))
                {
                    vertexDuplicates_[i] = j;
                    break;
                }
            }
        }
    }
    else
    {
        ATOMIC_LOGERROR("Failed to lock the model vertex buffer to get original vertices");
        return;
    }

    // Create StaticModels in the scene. Clone the model for each so that we can modify the vertex data individually
    for (int y = -1; y <= 1; ++y)
    {
        for (int x = -1; x <= 1; ++x)
        {
            Node* node = scene_->CreateChild("Object");
            node->SetPosition(Vector3(x * 2.0f, 0.0f, y * 2.0f));
            StaticModel* object = node->CreateComponent<StaticModel>();
            SharedPtr<Model> cloneModel = originalModel->Clone();
            object->SetModel(cloneModel);
            // Store the cloned vertex buffer that we will modify when animating
            animatingBuffers_.Push(SharedPtr<VertexBuffer>(cloneModel->GetGeometry(0, 0)->GetVertexBuffer(0)));
        }
    }

    // Finally create one model (pyramid shape) and a StaticModel to display it from scratch
    // Note: there are duplicated vertices to enable face normals. We will calculate normals programmatically
    {
        const unsigned numVertices = 18;

        float vertexData[] = {
            // Position             Normal
            0.0f, 0.5f, 0.0f,       0.0f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f,      0.0f, 0.0f, 0.0f,
            0.5f, -0.5f, -0.5f,     0.0f, 0.0f, 0.0f,

            0.0f, 0.5f, 0.0f,       0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f,      0.0f, 0.0f, 0.0f,

            0.0f, 0.5f, 0.0f,       0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f,    0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 0.0f,

            0.0f, 0.5f, 0.0f,       0.0f, 0.0f, 0.0f,
            0.5f, -0.5f, -0.5f,     0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f,    0.0f, 0.0f, 0.0f,

            0.5f, -0.5f, -0.5f,     0.0f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f,      0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 0.0f,

            0.5f, -0.5f, -0.5f,     0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f,    0.0f, 0.0f, 0.0f
        };

        const unsigned short indexData[] = {
            0, 1, 2,
            3, 4, 5,
            6, 7, 8,
            9, 10, 11,
            12, 13, 14,
            15, 16, 17
        };

        // Calculate face normals now
        for (unsigned i = 0; i < numVertices; i += 3)
        {
            Vector3& v1 = *(reinterpret_cast<Vector3*>(&vertexData[6 * i]));
            Vector3& v2 = *(reinterpret_cast<Vector3*>(&vertexData[6 * (i + 1)]));
            Vector3& v3 = *(reinterpret_cast<Vector3*>(&vertexData[6 * (i + 2)]));
            Vector3& n1 = *(reinterpret_cast<Vector3*>(&vertexData[6 * i + 3]));
            Vector3& n2 = *(reinterpret_cast<Vector3*>(&vertexData[6 * (i + 1) + 3]));
            Vector3& n3 = *(reinterpret_cast<Vector3*>(&vertexData[6 * (i + 2) + 3]));

            Vector3 edge1 = v1 - v2;
            Vector3 edge2 = v1 - v3;
            n1 = n2 = n3 = edge1.CrossProduct(edge2).Normalized();
        }

        SharedPtr<Model> fromScratchModel(new Model(context_));
        SharedPtr<VertexBuffer> vb(new VertexBuffer(context_));
        SharedPtr<IndexBuffer> ib(new IndexBuffer(context_));
        SharedPtr<Geometry> geom(new Geometry(context_));

        // Shadowed buffer needed for raycasts to work, and so that data can be automatically restored on device loss
        vb->SetShadowed(true);
        // We could use the "legacy" element bitmask to define elements for more compact code, but let's demonstrate
        // defining the vertex elements explicitly to allow any element types and order
        PODVector<VertexElement> elements;
        elements.Push(VertexElement(TYPE_VECTOR3, SEM_POSITION));
        elements.Push(VertexElement(TYPE_VECTOR3, SEM_NORMAL));
        vb->SetSize(numVertices, elements);
        vb->SetData(vertexData);

        ib->SetShadowed(true);
        ib->SetSize(numVertices, false);
        ib->SetData(indexData);

        geom->SetVertexBuffer(0, vb);
        geom->SetIndexBuffer(ib);
        geom->SetDrawRange(TRIANGLE_LIST, 0, numVertices);

        fromScratchModel->SetNumGeometries(1);
        fromScratchModel->SetGeometry(0, 0, geom);
        fromScratchModel->SetBoundingBox(BoundingBox(Vector3(-0.5f, -0.5f, -0.5f), Vector3(0.5f, 0.5f, 0.5f)));

        // Though not necessary to render, the vertex & index buffers must be listed in the model so that it can be saved properly
        Vector<SharedPtr<VertexBuffer> > vertexBuffers;
        Vector<SharedPtr<IndexBuffer> > indexBuffers;
        vertexBuffers.Push(vb);
        indexBuffers.Push(ib);
        // Morph ranges could also be not defined. Here we simply define a zero range (no morphing) for the vertex buffer
        PODVector<unsigned> morphRangeStarts;
        PODVector<unsigned> morphRangeCounts;
        morphRangeStarts.Push(0);
        morphRangeCounts.Push(0);
        fromScratchModel->SetVertexBuffers(vertexBuffers, morphRangeStarts, morphRangeCounts);
        fromScratchModel->SetIndexBuffers(indexBuffers);

        Node* node = scene_->CreateChild("FromScratchObject");
        node->SetPosition(Vector3(0.0f, 3.0f, 0.0f));
        StaticModel* object = node->CreateComponent<StaticModel>();
        object->SetModel(fromScratchModel);
    }

    // Create the camera
    cameraNode_ = new Node(context_);
    cameraNode_->SetPosition(Vector3(0.0f, 2.0f, -20.0f));
    Camera* camera = cameraNode_->CreateComponent<Camera>();
    camera->SetFarClip(300.0f);
}
	inline void operator()(Topology &t,const SharedPtr<Peer> &p)
	{
		if (p->resetWithinScope(RR,_scope,_now))
			peersReset.push_back(p);
	}
Beispiel #19
0
bool Texture3D::BeginLoad(Deserializer& source)
{
    auto* cache = GetSubsystem<ResourceCache>();

    // In headless mode, do not actually load the texture, just return success
    if (!graphics_)
        return true;

    // If device is lost, retry later
    if (graphics_->IsDeviceLost())
    {
        URHO3D_LOGWARNING("Texture load while device is lost");
        dataPending_ = true;
        return true;
    }

    String texPath, texName, texExt;
    SplitPath(GetName(), texPath, texName, texExt);

    cache->ResetDependencies(this);

    loadParameters_ = new XMLFile(context_);
    if (!loadParameters_->Load(source))
    {
        loadParameters_.Reset();
        return false;
    }

    XMLElement textureElem = loadParameters_->GetRoot();
    XMLElement volumeElem = textureElem.GetChild("volume");
    XMLElement colorlutElem = textureElem.GetChild("colorlut");

    if (volumeElem)
    {
        String name = volumeElem.GetAttribute("name");

        String volumeTexPath, volumeTexName, volumeTexExt;
        SplitPath(name, volumeTexPath, volumeTexName, volumeTexExt);
        // If path is empty, add the XML file path
        if (volumeTexPath.Empty())
            name = texPath + name;

        loadImage_ = cache->GetTempResource<Image>(name);
        // Precalculate mip levels if async loading
        if (loadImage_ && GetAsyncLoadState() == ASYNC_LOADING)
            loadImage_->PrecalculateLevels();
        cache->StoreResourceDependency(this, name);
        return true;
    }
    else if (colorlutElem)
    {
        String name = colorlutElem.GetAttribute("name");

        String colorlutTexPath, colorlutTexName, colorlutTexExt;
        SplitPath(name, colorlutTexPath, colorlutTexName, colorlutTexExt);
        // If path is empty, add the XML file path
        if (colorlutTexPath.Empty())
            name = texPath + name;

        SharedPtr<File> file = GetSubsystem<ResourceCache>()->GetFile(name);
        loadImage_ = new Image(context_);
        if (!loadImage_->LoadColorLUT(*(file.Get())))
        {
            loadParameters_.Reset();
            loadImage_.Reset();
            return false;
        }
        // Precalculate mip levels if async loading
        if (loadImage_ && GetAsyncLoadState() == ASYNC_LOADING)
            loadImage_->PrecalculateLevels();
        cache->StoreResourceDependency(this, name);
        return true;
    }

    URHO3D_LOGERROR("Texture3D XML data for " + GetName() + " did not contain either volume or colorlut element");
    return false;
}
Beispiel #20
0
void LoadSkeleton(const String& skeletonFileName)
{
    // Process skeleton first (if found)
    XMLElement skeletonRoot;
    File skeletonFileSource(context_);
    skeletonFileSource.Open(skeletonFileName);
    if (!skelFile_->Load(skeletonFileSource))
        PrintLine("Failed to load skeleton " + skeletonFileName);
    skeletonRoot = skelFile_->GetRoot();

    if (skeletonRoot)
    {
        XMLElement bonesRoot = skeletonRoot.GetChild("bones");
        XMLElement bone = bonesRoot.GetChild("bone");
        while (bone)
        {
            unsigned index = bone.GetInt("id");
            String name = bone.GetAttribute("name");
            if (index >= bones_.Size())
                bones_.Resize(index + 1);

            // Convert from right- to left-handed
            XMLElement position = bone.GetChild("position");
            float x = position.GetFloat("x");
            float y = position.GetFloat("y");
            float z = position.GetFloat("z");
            Vector3 pos(x, y, -z);

            XMLElement rotation = bone.GetChild("rotation");
            XMLElement axis = rotation.GetChild("axis");
            float angle = -rotation.GetFloat("angle") * M_RADTODEG;
            x = axis.GetFloat("x");
            y = axis.GetFloat("y");
            z = axis.GetFloat("z");
            Vector3 axisVec(x, y, -z);
            Quaternion rot(angle, axisVec);

            bones_[index].name_ = name;
            bones_[index].parentIndex_ = index; // Fill in the correct parent later
            bones_[index].bindPosition_ = pos;
            bones_[index].bindRotation_ = rot;
            bones_[index].bindScale_ = Vector3::ONE;
            bones_[index].collisionMask_ = 0;
            bones_[index].radius_ = 0.0f;

            bone = bone.GetNext("bone");
        }

        // Go through the bone hierarchy
        XMLElement boneHierarchy = skeletonRoot.GetChild("bonehierarchy");
        XMLElement boneParent = boneHierarchy.GetChild("boneparent");
        while (boneParent)
        {
            String bone = boneParent.GetAttribute("bone");
            String parent = boneParent.GetAttribute("parent");
            unsigned i = 0, j = 0;
            for (i = 0; i < bones_.Size() && bones_[i].name_ != bone; ++i);
            for (j = 0; j < bones_.Size() && bones_[j].name_ != parent; ++j);

            if (i >= bones_.Size() || j >= bones_.Size())
                ErrorExit("Found indeterminate parent bone assignment");
            bones_[i].parentIndex_ = j;

            boneParent = boneParent.GetNext("boneparent");
        }

        // Calculate bone derived positions
        for (unsigned i = 0; i < bones_.Size(); ++i)
        {
            Vector3 derivedPosition = bones_[i].bindPosition_;
            Quaternion derivedRotation = bones_[i].bindRotation_;
            Vector3 derivedScale = bones_[i].bindScale_;

            unsigned index = bones_[i].parentIndex_;
            if (index != i)
            {
                for (;;)
                {
                    derivedPosition = bones_[index].bindPosition_ + (bones_[index].bindRotation_ * (bones_[index].bindScale_ * derivedPosition));
                    derivedRotation = bones_[index].bindRotation_ * derivedRotation;
                    derivedScale = bones_[index].bindScale_ * derivedScale;
                    if (bones_[index].parentIndex_ != index)
                        index = bones_[index].parentIndex_;
                    else
                        break;
                }
            }

            bones_[i].derivedPosition_ = derivedPosition;
            bones_[i].derivedRotation_ = derivedRotation;
            bones_[i].derivedScale_ = derivedScale;
            bones_[i].worldTransform_ = Matrix3x4(derivedPosition, derivedRotation, derivedScale);
            bones_[i].inverseWorldTransform_ = bones_[i].worldTransform_.Inverse();
        }

        PrintLine("Processed skeleton");
    }
}
Beispiel #21
0
bool WatcherMgr::RemoveWatcher(SharedPtr<WatcherBase> pWatcher)
{
    if(pWatcher.isNull())
        return false;
    return RemoveWatcher(pWatcher->GetConnID());
}
Beispiel #22
0
void LoadMesh(const String& inputFileName, bool generateTangents, bool splitSubMeshes, bool exportMorphs)
{
    File meshFileSource(context_);
    meshFileSource.Open(inputFileName);
    if (!meshFile_->Load(meshFileSource))
        ErrorExit("Could not load input file " + inputFileName);

    XMLElement root = meshFile_->GetRoot("mesh");
    XMLElement subMeshes = root.GetChild("submeshes");
    XMLElement skeletonLink = root.GetChild("skeletonlink");
    if (root.IsNull())
        ErrorExit("Could not load input file " + inputFileName);

    String skeletonName = skeletonLink.GetAttribute("name");
    if (!skeletonName.Empty())
        LoadSkeleton(GetPath(inputFileName) + GetFileName(skeletonName) + ".skeleton.xml");

    // Check whether there's benefit of avoiding 32bit indices by splitting each submesh into own buffer
    XMLElement subMesh = subMeshes.GetChild("submesh");
    unsigned totalVertices = 0;
    unsigned maxSubMeshVertices = 0;
    while (subMesh)
    {
        materialNames_.Push(subMesh.GetAttribute("material"));
        XMLElement geometry = subMesh.GetChild("geometry");
        if (geometry)
        {
            unsigned vertices = geometry.GetInt("vertexcount");
            totalVertices += vertices;
            if (maxSubMeshVertices < vertices)
                maxSubMeshVertices = vertices;
        }
        ++numSubMeshes_;

        subMesh = subMesh.GetNext("submesh");
    }

    XMLElement sharedGeometry = root.GetChild("sharedgeometry");
    if (sharedGeometry)
    {
        unsigned vertices = sharedGeometry.GetInt("vertexcount");
        totalVertices += vertices;
        if (maxSubMeshVertices < vertices)
            maxSubMeshVertices = vertices;
    }

    if (!sharedGeometry && (splitSubMeshes || (totalVertices > 65535 && maxSubMeshVertices <= 65535)))
    {
        useOneBuffer_ = false;
        vertexBuffers_.Resize(numSubMeshes_);
        indexBuffers_.Resize(numSubMeshes_);
    }
    else
    {
        vertexBuffers_.Resize(1);
        indexBuffers_.Resize(1);
    }

    subMesh = subMeshes.GetChild("submesh");
    unsigned indexStart = 0;
    unsigned vertexStart = 0;
    unsigned subMeshIndex = 0;

    PODVector<unsigned> vertexStarts;
    vertexStarts.Resize(numSubMeshes_);

    while (subMesh)
    {
        XMLElement geometry = subMesh.GetChild("geometry");
        XMLElement faces = subMesh.GetChild("faces");

        // If no submesh vertexbuffer, process the shared geometry, but do it only once
        unsigned vertices = 0;
        if (!geometry)
        {
            vertexStart = 0;
            if (!subMeshIndex)
                geometry = root.GetChild("sharedgeometry");
        }

        if (geometry)
            vertices = geometry.GetInt("vertexcount");

        ModelSubGeometryLodLevel subGeometryLodLevel;
        ModelVertexBuffer* vBuf;
        ModelIndexBuffer* iBuf;

        if (useOneBuffer_)
        {
            vBuf = &vertexBuffers_[0];
            if (vertices)
                vBuf->vertices_.Resize(vertexStart + vertices);
            iBuf = &indexBuffers_[0];

            subGeometryLodLevel.vertexBuffer_ = 0;
            subGeometryLodLevel.indexBuffer_ = 0;
        }
        else
        {
            vertexStart = 0;
            indexStart = 0;

            vBuf = &vertexBuffers_[subMeshIndex];
            vBuf->vertices_.Resize(vertices);
            iBuf = &indexBuffers_[subMeshIndex];

            subGeometryLodLevel.vertexBuffer_ = subMeshIndex;
            subGeometryLodLevel.indexBuffer_ = subMeshIndex;
        }

        // Store the start vertex for later use
        vertexStarts[subMeshIndex] = vertexStart;

        // Ogre may have multiple buffers in one submesh. These will be merged into one
        XMLElement bufferDef;
        if (geometry)
            bufferDef = geometry.GetChild("vertexbuffer");

        while (bufferDef)
        {
            if (bufferDef.HasAttribute("positions"))
                vBuf->elementMask_ |= MASK_POSITION;
            if (bufferDef.HasAttribute("normals"))
                vBuf->elementMask_ |= MASK_NORMAL;
            if (bufferDef.HasAttribute("texture_coords"))
            {
                vBuf->elementMask_ |= MASK_TEXCOORD1;
                if (bufferDef.GetInt("texture_coords") > 1)
                    vBuf->elementMask_ |= MASK_TEXCOORD2;
            }

            unsigned vertexNum = vertexStart;
            if (vertices)
            {
                XMLElement vertex = bufferDef.GetChild("vertex");
                while (vertex)
                {
                    XMLElement position = vertex.GetChild("position");
                    if (position)
                    {
                        // Convert from right- to left-handed
                        float x = position.GetFloat("x");
                        float y = position.GetFloat("y");
                        float z = position.GetFloat("z");
                        Vector3 vec(x, y, -z);

                        vBuf->vertices_[vertexNum].position_ = vec;
                        boundingBox_.Merge(vec);
                    }
                    XMLElement normal = vertex.GetChild("normal");
                    if (normal)
                    {
                        // Convert from right- to left-handed
                        float x = normal.GetFloat("x");
                        float y = normal.GetFloat("y");
                        float z = normal.GetFloat("z");
                        Vector3 vec(x, y, -z);

                        vBuf->vertices_[vertexNum].normal_ = vec;
                    }
                    XMLElement uv = vertex.GetChild("texcoord");
                    if (uv)
                    {
                        float x = uv.GetFloat("u");
                        float y = uv.GetFloat("v");
                        Vector2 vec(x, y);

                        vBuf->vertices_[vertexNum].texCoord1_ = vec;

                        if (vBuf->elementMask_ & MASK_TEXCOORD2)
                        {
                            uv = uv.GetNext("texcoord");
                            if (uv)
                            {
                                float x = uv.GetFloat("u");
                                float y = uv.GetFloat("v");
                                Vector2 vec(x, y);

                                vBuf->vertices_[vertexNum].texCoord2_ = vec;
                            }
                        }
                    }

                    vertexNum++;
                    vertex = vertex.GetNext("vertex");
                }
            }

            bufferDef = bufferDef.GetNext("vertexbuffer");
        }

        unsigned triangles = faces.GetInt("count");
        unsigned indices = triangles * 3;

        XMLElement triangle = faces.GetChild("face");
        while (triangle)
        {
            unsigned v1 = triangle.GetInt("v1");
            unsigned v2 = triangle.GetInt("v2");
            unsigned v3 = triangle.GetInt("v3");
            iBuf->indices_.Push(v3 + vertexStart);
            iBuf->indices_.Push(v2 + vertexStart);
            iBuf->indices_.Push(v1 + vertexStart);
            triangle = triangle.GetNext("face");
        }

        subGeometryLodLevel.indexStart_ = indexStart;
        subGeometryLodLevel.indexCount_ = indices;
        if (vertexStart + vertices > 65535)
            iBuf->indexSize_ = sizeof(unsigned);

        XMLElement boneAssignments = subMesh.GetChild("boneassignments");
        if (bones_.Size())
        {
            if (boneAssignments)
            {
                XMLElement boneAssignment = boneAssignments.GetChild("vertexboneassignment");
                while (boneAssignment)
                {
                    unsigned vertex = boneAssignment.GetInt("vertexindex") + vertexStart;
                    unsigned bone = boneAssignment.GetInt("boneindex");
                    float weight = boneAssignment.GetFloat("weight");

                    BoneWeightAssignment assign;
                    assign.boneIndex_ = bone;
                    assign.weight_ = weight;
                    // Source data might have 0 weights. Disregard these
                    if (assign.weight_ > 0.0f)
                    {
                        subGeometryLodLevel.boneWeights_[vertex].Push(assign);

                        // Require skinning weight to be sufficiently large before vertex contributes to bone hitbox
                        if (assign.weight_ > 0.33f)
                        {
                            // Check distance of vertex from bone to get bone max. radius information
                            Vector3 bonePos = bones_[bone].derivedPosition_;
                            Vector3 vertexPos = vBuf->vertices_[vertex].position_;
                            float distance = (bonePos - vertexPos).Length();
                            if (distance > bones_[bone].radius_)
                            {
                                bones_[bone].collisionMask_ |= 1;
                                bones_[bone].radius_ = distance;
                            }
                            // Build the hitbox for the bone
                            bones_[bone].boundingBox_.Merge(bones_[bone].inverseWorldTransform_ * (vertexPos));
                            bones_[bone].collisionMask_ |= 2;
                        }
                    }
                    boneAssignment = boneAssignment.GetNext("vertexboneassignment");
                }
            }

            if ((subGeometryLodLevel.boneWeights_.Size()) && bones_.Size())
            {
                vBuf->elementMask_ |= MASK_BLENDWEIGHTS | MASK_BLENDINDICES;
                bool sorted = false;

                // If amount of bones is larger than supported by HW skinning, must remap per submesh
                if (bones_.Size() > maxBones_)
                {
                    HashMap<unsigned, unsigned> usedBoneMap;
                    unsigned remapIndex = 0;
                    for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i =
                                subGeometryLodLevel.boneWeights_.Begin(); i != subGeometryLodLevel.boneWeights_.End(); ++i)
                    {
                        // Sort the bone assigns by weight
                        Sort(i->second_.Begin(), i->second_.End(), CompareWeights);

                        // Use only the first 4 weights
                        for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                        {
                            unsigned originalIndex = i->second_[j].boneIndex_;
                            if (!usedBoneMap.Contains(originalIndex))
                            {
                                usedBoneMap[originalIndex] = remapIndex;
                                remapIndex++;
                            }
                            i->second_[j].boneIndex_ = usedBoneMap[originalIndex];
                        }
                    }

                    // If still too many bones in one subgeometry, error
                    if (usedBoneMap.Size() > maxBones_)
                        ErrorExit("Too many bones (limit " + String(maxBones_) + ") in submesh " + String(subMeshIndex + 1));

                    // Write mapping of vertex buffer bone indices to original bone indices
                    subGeometryLodLevel.boneMapping_.Resize(usedBoneMap.Size());
                    for (HashMap<unsigned, unsigned>::Iterator j = usedBoneMap.Begin(); j != usedBoneMap.End(); ++j)
                        subGeometryLodLevel.boneMapping_[j->second_] = j->first_;

                    sorted = true;
                }

                for (HashMap<unsigned, PODVector<BoneWeightAssignment> >::Iterator i = subGeometryLodLevel.boneWeights_.Begin();
                        i != subGeometryLodLevel.boneWeights_.End(); ++i)
                {
                    // Sort the bone assigns by weight, if not sorted yet in bone remapping pass
                    if (!sorted)
                        Sort(i->second_.Begin(), i->second_.End(), CompareWeights);

                    float totalWeight = 0.0f;
                    float normalizationFactor = 0.0f;

                    // Calculate normalization factor in case there are more than 4 blend weights, or they do not add up to 1
                    for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                        totalWeight += i->second_[j].weight_;
                    if (totalWeight > 0.0f)
                        normalizationFactor = 1.0f / totalWeight;

                    for (unsigned j = 0; j < i->second_.Size() && j < 4; ++j)
                    {
                        vBuf->vertices_[i->first_].blendIndices_[j] = i->second_[j].boneIndex_;
                        vBuf->vertices_[i->first_].blendWeights_[j] = i->second_[j].weight_ * normalizationFactor;
                    }

                    // If there are less than 4 blend weights, fill rest with zero
                    for (unsigned j = i->second_.Size(); j < 4; ++j)
                    {
                        vBuf->vertices_[i->first_].blendIndices_[j] = 0;
                        vBuf->vertices_[i->first_].blendWeights_[j] = 0.0f;
                    }

                    vBuf->vertices_[i->first_].hasBlendWeights_ = true;
                }
            }
        }
        else if (boneAssignments)
            PrintLine("No skeleton loaded, skipping skinning information");

        // Calculate center for the subgeometry
        Vector3 center = Vector3::ZERO;
        for (unsigned i = 0; i < iBuf->indices_.Size(); i += 3)
        {
            center += vBuf->vertices_[iBuf->indices_[i]].position_;
            center += vBuf->vertices_[iBuf->indices_[i + 1]].position_;
            center += vBuf->vertices_[iBuf->indices_[i + 2]].position_;
        }
        if (iBuf->indices_.Size())
            center /= (float)iBuf->indices_.Size();
        subGeometryCenters_.Push(center);

        indexStart += indices;
        vertexStart += vertices;

        OptimizeIndices(&subGeometryLodLevel, vBuf, iBuf);

        PrintLine("Processed submesh " + String(subMeshIndex + 1) + ": " + String(vertices) + " vertices " +
                  String(triangles) + " triangles");
        Vector<ModelSubGeometryLodLevel> thisSubGeometry;
        thisSubGeometry.Push(subGeometryLodLevel);
        subGeometries_.Push(thisSubGeometry);

        subMesh = subMesh.GetNext("submesh");
        subMeshIndex++;
    }

    // Process LOD levels, if any
    XMLElement lods = root.GetChild("levelofdetail");
    if (lods)
    {
        try
        {
            // For now, support only generated LODs, where the vertices are the same
            XMLElement lod = lods.GetChild("lodgenerated");
            while (lod)
            {
                float distance = M_EPSILON;
                if (lod.HasAttribute("fromdepthsquared"))
                    distance = sqrtf(lod.GetFloat("fromdepthsquared"));
                if (lod.HasAttribute("value"))
                    distance = lod.GetFloat("value");
                XMLElement lodSubMesh = lod.GetChild("lodfacelist");
                while (lodSubMesh)
                {
                    unsigned subMeshIndex = lodSubMesh.GetInt("submeshindex");
                    unsigned triangles = lodSubMesh.GetInt("numfaces");

                    ModelSubGeometryLodLevel newLodLevel;
                    ModelSubGeometryLodLevel& originalLodLevel = subGeometries_[subMeshIndex][0];

                    // Copy all initial values
                    newLodLevel = originalLodLevel;

                    ModelVertexBuffer* vBuf;
                    ModelIndexBuffer* iBuf;

                    if (useOneBuffer_)
                    {
                        vBuf = &vertexBuffers_[0];
                        iBuf = &indexBuffers_[0];
                    }
                    else
                    {
                        vBuf = &vertexBuffers_[subMeshIndex];
                        iBuf = &indexBuffers_[subMeshIndex];
                    }

                    unsigned indexStart = iBuf->indices_.Size();
                    unsigned indexCount = triangles * 3;
                    unsigned vertexStart = vertexStarts[subMeshIndex];

                    newLodLevel.distance_ = distance;
                    newLodLevel.indexStart_ = indexStart;
                    newLodLevel.indexCount_ = indexCount;

                    // Append indices to the original index buffer
                    XMLElement triangle = lodSubMesh.GetChild("face");
                    while (triangle)
                    {
                        unsigned v1 = triangle.GetInt("v1");
                        unsigned v2 = triangle.GetInt("v2");
                        unsigned v3 = triangle.GetInt("v3");
                        iBuf->indices_.Push(v3 + vertexStart);
                        iBuf->indices_.Push(v2 + vertexStart);
                        iBuf->indices_.Push(v1 + vertexStart);
                        triangle = triangle.GetNext("face");
                    }

                    OptimizeIndices(&newLodLevel, vBuf, iBuf);

                    subGeometries_[subMeshIndex].Push(newLodLevel);
                    PrintLine("Processed LOD level for submesh " + String(subMeshIndex + 1) + ": distance " + String(distance));

                    lodSubMesh = lodSubMesh.GetNext("lodfacelist");
                }
                lod = lod.GetNext("lodgenerated");
            }
        }
        catch (...) {}
    }

    // Process poses/morphs
    // First find out all pose definitions
    if (exportMorphs)
    {
        try
        {
            Vector<XMLElement> poses;
            XMLElement posesRoot = root.GetChild("poses");
            if (posesRoot)
            {
                XMLElement pose = posesRoot.GetChild("pose");
                while (pose)
                {
                    poses.Push(pose);
                    pose = pose.GetNext("pose");
                }
            }

            // Then process animations using the poses
            XMLElement animsRoot = root.GetChild("animations");
            if (animsRoot)
            {
                XMLElement anim = animsRoot.GetChild("animation");
                while (anim)
                {
                    String name = anim.GetAttribute("name");
                    float length = anim.GetFloat("length");
                    HashSet<unsigned> usedPoses;
                    XMLElement tracks = anim.GetChild("tracks");
                    if (tracks)
                    {
                        XMLElement track = tracks.GetChild("track");
                        while (track)
                        {
                            XMLElement keyframes = track.GetChild("keyframes");
                            if (keyframes)
                            {
                                XMLElement keyframe = keyframes.GetChild("keyframe");
                                while (keyframe)
                                {
                                    float time = keyframe.GetFloat("time");
                                    XMLElement poseref = keyframe.GetChild("poseref");
                                    // Get only the end pose
                                    if (poseref && time == length)
                                        usedPoses.Insert(poseref.GetInt("poseindex"));

                                    keyframe = keyframe.GetNext("keyframe");
                                }
                            }
                            track = track.GetNext("track");
                        }
                    }

                    if (usedPoses.Size())
                    {
                        ModelMorph newMorph;
                        newMorph.name_ = name;

                        if (useOneBuffer_)
                            newMorph.buffers_.Resize(1);
                        else
                            newMorph.buffers_.Resize(usedPoses.Size());

                        unsigned bufIndex = 0;

                        for (HashSet<unsigned>::Iterator i = usedPoses.Begin(); i != usedPoses.End(); ++i)
                        {
                            XMLElement pose = poses[*i];
                            unsigned targetSubMesh = pose.GetInt("index");
                            XMLElement poseOffset = pose.GetChild("poseoffset");

                            if (useOneBuffer_)
                                newMorph.buffers_[bufIndex].vertexBuffer_ = 0;
                            else
                                newMorph.buffers_[bufIndex].vertexBuffer_ = targetSubMesh;

                            newMorph.buffers_[bufIndex].elementMask_ = MASK_POSITION;

                            ModelVertexBuffer* vBuf = &vertexBuffers_[newMorph.buffers_[bufIndex].vertexBuffer_];

                            while (poseOffset)
                            {
                                // Convert from right- to left-handed
                                unsigned vertexIndex = poseOffset.GetInt("index") + vertexStarts[targetSubMesh];
                                float x = poseOffset.GetFloat("x");
                                float y = poseOffset.GetFloat("y");
                                float z = poseOffset.GetFloat("z");
                                Vector3 vec(x, y, -z);

                                if (vBuf->morphCount_ == 0)
                                {
                                    vBuf->morphStart_ = vertexIndex;
                                    vBuf->morphCount_ = 1;
                                }
                                else
                                {
                                    unsigned first = vBuf->morphStart_;
                                    unsigned last = first + vBuf->morphCount_ - 1;
                                    if (vertexIndex < first)
                                        first = vertexIndex;
                                    if (vertexIndex > last)
                                        last = vertexIndex;
                                    vBuf->morphStart_ = first;
                                    vBuf->morphCount_ = last - first + 1;
                                }

                                ModelVertex newVertex;
                                newVertex.position_ = vec;
                                newMorph.buffers_[bufIndex].vertices_.Push(MakePair(vertexIndex, newVertex));
                                poseOffset = poseOffset.GetNext("poseoffset");
                            }

                            if (!useOneBuffer_)
                                ++bufIndex;
                        }
                        morphs_.Push(newMorph);
                        PrintLine("Processed morph " + name + " with " + String(usedPoses.Size()) + " sub-poses");
                    }

                    anim = anim.GetNext("animation");
                }
            }
        }
        catch (...) {}
    }

    // Check any of the buffers for vertices with missing blend weight assignments
    for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
    {
        if (vertexBuffers_[i].elementMask_ & MASK_BLENDWEIGHTS)
        {
            for (unsigned j = 0; j < vertexBuffers_[i].vertices_.Size(); ++j)
                if (!vertexBuffers_[i].vertices_[j].hasBlendWeights_)
                    ErrorExit("Found a vertex with missing skinning information");
        }
    }

    // Tangent generation
    if (generateTangents)
    {
        for (unsigned i = 0; i < subGeometries_.Size(); ++i)
        {
            for (unsigned j = 0; j < subGeometries_[i].Size(); ++j)
            {
                ModelVertexBuffer& vBuf = vertexBuffers_[subGeometries_[i][j].vertexBuffer_];
                ModelIndexBuffer& iBuf = indexBuffers_[subGeometries_[i][j].indexBuffer_];
                unsigned indexStart = subGeometries_[i][j].indexStart_;
                unsigned indexCount = subGeometries_[i][j].indexCount_;

                // If already has tangents, do not regenerate
                if (vBuf.elementMask_ & MASK_TANGENT || vBuf.vertices_.Empty() || iBuf.indices_.Empty())
                    continue;

                vBuf.elementMask_ |= MASK_TANGENT;

                if ((vBuf.elementMask_ & (MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1)) != (MASK_POSITION | MASK_NORMAL |
                        MASK_TEXCOORD1))
                    ErrorExit("To generate tangents, positions normals and texcoords are required");

                GenerateTangents(&vBuf.vertices_[0], sizeof(ModelVertex), &iBuf.indices_[0], sizeof(unsigned), indexStart,
                                 indexCount, offsetof(ModelVertex, normal_), offsetof(ModelVertex, texCoord1_), offsetof(ModelVertex,
                                         tangent_));

                PrintLine("Generated tangents");
            }
        }
    }
}
void SceneHudPanel::UpdatePanel(float frametime, const SharedPtr<Urho3D::UIElement> &widget)
{
    if (!limiter_.ShouldUpdate(frametime))
        return;

    Text *sceneText = dynamic_cast<Text*>(widget.Get());
    if (!sceneText || !framework_->Renderer())
        return;

    Scene *scene = framework_->Renderer()->MainCameraScene();
    if (!scene)
        return;
    
    String str;

    SceneInfo info;
    auto entities = scene->Entities();
    info.ents = entities.Size();
    for(auto entIter = entities.Begin(); entIter != entities.End(); ++entIter)
    {
        const EntityPtr ent = entIter->second_;
        if (ent->Parent())
            info.entsParented++;
        else
            info.entsRoot++;

        if (ent->IsLocal())
            info.entsLocal++;
        if (ent->IsReplicated())
            info.entsReplicated++;
        if (ent->IsTemporary())
            info.entsTemporary++;

        String group = ent->Group().Trimmed();
        if (!group.Empty())
        {
            info.entGroups[group]++;
            InsertAlpha(info.groups, group);

            if ((int)group.Length() > info.pad)
                info.pad = group.Length() + 2;
        }

        auto components = ent->Components();
        info.comps += components.Size();
        for(auto compIter = components.Begin(); compIter != components.End(); ++compIter)
        {
            auto comp = compIter->second_;
            String type = comp->TypeName();
            info.compTypes[type]++;
            InsertAlpha(info.types, type);

            if (comp->IsLocal())
                info.compsLocal++;
            if (comp->IsReplicated())
                info.compsReplicated++;
            if (comp->IsTemporary())
                info.compsTemporary++;

            if ((int)type.Length() > info.pad)
                info.pad = type.Length() + 2;
        }
        if (components.Empty())
            info.entsEmpty++;
    }

    str.AppendWithFormat("%s   %u\n", PadString("Entities", info.pad).CString(), info.ents);
    str.AppendWithFormat("  %s %u\n", PadString("Root", info.pad).CString(), info.entsRoot);
    str.AppendWithFormat("  %s %u\n", PadString("Parented", info.pad).CString(), info.entsParented);
    str.AppendWithFormat("  %s %u\n", PadString("Empty", info.pad).CString(), info.entsEmpty);
    str.AppendWithFormat("  %s %u\n", PadString("Replicated", info.pad).CString(), info.entsReplicated);
    str.AppendWithFormat("  %s %u\n", PadString("Local", info.pad).CString(), info.entsLocal);
    str.AppendWithFormat("  %s %u\n\n", PadString("Temporary", info.pad).CString(), info.entsTemporary);

    if (!info.groups.Empty())
    {
        str.AppendWithFormat("%s   %u\n", PadString("Entity Groups", info.pad).CString(), info.groups.Size());
        foreach(auto &group, info.groups)
        {
            uint num = info.entGroups[group];
            str.AppendWithFormat("  %s %u\n", PadString(group, info.pad).CString(), num);
        }
        str.Append("\n");
    }
Beispiel #24
0
void WriteOutput(const String& outputFileName, bool exportAnimations, bool rotationsOnly, bool saveMaterialList)
{
    // Begin serialization
    {
        File dest(context_);
        if (!dest.Open(outputFileName, FILE_WRITE))
            ErrorExit("Could not open output file " + outputFileName);

        // ID
        dest.WriteFileID("UMDL");

        // Vertexbuffers
        dest.WriteUInt(vertexBuffers_.Size());
        for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
            vertexBuffers_[i].WriteData(dest);

        // Indexbuffers
        dest.WriteUInt(indexBuffers_.Size());
        for (unsigned i = 0; i < indexBuffers_.Size(); ++i)
            indexBuffers_[i].WriteData(dest);

        // Subgeometries
        dest.WriteUInt(subGeometries_.Size());
        for (unsigned i = 0; i < subGeometries_.Size(); ++i)
        {
            // Write bone mapping info from the first LOD level. It does not change for further LODs
            dest.WriteUInt(subGeometries_[i][0].boneMapping_.Size());
            for (unsigned k = 0; k < subGeometries_[i][0].boneMapping_.Size(); ++k)
                dest.WriteUInt(subGeometries_[i][0].boneMapping_[k]);

            // Lod levels for this subgeometry
            dest.WriteUInt(subGeometries_[i].Size());
            for (unsigned j = 0; j < subGeometries_[i].Size(); ++j)
            {
                dest.WriteFloat(subGeometries_[i][j].distance_);
                dest.WriteUInt((unsigned)subGeometries_[i][j].primitiveType_);
                dest.WriteUInt(subGeometries_[i][j].vertexBuffer_);
                dest.WriteUInt(subGeometries_[i][j].indexBuffer_);
                dest.WriteUInt(subGeometries_[i][j].indexStart_);
                dest.WriteUInt(subGeometries_[i][j].indexCount_);
            }
        }

        // Morphs
        dest.WriteUInt(morphs_.Size());
        for (unsigned i = 0; i < morphs_.Size(); ++i)
            morphs_[i].WriteData(dest);

        // Skeleton
        dest.WriteUInt(bones_.Size());
        for (unsigned i = 0; i < bones_.Size(); ++i)
        {
            dest.WriteString(bones_[i].name_);
            dest.WriteUInt(bones_[i].parentIndex_);
            dest.WriteVector3(bones_[i].bindPosition_);
            dest.WriteQuaternion(bones_[i].bindRotation_);
            dest.WriteVector3(bones_[i].bindScale_);

            Matrix3x4 offsetMatrix(bones_[i].derivedPosition_, bones_[i].derivedRotation_, bones_[i].derivedScale_);
            offsetMatrix = offsetMatrix.Inverse();
            dest.Write(offsetMatrix.Data(), sizeof(Matrix3x4));

            dest.WriteUByte(bones_[i].collisionMask_);
            if (bones_[i].collisionMask_ & 1)
                dest.WriteFloat(bones_[i].radius_);
            if (bones_[i].collisionMask_ & 2)
                dest.WriteBoundingBox(bones_[i].boundingBox_);
        }

        // Bounding box
        dest.WriteBoundingBox(boundingBox_);

        // Geometry centers
        for (unsigned i = 0; i < subGeometryCenters_.Size(); ++i)
            dest.WriteVector3(subGeometryCenters_[i]);
    }

    if (saveMaterialList)
    {
        String materialListName = ReplaceExtension(outputFileName, ".txt");
        File listFile(context_);
        if (listFile.Open(materialListName, FILE_WRITE))
        {
            for (unsigned i = 0; i < materialNames_.Size(); ++i)
            {
                // Assume the materials will be located inside the standard Materials subdirectory
                listFile.WriteLine("Materials/" + ReplaceExtension(SanitateAssetName(materialNames_[i]), ".xml"));
            }
        }
        else
            PrintLine("Warning: could not write material list file " + materialListName);
    }

    XMLElement skeletonRoot = skelFile_->GetRoot("skeleton");
    if (skeletonRoot && exportAnimations)
    {
        // Go through animations
        XMLElement animationsRoot = skeletonRoot.GetChild("animations");
        if (animationsRoot)
        {
            XMLElement animation = animationsRoot.GetChild("animation");
            while (animation)
            {
                ModelAnimation newAnimation;
                newAnimation.name_ = animation.GetAttribute("name");
                newAnimation.length_ = animation.GetFloat("length");

                XMLElement tracksRoot = animation.GetChild("tracks");
                XMLElement track = tracksRoot.GetChild("track");
                while (track)
                {
                    String trackName = track.GetAttribute("bone");
                    ModelBone* bone = 0;
                    for (unsigned i = 0; i < bones_.Size(); ++i)
                    {
                        if (bones_[i].name_ == trackName)
                        {
                            bone = &bones_[i];
                            break;
                        }
                    }
                    if (!bone)
                        ErrorExit("Found animation track for unknown bone " + trackName);

                    AnimationTrack newAnimationTrack;
                    newAnimationTrack.name_ = trackName;
                    if (!rotationsOnly)
                        newAnimationTrack.channelMask_ = CHANNEL_POSITION | CHANNEL_ROTATION;
                    else
                        newAnimationTrack.channelMask_ = CHANNEL_ROTATION;

                    XMLElement keyFramesRoot = track.GetChild("keyframes");
                    XMLElement keyFrame = keyFramesRoot.GetChild("keyframe");
                    while (keyFrame)
                    {
                        AnimationKeyFrame newKeyFrame;

                        // Convert from right- to left-handed
                        XMLElement position = keyFrame.GetChild("translate");
                        float x = position.GetFloat("x");
                        float y = position.GetFloat("y");
                        float z = position.GetFloat("z");
                        Vector3 pos(x, y, -z);

                        XMLElement rotation = keyFrame.GetChild("rotate");
                        XMLElement axis = rotation.GetChild("axis");
                        float angle = -rotation.GetFloat("angle") * M_RADTODEG;
                        x = axis.GetFloat("x");
                        y = axis.GetFloat("y");
                        z = axis.GetFloat("z");
                        Vector3 axisVec(x, y, -z);
                        Quaternion rot(angle, axisVec);

                        // Transform from bind-pose relative into absolute
                        pos = bone->bindPosition_ + bone->bindRotation_ * pos;
                        rot = bone->bindRotation_ * rot;

                        newKeyFrame.time_ = keyFrame.GetFloat("time");
                        newKeyFrame.position_ = pos;
                        newKeyFrame.rotation_ = rot;

                        newAnimationTrack.keyFrames_.Push(newKeyFrame);
                        keyFrame = keyFrame.GetNext("keyframe");
                    }

                    // Make sure keyframes are sorted from beginning to end
                    Sort(newAnimationTrack.keyFrames_.Begin(), newAnimationTrack.keyFrames_.End(), CompareKeyFrames);

                    // Do not add tracks with no keyframes
                    if (newAnimationTrack.keyFrames_.Size())
                        newAnimation.tracks_.Push(newAnimationTrack);

                    track = track.GetNext("track");
                }

                // Write each animation into a separate file
                String animationFileName = outputFileName.Replaced(".mdl", "");
                animationFileName += "_" + newAnimation.name_ + ".ani";

                File dest(context_);
                if (!dest.Open(animationFileName, FILE_WRITE))
                    ErrorExit("Could not open output file " + animationFileName);

                dest.WriteFileID("UANI");
                dest.WriteString(newAnimation.name_);
                dest.WriteFloat(newAnimation.length_);
                dest.WriteUInt(newAnimation.tracks_.Size());
                for (unsigned i = 0; i < newAnimation.tracks_.Size(); ++i)
                {
                    AnimationTrack& track = newAnimation.tracks_[i];
                    dest.WriteString(track.name_);
                    dest.WriteUByte(track.channelMask_);
                    dest.WriteUInt(track.keyFrames_.Size());
                    for (unsigned j = 0; j < track.keyFrames_.Size(); ++j)
                    {
                        AnimationKeyFrame& keyFrame = track.keyFrames_[j];
                        dest.WriteFloat(keyFrame.time_);
                        if (track.channelMask_ & CHANNEL_POSITION)
                            dest.WriteVector3(keyFrame.position_);
                        if (track.channelMask_ & CHANNEL_ROTATION)
                            dest.WriteQuaternion(keyFrame.rotation_);
                        if (track.channelMask_ & CHANNEL_SCALE)
                            dest.WriteVector3(keyFrame.scale_);
                    }
                }

                animation = animation.GetNext("animation");
                PrintLine("Processed animation " + newAnimation.name_);
            }
        }
    }
}
Beispiel #25
0
bool Texture2D::SetData(SharedPtr<Image> image, bool useAlpha)
{
    if (!image)
    {
        URHO3D_LOGERROR("Null image, can not set data");
        return false;
    }

    unsigned memoryUse = sizeof(Texture2D);

    int quality = QUALITY_HIGH;
    Renderer* renderer = GetSubsystem<Renderer>();
    if (renderer)
        quality = renderer->GetTextureQuality();

    if (!image->IsCompressed())
    {
        // Convert unsuitable formats to RGBA
        unsigned components = image->GetComponents();
        if (Graphics::GetGL3Support() && ((components == 1 && !useAlpha) || components == 2))
        {
            image = image->ConvertToRGBA();
            if (!image)
                return false;
            components = image->GetComponents();
        }

        unsigned char* levelData = image->GetData();
        int levelWidth = image->GetWidth();
        int levelHeight = image->GetHeight();
        unsigned format = 0;

        // Discard unnecessary mip levels
        for (unsigned i = 0; i < mipsToSkip_[quality]; ++i)
        {
            image = image->GetNextLevel();
            levelData = image->GetData();
            levelWidth = image->GetWidth();
            levelHeight = image->GetHeight();
        }

        switch (components)
        {
        case 1:
            format = useAlpha ? Graphics::GetAlphaFormat() : Graphics::GetLuminanceFormat();
            break;

        case 2:
            format = Graphics::GetLuminanceAlphaFormat();
            break;

        case 3:
            format = Graphics::GetRGBFormat();
            break;

        case 4:
            format = Graphics::GetRGBAFormat();
            break;

        default:
            assert(false);  // Should not reach here
            break;
        }

        // If image was previously compressed, reset number of requested levels to avoid error if level count is too high for new size
        if (IsCompressed() && requestedLevels_ > 1)
            requestedLevels_ = 0;
        SetSize(levelWidth, levelHeight, format);
        if (!object_)
            return false;

        for (unsigned i = 0; i < levels_; ++i)
        {
            SetData(i, 0, 0, levelWidth, levelHeight, levelData);
            memoryUse += levelWidth * levelHeight * components;

            if (i < levels_ - 1)
            {
                image = image->GetNextLevel();
                levelData = image->GetData();
                levelWidth = image->GetWidth();
                levelHeight = image->GetHeight();
            }
        }
    }
    else
    {
        int width = image->GetWidth();
        int height = image->GetHeight();
        unsigned levels = image->GetNumCompressedLevels();
        unsigned format = graphics_->GetFormat(image->GetCompressedFormat());
        bool needDecompress = false;

        if (!format)
        {
            format = Graphics::GetRGBAFormat();
            needDecompress = true;
        }

        unsigned mipsToSkip = mipsToSkip_[quality];
        if (mipsToSkip >= levels)
            mipsToSkip = levels - 1;
        while (mipsToSkip && (width / (1 << mipsToSkip) < 4 || height / (1 << mipsToSkip) < 4))
            --mipsToSkip;
        width /= (1 << mipsToSkip);
        height /= (1 << mipsToSkip);

        SetNumLevels((unsigned)Max((int)(levels - mipsToSkip), 1));
        SetSize(width, height, format);

        for (unsigned i = 0; i < levels_ && i < levels - mipsToSkip; ++i)
        {
            CompressedLevel level = image->GetCompressedLevel(i + mipsToSkip);
            if (!needDecompress)
            {
                SetData(i, 0, 0, level.width_, level.height_, level.data_);
                memoryUse += level.rows_ * level.rowSize_;
            }
            else
            {
                unsigned char* rgbaData = new unsigned char[level.width_ * level.height_ * 4];
                level.Decompress(rgbaData);
                SetData(i, 0, 0, level.width_, level.height_, rgbaData);
                memoryUse += level.width_ * level.height_ * 4;
                delete[] rgbaData;
            }
        }
    }

    SetMemoryUse(memoryUse);
    return true;
}
bool ShaderVariation::LoadByteCode(const String& binaryShaderName)
{
    ResourceCache* cache = owner_->GetSubsystem<ResourceCache>();
    if (!cache->Exists(binaryShaderName))
        return false;

    FileSystem* fileSystem = owner_->GetSubsystem<FileSystem>();
    unsigned sourceTimeStamp = owner_->GetTimeStamp();
    // If source code is loaded from a package, its timestamp will be zero. Else check that binary is not older
    // than source
    if (sourceTimeStamp && fileSystem->GetLastModifiedTime(cache->GetResourceFileName(binaryShaderName)) < sourceTimeStamp)
        return false;

    SharedPtr<File> file = cache->GetFile(binaryShaderName);
    if (!file || file->ReadFileID() != "USHD")
    {
        ATOMIC_LOGERROR(binaryShaderName + " is not a valid shader bytecode file");
        return false;
    }

    /// \todo Check that shader type and model match
    /*unsigned short shaderType = */file->ReadUShort();
    /*unsigned short shaderModel = */file->ReadUShort();

    unsigned numParameters = file->ReadUInt();
    for (unsigned i = 0; i < numParameters; ++i)
    {
        String name = file->ReadString();
        unsigned reg = file->ReadUByte();
        unsigned regCount = file->ReadUByte();

        ShaderParameter parameter;
        parameter.type_ = type_;
        parameter.name_ = name;
        parameter.register_ = reg;
        parameter.regCount_ = regCount;
        parameters_[StringHash(name)] = parameter;
    }

    unsigned numTextureUnits = file->ReadUInt();
    for (unsigned i = 0; i < numTextureUnits; ++i)
    {
        /*String unitName = */file->ReadString();
        unsigned reg = file->ReadUByte();

        if (reg < MAX_TEXTURE_UNITS)
            useTextureUnit_[reg] = true;
    }

    unsigned byteCodeSize = file->ReadUInt();
    if (byteCodeSize)
    {
        byteCode_.Resize(byteCodeSize);
        file->Read(&byteCode_[0], byteCodeSize);

        if (type_ == VS)
            ATOMIC_LOGDEBUG("Loaded cached vertex shader " + GetFullName());
        else
            ATOMIC_LOGDEBUG("Loaded cached pixel shader " + GetFullName());

        return true;
    }
    else
    {
        ATOMIC_LOGERROR(binaryShaderName + " has zero length bytecode");
        return false;
    }
}
Beispiel #27
0
	~BaseEntity(){ manager->releaseEntity(this); }
Beispiel #28
0
bool TextureCube::BeginLoad(Deserializer& source)
{
    ResourceCache* cache = context_->resourceCache();

    // In headless mode, do not actually load the texture, just return success
    if (!graphics_)
        return true;

    // If device is lost, retry later
    if (graphics_->IsDeviceLost())
    {
        URHO3D_LOGWARNING("Texture load while device is lost");
        dataPending_ = true;
        return true;
    }

    cache->ResetDependencies(this);

    QString texPath, texName, texExt;
    SplitPath(GetName(), texPath, texName, texExt);

    loadParameters_ = (new XMLFile(context_));
    if (!loadParameters_->Load(source))
    {
        loadParameters_.Reset();
        return false;
    }

    loadImages_.clear();

    XMLElement textureElem = loadParameters_->GetRoot();
    XMLElement imageElem = textureElem.GetChild("image");
    // Single image and multiple faces with layout
    if (imageElem)
    {
        QString name = imageElem.GetAttribute("name");
        // If path is empty, add the XML file path
        if (GetPath(name).isEmpty())
            name = texPath + name;

        SharedPtr<Image> image = cache->GetTempResource<Image>(name);
        if (!image)
            return false;

        int faceWidth, faceHeight;
        loadImages_.resize(MAX_CUBEMAP_FACES);

        if (image->IsCubemap())
        {
            loadImages_[FACE_POSITIVE_X] = image;
            loadImages_[FACE_NEGATIVE_X] = loadImages_[FACE_POSITIVE_X]->GetNextSibling();
            loadImages_[FACE_POSITIVE_Y] = loadImages_[FACE_NEGATIVE_X]->GetNextSibling();
            loadImages_[FACE_NEGATIVE_Y] = loadImages_[FACE_POSITIVE_Y]->GetNextSibling();
            loadImages_[FACE_POSITIVE_Z] = loadImages_[FACE_NEGATIVE_Y]->GetNextSibling();
            loadImages_[FACE_NEGATIVE_Z] = loadImages_[FACE_POSITIVE_Z]->GetNextSibling();
        }
        else
        {

            CubeMapLayout layout = (CubeMapLayout)GetStringListIndex(imageElem.GetAttribute("layout"), cubeMapLayoutNames, CML_HORIZONTAL);

            switch (layout)
            {
            case CML_HORIZONTAL:
                faceWidth = image->GetWidth() / MAX_CUBEMAP_FACES;
                faceHeight = image->GetHeight();
                loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 0, 0, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 1, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 2, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 3, 0, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 4, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 5, 0, faceWidth, faceHeight);
                break;

            case CML_HORIZONTALNVIDIA:
                faceWidth = image->GetWidth() / MAX_CUBEMAP_FACES;
                faceHeight = image->GetHeight();
                for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
                    loadImages_[i] = GetTileImage(image, i, 0, faceWidth, faceHeight);
                break;

            case CML_HORIZONTALCROSS:
                faceWidth = image->GetWidth() / 4;
                faceHeight = image->GetHeight() / 3;
                loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 1, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 1, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 3, 1, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 1, 2, faceWidth, faceHeight);
                break;

            case CML_VERTICALCROSS:
                faceWidth = image->GetWidth() / 3;
                faceHeight = image->GetHeight() / 4;
                loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 1, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 1, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 1, 2, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 1, 3, faceWidth, faceHeight);
                if (loadImages_[FACE_NEGATIVE_Z])
                {
                    loadImages_[FACE_NEGATIVE_Z]->FlipVertical();
                    loadImages_[FACE_NEGATIVE_Z]->FlipHorizontal();
                }
                break;

            case CML_BLENDER:
                faceWidth = image->GetWidth() / 3;
                faceHeight = image->GetHeight() / 2;
                loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 1, 0, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 0, faceWidth, faceHeight);
                loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 0, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 1, faceWidth, faceHeight);
                loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 2, 1, faceWidth, faceHeight);
                break;
            }
        }
    }
    // Face per image
    else
    {
        XMLElement faceElem = textureElem.GetChild("face");
        while (faceElem)
        {
            QString name = faceElem.GetAttribute("name");

            // If path is empty, add the XML file path
            if (GetPath(name).isEmpty())
                name = texPath + name;

            loadImages_.push_back(cache->GetTempResource<Image>(name));
            cache->StoreResourceDependency(this, name);

            faceElem = faceElem.GetNext("face");
        }
    }

    // Precalculate mip levels if async loading
    if (GetAsyncLoadState() == ASYNC_LOADING)
    {
        for (unsigned i = 0; i < loadImages_.size(); ++i)
        {
            if (loadImages_[i])
                loadImages_[i]->PrecalculateLevels();
        }
    }

    return true;
}
Beispiel #29
0
SharedPtr<Model> Model::Clone(const String& cloneName) const
{
    SharedPtr<Model> ret(new Model(context_));

    ret->SetName(cloneName);
    ret->boundingBox_ = boundingBox_;
    ret->skeleton_ = skeleton_;
    ret->geometryBoneMappings_ = geometryBoneMappings_;
    ret->geometryCenters_ = geometryCenters_;
    ret->morphs_ = morphs_;
    ret->morphRangeStarts_ = morphRangeStarts_;
    ret->morphRangeCounts_ = morphRangeCounts_;

    // Deep copy vertex/index buffers
    HashMap<VertexBuffer*, VertexBuffer*> vbMapping;
    for (Vector<SharedPtr<VertexBuffer> >::ConstIterator i = vertexBuffers_.Begin(); i != vertexBuffers_.End(); ++i)
    {
        VertexBuffer* origBuffer = *i;
        SharedPtr<VertexBuffer> cloneBuffer;

        if (origBuffer)
        {
            cloneBuffer = new VertexBuffer(context_);
            cloneBuffer->SetSize(origBuffer->GetVertexCount(), origBuffer->GetElementMask(), origBuffer->IsDynamic());
            cloneBuffer->SetShadowed(origBuffer->IsShadowed());
            if (origBuffer->IsShadowed())
                cloneBuffer->SetData(origBuffer->GetShadowData());
            else
            {
                void* origData = origBuffer->Lock(0, origBuffer->GetVertexCount());
                if (origData)
                    cloneBuffer->SetData(origData);
                else
                    URHO3D_LOGERROR("Failed to lock original vertex buffer for copying");
            }
            vbMapping[origBuffer] = cloneBuffer;
        }

        ret->vertexBuffers_.Push(cloneBuffer);
    }

    HashMap<IndexBuffer*, IndexBuffer*> ibMapping;
    for (Vector<SharedPtr<IndexBuffer> >::ConstIterator i = indexBuffers_.Begin(); i != indexBuffers_.End(); ++i)
    {
        IndexBuffer* origBuffer = *i;
        SharedPtr<IndexBuffer> cloneBuffer;

        if (origBuffer)
        {
            cloneBuffer = new IndexBuffer(context_);
            cloneBuffer->SetSize(origBuffer->GetIndexCount(), origBuffer->GetIndexSize() == sizeof(unsigned),
                origBuffer->IsDynamic());
            cloneBuffer->SetShadowed(origBuffer->IsShadowed());
            if (origBuffer->IsShadowed())
                cloneBuffer->SetData(origBuffer->GetShadowData());
            else
            {
                void* origData = origBuffer->Lock(0, origBuffer->GetIndexCount());
                if (origData)
                    cloneBuffer->SetData(origData);
                else
                    URHO3D_LOGERROR("Failed to lock original index buffer for copying");
            }
            ibMapping[origBuffer] = cloneBuffer;
        }

        ret->indexBuffers_.Push(cloneBuffer);
    }

    // Deep copy all the geometry LOD levels and refer to the copied vertex/index buffers
    ret->geometries_.Resize(geometries_.Size());
    for (unsigned i = 0; i < geometries_.Size(); ++i)
    {
        ret->geometries_[i].Resize(geometries_[i].Size());
        for (unsigned j = 0; j < geometries_[i].Size(); ++j)
        {
            SharedPtr<Geometry> cloneGeometry;
            Geometry* origGeometry = geometries_[i][j];

            if (origGeometry)
            {
                cloneGeometry = new Geometry(context_);
                cloneGeometry->SetIndexBuffer(ibMapping[origGeometry->GetIndexBuffer()]);
                unsigned numVbs = origGeometry->GetNumVertexBuffers();
                for (unsigned k = 0; k < numVbs; ++k)
                {
                    cloneGeometry->SetVertexBuffer(k, vbMapping[origGeometry->GetVertexBuffer(k)]);
                }
                cloneGeometry->SetDrawRange(origGeometry->GetPrimitiveType(), origGeometry->GetIndexStart(),
                    origGeometry->GetIndexCount(), origGeometry->GetVertexStart(), origGeometry->GetVertexCount(), false);
                cloneGeometry->SetLodDistance(origGeometry->GetLodDistance());
            }

            ret->geometries_[i][j] = cloneGeometry;
        }
    }


    // Deep copy the morph data (if any) to allow modifying it
    for (Vector<ModelMorph>::Iterator i = ret->morphs_.Begin(); i != ret->morphs_.End(); ++i)
    {
        ModelMorph& morph = *i;
        for (HashMap<unsigned, VertexBufferMorph>::Iterator j = morph.buffers_.Begin(); j != morph.buffers_.End(); ++j)
        {
            VertexBufferMorph& vbMorph = j->second_;
            if (vbMorph.dataSize_)
            {
                SharedArrayPtr<unsigned char> cloneData(new unsigned char[vbMorph.dataSize_]);
                memcpy(cloneData.Get(), vbMorph.morphData_.Get(), vbMorph.dataSize_);
                vbMorph.morphData_ = cloneData;
            }
        }
    }

    ret->SetMemoryUse(GetMemoryUse());

    return ret;
}
void WebFrameLoaderClient::dispatchDidFinishLoad()
{
    SharedPtr<WebFrameLoadDelegate> webFrameLoadDelegate = m_webFrame->webView()->webFrameLoadDelegate();
    if (webFrameLoadDelegate)
        webFrameLoadDelegate->didFinishLoad(m_webFrame);
}