Add updating of node properties and node selection
This commit is contained in:
parent
9830aa00ea
commit
c27ad8ccc9
2 changed files with 134 additions and 22 deletions
|
@ -13,7 +13,6 @@ func node_to_tree(node, root=false):
|
|||
n["type"] = node.get_class()
|
||||
n["index"] = node.get_index()
|
||||
n["path"] = "/" + node.get_path().get_concatenated_names()
|
||||
print(n)
|
||||
var c = []
|
||||
for i in node.get_children():
|
||||
c.append(node_to_tree(i))
|
||||
|
@ -21,6 +20,47 @@ func node_to_tree(node, root=false):
|
|||
n["children"] = c
|
||||
return n
|
||||
|
||||
func node_to_props(node):
|
||||
var n = {}
|
||||
n["name"] = node.name
|
||||
n["type"] = node.get_class()
|
||||
n["path"] = "/" + node.get_path().get_concatenated_names()
|
||||
n["props"] = []
|
||||
var props = node.get_property_list()
|
||||
var i = 0
|
||||
# NOTE: I cannot begin to fathom the reasons for why this shit is done
|
||||
# the way that it is, but this is bordering on an exercise
|
||||
# in pure futility at this stage.
|
||||
while i < len(props):
|
||||
var p = props[i]
|
||||
if p["usage"] & 128 == 128:
|
||||
var cat = {}
|
||||
cat["name"] = p["name"]
|
||||
cat["props"] = []
|
||||
|
||||
if i == len(props) - 1:
|
||||
break
|
||||
|
||||
i += 1
|
||||
|
||||
while i < len(props):
|
||||
p = props[i]
|
||||
if p["usage"] & 128 == 128:
|
||||
break
|
||||
if p["usage"] & 4 == 4:
|
||||
var c = {}
|
||||
c["name"] = p["name"]
|
||||
c["value"] = node.get(p["name"])
|
||||
cat["props"].append(c)
|
||||
i += 1
|
||||
|
||||
n["props"].append(cat)
|
||||
else:
|
||||
print(p["name"], " ", p["usage"])
|
||||
break
|
||||
n["props"].reverse()
|
||||
return n
|
||||
|
||||
func parse_command(str: String, peer: StreamPeerTCP):
|
||||
var cmd = JSON.parse_string(str)
|
||||
print(cmd)
|
||||
|
@ -28,20 +68,41 @@ func parse_command(str: String, peer: StreamPeerTCP):
|
|||
"open-scene":
|
||||
print("Opening")
|
||||
EditorInterface.open_scene_from_path(cmd["scene"])
|
||||
|
||||
"select-node":
|
||||
var n = get_node(NodePath(cmd["path"]))
|
||||
EditorInterface.edit_node(n)
|
||||
|
||||
"get-scene-tree":
|
||||
var result = node_to_tree(EditorInterface.get_edited_scene_root(), true)
|
||||
var result = node_to_props(EditorInterface.get_selection().get_selected_nodes()[0])
|
||||
result = JSON.stringify({"for-cmd": "get-selected-node", "value": result})
|
||||
peer.put_data(result.to_utf8_buffer())
|
||||
|
||||
# TODO: this is terrible
|
||||
await get_tree().create_timer(0.05).timeout
|
||||
|
||||
result = node_to_tree(EditorInterface.get_edited_scene_root(), true)
|
||||
result = JSON.stringify({"for-cmd": "get-scene-tree", "value": result})
|
||||
peer.put_data(result.to_utf8_buffer())
|
||||
|
||||
"set-node-name":
|
||||
var n = get_node(NodePath(cmd["path"]))
|
||||
var new_name = cmd["new-name"]
|
||||
print("setting ", n, "'s name as ", new_name)
|
||||
n.name = new_name
|
||||
|
||||
"update-property":
|
||||
var n = get_node(NodePath(cmd["path"]))
|
||||
var prop = cmd["name"]
|
||||
var val = cmd ["new-value"]
|
||||
|
||||
n.set(prop, val)
|
||||
|
||||
_:
|
||||
print("Not a valid command: ", cmd["command"])
|
||||
|
||||
if cmd["command"] != "get-scene-tree":
|
||||
parse_command(JSON.stringify({"command": "get-scene-tree"}), peer)
|
||||
if cmd["command"] != "get-scene-tree":
|
||||
await parse_command(JSON.stringify({"command": "get-scene-tree"}), peer)
|
||||
|
||||
func _enter_tree() -> void:
|
||||
server = TCPServer.new()
|
||||
|
|
87
godot-rc.el
87
godot-rc.el
|
@ -39,6 +39,9 @@
|
|||
(defvar godot-rc-selected-scene nil
|
||||
"The currently selected scene - set automatically when visiting a .tscn file.")
|
||||
|
||||
(defvar godot-rc-selected-node nil
|
||||
"The JSON representation of the selected node.")
|
||||
|
||||
(defvar godot-rc-process nil
|
||||
"The network process for the remote control connection.")
|
||||
|
||||
|
@ -56,8 +59,11 @@
|
|||
|
||||
(defun godot-rc-process-filter-function (proc resp)
|
||||
"Handle RESP responses from the Godot PROC."
|
||||
(message (format "%s" proc))
|
||||
(let ((response (json-parse-string resp :object-type 'plist :array-type 'list)))
|
||||
(cond
|
||||
((equal "get-selected-node" (plist-get response :for-cmd))
|
||||
(setq godot-rc-selected-node (plist-get response :value)))
|
||||
((equal "get-scene-tree" (plist-get response :for-cmd))
|
||||
(scene-tree-render (plist-get response :value))))))
|
||||
|
||||
|
@ -87,63 +93,108 @@
|
|||
;; TODO: this needs to check if file-name is in the godot-rc-project-root and turn it into a res:// path
|
||||
(defun godot-rc-open-scene (file-name &optional quiet)
|
||||
"Open FILE-NAME as a scene in Godot."
|
||||
(godot-rc-send-command `(:command "open-scene" :scene ,file-name :get-result ,(if quiet :false t)))
|
||||
(setq godot-rc-selected-scene file-name))
|
||||
(when (not (equal file-name godot-rc-selected-scene))
|
||||
(godot-rc-send-command `(:command "open-scene" :scene ,file-name :get-result ,(if quiet :false t)))
|
||||
(setq godot-rc-selected-scene file-name)))
|
||||
|
||||
(defun tscn-check-visibility (win)
|
||||
(defun tscn-check-visibility (&optional win)
|
||||
"When WIN changes to a TSCN, tell Godot to open the scene."
|
||||
(let ((buf (current-buffer)))
|
||||
(when (equal (file-name-extension (buffer-file-name buf)) "tscn")
|
||||
(godot-rc-open-scene (buffer-file-name buf)))))
|
||||
|
||||
(add-hook 'find-file-hook #'tscn-check-visibility)
|
||||
(add-hook 'window-buffer-change-functions #'tscn-check-visibility)
|
||||
(add-hook 'window-selection-change-functions #'tscn-check-visibility)
|
||||
|
||||
;;; Scene-tree-mode and relevant commands
|
||||
(defclass scene-tree-node-property-section (magit-section)
|
||||
((prop-name :initform nil))
|
||||
"A `magit-section' used by `scene-tree-mode'")
|
||||
|
||||
(defclass scene-tree-node-section (magit-section)
|
||||
(;(keymap :initform 'org-roam-node-map)
|
||||
( ;(keymap :initform 'org-roam-node-map)
|
||||
(node :initform nil))
|
||||
"A `magit-section' used by `org-roam-mode' to outline NODE in its own heading.")
|
||||
"A `magit-section' used by `scene-tree-mode'.")
|
||||
|
||||
(defun insert-node (node depth)
|
||||
"Insert a NODE and it's children as magit sections."
|
||||
(magit-insert-section (scene-tree-node-section node)
|
||||
(magit-insert-heading (concat
|
||||
(make-string (* depth 2) ?\s)
|
||||
(propertize (plist-get node :name) 'face 'font-lock-function-call-face)
|
||||
(propertize (plist-get node :name) 'face `(:inherit font-lock-function-call-face
|
||||
:underline ,(equal (plist-get node :path)
|
||||
(plist-get godot-rc-selected-node :path))))
|
||||
" : "
|
||||
(propertize (plist-get node :type) 'face 'font-lock-type-face)
|
||||
"\n"))
|
||||
(dolist (n (plist-get node :children))
|
||||
(insert-node n (+ 1 depth)))))
|
||||
|
||||
(defun insert-node-property-category (category)
|
||||
"Insert a node CATEGORY as a magit section."
|
||||
(magit-insert-section (magit-section)
|
||||
(magit-insert-heading (propertize (plist-get category :name) 'face 'font-lock-constant-face))
|
||||
(dolist (n (plist-get category :props))
|
||||
(insert-node-property n))))
|
||||
|
||||
(defun insert-node-property (property)
|
||||
"Insert a node PROPERTY as a magit section."
|
||||
(magit-insert-section (scene-tree-node-property-section (plist-get property :name))
|
||||
(magit-insert-heading (concat
|
||||
" "
|
||||
(propertize (plist-get property :name) 'face 'font-lock-variable-use-face)
|
||||
" = "
|
||||
(format "%s" (plist-get property :value))))))
|
||||
|
||||
(defun scene-tree-render (tree)
|
||||
"Render the scene tree."
|
||||
(with-current-buffer godot-rc-scene-tree-buffer
|
||||
(let ((inhibit-read-only t))
|
||||
(let ((l (line-number-at-pos))
|
||||
(inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(magit-insert-section (magit-section "SceneTree")
|
||||
(magit-insert-heading (file-name-nondirectory godot-rc-selected-scene)
|
||||
"\n\n")
|
||||
(insert-node tree 0))
|
||||
(goto-char 0))))
|
||||
(insert "\n\n")
|
||||
(magit-insert-section (magit-section "NodeProperties")
|
||||
(magit-insert-heading (format "%s | Properties\n"
|
||||
(plist-get godot-rc-selected-node :name)))
|
||||
|
||||
(defun scene-tree-rename-at-point (name)
|
||||
(dolist (n (plist-get godot-rc-selected-node :props))
|
||||
(insert-node-property-category n)))
|
||||
(goto-line l))))
|
||||
|
||||
(defun scene-tree-update-property-at-point (new-value)
|
||||
"Update the property at point to be NEW-VALUE."
|
||||
(interactive "xNew value: ")
|
||||
(godot-rc-send-command
|
||||
`(:command "update-property"
|
||||
:path ,(plist-get godot-rc-selected-node :path)
|
||||
:name ,(slot-value (magit-current-section) 'value)
|
||||
:new-value ,new-value)))
|
||||
|
||||
(defun scene-tree-interact-at-point ()
|
||||
"Rename node at point."
|
||||
(interactive "sNew name: ")
|
||||
(let ((node-path (plist-get (slot-value (magit-current-section) 'value) :path)))
|
||||
(godot-rc-send-command `(:command "set-node-name" :path ,node-path :new-name ,name))))
|
||||
(interactive)
|
||||
(cond
|
||||
((scene-tree-node-section-p (magit-current-section))
|
||||
(let ((node-path (plist-get (slot-value (magit-current-section) 'value) :path)))
|
||||
(godot-rc-send-command `(:command "select-node" :path ,node-path))))
|
||||
((scene-tree-node-property-section-p (magit-current-section))
|
||||
(call-interactively 'scene-tree-update-property-at-point))))
|
||||
|
||||
(defvar scene-tree-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map magit-section-mode-map)
|
||||
(define-key map [C-return] 'scene-tree-rename-at-point)
|
||||
map
|
||||
"Keymap for scene-tree-mode"))
|
||||
(define-key map [return] 'scene-tree-interact-at-point)
|
||||
map)
|
||||
"Keymap for scene-tree-mode.")
|
||||
|
||||
(define-derived-mode scene-tree-mode magit-section-mode "Scene Tree"
|
||||
"Mode for showing the scene tree."
|
||||
:group 'godot-rc)
|
||||
(define-derived-mode scene-tree-mode magit-section-mode "Scene Tree"
|
||||
"Mode for showing the scene tree."
|
||||
:group 'godot-rc)
|
||||
|
||||
(provide 'godot-rc)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue