Moved Added PropTool.

This commit is contained in:
Relintai 2019-12-20 01:04:31 +01:00
parent 35c8845205
commit df438053eb
14 changed files with 732 additions and 0 deletions

12
README.md Normal file
View File

@ -0,0 +1,12 @@
# Prop Tool
This is an addon for https://github.com/Relintai/voxelman, to help with creating/editing props.
Props are 3d obects in the world, they can contain lights (VoxelmanLight), meshes (MehDataResorce), and other Props, and scenes.
VoxelmanLights are precalculated lights inside the cunks.
MeshDataResources exists, because you cannot access mesh data in gles2 from normal meshes. Voxelman merges all meshes that you add like this automatically.
Looks like this:
![prop_tool screenshot](screenshots/prop_tool.png)

View File

@ -0,0 +1,3 @@
tool
extends Entity

View File

@ -0,0 +1,17 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://data/models/armature_model_orig_v2.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/prop_tool/player/PropToolDisplayPlayer.gd" type="Script" id=2]
[node name="DisplayPlayer" type="Entity" groups=[
"players",
]]
input_ray_pickable = false
collision_layer = 3
collision_mask = 3
character_skeleton_path = NodePath("character")
script = ExtResource( 2 )
[node name="character" parent="." instance=ExtResource( 1 )]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00126277, 0.085327, -0.000325084 )
use_threads = false

7
plugin.cfg Normal file
View File

@ -0,0 +1,7 @@
[plugin]
name="Prop Tool"
description=""
author="Relintai"
version=""
script="plugin.gd"

280
plugin.gd Normal file
View File

