StringHash StringHashRegister::RegisterString(const StringHash& hash, const char* string) { if (mutex_) mutex_->Acquire(); auto iter = map_.find(hash); if (iter == map_.end()) { map_[hash] = string; } else if (iter->compare(string, Qt::CaseInsensitive) != 0) { URHO3D_LOGWARNING(QString::asprintf("StringHash collision detected! Both \"%s\" and \"%s\" have hash #%s", string, qPrintable(*iter), qPrintable(hash.ToString()))); } if (mutex_) mutex_->Release(); return hash; }
StringHash StringHashRegister::RegisterString(const StringHash& hash, const char* string) { if (mutex_) mutex_->Acquire(); auto iter = map_.Find(hash); if (iter == map_.End()) { map_.Populate(hash, string); } else if (iter->second_.Compare(string, false) != 0) { URHO3D_LOGWARNINGF("StringHash collision detected! Both \"%s\" and \"%s\" have hash #%s", string, iter->second_.CString(), hash.ToString().CString()); } if (mutex_) mutex_->Release(); return hash; }
void Node::SetNetParentAttr(const PODVector<unsigned char>& value) { Scene* scene = GetScene(); if (!scene) return; MemoryBuffer buf(value); // If nothing in the buffer, parent is the root node if (buf.IsEof()) { scene->AddChild(this); return; } unsigned baseNodeID = buf.ReadNetID(); Node* baseNode = scene->GetNode(baseNodeID); if (!baseNode) { LOGWARNING("Failed to find parent node " + String(baseNodeID)); return; } // If buffer contains just an ID, the parent is replicated and we are done if (buf.IsEof()) baseNode->AddChild(this); else { // Else the parent is local and we must find it recursively by name hash StringHash nameHash = buf.ReadStringHash(); Node* parentNode = baseNode->GetChild(nameHash, true); if (!parentNode) LOGWARNING("Failed to find parent node with name hash " + nameHash.ToString()); else parentNode->AddChild(this); } }
bool BackgroundLoader::QueueResource(StringHash type, const ea::string& name, bool sendEventOnFailure, Resource* caller) { StringHash nameHash(name); ea::pair<StringHash, StringHash> key = ea::make_pair(type, nameHash); MutexLock lock(backgroundLoadMutex_); // Check if already exists in the queue if (backgroundLoadQueue_.find(key) != backgroundLoadQueue_.end()) return false; BackgroundLoadItem& item = backgroundLoadQueue_[key]; item.sendEventOnFailure_ = sendEventOnFailure; // Make sure the pointer is non-null and is a Resource subclass item.resource_ = DynamicCast<Resource>(owner_->GetContext()->CreateObject(type)); if (!item.resource_) { URHO3D_LOGERROR("Could not load unknown resource type " + type.ToString()); if (sendEventOnFailure && Thread::IsMainThread()) { using namespace UnknownResourceType; VariantMap& eventData = owner_->GetEventDataMap(); eventData[P_RESOURCETYPE] = type; owner_->SendEvent(E_UNKNOWNRESOURCETYPE, eventData); } backgroundLoadQueue_.erase(key); return false; } URHO3D_LOGDEBUG("Background loading resource " + name); item.resource_->SetName(name); item.resource_->SetAsyncLoadState(ASYNC_QUEUED); // If this is a resource calling for the background load of more resources, mark the dependency as necessary if (caller) { ea::pair<StringHash, StringHash> callerKey = ea::make_pair(caller->GetType(), caller->GetNameHash()); auto j = backgroundLoadQueue_.find( callerKey); if (j != backgroundLoadQueue_.end()) { BackgroundLoadItem& callerItem = j->second; item.dependents_.insert(callerKey); callerItem.dependencies_.insert(key); } else URHO3D_LOGWARNING("Resource " + caller->GetName() + " requested for a background loaded resource but was not in the background load queue"); } // Start the background loader thread now if (!IsStarted()) Run(); return true; }
void JSEventHelper::HandleEvent(StringHash eventType, VariantMap& eventData) { if (object_.Null()) return; JSVM* vm = JSVM::GetJSVM(0); duk_context* ctx = vm->GetJSContext(); duk_idx_t top = duk_get_top(ctx); js_push_class_object_instance(ctx, this); duk_get_prop_string(ctx, -1, "__eventHelperFunctions"); assert(duk_is_object(ctx, -1)); duk_get_prop_string(ctx, -1, eventType.ToString().CString()); if (duk_is_function(ctx, -1)) { // look in the variant map cache duk_push_global_stash(ctx); duk_get_prop_index(ctx, -1, JS_GLOBALSTASH_VARIANTMAP_CACHE); duk_push_pointer(ctx, (void*) &eventData); duk_get_prop(ctx, -2); if (!duk_is_object(ctx, -1)) { // pop result duk_pop(ctx); // we need to push a new variant map and store to cache // the cache object will be cleared at the send end in the // global listener above js_push_variantmap(ctx, eventData); duk_push_pointer(ctx, (void*) &eventData); duk_dup(ctx, -2); duk_put_prop(ctx, -4); } duk_remove(ctx, -2); // vmap cache duk_remove(ctx, -2); // global stash if (duk_pcall(ctx, 1) != 0) { vm->SendJSErrorEvent(); } else { // For widget events, need to check return value // and set whether handled if (eventType == E_WIDGETEVENT) { if (duk_is_boolean(ctx, -1)) { if (duk_to_boolean(ctx, -1)) { eventData[WidgetEvent::P_HANDLED] = true; } } } } } duk_set_top(ctx, top); }