aboutsummaryrefslogtreecommitdiff
path: root/addons/voxel-core/classes/voxel_set.gd
diff options
context:
space:
mode:
authorjacopograndi <jacopo.grandi@outlook.it>2021-12-09 00:52:59 +0100
committerjacopograndi <jacopo.grandi@outlook.it>2021-12-09 00:52:59 +0100
commit0f518727c28d3204415db14c7ca0e4f7cb653677 (patch)
treea595121771b69a52f17154d8e5c61b7e4b2b8190 /addons/voxel-core/classes/voxel_set.gd
working
Diffstat (limited to 'addons/voxel-core/classes/voxel_set.gd')
-rw-r--r--addons/voxel-core/classes/voxel_set.gd234
1 files changed, 234 insertions, 0 deletions
diff --git a/addons/voxel-core/classes/voxel_set.gd b/addons/voxel-core/classes/voxel_set.gd
new file mode 100644
index 0000000..d0bccac
--- /dev/null
+++ b/addons/voxel-core/classes/voxel_set.gd
@@ -0,0 +1,234 @@
+tool
+class_name VoxelSet, "res://addons/voxel-core/assets/classes/voxel_set.png"
+extends Resource
+# Library of Voxels used by VoxelObjects.
+
+
+
+## Signals
+# Emitted on request_refresh
+signal requested_refresh
+
+
+
+## Exported Variables
+# Size of each tile in tiles in pixels
+export var tile_size := Vector2(32.0, 32.0) setget set_tile_size
+
+# Texture used for tiles / uv mapping
+export var tiles : Texture = null setget set_tiles
+
+# Materials used by voxels
+export(Array, Material) var materials := [
+ SpatialMaterial.new(),
+] setget set_materials
+
+
+
+## Private Variables
+# Voxels stored by their id
+var _voxels := []
+
+# Flag indicating whether _uv_scale, tile_size and tiles texture is set
+var _uv_ready := false
+
+# World UV Scale, calculated on request_refresh
+var _uv_scale := Vector2.ONE
+
+
+
+## Built-In Virtual Methods
+func _get(property : String):
+ if property == "VOXELS":
+ return _voxels
+
+
+func _set(property : String, value) -> bool:
+ if property == "VOXELS":
+ if typeof(value) == TYPE_DICTIONARY:
+ for key in value:
+ var voxel : Dictionary = value[key]
+ if voxel.has("vsn"):
+ Voxel.set_name(voxel, voxel["vsn"])
+ voxel.erase("vsn")
+ _voxels.append(value[key])
+ else:
+ _voxels = value
+ return true
+ return false
+
+
+func _get_property_list():
+ var properties = []
+
+ properties.append({
+ "name": "VOXELS",
+ "type": TYPE_ARRAY,
+ "hint": PROPERTY_HINT_NONE,
+ "usage": PROPERTY_USAGE_STORAGE,
+ })
+
+ return properties
+
+
+
+## Public Methods
+# Sets tile_size, calls on request_refresh by default
+func set_tile_size(value : Vector2, refresh := true) -> void:
+ tile_size = Vector2(
+ floor(clamp(value.x, 1, 256)),
+ floor(clamp(value.y, 1, 256)))
+
+ if refresh:
+ request_refresh()
+
+
+# Sets tiles, calls on request_refresh by default
+func set_tiles(value : Texture, refresh := true) -> void:
+ tiles = value
+
+ if refresh:
+ request_refresh()
+
+
+# Sets materials used by voxels in VoxelSet
+func set_materials(values : Array, refresh := true) -> void:
+ for index in range(values.size()):
+ var material = values[index]
+ if is_instance_valid(material) and not (material is SpatialMaterial or material is ShaderMaterial):
+ printerr("VoxelSet : Expected Spatial or Shader material got " + str(material))
+ values[index] = null
+
+ if values.empty():
+ materials.resize(1)
+ else:
+ materials = values
+ property_list_changed_notify()
+
+ if refresh:
+ request_refresh()
+
+
+# Returns VoxelSet material with id if present, otherwise returns null
+func get_material(id : int) -> Material:
+ return materials[id] if id > -1 and id < materials.size() else null
+
+
+# Returns number of voxels in VoxelSet
+func size() -> int:
+ return _voxels.size()
+
+
+# Returns true if VoxelSet has no voxels
+func empty() -> bool:
+ return _voxels.empty()
+
+
+# Returns true if VoxelSet has voxel with given id
+func has_id(id : int) -> bool:
+ return id > -1 and id < _voxels.size()
+
+
+# Returns true if VoxelSet has everything necessary for uv mapping
+func uv_ready() -> bool:
+ return _uv_ready
+
+
+# Returns the uv scale
+func uv_scale() -> Vector2:
+ return _uv_scale
+
+
+# Returns true if given id is valid
+static func is_valid_id(id : int) -> bool:
+ return id > -1
+
+
+# Returns a list of all the voxel ids
+# returns : Array<int> : contained voxel ids
+func get_ids() -> Array:
+ return range(_voxels.size())
+
+
+# Returns name associated with the given id, returns a empty string if id isn't found
+func id_to_name(id : int) -> String:
+ return Voxel.get_name(get_voxel(id))
+
+
+# Returns the id of the voxel with the given name, returns -1 if not found
+func name_to_id(name : String) -> int:
+ name = name.to_lower()
+ for id in get_ids():
+ if id_to_name(id) == name:
+ return id
+ return -1
+
+
+# Appends voxel to end of VoxelSet
+func add_voxel(voxel : Dictionary) -> void:
+ _voxels.append(voxel)
+
+
+# Sets the voxel at given id
+func set_voxel(id : int, voxel : Dictionary) -> void:
+ if not has_id(id):
+ printerr("VoxelSet : given id `" + str(id) + "` is out of range")
+ return
+
+ _voxels[id] = voxel
+
+
+# Insert voxel with given id
+func insert_voxel(id : int, voxel : Dictionary) -> void:
+ if id < -1 and id > _voxels.size():
+ printerr("VoxelSet : given id `" + str(id) + "` is out of range")
+ return
+
+ _voxels.insert(id, voxel)
+
+
+# Replaces all _voxels
+func set_voxels(voxels : Array) -> void:
+ _voxels = voxels
+
+
+# Gets voxel Dictionary by their id, returns an empty Dictionary if not found
+func get_voxel(id : int) -> Dictionary:
+ return _voxels[id] if has_id(id) else {}
+
+
+# Erase voxel from VoxelSet
+func erase_voxel(id : int) -> void:
+ _voxels.remove(id)
+
+
+# Erases all voxels in VoxelSet
+func erase_voxels() -> void:
+ _voxels.clear()
+
+
+# Should be called when noticable changes have been committed to voxels.
+# Emits requested_refresh, calculates _uv_scale and updates _uv_ready
+func request_refresh() -> void:
+ _uv_ready = is_instance_valid(tiles)
+ if _uv_ready:
+ _uv_scale = Vector2.ONE / (tiles.get_size() / tile_size)
+ else:
+ _uv_scale = Vector2.ONE
+ emit_signal("requested_refresh")
+
+
+# Loads file's content as voxels
+# NOTE: Reference Reader.gd for valid file imports
+# source_file : String : Path to file to be loaded
+# return int : int : Error code
+func load_file(source_file : String, append := false) -> int:
+ var read := Reader.read_file(source_file)
+ var error : int = read.get("error", FAILED)
+ if error == OK:
+ if append:
+ for voxel in read["palette"]:
+ add_voxel(voxel)
+ else:
+ set_voxels(read["palette"])
+ return error