Extracted grunkable logic to component & extended to physical props as well

This commit is contained in:
Rob Kelly 2025-07-03 18:05:06 -06:00
parent 9fe591d92a
commit d301ff277f
44 changed files with 860 additions and 161 deletions

View File

@ -2,7 +2,7 @@
[ext_resource type="ArrayMesh" uid="uid://cqd0a7ousx01n" path="res://assets/level/hallway/hallway_1.mesh" id="1_ckpmb"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="2_a8b6q"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="3_8umoc"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="3_8umoc"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="4_s4vba"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="5_n7a6q"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="6_hwbyh"]

View File

@ -17,7 +17,7 @@
[ext_resource type="Material" uid="uid://dt73a25l7h8if" path="res://levels/ghost_ship/guide_sign/crew_quarters_sign.material" id="15_ygcwo"]
[ext_resource type="ArrayMesh" uid="uid://b3f5p4o7qr1mf" path="res://assets/level/t-junction/t-junction_2.mesh" id="16_0fxnd"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="17_wqkax"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="18_ew4hm"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="18_ew4hm"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="19_0xbp3"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="20_wp8cq"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="21_opjmq"]

View File

@ -18,7 +18,7 @@
[ext_resource type="Texture2D" uid="uid://bmwmajwul60ti" path="res://assets/level/ceiling/ceiling_1_N.png" id="16_jbppi"]
[ext_resource type="Texture2D" uid="uid://8hav47a84uk" path="res://assets/level/ceiling/ceiling_1_R.png" id="17_ddwoq"]
[ext_resource type="ArrayMesh" uid="uid://d0sdsir1hqnbu" path="res://assets/level/wall/wall_4.mesh" id="18_rwb8f"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="19_hpoqx"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="19_hpoqx"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="20_77h2o"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="21_j4f2j"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="22_4q4f8"]

View File

@ -9,9 +9,9 @@
[ext_resource type="ArrayMesh" uid="uid://dkh2r61ydupb7" path="res://assets/level/floor/floor_2.mesh" id="7_bnexv"]
[ext_resource type="ArrayMesh" uid="uid://dbgk0kdg1vufk" path="res://assets/level/ceiling/ceiling_1.mesh" id="8_p5an5"]
[ext_resource type="PackedScene" uid="uid://oipf3w7hm5gf" path="res://src/props/operating_table/operating_table.tscn" id="9_1syyw"]
[ext_resource type="PackedScene" uid="uid://h2gswdcxyotk" path="res://src/props/med_cart/med_cart.tscn" id="10_loej8"]
[ext_resource type="PackedScene" uid="uid://h2gswdcxyotk" path="res://src/props/med_cart/static_med_cart.tscn" id="10_loej8"]
[ext_resource type="PackedScene" uid="uid://c8pkhw0b47xdd" path="res://src/props/cupboard/cupboard.tscn" id="11_5abrm"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="12_t0ymk"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="12_t0ymk"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="13_glbip"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="14_nqwfe"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="15_h56f5"]

View File

@ -13,7 +13,7 @@
[ext_resource type="Texture2D" uid="uid://dkilg200w8x4y" path="res://assets/props/vending_machine/vending_machine_M.png" id="11_ps4r1"]
[ext_resource type="Texture2D" uid="uid://8v7jta2qdvut" path="res://assets/props/vending_machine/vending_machine_N.png" id="12_iie7g"]
[ext_resource type="Texture2D" uid="uid://gbvtbiurxrop" path="res://assets/props/vending_machine/vending_machine_R.png" id="13_nvfj8"]
[ext_resource type="PackedScene" uid="uid://cklppdtyaadlo" path="res://src/props/trash_can/trash_can.tscn" id="14_3wo07"]
[ext_resource type="PackedScene" uid="uid://cklppdtyaadlo" path="res://src/props/trash_can/static_trash_can.tscn" id="14_3wo07"]
[ext_resource type="PackedScene" uid="uid://30o8ltnnxpxo" path="res://src/effects/floating_dust.tscn" id="15_87puh"]
[ext_resource type="PackedScene" uid="uid://d2feet02a603e" path="res://src/props/overhead_light/overhead_light.tscn" id="16_s0n7p"]
[ext_resource type="Texture2D" uid="uid://wqqwtmtmp147" path="res://assets/level/overhead_light_maskC.png" id="17_6lrbi"]

View File

@ -14,7 +14,7 @@
[ext_resource type="Texture2D" uid="uid://bgc8oqsnimb8i" path="res://assets/level/floor/floor_1_N.png" id="12_ukiad"]
[ext_resource type="Texture2D" uid="uid://23uupxc78b8n" path="res://assets/level/floor/floor_1_R.png" id="13_1vbec"]
[ext_resource type="PackedScene" uid="uid://ctm84yms40858" path="res://src/props/railing/railing.tscn" id="14_mspvt"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="15_5lcoj"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="15_5lcoj"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="16_bembv"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="17_8j8pa"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="18_ch7mi"]

View File

