Skip to content

Commit

Permalink
Version 6.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Jummit committed Sep 27, 2023
1 parent 4910150 commit 6543d55
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 305 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 6.1

### Breaking

* Added `mesh_instance` property which is used to provide the mesh with the shard material.

### Changed

* Made the cube in the demo a RigidBody3D, which is closer to real-world usage.
* Only one material is generated for each destroyed object.

### Fixed

* Removed embedded scene in `destructible_cube.tscn`

### Added

* Added more documentation.
* Added "addon" tag to project.

## 6.0

### Breaking
Expand Down
51 changes: 35 additions & 16 deletions addons/destruction/destruction.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ extends Node

## Handles destruction of the parent node.
##
## When [method destroy] is called, the parent node is freed and
## shards are added to the [member shard_container]. The [member shard]
## scene is used as a template for [RigidBody3D]s created from the meshes
## inside the [member fragmented] scene..
## When [method destroy] is called, the parent node is freed and shards
## are added to the [member shard_container]. The [member shard] scene
## is used as a template for [RigidBody3D]s created from the meshes
## inside the [member fragmented] scene.

## A scene of the fragmented mesh containing multiple [MeshInstance3D]s.
@export var fragmented: PackedScene: set = set_fragmented
## The shard which is instanced for every part of the fragmented version.
@export var shard := preload("shard.tscn"): set = set_shard
## The mesh instance which is used to retrieve the shard material.
@export var mesh_instance: MeshInstance3D:
set = set_mesh_instance
## The node where created shards are added to.
@onready @export var shard_container := get_node("../../")

Expand All @@ -41,7 +44,7 @@ static var cached_shapes := {}
## Remove the parent node and add shards to the shard container.
func destroy(explosion_power := 1.0) -> void:
var shards = _create_shards(explosion_power)
shard_container.add_child(shards)
shard_container.add_child(shards, true)
shards.global_transform.origin = get_parent().global_transform.origin
get_parent().queue_free()

Expand All @@ -58,12 +61,20 @@ func set_fragmented(to: PackedScene) -> void:
get_tree().node_configuration_warning_changed.emit(self)


func set_mesh_instance(to: MeshInstance3D) -> void:
mesh_instance = to
if is_inside_tree():
get_tree().node_configuration_warning_changed.emit(self)


func _get_configuration_warnings() -> PackedStringArray:
var warnings := []
if not fragmented:
warnings.append("No fragmented version set")
elif not shard:
if not shard:
warnings.append("No shard template set")
if not mesh_instance:
warnings.append("No mesh instance set")
return warnings


Expand All @@ -74,25 +85,33 @@ func _create_shards(explosion_power : float):
cached_shapes[shard_mesh] = shard_mesh.mesh.create_convex_shape()
var original_meshes = cached_meshes[fragmented]

var material: StandardMaterial3D = mesh_instance.mesh.surface_get_material(0)
if not material:
material = mesh_instance.material_override
if material:
material = material.duplicate()
material.flags_transparent = true
if fade_delay > 0:
get_tree().create_tween().tween_property(material, "albedo_color",
Color(1, 1, 1, 0), 2)\
.set_delay(fade_delay)\
.set_trans(Tween.TRANS_EXPO)\
.set_ease(Tween.EASE_OUT)

var shards := Node3D.new()
shards.name = str(cached_meshes[fragmented].name) + "Shards"
shards.name = get_parent().name + "Shards"
for original in original_meshes.get_children():
if not original is MeshInstance3D:
continue
var new_shard: RigidBody3D = shard.instantiate()

var mesh_instance: MeshInstance3D = new_shard.get_node("MeshInstance")
mesh_instance.mesh = original.mesh

var collision_shape : CollisionShape3D = new_shard.get_node("CollisionShape")
collision_shape.shape = cached_shapes[original]

shards.add_child(new_shard, true)
new_shard.position = original.position
new_shard.collision_layer = collision_layer
new_shard.collision_mask = collision_mask
new_shard.material = material
new_shard.mesh = original.mesh
new_shard.shape = cached_shapes[original]
new_shard.fade_delay = fade_delay
new_shard.explosion_power = explosion_power
new_shard.shrink_delay = shrink_delay

shards.add_child(new_shard)
return shards
2 changes: 1 addition & 1 deletion addons/destruction/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
name="Destruction"
description="Destroy 3D objects."
author="Jummit"
version="6.0"
version="6.1"
script="plugin.gd"
33 changes: 12 additions & 21 deletions addons/destruction/shard.gd
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,33 @@ extends RigidBody3D
## Shard created by [Destruction].

## See [member Destruction.shrink_delay].
var shrink_delay : float
var shrink_delay: float
## See [method Destruction.destroy].
var explosion_power : float
var explosion_power: float
## See [member Destruction.fade_delay].
var fade_delay : float
var fade_delay: float
var material: Material
var shape: Shape3D
var mesh: Mesh

@onready var mesh_instance: MeshInstance3D = $MeshInstance
@onready var collision_shape: CollisionShape3D = $CollisionShape

func _ready():
mesh_instance.mesh = mesh
mesh_instance.material_override = material
collision_shape.shape = shape
if shrink_delay < 0 and fade_delay < 0:
await get_tree().create_timer(2).timeout
else:
# Both of these are required to skip the first loop due to this bug:
# https://github.com/godotengine/godot/issues/75934
await get_tree().physics_frame
await get_tree().physics_frame

var material: StandardMaterial3D = mesh_instance.mesh.surface_get_material(0)
if not material:
return
material = material.duplicate()
mesh_instance.material_override = material
material.flags_transparent = true

var tween = create_tween()

if fade_delay > 0:
tween.tween_property(material, "albedo_color", Color(1, 1, 1, 0), 2)\
.set_delay(fade_delay)\
.set_trans(Tween.TRANS_EXPO)\
.set_ease(Tween.EASE_OUT)

apply_impulse(_random_direction() * explosion_power, -position.normalized())

var tween = create_tween()
if shrink_delay > 0:
tween.parallel().tween_property(mesh_instance, "scale", Vector3.ZERO, 2)\
tween.tween_property(mesh_instance, "scale", Vector3.ZERO, 2)\
.set_delay(shrink_delay)
await tween.finished
queue_free()
Expand Down
1 change: 0 additions & 1 deletion addons/destruction/shard.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ script = ExtResource("1_c05n7")
editor_description = "Configured in the _ready function."

[node name="MeshInstance" type="MeshInstance3D" parent="."]
editor_description = "Configured in the _ready function."
Loading

0 comments on commit 6543d55

Please sign in to comment.