@ -0,0 +1,280 @@
tool
extends EditorPlugin
const main_scene_path : String = "res://addons/prop_tool/scenes/main.tscn"
const temp_scene_path : String = "res://addons/prop_tool/scenes/main_temp.tscn"
const temp_path : String = "res://addons/prop_tool/scenes/temp/"
var buttons_added : bool = false
var light_button : ToolButton
var mesh_button : ToolButton
var prop_button : ToolButton
var scene_button : ToolButton
var entity_button : ToolButton
var edited_prop : PropData
func _enter_tree():
var dir : Directory = Directory.new()
dir.copy(main_scene_path, temp_scene_path)
light_button = ToolButton.new()
light_button.text = "Light"
light_button.connect("pressed", self, "add_light")
mesh_button = ToolButton.new()
mesh_button.text = "Mesh"
mesh_button.connect("pressed", self, "add_mesh")
prop_button = ToolButton.new()
prop_button.text = "Prop"
prop_button.connect("pressed", self, "add_prop")
scene_button = ToolButton.new()
scene_button.text = "Scene"
scene_button.connect("pressed", self, "add_scene")
entity_button = ToolButton.new()
entity_button.text = "Entity"
entity_button.connect("pressed", self, "add_entity")
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, light_button)
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, mesh_button)
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, prop_button)
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, scene_button)
add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, entity_button)
light_button.hide()
mesh_button.hide()
prop_button.hide()
scene_button.hide()
entity_button.hide()
connect("scene_changed", self, "scene_changed")
func _exit_tree():
var dir : Directory = Directory.new()
dir.remove(temp_scene_path)
if is_instance_valid(light_button):
light_button.queue_free()
if is_instance_valid(mesh_button):
mesh_button.queue_free()
if is_instance_valid(prop_button):
prop_button.queue_free()
if is_instance_valid(scene_button):
scene_button.queue_free()
if is_instance_valid(entity_button):
entity_button.queue_free()
light_button = null
mesh_button = null
prop_button = null
scene_button = null
entity_button = null
edited_prop = null
disconnect("scene_changed", self, "scene_changed")
func scene_changed(scene):
if scene.has_method("set_target_prop"):
scene.plugin = self
if not buttons_added:
light_button.show()
mesh_button.show()
prop_button.show()
scene_button.show()
entity_button.show()
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, light_button)
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, mesh_button)
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, prop_button)
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, scene_button)
# add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, entity_button)
buttons_added = true
else:
if buttons_added:
light_button.hide()
mesh_button.hide()
prop_button.hide()
scene_button.hide()
entity_button.hide()
#
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, light_button)
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, mesh_button)
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, prop_button)
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, scene_button)
# remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, entity_button)
buttons_added = false
func apply_changes() -> void:
var scene : Node = get_editor_interface().get_edited_scene_root()
if scene is PropTool:
# if scene.has_method("set_target_prop") and scene.has_method("save"):
scene.save()
func edit(object : Object) -> void:
var pedited_prop = object as PropData
var p : String = create_or_get_scene_path(pedited_prop)
get_editor_interface().open_scene_from_path(p)
func handles(object : Object) -> bool:
return object is PropData
func add_light():
var selection : Array = get_editor_interface().get_selection().get_selected_nodes()
var selected : Node
if selection.size() != 1:
selected = get_editor_interface().get_edited_scene_root()
else:
selected = selection[0]
var s : Node = selected
var n = PropToolLight.new()
var u : UndoRedo = get_undo_redo()
u.create_action("Add Light")
u.add_do_method(s, "add_child", n)
u.add_do_property(n, "owner", get_editor_interface().get_edited_scene_root())
u.add_undo_method(s, "remove_child", n)
u.commit_action()
get_editor_interface().get_selection().clear()
get_editor_interface().get_selection().add_node(n)
func add_mesh():
var selected : Array = get_editor_interface().get_selection().get_selected_nodes()
if selected.size() != 1:
return
var s : Node = selected[0]
var n = PropToolMesh.new()
var u : UndoRedo = get_undo_redo()
u.create_action("Add Mesh")
u.add_do_method(s, "add_child", n)
u.add_do_property(n, "owner", get_editor_interface().get_edited_scene_root())
u.add_undo_method(s, "remove_child", n)
u.commit_action()
get_editor_interface().get_selection().clear()
get_editor_interface().get_selection().add_node(n)
func add_prop():
var selected : Array = get_editor_interface().get_selection().get_selected_nodes()
if selected.size() != 1:
return
var s : Node = selected[0]
var n = PropTool.new()
var u : UndoRedo = get_undo_redo()
u.create_action("Add Prop")
u.add_do_method(s, "add_child", n)
u.add_do_property(n, "owner", get_editor_interface().get_edited_scene_root())
u.add_undo_method(s, "remove_child", n)
u.commit_action()
get_editor_interface().get_selection().clear()
get_editor_interface().get_selection().add_node(n)
func add_scene():
var selected : Array = get_editor_interface().get_selection().get_selected_nodes()
if selected.size() != 1:
return
var s : Node = selected[0]
var n = PropToolScene.new()
var u : UndoRedo = get_undo_redo()
u.create_action("Add Scene")
u.add_do_method(s, "add_child", n)
u.add_do_property(n, "owner", get_editor_interface().get_edited_scene_root())
u.add_undo_method(s, "remove_child", n)
u.commit_action()
get_editor_interface().get_selection().clear()
get_editor_interface().get_selection().add_node(n)
func add_entity():
var selected : Array = get_editor_interface().get_selection().get_selected_nodes()
if selected.size() != 1:
return
var s : Node = selected[0]
var n = PropToolEntity.new()
var u : UndoRedo = get_undo_redo()
u.create_action("Add Entity")
u.add_do_method(s, "add_child", n)
u.add_do_property(n, "owner", get_editor_interface().get_edited_scene_root())
u.add_undo_method(s, "remove_child", n)
u.commit_action()
get_editor_interface().get_selection().clear()
get_editor_interface().get_selection().add_node(n)
func create_or_get_scene_path(data: PropData) -> String:
var path : String = temp_path + data.resource_path.get_file().get_basename() + ".tscn"
var dir : Directory = Directory.new()
if not dir.file_exists(path):
create_scene(data)
return path
func create_or_get_scene(data: PropData) -> PropTool:
if data == null:
print("PropTool plugin.gd: Data is null!")
return null
var path : String = temp_path + data.resource_path.get_file().get_basename() + ".tscn"
var dir : Directory = Directory.new()
var ps : PackedScene
if not dir.file_exists(path):
ps = create_scene(data)
else:
ps = ResourceLoader.load(path, "PackedScene")
if ps == null:
return null
var pt : PropTool = ps.instance() as PropTool
pt.plugin = self
return pt
func create_scene(data: PropData) -> PackedScene:
var pt : PropTool = PropTool.new()
pt.plugin = self
pt.set_target_prop(data)
var ps : PackedScene = PackedScene.new()
ps.pack(pt)
var err = ResourceSaver.save(temp_path + data.resource_path.get_file().get_basename() + ".tscn", ps)
pt.queue_free()
return ps

