void SceneTreeEditor::_compute_hash(Node *p_node, uint64_t &hash) { hash = hash_djb2_one_64(p_node->get_instance_id(), hash); if (p_node->get_parent()) hash = hash_djb2_one_64(p_node->get_parent()->get_instance_id(), hash); //so a reparent still produces a different hash for (int i = 0; i < p_node->get_child_count(); i++) { _compute_hash(p_node->get_child(i), hash); } }
void SceneTreeEditor::_update_tree() { if (!is_inside_tree()) { tree_dirty = false; return; } updating_tree = true; tree->clear(); if (get_scene_node()) { _add_nodes(get_scene_node(), NULL); last_hash = hash_djb2_one_64(0); _compute_hash(get_scene_node(), last_hash); } updating_tree = false; tree_dirty = false; }
void SceneTreeEditor::_test_update_tree() { pending_test_update=false; if (!is_inside_tree()) return; if(tree_dirty) return; // don't even bother uint64_t hash = hash_djb2_one_64(0); if (get_scene_node()) _compute_hash(get_scene_node(),hash); //test hash if (hash==last_hash) return; // did not change MessageQueue::get_singleton()->push_call(this,"_update_tree"); tree_dirty=true; }
uint64_t ClassDB::get_api_hash(APIType p_api) { OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG)); List<StringName> names; const StringName *k = NULL; while ((k = classes.next(k))) { names.push_back(*k); } //must be alphabetically sorted for hash to compute names.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { ClassInfo *t = classes.getptr(E->get()); ERR_FAIL_COND_V(!t, 0); if (t->api != p_api || !t->exposed) continue; hash = hash_djb2_one_64(t->name.hash(), hash); hash = hash_djb2_one_64(t->inherits.hash(), hash); { //methods List<StringName> snames; k = NULL; while ((k = t->method_map.next(k))) { snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { MethodBind *mb = t->method_map[F->get()]; hash = hash_djb2_one_64(mb->get_name().hash(), hash); hash = hash_djb2_one_64(mb->get_argument_count(), hash); hash = hash_djb2_one_64(mb->get_argument_type(-1), hash); //return for (int i = 0; i < mb->get_argument_count(); i++) { const PropertyInfo info = mb->get_argument_info(i); hash = hash_djb2_one_64(info.type, hash); hash = hash_djb2_one_64(info.name.hash(), hash); hash = hash_djb2_one_64(info.hint, hash); hash = hash_djb2_one_64(info.hint_string.hash(), hash); } hash = hash_djb2_one_64(mb->get_default_argument_count(), hash); for (int i = 0; i < mb->get_default_argument_count(); i++) { //hash should not change, i hope for tis Variant da = mb->get_default_argument(i); hash = hash_djb2_one_64(da.hash(), hash); } hash = hash_djb2_one_64(mb->get_hint_flags(), hash); } } { //constants List<StringName> snames; k = NULL; while ((k = t->constant_map.next(k))) { snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { hash = hash_djb2_one_64(F->get().hash(), hash); hash = hash_djb2_one_64(t->constant_map[F->get()], hash); } } { //signals List<StringName> snames; k = NULL; while ((k = t->signal_map.next(k))) { snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { MethodInfo &mi = t->signal_map[F->get()]; hash = hash_djb2_one_64(F->get().hash(), hash); for (int i = 0; i < mi.arguments.size(); i++) { hash = hash_djb2_one_64(mi.arguments[i].type, hash); } } } { //properties List<StringName> snames; k = NULL; while ((k = t->property_setget.next(k))) { snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { PropertySetGet *psg = t->property_setget.getptr(F->get()); hash = hash_djb2_one_64(F->get().hash(), hash); hash = hash_djb2_one_64(psg->setter.hash(), hash); hash = hash_djb2_one_64(psg->getter.hash(), hash); } } //property list for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) { hash = hash_djb2_one_64(F->get().name.hash(), hash); hash = hash_djb2_one_64(F->get().type, hash); hash = hash_djb2_one_64(F->get().hint, hash); hash = hash_djb2_one_64(F->get().hint_string.hash(), hash); hash = hash_djb2_one_64(F->get().usage, hash); } } return hash; #else return 0; #endif }
uint32_t Variant::hash() const { switch( type ) { case NIL: { return 0; } break; case BOOL: { return _data._bool?1:0; } break; case INT: { return _data._int; } break; case REAL: { MarshallFloat mf; mf.f=_data._real; return mf.i; } break; case STRING: { return reinterpret_cast<const String*>(_data._mem)->hash(); } break; // math types case VECTOR2: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2*>(_data._mem)->x); return hash_djb2_one_float(reinterpret_cast<const Vector2*>(_data._mem)->y,hash); } break; case RECT2: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2*>(_data._mem)->pos.x); hash = hash_djb2_one_float(reinterpret_cast<const Rect2*>(_data._mem)->pos.y,hash); hash = hash_djb2_one_float(reinterpret_cast<const Rect2*>(_data._mem)->size.x,hash); return hash_djb2_one_float(reinterpret_cast<const Rect2*>(_data._mem)->size.y,hash); } break; case MATRIX32: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<2;j++) { hash = hash_djb2_one_float(_data._matrix32->elements[i][j],hash); } } return hash; } break; case VECTOR3: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3*>(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast<const Vector3*>(_data._mem)->y,hash); return hash_djb2_one_float(reinterpret_cast<const Vector3*>(_data._mem)->z,hash); } break; case PLANE: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane*>(_data._mem)->normal.x); hash = hash_djb2_one_float(reinterpret_cast<const Plane*>(_data._mem)->normal.y,hash); hash = hash_djb2_one_float(reinterpret_cast<const Plane*>(_data._mem)->normal.z,hash); return hash_djb2_one_float(reinterpret_cast<const Plane*>(_data._mem)->d,hash); } break; /* case QUAT: { } break;*/ case _AABB: { uint32_t hash = 5831; for(int i=0;i<3;i++) { hash = hash_djb2_one_float(_data._aabb->pos[i],hash); hash = hash_djb2_one_float(_data._aabb->size[i],hash); } return hash; } break; case QUAT: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quat*>(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast<const Quat*>(_data._mem)->y,hash); hash = hash_djb2_one_float(reinterpret_cast<const Quat*>(_data._mem)->z,hash); return hash_djb2_one_float(reinterpret_cast<const Quat*>(_data._mem)->w,hash); } break; case MATRIX3: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { hash = hash_djb2_one_float(_data._matrix3->elements[i][j],hash); } } return hash; } break; case TRANSFORM: { uint32_t hash = 5831; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { hash = hash_djb2_one_float(_data._transform->basis.elements[i][j],hash); } hash = hash_djb2_one_float(_data._transform->origin[i],hash); } return hash; } break; // misc types case COLOR: { uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Color*>(_data._mem)->r); hash = hash_djb2_one_float(reinterpret_cast<const Color*>(_data._mem)->g,hash); hash = hash_djb2_one_float(reinterpret_cast<const Color*>(_data._mem)->b,hash); return hash_djb2_one_float(reinterpret_cast<const Color*>(_data._mem)->a,hash); } break; case IMAGE: { return 0; } break; case _RID: { return hash_djb2_one_64(reinterpret_cast<const RID*>(_data._mem)->get_id()); } break; case OBJECT: { return hash_djb2_one_64(make_uint64_t(_get_obj().obj)); } break; case NODE_PATH: { return reinterpret_cast<const NodePath*>(_data._mem)->hash(); } break; case INPUT_EVENT: { return hash_djb2_buffer((uint8_t*)_data._input_event,sizeof(InputEvent)); } break; case DICTIONARY: { return reinterpret_cast<const Dictionary*>(_data._mem)->hash(); } break; case ARRAY: { const Array& arr = *reinterpret_cast<const Array* >(_data._mem); return arr.hash(); } break; case RAW_ARRAY: { const DVector<uint8_t>& arr = *reinterpret_cast<const DVector<uint8_t>* >(_data._mem); int len = arr.size(); DVector<uint8_t>::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len); } break; case INT_ARRAY: { const DVector<int>& arr = *reinterpret_cast<const DVector<int>* >(_data._mem); int len = arr.size(); DVector<int>::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len*sizeof(int)); } break; case REAL_ARRAY: { const DVector<real_t>& arr = *reinterpret_cast<const DVector<real_t>* >(_data._mem); int len = arr.size(); DVector<real_t>::Read r = arr.read(); return hash_djb2_buffer((uint8_t*)&r[0],len*sizeof(real_t)); } break; case STRING_ARRAY: { uint32_t hash=5831; const DVector<String>& arr = *reinterpret_cast<const DVector<String>* >(_data._mem); int len = arr.size(); DVector<String>::Read r = arr.read(); for(int i=0;i<len;i++) { hash = hash_djb2_one_32(r[i].hash(),hash); } return hash; } break; case VECTOR2_ARRAY: { uint32_t hash=5831; const DVector<Vector2>& arr = *reinterpret_cast<const DVector<Vector2>* >(_data._mem); int len = arr.size(); DVector<Vector2>::Read r = arr.read(); for(int i=0;i<len;i++) { hash = hash_djb2_one_float(r[i].x,hash); hash = hash_djb2_one_float(r[i].y,hash); } return hash; } break; case VECTOR3_ARRAY: { uint32_t hash=5831; const DVector<Vector3>& arr = *reinterpret_cast<const DVector<Vector3>* >(_data._mem); int len = arr.size(); DVector<Vector3>::Read r = arr.read(); for(int i=0;i<len;i++) { hash = hash_djb2_one_float(r[i].x,hash); hash = hash_djb2_one_float(r[i].y,hash); hash = hash_djb2_one_float(r[i].z,hash); } return hash; } break; case COLOR_ARRAY: { uint32_t hash=5831; const DVector<Color>& arr = *reinterpret_cast<const DVector<Color>* >(_data._mem); int len = arr.size(); DVector<Color>::Read r = arr.read(); for(int i=0;i<len;i++) { hash = hash_djb2_one_float(r[i].r,hash); hash = hash_djb2_one_float(r[i].g,hash); hash = hash_djb2_one_float(r[i].b,hash); hash = hash_djb2_one_float(r[i].a,hash); } return hash; } break; default: {} } return 0; }