diff --git a/blends/Makefile b/blends/Makefile new file mode 100644 index 0000000..55113b6 --- /dev/null +++ b/blends/Makefile @@ -0,0 +1,10 @@ +BLEND_FILES = $(shell find -type f -name '*.blend') +GLB_TARGETS = $(patsubst %.blend, ../godot/%.glb, $(BLEND_FILES)) + +all: ${GLB_TARGETS} + + +# --factory-startup disables addons (My custom addons are buggy and crash lots) +../godot/%.glb: %.blend + mkdir -p $(shell dirname $@) + blender -b --factory-startup $< --python-text export.py --export-path $@ diff --git a/blends/README.md b/blends/README.md new file mode 100644 index 0000000..f051e76 --- /dev/null +++ b/blends/README.md @@ -0,0 +1,10 @@ +# Automating exports +each blend file has a text block named "export.py" which is usually just the file in this directory +## Exporting from the Blender +- Create a new text block by opening "export.py" Make sure to relativize the path by clicking "File>>External Data>>Make paths relative" +Right now the script depends on the location of the script to find the root of the blends folder so it will not work if the export.py text block is internal +- Create a collection named "export" and move the objects to be exported inside +- Run the script inside Blender +## Exporting from CLI +- Save the blend file with a export collection as above +- Run `make` \ No newline at end of file diff --git a/blends/export.py b/blends/export.py new file mode 100644 index 0000000..72bfbc0 --- /dev/null +++ b/blends/export.py @@ -0,0 +1,44 @@ +import bpy +from sys import argv +from pathlib import Path + +blends_folder = (Path(bpy.path.abspath(bpy.data.texts["export.py"].filepath))/"..").resolve() +blend_path = Path(bpy.path.abspath(bpy.context.blend_data.filepath)).relative_to(blends_folder) +godot_folder = (Path(bpy.path.abspath(bpy.data.texts["export.py"].filepath))/".."/".."/"godot").resolve() +export_file = str((godot_folder/blend_path).resolve()).replace(".blend", ".glb") + +def export(path: str): + bpy.ops.object.mode_set(mode="OBJECT") + bpy.context.view_layer.update() + # Clear the selection + for target in bpy.context.selected_objects: + target.select_set(False) + collection = bpy.data.collections["export"] + for target in collection.objects: + target.select_set(True) + bpy.context.view_layer.update() + bpy.ops.export_scene.gltf( + filepath=path, + export_format="GLB", + use_selection=True, + export_colors=False, + export_apply=True, + export_animation_mode="NLA_TRACKS", + export_anim_slide_to_zero=True, + ) + +try: + i = next((i for i, arg in enumerate(argv) if arg == "--export-path"), None) + if i is None: + path = export_file + else: + path = str(Path(argv[i+1]).resolve()) + export(path) + print("Export successful") + if bpy.app.background: + quit(0) +except SystemExit as e: + quit(e.code) +except: + import traceback + traceback.print_exc() diff --git a/blends/small_room.blend b/blends/small_room.blend new file mode 100644 index 0000000..b830aaf --- /dev/null +++ b/blends/small_room.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7ca326bee07aee490ffc0c13074af5848a16afe08f0d933354b25181fef8eb2 +size 959896 diff --git a/blends/small_room.blend1 b/blends/small_room.blend1 new file mode 100644 index 0000000..36d92e6 Binary files /dev/null and b/blends/small_room.blend1 differ diff --git a/godot/control_scheme/control_target_overlay.material b/godot/control_scheme/control_target_overlay.material new file mode 100644 index 0000000..fcdc96e --- /dev/null +++ b/godot/control_scheme/control_target_overlay.material @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83a5adc4b833fc7a42cad6a04f5b3d502ca33fc2c0545d350f546aa998cb8117 +size 175 diff --git a/godot/control_scheme/controller.gd b/godot/control_scheme/controller.gd new file mode 100644 index 0000000..bcf102e --- /dev/null +++ b/godot/control_scheme/controller.gd @@ -0,0 +1,63 @@ +extends Node3D + +@export var camera: Camera3D +@export var target: Node3D +@export var sensitivity := 0.01 + +func _input(event): + if event is InputEventMouseMotion: + rotate_view(event.relative*sensitivity) + +func _process(_delta): + transform.origin = target.global_position + camera.global_position = %camera_spot.global_position + camera.look_at(target.global_position) + +func rotate_view(amount: Vector2): + rotate_y(-amount.x) + %rotate_helper.rotate_z(amount.y) + %rotate_helper.rotation_degrees.z = clampf(%rotate_helper.rotation_degrees.z, -77, 77) + +func set_target(node: Node3D, should_unset=true): + if target != null and should_unset: + pass + +var old_material_props = null + +func change_material(mesh: MeshInstance3D): + if old_material_props != null: + push_error("UH OOH!!! 628") + old_material_props = [] + for i in range(mesh.get_surface_override_material_count()): + var mat := mesh.get_active_material(i) + if mat is BaseMaterial3D: + old_material_props.append(mat.depth_draw_mode) + mat.depth_draw_mode = BaseMaterial3D.DEPTH_DRAW_DISABLED + push_next_pass(mat, preload("control_target_overlay.material")) + else: + old_material_props.append(null) + push_error("Don't know how to handle shader material for", mesh) + +func unchange_material(mesh: MeshInstance3D): + if old_material_props == null: + push_error("UH OOH!!! 629") + for i in range(mesh.get_surface_override_material_count()): + var mat := mesh.get_active_material(i) + if mat is BaseMaterial3D: + mat.depth_draw_mode = old_material_props[i] + pop_next_pass(mat) + else: + push_error("Don't know how to handle shader material for", mesh) + +func push_next_pass(m: Material, with: Material): + if m.next_pass != null: + push_next_pass(m.next_pass, with) + else: + m.next_pass = with + +func pop_next_pass(m: Material): + if m == null: + return true + if pop_next_pass(m.next_pass): + m.next_pass = null + return false diff --git a/godot/control_scheme/controller.tscn b/godot/control_scheme/controller.tscn new file mode 100644 index 0000000..6c16385 --- /dev/null +++ b/godot/control_scheme/controller.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3 uid="uid://drmb4sitb74fx"] + +[ext_resource type="Script" path="res://control_scheme/controller.gd" id="1_h3pjb"] + +[node name="controller" type="Node3D"] +top_level = true +script = ExtResource("1_h3pjb") + +[node name="rotate_helper" type="Node3D" parent="."] +unique_name_in_owner = true + +[node name="camera_spot" type="Marker3D" parent="rotate_helper"] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0) diff --git a/godot/controller_event_bus.gd b/godot/controller_event_bus.gd new file mode 100644 index 0000000..487b284 --- /dev/null +++ b/godot/controller_event_bus.gd @@ -0,0 +1,2 @@ +extends Node + diff --git a/godot/project.godot b/godot/project.godot index 0cf4eb4..489a5ff 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -14,6 +14,14 @@ config/name="Hurrmmm" config/features=PackedStringArray("4.1", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +ControllerEventBus="*res://controller_event_bus.gd" + [dotnet] project/assembly_name="Hurrmmm" + +[filesystem] + +import/blender/enabled=false diff --git a/godot/small_room.glb b/godot/small_room.glb new file mode 100644 index 0000000..ba1e75e --- /dev/null +++ b/godot/small_room.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa4ad5b52dd06febea07af3f68b655f620cd3356345bd41e8de28925bda52962 +size 13732 diff --git a/godot/small_room.glb.import b/godot/small_room.glb.import new file mode 100644 index 0000000..281f679 --- /dev/null +++ b/godot/small_room.glb.import @@ -0,0 +1,32 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bua7f25rpewkp" +path="res://.godot/imported/small_room.glb-40e857318362384b2412bafcaef8b669.scn" + +[deps] + +source_file="res://small_room.glb" +dest_files=["res://.godot/imported/small_room.glb-40e857318362384b2412bafcaef8b669.scn"] + +[params] + +nodes/root_type="Node3D" +nodes/root_name="Scene Root" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +import_script/path="" +_subresources={} +gltf/embedded_image_handling=1 diff --git a/godot/tests/control_scheme/test_basic_controls.tscn b/godot/tests/control_scheme/test_basic_controls.tscn new file mode 100644 index 0000000..0d5bc9e --- /dev/null +++ b/godot/tests/control_scheme/test_basic_controls.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=3 uid="uid://70bb2yncbl"] + +[ext_resource type="PackedScene" uid="uid://bua7f25rpewkp" path="res://small_room.glb" id="1_2ticn"] +[ext_resource type="PackedScene" uid="uid://drmb4sitb74fx" path="res://control_scheme/controller.tscn" id="2_dcvuq"] + +[sub_resource type="Environment" id="Environment_f0m14"] +ambient_light_source = 2 +ambient_light_color = Color(1, 1, 1, 1) +ambient_light_energy = 0.5 + +[node name="small_room" instance=ExtResource("1_2ticn")] + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." index="3"] +environment = SubResource("Environment_f0m14") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="WorldEnvironment" index="0"] +transform = Transform3D(1, 0, 0, 0, 0.933762, 0.357895, 0, -0.357895, 0.933762, 0, 1.43864, 1.81738) + +[node name="controller" parent="." index="4" node_paths=PackedStringArray("camera", "target") instance=ExtResource("2_dcvuq")] +camera = NodePath("Camera3D") +target = NodePath("../grape") + +[node name="Camera3D" type="Camera3D" parent="controller" index="1"]