Changeset View
Changeset View
Standalone View
Standalone View
source/blender/io/common/intern/abstract_hierarchy_iterator.cc
| Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| original_export_path = reference_export_path; | original_export_path = reference_export_path; | ||||
| } | } | ||||
| void HierarchyContext::mark_as_not_instanced() | void HierarchyContext::mark_as_not_instanced() | ||||
| { | { | ||||
| original_export_path.clear(); | original_export_path.clear(); | ||||
| } | } | ||||
| EnsuredWriter::EnsuredWriter() : writer_(nullptr), newly_created_(false) | |||||
| { | |||||
| } | |||||
| EnsuredWriter::EnsuredWriter(AbstractHierarchyWriter *writer, bool newly_created) | |||||
| : writer_(writer), newly_created_(newly_created) | |||||
| { | |||||
| } | |||||
| EnsuredWriter EnsuredWriter::empty() | |||||
| { | |||||
| return EnsuredWriter(nullptr, false); | |||||
| } | |||||
| EnsuredWriter EnsuredWriter::existing(AbstractHierarchyWriter *writer) | |||||
| { | |||||
| return EnsuredWriter(writer, false); | |||||
| } | |||||
| EnsuredWriter EnsuredWriter::newly_created(AbstractHierarchyWriter *writer) | |||||
| { | |||||
| return EnsuredWriter(writer, true); | |||||
| } | |||||
| bool EnsuredWriter::is_newly_created() const | |||||
| { | |||||
| return newly_created_; | |||||
| } | |||||
| EnsuredWriter::operator bool() const | |||||
| { | |||||
| return writer_ != nullptr; | |||||
| } | |||||
| AbstractHierarchyWriter *EnsuredWriter::operator->() | |||||
| { | |||||
| return writer_; | |||||
| } | |||||
| AbstractHierarchyWriter::~AbstractHierarchyWriter() | AbstractHierarchyWriter::~AbstractHierarchyWriter() | ||||
| { | { | ||||
| } | } | ||||
| bool AbstractHierarchyWriter::check_is_animated(const HierarchyContext &context) const | bool AbstractHierarchyWriter::check_is_animated(const HierarchyContext &context) const | ||||
| { | { | ||||
| const Object *object = context.object; | const Object *object = context.object; | ||||
| Show All 14 Lines | while (md) { | ||||
| } | } | ||||
| md = md->next; | md = md->next; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph) | AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph) | ||||
| : depsgraph_(depsgraph), writers_() | : depsgraph_(depsgraph), writers_(), export_subset_({true, true}) | ||||
| { | { | ||||
| } | } | ||||
| AbstractHierarchyIterator::~AbstractHierarchyIterator() | AbstractHierarchyIterator::~AbstractHierarchyIterator() | ||||
| { | { | ||||
| } | } | ||||
| void AbstractHierarchyIterator::iterate_and_write() | void AbstractHierarchyIterator::iterate_and_write() | ||||
| Show All 10 Lines | |||||
| void AbstractHierarchyIterator::release_writers() | void AbstractHierarchyIterator::release_writers() | ||||
| { | { | ||||
| for (WriterMap::value_type it : writers_) { | for (WriterMap::value_type it : writers_) { | ||||
| delete_object_writer(it.second); | delete_object_writer(it.second); | ||||
| } | } | ||||
| writers_.clear(); | writers_.clear(); | ||||
| } | } | ||||
| void AbstractHierarchyIterator::set_export_subset(ExportSubset export_subset) | |||||
| { | |||||
| export_subset_ = export_subset; | |||||
| } | |||||
| std::string AbstractHierarchyIterator::make_valid_name(const std::string &name) const | std::string AbstractHierarchyIterator::make_valid_name(const std::string &name) const | ||||
| { | { | ||||
| return name; | return name; | ||||
| } | } | ||||
| std::string AbstractHierarchyIterator::get_id_name(const ID *id) const | std::string AbstractHierarchyIterator::get_id_name(const ID *id) const | ||||
| { | { | ||||
| if (id == nullptr) { | if (id == nullptr) { | ||||
| ▲ Show 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | for (HierarchyContext *context : children) { | ||||
| } | } | ||||
| determine_duplication_references(context, indent + " "); | determine_duplication_references(context, indent + " "); | ||||
| } | } | ||||
| } | } | ||||
| void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_context) | void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_context) | ||||
| { | { | ||||
| AbstractHierarchyWriter *transform_writer = nullptr; | |||||
| float parent_matrix_inv_world[4][4]; | float parent_matrix_inv_world[4][4]; | ||||
| if (parent_context) { | if (parent_context) { | ||||
| invert_m4_m4(parent_matrix_inv_world, parent_context->matrix_world); | invert_m4_m4(parent_matrix_inv_world, parent_context->matrix_world); | ||||
| } | } | ||||
| else { | else { | ||||
| unit_m4(parent_matrix_inv_world); | unit_m4(parent_matrix_inv_world); | ||||
| } | } | ||||
| for (HierarchyContext *context : graph_children(parent_context)) { | for (HierarchyContext *context : graph_children(parent_context)) { | ||||
| // Update the context so that it is correct for this parent-child relation. | // Update the context so that it is correct for this parent-child relation. | ||||
| copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world); | copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world); | ||||
| // Get or create the transform writer. | // Get or create the transform writer. | ||||
| transform_writer = ensure_writer(context, &AbstractHierarchyIterator::create_transform_writer); | EnsuredWriter transform_writer = ensure_writer( | ||||
| if (transform_writer == nullptr) { | context, &AbstractHierarchyIterator::create_transform_writer); | ||||
| if (!transform_writer) { | |||||
| // Unable to export, so there is nothing to attach any children to; just abort this entire | // Unable to export, so there is nothing to attach any children to; just abort this entire | ||||
| // branch of the export hierarchy. | // branch of the export hierarchy. | ||||
| return; | return; | ||||
| } | } | ||||
| BLI_assert(DEG_is_evaluated_object(context->object)); | BLI_assert(DEG_is_evaluated_object(context->object)); | ||||
| /* XXX This can lead to too many XForms being written. For example, a camera writer can refuse | if (transform_writer.is_newly_created() || export_subset_.transforms) { | ||||
| * to write an orthographic camera. By the time that this is known, the XForm has already been | /* XXX This can lead to too many XForms being written. For example, a camera writer can | ||||
| * written. */ | * refuse to write an orthographic camera. By the time that this is known, the XForm has | ||||
| * already been written. */ | |||||
| transform_writer->write(*context); | transform_writer->write(*context); | ||||
| } | |||||
| if (!context->weak_export) { | if (!context->weak_export) { | ||||
| make_writers_particle_systems(context); | make_writers_particle_systems(context); | ||||
| make_writer_object_data(context); | make_writer_object_data(context); | ||||
| } | } | ||||
| // Recurse into this object's children. | // Recurse into this object's children. | ||||
| make_writers(context); | make_writers(context); | ||||
| Show All 16 Lines | void AbstractHierarchyIterator::make_writer_object_data(const HierarchyContext *context) | ||||
| if (data_context.is_instance()) { | if (data_context.is_instance()) { | ||||
| ID *object_data = static_cast<ID *>(context->object->data); | ID *object_data = static_cast<ID *>(context->object->data); | ||||
| data_context.original_export_path = duplisource_export_path_[object_data]; | data_context.original_export_path = duplisource_export_path_[object_data]; | ||||
| /* If the object is marked as an instance, so should the object data. */ | /* If the object is marked as an instance, so should the object data. */ | ||||
| BLI_assert(data_context.is_instance()); | BLI_assert(data_context.is_instance()); | ||||
| } | } | ||||
| AbstractHierarchyWriter *data_writer; | /* Always write upon creation, otherwise depend on which subset is active. */ | ||||
| data_writer = ensure_writer(&data_context, &AbstractHierarchyIterator::create_data_writer); | EnsuredWriter data_writer = ensure_writer(&data_context, | ||||
| if (data_writer == nullptr) { | &AbstractHierarchyIterator::create_data_writer); | ||||
| if (!data_writer) { | |||||
| return; | return; | ||||
| } | } | ||||
| if (data_writer.is_newly_created() || export_subset_.shapes) { | |||||
| data_writer->write(data_context); | data_writer->write(data_context); | ||||
| } | } | ||||
| } | |||||
| void AbstractHierarchyIterator::make_writers_particle_systems( | void AbstractHierarchyIterator::make_writers_particle_systems( | ||||
| const HierarchyContext *transform_context) | const HierarchyContext *transform_context) | ||||
| { | { | ||||
| Object *object = transform_context->object; | Object *object = transform_context->object; | ||||
| ParticleSystem *psys = static_cast<ParticleSystem *>(object->particlesystem.first); | ParticleSystem *psys = static_cast<ParticleSystem *>(object->particlesystem.first); | ||||
| for (; psys; psys = psys->next) { | for (; psys; psys = psys->next) { | ||||
| if (!psys_check_enabled(object, psys, true)) { | if (!psys_check_enabled(object, psys, true)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| HierarchyContext hair_context = *transform_context; | HierarchyContext hair_context = *transform_context; | ||||
| hair_context.export_path = path_concatenate(transform_context->export_path, | hair_context.export_path = path_concatenate(transform_context->export_path, | ||||
| make_valid_name(psys->name)); | make_valid_name(psys->name)); | ||||
| hair_context.particle_system = psys; | hair_context.particle_system = psys; | ||||
| AbstractHierarchyWriter *writer = nullptr; | EnsuredWriter writer; | ||||
| switch (psys->part->type) { | switch (psys->part->type) { | ||||
| case PART_HAIR: | case PART_HAIR: | ||||
| writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_hair_writer); | writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_hair_writer); | ||||
| break; | break; | ||||
| case PART_EMITTER: | case PART_EMITTER: | ||||
| writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_particle_writer); | writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_particle_writer); | ||||
| break; | break; | ||||
| } | } | ||||
| if (!writer) { | |||||
| continue; | |||||
| } | |||||
| if (writer != nullptr) { | /* Always write upon creation, otherwise depend on which subset is active. */ | ||||
| if (writer.is_newly_created() || export_subset_.shapes) { | |||||
| writer->write(hair_context); | writer->write(hair_context); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| std::string AbstractHierarchyIterator::get_object_name(const Object *object) const | std::string AbstractHierarchyIterator::get_object_name(const Object *object) const | ||||
| { | { | ||||
| return get_id_name(&object->id); | return get_id_name(&object->id); | ||||
| Show All 11 Lines | AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer( | ||||
| WriterMap::const_iterator it = writers_.find(export_path); | WriterMap::const_iterator it = writers_.find(export_path); | ||||
| if (it == writers_.end()) { | if (it == writers_.end()) { | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| return it->second; | return it->second; | ||||
| } | } | ||||
| AbstractHierarchyWriter *AbstractHierarchyIterator::ensure_writer( | EnsuredWriter AbstractHierarchyIterator::ensure_writer( | ||||
| HierarchyContext *context, AbstractHierarchyIterator::create_writer_func create_func) | HierarchyContext *context, AbstractHierarchyIterator::create_writer_func create_func) | ||||
| { | { | ||||
| AbstractHierarchyWriter *writer = get_writer(context->export_path); | AbstractHierarchyWriter *writer = get_writer(context->export_path); | ||||
| if (writer != nullptr) { | if (writer != nullptr) { | ||||
| return writer; | return EnsuredWriter::existing(writer); | ||||
| } | } | ||||
| writer = (this->*create_func)(context); | writer = (this->*create_func)(context); | ||||
| if (writer == nullptr) { | if (writer == nullptr) { | ||||
| return nullptr; | return EnsuredWriter::empty(); | ||||
| } | } | ||||
| writers_[context->export_path] = writer; | writers_[context->export_path] = writer; | ||||
| return EnsuredWriter::newly_created(writer); | |||||
| return writer; | |||||
| } | } | ||||
| std::string AbstractHierarchyIterator::path_concatenate(const std::string &parent_path, | std::string AbstractHierarchyIterator::path_concatenate(const std::string &parent_path, | ||||
| const std::string &child_path) const | const std::string &child_path) const | ||||
| { | { | ||||
| return parent_path + "/" + child_path; | return parent_path + "/" + child_path; | ||||
| } | } | ||||
| Show All 11 Lines | |||||