aboutsummaryrefslogtreecommitdiff
path: root/assets/addons/voxel-core/classes/voxel.gd
diff options
context:
space:
mode:
Diffstat (limited to 'assets/addons/voxel-core/classes/voxel.gd')
-rw-r--r--assets/addons/voxel-core/classes/voxel.gd330
1 files changed, 330 insertions, 0 deletions
diff --git a/assets/addons/voxel-core/classes/voxel.gd b/assets/addons/voxel-core/classes/voxel.gd
new file mode 100644
index 0000000..f9bc7bb
--- /dev/null
+++ b/assets/addons/voxel-core/classes/voxel.gd
@@ -0,0 +1,330 @@
+tool
+class_name Voxel, "res://addons/voxel-core/assets/classes/voxel.png"
+extends Object
+# Utility class containing various properties and methods to do with voxels.
+#
+# Voxel Schema:
+# Every voxel is a Dictionary, not every Dictionary is a voxel, only by following
+# the voxel scheme indicated below can wide varieties of voxels be produced.
+# Note that voxel dictionaries may have additions, but they must be done in such
+# a way as to respect the original structure so as to avoid conflicts.
+#
+# {
+# name : String ~ Used in VoxelSets, should always be lowercase
+# color : Color ~ Default color used for all voxel faces, if not present fallback is Transparent color
+# colors : Dictionary = { ~ Color used on a per face bases, if not present fallback is voxel color
+# Vector3.UP : Color
+# Vector3.DOWN : Color
+# Vector3.RIGHT : Color
+# Vector3.LEFT : Color
+# Vector3.FORWARD : Color
+# Vector3.BACK : Color
+# }
+# uv : Vector2 ~ Default uv position used for all voxel faces, if not present fallback is (-1.0, -1.0)
+# uvs : Dictionary = { ~ uv position used on a per face bases, if not present fallback to voxel uv
+# Vector3.UP : Vector2
+# Vector3.DOWN : Vector2
+# Vector3.RIGHT : Vector2
+# Vector3.LEFT : Vector2
+# Vector3.FORWARD : Vector2
+# Vector3.BACK : Vector2
+# }
+# metallic : float ~ Metallic value used for all voxel face's material, must be between 0.0 and 1.0 and if not present fallback is 0.0
+# specular : float ~ Specular value used for all voxel faces, must be between 0.0 and 1.0 and if not present fallback is 0.5
+# roughness : float ~ Roughness value used for all voxel faces, must be between 0.0 and 1.0 and if not present fallback is 1.0
+# energy : float ~ Emission energy value used for all voxel faces, must be between 0.0 and 16.0 and if not present fallback is 0.0
+# energy_color : Color ~ Emission color used for all voxel faces, if not present fallback is white
+# material : int ~ ID of the VoxelSet material used for this voxel, if not present fallback is -1
+# }
+#
+
+
+
+## Constants
+# Lists of all voxel faces, and their adjacent directions
+const Faces := {
+ Vector3.RIGHT: [ Vector3.FORWARD, Vector3.BACK, Vector3.DOWN, Vector3.UP ],
+ Vector3.UP: [ Vector3.LEFT, Vector3.RIGHT, Vector3.FORWARD, Vector3.BACK ],
+ Vector3.FORWARD: [ Vector3.LEFT, Vector3.RIGHT, Vector3.DOWN, Vector3.UP ],
+ Vector3.LEFT: [ Vector3.FORWARD, Vector3.BACK, Vector3.DOWN, Vector3.UP ],
+ Vector3.DOWN: [ Vector3.LEFT, Vector3.RIGHT, Vector3.FORWARD, Vector3.BACK ],
+ Vector3.BACK: [ Vector3.LEFT, Vector3.RIGHT, Vector3.DOWN, Vector3.UP ],
+}
+
+# 0.5 means that voxels will have the dimensions of 0.5 x 0.5 x 0.5
+const VoxelWorldSize := 0.5
+
+
+
+## Public Methods
+# Returns Dictionary representation of a colored voxel
+# color : Color : color to set
+# colors : Dictionary<Vector3, Color> : face colors to set
+# return : Dictionary<String, Variant> : Dictionary representing voxel
+static func colored(color : Color, colors := {}) -> Dictionary:
+ var voxel = {}
+ voxel["color"] = color
+ if not colors.empty():
+ voxel["colors"] = colors.duplicate()
+ return voxel
+
+
+# Returns true if voxel has color defined
+static func has_color(voxel : Dictionary) -> bool:
+ return voxel.has("color")
+
+
+# Returns the defined color within given voxel if present, otherwise returns transparent color
+static func get_color(voxel : Dictionary) -> Color:
+ return voxel.get("color", Color.transparent)
+
+
+# Sets the given color to the given voxel
+static func set_color(voxel : Dictionary, color : Color) -> void:
+ voxel["color"] = color
+
+
+# Returns true if voxel has specified color at given face
+static func has_face_color(voxel : Dictionary, face : Vector3) -> bool:
+ return voxel.has("colors") and voxel["colors"].has(face)
+
+
+# Returns the defined color at given face if present, otherwise returns color
+static func get_face_color(voxel : Dictionary, face : Vector3) -> Color:
+ return voxel["colors"].get(face, get_color(voxel)) if voxel.has("colors") else get_color(voxel)
+
+
+# Sets the given color at the given face to the given voxel
+static func set_face_color(voxel : Dictionary, face : Vector3, color : Color) -> void:
+ if not voxel.has("colors"): voxel["colors"] = {}
+ voxel["colors"][face] = color
+
+
+# Removes color at given face from given voxel
+static func remove_face_color(voxel : Dictionary, face : Vector3) -> void:
+ if voxel.has("colors"):
+ voxel["colors"].erase(face)
+ if voxel["colors"].empty():
+ voxel.erase("colors")
+
+
+# Returns Dictionary representation of a uvd voxel
+# uv : Vector2 : uv to set
+# uvs : Dictionary<Vector3, Vector2> : face uv to set
+# color : Color : color to set
+# colors : Dictionary<Vector3, Color> : face colors to set
+# return : Dictionary<String, Variant> : Dictionary representing voxel
+static func uvd(uv : Vector2, uvs := {}, color := Color.white, colors := {}) -> Dictionary:
+ var voxel = colored(color, colors)
+ voxel["uv"] = uv
+ if not uvs.empty():
+ voxel["uvs"] = uvs
+ return voxel
+
+
+# Returns true if voxel has uv defined
+static func has_uv(voxel : Dictionary) -> bool:
+ return voxel.has("uv")
+
+
+# Returns the defined uv within given voxel if present, otherwise returns a negative vector
+static func get_uv(voxel : Dictionary) -> Vector2:
+ return voxel.get("uv", -Vector2.ONE)
+
+
+# Sets the given uv to the given voxel
+static func set_uv(voxel : Dictionary, uv : Vector2) -> void:
+ voxel["uv"] = uv
+
+
+# Removes uv from given voxel
+static func remove_uv(voxel : Dictionary) -> void:
+ voxel.erase("uv")
+
+
+# Returns true if voxel has specified uv at given face
+static func has_face_uv(voxel : Dictionary, face : Vector3) -> bool:
+ return voxel.has("uvs") and voxel["uvs"].has(face)
+
+
+# Returns the defined uv at given face if present, otherwise returns uv
+static func get_face_uv(voxel : Dictionary, face : Vector3) -> Vector2:
+ return voxel["uvs"].get(face, get_uv(voxel)) if voxel.has("uvs") else get_uv(voxel)
+
+
+# Sets the given uv at the given face to the given voxel
+static func set_face_uv(voxel : Dictionary, face : Vector3, uv : Vector2) -> void:
+ if not voxel.has("uvs"):
+ voxel["uvs"] = {}
+ voxel["uvs"][face] = uv
+
+
+# Removes uv at given face from given voxel
+static func remove_face_uv(voxel : Dictionary, face : Vector3) -> void:
+ if voxel.has("uvs"):
+ voxel["uvs"].erase(face)
+ if voxel["uvs"].empty():
+ voxel.erase("uvs")
+
+
+# Returns true if given name is valid
+static func is_valid_name(name : String) -> bool:
+ return not name.empty()
+
+
+# Returns the defined name within given voxel if present, otherwise returns an empty string
+static func get_name(voxel : Dictionary) -> String:
+ return voxel.get("name", "")
+
+
+# Sets the given name to the given voxel
+static func set_name(voxel : Dictionary, name : String) -> void:
+ voxel["name"] = name.to_lower()
+
+
+# Removes name from given voxel
+static func remove_name(voxel : Dictionary) -> void:
+ voxel.erase("name")
+
+
+# Returns the defined metallic within given voxel if present, otherwise returns 0
+static func get_metallic(voxel : Dictionary) -> float:
+ return voxel.get("metallic", 0.0)
+
+
+# Sets the given metallic to the given voxel
+static func set_metallic(voxel : Dictionary, metallic : float) -> void:
+ voxel["metallic"] = metallic
+
+
+# Removes metallic from given voxel
+static func remove_metallic(voxel : Dictionary) -> void:
+ voxel.erase("metallic")
+
+
+# Returns the defined specular within given voxel if present, otherwise returns 0.5
+static func get_specular(voxel : Dictionary) -> float:
+ return voxel.get("specular", 0.5)
+
+
+# Sets the given specular to the given voxel
+static func set_specular(voxel : Dictionary, specular : float) -> void:
+ voxel["specular"] = specular
+
+
+# Removes specular from given voxel
+static func remove_specular(voxel : Dictionary) -> void:
+ voxel.erase("specular")
+
+
+# Returns the defined roughness within given voxel if present, otherwise returns 1
+static func get_roughness(voxel : Dictionary) -> float:
+ return voxel.get("roughness", 1.0)
+
+
+# Sets the given roughness to the given voxel
+static func set_roughness(voxel : Dictionary, roughness : float) -> void:
+ voxel["roughness"] = roughness
+
+
+# Removes roughness from given voxel
+static func remove_roughness(voxel : Dictionary) -> void:
+ voxel.erase("roughness")
+
+
+# Returns the defined energy within given voxel if present, otherwise returns 0
+static func get_energy(voxel : Dictionary) -> float:
+ return voxel.get("energy", 0.0)
+
+
+# Sets the given energy to the given voxel
+static func set_energy(voxel : Dictionary, energy : float) -> void:
+ voxel["energy"] = energy
+
+
+# Removes energy from given voxel
+static func remove_energy(voxel : Dictionary) -> void:
+ voxel.erase("energy")
+
+
+# Returns the defined energy_color within given voxel if present, otherwise returns Color.white
+static func get_energy_color(voxel : Dictionary) -> Color:
+ return voxel.get("energy_color", Color.white)
+
+
+# Sets the given energy_color to the given voxel
+static func set_energy_color(voxel : Dictionary, energy_color : Color) -> void:
+ voxel["energy_color"] = energy_color
+
+
+# Removes energy_color from given voxel
+static func remove_energy_color(voxel : Dictionary) -> void:
+ voxel.erase("energy_color")
+
+
+# Returns the defined material within given voxel if present, otherwise returns -1
+static func get_material(voxel : Dictionary) -> int:
+ return voxel.get("material", -1)
+
+
+# Sets the given material to the given voxel
+static func set_material(voxel : Dictionary, material : int) -> void:
+ voxel["material"] = material
+
+
+# Removes material from given voxel
+static func remove_material(voxel : Dictionary) -> void:
+ voxel.erase("material")
+
+
+# Removes unnecessary properties of given voxel in accordance to Voxel schema
+static func clean(voxel : Dictionary) -> void:
+ if not is_valid_name(get_name(voxel)):
+ remove_name(voxel)
+
+ if get_uv(voxel) == get_uv({}):
+ remove_uv(voxel)
+
+ for face in Faces:
+ if get_face_color(voxel, face) == get_color({}):
+ remove_face_color(voxel, face)
+ if get_face_uv(voxel, face) == get_uv({}):
+ remove_face_uv(voxel, face)
+
+ if get_material(voxel) == get_material({}):
+ remove_material(voxel)
+
+ if get_metallic(voxel) == get_metallic({}):
+ remove_metallic(voxel)
+
+ if get_specular(voxel) == get_specular({}):
+ remove_specular(voxel)
+
+ if get_roughness(voxel) == get_roughness({}):
+ remove_roughness(voxel)
+
+ if get_energy(voxel) == get_energy({}):
+ remove_energy(voxel)
+
+ if get_energy_color(voxel) == get_energy_color({}):
+ remove_energy_color(voxel)
+
+
+# Returns the world position as snapped world position
+static func world_to_snapped(world : Vector3) -> Vector3:
+ return (world / VoxelWorldSize).floor() * VoxelWorldSize
+
+
+# Returns the snapped world position as voxel grid position
+static func snapped_to_grid(snapped : Vector3) -> Vector3:
+ return snapped / VoxelWorldSize
+
+
+# Returns world position as voxel grid position
+static func world_to_grid(world : Vector3) -> Vector3:
+ return snapped_to_grid(world_to_snapped(world))
+
+
+# Returns voxel grid position as snapped world position
+static func grid_to_snapped(grid : Vector3) -> Vector3:
+ return grid * VoxelWorldSize