1
scenes/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
main_temp.tscn

6
scenes/main.tscn Normal file
View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/prop_tool/tools/PropTool.gd" type="Script" id=1]
[node name="PropTool" type="Spatial"]
script = ExtResource( 1 )

1
scenes/temp/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.tscn

152
tools/PropTool.gd Normal file
View File

@ -0,0 +1,152 @@
tool
extends Spatial
class_name PropTool
export(bool) var refresh : bool setget refresh_set
export(PropData) var target_prop : PropData setget target_prop_set
export(bool) var snap_to_mesh : bool = false
export(Vector3) var snap_axis : Vector3 = Vector3(0, -1, 0)
var plugin : EditorPlugin
func save() -> void:
if target_prop == null:
return
print("save " + target_prop.resource_path)
while target_prop.get_prop_count() > 0:
target_prop.remove_prop(0)
for child in get_children():
save_node(child, transform)
target_prop.snap_to_mesh = snap_to_mesh
target_prop.snap_axis = snap_axis
ResourceSaver.save(target_prop.resource_path, target_prop)
func save_node(node : Node, parent_transform: Transform) -> void:
if node is Spatial and node.has_method("get_data"):
var prop : PropDataEntry = node.get_data()
if prop:
prop.transform = parent_transform * (node as Spatial).transform
target_prop.add_prop(prop)
if node.has_method("evaluate_children") and not node.evaluate_children():
return
for child in node.get_children():
save_node(child, parent_transform * node.transform)
else:
if node.has_method("set_target_prop"):
if node.target_prop:
var prop : PropDataProp = PropDataProp.new()
prop.prop = node.target_prop
prop.transform = parent_transform * (node as Spatial).transform
target_prop.add_prop(prop)
else:
for child in node.get_children():
save_node(child, parent_transform)
func rebuild_hierarchy() -> void:
for ch in get_children():
ch.queue_free()
if target_prop == null:
return
snap_to_mesh = target_prop.snap_to_mesh
snap_axis = target_prop.snap_axis
for i in range(target_prop.get_prop_count()):
print(i)
var prop : PropDataEntry = target_prop.get_prop(i)
if prop is PropDataLight:
var l : PropToolLight = PropToolLight.new()
add_child(l)
l.owner = self
l.transform = prop.transform
l.set_data(prop as PropDataLight)
elif prop is PropDataMesh:
var m : PropToolMesh = PropToolMesh.new()
add_child(m)
m.owner = self
m.transform = prop.transform
m.set_data(prop as PropDataMesh)
elif prop is PropDataScene:
var s : PropToolScene = PropToolScene.new()
add_child(s)
s.owner = self
s.transform = prop.transform
s.set_data(prop as PropDataScene)
elif prop is PropDataProp:
var s : Node = plugin.create_or_get_scene(prop.prop)
add_child(s)
s.owner = self
s.transform = prop.transform
# s.set_target_prop(prop.prop)
elif prop is PropDataEntity:
var s : PropToolEntity = PropToolEntity.new()
add_child(s)
s.owner = self
s.transform = prop.transform
s.set_data(prop as PropDataEntity)
func refresh_set(value):
if value:
rebuild_hierarchy()
func set_target_prop(prop: PropData) -> void:
# if prop == null:
# return
target_prop = prop
rebuild_hierarchy()
func get_plugin():
return plugin
func target_prop_set(prop: PropData) -> void:
target_prop = prop
if prop == null:
return
var last_prop_tool : PropTool = self
var root : Node = self
while root.get_parent() != null:
root = root.get_parent()
if root and root.has_method("target_prop_set"):
last_prop_tool = root as PropTool
if last_prop_tool == self:
return
last_prop_tool.load_scene_for(self, prop)
func load_scene_for(t: PropTool, prop: PropData):
if not plugin:
return
t.queue_free()
var s : Node = plugin.create_or_get_scene(prop)
add_child(s)
s.owner = self

