From c3a651f01dba22ca66c068658e34ba2f314e18b1 Mon Sep 17 00:00:00 2001 From: Variable <77773850+Variable-ind@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:26:24 +0500 Subject: [PATCH] Fix cel3d compatibility when transferring project from 0.x to 1.0 (#927) * part 1/2 * part 2/2 * increased pxo version * improvements * formatting * formatting (missed this one on last commit) * fix capsule and text 3d * formatting * fixed capsule shape * Fixed text mesh and exposed some new parameters * fix some typos * Fixed some bugs * minor typo * formatting * thin lines on hover, thick lines on select * add proposed changes --- project.godot | 2 +- src/Classes/Cel3D.gd | 84 ++++++++++++++++++++++++++++++++++--- src/Classes/Cel3DObject.gd | 6 +++ src/Classes/Project.gd | 2 + src/Tools/3DShapeEdit.gd | 13 +++--- src/Tools/3DShapeEdit.tscn | 85 +++++++++++++++++++++++++++++++++++--- src/UI/Canvas/Gizmos3D.gd | 4 +- 7 files changed, 178 insertions(+), 18 deletions(-) diff --git a/project.godot b/project.godot index 610636e26..3677f4cca 100644 --- a/project.godot +++ b/project.godot @@ -24,7 +24,7 @@ config/macos_native_icon="res://assets/graphics/icons/icon.icns" config/windows_native_icon="res://assets/graphics/icons/icon.ico" config/Version="v1.0-dev" config/ExtensionsAPI_Version=4 -config/Pxo_Version=2 +config/Pxo_Version=3 [audio] diff --git a/src/Classes/Cel3D.gd b/src/Classes/Cel3D.gd index 3de3e1d47..c4d62533d 100644 --- a/src/Classes/Cel3D.gd +++ b/src/Classes/Cel3D.gd @@ -180,25 +180,99 @@ func serialize() -> Dictionary: func deserialize(dict: Dictionary) -> void: + if dict.has("pxo_version"): + if dict["pxo_version"] == 2: # It's a 0.x project convert it to 1.0 format + convert_0x_to_1x(dict) super.deserialize(dict) scene_properties = {} var scene_properties_str: Dictionary = dict["scene_properties"] + var objects_copy_str: Dictionary = dict["object_properties"] for prop in scene_properties_str: scene_properties[prop] = str_to_var(scene_properties_str[prop]) - var objects_copy_str: Dictionary = dict["object_properties"] - for object in objects_copy_str: - if typeof(object) != TYPE_STRING: + for object_id_as_str in objects_copy_str: + if typeof(object_id_as_str) != TYPE_STRING: # failsafe in case something has gone wrong return - var id := int(object) + var id := int(object_id_as_str) if current_object_id < id: current_object_id = id - object_properties[id] = str_to_var(objects_copy_str[object]) + object_properties[id] = str_to_var(objects_copy_str[object_id_as_str]) current_object_id += 1 deserialize_scene_properties() for object in object_properties: _add_object_node(object) +## Used to convert 3d cels found in projects exported from a 0.x version to 1.x +func convert_0x_to_1x(dict: Dictionary) -> void: + # Converting the scene dictionary + var scene_dict: Dictionary = dict["scene_properties"] + var old_transform_string = scene_dict["camera_transform"] + scene_dict["camera_transform"] = ( + "Transform3D(" + old_transform_string.replace(" - ", ", ") + ")" + ) + scene_dict["camera_projection"] = var_to_str(int(scene_dict["camera_projection"])) + scene_dict["camera_fov"] = var_to_str(scene_dict["camera_fov"]) + scene_dict["camera_size"] = var_to_str(scene_dict["camera_size"]) + scene_dict["ambient_light_color"] = "Color(" + scene_dict["ambient_light_color"] + ")" + scene_dict["ambient_light_energy"] = var_to_str(scene_dict["ambient_light_energy"]) + # Converting the objects dictionary + var objects_copy_str: Dictionary = dict["object_properties"] + for object_id_as_str in objects_copy_str.keys(): + var object_info = objects_copy_str[object_id_as_str] + for object_property in object_info: + if object_property == "id" or object_property == "type": + object_info[object_property] = int(object_info[object_property]) + elif typeof(object_info[object_property]) != TYPE_STRING: + continue + elif "color" in object_property: # Convert a String to a Color + object_info[object_property] = str_to_var( + "Color(" + object_info[object_property] + ")" + ) + elif "transform" in object_property: # Convert a String to a Transform + var transform_string: String = object_info[object_property].replace(" - ", ", ") + object_info[object_property] = str_to_var("Transform3D(" + transform_string + ")") + elif "v2" in object_property: # Convert a String to a Vector2 + object_info[object_property] = str_to_var("Vector2" + object_info[object_property]) + elif "size" in object_property or "center_offset" in object_property: + # Convert a String to a Vector3 + object_info[object_property] = str_to_var("Vector3" + object_info[object_property]) + # Special operations to adjust gizmo + match object_info["type"]: + 0: # BOX + object_info["transform"] = object_info["transform"].scaled(Vector3.ONE * 2) + object_info["mesh_size"] /= 2 + 1: # SPHERE + object_info["transform"] = object_info["transform"].scaled(Vector3.ONE * 2) + object_info["mesh_radius"] /= 2 + object_info["mesh_height"] /= 2 + 2: # CAPSULE + object_info["transform"] = ( + object_info["transform"] + . scaled(Vector3.ONE * 2) + . rotated_local(Vector3.LEFT, deg_to_rad(-90)) + ) + object_info["mesh_radius"] /= 2 + object_info["mesh_height"] = ( + object_info["mesh_mid_height"] + object_info["mesh_radius"] + ) + 3: # CYLINDER + object_info["transform"] = object_info["transform"].scaled(Vector3.ONE * 2) + object_info["mesh_height"] /= 2 + object_info["mesh_bottom_radius"] /= 2 + object_info["mesh_top_radius"] /= 2 + 4: # PRISM + object_info["transform"] = object_info["transform"].scaled(Vector3.ONE * 2) + object_info["mesh_size"] /= 2 + 6: # PLANE + object_info["transform"] = object_info["transform"].scaled(Vector3.ONE * 2) + object_info["mesh_sizev2"] /= 2 + 7: # TEXT + object_info["mesh_vertical_alignment"] = VERTICAL_ALIGNMENT_BOTTOM + object_info["mesh_font_size"] = 12 + object_info["mesh_offset"] = Vector2.UP * 3 + objects_copy_str[object_id_as_str] = var_to_str(objects_copy_str[object_id_as_str]) + + func on_remove() -> void: if is_instance_valid(viewport): viewport.queue_free() diff --git a/src/Classes/Cel3DObject.gd b/src/Classes/Cel3DObject.gd index bd73debb1..b17a32606 100644 --- a/src/Classes/Cel3DObject.gd +++ b/src/Classes/Cel3DObject.gd @@ -95,8 +95,11 @@ func serialize() -> Dictionary: Type.TEXT: dict["mesh_text"] = mesh.text dict["mesh_pixel_size"] = mesh.pixel_size + dict["mesh_font_size"] = mesh.font_size + dict["mesh_offset"] = mesh.offset dict["mesh_curve_step"] = mesh.curve_step dict["mesh_horizontal_alignment"] = mesh.horizontal_alignment + dict["mesh_vertical_alignment"] = mesh.vertical_alignment else: dict["light_color"] = node3d_type.light_color dict["light_energy"] = node3d_type.light_energy @@ -153,8 +156,11 @@ func deserialize(dict: Dictionary) -> void: Type.TEXT: mesh.text = dict["mesh_text"] mesh.pixel_size = dict["mesh_pixel_size"] + mesh.font_size = dict["mesh_font_size"] + mesh.offset = dict["mesh_offset"] mesh.curve_step = dict["mesh_curve_step"] mesh.horizontal_alignment = dict["mesh_horizontal_alignment"] + mesh.vertical_alignment = dict["mesh_vertical_alignment"] else: node3d_type.light_color = dict["light_color"] node3d_type.light_energy = dict["light_energy"] diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index f27908f68..1dab1f5d7 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -377,6 +377,8 @@ func deserialize(dict: Dictionary) -> void: cels.append(GroupCel.new()) Global.LayerTypes.THREE_D: cels.append(Cel3D.new(size, true)) + if dict.has("pxo_version"): + cel["pxo_version"] = dict["pxo_version"] cels[cel_i].deserialize(cel) _deserialize_metadata(cels[cel_i], cel) cel_i += 1 diff --git a/src/Tools/3DShapeEdit.gd b/src/Tools/3DShapeEdit.gd index da42ba82a..4e1871bf7 100644 --- a/src/Tools/3DShapeEdit.gd +++ b/src/Tools/3DShapeEdit.gd @@ -58,9 +58,12 @@ var _object_names := { "node3d_type:mesh:top_radius": $"%MeshTopRadius", "node3d_type:mesh:bottom_radius": $"%MeshBottomRadius", "node3d_type:mesh:text": $"%MeshText", + "node3d_type:mesh:offset": $"%MeshOffsetV2", "node3d_type:mesh:pixel_size": $"%MeshPixelSize", + "node3d_type:mesh:font_size": $"%MeshFontSize", "node3d_type:mesh:curve_step": $"%MeshCurveStep", "node3d_type:mesh:horizontal_alignment": $"%MeshHorizontalAlignment", + "node3d_type:mesh:vertical_alignment": $"%MeshVerticalAlignment", "node3d_type:light_color": $"%LightColor", "node3d_type:light_energy": $"%LightEnergy", "node3d_type:light_negative": $"%LightNegative", @@ -118,8 +121,8 @@ func _ready() -> void: node.color_changed.connect(_object_property_color_changed.bind(prop)) elif node is CheckBox: node.toggled.connect(_object_property_toggled.bind(prop)) - elif node is LineEdit: - node.text_changed.connect(_object_property_text_changed.bind(prop)) + elif node is TextEdit: + node.text_changed.connect(_object_property_text_changed.bind(node, prop)) func draw_start(pos: Vector2i) -> void: @@ -369,7 +372,7 @@ func _set_node_values(to_edit: Object, properties: Dictionary) -> void: node.color = value elif node is CheckBox: node.button_pressed = value - elif node is LineEdit: + elif node is TextEdit: if node.text != value: node.text = value @@ -443,8 +446,8 @@ func _object_property_toggled(value: bool, prop: String) -> void: _value_handle_change() -func _object_property_text_changed(value: String, prop: String) -> void: - _set_value_from_node(_cel.selected, value, prop) +func _object_property_text_changed(text_edit: TextEdit, prop: String) -> void: + _set_value_from_node(_cel.selected, text_edit.text, prop) _value_handle_change() diff --git a/src/Tools/3DShapeEdit.tscn b/src/Tools/3DShapeEdit.tscn index c6c98bd99..f2ffed41b 100644 --- a/src/Tools/3DShapeEdit.tscn +++ b/src/Tools/3DShapeEdit.tscn @@ -285,6 +285,7 @@ columns = 2 layout_mode = 2 size_flags_horizontal = 3 text = "Size:" +clip_text = true [node name="MeshSize" parent="ObjectOptions/MeshOptions/GridContainer" index="1" instance=ExtResource("7")] unique_name_in_owner = true @@ -299,6 +300,7 @@ show_ratio = true layout_mode = 2 size_flags_horizontal = 3 text = "Size:" +clip_text = true [node name="MeshSizeV2" parent="ObjectOptions/MeshOptions/GridContainer" index="3" instance=ExtResource("3")] unique_name_in_owner = true @@ -313,6 +315,7 @@ snap_step = 0.01 layout_mode = 2 size_flags_horizontal = 3 text = "Left to right:" +clip_text = true [node name="MeshLeftToRight" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="5"] unique_name_in_owner = true @@ -336,6 +339,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Radius:" +clip_text = true [node name="MeshRadius" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="7"] unique_name_in_owner = true @@ -360,6 +364,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Height:" +clip_text = true [node name="MeshHeight" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="9"] unique_name_in_owner = true @@ -384,6 +389,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Radial segments:" +clip_text = true [node name="MeshRadialSegments" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="11"] unique_name_in_owner = true @@ -407,6 +413,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Rings:" +clip_text = true [node name="MeshRings" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="13"] unique_name_in_owner = true @@ -430,6 +437,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Is hemisphere:" +clip_text = true [node name="MeshIsHemisphere" type="CheckBox" parent="ObjectOptions/MeshOptions/GridContainer" index="15"] unique_name_in_owner = true @@ -442,6 +450,7 @@ text = "On" layout_mode = 2 size_flags_horizontal = 3 text = "Top radius:" +clip_text = true [node name="MeshTopRadius" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="17"] unique_name_in_owner = true @@ -465,6 +474,7 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Bottom radius:" +clip_text = true [node name="MeshBottomRadius" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="19"] unique_name_in_owner = true @@ -488,9 +498,11 @@ script = ExtResource("5") layout_mode = 2 size_flags_horizontal = 3 text = "Text:" +clip_text = true -[node name="MeshText" type="LineEdit" parent="ObjectOptions/MeshOptions/GridContainer" index="21"] +[node name="MeshText" type="TextEdit" parent="ObjectOptions/MeshOptions/GridContainer" index="21"] unique_name_in_owner = true +custom_minimum_size = Vector2(150, 50) layout_mode = 2 size_flags_horizontal = 3 @@ -498,6 +510,7 @@ size_flags_horizontal = 3 layout_mode = 2 size_flags_horizontal = 3 text = "Pixel size:" +clip_text = true [node name="MeshPixelSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="23"] unique_name_in_owner = true @@ -519,12 +532,53 @@ stretch_margin_bottom = 3 script = ExtResource("5") snap_step = 0.01 -[node name="MeshCurveStepLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"] +[node name="MeshFontSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Font size:" +clip_text = true + +[node name="MeshFontSize" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="25"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +focus_mode = 2 +mouse_default_cursor_shape = 2 +theme_type_variation = &"ValueSlider" +min_value = 1.0 +max_value = 10.0 +value = 1.0 +allow_greater = true +nine_patch_stretch = true +stretch_margin_left = 3 +stretch_margin_top = 3 +stretch_margin_right = 3 +stretch_margin_bottom = 3 +script = ExtResource("5") + +[node name="MeshOffsetLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="26"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Offset:" +clip_text = true + +[node name="MeshOffsetV2" parent="ObjectOptions/MeshOptions/GridContainer" index="27" instance=ExtResource("3")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +max_value = Vector2(10, 10) +allow_greater = true +allow_lesser = true +show_ratio = true +snap_step = 0.01 + +[node name="MeshCurveStepLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="28"] layout_mode = 2 size_flags_horizontal = 3 text = "Curve step:" +clip_text = true -[node name="MeshCurveStep" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="25"] +[node name="MeshCurveStep" type="TextureProgressBar" parent="ObjectOptions/MeshOptions/GridContainer" index="29"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -543,12 +597,13 @@ stretch_margin_right = 3 stretch_margin_bottom = 3 script = ExtResource("5") -[node name="MeshHorizontalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="26"] +[node name="MeshHorizontalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="30"] layout_mode = 2 size_flags_horizontal = 3 text = "Horizontal alignment:" +clip_text = true -[node name="MeshHorizontalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="27"] +[node name="MeshHorizontalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="31"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 @@ -562,6 +617,26 @@ popup/item_1/id = 1 popup/item_2/text = "Right" popup/item_2/id = 2 +[node name="MeshVerticalAlignmentLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="32"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Vertical alignment:" +clip_text = true + +[node name="MeshVerticalAlignment" type="OptionButton" parent="ObjectOptions/MeshOptions/GridContainer" index="33"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +mouse_default_cursor_shape = 2 +item_count = 3 +selected = 0 +popup/item_0/text = "Top" +popup/item_0/id = 0 +popup/item_1/text = "Center" +popup/item_1/id = 1 +popup/item_2/text = "Bottom" +popup/item_2/id = 2 + [node name="LightOptions" type="VBoxContainer" parent="ObjectOptions" index="3"] unique_name_in_owner = true layout_mode = 2 diff --git a/src/UI/Canvas/Gizmos3D.gd b/src/UI/Canvas/Gizmos3D.gd index c04b8daa3..e94f3a91c 100644 --- a/src/UI/Canvas/Gizmos3D.gd +++ b/src/UI/Canvas/Gizmos3D.gd @@ -185,7 +185,7 @@ func _draw() -> void: continue if object.selected: # Draw bounding box outline - draw_multiline(points, selected_color, 1.0) + draw_multiline(points, selected_color, 0.5) if object.applying_gizmos == Cel3DObject.Gizmos.X_ROT: draw_line(gizmos_origin, Global.canvas.current_pixel, Color.RED) continue @@ -224,7 +224,7 @@ func _draw() -> void: draw_char(font, proj_back_local_scale / CHAR_SCALE, "Z") draw_set_transform_matrix(Transform2D()) elif object.hovered: - draw_multiline(points, hovered_color, 1.0) + draw_multiline(points, hovered_color) func _resize_vector(v: Vector2, l: float) -> Vector2: