Improve dragging items from Scene Preview into source code (#661)

Co-authored-by: David Kincaid <daelonsuzuka@gmail.com>
This commit is contained in:
Marvin Altemeier
2024-06-29 21:50:18 +02:00
committed by GitHub
parent 1ff626ba47
commit 6456a789af
2 changed files with 55 additions and 5 deletions

View File

@@ -26,6 +26,7 @@ import {
register_command,
createLogger,
make_docs_uri,
node_name_to_snake,
} from "../utils";
import { SceneParser } from "./parser";
import type { SceneNode, Scene } from "./types";
@@ -93,6 +94,8 @@ export class ScenePreviewProvider
): void | Thenable<void> {
data.set("godot/path", new vscode.DataTransferItem(source[0].relativePath));
data.set("godot/class", new vscode.DataTransferItem(source[0].className));
data.set("godot/unique", new vscode.DataTransferItem(source[0].unique));
data.set("godot/label", new vscode.DataTransferItem(source[0].label));
}
public provideDocumentDropEdits(
@@ -101,15 +104,43 @@ export class ScenePreviewProvider
dataTransfer: vscode.DataTransfer,
token: vscode.CancellationToken,
): vscode.ProviderResult<vscode.DocumentDropEdit> {
const path = dataTransfer.get("godot/path").value;
const className = dataTransfer.get("godot/class").value;
const path: string = dataTransfer.get("godot/path").value;
const className: string = dataTransfer.get("godot/class").value;
const line = document.lineAt(position.line);
const unique = dataTransfer.get("godot/unique").value === "true";
const label: string = dataTransfer.get("godot/label").value;
// TODO: compare the source scene to the target file
// What should happen when you drag a node into a script that isn't the
// "main" script for that scene?
// Attempt to calculate a relative path that resolves correctly?
if (className) {
// For the root node, the path is empty and needs to be replaced with the node name
const savePath = path || label;
if (path && className) {
if (document.languageId === "gdscript") {
return new vscode.DocumentDropEdit(`$${path}`);
let qualifiedPath = `$${savePath}`;
if (unique) {
// For unique nodes, we can use the % syntax and drop the full path
qualifiedPath = `%${label}`;
}
if (line.text === "") {
// We assume that if the user is dropping a node in an empty line, they are at the top of
// the script and want to declare an onready variable
return new vscode.DocumentDropEdit(
`@onready var ${node_name_to_snake(label)}: ${className} = ${qualifiedPath}`,
);
}
// In any other place, we assume the user wants to get a reference to the node itself
return new vscode.DocumentDropEdit(qualifiedPath);
}
if (document.languageId === "csharp") {
return new vscode.DocumentDropEdit(`GetNode<${className}>("${path}")`);
return new vscode.DocumentDropEdit(`GetNode<${className}>("${savePath}")`);
}
}
}

View File

@@ -42,3 +42,22 @@ export function make_docs_uri(path: string, fragment?: string) {
fragment: fragment,
});
}
/**
* Can be used to convert a conventional node name to a snake_case variable name.
*
* @example
* ```ts
* nodeNameToVar("MyNode") // my_node
* nodeNameToVar("Sprite2D") // sprite_2d
* nodeNameToVar("UI") // ui
* ```
*/
export function node_name_to_snake(name: string): string {
const snakeCase: string = name.replace(/([a-z])([A-Z0-9])/g, "$1_$2").toLowerCase();
if (snakeCase.startsWith("_")) {
return snakeCase.substring(1);
}
return snakeCase;
}