@ -4,7 +4,7 @@
[ext_resource type="PackedScene" uid="uid://ehf5sg3ahvbf" path="res://src/world/grunk_beast/grunk_beast.tscn" id="2_1lom2"]
[ext_resource type="ArrayMesh" uid="uid://cqd0a7ousx01n" path="res://assets/level/hallway/hallway_1.mesh" id="3_gyhlh"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="4_jj0u7"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="5_18csx"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="5_18csx"]
[ext_resource type="Texture2D" uid="uid://clofvb76pv6g" path="res://assets/red.png" id="5_jj0u7"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="6_e2fuu"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="7_hv7qb"]

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=16 format=3 uid="uid://c7us4smgk3487"]
[gd_scene load_steps=17 format=3 uid="uid://c7us4smgk3487"]
[ext_resource type="Script" uid="uid://68r4ht5ut1ct" path="res://src/game/level.gd" id="1_252gx"]
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="1_sumi4"]
[ext_resource type="ArrayMesh" uid="uid://dpr5cgq743f4s" path="res://assets/level/floor/floor_9x9.mesh" id="2_jjage"]
[ext_resource type="Script" uid="uid://040xta01xqxd" path="res://src/props/physics/holdable.gd" id="4_252gx"]
[ext_resource type="PackedScene" uid="uid://drm5dspi48pf5" path="res://src/props/crate_long/phys_crate_long.tscn" id="5_35l2h"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_hda7d"]
@ -164,3 +165,6 @@ shape = SubResource("SphereShape3D_hyy3g")
[node name="Holdable" type="Node" parent="Ball"]
script = ExtResource("4_252gx")
metadata/_custom_type_script = "uid://040xta01xqxd"
[node name="PhysCrateLong" parent="." instance=ExtResource("5_35l2h")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0.9, -6)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=40 format=3 uid="uid://dc4tts6342cuj"]
[gd_scene load_steps=43 format=3 uid="uid://dc4tts6342cuj"]
[ext_resource type="Script" uid="uid://dmbdkydqnbyqv" path="res://levels/prop_test/prop_test.gd" id="1_ibd1t"]
[ext_resource type="PackedScene" uid="uid://bwe2jdmvinhqd" path="res://src/player/player.tscn" id="1_ml0ka"]
@ -9,23 +9,26 @@
[ext_resource type="PackedScene" uid="uid://b6eg8t04rkh0c" path="res://src/props/wall_switch/wall_switch.tscn" id="5_y13lv"]
[ext_resource type="PackedScene" uid="uid://cvx5u0ttmri4q" path="res://src/props/sofa/sofa.tscn" id="6_kccq3"]
[ext_resource type="PackedScene" uid="uid://ca7b5gjl3ri0p" path="res://src/props/cafe_table/cafe_table.tscn" id="6_tm4v6"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/crate_long.tscn" id="7_4jlf1"]
[ext_resource type="PackedScene" uid="uid://cppd3scvxf3eg" path="res://src/props/crate_long/static_crate_long.tscn" id="7_4jlf1"]
[ext_resource type="PackedScene" uid="uid://bpsiwx1517pk1" path="res://src/props/tarp_crate/tarp_crate.tscn" id="7_xlkhi"]
[ext_resource type="PackedScene" uid="uid://drm5dspi48pf5" path="res://src/props/crate_long/phys_crate_long.tscn" id="8_8a67w"]
[ext_resource type="PackedScene" uid="uid://c8pkhw0b47xdd" path="res://src/props/cupboard/cupboard.tscn" id="8_kgrlx"]
[ext_resource type="PackedScene" uid="uid://dl6vekf0joac4" path="res://src/props/eva_suit/eva_suit.tscn" id="9_7md1e"]
[ext_resource type="PackedScene" uid="uid://b56sbxcwhveex" path="res://src/props/eva_suit/empty_enclosure.tscn" id="10_s7h0g"]
[ext_resource type="PackedScene" uid="uid://h2gswdcxyotk" path="res://src/props/med_cart/med_cart.tscn" id="11_s7h0g"]
[ext_resource type="PackedScene" uid="uid://h2gswdcxyotk" path="res://src/props/med_cart/static_med_cart.tscn" id="11_s7h0g"]
[ext_resource type="PackedScene" uid="uid://bve6iya13lhah" path="res://src/props/monitor/monitor.tscn" id="12_wyhm4"]
[ext_resource type="PackedScene" uid="uid://oipf3w7hm5gf" path="res://src/props/operating_table/operating_table.tscn" id="13_vp610"]
[ext_resource type="PackedScene" uid="uid://d2feet02a603e" path="res://src/props/overhead_light/overhead_light.tscn" id="14_sbwfa"]
[ext_resource type="PackedScene" uid="uid://cv6sxj04rrkt2" path="res://src/props/med_cart/phys_med_cart.tscn" id="14_u3x5h"]
[ext_resource type="PackedScene" uid="uid://rykf34p8n8x6" path="res://src/props/overhead_light/burnout_light.tscn" id="15_r8upy"]
[ext_resource type="PackedScene" uid="uid://ctm84yms40858" path="res://src/props/railing/railing.tscn" id="16_kccq3"]
[ext_resource type="PackedScene" uid="uid://ctr56p23cvupu" path="res://src/props/retinal_scanner/retinal_scanner.tscn" id="17_r8upy"]
[ext_resource type="PackedScene" uid="uid://cjqayfrj2oxyr" path="res://src/props/tarp_crate/tarp_crate_logo.tscn" id="20_pfhf5"]
[ext_resource type="PackedScene" uid="uid://cklppdtyaadlo" path="res://src/props/trash_can/trash_can.tscn" id="21_wgtci"]
[ext_resource type="PackedScene" uid="uid://cklppdtyaadlo" path="res://src/props/trash_can/static_trash_can.tscn" id="21_wgtci"]
[ext_resource type="PackedScene" uid="uid://dtus42gmb1kqq" path="res://src/props/vending_machine/vending_machine.tscn" id="22_6oadn"]
[ext_resource type="Texture2D" uid="uid://d2xq0uvxh2ojk" path="res://assets/props/vending_machine/vending_machine_C.png" id="23_ibd1t"]
[ext_resource type="Texture2D" uid="uid://d0xe37qm3k7d8" path="res://assets/props/vending_machine/vending_machine_E.png" id="24_mvw32"]
[ext_resource type="PackedScene" uid="uid://p86qtslgpe1i" path="res://src/props/trash_can/phys_trash_can.tscn" id="25_8eukv"]
[ext_resource type="Texture2D" uid="uid://dkilg200w8x4y" path="res://assets/props/vending_machine/vending_machine_M.png" id="25_yijpk"]
[ext_resource type="Texture2D" uid="uid://8v7jta2qdvut" path="res://assets/props/vending_machine/vending_machine_N.png" id="26_qnhar"]
[ext_resource type="Texture2D" uid="uid://gbvtbiurxrop" path="res://assets/props/vending_machine/vending_machine_R.png" id="27_8a67w"]
@ -179,10 +182,13 @@ text = "Open"
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.7, 0.4, -9)
skeleton = NodePath("../..")
[node name="CrateLong" parent="Props" instance=ExtResource("7_4jlf1")]
[node name="StaticCrateLong" parent="Props" instance=ExtResource("7_4jlf1")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.9, 1.5, -9)
skeleton = NodePath("../..")
[node name="PhysCrateLong" parent="Props" instance=ExtResource("8_8a67w")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.1, 1.5, -7.5)
[node name="Cupboard" parent="Props" instance=ExtResource("8_kgrlx")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.9, 2.4, -9)
skeleton = NodePath("../..")
@ -193,10 +199,13 @@ transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 7.5223
[node name="EVASuit2" parent="Props" instance=ExtResource("10_s7h0g")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 10.8753, 1.49988, -11.2474)
[node name="MedCart" parent="Props" instance=ExtResource("11_s7h0g")]
[node name="StaticMedCart" parent="Props" instance=ExtResource("11_s7h0g")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.8, 0.5, -10.8)
skeleton = NodePath("../..")
[node name="PhysMedCart" parent="Props" instance=ExtResource("14_u3x5h")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 14.7, 0.5, -9.6)
[node name="Monitor" parent="Props" instance=ExtResource("12_wyhm4")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 15.3, 1.5, -10.8)
@ -229,10 +238,13 @@ skeleton = NodePath("../..")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 39, 0.8, -12)
skeleton = NodePath("../..")
[node name="TrashCan" parent="Props" instance=ExtResource("21_wgtci")]
[node name="StaticTrashCan" parent="Props" instance=ExtResource("21_wgtci")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42, 0.5, -12)
skeleton = NodePath("../..")
[node name="PhysTrashCan" parent="Props" instance=ExtResource("25_8eukv")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.9, 0.5, -10.8)
[node name="VendingMachine" parent="Props" instance=ExtResource("22_6oadn")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 45, 1.5654, -12)

View File

@ -210,6 +210,7 @@ locale/translations=PackedStringArray("res://assets/text/text.en.translation")
3d_physics/layer_4="Player"
3d_physics/layer_5="GameSounds"
3d_physics/layer_6="Player Physics"
3d_physics/layer_7="Prop Physics"
[physics]

View File

@ -14,11 +14,10 @@ func _spray() -> void:
spray_sfx.set_angle_from_normal(laser.get_collision_normal())
var collider := laser.get_collider()
if collider is GunkBody:
var gunk_component := Gunkable.get_component(collider)
if gunk_component:
var point := laser.get_collision_point()
var point_scale := point.distance_to(global_position) * spray_scale
(collider as GunkBody).paint_continuous(
point, laser.get_collision_normal(), point_scale
)
gunk_component.paint_continuous(point, laser.get_collision_normal(), point_scale)
if collider is Sprayable:
(collider as Sprayable).hit(damage)

View File

