From 054daf997520c33ae603b763230361a1665b9119 Mon Sep 17 00:00:00 2001 From: ruaridhg <32329546+ruaridhg@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:12:23 +0100 Subject: [PATCH 1/8] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a88cd22..0b92a64 100644 --- a/README.md +++ b/README.md @@ -78,3 +78,12 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s ## Contributions Please see [Dev Notes](./docs/Dev_notes.md) if you wish to contribute. Feel free to submit suggestions via issues and/or PRs. + + + ## Authors + +[Tom Dowrick](https://github.com/tdowrick) +[Ruaridh Gollifer](https://github.com/ruaridhg) +[Sofía Miñano](https://github.com/sfmig) +[Harvey Mannering](https://github.com/harveymannering) + From 3fe8b7404ec64a7eb2ccd69e59d59bed66add6cd Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 14:51:47 +0100 Subject: [PATCH 2/8] Added authors, fixed define_prop poll and UD props saved params --- README.md | 3 +- randomisation_seed.sh | 2 +- randomiser/define_prop/ui.py | 97 ++++++++++----------- randomiser/random_all/operators.py | 133 +++++++++++++++++++++++++++-- 4 files changed, 177 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 0b92a64..03c8360 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,10 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s Please see [Dev Notes](./docs/Dev_notes.md) if you wish to contribute. Feel free to submit suggestions via issues and/or PRs. - + ## Authors [Tom Dowrick](https://github.com/tdowrick) [Ruaridh Gollifer](https://github.com/ruaridhg) [Sofía Miñano](https://github.com/sfmig) [Harvey Mannering](https://github.com/harveymannering) - diff --git a/randomisation_seed.sh b/randomisation_seed.sh index b57bec0..1327c2d 100644 --- a/randomisation_seed.sh +++ b/randomisation_seed.sh @@ -3,4 +3,4 @@ source ~/.bash_profile # zip randomiser, launch blender and install+enable, set seed and input bounds zip randomiser.zip -FS -r randomiser/ -blender random_all.blend --python install_and_enable_addons.py -- ./randomiser.zip --seed 32 --input ./input_bounds.json --output ./output_randomisations_per_frame1697116725.310647.json +blender define_prop.blend --python install_and_enable_addons.py -- ./randomiser.zip --seed 32 --input ./input_bounds.json --output ./output_randomisations_per_frame1697116725.310647.json diff --git a/randomiser/define_prop/ui.py b/randomiser/define_prop/ui.py index 37adaae..ca7d196 100644 --- a/randomiser/define_prop/ui.py +++ b/randomiser/define_prop/ui.py @@ -192,7 +192,6 @@ def get_attr_only_str(full_str): len_path = len(full_str.rsplit(".", config.MAX_NUMBER_OF_SUBPANELS)) - mod list_parent_nodes_str = full_str.rsplit(".", len_path - 3) attribute_only_str = full_str.replace(list_parent_nodes_str[0] + ".", "") - return attribute_only_str @@ -395,13 +394,13 @@ def poll(cls, context): if "Camera" in current_obj: action = attr_get_type( bpy.data.cameras[idx], - get_attr_only_str(attribute_only_str), + attribute_only_str, )[1] else: action = attr_get_type( bpy.data.objects[idx], - get_attr_only_str(attribute_only_str), + attribute_only_str, )[1] elif "bpy.context.scene" in full_str: @@ -455,51 +454,53 @@ def draw(self, context): full_str = sockets_props_collection.name attribute_only_str = get_attr_only_str(full_str) - list_all_UD_props = [] - for UD_str in bpy.context.scene.custom: - objects_in_scene = [] - for key in bpy.data.objects: - objects_in_scene.append(key.name) - - if "[" in UD_str.name: - obj_str = get_obj_str(UD_str.name) - - for i, obj in enumerate(objects_in_scene): - if obj in obj_str: - current_obj = obj - idx = i - - if "Camera" in current_obj: - if ( - attr_get_type( - bpy.data.cameras[idx], - get_attr_only_str(UD_str.name), - )[1] - != "dummy" - ): - list_all_UD_props.append(UD_str) - - else: - if ( - attr_get_type( - bpy.data.objects[idx], - get_attr_only_str(UD_str.name), - )[1] - != "dummy" - ): - list_all_UD_props.append(UD_str) - - elif ( - attr_get_type( - bpy.context.scene, get_attr_only_str(UD_str.name) - )[1] - != "dummy" - ): - list_all_UD_props.append(UD_str) - - list_current_UD_props = list_all_UD_props[ - bpy.context.scene.custom_index - ].name + # list_all_UD_props = [] + # for UD_str in bpy.context.scene.custom: + # objects_in_scene = [] + # for key in bpy.data.objects: + # objects_in_scene.append(key.name) + + # if "[" in UD_str.name: + # obj_str = get_obj_str(UD_str.name) + + # for i, obj in enumerate(objects_in_scene): + # if obj in obj_str: + # current_obj = obj + # idx = i + + # if "Camera" in current_obj: + # if ( + # attr_get_type( + # bpy.data.cameras[idx], + # get_attr_only_str(UD_str.name), + # )[1] + # != "dummy" + # ): + # list_all_UD_props.append(UD_str) + + # else: + # if ( + # attr_get_type( + # bpy.data.objects[idx], + # get_attr_only_str(UD_str.name), + # )[1] + # != "dummy" + # ): + # list_all_UD_props.append(UD_str) + + # elif ( + # attr_get_type( + # bpy.context.scene, get_attr_only_str(UD_str.name) + # )[1] + # != "dummy" + # ): + # list_all_UD_props.append(UD_str) + + # list_current_UD_props = list_all_UD_props[ + # bpy.context.scene.custom_index + # ].name + + list_current_UD_props = sockets_props_collection.name # Draw UD props to randomise including their # min/max boundaries diff --git a/randomiser/random_all/operators.py b/randomiser/random_all/operators.py index 3312274..8615c84 100644 --- a/randomiser/random_all/operators.py +++ b/randomiser/random_all/operators.py @@ -6,6 +6,7 @@ import numpy as np from bpy.app.handlers import persistent +from ..define_prop.ui import attr_get_type, get_attr_only_str, get_obj_str from ..transform.operators import get_transform_inputs, randomise_selected from ..utils import nodes2rand @@ -308,6 +309,121 @@ def execute(self, context): MAT_sck_values_str = "Values " + MAT_sck_values_str all_mat_dict[MAT_sck_values_str] = tmp_values + ### UD props + bpy.data.scenes["Scene"].frame_current = 0 + + all_UD_props_dict = {} + cs = bpy.context.scene + + list_subpanel_UD_props_names = [ + UD.name for UD in cs.socket_props_per_UD.collection + ] + # for every UD prop: save name of UD prop + sockets_to_randomise_per_UD = [] + for UD_str in list_subpanel_UD_props_names: + sckt = cs.socket_props_per_UD.collection[UD_str].name + if cs.socket_props_per_UD.collection[UD_str].bool_randomise: + sockets_to_randomise_per_UD.append(sckt) + + for UD_str in sockets_to_randomise_per_UD: + # get collection of socket properties for this UD prop + # NOTE: socket properties do not include the actual socket object + sockets_props_collection = cs.socket_props_per_UD.collection[ + UD_str + ] + # for UD_idx in range(len(sockets_to_randomise_per_UD)): + # # get this subpanel's GNG + # subpanel_UD = cs.socket_props_per_UD.collection[UD_idx] + # tmp_GNG = subpanel_UD.name + + # sockets_props_collection = cs.socket_props_per_UD.collection[ + # subpanel_UD.name + # ] + + full_str = sockets_props_collection.name + attribute_only_str = get_attr_only_str(full_str) + + list_all_UD_props = [] + list_all_attr_str = [] + + objects_in_scene = [] + for key in bpy.data.objects: + objects_in_scene.append(key.name) + + if "[" in full_str: + obj_str = get_obj_str(full_str) + + for i, obj in enumerate(objects_in_scene): + if obj in obj_str: + current_obj = obj + idx = i + + if "Camera" in current_obj: + if ( + attr_get_type( + bpy.data.cameras[idx], + get_attr_only_str(full_str), + )[1] + != "dummy" + ): + list_all_UD_props.append(full_str) + list_all_attr_str.append(attribute_only_str) + + else: + if ( + attr_get_type( + bpy.data.objects[idx], + get_attr_only_str(full_str), + )[1] + != "dummy" + ): + list_all_UD_props.append(full_str) + list_all_attr_str.append(attribute_only_str) + + elif ( + attr_get_type(bpy.context.scene, get_attr_only_str(full_str))[ + 1 + ] + != "dummy" + ): + list_all_UD_props.append(full_str) + list_all_attr_str.append(attribute_only_str) + + list_UD_props_sorted = list_all_UD_props + for i_n, nd in enumerate(list_UD_props_sorted): + tmp_values = [] + for frm in range(tot_frame_no): + bpy.app.handlers.frame_change_pre[0]("dummy") + bpy.data.scenes["Scene"].frame_current = frm + bpy.ops.node.randomise_all_ud_sockets("INVOKE_DEFAULT") + + if "[" in nd: + if "Camera" in nd: + tmp_values.append( + attr_get_type( + bpy.data.cameras[idx], + list_all_attr_str[i_n], + )[1] + ) + + else: + tmp_values.append( + attr_get_type( + bpy.data.objects[idx], + list_all_attr_str[i_n], + )[1] + ) + + elif "bpy.context.scene" in nd: + tmp_values.append( + attr_get_type( + bpy.context.scene, + list_all_attr_str[i_n], + )[1] + ) + + all_UD_props_dict[nd] = tmp_values + data = { "location_str": loc_value_str, "loc_x": x_pos_vals, @@ -319,6 +435,7 @@ def execute(self, context): "rot_z": z_rot_vals, "geometry": all_geom_dict, "materials": all_mat_dict, + "user_defined_props": all_UD_props_dict, } ct = datetime.datetime.now() @@ -329,13 +446,15 @@ def execute(self, context): path_to_file = path_to_file + file_ext with open(path_to_file, "w") as out_file_obj: - # convert the dictionary into text - text = json.dumps(data, indent=4) - # write the text into the file - out_file_obj.write(text) - - print("Outputs parameters saved to file: ", path_to_file) - print("Total number of frames saved = ", tot_frame_no) + try: + # convert the dictionary into text + text = json.dumps(data, indent=4) + # write the text into the file + out_file_obj.write(text) + print("Outputs parameters saved to file: ", path_to_file) + print("Total number of frames saved = ", tot_frame_no) + except Exception: + print("Cannot save parameters to file") return {"FINISHED"} From 46c376e355bbe893b2c4e4d48ef8c68aa4977437 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 15:36:53 +0100 Subject: [PATCH 3/8] Added bool rand for camera transforms and no file saved if json error --- randomiser/define_prop/operators.py | 10 +-- randomiser/random_all/operators.py | 111 ++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/randomiser/define_prop/operators.py b/randomiser/define_prop/operators.py index 894325d..1d96498 100644 --- a/randomiser/define_prop/operators.py +++ b/randomiser/define_prop/operators.py @@ -29,21 +29,21 @@ def attr_set_val(obj, path, min_val, max_val, UD_type): # print("Property does not exist") pass - print("obj = ", path_attr) + # print("obj = ", path_attr) if UD_type == float: value = random.uniform(min_val, max_val) - print("1D float = ", value) + # print("1D float = ", value) elif UD_type == Vector: value = random.uniform(min_val, max_val) - print("3D Vector float = ", value) + # print("3D Vector float = ", value) elif UD_type == Euler: deg2rad = np.pi / 180 value = random.uniform(min_val, max_val) value = value * deg2rad - print("Euler = ", value) + # print("Euler = ", value) else: value = random.randint(min_val, max_val) - print("Integer = ", value) + # print("Integer = ", value) setattr(prop, path_attr, value) diff --git a/randomiser/random_all/operators.py b/randomiser/random_all/operators.py index 8615c84..3315842 100644 --- a/randomiser/random_all/operators.py +++ b/randomiser/random_all/operators.py @@ -147,6 +147,24 @@ def execute(self, context): ### TRANSFORMS bpy.data.scenes["Scene"].frame_current = 0 + ( + loc, + loc_x_range, + loc_y_range, + loc_z_range, + rot, + rot_x_range, + rot_y_range, + rot_z_range, + delta_on, + rand_posx, + rand_posy, + rand_posz, + rand_rotx, + rand_roty, + rand_rotz, + ) = get_transform_inputs(context) + x_pos_vals = [] y_pos_vals = [] z_pos_vals = [] @@ -163,29 +181,56 @@ def execute(self, context): value_str = "rotation_euler" rad2deg = 180 / np.pi + if rand_posx: + print("bool on") + all_transform_dict = {} + tmp_values_loc = {} + tmp_values_rot = {} for idx in range(tot_frame_no): bpy.app.handlers.frame_change_pre[0]("dummy") bpy.data.scenes["Scene"].frame_current = idx - x_pos_vals.append( - getattr(bpy.context.scene.camera, loc_value_str)[0] - ) - y_pos_vals.append( - getattr(bpy.context.scene.camera, loc_value_str)[1] - ) - z_pos_vals.append( - getattr(bpy.context.scene.camera, loc_value_str)[2] - ) + if rand_posx: + x_pos_vals.append( + getattr(bpy.context.scene.camera, loc_value_str)[0] + ) + tmp_values_loc["x_pos_vals"] = x_pos_vals - x_rot_vals.append( - getattr(bpy.context.scene.camera, value_str)[0] * rad2deg - ) - y_rot_vals.append( - getattr(bpy.context.scene.camera, value_str)[1] * rad2deg - ) - z_rot_vals.append( - getattr(bpy.context.scene.camera, value_str)[2] * rad2deg - ) + if rand_posy: + y_pos_vals.append( + getattr(bpy.context.scene.camera, loc_value_str)[1] + ) + tmp_values_loc["y_pos_vals"] = y_pos_vals + + if rand_posz: + z_pos_vals.append( + getattr(bpy.context.scene.camera, loc_value_str)[2] + ) + tmp_values_loc["z_pos_vals"] = z_pos_vals + + if rand_rotx: + x_rot_vals.append( + getattr(bpy.context.scene.camera, value_str)[0] * rad2deg + ) + tmp_values_rot["x_rot_vals"] = x_rot_vals + + if rand_roty: + y_rot_vals.append( + getattr(bpy.context.scene.camera, value_str)[1] * rad2deg + ) + tmp_values_rot["y_rot_vals"] = y_rot_vals + + if rand_rotz: + z_rot_vals.append( + getattr(bpy.context.scene.camera, value_str)[2] * rad2deg + ) + tmp_values_rot["z_rot_vals"] = z_rot_vals + + if tmp_values_loc: + all_transform_dict[loc_value_str] = tmp_values_loc + + if tmp_values_rot: + all_transform_dict[value_str] = tmp_values_rot ### GEOMETRY bpy.data.scenes["Scene"].frame_current = 0 @@ -286,6 +331,7 @@ def execute(self, context): ) # issue # w/ this being called so often - # might need moved to diff for loop? + tmp_values.append( getattr( sckt, @@ -425,14 +471,15 @@ def execute(self, context): all_UD_props_dict[nd] = tmp_values data = { - "location_str": loc_value_str, - "loc_x": x_pos_vals, - "loc_y": y_pos_vals, - "loc_z": z_pos_vals, - "rotation_str": value_str, - "rot_x": x_rot_vals, - "rot_y": y_rot_vals, - "rot_z": z_rot_vals, + # "location_str": loc_value_str, + # "loc_x": x_pos_vals, + # "loc_y": y_pos_vals, + # "loc_z": z_pos_vals, + # "rotation_str": value_str, + # "rot_x": x_rot_vals, + # "rot_y": y_rot_vals, + # "rot_z": z_rot_vals, + "camera_transforms": all_transform_dict, "geometry": all_geom_dict, "materials": all_mat_dict, "user_defined_props": all_UD_props_dict, @@ -445,16 +492,16 @@ def execute(self, context): path_to_file = "output_randomisations_per_frame" + ts_str path_to_file = path_to_file + file_ext - with open(path_to_file, "w") as out_file_obj: - try: - # convert the dictionary into text - text = json.dumps(data, indent=4) + try: + # convert the dictionary into text + text = json.dumps(data, indent=4) + with open(path_to_file, "w") as out_file_obj: # write the text into the file out_file_obj.write(text) print("Outputs parameters saved to file: ", path_to_file) print("Total number of frames saved = ", tot_frame_no) - except Exception: - print("Cannot save parameters to file") + except Exception: + print("Cannot save parameters to file") return {"FINISHED"} From 20767998d62e349d82abea530273b750824c7dbd Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 16:23:33 +0100 Subject: [PATCH 4/8] Randomisation_seed.sh uses sample.blend --- randomisation_seed.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/randomisation_seed.sh b/randomisation_seed.sh index 1327c2d..697d531 100644 --- a/randomisation_seed.sh +++ b/randomisation_seed.sh @@ -3,4 +3,4 @@ source ~/.bash_profile # zip randomiser, launch blender and install+enable, set seed and input bounds zip randomiser.zip -FS -r randomiser/ -blender define_prop.blend --python install_and_enable_addons.py -- ./randomiser.zip --seed 32 --input ./input_bounds.json --output ./output_randomisations_per_frame1697116725.310647.json +blender sample.blend --python install_and_enable_addons.py -- ./randomiser.zip --seed 32 --input ./input_bounds.json --output ./output_randomisations_per_frame1697116725.310647.json From f0df3f3b331c7410355e330875c0694188226c96 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 16:23:57 +0100 Subject: [PATCH 5/8] Added oustanding issues to contributions section of README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 03c8360..11535c7 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,13 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s Please see [Dev Notes](./docs/Dev_notes.md) if you wish to contribute. Feel free to submit suggestions via issues and/or PRs. + There are a few outstanding issues for enhancements: + - Not able to currently export materials colour default value for save params button + - Materials colour min-max can only be set to the same values in the 4D matrix using the [input file](/input_bounds.json) + - No functionality for reading in min-max input boundaries for user defined panel + - Not able to currently handle an empty UIlist in the user defined panel which causes issues for other funtionality in the add-on (which are resolved by adding at least one UD prop to UIlist) + - General refactoring for repeated code + ## Authors From 869036b0dc3d05b2249bec9c815cab9819b54dab Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 16:36:28 +0100 Subject: [PATCH 6/8] Updated README for outstanding issues and start of refactoring solution --- README.md | 3 +- randomiser/utils/list_props_to_randomise.py | 114 ++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 randomiser/utils/list_props_to_randomise.py diff --git a/README.md b/README.md index 11535c7..62cc5f0 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,8 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s - Materials colour min-max can only be set to the same values in the 4D matrix using the [input file](/input_bounds.json) - No functionality for reading in min-max input boundaries for user defined panel - Not able to currently handle an empty UIlist in the user defined panel which causes issues for other funtionality in the add-on (which are resolved by adding at least one UD prop to UIlist) - - General refactoring for repeated code + - Can randomise all panels and save the output parameters, however the functionality to toggle on/off selection of individual parameters is only available for camera transforms and user defined properties currently, but not geometry and materials panels where all these properties will be randomised and exported when this functionality is used. + - General refactoring for repeated code for example [for the geometry and materials issue mentioned above](/randomiser/utils/list_props_to_randomise.py) ## Authors diff --git a/randomiser/utils/list_props_to_randomise.py b/randomiser/utils/list_props_to_randomise.py new file mode 100644 index 0000000..320aff1 --- /dev/null +++ b/randomiser/utils/list_props_to_randomise.py @@ -0,0 +1,114 @@ +import bpy + + +def mat_list_to_rand(cs): + list_subpanel_material_names = [ + mat.name + for mat in cs.socket_props_per_material.collection + # for mat in cs.socket_props_per_material.candidate_materials + ] + + # for every material: save sockets to randomise + sockets_to_randomise_per_material = {} + for mat_str in list_subpanel_material_names: + # get collection of socket properties for this material + # ATT socket properties do not include the actual socket object + if cs.socket_props_per_material.collection[ + mat_str + ].update_sockets_collection: + print("Collection of material sockets updated") + + sockets_props_collection = cs.socket_props_per_material.collection[ + mat_str + ].collection + + # get candidate sockets for this material + candidate_sockets = cs.socket_props_per_material.collection[ + mat_str + ].candidate_sockets + + # if socket unlinked and randomisation toggle is True: + # modify socket props to set toggle to False + sockets_to_randomise_per_material[mat_str] = [] + for sckt in candidate_sockets: + # get socket identifier sting + sckt_id = sckt.node.name + "_" + sckt.name + if sckt.node.id_data.name in bpy.data.node_groups: + sckt_id = sckt.node.id_data.name + "_" + sckt_id + + # if this socket is selected to randomise but it is unlinked: + # set randomisation toggle to False + if (not sckt.is_linked) and ( + sockets_props_collection[sckt_id].bool_randomise + ): + setattr( + sockets_props_collection[sckt_id], + "bool_randomise", + False, + ) + print( + f"Socket {sckt_id} from {mat_str} is unlinked:", + "randomisation toggle set to False", + ) + + # after modifying randomisation toggle + # save list of sockets to randomise to dict, + # with key = material + if sockets_props_collection[sckt_id].bool_randomise: + sockets_to_randomise_per_material[mat_str].append(sckt) + + return list_subpanel_material_names, sockets_to_randomise_per_material + + +def geom_list_to_rand(cs): + list_subpanel_gng_names = [ + gng.name for gng in cs.socket_props_per_gng.collection + ] + # for every GNG: save sockets to randomise + sockets_to_randomise_per_gng = {} + for gng_str in list_subpanel_gng_names: + # get collection of socket properties for this GNG + # ATT socket properties do not include the actual socket object + if cs.socket_props_per_gng.collection[ + gng_str + ].update_sockets_collection: + print("Collection of geometry sockets updated") + + sockets_props_collection = cs.socket_props_per_gng.collection[ + gng_str + ].collection + + # get candidate sockets for this GNG + candidate_sockets = cs.socket_props_per_gng.collection[ + gng_str + ].candidate_sockets + + # if socket unlinked and randomisation toggle is True: + # modify socket props to set toggle to False + sockets_to_randomise_per_gng[gng_str] = [] + for sckt in candidate_sockets: + # get socket identifier string + sckt_id = sckt.node.name + "_" + sckt.name + + # if this socket is selected to randomise but it is unlinked: + # set randomisation toggle to False + if (not sckt.is_linked) and ( + sockets_props_collection[sckt_id].bool_randomise + ): + setattr( + sockets_props_collection[sckt_id], + "bool_randomise", + False, + ) + print( + f"Socket {sckt_id} from {gng_str} is unlinked:", + "randomisation toggle set to False", + ) + + # after modifying randomisation toggle + # save list of sockets to randomise to dict, + # with key = material + if sockets_props_collection[sckt_id].bool_randomise: + sockets_to_randomise_per_gng[gng_str].append(sckt) + + return sockets_to_randomise_per_gng From d6fd9ae1a941310caccd9ea51630b429d35083e2 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 16:37:38 +0100 Subject: [PATCH 7/8] Authors list formatting --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 62cc5f0..22c7f7e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,9 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s ## Authors [Tom Dowrick](https://github.com/tdowrick) + [Ruaridh Gollifer](https://github.com/ruaridhg) + [Sofía Miñano](https://github.com/sfmig) + [Harvey Mannering](https://github.com/harveymannering) From 791f8fa6334f155641b381a9f6946ae27194c488 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Fri, 20 Oct 2023 17:26:20 +0100 Subject: [PATCH 8/8] Added screenshots of add-on panels to docs --- README.md | 10 +++++++++- docs/Materials_geometry_panel.md | 15 ++++++++++++++- docs/user_defined_panel.md | 6 ++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 22c7f7e..a4f6f0f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Blender Randomiser is a Blender add-on that allows different scene properties to ## Purpose The add-on was originally developed to render a highly diverse and (near) photo-realistic synthetic dataset of laparoscopic surgery camera views. To replicate the different camera positions used in surgery as well as the shape and appearance of the tissues involved with surgery, we focused on three main components to randomise: - - **Camera transforms** (location and Euler rotation with toggle for randomising in absolute or relative i.e. delta terms) + - **Camera transforms** (location and Euler rotation with toggle for randomising in absolute or relative i.e. delta terms) ![camera_transforms](/docs/images/Transforms_panel.png) - **Geometry** ([see further details](/docs/Materials_geometry_panel.md)) - **Materials**([see further details](/docs/Materials_geometry_panel.md)) @@ -22,6 +22,9 @@ In the add-on, these three components appear as separate UI panels. - Capability to randomise the desired properties at every frame of an animation - [Save Parameter panel](/docs/input_output.md) with outputs saved to `.json` [file](/output_randomisations_per_frame1697116725.310647.json) with a timestamp + The add-on panel called "Randomiser" is located in the Geometry Nodes tab on Blender: + ![Addon_location](/docs/images/Addon_location.png) + ## Installation via command line 1. First, clone the repository in your desired directory @@ -37,6 +40,9 @@ git clone https://github.com/UCL/Blender_Randomiser.git - This will zip the `randomiser` subdirectory, open the `sample.blend` file with Blender, and use Blender's Python interpreter to execute the `install_and_enable_addons.py` script. - The `install_and_enable_addons.py` script installs and enables any add-ons that are passed as command line arguments (add-ons can be passed as a path to a single Python file, or as a zip file) +> [!NOTE] `source ~/.bash_profile` is used in the bash script to create an alias for blender with the following line in the bash_profile: +> `alias blender=/Applications/Blender.app/Contents/MacOS/Blender` + > **Advanced Usage** > In step 3, run the [randomisation_seed.sh](/randomisation_seed.sh) bash script instead which has optional inputs: > - `--seed 32` which is an input to Blender @@ -79,6 +85,8 @@ Alternatively, install [manually](/docs/Install_addon_manually.md) via Blender s Please see [Dev Notes](./docs/Dev_notes.md) if you wish to contribute. Feel free to submit suggestions via issues and/or PRs. + It can be helpful to use different `.blend` files for prototyping as it can preload certain features you're testing. + There are a few outstanding issues for enhancements: - Not able to currently export materials colour default value for save params button - Materials colour min-max can only be set to the same values in the 4D matrix using the [input file](/input_bounds.json) diff --git a/docs/Materials_geometry_panel.md b/docs/Materials_geometry_panel.md index 93c949a..6dfd0f9 100644 --- a/docs/Materials_geometry_panel.md +++ b/docs/Materials_geometry_panel.md @@ -1,4 +1,5 @@ ## Materials +![Materials_panel](/docs/images/Materials_panel.png) - A panel to randomise properties relative to the material nodes: - nodes and node groups are aggregated based on the material they belong to. - only materials with use_nodes=True are added to the panel. By default, use_nodes is set to True, but this is a convenient way to add/remove materials from the panel. @@ -10,12 +11,24 @@ Clicking the name of the material in a subpanel header shows its node graph. If a material is clicked and it has no slot assigned, a new slot will be created for it - ## Geometry +![Geometry_panel](/docs/images/Geometry_panel.png) + - A panel to randomise properties relative to the geometry nodes: - nodes are aggregated based on the node group they belong to. - Same functionalities as in material nodes panel: new or deleted nodes are automatically added, recursive node groups are accepted,etc. +An example of a cube object: +![Geometry_cube_example](/docs/images/Geometry_cube_example.png) + +An example of a sphere object with recursive node groups: +![Geometry_sphere_recursive_example](/docs/images/Geometry_SPHERE_node_group_within_node_group.png) + +>[!NOTE] +> Only the geometry linked to the current active selective object is visible via the node graph view + ### When is a new modifier automatically added to an object’s geometry? If a geometry node group is not inside another node group, and is not linked to a modifier of the currently active object, a new modifier is created and the geometry node group is linked to it. + +This example panel set-up for geometry and materials can produce an [output_file](/output_randomisations_per_frame1697817956.010714_mat_geom_example.json) diff --git a/docs/user_defined_panel.md b/docs/user_defined_panel.md index 6d72e3b..1822735 100644 --- a/docs/user_defined_panel.md +++ b/docs/user_defined_panel.md @@ -1,3 +1,9 @@ +## User Defined Properties Panel + +![UD_props_panel](/docs/images/UD_panel.png) + +This example panel set-up can produce an [output_file](/output_randomisations_per_frame1697817657.502794_UD_example.json) + Some examples of useful user-defined properties could be: - bpy.data.objects["Cube"].location (Float 3D) - bpy.context.scene.frame_current (int 1D)