71
tools/PropToolEntity.gd Normal file
View File

@ -0,0 +1,71 @@
tool
extends Spatial
class_name PropToolEntity
export(EntityData) var entity_data : EntityData setget set_entity_data
export(int) var entity_data_id : int
export(int) var level : int = 1
var _prop_entity : PropDataEntity
var _entity : Entity
func get_data() -> PropDataEntity:
if not visible or entity_data == null:
return null
if _prop_entity == null:
_prop_entity = PropDataEntity.new()
_prop_entity.entity_data_id = entity_data.id
_prop_entity.level = level
return _prop_entity
func set_data(scene: PropDataEntity) -> void:
_prop_entity = scene
entity_data_id = _prop_entity.entity_data_id
level = _prop_entity.level
var dir = Directory.new()
if dir.open("res://data/entities/") == OK:
dir.list_dir_begin()
var file_name = dir.get_next()
while (file_name != ""):
if not dir.current_is_dir():
var ed : EntityData = ResourceLoader.load("res://data/entities/" + file_name, "EntityData")
if ed != null and ed.id == entity_data_id:
set_entity_data(ed)
return
file_name = dir.get_next()
print("PropToolEntity: Entity not found!")
func set_entity_data(ed: EntityData) -> void:
entity_data = ed
if entity_data == null:
return
if _entity == null:
var scene : PackedScene = load("res://addons/prop_tool/player/PropToolDisplayPlayer.tscn")
_entity = scene.instance() as Entity
add_child(_entity)
# _entity.owner = owner
# _entity.get_node(_entity.character_skeleton_path).owner = owner
_entity.get_node(_entity.character_skeleton_path).refresh_in_editor = true
# _entity.get_character_skeleton().refresh_in_editor = true
_entity.sentity_data = entity_data
name = entity_data.text_name
func evaluate_children() -> bool:
return false

36
tools/PropToolLight.gd Normal file
View File

@ -0,0 +1,36 @@
tool
extends OmniLight
class_name PropToolLight
var _prop_light : PropDataLight
#func _ready():
# set_notify_transform(true)
func get_data() -> PropDataLight:
if not visible:
return null
if _prop_light == null:
_prop_light = PropDataLight.new()
_prop_light.light_color = light_color
_prop_light.light_size = omni_range
return _prop_light
func set_data(light : PropDataLight) -> void:
_prop_light = light
light_color = _prop_light.light_color
omni_range = _prop_light.light_size
light_energy = _prop_light.light_size
#func save():
# if get_node("..").has_method("save"):
# get_node("..").save()
#
#func _notification(what):
# if what == NOTIFICATION_TRANSFORM_CHANGED:
# save()

84
tools/PropToolMesh.gd Normal file
View File

@ -0,0 +1,84 @@
tool
extends MeshInstance
class_name PropToolMesh
export(MeshDataResource) var mesh_data : MeshDataResource setget set_prop_mesh
export(Texture) var texture : Texture setget set_texture
export(bool) var snap_to_mesh : bool = false
export(Vector3) var snap_axis : Vector3 = Vector3(0, -1, 0)
export(bool) var generate : bool setget set_generate
var _prop_mesh : PropDataMesh
var _material : SpatialMaterial
func get_data() -> PropDataMesh:
if not visible or mesh_data == null:
return null
if _prop_mesh == null:
_prop_mesh = PropDataMesh.new()
_prop_mesh.mesh = mesh_data
_prop_mesh.texture = texture
_prop_mesh.snap_to_mesh = snap_to_mesh
_prop_mesh.snap_axis = snap_axis
return _prop_mesh
func set_data(data : PropDataMesh) -> void:
_prop_mesh = data
set_texture(_prop_mesh.texture)
set_prop_mesh(_prop_mesh.mesh)
snap_to_mesh = _prop_mesh.snap_to_mesh
snap_axis = _prop_mesh.snap_axis
func set_prop_mesh(md : MeshDataResource) -> void:
mesh_data = md
set_generate(true)
func set_texture(tex : Texture) -> void:
texture = tex
func set_generate(val : bool) -> void:
if val:
if !mesh_data:
mesh = null
return
var m : ArrayMesh = ArrayMesh.new()
var arr = []
arr.resize(ArrayMesh.ARRAY_MAX)
var v : PoolVector3Array = PoolVector3Array()
v.append_array(mesh_data.array[Mesh.ARRAY_VERTEX])
arr[Mesh.ARRAY_VERTEX] = v
var norm : PoolVector3Array = PoolVector3Array()
norm.append_array(mesh_data.array[Mesh.ARRAY_NORMAL])
arr[Mesh.ARRAY_NORMAL] = norm
var uv : PoolVector2Array = PoolVector2Array()
uv.append_array(mesh_data.array[Mesh.ARRAY_TEX_UV])
arr[Mesh.ARRAY_TEX_UV] = uv
var ind : PoolIntArray = PoolIntArray()
ind.append_array(mesh_data.array[Mesh.ARRAY_INDEX])
arr[Mesh.ARRAY_INDEX] = ind
m.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr)
mesh = m
if texture != null:
if _material == null:
_material = SpatialMaterial.new()
_material.albedo_texture = texture
material_override = _material

32
tools/PropToolProp.gd Normal file
View File

@ -0,0 +1,32 @@
tool
extends Spatial
class_name PropToolProp
export(PropData) var prop_data : PropData
export(bool) var snap_to_mesh : bool = false
export(Vector3) var snap_axis : Vector3 = Vector3(0, -1, 0)
var _prop_prop : PropDataProp
func get_data() -> PropDataProp:
if not visible or prop_data == null:
return null
if _prop_prop == null:
_prop_prop = PropDataProp.new()
_prop_prop.prop = prop_data
_prop_prop.snap_to_mesh = snap_to_mesh
_prop_prop.snap_axis = snap_axis
return _prop_prop
func set_data(prop: PropDataProp) -> void:
_prop_prop = prop
prop_data = _prop_prop.prop
snap_to_mesh = prop_data.snap_to_mesh
snap_axis = prop_data.snap_axis
func refresh() -> void:
return

30
tools/PropToolScene.gd Normal file
View File

@ -0,0 +1,30 @@
tool
extends Spatial
class_name PropToolScene
export(PackedScene) var scene_data : PackedScene
export(bool) var snap_to_mesh : bool = false
export(Vector3) var snap_axis : Vector3 = Vector3(0, -1, 0)
var _prop_scene : PropDataScene
func get_data() -> PropDataScene:
if not visible or scene_data == null:
return null
if _prop_scene == null:
_prop_scene = PropDataScene.new()
_prop_scene.scene = scene_data
_prop_scene.snap_to_mesh = snap_to_mesh
_prop_scene.snap_axis = snap_axis
return _prop_scene
func set_data(scene: PropDataScene) -> void:
_prop_scene = scene
scene_data = _prop_scene.scene
snap_to_mesh = _prop_scene.snap_to_mesh
snap_axis = _prop_scene.snap_axis