@ -19,15 +19,16 @@ func _fire() -> void:
if raycast.is_colliding() and not World.instance.manager.is_tank_full():
brush_animation.play("brush")
var collider := raycast.get_collider()
if collider is GunkBody:
(collider as GunkBody).paint_dot(
var gunk_component := Gunkable.get_component(collider)
if gunk_component:
gunk_component.paint_dot(
raycast.get_collision_point(),
raycast.get_collision_normal(),
BRUSH_SCALE,
PAINT_COLOR
)
if collider is GunkNode:
(collider as GunkNode).hit(damage)
if collider is Sprayable:
(collider as Sprayable).hit(damage)
else:
brush_animation.stop()

View File

@ -117,8 +117,7 @@ unique_name_in_owner = true
visible = false
texture_filter = 1
layout_mode = 0
offset_left = -40.0
offset_right = 24.0
offset_right = 64.0
offset_bottom = 128.0
scale = Vector2(5, 5)
texture = ExtResource("4_atd0h")

View File

@ -36,7 +36,7 @@ func _fire() -> void:
func _spray() -> void:
var prev_target: GunkBody = null
var prev_target: Gunkable = null
var prev_point: Vector3
var prev_normal: Vector3
@ -46,19 +46,21 @@ func _spray() -> void:
spray_sfx.set_angle_from_normal(laser.get_collision_normal())
var collider := laser.get_collider()
if collider is GunkBody:
var target := collider as GunkBody
var gunk_component := Gunkable.get_component(collider)
if gunk_component:
var point := laser.get_collision_point()
var normal := laser.get_collision_normal()
# Always paint at least a dot, to cap the ends of the line
target.paint_dot(point, normal, spray_scale)
if target == prev_target:
gunk_component.paint_dot(point, normal, spray_scale)
if gunk_component == prev_target:
# Continue the multiline if possible
target.add_to_multiline(prev_point, prev_normal, point, normal, spray_scale * 2)
gunk_component.add_to_multiline(
prev_point, prev_normal, point, normal, spray_scale * 2
)
prev_point = point
prev_normal = normal
prev_target = target
prev_target = gunk_component
prev_point = point
prev_normal = normal
elif collider is Sprayable:

View File

@ -321,11 +321,6 @@ offset_left = 344.0
offset_top = 211.0
offset_right = 344.0
offset_bottom = 211.0
BUFFER_RUMBLE_FACTOR = 3.0
RUMBLE_DECAY = 10
NEEDLE_ACCEL = 1.0
NEEDLE_VELOCITY_MAX = 1.0
debug_collect = 0.0
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true

View File

@ -34,9 +34,10 @@ func play_footstep() -> void:
func get_material_under_foot() -> SurfaceMaterial.Type:
var collider := foot_cast.get_collider() as Node
if collider is GunkBody:
var gunk_component := Gunkable.get_component(collider)
if gunk_component:
# Special case: check if collision surface is gunked
if (collider as GunkBody).is_point_gunked(
if gunk_component.is_point_gunked(
foot_cast.get_collision_point(), foot_cast.get_collision_normal()
):
return SurfaceMaterial.Type.GRUNK

View File

@ -14,10 +14,10 @@ extends Node3D
@export var hold_damping := 8.0
## Temporary collision layer.
@export_flags_3d_physics var hold_collision_layer := 0
@export_flags_3d_physics var hold_collision_layer := 0b01000000
## Temporary collision mask.
@export_flags_3d_physics var hold_collision_physics := 1
@export_flags_3d_physics var hold_collision_physics := 0b01000001
## The object currently being held.
var _held_object: RigidBody3D

View File

@ -684,6 +684,8 @@ script = ExtResource("7_x42xx")
[node name="HoldComponent" type="Node3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D"]
script = ExtResource("11_h0enb")
hold_accel = 40.0
hold_speed = 20.0
[node name="HoldPoint" type="Marker3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D/HoldComponent"]
unique_name_in_owner = true

View File

@ -1,11 +1,12 @@
[gd_scene load_steps=9 format=3 uid="uid://ca7b5gjl3ri0p"]
[gd_scene load_steps=10 format=3 uid="uid://ca7b5gjl3ri0p"]
[ext_resource type="Texture2D" uid="uid://kji1r64xr62b" path="res://assets/props/cafe_table/cafe_table_C.png" id="1_8c2wd"]
[ext_resource type="ArrayMesh" uid="uid://02pxl1iknwie" path="res://assets/props/cafe_table/cafe_table.obj" id="1_kbxmn"]
[ext_resource type="Texture2D" uid="uid://chh8wcdsu601s" path="res://assets/props/cafe_table/cafe_table_M.png" id="2_atatm"]
[ext_resource type="Texture2D" uid="uid://6nrac2ciprd4" path="res://assets/props/cafe_table/cafe_table_N.png" id="3_4grlf"]
[ext_resource type="Texture2D" uid="uid://dryw5kjktefst" path="res://assets/props/cafe_table/cafe_table_R.png" id="4_naoko"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="5_ywp2f"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="7_atatm"]
[ext_resource type="Material" uid="uid://cqjr3cbxtfg2j" path="res://assets/materials/gunk.material" id="8_4grlf"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_q50g7"]
albedo_texture = ExtResource("1_8c2wd")
@ -23,7 +24,14 @@ data = PackedVector3Array(0.9, 0, -0.05, 0.9, 0, -2.95, 1.5, 0, -0.05, 1.5, 0, -
mesh = ExtResource("1_kbxmn")
surface_material_override/0 = SubResource("StandardMaterial3D_q50g7")
[node name="GunkBody" parent="." groups=["PlasticMaterial"] instance=ExtResource("5_ywp2f")]
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["PlasticMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_c6qxl")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("7_atatm")]
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("8_4grlf")

View File

@ -0,0 +1,58 @@
[gd_scene load_steps=13 format=3 uid="uid://drm5dspi48pf5"]
[ext_resource type="Script" uid="uid://sksndhqyo2bn" path="res://src/props/physics/persistent_prop.gd" id="1_q4djj"]
[ext_resource type="ArrayMesh" uid="uid://cd7vwjss7qytk" path="res://assets/props/crate_long/crate_long.obj" id="1_sao54"]
[ext_resource type="Texture2D" uid="uid://cd0w8eqpount3" path="res://assets/props/crate_long/crate_long_C.png" id="2_rlyiq"]
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="3_p8srg"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="4_q4djj"]
[ext_resource type="Texture2D" uid="uid://b1m1my5q2vlwi" path="res://assets/props/crate_long/crate_long_R.png" id="5_eb8p8"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_064yj"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="7_rlyiq"]
[ext_resource type="Script" uid="uid://040xta01xqxd" path="res://src/props/physics/holdable.gd" id="8_p8srg"]
[sub_resource type="BoxShape3D" id="BoxShape3D_p8srg"]
size = Vector3(0.75, 0.5, 1.5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8j27j"]
albedo_texture = ExtResource("2_rlyiq")
metallic = 1.0
metallic_texture = ExtResource("3_p8srg")
roughness_texture = ExtResource("5_eb8p8")
normal_enabled = true
normal_texture = ExtResource("4_q4djj")
ao_enabled = true
texture_filter = 2
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_p8srg"]
data = PackedVector3Array(0.375, -0.15, 0.75, 0.275, -0.25, 0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.275, -0.25, 0.75, 0.275, 0.25, 0.75, 0.275, 0.25, 0.75, 0.275, -0.25, 0.75, -0.275, 0.25, 0.75, -0.275, 0.25, 0.75, 0.275, -0.25, 0.75, -0.375, 0.15, 0.75, -0.375, 0.15, 0.75, 0.275, -0.25, 0.75, -0.375, -0.15, 0.75, -0.375, -0.15, 0.75, 0.275, -0.25, 0.75, -0.275, -0.25, 0.75, 0.375, 0.15, -0.75, 0.375, -0.15, -0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.375, -0.15, -0.75, 0.375, -0.15, 0.75, -0.275, 0.25, -0.75, 0.275, 0.25, -0.75, -0.275, 0.25, 0.75, -0.275, 0.25, 0.75, 0.275, 0.25, -0.75, 0.275, 0.25, 0.75, -0.375, 0.15, 0.75, -0.375, -0.15, 0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.375, -0.15, 0.75, -0.375, -0.15, -0.75, -0.375, -0.15, -0.75, -0.275, -0.25, -0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.275, -0.25, -0.75, -0.275, 0.25, -0.75, -0.275, 0.25, -0.75, -0.275, -0.25, -0.75, 0.275, 0.25, -0.75, 0.275, 0.25, -0.75, -0.275, -0.25, -0.75, 0.375, 0.15, -0.75, 0.375, 0.15, -0.75, -0.275, -0.25, -0.75, 0.375, -0.15, -0.75, 0.375, -0.15, -0.75, -0.275, -0.25, -0.75, 0.275, -0.25, -0.75, -0.275, -0.25, 0.75, -0.275, -0.25, -0.75, -0.375, -0.15, 0.75, -0.375, -0.15, 0.75, -0.275, -0.25, -0.75, -0.375, -0.15, -0.75, -0.275, 0.25, -0.75, -0.275, 0.25, 0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.275, 0.25, 0.75, -0.375, 0.15, 0.75, 0.275, -0.25, -0.75, 0.275, -0.25, 0.75, 0.375, -0.15, -0.75, 0.375, -0.15, -0.75, 0.275, -0.25, 0.75, 0.375, -0.15, 0.75, 0.275, 0.25, 0.75, 0.275, 0.25, -0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.275, 0.25, -0.75, 0.375, 0.15, -0.75, 0.275, -0.25, -0.75, -0.275, -0.25, -0.75, 0.275, -0.25, 0.75, 0.275, -0.25, 0.75, -0.275, -0.25, -0.75, -0.275, -0.25, 0.75)
[node name="PhysCrateLong" type="RigidBody3D" groups=["Persistent", "PlasticMaterial"]]
collision_layer = 67
collision_mask = 73
mass = 200.0
script = ExtResource("1_q4djj")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_p8srg")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = ExtResource("1_sao54")
surface_material_override/0 = SubResource("StandardMaterial3D_8j27j")
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
collision_layer = 4
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_p8srg")
[node name="Gunkable" parent="MeshInstance3D/StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_064yj")]
mask_dim = 128
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("7_rlyiq")
[node name="Holdable" type="Node" parent="."]
script = ExtResource("8_p8srg")
hold_distance = 2.0
metadata/_custom_type_script = "uid://040xta01xqxd"

View File

@ -5,7 +5,7 @@
[ext_resource type="Texture2D" uid="uid://da5p04vbiy3xe" path="res://assets/props/crate_long/crate_long_M.png" id="3_c6a2t"]
[ext_resource type="Texture2D" uid="uid://bsovubygl3go2" path="res://assets/props/crate_long/crate_long_N.png" id="4_d06p6"]
[ext_resource type="Texture2D" uid="uid://b1m1my5q2vlwi" path="res://assets/props/crate_long/crate_long_R.png" id="5_cmp6v"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="5_d06p6"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_agrnx"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="6_c6a2t"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5pe4w"]
@ -21,13 +21,19 @@ texture_filter = 2
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_d06p6"]
data = PackedVector3Array(0.375, -0.15, 0.75, 0.275, -0.25, 0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.275, -0.25, 0.75, 0.275, 0.25, 0.75, 0.275, 0.25, 0.75, 0.275, -0.25, 0.75, -0.275, 0.25, 0.75, -0.275, 0.25, 0.75, 0.275, -0.25, 0.75, -0.375, 0.15, 0.75, -0.375, 0.15, 0.75, 0.275, -0.25, 0.75, -0.375, -0.15, 0.75, -0.375, -0.15, 0.75, 0.275, -0.25, 0.75, -0.275, -0.25, 0.75, 0.375, 0.15, -0.75, 0.375, -0.15, -0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.375, -0.15, -0.75, 0.375, -0.15, 0.75, -0.275, 0.25, -0.75, 0.275, 0.25, -0.75, -0.275, 0.25, 0.75, -0.275, 0.25, 0.75, 0.275, 0.25, -0.75, 0.275, 0.25, 0.75, -0.375, 0.15, 0.75, -0.375, -0.15, 0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.375, -0.15, 0.75, -0.375, -0.15, -0.75, -0.375, -0.15, -0.75, -0.275, -0.25, -0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.275, -0.25, -0.75, -0.275, 0.25, -0.75, -0.275, 0.25, -0.75, -0.275, -0.25, -0.75, 0.275, 0.25, -0.75, 0.275, 0.25, -0.75, -0.275, -0.25, -0.75, 0.375, 0.15, -0.75, 0.375, 0.15, -0.75, -0.275, -0.25, -0.75, 0.375, -0.15, -0.75, 0.375, -0.15, -0.75, -0.275, -0.25, -0.75, 0.275, -0.25, -0.75, -0.275, -0.25, 0.75, -0.275, -0.25, -0.75, -0.375, -0.15, 0.75, -0.375, -0.15, 0.75, -0.275, -0.25, -0.75, -0.375, -0.15, -0.75, -0.275, 0.25, -0.75, -0.275, 0.25, 0.75, -0.375, 0.15, -0.75, -0.375, 0.15, -0.75, -0.275, 0.25, 0.75, -0.375, 0.15, 0.75, 0.275, -0.25, -0.75, 0.275, -0.25, 0.75, 0.375, -0.15, -0.75, 0.375, -0.15, -0.75, 0.275, -0.25, 0.75, 0.375, -0.15, 0.75, 0.275, 0.25, 0.75, 0.275, 0.25, -0.75, 0.375, 0.15, 0.75, 0.375, 0.15, 0.75, 0.275, 0.25, -0.75, 0.375, 0.15, -0.75, 0.275, -0.25, -0.75, -0.275, -0.25, -0.75, 0.275, -0.25, 0.75, 0.275, -0.25, 0.75, -0.275, -0.25, -0.75, -0.275, -0.25, 0.75)
[node name="CrateLong" type="MeshInstance3D"]
[node name="StaticCrateLong" type="MeshInstance3D"]
mesh = ExtResource("1_d06p6")
surface_material_override/0 = SubResource("StandardMaterial3D_5pe4w")
[node name="GunkBody" parent="." groups=["PlasticMaterial"] instance=ExtResource("5_d06p6")]
mask_dim = 128
source_gunk_material = ExtResource("6_c6a2t")
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["PlasticMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_d06p6")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_agrnx")]
mask_dim = 128
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("6_c6a2t")

View File

@ -1,11 +1,12 @@
[gd_scene load_steps=9 format=3 uid="uid://c8pkhw0b47xdd"]
[gd_scene load_steps=10 format=3 uid="uid://c8pkhw0b47xdd"]
[ext_resource type="Texture2D" uid="uid://dg4odum5vfc2r" path="res://assets/props/cupboard/cupboard_C.png" id="1_00yk4"]
[ext_resource type="ArrayMesh" uid="uid://dgfds7nbhxbbl" path="res://assets/props/cupboard/cupboard.obj" id="1_ssqwt"]
[ext_resource type="Texture2D" uid="uid://dkx0128lukxme" path="res://assets/props/cupboard/cupboard_M.png" id="2_w0nd8"]
[ext_resource type="Texture2D" uid="uid://c0qid1gqplbly" path="res://assets/props/cupboard/cupboard_N.png" id="3_ssqwt"]
[ext_resource type="Texture2D" uid="uid://cdmgbmje8ub3y" path="res://assets/props/cupboard/cupboard_R.png" id="4_q3cl1"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="5_q3cl1"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="7_wyuua"]
[ext_resource type="Material" uid="uid://cqjr3cbxtfg2j" path="res://assets/materials/gunk.material" id="8_rgfsf"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wyuua"]
albedo_texture = ExtResource("1_00yk4")
@ -23,7 +24,14 @@ data = PackedVector3Array(-0.5, 0.5, 2, -0.5, -0.5, 2, -0.5, 0.5, -2, -0.5, 0.5,
mesh = ExtResource("1_ssqwt")
surface_material_override/0 = SubResource("StandardMaterial3D_wyuua")
[node name="GunkBody" parent="." groups=["MetalMaterial"] instance=ExtResource("5_q3cl1")]
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["MetalMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_tv0mb")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("7_wyuua")]
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("8_rgfsf")

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,12 @@
[gd_scene load_steps=9 format=3 uid="uid://oipf3w7hm5gf"]
[gd_scene load_steps=10 format=3 uid="uid://oipf3w7hm5gf"]
[ext_resource type="ArrayMesh" uid="uid://c0nxj2li1pefb" path="res://assets/props/operating_table/operating_table.obj" id="1_pt2ft"]
[ext_resource type="Texture2D" uid="uid://e7kat4x3brst" path="res://assets/props/operating_table/operating_table_C.png" id="2_73alj"]
[ext_resource type="Texture2D" uid="uid://ctv1f41eefar0" path="res://assets/props/operating_table/operating_table_M.png" id="3_lhd0e"]
[ext_resource type="Texture2D" uid="uid://uk3m431m6r0" path="res://assets/props/operating_table/operating_table_N.png" id="4_mevr1"]
[ext_resource type="Texture2D" uid="uid://c4u3qvdtyoq4a" path="res://assets/props/operating_table/operating_table_R.png" id="5_lcrh2"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="6_lhd0e"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_mevr1"]
[ext_resource type="Material" uid="uid://cqjr3cbxtfg2j" path="res://assets/materials/gunk.material" id="7_lcrh2"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lhd0e"]
albedo_texture = ExtResource("2_73alj")
@ -23,8 +24,15 @@ data = PackedVector3Array(-0.9749, 0.4, 0.5127, -0.9749, 0.3, 0.5127, -0.9715, 0
mesh = ExtResource("1_pt2ft")
surface_material_override/0 = SubResource("StandardMaterial3D_lhd0e")
[node name="GunkBody" parent="." instance=ExtResource("6_lhd0e")]
mask_dim = 192
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["MetalMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D2" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_5ju1e")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_mevr1")]
mask_dim = 192
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("7_lcrh2")

View File

@ -5,7 +5,7 @@
[ext_resource type="Texture2D" uid="uid://c3pfufk3r4611" path="res://assets/props/overhead_light/overhead_light_burnout_M.png" id="2_esawx"]
[ext_resource type="Texture2D" uid="uid://buxuntbbfwvfg" path="res://assets/props/overhead_light/overhead_light_burnout_N.png" id="3_vg5ej"]
[ext_resource type="Texture2D" uid="uid://c40m0iq5tot1a" path="res://assets/props/overhead_light/overhead_light_burnout_R.png" id="4_0f8x7"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="5_qcusd"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_1oo6x"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="6_8nypc"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_niury"]
@ -26,9 +26,15 @@ data = PackedVector3Array(0.4, -0.1, 0.75, 0.3, -0.2, 0.75, 0.4, 0, 0.75, 0.4, 0
mesh = ExtResource("1_esawx")
surface_material_override/0 = SubResource("StandardMaterial3D_niury")
[node name="GunkBody" parent="MeshInstance3D" instance=ExtResource("5_qcusd")]
mask_dim = 64
source_gunk_material = ExtResource("6_8nypc")
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_jad1v")
[node name="Gunkable" parent="MeshInstance3D/StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_1oo6x")]
mask_dim = 64
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("6_8nypc")

View File

@ -4,18 +4,18 @@ extends Node3D
@export var initial_mask: Texture
@onready var spot_light_3d: SpotLight3D = %SpotLight3D
@onready var gunk_body: GunkBody = %GunkBody
@onready var gunkable: Gunkable = %Gunkable
func _ready() -> void:
if initial_mask:
gunk_body.initial_mask = initial_mask
gunkable.initial_mask = initial_mask
_deferred_init.call_deferred()
func _deferred_init() -> void:
gunk_body.trigger_recompute()
gunkable.trigger_recompute()
func _on_clear_total_updated(clear_total: float) -> void:

View File

@ -7,8 +7,8 @@
[ext_resource type="Texture2D" uid="uid://bh2jmk7jfjmyr" path="res://assets/props/overhead_light/overhead_light_M.png" id="3_ngq1d"]
[ext_resource type="Texture2D" uid="uid://no4s7dsg8tih" path="res://assets/props/overhead_light/overhead_light_N.png" id="4_3gl0p"]
[ext_resource type="Texture2D" uid="uid://cr5e4hk33wmwf" path="res://assets/props/overhead_light/overhead_light_R.png" id="5_210ch"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="6_3gl0p"]
[ext_resource type="Material" uid="uid://dutkfm4ek0ysh" path="res://assets/materials/gunk_bright.material" id="8_3gl0p"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="10_ljcul"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ljcul"]
resource_local_to_scene = true
@ -117,12 +117,18 @@ libraries = {
}
autoplay = "flicker"
[node name="GunkBody" parent="MeshInstance3D" instance=ExtResource("6_3gl0p")]
unique_name_in_owner = true
mask_dim = 64
source_gunk_material = ExtResource("8_3gl0p")
[node name="StaticBody3D" type="StaticBody3D" parent="MeshInstance3D"]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_jdrpd")
[connection signal="clear_total_updated" from="MeshInstance3D/GunkBody" to="." method="_on_clear_total_updated"]
[node name="Gunkable" parent="MeshInstance3D/StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("10_ljcul")]
unique_name_in_owner = true
mask_dim = 64
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("8_3gl0p")
[connection signal="clear_total_updated" from="MeshInstance3D/StaticBody3D/Gunkable" to="." method="_on_clear_total_updated"]

View File

@ -0,0 +1,18 @@
extends RigidBody3D
func serialize() -> Dictionary:
return {
"transform": transform,
"linear_velocity": linear_velocity,
"angular_velocity": angular_velocity,
}
func deserialize(state: Dictionary) -> void:
@warning_ignore("unsafe_cast")
transform = state["transform"] as Transform3D
@warning_ignore("unsafe_cast")
linear_velocity = state["linear_velocity"] as Vector3
@warning_ignore("unsafe_cast")
angular_velocity = state["angular_velocity"] as Vector3

View File

@ -0,0 +1 @@
uid://sksndhqyo2bn

View File

@ -5,8 +5,8 @@
[ext_resource type="Texture2D" uid="uid://dgyk61lmv3q66" path="res://assets/props/railing/railing_M.png" id="3_vgbo1"]
[ext_resource type="Texture2D" uid="uid://cd142v5tbh10j" path="res://assets/props/railing/railing_N.png" id="4_d75t1"]
[ext_resource type="Texture2D" uid="uid://tpweuhaqj3uy" path="res://assets/props/railing/railing_R.png" id="5_557y4"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="6_vgbo1"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="7_vgbo1"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="8_d75t1"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nyaqk"]
albedo_texture = ExtResource("2_2gmox")
@ -24,9 +24,15 @@ data = PackedVector3Array(1.475, 0.5, 0, 1.5, 0.5, 0.025, -1.475, 0.5, 0, -1.475
mesh = ExtResource("1_43h1k")
surface_material_override/0 = SubResource("StandardMaterial3D_nyaqk")
[node name="GunkBody" parent="." instance=ExtResource("6_vgbo1")]
mask_dim = 128
source_gunk_material = ExtResource("7_vgbo1")
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["MetalMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_557y4")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("8_d75t1")]
mask_dim = 128
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("7_vgbo1")

View File

@ -1,11 +1,12 @@
[gd_scene load_steps=9 format=3 uid="uid://cvx5u0ttmri4q"]
[gd_scene load_steps=10 format=3 uid="uid://cvx5u0ttmri4q"]
[ext_resource type="ArrayMesh" uid="uid://b8p36gpkqwmkb" path="res://assets/props/sofa/sofa.obj" id="1_xi4at"]
[ext_resource type="Texture2D" uid="uid://c7wa2igxm2vta" path="res://assets/props/sofa/sofa_C.png" id="2_dd1m6"]
[ext_resource type="Texture2D" uid="uid://bdutuchsgsudg" path="res://assets/props/sofa/sofa_M.png" id="3_tqm3d"]
[ext_resource type="Texture2D" uid="uid://c0fmlt2f7h0l7" path="res://assets/props/sofa/sofa_N.png" id="4_kf17g"]
[ext_resource type="Texture2D" uid="uid://bgedr6qe65yve" path="res://assets/props/sofa/sofa_R.png" id="5_0yugb"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="6_dd1m6"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_tqm3d"]
[ext_resource type="Material" uid="uid://cqjr3cbxtfg2j" path="res://assets/materials/gunk.material" id="7_kf17g"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_dd1m6"]
albedo_texture = ExtResource("2_dd1m6")
@ -23,8 +24,15 @@ data = PackedVector3Array(-1.25, 0.05, 0.6, -1.09, -0.35, 0.6, -1.25, -0.5, 0.6,
mesh = ExtResource("1_xi4at")
surface_material_override/0 = SubResource("StandardMaterial3D_dd1m6")
[node name="GunkBody" parent="." instance=ExtResource("6_dd1m6")]
mask_dim = 196
[node name="StaticBody3D" type="StaticBody3D" parent="."]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_tqm3d")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_tqm3d")]
mask_dim = 196
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("7_kf17g")

View File

@ -5,7 +5,7 @@
[ext_resource type="Texture2D" uid="uid://boqywmqew0f1i" path="res://assets/props/tarp_crate/tarp_crate_M.png" id="2_4lu2x"]
[ext_resource type="Texture2D" uid="uid://2eg8lmfp1r45" path="res://assets/props/tarp_crate/tarp_crate_N.png" id="3_vis60"]
[ext_resource type="Texture2D" uid="uid://i031i4c162sf" path="res://assets/props/tarp_crate/tarp_crate_R.png" id="4_p1cm3"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="5_p1cm3"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="6_p1cm3"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="6_vis60"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qbm60"]
@ -27,9 +27,15 @@ data = PackedVector3Array(-0.5, 0.7, 0.5, -0.5, -0.7, 0.5, -0.5, 0.7, -0.5, -0.5
mesh = ExtResource("1_p1cm3")
surface_material_override/0 = SubResource("StandardMaterial3D_qbm60")
[node name="GunkBody" parent="." groups=["PlasticMaterial"] instance=ExtResource("5_p1cm3")]
mask_dim = 196
source_gunk_material = ExtResource("6_vis60")
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["PlasticMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_v6rol")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("6_p1cm3")]
mask_dim = 196
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("6_vis60")

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,8 +7,8 @@
[ext_resource type="Texture2D" uid="uid://8v7jta2qdvut" path="res://assets/props/vending_machine/vending_machine_N.png" id="4_m0mqe"]
[ext_resource type="Texture2D" uid="uid://gbvtbiurxrop" path="res://assets/props/vending_machine/vending_machine_R.png" id="5_pmvmu"]
[ext_resource type="Script" uid="uid://jybe7wejrtuj" path="res://src/props/vending_machine/vending_machine.gd" id="6_5b31a"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="6_kgb1h"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="8_b7lht"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="10_8xld6"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_v4lrk"]
resource_local_to_scene = true
@ -31,9 +31,14 @@ mesh = ExtResource("1_5b31a")
surface_material_override/0 = SubResource("StandardMaterial3D_v4lrk")
script = ExtResource("6_5b31a")
[node name="GunkBody" parent="." groups=["MetalMaterial"] instance=ExtResource("6_kgb1h")]
source_gunk_material = ExtResource("8_b7lht")
[node name="StaticBody3D" type="StaticBody3D" parent="." groups=["MetalMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody"]
visible = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
shape = SubResource("ConcavePolygonShape3D_1s701")
[node name="Gunkable" parent="StaticBody3D" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("10_8xld6")]
body = NodePath("..")
mesh_instance = NodePath("../..")
source_gunk_material = ExtResource("8_b7lht")

View File

@ -12,7 +12,8 @@ const CLEAN_THRESHOLD := 1400
@onready var animation_player: AnimationPlayer = %AnimationPlayer
@onready var light_animation: AnimationPlayer = %LightAnimation
@onready var gunk_body: GunkBody = %GunkBody
@onready var gunkable: Gunkable = %Gunkable
@onready var interactive: Interactive = %Interactive
@onready var action_sfx: AudioStreamPlayer3D = %ActionSFX
@onready var action_delay: Timer = %ActionDelay
@ -27,7 +28,7 @@ func _ready() -> void:
func _deferred_init() -> void:
if clean:
gunk_body.clear_all()
gunkable.clear_all()
_on_clean()
if enabled:
_on_enable()
@ -82,7 +83,7 @@ func _animation_finished(anim_name: StringName) -> void:
interactive.enabled = enabled
func _on_gunk_body_clear_total_updated(clear_total: float) -> void:
func _on_clear_total_updated(clear_total: float) -> void:
if not clean and clear_total >= CLEAN_THRESHOLD:
_on_clean()

View File

@ -6,8 +6,8 @@
[ext_resource type="Texture2D" uid="uid://bur4dtt4irwgd" path="res://assets/props/wall_switch/wall_switch_M.png" id="3_3fhmv"]
[ext_resource type="Texture2D" uid="uid://ddve6jcfcuthx" path="res://assets/props/wall_switch/wall_switch_N.png" id="4_pg3hp"]
[ext_resource type="Texture2D" uid="uid://rq5e0a3sco88" path="res://assets/props/wall_switch/wall_switch_R.png" id="5_555wb"]
[ext_resource type="PackedScene" uid="uid://c2omlx4ptrc01" path="res://src/world/gunk_body/gunk_body.tscn" id="7_3ib1l"]
[ext_resource type="Material" uid="uid://c1vy4bkwb1g5m" path="res://assets/materials/gunk_lowrez.material" id="8_2qpft"]
[ext_resource type="PackedScene" uid="uid://cdi5sl60mw1po" path="res://src/world/gunk_body/gunkable.tscn" id="9_eim2y"]
[ext_resource type="Script" uid="uid://deg5xd87cy8rg" path="res://src/props/interactive.gd" id="10_qw6jt"]
[ext_resource type="AudioStream" uid="uid://bgayfws34lg7q" path="res://assets/sfx/click_electronic_04.wav" id="11_7shuc"]
[ext_resource type="AudioStream" uid="uid://cnje66wrijwxw" path="res://assets/sfx/wall_switch.wav" id="12_2qpft"]
@ -200,15 +200,20 @@ surface_material_override/0 = SubResource("StandardMaterial3D_jtkkw")
[node name="AnimationPlayer" parent="." index="1"]
unique_name_in_owner = true
[node name="GunkBody" parent="." index="2" node_paths=PackedStringArray("mesh_instance") instance=ExtResource("7_3ib1l")]
[node name="StaticBody3D" type="StaticBody3D" parent="." index="2" groups=["PlasticMaterial"]]
collision_layer = 5
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" index="0"]
shape = SubResource("ConcavePolygonShape3D_2qpft")
[node name="Gunkable" parent="StaticBody3D" index="1" node_paths=PackedStringArray("body", "mesh_instance") instance=ExtResource("9_eim2y")]
unique_name_in_owner = true
mask_dim = 64
mesh_instance = NodePath("../Armature/Skeleton3D/WallSwitch_2")
body = NodePath("..")
mesh_instance = NodePath("../../Armature/Skeleton3D/WallSwitch_2")
source_gunk_material = ExtResource("8_2qpft")
[node name="CollisionShape3D" type="CollisionShape3D" parent="GunkBody" index="2"]
shape = SubResource("ConcavePolygonShape3D_2qpft")
[node name="Lights" type="Node3D" parent="." index="3"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.137, 0.18, 0.08)
@ -267,7 +272,7 @@ metadata/_custom_type_script = "uid://c5o1d2shq2qig"
[node name="CollisionShape3D" type="CollisionShape3D" parent="WallSwitchGameSoundEmitter" index="0"]
shape = SubResource("SphereShape3D_mxsyy")
[connection signal="clear_total_updated" from="GunkBody" to="." method="_on_gunk_body_clear_total_updated"]
[connection signal="clear_total_updated" from="StaticBody3D/Gunkable" to="." method="_on_clear_total_updated"]
[connection signal="activated" from="Interactive" to="." method="_activate"]
[connection signal="timeout" from="ActionDelay" to="." method="_on_action_delay_timeout"]
[connection signal="timeout" from="ActionDelay" to="WallSwitchGameSoundEmitter" method="emit_sound_here"]

View File

@ -0,0 +1,309 @@
class_name Gunkable extends Node
## Component behavior for gunkable props & geometry.
## Emitted from the main thread after the clear total is asynchronously updated.
signal clear_total_updated(clear_total: float)
const CONTINUITY_LIMIT := 32
const BUFFER_LIMIT := 3
const FACE_EPSILON := 0.01
const CLEAR_COLOR := Color.BLACK
const MASK_COLOR := Color.RED
const CLEAR_TOTAL_EPSILON := 1
const MASK_THRESHOLD := 0.5
@export var mask_dim := 256
@export var body: PhysicsBody3D
@export var mesh_instance: MeshInstance3D
@export var initial_mask: Texture
@export var source_gunk_material: ShaderMaterial
var meshtool := MeshDataTool.new()
var _polyline_buffer: Array[Vector2] = []
var _continued_paint_this_frame := false
var _multiline_buffer := PackedVector2Array()
var _multiline_width := 1.0
var _clear_total := 0.0
var _prev_clear_total := -1.0
# _clear_total is async computed in separate thread
var _mask_tx: Texture2D
var _cached_mask: Image
var _thread: Thread
var _mutex: Mutex = Mutex.new()
var _semaphore: Semaphore = Semaphore.new()
var _exit_thread := false
@onready var mask_viewport: SubViewport = %MaskViewport
@onready var mask_control: DrawController = %MaskControl
@onready var mask_texture: TextureRect = %MaskTexture
func _ready() -> void:
# If no physics body was provided, use the parent.
if not body:
body = get_parent() as PhysicsBody3D
assert(body, "GunkBody %s has no associated physics body!" % str(self))
# If no mesh_instance was provided, use the parent.
if not mesh_instance:
mesh_instance = get_parent() as MeshInstance3D
assert(mesh_instance, "GunkBody %s has no associated mesh!" % str(self))
mask_viewport.size = Vector2(mask_dim, mask_dim)
# Create a new instance of the gunk material
var mat_instance: ShaderMaterial = source_gunk_material.duplicate()
# Set material gunk mask to our mask viewport texture
mat_instance.set_shader_parameter("gunk_mask", mask_viewport.get_texture())
# Overlay mesh with gunk material
mesh_instance.material_overlay = mat_instance
_deferred_init.call_deferred()
# Initialize meshtool
meshtool.create_from_surface(mesh_instance.mesh as ArrayMesh, 0)
_thread = Thread.new()
_thread.start(_async_compute_clear_total)
func _deferred_init() -> void:
if initial_mask:
mask_texture.texture = initial_mask
mask_texture.visible = true
func _async_compute_clear_total() -> void:
# Ignore first two calls (initial mask clear & texture)
# NOTE: this technically could put us in a glitched state if that mask clear & texture don't happen
# and the thread wouldn't be able to hit the exit condition.
# If the application hangs in a weird way immediately after loading a scene, maybe this is why!
_semaphore.wait()
_semaphore.wait()
while true:
_semaphore.wait()
# check exit flag
_mutex.lock()
var exiting := _exit_thread
_mutex.unlock()
if exiting:
break
# Get mask from GPU
# TODO: does this need mutex protection?
_mutex.lock()
_cached_mask = _mask_tx.get_image()
_cached_mask.convert(Image.FORMAT_R8)
_mutex.unlock()
var px_data := _cached_mask.get_data()
var px_sum := 0
for px in px_data:
px_sum += px
var new_total := px_sum / 255.0
# Write total
_mutex.lock()
_clear_total = new_total
_mutex.unlock()
func _exit_tree() -> void:
# Flag processing flag to cleanly exit
_mutex.lock()
_exit_thread = true
_mutex.unlock()
_semaphore.post()
_thread.wait_to_finish()
func clear_all() -> void:
mask_control.clear(MASK_COLOR)
## Get the precise number of gunk pixels cleared from this image.
##
## This will use a cached result unless the mask has been painted since the last calculation.
## Be aware that cache misses are potentially quite expensive.
func get_clear_total() -> float:
# Protect with mutex
_mutex.lock()
var total := _clear_total
_mutex.unlock()
return total
## Get the index of the mesh face on which the given point+normal lies.
##
## Returns -1 if the given point+normal does not lie on a mesh face within tolerance.
func _get_face(point: Vector3, normal: Vector3) -> int:
var min_i := -1
var min_planar_dist := INF
for i in range(meshtool.get_face_count()):
var sdist := meshtool.get_face_normal(i).distance_squared_to(normal)
if sdist > FACE_EPSILON:
continue
# Normals match, so check if the point is on this face
var v1 := meshtool.get_vertex(meshtool.get_face_vertex(i, 0))
var v2 := meshtool.get_vertex(meshtool.get_face_vertex(i, 1))
var v3 := meshtool.get_vertex(meshtool.get_face_vertex(i, 2))
if GeometryTools.is_in_triangle(point, v1, v2, v3):
var planar_dist := absf(Plane(v1, v2, v3).distance_to(point))
if planar_dist < min_planar_dist:
min_i = i
min_planar_dist = planar_dist
return min_i
## UV-unwrap a point+normal in 3D space onto the UV space of this mesh.
##
## Returns Vector2.INF if the given point+normal does not lie on this mesh within tolerance.
func _get_uv(point: Vector3, normal: Vector3) -> Vector2:
var face := _get_face(point, normal)
if face < 0:
return Vector2.INF
var fv0 := meshtool.get_face_vertex(face, 0)
var fv1 := meshtool.get_face_vertex(face, 1)
var fv2 := meshtool.get_face_vertex(face, 2)
var v1 := meshtool.get_vertex(fv0)
var v2 := meshtool.get_vertex(fv1)
var v3 := meshtool.get_vertex(fv2)
var bc := GeometryTools.barycentric(point, v1, v2, v3) # TODO memoize
var uv1 := meshtool.get_vertex_uv(fv0)
var uv2 := meshtool.get_vertex_uv(fv1)
var uv3 := meshtool.get_vertex_uv(fv2)
return (uv1 * bc.x) + (uv2 * bc.y) + (uv3 * bc.z)
## UV-unwrap a point+normal in 3D space onto the pixel space of this mesh's texture.
##
## Returns Vector2.INF if the given point+normal does not lie on this mesh within tolerance.
func _get_px(point: Vector3, normal: Vector3) -> Vector2:
return _get_uv(point * body.global_transform, normal * body.global_basis) * mask_control.size
func is_point_gunked(point: Vector3, normal: Vector3) -> bool:
var px := _get_px(point, normal)
var result := false
# XXX deadlock potential?
_mutex.lock()
result = _cached_mask and _cached_mask.get_pixelv(px).r < MASK_THRESHOLD
_mutex.unlock()
return result
## Paint a dot on the gunk mask.
func paint_dot(point: Vector3, normal: Vector3, radius: float, color: Color = MASK_COLOR) -> void:
var px := _get_px(point, normal)
if px == Vector2.INF:
return
mask_control.queue_draw(
func() -> void: mask_control.draw_circle(px, radius, color, true, -1, true)
)
## Paint a continuous line on the gunk mask if called on successive frames.
func paint_continuous(
point: Vector3, normal: Vector3, width: float, color: Color = MASK_COLOR
) -> void:
var px := _get_px(point, normal)
if _polyline_buffer and px.distance_to(_polyline_buffer[0]) <= CONTINUITY_LIMIT:
_polyline_buffer.push_front(px)
if len(_polyline_buffer) > BUFFER_LIMIT:
_polyline_buffer.pop_back()
var polyline := PackedVector2Array(_polyline_buffer)
mask_control.queue_draw(
func() -> void: mask_control.draw_polyline(polyline, color, width * 2, true)
)
else:
_polyline_buffer = [px]
# Always paint a circle, to round out corners & cap ends
mask_control.queue_draw(
func() -> void: mask_control.draw_circle(px, width, color, true, -1, true)
)
_continued_paint_this_frame = true
## Add a segment to the multiline to paint this frame.
func add_to_multiline(
point_a: Vector3, normal_a: Vector3, point_b: Vector3, normal_b: Vector3, width: float
) -> void:
var px_a := _get_px(point_a, normal_a)
var px_b := _get_px(point_b, normal_b)
if px_a == Vector2.INF or px_b == Vector2.INF or px_a.distance_to(px_b) > CONTINUITY_LIMIT:
return
_multiline_buffer.append(px_a)
_multiline_buffer.append(px_b)
_multiline_width = width
func _process(_delta: float) -> void:
# Check if processing thread has updated the clear total
_mutex.lock()
var new_total := _clear_total
_mutex.unlock()
var delta := new_total - _prev_clear_total
if abs(delta) > CLEAR_TOTAL_EPSILON:
clear_total_updated.emit(new_total)
# Do not fire signal on first compute after initialization
# This prevents the player from collecting the grunk from the initial mask.
if _prev_clear_total >= 0:
# XXX due to fp error, this will drift from the "true count" over time
# but it probably won't matter :shrug:
World.instance.manager.collect_grunk(delta)
_prev_clear_total = new_total
# If paint_continuous wasn't called last frame, stop the current polyline.
if not _continued_paint_this_frame:
_polyline_buffer = []
_continued_paint_this_frame = false
# If we've buffered a multiline in the last frame, draw it & clear the buffer.
# The width of the multiline will just be the width of the last call.
if _multiline_buffer:
var points := _multiline_buffer.duplicate()
var width := _multiline_width
mask_control.queue_draw(
func() -> void: mask_control.draw_multiline(points, MASK_COLOR, width, true)
)
_multiline_buffer = PackedVector2Array()
func trigger_recompute() -> void:
_mutex.lock()
_mask_tx = mask_viewport.get_texture()
_mutex.unlock()
_semaphore.post()
func _on_mask_painted() -> void:
# XXX any problem with posting each frame?
trigger_recompute.call_deferred()
func serialize() -> Dictionary:
var state := {"mask": mask_viewport.get_texture().get_image()}
return state
func deserialize(state: Dictionary) -> void:
@warning_ignore("unsafe_cast")
initial_mask = ImageTexture.create_from_image(state["mask"] as Image)
static func get_component(o: Object) -> Gunkable:
var n := o as Node
if n and n.has_node("Gunkable"):
return n.get_node_or_null("Gunkable") as Gunkable
return null

View File

@ -0,0 +1 @@
uid://co0g2klfmor48

View File

@ -0,0 +1,47 @@
[gd_scene load_steps=3 format=3 uid="uid://cdi5sl60mw1po"]
[ext_resource type="Script" uid="uid://co0g2klfmor48" path="res://src/world/gunk_body/gunkable.gd" id="1_47xoo"]
[ext_resource type="Script" uid="uid://bom5qysgfvap1" path="res://src/world/gunk_body/draw_controller.gd" id="2_srn13"]
[node name="Gunkable" type="Node" groups=["Persistent"]]
script = ExtResource("1_47xoo")
metadata/_custom_type_script = "uid://co0g2klfmor48"
[node name="MaskViewport" type="SubViewport" parent="."]
unique_name_in_owner = true
transparent_bg = true
handle_input_locally = false
size = Vector2i(1024, 1024)
render_target_clear_mode = 1
render_target_update_mode = 4
[node name="MaskClear" type="ColorRect" parent="MaskViewport"]
unique_name_in_owner = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="MaskTexture" type="TextureRect" parent="MaskViewport"]
unique_name_in_owner = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MaskControl" type="Control" parent="MaskViewport"]
unique_name_in_owner = true
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_srn13")
[connection signal="visibility_changed" from="MaskViewport/MaskClear" to="MaskViewport/MaskControl" method="_set_dirty"]
[connection signal="visibility_changed" from="MaskViewport/MaskTexture" to="MaskViewport/MaskControl" method="_set_dirty"]
[connection signal="draw" from="MaskViewport/MaskControl" to="." method="_on_mask_painted"]

View File

@ -4,7 +4,7 @@
[ext_resource type="Resource" uid="uid://tgac5tnfx56r" path="res://src/world/world_manager.tres" id="2_5kmgb"]
[ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="2_6fy3g"]
[ext_resource type="Resource" uid="uid://0i72bf8ip1lx" path="res://src/world/spook_manager.tres" id="3_l0av5"]
[ext_resource type="PackedScene" uid="uid://c7us4smgk3487" path="res://levels/physics_test/physics_test.tscn" id="4_5kmgb"]
[ext_resource type="PackedScene" uid="uid://dc4tts6342cuj" path="res://levels/prop_test/prop_test.tscn" id="4_5kmgb"]
[ext_resource type="PackedScene" uid="uid://c0uitm5cg88h1" path="res://src/ui/menus/kill_screen/kill_screen.tscn" id="6_l0av5"]
[ext_resource type="PackedScene" uid="uid://brknr57xc2cp0" path="res://src/ui/elements/save_icon/save_icon.tscn" id="7_5kmgb"]