Skip to content

Conversation

aaronfranke
Copy link
Member

@aaronfranke aaronfranke commented Jul 19, 2025

As a follow-up to some recent editor organization efforts, this PR organizes more of the 3D editor code.

The way I made this PR is by working on my own changes to allow disabling the 3D in the editor, but without any intention to merge those in. Instead, I want to only merge in organizational changes that makes sense even without that ability.

Rather than making a bulleted list, I have left review comments below. It may be a good idea to review this PR by reading those and using 👍 if that part looks good to you, or replying if not.

@aaronfranke aaronfranke added this to the 4.6 milestone Jul 19, 2025
@aaronfranke aaronfranke requested review from a team as code owners July 19, 2025 05:14
@aaronfranke aaronfranke requested review from a team as code owners July 19, 2025 05:14
@aaronfranke aaronfranke requested review from a team as code owners July 19, 2025 05:14
@aaronfranke aaronfranke requested review from a team as code owners July 19, 2025 05:14

#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a small number of cases where a header needs a class to work, but wasn't including it. These things were being included transitively when 3D is enabled in the editor, but fail to compile otherwise. This PR fixes these cases by adding the includes, including this one include in the core folder, and a few others elsewhere.

switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
Node3DEditor::get_singleton()->connect(SNAME("transform_key_request"), callable_mp(this, &AnimationPlayerEditorPlugin::_transform_key_request));
Node3DEditor::get_singleton()->connect(SNAME("transform_3d_key_request"), callable_mp(this, &AnimationPlayerEditorPlugin::_transform_3d_key_request));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were a few APIs in the animation editor, and this signal for communicating with Node3DEditor, with "transform" in the name, but these APIs only operate on 3D transform. I've renamed them with "3d" for clarity. These are internal APIs, not exposed anywhere.

Comment on lines +4729 to +4757
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
if (canvas_item) {
new_additive_node_entry.transform_2d = canvas_item->get_transform();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This preserves the transform data of CanvasItems, though the data still doesn't end up being used currently. I didn't want to change too much in this PR but this would enable us to support Control nodes in EditorNode::reload_instances_with_path_in_edited_scenes() later if we wanted to.


Ref<ORMMaterial3DConversionPlugin> orm_mat_convert;
orm_mat_convert.instantiate();
resource_conversion_plugins.push_back(orm_mat_convert);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This groups together EditorNode's registration of 3D material conversion plugins.

Comment on lines +4499 to +4590
void _insert_collision_object_rid_recursive(Node *p_node, HashSet<RID> &p_col_obj_rids) {
CollisionObject3D *col_obj = Object::cast_to<CollisionObject3D>(p_node);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several renames for clarity, and to match Godot's p_ naming convention. node -> p_node, rids -> p_col_obj_rids, co -> col_obj, and below rids -> col_obj_rids_to_exclude.

AnimatedSprite2D *as2d = Object::cast_to<AnimatedSprite2D>(selected);
AnimatedSprite3D *as3d = Object::cast_to<AnimatedSprite3D>(selected);
if (as2d || as3d) {
if (selected->has_method("get_sprite_frames")) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using ->call("get_sprite_frames") immediately below, so this is less code and more straightforward of a check. Technically could allow user-made AnimatedSprite classes, but that wasn't a goal here, just a happy consequence.

} else if (res_atlas_texture.is_valid()) {
r = res_atlas_texture->get_region();
}
Rect2 r = _get_edited_object_region();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ This changes behavior, this part needs close review.

This change reduces code duplication, since this logic is already present in the _get_edited_object_region helper function. However, that function also contains this code:

	const Ref<Texture2D> object_texture = _get_edited_object_texture();
	if (region == Rect2() && object_texture.is_valid()) {
		region = Rect2(Vector2(), object_texture->get_size());
	}

I think that's fine, since it only happens when region is a zero rect, and my guess is that using object_texture's rect as a fallback is better than no fallback, but I can't be certain of that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it and don't see any difference in behavior.

undo_redo->add_do_method(node_sprite_3d, "set_region_rect", node_sprite_3d->get_region_rect());
undo_redo->add_undo_method(node_sprite_3d, "set_region_rect", rect_prev);
} else if (node_ninepatch) {
if (node_ninepatch) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In these if statements, put Control-based things first, and Node2D/Node3D things after it. This is arguably more organized, but the motivation here was so you can put #ifndef _2D_DISABLED above the } else if (condition) {.

PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
root_collision_body = PhysicsServer3D::get_singleton()->body_create();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is only ever null or the result of body_create(), so it's a body. The word "instance" is too generic, it's not clear if it's a body, area, shape, etc. Therefore, I renamed it.

@aaronfranke aaronfranke requested a review from KoBeWi July 21, 2025 16:24
@WhalesState

This comment was marked as resolved.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, it works as expected. Code looks good to me.

undo_redo->add_undo_method(this, "_set_owner_for_node_and_children", n2d, editor_root);
}
undo_redo->commit_action();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated noisy change IMO, I'd restore


case CONTAINER_SPATIAL_EDITOR_MENU: {
Node3DEditor::get_singleton()->add_control_to_menu_panel(p_control);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove them, it's unnecessary noise for minor nitpicking change

// Make sure MeshLibrary is updated in the editor.
ResourceLoader::load(p_file)->reload_from_file();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please restore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants