mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-04 14:11:02 +03:00
Apply general code formatting to some pages in the tutorial section
This commit is contained in:
@@ -30,11 +30,12 @@ An ``AudioStreamPlayer`` named ``AudioStreamRecord`` is used for recording.
|
||||
var effect
|
||||
var recording
|
||||
|
||||
|
||||
func _ready():
|
||||
# We get the index of the "Record" bus.
|
||||
var idx = AudioServer.get_bus_index("Record")
|
||||
# And use it to retrieve its first effect, which has been defined
|
||||
# as an "AudioEffectRecord" resource.
|
||||
# And use it to retrieve its first effect, which has been defined
|
||||
# as an "AudioEffectRecord" resource.
|
||||
effect = AudioServer.get_bus_effect(idx, 0)
|
||||
|
||||
The audio recording is handled by the :ref:`class_AudioEffectRecord` resource
|
||||
|
||||
@@ -40,11 +40,13 @@ Add these two and it's possible to guess almost exactly when sound or music will
|
||||
var time_begin
|
||||
var time_delay
|
||||
|
||||
|
||||
func _ready()
|
||||
time_begin = OS.get_ticks_usec()
|
||||
time_delay = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency()
|
||||
$Player.play()
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Obtain from ticks.
|
||||
var time = (OS.get_ticks_usec() - time_begin) / 1000000.0
|
||||
@@ -92,6 +94,7 @@ Here is the same code as before using this approach:
|
||||
func _ready()
|
||||
$Player.play()
|
||||
|
||||
|
||||
func _process(delta):
|
||||
var time = $Player.get_playback_position() + AudioServer.get_time_since_last_mix()
|
||||
# Compensate for output latency.
|
||||
|
||||
@@ -43,10 +43,12 @@ Create a Node and attach the following script.
|
||||
|
||||
extends Node
|
||||
|
||||
|
||||
# Load the custom images for the mouse cursor.
|
||||
var arrow = load("res://arrow.png")
|
||||
var beam = load("res://beam.png")
|
||||
|
||||
|
||||
func _ready():
|
||||
# Changes only the arrow shape of the cursor.
|
||||
# This is similar to changing it in the project settings.
|
||||
|
||||
@@ -35,6 +35,7 @@ Examples:
|
||||
if event.is_action_pressed("jump"):
|
||||
jump()
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
if Input.is_action_pressed("move_right"):
|
||||
# Move as long as the key/button is pressed.
|
||||
@@ -78,6 +79,7 @@ attach the following script:
|
||||
|
||||
extends Node
|
||||
|
||||
|
||||
func _input(event):
|
||||
print(event.as_text())
|
||||
|
||||
@@ -302,17 +304,19 @@ node:
|
||||
|
||||
extends Node
|
||||
|
||||
|
||||
var dragging = false
|
||||
var click_radius = 32 # Size of the sprite
|
||||
var click_radius = 32 # Size of the sprite.
|
||||
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
|
||||
if (event.position - $Sprite.position).length() < click_radius:
|
||||
# Start dragging if the click is on the sprite.
|
||||
if !dragging and event.pressed:
|
||||
if not dragging and event.pressed:
|
||||
dragging = true
|
||||
# Stop dragging if the button is released.
|
||||
if dragging and !event.pressed:
|
||||
if dragging and not event.pressed:
|
||||
dragging = false
|
||||
|
||||
if event is InputEventMouseMotion and dragging:
|
||||
|
||||
@@ -44,7 +44,7 @@ You can set up your InputMap under **Project > Project Settings > Input Map** an
|
||||
|
||||
func _process(delta):
|
||||
if Input.is_action_pressed("ui_right"):
|
||||
# Move right
|
||||
# Move right.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
@@ -52,7 +52,7 @@ You can set up your InputMap under **Project > Project Settings > Input Map** an
|
||||
{
|
||||
if (Input.IsActionPressed("ui_right"))
|
||||
{
|
||||
// Move right
|
||||
// Move right.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,19 +184,19 @@ The Input singleton has a method for this:
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
var ev = InputEventAction.new()
|
||||
# set as move_left, pressed
|
||||
# Set as move_left, pressed.
|
||||
ev.action = "move_left"
|
||||
ev.pressed = true
|
||||
# feedback
|
||||
# Feedback.
|
||||
Input.parse_input_event(ev)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
var ev = new InputEventAction();
|
||||
// set as move_left, pressed
|
||||
// Set as move_left, pressed.
|
||||
ev.SetAction("move_left");
|
||||
ev.SetPressed(true);
|
||||
// feedback
|
||||
// Feedback.
|
||||
Input.ParseInputEvent(ev);
|
||||
|
||||
InputMap
|
||||
|
||||
@@ -29,26 +29,26 @@ for example:
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _input(event):
|
||||
# Mouse in viewport coordinates
|
||||
# Mouse in viewport coordinates.
|
||||
if event is InputEventMouseButton:
|
||||
print("Mouse Click/Unclick at: ", event.position)
|
||||
elif event is InputEventMouseMotion:
|
||||
print("Mouse Motion at: ", event.position)
|
||||
|
||||
# Print the size of the viewport
|
||||
# Print the size of the viewport.
|
||||
print("Viewport Resolution is: ", get_viewport_rect().size)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
// Mouse in viewport coordinates
|
||||
// Mouse in viewport coordinates.
|
||||
if (@event is InputEventMouseButton eventMouseButton)
|
||||
GD.Print("Mouse Click/Unclick at: ", eventMouseButton.Position);
|
||||
else if (@event is InputEventMouseMotion eventMouseMotion)
|
||||
GD.Print("Mouse Motion at: ", eventMouseMotion.Position);
|
||||
|
||||
// Print the size of the viewport
|
||||
// Print the size of the viewport.
|
||||
GD.Print("Viewport Resolution is: ", GetViewportRect().Size);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ with the main scene of the game:
|
||||
var time_max = 100 # msec
|
||||
var current_scene
|
||||
|
||||
|
||||
func _ready():
|
||||
var root = get_tree().get_root()
|
||||
current_scene = root.get_child(root.get_child_count() -1)
|
||||
@@ -111,16 +112,16 @@ progress bar or loading screen.
|
||||
|
||||
::
|
||||
|
||||
func goto_scene(path): # game requests to switch to this scene
|
||||
func goto_scene(path): # Game requests to switch to this scene.
|
||||
loader = ResourceLoader.load_interactive(path)
|
||||
if loader == null: # check for errors
|
||||
if loader == null: # Check for errors.
|
||||
show_error()
|
||||
return
|
||||
set_process(true)
|
||||
|
||||
current_scene.queue_free() # get rid of the old scene
|
||||
current_scene.queue_free() # Get rid of the old scene.
|
||||
|
||||
# start your "loading..." animation
|
||||
# Start your "loading..." animation.
|
||||
get_node("animation").play("loading")
|
||||
|
||||
wait_frames = 1
|
||||
@@ -145,14 +146,15 @@ precise control over the timings.
|
||||
set_process(false)
|
||||
return
|
||||
|
||||
if wait_frames > 0: # wait for frames to let the "loading" animation show up
|
||||
# Wait for frames to let the "loading" animation show up.
|
||||
if wait_frames > 0:
|
||||
wait_frames -= 1
|
||||
return
|
||||
|
||||
var t = OS.get_ticks_msec()
|
||||
while OS.get_ticks_msec() < t + time_max: # use "time_max" to control for how long we block this thread
|
||||
|
||||
# poll your loader
|
||||
# Use "time_max" to control for how long we block this thread.
|
||||
while OS.get_ticks_msec() < t + time_max:
|
||||
# Poll your loader.
|
||||
var err = loader.poll()
|
||||
|
||||
if err == ERR_FILE_EOF: # Finished loading.
|
||||
@@ -162,7 +164,7 @@ precise control over the timings.
|
||||
break
|
||||
elif err == OK:
|
||||
update_progress()
|
||||
else: # error during loading
|
||||
else: # Error during loading.
|
||||
show_error()
|
||||
loader = null
|
||||
break
|
||||
@@ -181,12 +183,14 @@ loader.
|
||||
# Update your progress bar?
|
||||
get_node("progress").set_progress(progress)
|
||||
|
||||
# ... or update a progress animation?
|
||||
# ...or update a progress animation?
|
||||
var length = get_node("animation").get_current_animation_length()
|
||||
|
||||
# Call this on a paused animation. Use "true" as the second argument to force the animation to update.
|
||||
# Call this on a paused animation. Use "true" as the second argument to
|
||||
# force the animation to update.
|
||||
get_node("animation").seek(progress * length, true)
|
||||
|
||||
|
||||
func set_new_scene(scene_resource):
|
||||
current_scene = scene_resource.instance()
|
||||
get_node("/root").add_child(current_scene)
|
||||
@@ -273,8 +277,10 @@ Example:
|
||||
queue = preload("res://resource_queue.gd").new()
|
||||
queue.start()
|
||||
|
||||
# Suppose your game starts with a 10 second cutscene, during which the user can't interact with the game.
|
||||
# For that time, we know they won't use the pause menu, so we can queue it to load during the cutscene:
|
||||
# Suppose your game starts with a 10 second cutscene, during which the user
|
||||
# can't interact with the game.
|
||||
# For that time, we know they won't use the pause menu, so we can queue it
|
||||
# to load during the cutscene:
|
||||
queue.queue_resource("res://pause_menu.tres")
|
||||
start_cutscene()
|
||||
|
||||
@@ -282,17 +288,18 @@ Example:
|
||||
pause_menu = queue.get_resource("res://pause_menu.tres").instance()
|
||||
pause_menu.show()
|
||||
|
||||
# when you need a new scene:
|
||||
queue.queue_resource("res://level_1.tscn", true) # Use "true" as the second argument to put it at the front
|
||||
# of the queue, pausing the load of any other resource.
|
||||
# When you need a new scene:
|
||||
queue.queue_resource("res://level_1.tscn", true)
|
||||
# Use "true" as the second argument to put it at the front of the queue,
|
||||
# pausing the load of any other resource.
|
||||
|
||||
# to check progress
|
||||
# To check progress.
|
||||
if queue.is_ready("res://level_1.tscn"):
|
||||
show_new_level(queue.get_resource("res://level_1.tscn"))
|
||||
else:
|
||||
update_progress(queue.get_progress("res://level_1.tscn"))
|
||||
|
||||
# when the user walks away from the trigger zone in your Metroidvania game:
|
||||
# When the user walks away from the trigger zone in your Metroidvania game:
|
||||
queue.cancel_resource("res://zone_2.tscn")
|
||||
|
||||
**Note**: this code, in its current form, is not tested in real world
|
||||
|
||||
@@ -137,26 +137,26 @@ way to pull the data out of the file as well.
|
||||
# Note: This can be called from anywhere inside the tree. This function is
|
||||
# path independent.
|
||||
# Go through everything in the persist category and ask them to return a
|
||||
# dict of relevant variables
|
||||
# dict of relevant variables.
|
||||
func save_game():
|
||||
var save_game = File.new()
|
||||
save_game.open("user://savegame.save", File.WRITE)
|
||||
var save_nodes = get_tree().get_nodes_in_group("Persist")
|
||||
for node in save_nodes:
|
||||
# Check the node is an instanced scene so it can be instanced again during load
|
||||
# Check the node is an instanced scene so it can be instanced again during load.
|
||||
if node.filename.empty():
|
||||
print("persistent node '%s' is not an instanced scene, skipped" % node.name)
|
||||
continue
|
||||
|
||||
# Check the node has a save function
|
||||
# Check the node has a save function.
|
||||
if !node.has_method("save"):
|
||||
print("persistent node '%s' is missing a save() function, skipped" % node.name)
|
||||
continue
|
||||
|
||||
# Call the node's save function
|
||||
# Call the node's save function.
|
||||
var node_data = node.call("save")
|
||||
|
||||
# Store the save dictionary as a new line in the save file
|
||||
# Store the save dictionary as a new line in the save file.
|
||||
save_game.store_line(to_json(node_data))
|
||||
save_game.close()
|
||||
|
||||
@@ -165,7 +165,7 @@ way to pull the data out of the file as well.
|
||||
// Note: This can be called from anywhere inside the tree. This function is
|
||||
// path independent.
|
||||
// Go through everything in the persist category and ask them to return a
|
||||
// dict of relevant variables
|
||||
// dict of relevant variables.
|
||||
public void SaveGame()
|
||||
{
|
||||
var saveGame = new File();
|
||||
@@ -174,24 +174,24 @@ way to pull the data out of the file as well.
|
||||
var saveNodes = GetTree().GetNodesInGroup("Persist");
|
||||
foreach (Node saveNode in saveNodes)
|
||||
{
|
||||
// Check the node is an instanced scene so it can be instanced again during load
|
||||
// Check the node is an instanced scene so it can be instanced again during load.
|
||||
if (saveNode.Filename.Empty())
|
||||
{
|
||||
GD.Print(String.Format("persistent node '{0}' is not an instanced scene, skipped", saveNode.Name));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the node has a save function
|
||||
// Check the node has a save function.
|
||||
if (!saveNode.HasMethod("Save"))
|
||||
{
|
||||
GD.Print(String.Format("persistent node '{0}' is missing a Save() function, skipped", saveNode.Name));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Call the node's save function
|
||||
// Call the node's save function.
|
||||
var nodeData = saveNode.Call("Save");
|
||||
|
||||
// Store the save dictionary as a new line in the save file
|
||||
// Store the save dictionary as a new line in the save file.
|
||||
saveGame.StoreLine(JSON.Print(nodeData));
|
||||
}
|
||||
|
||||
@@ -240,6 +240,7 @@ load function:
|
||||
if i == "filename" or i == "parent" or i == "pos_x" or i == "pos_y":
|
||||
continue
|
||||
new_object.set(i, node_data[i])
|
||||
|
||||
save_game.close()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
@@ -55,6 +55,7 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
|
||||
|
||||
extends MultiMeshInstance
|
||||
|
||||
|
||||
func _ready():
|
||||
# Create the multimesh.
|
||||
multimesh = MultiMesh.new()
|
||||
@@ -66,6 +67,7 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
|
||||
multimesh.instance_count = 10000
|
||||
# Maybe not all of them should be visible at first.
|
||||
multimesh.visible_instance_count = 1000
|
||||
|
||||
# Set the transform of the instances.
|
||||
for i in multimesh.visible_instance_count:
|
||||
multimesh.set_instance_transform(i, Transform(Basis(), Vector3(i * 20, 0, 0)))
|
||||
@@ -88,6 +90,7 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
|
||||
multimesh.InstanceCount = 1000;
|
||||
// Maybe not all of them should be visible at first.
|
||||
multimesh.VisibleInstanceCount = 1000;
|
||||
|
||||
// Set the transform of the instances.
|
||||
for (int i = 0; i < multimesh.VisibleInstanceCount; i++)
|
||||
{
|
||||
|
||||
@@ -91,9 +91,11 @@ This is a simple example of how to create a sprite from code and move it using t
|
||||
|
||||
extends Node2D
|
||||
|
||||
# VisualServer expects references to be kept around
|
||||
|
||||
# VisualServer expects references to be kept around.
|
||||
var sprite
|
||||
|
||||
|
||||
func _ready():
|
||||
# Create a canvas item, child of this node.
|
||||
var ci_rid = VisualServer.canvas_item_create()
|
||||
@@ -130,9 +132,11 @@ The 3D APIs are different from the 2D ones, so the instantiation API must be use
|
||||
|
||||
extends Spatial
|
||||
|
||||
# VisualServer expects references to be kept around
|
||||
|
||||
# VisualServer expects references to be kept around.
|
||||
var mesh
|
||||
|
||||
|
||||
func _ready():
|
||||
# Create a visual instance (for 3D).
|
||||
var instance = VisualServer.instance_create()
|
||||
@@ -157,14 +161,16 @@ and moves a :ref:`CanvasItem <class_CanvasItem>` when the body moves.
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
# Physics2DServer expects references to be kept around
|
||||
# Physics2DServer expects references to be kept around.
|
||||
var body
|
||||
var shape
|
||||
|
||||
|
||||
func _body_moved(state, index):
|
||||
# Created your own canvas item, use it here.
|
||||
VisualServer.canvas_item_set_transform(canvas_item, state.transform)
|
||||
|
||||
|
||||
func _ready():
|
||||
# Create the body.
|
||||
body = Physics2DServer.body_create()
|
||||
|
||||
@@ -51,12 +51,15 @@ when needed:
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
var import_plugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
import_plugin = preload("import_plugin.gd").new()
|
||||
add_import_plugin(import_plugin)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_import_plugin(import_plugin)
|
||||
import_plugin = null
|
||||
@@ -90,6 +93,7 @@ Let's begin to code our plugin, one method at time:
|
||||
tool
|
||||
extends EditorImportPlugin
|
||||
|
||||
|
||||
func get_importer_name():
|
||||
return "demos.sillymaterial"
|
||||
|
||||
@@ -178,8 +182,10 @@ good practice to use an enum so you can refer to them using names.
|
||||
tool
|
||||
extends EditorImportPlugin
|
||||
|
||||
|
||||
enum Presets { DEFAULT }
|
||||
|
||||
|
||||
...
|
||||
|
||||
Now that the enum is defined, let's keep looking at the methods of an import
|
||||
|
||||
@@ -20,16 +20,19 @@ getting a ``plugin.cfg`` file created, and start with our
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
# MyEditorPlugin.gd
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
tool extends EditorPlugin
|
||||
|
||||
var plugin: EditorInspectorPlugin
|
||||
var plugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
# EditorInspectorPlugin is a resource, so we use `new()` instead of `instance()`.
|
||||
plugin = preload("res://addons/MyPlugin/MyInspectorPlugin.gd").new()
|
||||
add_inspector_plugin(plugin)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_inspector_plugin(plugin)
|
||||
|
||||
@@ -53,9 +56,9 @@ overriding or changing existing property editors.
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
# MyInspectorPlugin.gd
|
||||
|
||||
extends EditorInspectorPlugin
|
||||
|
||||
|
||||
func can_handle(object):
|
||||
# Here you can specify which object types (classes) should be handled by
|
||||
# this plugin. For example if the plugin is specific to your player
|
||||
@@ -64,6 +67,7 @@ overriding or changing existing property editors.
|
||||
# In this example we'll support all objects, so:
|
||||
return true
|
||||
|
||||
|
||||
func parse_property(object, type, path, hint, hint_text, usage):
|
||||
# We will handle properties of type integer.
|
||||
if type == TYPE_INT:
|
||||
@@ -91,9 +95,11 @@ the inspector.
|
||||
extends EditorProperty
|
||||
class_name MyIntEditor
|
||||
|
||||
|
||||
var updating = false
|
||||
var spin = EditorSpinSlider.new()
|
||||
|
||||
|
||||
func _init():
|
||||
# We'll add an EditorSpinSlider control, which is the same that the
|
||||
# inspector already uses for integer and float edition.
|
||||
@@ -108,11 +114,13 @@ the inspector.
|
||||
spin.set_max(1000)
|
||||
spin.connect("value_changed", self, "_spin_changed")
|
||||
|
||||
|
||||
func _spin_changed(value):
|
||||
if (updating):
|
||||
return
|
||||
emit_changed(get_edited_property(), value)
|
||||
|
||||
|
||||
func update_property():
|
||||
var new_value = get_edited_object()[get_edited_property()]
|
||||
updating = true
|
||||
|
||||
@@ -91,12 +91,14 @@ like this:
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
# Initialization of the plugin goes here
|
||||
# Initialization of the plugin goes here.
|
||||
pass
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
# Clean-up of the plugin goes here
|
||||
# Clean-up of the plugin goes here.
|
||||
pass
|
||||
|
||||
.. code-tab:: csharp
|
||||
@@ -110,12 +112,12 @@ like this:
|
||||
{
|
||||
public override void _EnterTree()
|
||||
{
|
||||
// Initialization of the plugin goes here
|
||||
// Initialization of the plugin goes here.
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// Clean-up of the plugin goes here
|
||||
// Clean-up of the plugin goes here.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -156,9 +158,11 @@ clicked. For that, we'll need a simple script that extends from
|
||||
tool
|
||||
extends Button
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
connect("pressed", self, "clicked")
|
||||
|
||||
|
||||
func clicked():
|
||||
print("You clicked me!")
|
||||
|
||||
@@ -198,14 +202,16 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
# Initialization of the plugin goes here
|
||||
# Add the new type with a name, a parent type, a script and an icon
|
||||
# Initialization of the plugin goes here.
|
||||
# Add the new type with a name, a parent type, a script and an icon.
|
||||
add_custom_type("MyButton", "Button", preload("my_button.gd"), preload("icon.png"))
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
# Clean-up of the plugin goes here
|
||||
# Always remember to remove it from the engine when deactivated
|
||||
# Clean-up of the plugin goes here.
|
||||
# Always remember to remove it from the engine when deactivated.
|
||||
remove_custom_type("MyButton")
|
||||
|
||||
.. code-tab:: csharp
|
||||
@@ -219,8 +225,8 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
|
||||
{
|
||||
public override void _EnterTree()
|
||||
{
|
||||
// Initialization of the plugin goes here
|
||||
// Add the new type with a name, a parent type, a script and an icon
|
||||
// Initialization of the plugin goes here.
|
||||
// Add the new type with a name, a parent type, a script and an icon.
|
||||
var script = GD.Load<Script>("MyButton.cs");
|
||||
var texture = GD.Load<Texture>("icon.png");
|
||||
AddCustomType("MyButton", "Button", script, texture);
|
||||
@@ -228,8 +234,8 @@ dialog. For that, change the ``custom_node.gd`` script to the following:
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// Clean-up of the plugin goes here
|
||||
// Always remember to remove it from the engine when deactivated
|
||||
// Clean-up of the plugin goes here.
|
||||
// Always remember to remove it from the engine when deactivated.
|
||||
RemoveCustomType("MyButton");
|
||||
}
|
||||
}
|
||||
@@ -312,23 +318,26 @@ The script could look like this:
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
# A class member to hold the dock during the plugin life cycle
|
||||
|
||||
# A class member to hold the dock during the plugin life cycle.
|
||||
var dock
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
# Initialization of the plugin goes here
|
||||
# Load the dock scene and instance it
|
||||
# Initialization of the plugin goes here.
|
||||
# Load the dock scene and instance it.
|
||||
dock = preload("res://addons/my_custom_dock/my_dock.tscn").instance()
|
||||
|
||||
# Add the loaded scene to the docks
|
||||
# Add the loaded scene to the docks.
|
||||
add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
|
||||
# Note that LEFT_UL means the left of the editor, upper-left dock
|
||||
# Note that LEFT_UL means the left of the editor, upper-left dock.
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
# Clean-up of the plugin goes here
|
||||
# Remove the dock
|
||||
# Clean-up of the plugin goes here.
|
||||
# Remove the dock.
|
||||
remove_control_from_docks(dock)
|
||||
# Erase the control from the memory
|
||||
# Erase the control from the memory.
|
||||
dock.free()
|
||||
|
||||
.. code-tab:: csharp
|
||||
@@ -350,10 +359,10 @@ The script could look like this:
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
// Clean-up of the plugin goes here
|
||||
// Remove the dock
|
||||
// Clean-up of the plugin goes here.
|
||||
// Remove the dock.
|
||||
RemoveControlFromDocks(dock);
|
||||
// Erase the control from the memory
|
||||
// Erase the control from the memory.
|
||||
dock.Free();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ This would be a basic setup:
|
||||
::
|
||||
|
||||
# MyCustomGizmoPlugin.gd
|
||||
|
||||
extends EditorSpatialGizmoPlugin
|
||||
|
||||
|
||||
func get_name():
|
||||
return "CustomNode"
|
||||
|
||||
@@ -39,17 +39,19 @@ This would be a basic setup:
|
||||
::
|
||||
|
||||
# MyCustomEditorPlugin.gd
|
||||
|
||||
tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
const MyCustomGizmoPlugin = preload("res://addons/my-addon/MyCustomGizmoPlugin.gd")
|
||||
|
||||
var gizmo_plugin = MyCustomGizmoPlugin.new()
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
add_spatial_gizmo_plugin(gizmo_plugin)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_spatial_gizmo_plugin(gizmo_plugin)
|
||||
|
||||
@@ -69,8 +71,11 @@ method so that it returns ``true`` when the spatial parameter is of our target t
|
||||
|
||||
# ...
|
||||
|
||||
|
||||
func has_gizmo(spatial):
|
||||
return spatial is MyCustomSpatial
|
||||
|
||||
|
||||
# ...
|
||||
|
||||
Then we can override methods like :ref:`redraw()<class_EditorSpatialGizmoPlugin_method_redraw>`
|
||||
@@ -80,10 +85,12 @@ or all the handle related ones.
|
||||
|
||||
# ...
|
||||
|
||||
|
||||
func _init():
|
||||
create_material("main", Color(1, 0, 0))
|
||||
create_handle_material("handles")
|
||||
|
||||
|
||||
func redraw(gizmo):
|
||||
gizmo.clear()
|
||||
|
||||
@@ -102,6 +109,7 @@ or all the handle related ones.
|
||||
gizmo.add_lines(lines, get_material("main", gizmo), false)
|
||||
gizmo.add_handles(handles, get_material("handles", gizmo))
|
||||
|
||||
|
||||
# ...
|
||||
|
||||
Note that we created a material in the `_init` method, and retrieved it in the `redraw`
|
||||
@@ -115,15 +123,19 @@ So the final plugin would look somewhat like this:
|
||||
|
||||
extends EditorSpatialGizmoPlugin
|
||||
|
||||
|
||||
const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")
|
||||
|
||||
|
||||
func _init():
|
||||
create_material("main", Color(1,0,0))
|
||||
create_handle_material("handles")
|
||||
|
||||
|
||||
func has_gizmo(spatial):
|
||||
return spatial is MyCustomSpatial
|
||||
|
||||
|
||||
func redraw(gizmo):
|
||||
gizmo.clear()
|
||||
|
||||
@@ -142,8 +154,9 @@ So the final plugin would look somewhat like this:
|
||||
gizmo.add_lines(lines, get_material("main", gizmo), false)
|
||||
gizmo.add_handles(handles, get_material("handles", gizmo))
|
||||
|
||||
# you should implement the rest of handle-related callbacks
|
||||
# (get_handle_name(), get_handle_value(), commit_handle()...)
|
||||
|
||||
# You should implement the rest of handle-related callbacks
|
||||
# (get_handle_name(), get_handle_value(), commit_handle()...).
|
||||
|
||||
Note that we just added some handles in the redraw method, but we still need to implement
|
||||
the rest of handle-related callbacks in :ref:`EditorSpatialGizmoPlugin <class_EditorSpatialGizmoPlugin>`
|
||||
@@ -165,13 +178,16 @@ for the Spatial nodes we want to target.
|
||||
# MyCustomGizmoPlugin.gd
|
||||
extends EditorSpatialGizmoPlugin
|
||||
|
||||
|
||||
const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")
|
||||
const MyCustomGizmo = preload("res://addons/my-addon/MyCustomGizmo.gd")
|
||||
|
||||
|
||||
func _init():
|
||||
create_material("main", Color(1, 0, 0))
|
||||
create_handle_material("handles")
|
||||
|
||||
|
||||
func create_gizmo(spatial):
|
||||
if spatial is MyCustomSpatial:
|
||||
return MyCustomGizmo.new()
|
||||
@@ -184,12 +200,13 @@ This way all the gizmo logic and drawing methods can be implemented in a new cla
|
||||
::
|
||||
|
||||
# MyCustomGizmo.gd
|
||||
|
||||
extends EditorSpatialGizmo
|
||||
|
||||
# You can store data in the gizmo itself (more useful when working with handles)
|
||||
|
||||
# You can store data in the gizmo itself (more useful when working with handles).
|
||||
var gizmo_size = 3.0
|
||||
|
||||
|
||||
func redraw():
|
||||
clear()
|
||||
|
||||
@@ -211,8 +228,9 @@ This way all the gizmo logic and drawing methods can be implemented in a new cla
|
||||
var handles_material = get_plugin().get_material("handles", self)
|
||||
add_handles(handles, handles_material)
|
||||
|
||||
# you should implement the rest of handle-related callbacks
|
||||
# (get_handle_name(), get_handle_value(), commit_handle()...)
|
||||
|
||||
# You should implement the rest of handle-related callbacks
|
||||
# (get_handle_name(), get_handle_value(), commit_handle()...).
|
||||
|
||||
Note that we just added some handles in the redraw method, but we still need to implement
|
||||
the rest of handle-related callbacks in :ref:`EditorSpatialGizmo<class_EditorSpatialGizmo>`
|
||||
|
||||
@@ -33,26 +33,31 @@ all you need to initialize your plugin.
|
||||
::
|
||||
|
||||
# PerlinNoise3D.gd
|
||||
|
||||
tool
|
||||
extends VisualShaderNodeCustom
|
||||
class_name VisualShaderNodePerlinNoise3D
|
||||
|
||||
|
||||
func _get_name():
|
||||
return "PerlinNoise3D"
|
||||
|
||||
|
||||
func _get_category():
|
||||
return "MyShaderNodes"
|
||||
|
||||
|
||||
func _get_description():
|
||||
return "Classic Perlin-Noise-3D function (by Curly-Brace)"
|
||||
|
||||
|
||||
func _get_return_icon_type():
|
||||
return VisualShaderNode.PORT_TYPE_SCALAR
|
||||
|
||||
|
||||
func _get_input_port_count():
|
||||
return 4
|
||||
|
||||
|
||||
func _get_input_port_name(port):
|
||||
match port:
|
||||
0:
|
||||
@@ -64,6 +69,7 @@ all you need to initialize your plugin.
|
||||
3:
|
||||
return "time"
|
||||
|
||||
|
||||
func _get_input_port_type(port):
|
||||
match port:
|
||||
0:
|
||||
@@ -75,15 +81,19 @@ all you need to initialize your plugin.
|
||||
3:
|
||||
return VisualShaderNode.PORT_TYPE_SCALAR
|
||||
|
||||
|
||||
func _get_output_port_count():
|
||||
return 1
|
||||
|
||||
|
||||
func _get_output_port_name(port):
|
||||
return "result"
|
||||
|
||||
|
||||
func _get_output_port_type(port):
|
||||
return VisualShaderNode.PORT_TYPE_SCALAR
|
||||
|
||||
|
||||
func _get_global_code(mode):
|
||||
return """
|
||||
vec3 mod289_3(vec3 x) {
|
||||
@@ -106,7 +116,7 @@ all you need to initialize your plugin.
|
||||
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
// Classic Perlin noise
|
||||
// Classic Perlin noise.
|
||||
float cnoise(vec3 P) {
|
||||
vec3 Pi0 = floor(P); // Integer part for indexing.
|
||||
vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1.
|
||||
@@ -176,6 +186,7 @@ all you need to initialize your plugin.
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
func _get_code(input_vars, output_vars, mode, type):
|
||||
return output_vars[0] + " = cnoise(vec3((%s.xy + %s.xy) * %s, %s)) * 0.5 + 0.5" % [input_vars[0], input_vars[1], input_vars[2], input_vars[3]]
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ Creating a thread is very simple, just use the following code:
|
||||
# Third argument is optional userdata, it can be any variable.
|
||||
thread.start(self, "_thread_function", "Wafflecopter")
|
||||
|
||||
|
||||
# Run here and exit.
|
||||
# The argument is the userdata passed from start().
|
||||
# If no argument was passed, this one still needs to
|
||||
@@ -76,6 +77,7 @@ Here is an example of using a Mutex:
|
||||
var mutex
|
||||
var thread
|
||||
|
||||
|
||||
# The thread will start here.
|
||||
func _ready():
|
||||
mutex = Mutex.new()
|
||||
@@ -87,12 +89,14 @@ Here is an example of using a Mutex:
|
||||
counter += 1
|
||||
mutex.unlock()
|
||||
|
||||
|
||||
# Increment the value from the thread, too.
|
||||
func _thread_function(userdata):
|
||||
mutex.lock()
|
||||
counter += 1
|
||||
mutex.unlock()
|
||||
|
||||
|
||||
# Thread must be disposed (or "joined"), for portability.
|
||||
func _exit_tree():
|
||||
thread.wait_to_finish()
|
||||
@@ -120,6 +124,7 @@ ready to be processed:
|
||||
var thread
|
||||
var exit_thread = false
|
||||
|
||||
|
||||
# The thread will start here.
|
||||
func _ready():
|
||||
mutex = Mutex.new()
|
||||
@@ -129,6 +134,7 @@ ready to be processed:
|
||||
thread = Thread.new()
|
||||
thread.start(self, "_thread_function")
|
||||
|
||||
|
||||
func _thread_function(userdata):
|
||||
while true:
|
||||
semaphore.wait() # Wait until posted.
|
||||
@@ -144,9 +150,11 @@ ready to be processed:
|
||||
counter += 1 # Increment counter, protect with Mutex.
|
||||
mutex.unlock()
|
||||
|
||||
|
||||
func increment_counter():
|
||||
semaphore.post() # Make the thread process.
|
||||
|
||||
|
||||
func get_counter():
|
||||
mutex.lock()
|
||||
# Copy counter, protect with Mutex.
|
||||
@@ -154,6 +162,7 @@ ready to be processed:
|
||||
mutex.unlock()
|
||||
return counter_value
|
||||
|
||||
|
||||
# Thread must be disposed (or "joined"), for portability.
|
||||
func _exit_tree():
|
||||
# Set exit condition to true.
|
||||
|
||||
@@ -58,14 +58,14 @@ shader resource to it. You can access your rendered ``Viewport`` with the built-
|
||||
|
||||
.. code-block:: glsl
|
||||
|
||||
// Inside the Shader
|
||||
// Inside the Shader.
|
||||
uniform sampler2D ViewportTexture;
|
||||
|
||||
And you can pass the texture into the shader from GDScript like so:
|
||||
|
||||
::
|
||||
|
||||
# In GDScript
|
||||
# In GDScript.
|
||||
func _ready():
|
||||
$Sprite.material.set_shader_param("ViewportTexture", $Viewport.get_texture())
|
||||
|
||||
@@ -133,7 +133,7 @@ does not matter:
|
||||
|
||||
shader_type canvas_item;
|
||||
|
||||
//Blurs the screen in the X-direction.
|
||||
// Blurs the screen in the X-direction.
|
||||
void fragment() {
|
||||
vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16;
|
||||
col += texture(TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
|
||||
@@ -151,7 +151,7 @@ does not matter:
|
||||
|
||||
shader_type canvas_item;
|
||||
|
||||
//Blurs the screen in the Y-direction.
|
||||
// Blurs the screen in the Y-direction.
|
||||
void fragment() {
|
||||
vec3 col = texture(TEXTURE, SCREEN_UV).xyz * 0.16;
|
||||
col += texture(TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
|
||||
|
||||
@@ -97,7 +97,7 @@ different from the one specified in size, by calling:
|
||||
|
||||
::
|
||||
|
||||
viewport.set_size_override(true, Vector2(width, height)) # Custom size for 2D
|
||||
viewport.set_size_override(true, Vector2(width, height)) # Custom size for 2D.
|
||||
viewport.set_size_override_stretch(true) # Enable stretch for custom size.
|
||||
|
||||
The root :ref:`Viewport <class_Viewport>` uses this for the stretch options in the project
|
||||
@@ -155,7 +155,7 @@ it using (for example):
|
||||
|
||||
::
|
||||
|
||||
# Wait until the frame has finished before getting the texture
|
||||
# Wait until the frame has finished before getting the texture.
|
||||
yield(VisualServer, "frame_post_draw")
|
||||
# You can get the image after this.
|
||||
|
||||
|
||||
@@ -50,11 +50,14 @@ Now add a script to the main node and add the following code:
|
||||
|
||||
extends Spatial
|
||||
|
||||
|
||||
var perform_runtime_config = false
|
||||
|
||||
|
||||
onready var ovr_init_config = preload("res://addons/godot_ovrmobile/OvrInitConfig.gdns").new()
|
||||
onready var ovr_performance = preload("res://addons/godot_ovrmobile/OvrPerformance.gdns").new()
|
||||
|
||||
|
||||
func _ready():
|
||||
var interface = ARVRServer.find_interface("OVRMobile")
|
||||
if interface:
|
||||
@@ -65,7 +68,7 @@ Now add a script to the main node and add the following code:
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if !perform_runtime_config:
|
||||
if not perform_runtime_config:
|
||||
ovr_performance.set_clock_levels(1, 1)
|
||||
ovr_performance.set_extra_latency_mode(1)
|
||||
perform_runtime_config = true
|
||||
|
||||
Reference in New Issue
Block a user