Commit before damnger
This commit is contained in:
parent
fe1eb58626
commit
14f0200b50
101 changed files with 8087 additions and 15 deletions
116
AudioMixerVisualizer/AudioDebugVisualizer.tscn
Normal file
116
AudioMixerVisualizer/AudioDebugVisualizer.tscn
Normal file
|
@ -0,0 +1,116 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://cpp7g0af4m0ed"]
|
||||
|
||||
[ext_resource type="Script" path="res://AudioMixerVisualizer/AudioMixerDebugVisualization.gd" id="1"]
|
||||
[ext_resource type="Script" path="res://AudioMixerVisualizer/AudioMixerMeterDrawer.gd" id="2"]
|
||||
[ext_resource type="Script" path="res://AudioMixerVisualizer/AudioMixerVolumeDrawer.gd" id="3"]
|
||||
[ext_resource type="FontFile" uid="uid://yewopnpud14o" path="res://AudioMixerVisualizer/AudioMixerDebugFont.tres" id="4"]
|
||||
|
||||
[node name="AudioDebugVisualizer" type="CanvasLayer"]
|
||||
process_mode = 3
|
||||
layer = 128
|
||||
|
||||
[node name="Mixer" type="Control" parent="."]
|
||||
custom_minimum_size = Vector2(2.08165e-12, 100)
|
||||
layout_mode = 3
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -500.0
|
||||
offset_top = -140.0
|
||||
offset_right = 500.0
|
||||
offset_bottom = -10.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
mouse_filter = 2
|
||||
script = ExtResource("1")
|
||||
font_fx = ExtResource("4")
|
||||
|
||||
[node name="Container" type="HBoxContainer" parent="Mixer"]
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
mouse_filter = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="Bus" type="PanelContainer" parent="Mixer/Container"]
|
||||
custom_minimum_size = Vector2(60, 0)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="Mixer/Container/Bus"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="label_name" type="Label" parent="Mixer/Container/Bus/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Bus"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
clip_text = true
|
||||
|
||||
[node name="label_peak" type="Label" parent="Mixer/Container/Bus/VBox"]
|
||||
modulate = Color(0.521569, 0.521569, 0.521569, 1)
|
||||
layout_mode = 2
|
||||
text = "-0.1"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="Mixer/Container/Bus/VBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Meter" type="Panel" parent="Mixer/Container/Bus/VBox/HBox"]
|
||||
custom_minimum_size = Vector2(20, 0)
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="HBox" type="HBoxContainer" parent="Mixer/Container/Bus/VBox/HBox/Meter"]
|
||||
clip_contents = true
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 1.0
|
||||
offset_top = 1.0
|
||||
offset_right = -1.0
|
||||
offset_bottom = -1.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="fill_left" type="ColorRect" parent="Mixer/Container/Bus/VBox/HBox/Meter/HBox"]
|
||||
modulate = Color(0.0784314, 0.737255, 0.309804, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="fill_right" type="ColorRect" parent="Mixer/Container/Bus/VBox/HBox/Meter/HBox"]
|
||||
modulate = Color(0.0784314, 0.737255, 0.309804, 1)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Volume" type="Panel" parent="Mixer/Container/Bus/VBox/HBox"]
|
||||
custom_minimum_size = Vector2(5, 0)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
script = ExtResource("3")
|
||||
|
||||
[node name="VBox_fx" type="VBoxContainer" parent="Mixer/Container/Bus/VBox/HBox"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[connection signal="mouse_entered" from="Mixer" to="Mixer" method="_on_mouse_entered"]
|
||||
[connection signal="mouse_exited" from="Mixer" to="Mixer" method="_on_mouse_exited"]
|
71
AudioMixerVisualizer/AudioMixerDebugFont.tres
Normal file
71
AudioMixerVisualizer/AudioMixerDebugFont.tres
Normal file
File diff suppressed because one or more lines are too long
162
AudioMixerVisualizer/AudioMixerDebugVisualization.gd
Normal file
162
AudioMixerVisualizer/AudioMixerDebugVisualization.gd
Normal file
|
@ -0,0 +1,162 @@
|
|||
extends Control
|
||||
|
||||
@export var font_fx : FontFile
|
||||
|
||||
class bus:
|
||||
var index
|
||||
var ui : Control
|
||||
var max_peak : float
|
||||
var fx : Array
|
||||
|
||||
var timer
|
||||
|
||||
func _init(bus_index, _ui, _fx):
|
||||
timer = 0
|
||||
max_peak = -200
|
||||
self.index = bus_index
|
||||
self.ui = _ui
|
||||
self.fx = _fx
|
||||
|
||||
func update(delta, peak):
|
||||
if peak > max_peak:
|
||||
max_peak = peak
|
||||
timer = 0
|
||||
|
||||
timer += delta
|
||||
if timer > 3:
|
||||
max_peak = peak
|
||||
|
||||
@onready var container = $Container
|
||||
@onready var bus_template = $Container/Bus
|
||||
var buses : Array
|
||||
|
||||
func _ready():
|
||||
# Add bus panels
|
||||
for i in AudioServer.bus_count:
|
||||
var bus_panel = bus_template.duplicate()
|
||||
container.add_child(bus_panel)
|
||||
var label : Label = bus_panel.get_node("VBox/label_name")
|
||||
label.text = AudioServer.get_bus_name(i)
|
||||
|
||||
# Add effect labels
|
||||
var vbox = bus_panel.get_node("VBox/HBox/VBox_fx")
|
||||
var fx = Array()
|
||||
for n in AudioServer.get_bus_effect_count(i):
|
||||
var effect : AudioEffect = AudioServer.get_bus_effect(i, n)
|
||||
fx.append(effect)
|
||||
|
||||
var fx_label = Label.new()
|
||||
fx_label.text = effect.resource_name
|
||||
fx_label.add_theme_font_override("font", font_fx)
|
||||
vbox.add_child(fx_label)
|
||||
|
||||
vbox.visible = true
|
||||
|
||||
vbox.set_anchors_preset(Control.PRESET_TOP_LEFT)
|
||||
vbox.pivot_offset = Vector2(0, 300)
|
||||
|
||||
var b = bus.new(i, bus_panel, fx)
|
||||
bus_panel.get_node("VBox/HBox/Meter").assign_bus(b)
|
||||
bus_panel.get_node("VBox/HBox/Volume").assign_bus(b)
|
||||
buses.append(b)
|
||||
|
||||
bus_template.queue_free()
|
||||
|
||||
func _process(delta):
|
||||
var mouse_pos = get_viewport().get_mouse_position()
|
||||
if mouse_pos.y > get_viewport_rect().size.y - 150:
|
||||
_hide()
|
||||
else:
|
||||
_show()
|
||||
|
||||
# Update bus panels
|
||||
for b in buses:
|
||||
var peak_l = AudioServer.get_bus_peak_volume_left_db(b.index, 0)
|
||||
var peak_r = AudioServer.get_bus_peak_volume_right_db(b.index, 0)
|
||||
var peak_max = max(peak_l, peak_r)
|
||||
|
||||
b.update(delta, peak_max)
|
||||
|
||||
# Mute/Solo
|
||||
var label_name : Label = b.ui.get_node("VBox/label_name")
|
||||
label_name.modulate = Color.WHITE
|
||||
if AudioServer.is_bus_mute(b.index):
|
||||
label_name.modulate = Color.CRIMSON
|
||||
if AudioServer.is_bus_solo(b.index):
|
||||
label_name.modulate = Color.YELLOW
|
||||
|
||||
# Meter fill
|
||||
var fill : ColorRect = b.ui.get_node("VBox/HBox/Meter/HBox/fill_left")
|
||||
fill.anchor_top = 1.0 - normalize_peak(peak_l)
|
||||
fill = b.ui.get_node("VBox/HBox/Meter/HBox/fill_right")
|
||||
fill.anchor_top = 1.0 - normalize_peak(peak_r)
|
||||
|
||||
# Peak label
|
||||
var label_peak : Label = b.ui.get_node("VBox/label_peak")
|
||||
var peak_text = ""
|
||||
if b.max_peak > -200:
|
||||
peak_text = str(ceil(b.max_peak * 10) / 10.0)
|
||||
if b.max_peak > 0:
|
||||
peak_text = "+" + peak_text
|
||||
label_peak.text = peak_text
|
||||
|
||||
# Peak label color
|
||||
if b.max_peak > 0.0:
|
||||
label_peak.modulate = Color.CRIMSON
|
||||
else:
|
||||
label_peak.modulate = Color(1.0, 1.0, 1.0, 0.5)
|
||||
|
||||
update_fx_labels()
|
||||
|
||||
func update_fx_labels():
|
||||
for b in buses:
|
||||
var fx_vbox = b.ui.get_node("VBox/HBox/VBox_fx")
|
||||
for i in b.fx.size():
|
||||
var label = fx_vbox.get_child(i)
|
||||
if AudioServer.is_bus_effect_enabled(b.index, i):
|
||||
label.modulate = Color.WHITE
|
||||
else:
|
||||
label.modulate = Color.DIM_GRAY
|
||||
|
||||
var fx = b.fx[i]
|
||||
var s = fx.resource_name
|
||||
|
||||
# Name
|
||||
if fx.get_class() == "AudioEffectLowPassFilter":
|
||||
s = "LPF"
|
||||
if fx.get_class() == "AudioEffectBandPassFilter":
|
||||
s = "BPF"
|
||||
if fx.get_class() == "AudioEffectReverb":
|
||||
s = "Verb"
|
||||
if fx.get_class() == "AudioEffectAmplify":
|
||||
s = "Amp"
|
||||
if fx.get_class() == "AudioEffectCompressor":
|
||||
s = "Comp"
|
||||
if fx.get_class() == "AudioEffectLimiter":
|
||||
s = "Lim"
|
||||
if fx.get_class() == "AudioEffectStereoEnhance":
|
||||
s = "StEnh"
|
||||
|
||||
# Settings
|
||||
if "volume_db" in fx:
|
||||
s = s + ", vol " + str(snapped(fx.volume_db, 0.01))
|
||||
if "resonance" in fx:
|
||||
s = s + ", res " + str(snapped(fx.resonance, 0.01))
|
||||
if "cutoff_hz" in fx:
|
||||
s = s + ", hz " + str(snapped(fx.cutoff_hz, 0.01))
|
||||
if "room_size" in fx:
|
||||
s = s + ", size " + str(snapped(fx.room_size, 0.01))
|
||||
if "wet" in fx:
|
||||
s = s + ", wet " + str(snapped(fx.wet, 0.01))
|
||||
label.text = s
|
||||
|
||||
# Takes a peak in db, and spits out a normalized 0 to 1 value
|
||||
func normalize_peak(peak_db):
|
||||
var p = (peak_db + 200) / 200.0
|
||||
return p * p * p * p * p * p
|
||||
|
||||
func _hide():
|
||||
modulate = Color(1.0, 1.0, 1.0, 0.25)
|
||||
|
||||
func _show():
|
||||
modulate = Color(1.0, 1.0, 1.0, 0.8)
|
1
AudioMixerVisualizer/AudioMixerDebugVisualization.gd.uid
Normal file
1
AudioMixerVisualizer/AudioMixerDebugVisualization.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://c4jq6us1dhv8m
|
35
AudioMixerVisualizer/AudioMixerMeterDrawer.gd
Normal file
35
AudioMixerVisualizer/AudioMixerMeterDrawer.gd
Normal file
|
@ -0,0 +1,35 @@
|
|||
extends Control
|
||||
|
||||
var bus
|
||||
|
||||
func assign_bus(_bus):
|
||||
self.bus = _bus
|
||||
|
||||
func _process(_delta):
|
||||
queue_redraw()
|
||||
|
||||
func _draw():
|
||||
if bus == null:
|
||||
return
|
||||
|
||||
var meter_ui = bus.ui.get_node("VBox/HBox/Meter/HBox")
|
||||
var pos = meter_ui.global_position - global_position
|
||||
var _size = meter_ui.size
|
||||
|
||||
# Draw db-markings
|
||||
var db_mark_color = Color(1.0, 1.0, 1.0, 0.03)
|
||||
for i in 12:
|
||||
draw_db_mark(pos, _size, i * -6, db_mark_color)
|
||||
|
||||
# Draw max-peak line
|
||||
draw_db_mark(pos, _size, bus.max_peak, Color(0.1, 0.8, 0.1, normalize_peak(bus.max_peak)))
|
||||
|
||||
func draw_db_mark(pos, _size, db, color):
|
||||
var db_norm = 1 - normalize_peak(db)
|
||||
var y_offset = Vector2(0, db_norm * _size.y)
|
||||
draw_line(pos + y_offset, pos + y_offset + Vector2(_size.x, 0), color)
|
||||
|
||||
# Takes a peak in db, and spits out a normalized 0 to 1 value
|
||||
func normalize_peak(peak_db):
|
||||
var p = (peak_db + 200) / 200.0
|
||||
return p * p * p * p * p * p
|
1
AudioMixerVisualizer/AudioMixerMeterDrawer.gd.uid
Normal file
1
AudioMixerVisualizer/AudioMixerMeterDrawer.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://bj5emg1onynp8
|
27
AudioMixerVisualizer/AudioMixerVolumeDrawer.gd
Normal file
27
AudioMixerVisualizer/AudioMixerVolumeDrawer.gd
Normal file
|
@ -0,0 +1,27 @@
|
|||
extends Control
|
||||
|
||||
var bus
|
||||
|
||||
func assign_bus(_bus):
|
||||
self.bus = _bus
|
||||
|
||||
func process(_delta):
|
||||
queue_redraw()
|
||||
|
||||
func _draw():
|
||||
if bus == null:
|
||||
return
|
||||
|
||||
var pos = Vector2(-1, 0)
|
||||
var _size = Vector2(size.x + 2, size.y)
|
||||
draw_volume_mark(pos, _size, AudioServer.get_bus_volume_db(bus.index), Color(1.0, 1.0, 1.0, 0.5))
|
||||
|
||||
func draw_volume_mark(pos, _size, db, color):
|
||||
var db_norm = 1 - normalize_peak(db)
|
||||
var y_offset = Vector2(0, db_norm * (_size.y - 10) + 10)
|
||||
draw_line(pos + y_offset, pos + y_offset + Vector2(_size.x, 0), color, 2.0)
|
||||
|
||||
# Takes a peak in db, and spits out a normalized 0 to 1 value
|
||||
func normalize_peak(peak_db):
|
||||
var p = (peak_db + 200) / 200.0
|
||||
return p * p * p * p * p * p
|
1
AudioMixerVisualizer/AudioMixerVolumeDrawer.gd.uid
Normal file
1
AudioMixerVisualizer/AudioMixerVolumeDrawer.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://dfguk2y5kq1w3
|
BIN
AudioMixerVisualizer/BarlowCondensed-Regular.ttf
Normal file
BIN
AudioMixerVisualizer/BarlowCondensed-Regular.ttf
Normal file
Binary file not shown.
35
AudioMixerVisualizer/BarlowCondensed-Regular.ttf.import
Normal file
35
AudioMixerVisualizer/BarlowCondensed-Regular.ttf.import
Normal file
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontFile"
|
||||
uid="uid://djsydx7kqwa0k"
|
||||
path="res://.godot/imported/BarlowCondensed-Regular.ttf-973b5bd97605c53120c8d42add219b73.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://AudioMixerVisualizer/BarlowCondensed-Regular.ttf"
|
||||
dest_files=["res://.godot/imported/BarlowCondensed-Regular.ttf-973b5bd97605c53120c8d42add219b73.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
allow_system_fallback=true
|
||||
force_autohinter=false
|
||||
hinting=1
|
||||
subpixel_positioning=1
|
||||
keep_rounding_remainders=true
|
||||
oversampling=0.0
|
||||
Fallbacks=null
|
||||
fallbacks=[]
|
||||
Compress=null
|
||||
compress=true
|
||||
preload=[]
|
||||
language_support={}
|
||||
script_support={}
|
||||
opentype_features={}
|
13
Demo/example.tscn
Normal file
13
Demo/example.tscn
Normal file
|
@ -0,0 +1,13 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://cacmio2fg7klb"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cpp7g0af4m0ed" path="res://AudioMixerVisualizer/AudioDebugVisualizer.tscn" id="1"]
|
||||
[ext_resource type="AudioStream" uid="uid://bvpyheijtxjes" path="res://Demo/example.wav" id="2"]
|
||||
|
||||
[node name="Node3D" type="Node3D"]
|
||||
|
||||
[node name="AudioDebugVisualizer" parent="." instance=ExtResource("1")]
|
||||
|
||||
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
|
||||
stream = ExtResource("2")
|
||||
autoplay = true
|
||||
bus = &"Example Bus"
|
BIN
Demo/example.wav
Normal file
BIN
Demo/example.wav
Normal file
Binary file not shown.
24
Demo/example.wav.import
Normal file
24
Demo/example.wav.import
Normal file
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bvpyheijtxjes"
|
||||
path="res://.godot/imported/example.wav-0a036c25aae6ac44b63679fdbaee4561.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Demo/example.wav"
|
||||
dest_files=["res://.godot/imported/example.wav-0a036c25aae6ac44b63679fdbaee4561.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=2
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=0
|
0
Screenshots/.gdignore
Normal file
0
Screenshots/.gdignore
Normal file
BIN
Screenshots/Screenshot.png
Normal file
BIN
Screenshots/Screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 224 KiB |
21
addons/vizpath/LICENSE
Normal file
21
addons/vizpath/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 markeel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
90
addons/vizpath/README.md
Normal file
90
addons/vizpath/README.md
Normal file
|
@ -0,0 +1,90 @@
|
|||
# Visualized Path plugin
|
||||
|
||||
A plugin for Godot 4 to visualize a path
|
||||
|
||||
## Overview
|
||||
|
||||
This plugin is designed to create a 3D mesh to visualize a path. It generates that mesh using
|
||||
an array of spots, where each spot has a normal defining the mesh face at that spot.
|
||||
|
||||
The path created will be directly between each spot and in the order specified. The direction
|
||||
between the spots is direct but the path can be bent based on the normals at each spot.
|
||||
|
||||
An optional tail and head can be placed at the beginning and ending of the path, to provide a
|
||||
decoration.
|
||||
|
||||
## Installation
|
||||
|
||||
The plugin is written in 100% GDScript so no compilation is required and should work on any
|
||||
platform.
|
||||
|
||||
To install it from the Godot Asset Library, within your project:
|
||||
- Select the AssetLib tab
|
||||
- Search for "3D Visualized Path"
|
||||
- Click Download button
|
||||
- After the dialog is presented with files, at least include the "addons" directory
|
||||
- From Project -> Project Settings...
|
||||
- Go to Plugins tab and enable vizpath plugin (not doing this will not let the path be selectable
|
||||
in the 3D view and will not present the spot control points
|
||||
|
||||
There are 3 main directories
|
||||
- addons/vizpath
|
||||
- examples/vizpath
|
||||
- source/vizpath
|
||||
|
||||
When loading as an asset in another project (as opposed to working on this asset) the following files
|
||||
should NOT be imported, they will likely conflict with your project
|
||||
- README.md
|
||||
- LICENSE
|
||||
- icon.svg
|
||||
- icon.svg.import
|
||||
- project.godot
|
||||
|
||||
After using this asset, the examples/vizpath and source/vizpath folders can be removed so as not
|
||||
to pollute your project.
|
||||
|
||||
## Usage
|
||||
|
||||
The typical use of this asset is to create the path from an array of VisualizationSpot resources
|
||||
in response to user input or actions by the AI during game play. The plugin does support manually
|
||||
creating a path in the editor and editing in the 3D view.
|
||||
|
||||
### Programatically through a script
|
||||
|
||||
To change the path, simply construct an array of VisualizationSpot objects (which define the
|
||||
point in local space to the VisualizedPath and the normal in local space). There are changed signals
|
||||
that detect the resource being updated and the path will be reconstructed.
|
||||
|
||||
#### Handling errors
|
||||
|
||||
If the path cannot be constructed (because the spots are too close to create a bend with the curve
|
||||
specified), the underlying mesh will not be created and the error list will be updated. To retrieve
|
||||
these errors a call to get_errors() can be made.
|
||||
|
||||
Based on the properties and how close the spots are allowed to be, you can guarantee that the path will
|
||||
always be constructed. If you allow unrestrained movement of the spots and the normals, you will
|
||||
need to report the error (which is what is done when using the Godot Editor)
|
||||
|
||||
### Directly in the editor
|
||||
|
||||
The VisualizedPath class will appear in the list of nodes when adding a node to a scene. The VisualizedPath
|
||||
class supports editing all the properties through the Inspector and updating
|
||||
the view immediately. It also allows a VisualizationSpot to be moved and its normal rotated using
|
||||
a subgizmo. At least 2 spots must be added. If the path is not valid, a warning will be presented
|
||||
on the VisualizedPath instance.
|
||||
|
||||
### Using subgizmo
|
||||
|
||||
To use the subgizmo, click on the VisualizedPath and in the 3D view click on the yellow cone for
|
||||
one of the spots. The manipulation gizmo changes to that spot and then it can be moved (changing
|
||||
the position of the spot), or rotated (changing the normal at that spot)
|
||||
|
||||
## Examples
|
||||
|
||||
Examples of using the plugin can be found in the "example/vizpath" directory. Feel free to
|
||||
delete this directory for your project.
|
||||
|
||||
## Source
|
||||
|
||||
Blender and Inkscape files used to create the meshes and the icon are included in the "source/vizpath"
|
||||
directory, which can also be removed without impacting its usage.
|
BIN
addons/vizpath/images/path.png
Normal file
BIN
addons/vizpath/images/path.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 811 B |
34
addons/vizpath/images/path.png.import
Normal file
34
addons/vizpath/images/path.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://d0ljaahn5bykd"
|
||||
path="res://.godot/imported/path.png-9af8c406cc1948c301cd69299f1231f1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/vizpath/images/path.png"
|
||||
dest_files=["res://.godot/imported/path.png-9af8c406cc1948c301cd69299f1231f1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
12
addons/vizpath/mesh/spot.mtl
Normal file
12
addons/vizpath/mesh/spot.mtl
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Blender 3.5.0 MTL File: 'spot.blend'
|
||||
# www.blender.org
|
||||
|
||||
newmtl Material
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
66
addons/vizpath/mesh/spot.obj
Normal file
66
addons/vizpath/mesh/spot.obj
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Blender 3.5.0
|
||||
# www.blender.org
|
||||
mtllib spot.mtl
|
||||
o Cube
|
||||
v 0.250000 -0.250000 -0.056205
|
||||
v 0.250000 -0.250000 -0.000000
|
||||
v 0.250000 0.250000 -0.056205
|
||||
v 0.250000 0.250000 0.000000
|
||||
v -0.250000 -0.250000 -0.056205
|
||||
v -0.250000 -0.250000 -0.000000
|
||||
v -0.250000 0.250000 -0.056205
|
||||
v -0.250000 0.250000 0.000000
|
||||
v 0.095182 -0.095182 -0.071294
|
||||
v 0.095182 0.095182 -0.071294
|
||||
v -0.095182 -0.095182 -0.071294
|
||||
v -0.095182 0.095182 -0.071294
|
||||
v 0.000000 0.000000 -0.500000
|
||||
vn -0.0970 -0.0000 -0.9953
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn 1.0000 -0.0000 -0.0000
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn -0.9762 -0.0000 -0.2167
|
||||
vn 0.0970 -0.0000 -0.9953
|
||||
vn -0.0000 -0.0970 -0.9953
|
||||
vn -0.0000 0.0970 -0.9953
|
||||
vn -0.0000 0.9762 -0.2167
|
||||
vn -0.0000 -0.9762 -0.2167
|
||||
vn 0.9762 -0.0000 -0.2167
|
||||
vt 0.625000 0.500000
|
||||
vt 0.375000 0.500000
|
||||
vt 0.625000 0.750000
|
||||
vt 0.375000 0.750000
|
||||
vt 0.625000 0.250000
|
||||
vt 0.125000 0.500000
|
||||
vt 0.375000 0.250000
|
||||
vt 0.625000 0.000000
|
||||
vt 0.625000 1.000000
|
||||
vt 0.375000 1.000000
|
||||
vt 0.375000 0.000000
|
||||
vt 0.125000 0.750000
|
||||
vt 0.625000 0.500000
|
||||
vt 0.625000 0.750000
|
||||
vt 0.625000 0.250000
|
||||
vt 0.625000 0.000000
|
||||
vt 0.625000 1.000000
|
||||
vt 0.625000 0.250000
|
||||
vt 0.625000 1.000000
|
||||
vt 0.625000 0.500000
|
||||
vt 0.625000 0.750000
|
||||
s 0
|
||||
usemtl Material
|
||||
f 5/5/1 7/8/1 12/16/1 11/15/1
|
||||
f 4/4/2 3/3/2 7/9/2 8/10/2
|
||||
f 8/11/3 7/8/3 5/5/3 6/7/3
|
||||
f 6/6/4 2/2/4 4/4/4 8/12/4
|
||||
f 2/2/5 1/1/5 3/3/5 4/4/5
|
||||
f 6/7/6 5/5/6 1/1/6 2/2/6
|
||||
f 11/15/7 12/16/7 13/18/7
|
||||
f 3/3/8 1/1/8 9/13/8 10/14/8
|
||||
f 1/1/9 5/5/9 11/15/9 9/13/9
|
||||
f 7/9/10 3/3/10 10/14/10 12/17/10
|
||||
f 12/17/11 10/14/11 13/19/11
|
||||
f 9/13/12 11/15/12 13/20/12
|
||||
f 10/14/13 9/13/13 13/21/13
|
25
addons/vizpath/mesh/spot.obj.import
Normal file
25
addons/vizpath/mesh/spot.obj.import
Normal file
|
@ -0,0 +1,25 @@
|
|||
[remap]
|
||||
|
||||
importer="wavefront_obj"
|
||||
importer_version=1
|
||||
type="Mesh"
|
||||
uid="uid://b2tsm0h3jdgvy"
|
||||
path="res://.godot/imported/spot.obj-f00a82a9756945bf04ad3b38eae5a1b4.mesh"
|
||||
|
||||
[deps]
|
||||
|
||||
files=["res://.godot/imported/spot.obj-f00a82a9756945bf04ad3b38eae5a1b4.mesh"]
|
||||
|
||||
source_file="res://addons/vizpath/mesh/spot.obj"
|
||||
dest_files=["res://.godot/imported/spot.obj-f00a82a9756945bf04ad3b38eae5a1b4.mesh", "res://.godot/imported/spot.obj-f00a82a9756945bf04ad3b38eae5a1b4.mesh"]
|
||||
|
||||
[params]
|
||||
|
||||
generate_tangents=true
|
||||
generate_lods=true
|
||||
generate_shadow_mesh=true
|
||||
generate_lightmap_uv2=false
|
||||
generate_lightmap_uv2_texel_size=0.2
|
||||
scale_mesh=Vector3(1, 1, 1)
|
||||
offset_mesh=Vector3(0, 0, 0)
|
||||
force_disable_mesh_compression=false
|
7
addons/vizpath/plugin.cfg
Normal file
7
addons/vizpath/plugin.cfg
Normal file
|
@ -0,0 +1,7 @@
|
|||
[plugin]
|
||||
|
||||
name="vizpath"
|
||||
description=""
|
||||
author="markeel"
|
||||
version="1.0.2"
|
||||
script="vizpath.gd"
|
36
addons/vizpath/resources/spot.gd
Normal file
36
addons/vizpath/resources/spot.gd
Normal file
|
@ -0,0 +1,36 @@
|
|||
@tool
|
||||
extends Resource
|
||||
class_name VisualizationSpot
|
||||
|
||||
## The VisualizationSpot class is a resource that allows the definition
|
||||
## of a spot for a VisualizedPath.
|
||||
##
|
||||
## A VisualizationSpot contains a point (local space) and a normal (local space)
|
||||
## that identifies where the path starts, ends, or turns.
|
||||
|
||||
## The point in local space where the path originates, terminates, or turns
|
||||
@export var point : Vector3 :
|
||||
set(p):
|
||||
point = p
|
||||
emit_changed()
|
||||
|
||||
## The normal defining the up direction of the plane this path will be in at this
|
||||
## point.
|
||||
@export var normal : Vector3 :
|
||||
set(n):
|
||||
normal = n
|
||||
emit_changed()
|
||||
|
||||
func _init():
|
||||
point = Vector3.ZERO
|
||||
normal = Vector3.FORWARD
|
||||
|
||||
func is_equal(other):
|
||||
if not point.is_equal_approx(other.point):
|
||||
return false
|
||||
if not normal.is_equal_approx(other.normal):
|
||||
return false
|
||||
return true
|
||||
|
||||
func _to_string():
|
||||
return "%s/%s" % [point, normal]
|
1
addons/vizpath/resources/spot.gd.uid
Normal file
1
addons/vizpath/resources/spot.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://d28qf56fgf0e4
|
8
addons/vizpath/resources/spot.tres
Normal file
8
addons/vizpath/resources/spot.tres
Normal file
|
@ -0,0 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="VisualizationSpot" load_steps=2 format=3 uid="uid://xujlcvwtxkk8"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="1_yfhm3"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_yfhm3")
|
||||
point = Vector3(0, 0, 0)
|
||||
normal = Vector3(0, 0, -1)
|
87
addons/vizpath/resources/viz_head.gd
Normal file
87
addons/vizpath/resources/viz_head.gd
Normal file
|
@ -0,0 +1,87 @@
|
|||
@tool
|
||||
extends Resource
|
||||
class_name VizHead
|
||||
|
||||
# The VizHead class is a resource that allows the creation
|
||||
# of a simple arrow head at the end of the path showing the
|
||||
# final destination of the path.
|
||||
#
|
||||
# It is designed to be used interchangeably with any resource
|
||||
# that defines an apply method with the signature defined
|
||||
# below.
|
||||
|
||||
## The width of the arrow head as a percentage of the
|
||||
## path width it is associated with.
|
||||
@export var width_factor : float = 2.0 :
|
||||
set(w):
|
||||
width_factor = w
|
||||
emit_changed()
|
||||
|
||||
## The length of the arrow head as a percentage of the
|
||||
## path width it is associated with
|
||||
@export var length_factor : float = 1.20 :
|
||||
set(l):
|
||||
length_factor = l
|
||||
emit_changed()
|
||||
|
||||
## The get_offset function will be called to shift the end of the last
|
||||
## segment to accomodate the head mesh
|
||||
##
|
||||
## This class can be overridden to provide a custom head to the path
|
||||
## by defining a resource that has an apply method with the following
|
||||
## definition:
|
||||
##
|
||||
## The [code]left[/code] and [code]right[/code] positions at the end of the path, where the
|
||||
## V texture coordinate is 0.0 for [code]left[/code] and 1.0 for [code]right[/code].
|
||||
## The [code]normal[/code] and the [code]direction[/code] define the position of the face and the
|
||||
## direction that the path is going.
|
||||
func get_offset(left : Vector3, right : Vector3, normal : Vector3, direction : Vector3) -> float:
|
||||
var segment := right - left
|
||||
var segment_len := segment.length()
|
||||
var arrow_point_len := segment_len * length_factor
|
||||
return arrow_point_len
|
||||
|
||||
## The apply function will be called when the path
|
||||
## mesh is created.
|
||||
##
|
||||
## This class can be overridden to provide a custom head to the path
|
||||
## by defining a resource that has an apply method with the following
|
||||
## definition:
|
||||
##
|
||||
## The [code]mesh_node[/code] parameter is the mesh instance of the visualized path.
|
||||
## Its interior mesh can be updated (typically with [SurfaceTool]).
|
||||
## The [code]u[/code] parameter is the U texture coordinate of the [code]left[/code] and
|
||||
## [code]right[/code] positions at the end of the path, where the V texture coordinate
|
||||
## is 0.0 for [code]left[/code] and 1.0 for [code]right[/code]. The [code]normal[/code] and
|
||||
## the [code]direction[/code] define the position of the face and the direction that the
|
||||
## path is going. The [code]path_mat[/code] is the material that was used
|
||||
## in the original path definition [member VisualizedPath.path_mat].
|
||||
func apply(mesh_node : MeshInstance3D, u : float, left : Vector3, right : Vector3, normal : Vector3, direction : Vector3, path_mat : Material):
|
||||
var segment := right - left
|
||||
var mid_segment := segment / 2.0
|
||||
var binormal := direction.cross(normal).normalized()
|
||||
var segment_len := segment.length()
|
||||
var arrow_base_len := segment_len * width_factor
|
||||
var extent_len := (arrow_base_len - segment_len)/2.0
|
||||
var arrow_left_extent := left - extent_len * binormal
|
||||
var arrow_right_extent := right + extent_len * binormal
|
||||
var arrow_point_len := segment_len * length_factor
|
||||
var arrow_fwd_extent := left + mid_segment + arrow_point_len * direction
|
||||
var v_extent = width_factor * 0.5
|
||||
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
st.set_material(path_mat)
|
||||
|
||||
st.set_uv(Vector2(u, 0.5 + v_extent))
|
||||
st.add_vertex(arrow_right_extent)
|
||||
|
||||
st.set_uv(Vector2(u, 0.5 - v_extent))
|
||||
st.add_vertex(arrow_left_extent)
|
||||
|
||||
st.set_uv(Vector2(u+arrow_point_len, 0.5))
|
||||
st.add_vertex(arrow_fwd_extent)
|
||||
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
1
addons/vizpath/resources/viz_head.gd.uid
Normal file
1
addons/vizpath/resources/viz_head.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cfan7h7m4fi7q
|
8
addons/vizpath/resources/viz_head.tres
Normal file
8
addons/vizpath/resources/viz_head.tres
Normal file
|
@ -0,0 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="VizHead" load_steps=2 format=3 uid="uid://ca6a3fjxcmbhc"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/viz_head.gd" id="1_7yqvb"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_7yqvb")
|
||||
width_factor = 2.0
|
||||
length_factor = 1.2
|
80
addons/vizpath/resources/viz_tail.gd
Normal file
80
addons/vizpath/resources/viz_tail.gd
Normal file
|
@ -0,0 +1,80 @@
|
|||
@tool
|
||||
extends Resource
|
||||
class_name VizTail
|
||||
|
||||
# The VizTail class is a resource that allows the creation
|
||||
# of a simple rounded tail at the beginning of the path showing the
|
||||
# start of the path.
|
||||
#
|
||||
# It is designed to be used interchangeably with any resource
|
||||
# that defines an apply method with the signature defined
|
||||
# below.
|
||||
|
||||
## The number of segments in the semi-sphere of tail
|
||||
@export var num_segs := 16 :
|
||||
set(s):
|
||||
num_segs = s
|
||||
emit_changed()
|
||||
|
||||
## The get_offset function will be called to shift the beginning of the first
|
||||
## segment to accomodate the tail mesh
|
||||
##
|
||||
## This class can be overridden to provide a custom head to the path
|
||||
## by defining a resource that has an apply method with the following
|
||||
## definition:
|
||||
##
|
||||
## The [code]left[/code] and [code]right[/code] positions at the start of the path, where the
|
||||
## V texture coordinate is 0.0 for [code]left[/code] and 1.0 for [code]right[/code].
|
||||
## The [code]normal[/code] and the [code]direction[/code] define the position of the face and the
|
||||
## direction that the path is going.
|
||||
func get_offset(left : Vector3, right : Vector3, normal : Vector3, direction : Vector3) -> float:
|
||||
return 0.0
|
||||
|
||||
## The apply function will be called when the path
|
||||
## mesh is created.
|
||||
##
|
||||
## This class can be overridden to provide a custom tail to the path
|
||||
## by defining a resource that has an apply method with the following
|
||||
## definition:
|
||||
##
|
||||
## The [code]mesh_node[/code] parameter is the mesh instance of the visualized path.
|
||||
## Its interior mesh can be updated (typically with [SurfaceTool]).
|
||||
## The [code]u[/code] parameter is the U texture coordinate of the [code]left[/code] and
|
||||
## [code]right[/code] positions at the end of the path, where the V texture coordinate
|
||||
## is 0.0 for [code]left[/code] and 1.0 for [code]right[/code]. The [code]normal[/code] and
|
||||
## the [code]direction[/code] define the position of the face and the direction that the
|
||||
## path is going. The [code]path_mat[/code] is the material that was used
|
||||
## in the original path definition [member VisualizedPath.path_mat].
|
||||
func apply(mesh_node : MeshInstance3D, u : float, left : Vector3, right : Vector3, normal : Vector3, direction : Vector3, path_mat : Material):
|
||||
var segment := right - left
|
||||
var mid_segment := segment / 2.0
|
||||
var mid_point := left + mid_segment
|
||||
var binormal := direction.cross(normal).normalized()
|
||||
var segment_len := segment.length()
|
||||
var mid_segment_len := mid_segment.length()
|
||||
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
var rotation_dir := -signf(direction.dot(mid_segment.rotated(normal, PI/2.0)))
|
||||
var last_pos := right
|
||||
var last_pu := u
|
||||
var last_pv := 1.0
|
||||
for i in range(num_segs):
|
||||
var weight := rotation_dir * float(i+1) / float(num_segs)
|
||||
var angle := weight * PI
|
||||
var pv := (1.0 + cos(angle))/2.0
|
||||
var pu := u - rotation_dir * mid_segment_len * sin(angle)
|
||||
var pos := mid_point + mid_segment.rotated(normal, angle)
|
||||
st.set_uv(Vector2(u, 0.5))
|
||||
st.add_vertex(mid_point)
|
||||
st.set_uv(Vector2(last_pu, last_pv))
|
||||
st.add_vertex(last_pos)
|
||||
st.set_uv(Vector2(pu, pv))
|
||||
st.add_vertex(pos)
|
||||
last_pos = pos
|
||||
last_pu = pu
|
||||
last_pv = pv
|
||||
st.set_material(path_mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
1
addons/vizpath/resources/viz_tail.gd.uid
Normal file
1
addons/vizpath/resources/viz_tail.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://b6jnvwm4145s3
|
7
addons/vizpath/resources/viz_tail.tres
Normal file
7
addons/vizpath/resources/viz_tail.tres
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="Resource" script_class="VizTail" load_steps=2 format=3 uid="uid://dnaxoh1d4t82c"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/viz_tail.gd" id="1_npnpb"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_npnpb")
|
||||
num_segs = 12
|
202
addons/vizpath/utilities/viz_bend.gd
Normal file
202
addons/vizpath/utilities/viz_bend.gd
Normal file
|
@ -0,0 +1,202 @@
|
|||
extends RefCounted
|
||||
class_name VizBend
|
||||
|
||||
var _error : String
|
||||
|
||||
var _bend_normal : Vector3
|
||||
var _bend_plane : Plane
|
||||
var _begin_on_bend_plane : Vector3
|
||||
var _end_on_bend_plane : Vector3
|
||||
var _intersect_data : OptVector3
|
||||
|
||||
var _plane_join_point : Vector3
|
||||
|
||||
var _bend_side : float
|
||||
var _curve_side : float
|
||||
|
||||
var _bend_begin_triangle : VizTriangle
|
||||
var _bend_end_triangle : VizTriangle
|
||||
|
||||
var _arc_begin_mid : Vector3
|
||||
var _arc_end_mid : Vector3
|
||||
|
||||
var _begin : Vector3
|
||||
var _begin_dir : Vector3
|
||||
var _end : Vector3
|
||||
var _end_dir : Vector3
|
||||
|
||||
class OptVector3:
|
||||
var vector : Vector3
|
||||
func _init(p_data : Vector3):
|
||||
vector = p_data
|
||||
|
||||
func _init(p_begin : VisualizationSpot, p_end : VisualizationSpot, p_width : float, p_bend_lip : float):
|
||||
if not _is_bendable(p_begin, p_end):
|
||||
return
|
||||
|
||||
_calc_bend_normal(p_begin, p_end)
|
||||
if not _calc_intersection_point(p_begin, p_end):
|
||||
return
|
||||
_calc_join_point(p_begin, p_end)
|
||||
_calc_bend_side(p_begin, p_end)
|
||||
_calc_triangles(p_begin, p_end, p_width, p_bend_lip)
|
||||
_calc_arc_plane()
|
||||
_begin = _bend_begin_triangle.get_leg_mid()
|
||||
if not _is_in_order(p_begin.point, _begin, _plane_join_point):
|
||||
_error = "bend point is too close to beginning for %s to %s with lip %s" % [p_begin.point, p_end.point, p_bend_lip]
|
||||
return
|
||||
_end = _bend_end_triangle.get_leg_mid()
|
||||
if not _is_in_order(_plane_join_point, _end, p_end.point):
|
||||
_error = "bend point is too close to end for %s to %s with lip %s" % [p_begin.point, p_end.point, p_bend_lip]
|
||||
return
|
||||
|
||||
func _to_string():
|
||||
return "%s->%s->%s" % [_begin, _plane_join_point, _end]
|
||||
|
||||
# ---------------------------------------------
|
||||
# Public Methoeds
|
||||
|
||||
func get_error() -> String:
|
||||
return _error
|
||||
|
||||
func is_invalid() -> bool:
|
||||
if _error != "":
|
||||
return true
|
||||
return false
|
||||
|
||||
func get_begin() -> Vector3:
|
||||
return _begin
|
||||
|
||||
func get_end() -> Vector3:
|
||||
return _end
|
||||
|
||||
func is_angled() -> bool:
|
||||
return not is_zero_approx(_bend_side)
|
||||
|
||||
func is_angled_against_curve() -> bool:
|
||||
if _bend_side * _curve_side < 0:
|
||||
return true
|
||||
return false
|
||||
|
||||
func get_half_leg_width() -> Vector3:
|
||||
return (_bend_begin_triangle.leg_left - _bend_begin_triangle.leg_right) / 2.0
|
||||
|
||||
func get_half_bend_width() -> Vector3:
|
||||
return (_bend_begin_triangle.bend_left - _bend_begin_triangle.bend_right) / 2.0
|
||||
|
||||
func get_begin_triangle() -> VizTriangle:
|
||||
return _bend_begin_triangle
|
||||
|
||||
func get_end_triangle() -> VizTriangle:
|
||||
return _bend_end_triangle
|
||||
|
||||
func get_shift_width() -> Vector3:
|
||||
return _arc_begin_mid - _bend_begin_triangle.get_bend_mid() + _bend_end_triangle.get_bend_mid() - _arc_end_mid
|
||||
|
||||
func get_shift_offset() -> Vector3:
|
||||
return _arc_begin_mid - _bend_begin_triangle.get_bend_mid()
|
||||
|
||||
func get_arc_begin_point() -> Vector3:
|
||||
return _arc_begin_mid
|
||||
|
||||
func get_arc_end_point() -> Vector3:
|
||||
return _arc_end_mid
|
||||
|
||||
func get_arc_point(weight : float, sharpness : float) -> Vector3:
|
||||
return _curve_point(_arc_begin_mid, _plane_join_point, _arc_end_mid, weight, sharpness)
|
||||
|
||||
# ---------------------------------------------
|
||||
# Private Methods
|
||||
|
||||
func _curve_point(p0 : Vector3, p1 : Vector3, p2 : Vector3, t : float, s : float) -> Vector3:
|
||||
var p := p1 + pow(1-t, 2.0) * s * (p0-p1) + pow(t, 2.0) * s * (p2-p1)
|
||||
return p
|
||||
|
||||
func _is_in_order(b : Vector3, m : Vector3, e : Vector3) -> bool:
|
||||
return (e-m).normalized().dot((m-b).normalized()) > 0
|
||||
|
||||
func _is_bendable(p_begin : VisualizationSpot, p_end : VisualizationSpot) -> bool:
|
||||
var dir := (p_end.point - p_begin.point).normalized()
|
||||
var begin_norm_sign := signf(dir.dot(p_begin.normal))
|
||||
var end_norm_sign := signf(dir.dot(p_end.normal))
|
||||
if begin_norm_sign == end_norm_sign:
|
||||
_error = "%s cannot be twisted into %s" % [ p_begin.normal, p_end.normal ]
|
||||
return false
|
||||
_curve_side = end_norm_sign
|
||||
return true
|
||||
|
||||
func _calc_bend_normal(p_begin : VisualizationSpot, p_end : VisualizationSpot):
|
||||
var middle = p_begin.point + (p_end.point - p_begin.point) / 2.0
|
||||
_bend_normal = p_begin.normal.cross(p_end.normal).normalized()
|
||||
_bend_plane = Plane(_bend_normal, middle)
|
||||
|
||||
func _calc_intersection_point(p_begin : VisualizationSpot, p_end : VisualizationSpot) -> bool:
|
||||
_begin_on_bend_plane = _bend_plane.project(p_begin.point)
|
||||
_end_on_bend_plane = _bend_plane.project(p_end.point)
|
||||
var dir := _end_on_bend_plane - _begin_on_bend_plane
|
||||
var begin_normal_on_bend_plane := _bend_plane.project(p_begin.point + p_begin.normal) - _begin_on_bend_plane
|
||||
var end_normal_on_bend_plane := _bend_plane.project(p_end.point + p_end.normal) - _end_on_bend_plane
|
||||
var begin_bend_binormal := begin_normal_on_bend_plane.cross(dir)
|
||||
var begin_bend_tangent := begin_bend_binormal.cross(begin_normal_on_bend_plane).normalized()
|
||||
var end_bend_binormal := end_normal_on_bend_plane.cross(dir)
|
||||
var end_bend_tangent := end_bend_binormal.cross(end_normal_on_bend_plane).normalized()
|
||||
_intersect_data = _intersect(_begin_on_bend_plane, begin_bend_tangent, _end_on_bend_plane, end_bend_tangent, _bend_normal)
|
||||
if _intersect_data == null:
|
||||
_error = "intersection failed unexpectedly: normal %s at %s is parallel with normal %s at %s" % [ begin_normal_on_bend_plane, _begin_on_bend_plane, end_normal_on_bend_plane, _end_on_bend_plane ]
|
||||
return false
|
||||
return true
|
||||
|
||||
func _calc_join_point(p_begin : VisualizationSpot, p_end : VisualizationSpot):
|
||||
var begin_bend_from_intersect := p_begin.point + _intersect_data.vector - _begin_on_bend_plane
|
||||
var end_bend_from_intersect := p_end.point + _intersect_data.vector - _end_on_bend_plane
|
||||
var begin_intersect_distance := begin_bend_from_intersect.distance_to(p_begin.point)
|
||||
var end_intersect_distance := end_bend_from_intersect.distance_to(p_end.point)
|
||||
var begin_to_end_on_bend_distance := end_bend_from_intersect.distance_to(begin_bend_from_intersect)
|
||||
var begin_to_end_intersect_join_numerator := begin_to_end_on_bend_distance * begin_intersect_distance / end_intersect_distance
|
||||
var begin_to_end_intersect_join_denominator := 1.0 + begin_intersect_distance / end_intersect_distance
|
||||
var begin_on_end_intersect_join_distance := begin_to_end_intersect_join_numerator / begin_to_end_intersect_join_denominator
|
||||
var begin_bend_dir := begin_bend_from_intersect - p_begin.point
|
||||
var end_bend_dir := end_bend_from_intersect - p_begin.point
|
||||
var begin_to_end_normal := begin_bend_dir.cross(end_bend_dir)
|
||||
var begin_to_end_binormal := begin_to_end_normal.cross(_bend_normal)
|
||||
var begin_on_end_intersect_side = signf(end_bend_dir.dot(begin_to_end_binormal))
|
||||
_plane_join_point = begin_bend_from_intersect - begin_on_end_intersect_side * begin_on_end_intersect_join_distance * _bend_normal
|
||||
|
||||
func _calc_bend_side(p_begin : VisualizationSpot, p_end : VisualizationSpot):
|
||||
_begin_dir = Vector3(_plane_join_point - p_begin.point).normalized()
|
||||
_end_dir = Vector3(p_end.point - _plane_join_point).normalized()
|
||||
_bend_side = signf(_bend_normal.dot(_end_dir))
|
||||
|
||||
func _calc_triangles(p_begin : VisualizationSpot, p_end : VisualizationSpot, p_width : float, p_bend_lip : float):
|
||||
var begin_binormal := _begin_dir.cross(p_begin.normal).normalized()
|
||||
var end_binormal := _end_dir.cross(p_end.normal).normalized()
|
||||
_bend_begin_triangle = VizTriangle.new()
|
||||
_bend_begin_triangle.update(_begin_dir, _plane_join_point, begin_binormal, p_width, p_bend_lip, _bend_normal, _bend_side, _curve_side)
|
||||
_bend_end_triangle = VizTriangle.new()
|
||||
_bend_end_triangle.update(-_end_dir, _plane_join_point, end_binormal, p_width, p_bend_lip, _bend_normal, -_bend_side, _curve_side)
|
||||
|
||||
func _calc_arc_plane():
|
||||
var begin_mid := _bend_begin_triangle.get_leg_mid()
|
||||
var end_mid := _bend_end_triangle.get_leg_mid()
|
||||
var arc_center := _plane_join_point - (_plane_join_point - begin_mid) - (_plane_join_point - end_mid)
|
||||
var arc_plane := Plane(_bend_normal, arc_center)
|
||||
_arc_begin_mid = arc_plane.project(_bend_begin_triangle.get_bend_mid())
|
||||
_arc_end_mid = arc_plane.project(_bend_end_triangle.get_bend_mid())
|
||||
|
||||
func _intersect(a : Vector3, a_norm : Vector3, b : Vector3, b_norm : Vector3, plane_norm : Vector3) -> OptVector3:
|
||||
var seg := b - a
|
||||
var seg_len := seg.length()
|
||||
var seg_norm := seg.normalized()
|
||||
var alpha_sign := signf(b_norm.cross(a_norm).dot(plane_norm))
|
||||
var cos_alpha := b_norm.dot(a_norm)
|
||||
var beta_sign := signf(seg_norm.cross(b_norm).dot(plane_norm))
|
||||
var cos_beta := seg_norm.dot(b_norm)
|
||||
var intersect_side := alpha_sign * beta_sign
|
||||
var sin_alpha := sqrt(1 - cos_alpha*cos_alpha)
|
||||
var sin_beta := sqrt(1 - cos_beta*cos_beta)
|
||||
if is_equal_approx(sin_alpha, 0.0):
|
||||
return null
|
||||
var q := seg_len * sin_beta / sin_alpha
|
||||
var p := a - intersect_side * q * a_norm
|
||||
return OptVector3.new(p)
|
||||
|
1
addons/vizpath/utilities/viz_bend.gd.uid
Normal file
1
addons/vizpath/utilities/viz_bend.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://g81gb6sdvfbe
|
120
addons/vizpath/utilities/viz_compound_leg.gd
Normal file
120
addons/vizpath/utilities/viz_compound_leg.gd
Normal file
|
@ -0,0 +1,120 @@
|
|||
extends RefCounted
|
||||
class_name VizCompoundLeg
|
||||
|
||||
var _error : String = ""
|
||||
var _begin : VisualizationSpot
|
||||
var _end : VisualizationSpot
|
||||
var _width : float
|
||||
var _bend_lip : float
|
||||
var _intermediate_spot : VisualizationSpot = null
|
||||
var _norm_distance : float
|
||||
var _max_join_point_on_begin : Vector3
|
||||
var _max_join_point_on_end : Vector3
|
||||
|
||||
func _init(p_begin : VisualizationSpot, p_end : VisualizationSpot, p_width : float, p_bend_lip : float):
|
||||
_begin = p_begin
|
||||
_end = p_end
|
||||
_width = p_width
|
||||
_bend_lip = p_bend_lip
|
||||
_calc_intermediate_point()
|
||||
# _calc_max_offset()
|
||||
_calc_intermediate_normal()
|
||||
|
||||
func _to_string():
|
||||
return "CLEG(%s to %s through %s)" % [_begin, _end, _intermediate_spot]
|
||||
|
||||
# ---------------------------------------------
|
||||
# Public Methoeds
|
||||
|
||||
func is_invalid() -> bool:
|
||||
return _error != ""
|
||||
|
||||
func get_error() -> String:
|
||||
return _error
|
||||
|
||||
func get_begin() -> VisualizationSpot:
|
||||
return _begin
|
||||
|
||||
func get_begin_ray() -> Vector3:
|
||||
return (_max_join_point_on_begin - _begin.point).normalized()
|
||||
|
||||
func adjust_begin(distance : float):
|
||||
var new_begin := VisualizationSpot.new()
|
||||
new_begin.point = _begin.point + distance * get_begin_ray()
|
||||
new_begin.normal = _begin.normal
|
||||
_begin = new_begin
|
||||
_calc_intermediate_normal()
|
||||
|
||||
func get_end() -> VisualizationSpot:
|
||||
return _end
|
||||
|
||||
func get_end_ray() -> Vector3:
|
||||
return (_end.point - _max_join_point_on_end).normalized()
|
||||
|
||||
func adjust_end(distance : float):
|
||||
var new_end := VisualizationSpot.new()
|
||||
new_end.point = _end.point - distance * get_end_ray()
|
||||
new_end.normal = _end.normal
|
||||
_end = new_end
|
||||
_calc_intermediate_normal()
|
||||
|
||||
var test_mat : Material = load("res://example/common/materials/white.tres")
|
||||
|
||||
func update_mesh(mesh_node : Node3D, u : float, segs : int, sharpness : float, mat : Material) -> float:
|
||||
var leg1 := VizSimpleLeg.new(_begin, _intermediate_spot, _width, _bend_lip)
|
||||
if leg1.is_invalid():
|
||||
print("leg1=%s: error=%s" % [ leg1, leg1.get_error() ])
|
||||
assert(!leg1.is_invalid())
|
||||
var leg2 := VizSimpleLeg.new(_intermediate_spot, _end, _width, _bend_lip)
|
||||
if leg2.is_invalid():
|
||||
print("leg2: error=%s" % leg2.get_error())
|
||||
assert(!leg2.is_invalid())
|
||||
u = leg1.update_mesh(mesh_node, u, segs, sharpness, mat)
|
||||
var left := leg1.get_end_left()
|
||||
var right := leg1.get_end_right()
|
||||
u = leg2.extend_mesh(mesh_node, u, left, right, segs, sharpness, mat)
|
||||
return u
|
||||
|
||||
# ---------------------------------------------
|
||||
# Local Methods
|
||||
|
||||
func _calc_intermediate_point():
|
||||
_intermediate_spot = VisualizationSpot.new()
|
||||
var intermediate_segment := _end.point - _begin.point
|
||||
_intermediate_spot.point = _begin.point + intermediate_segment / 2.0
|
||||
|
||||
func _calc_intermediate_normal():
|
||||
var begin_plane := Plane(_begin.normal, _begin.point)
|
||||
var max_point := begin_plane.project(_intermediate_spot.point)
|
||||
# var mid_point_distance := _intermediate_spot.point.distance_to(max_point)
|
||||
var mid_point_distance := _begin.point.distance_to(max_point)
|
||||
var cur_norm_distance = _bend_lip + VizSimpleLeg.MIN_SEGMENT_LENGTH
|
||||
var dir := (max_point - _begin.point).normalized()
|
||||
var valid := false
|
||||
while cur_norm_distance < mid_point_distance:
|
||||
var data := _check_normal(dir, cur_norm_distance)
|
||||
if data.size() == 3:
|
||||
_max_join_point_on_begin = data[0]
|
||||
_max_join_point_on_end = data[1]
|
||||
_intermediate_spot.normal = data[2]
|
||||
valid = true
|
||||
break
|
||||
cur_norm_distance += 0.01
|
||||
if not valid:
|
||||
_error = "%s is too close to %s to make compund leg with lip %s" % [ _begin.point, _end.point, _bend_lip ]
|
||||
|
||||
func _check_normal(dir : Vector3, norm_distance : float) -> Array:
|
||||
var candidate_segment := _intermediate_spot.point - (_begin.point + norm_distance * dir)
|
||||
var candidate_segment_dir := candidate_segment.normalized()
|
||||
var candidate_normal := ((_begin.normal + _end.normal)/2.0).normalized()
|
||||
var candidate_binormal := candidate_normal.cross(candidate_segment_dir).normalized()
|
||||
var candidate_mid := VisualizationSpot.new()
|
||||
candidate_mid.point = _intermediate_spot.point
|
||||
candidate_mid.normal = candidate_segment_dir.cross(candidate_binormal).normalized()
|
||||
var leg1 := VizSimpleLeg.new(_begin, candidate_mid, _width, _bend_lip)
|
||||
if not leg1.is_invalid():
|
||||
var leg2 := VizSimpleLeg.new(candidate_mid, _end, _width, _bend_lip)
|
||||
if not leg2.is_invalid():
|
||||
return [ leg1.get_leg_bend_begin(), leg2.get_leg_bend_end(), candidate_mid.normal ]
|
||||
return []
|
||||
|
1
addons/vizpath/utilities/viz_compound_leg.gd.uid
Normal file
1
addons/vizpath/utilities/viz_compound_leg.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://ce4k02xlfpr00
|
102
addons/vizpath/utilities/viz_mid.gd
Normal file
102
addons/vizpath/utilities/viz_mid.gd
Normal file
|
@ -0,0 +1,102 @@
|
|||
extends RefCounted
|
||||
class_name VizMid
|
||||
|
||||
var _seg1 : VizSegment
|
||||
var _seg2 : VizSegment
|
||||
var _width : float
|
||||
var _inner_radius : float
|
||||
|
||||
var _rotation_point : VisualizationSpot
|
||||
var _angle : float
|
||||
var _error : String
|
||||
|
||||
func _init(p_seg1 : VizSegment, p_seg2 : VizSegment, p_stroke_width : float, p_inner_radius : float):
|
||||
_seg1 = p_seg1
|
||||
_seg2 = p_seg2
|
||||
_width = p_stroke_width
|
||||
_inner_radius = p_inner_radius
|
||||
assert(p_seg1.get_end().is_equal(p_seg2.get_begin()))
|
||||
_calc_rotation_point()
|
||||
var center_distance := calc_center_distance(p_stroke_width, p_inner_radius)
|
||||
var turn_distance := calc_turn_distance(center_distance, _angle)
|
||||
p_seg1.adjust_end(turn_distance)
|
||||
if p_seg1.is_invalid():
|
||||
return
|
||||
p_seg2.adjust_begin(turn_distance)
|
||||
if p_seg2.is_invalid():
|
||||
return
|
||||
|
||||
# ---------------------------------------------
|
||||
# Public Methoeds
|
||||
|
||||
func is_invalid() -> bool:
|
||||
return _error != ""
|
||||
|
||||
func get_error() -> String:
|
||||
return _error
|
||||
|
||||
func update_mesh(_mesh_instance : MeshInstance3D, u : float, num_segs : int, mat : Material):
|
||||
return _create_fan(_mesh_instance, u, num_segs, mat)
|
||||
|
||||
# ---------------------------------------------
|
||||
# Private Methods
|
||||
|
||||
func _calc_rotation_point():
|
||||
var seg1_ray := _seg1.get_end_ray()
|
||||
var seg2_ray := _seg2.get_begin_ray()
|
||||
_angle = seg1_ray.angle_to(seg2_ray)
|
||||
var join_point := _seg1.get_end()
|
||||
var plane_normal := seg1_ray.cross(seg2_ray).normalized()
|
||||
if plane_normal == Vector3.ZERO:
|
||||
plane_normal = join_point.normal
|
||||
var binormal = plane_normal.cross(seg1_ray).normalized()
|
||||
var d := calc_center_distance(_width, _inner_radius)
|
||||
var e := calc_turn_distance(d, _angle)
|
||||
_rotation_point = VisualizationSpot.new()
|
||||
_rotation_point.point = join_point.point - e * seg1_ray + d * binormal
|
||||
_rotation_point.normal = plane_normal
|
||||
|
||||
func _create_fan(mesh_node : Node3D, u : float, num_segs : int, mat : Material) -> float:
|
||||
var radius := _width/2.0 + _inner_radius
|
||||
var arc_len := absf(_angle) * radius
|
||||
|
||||
var begin_half_width := _seg1.get_end_binormal() * _width/2.0
|
||||
var end_half_width := _seg2.get_begin_binormal() * _width/2.0
|
||||
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(_seg1.get_end().normal)
|
||||
|
||||
st.set_uv(Vector2(u, 1))
|
||||
st.add_vertex(_seg1.get_end().point + begin_half_width)
|
||||
st.set_uv(Vector2(u, 0))
|
||||
st.add_vertex(_seg1.get_end().point - begin_half_width)
|
||||
|
||||
var outer_base := _seg1.get_end().point + begin_half_width - _rotation_point.point
|
||||
var inner_base := _seg1.get_end().point - begin_half_width - _rotation_point.point
|
||||
for i in range(1, num_segs-1):
|
||||
var cur_angle : float = _angle * float(i) / float(num_segs-1)
|
||||
var cur_arc_len = absf(cur_angle) * radius
|
||||
var inner := _rotation_point.point + inner_base.rotated(_rotation_point.normal, cur_angle)
|
||||
var outer := _rotation_point.point + outer_base.rotated(_rotation_point.normal, cur_angle)
|
||||
st.set_uv(Vector2(u+cur_arc_len, 1))
|
||||
st.add_vertex(outer)
|
||||
st.set_uv(Vector2(u+cur_arc_len, 0))
|
||||
st.add_vertex(inner)
|
||||
|
||||
st.set_uv(Vector2(u+arc_len, 1))
|
||||
st.add_vertex(_seg2.get_begin().point + end_half_width)
|
||||
st.set_uv(Vector2(u+arc_len, 0))
|
||||
st.add_vertex(_seg2.get_begin().point - end_half_width)
|
||||
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
|
||||
return u + arc_len
|
||||
|
||||
static func calc_center_distance(stroke_width : float, inner_radius : float) -> float:
|
||||
return stroke_width / 2.0 + inner_radius
|
||||
|
||||
static func calc_turn_distance(center_distance : float, angle : float) -> float:
|
||||
return center_distance * tan(abs(angle)/2.0)
|
1
addons/vizpath/utilities/viz_mid.gd.uid
Normal file
1
addons/vizpath/utilities/viz_mid.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://b4vo8e10344ls
|
86
addons/vizpath/utilities/viz_segment.gd
Normal file
86
addons/vizpath/utilities/viz_segment.gd
Normal file
|
@ -0,0 +1,86 @@
|
|||
extends RefCounted
|
||||
class_name VizSegment
|
||||
|
||||
var _simple_leg : VizSimpleLeg = null
|
||||
var _compound_leg : VizCompoundLeg = null
|
||||
|
||||
func _init(p_begin : VisualizationSpot, p_end : VisualizationSpot, p_width : float, p_bend_lip : float):
|
||||
_simple_leg = VizSimpleLeg.new(p_begin, p_end, p_width, p_bend_lip)
|
||||
if _simple_leg.is_invalid():
|
||||
_compound_leg = VizCompoundLeg.new(p_begin, p_end, p_width, p_bend_lip)
|
||||
|
||||
func is_invalid() -> bool:
|
||||
if _simple_leg.is_invalid():
|
||||
if _compound_leg.is_invalid():
|
||||
return true
|
||||
return false
|
||||
|
||||
func get_error() -> String:
|
||||
if _simple_leg.is_invalid():
|
||||
if _compound_leg.is_invalid():
|
||||
return _compound_leg.get_error()
|
||||
|
||||
return _simple_leg.get_error()
|
||||
return ""
|
||||
|
||||
func get_begin() -> VisualizationSpot:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_begin()
|
||||
return _compound_leg.get_begin()
|
||||
|
||||
func get_begin_ray() -> Vector3:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_begin_ray()
|
||||
return _compound_leg.get_begin_ray()
|
||||
|
||||
func get_begin_binormal() -> Vector3:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_begin_ray().cross(_simple_leg.get_begin().normal)
|
||||
return _compound_leg.get_begin_ray().cross(_compound_leg.get_begin().normal)
|
||||
|
||||
func adjust_begin(distance : float):
|
||||
if not _simple_leg.is_invalid():
|
||||
_simple_leg.adjust_begin(distance)
|
||||
if _simple_leg.is_invalid():
|
||||
_compound_leg = VizCompoundLeg.new(_simple_leg.get_begin(), _simple_leg.get_end(), _simple_leg._width, _simple_leg._bend_lip)
|
||||
else:
|
||||
_compound_leg.adjust_begin(distance)
|
||||
|
||||
func get_end() -> VisualizationSpot:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_end()
|
||||
return _compound_leg.get_end()
|
||||
|
||||
func get_end_ray() -> Vector3:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_end_ray()
|
||||
return _compound_leg.get_end_ray()
|
||||
|
||||
func get_end_binormal() -> Vector3:
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg.get_end_ray().cross(_simple_leg.get_end().normal)
|
||||
return _compound_leg.get_end_ray().cross(_compound_leg.get_end().normal)
|
||||
|
||||
func adjust_end(distance : float):
|
||||
if not _simple_leg.is_invalid():
|
||||
_simple_leg.adjust_end(distance)
|
||||
if _simple_leg.is_invalid():
|
||||
_compound_leg = VizCompoundLeg.new(_simple_leg.get_begin(), _simple_leg.get_end(), _simple_leg._width, _simple_leg._bend_lip)
|
||||
else:
|
||||
_compound_leg.adjust_end(distance)
|
||||
|
||||
func update_mesh(mesh_instance : MeshInstance3D, u : float, segs : int, sharpness : float, mat : Material) -> float:
|
||||
if _simple_leg.is_invalid():
|
||||
if _compound_leg.is_invalid():
|
||||
return u
|
||||
u = _compound_leg.update_mesh(mesh_instance, u, segs, sharpness, mat)
|
||||
else:
|
||||
u = _simple_leg.update_mesh(mesh_instance, u, segs, sharpness, mat)
|
||||
return u
|
||||
|
||||
func _to_string():
|
||||
if not _simple_leg.is_invalid():
|
||||
return _simple_leg._to_string()
|
||||
if not _compound_leg.is_invalid():
|
||||
return _compound_leg._to_string()
|
||||
return "invalid segment"
|
1
addons/vizpath/utilities/viz_segment.gd.uid
Normal file
1
addons/vizpath/utilities/viz_segment.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://dx5hc2jl5ow46
|
307
addons/vizpath/utilities/viz_simple_leg.gd
Normal file
307
addons/vizpath/utilities/viz_simple_leg.gd
Normal file
|
@ -0,0 +1,307 @@
|
|||
extends RefCounted
|
||||
class_name VizSimpleLeg
|
||||
|
||||
var _error : String = ""
|
||||
var _begin : VisualizationSpot
|
||||
var _end : VisualizationSpot
|
||||
var _width : float
|
||||
var _bend_lip : float
|
||||
var _bend : VizBend
|
||||
|
||||
const MIN_SEGMENT_LENGTH=0.01
|
||||
const EPSILON=0.00001
|
||||
|
||||
func _init(p_begin : VisualizationSpot, p_end : VisualizationSpot, p_width : float, p_bend_lip : float):
|
||||
_begin = p_begin
|
||||
_end = p_end
|
||||
_width = p_width
|
||||
_bend_lip = p_bend_lip
|
||||
if not _has_valid_normal():
|
||||
return
|
||||
if _is_straight():
|
||||
return
|
||||
_bend = VizBend.new(_begin, _end, p_width, p_bend_lip)
|
||||
if not _bend.is_invalid():
|
||||
_check_offsets(_begin, _end)
|
||||
|
||||
# ---------------------------------------------
|
||||
# Public Methods
|
||||
|
||||
func get_error() -> String:
|
||||
if _error != "":
|
||||
return _error
|
||||
if _bend != null:
|
||||
return _bend.get_error()
|
||||
return ""
|
||||
|
||||
func is_invalid() -> bool:
|
||||
if _error != "":
|
||||
return true
|
||||
if _bend != null:
|
||||
return _bend.is_invalid()
|
||||
return false
|
||||
|
||||
func extend_mesh(mesh_node : Node3D, u : float, left : Vector3, right : Vector3, segs : int, sharpness : float, mat : Material) -> float:
|
||||
if _bend == null:
|
||||
u = _extend_straight_leg(mesh_node, u, left, right, _begin.point, _end.point, _begin.normal, mat)
|
||||
else:
|
||||
u = _extend_straight_leg(mesh_node, u, left, right, _begin.point, _bend.get_begin(), _begin.normal, mat)
|
||||
if _bend.is_angled():
|
||||
u = _create_begin_triangle(mesh_node, u, _begin.normal, _bend.get_begin_triangle(), mat)
|
||||
u = _create_bend(mesh_node, u, segs, sharpness, mat)
|
||||
if _bend.is_angled():
|
||||
u = _create_end_triangle(mesh_node, u, _end.normal, _bend.get_end_triangle(), mat)
|
||||
u = _create_straight_leg(mesh_node, u, _bend.get_end(), _end.point, _end.normal, mat)
|
||||
return u
|
||||
|
||||
func update_mesh(mesh_node : Node3D, u : float, segs : int, sharpness : float, mat : Material) -> float:
|
||||
if _bend == null:
|
||||
u = _create_straight_leg(mesh_node, u, _begin.point, _end.point, _begin.normal, mat)
|
||||
else:
|
||||
u = _create_straight_leg(mesh_node, u, _begin.point, _bend.get_begin(), _begin.normal, mat)
|
||||
if _bend.is_angled():
|
||||
u = _create_begin_triangle(mesh_node, u, _begin.normal, _bend.get_begin_triangle(), mat)
|
||||
u = _create_bend(mesh_node, u, segs, sharpness, mat)
|
||||
if _bend.is_angled():
|
||||
u = _create_end_triangle(mesh_node, u, _end.normal, _bend.get_end_triangle(), mat)
|
||||
u = _create_straight_leg(mesh_node, u, _bend.get_end(), _end.point, _end.normal, mat)
|
||||
return u
|
||||
|
||||
func get_begin() -> VisualizationSpot:
|
||||
return _begin
|
||||
|
||||
func get_leg_bend_begin() -> Vector3:
|
||||
if _bend == null:
|
||||
return (_end.point - _begin.point)/2.0
|
||||
return _bend.get_begin_triangle().get_leg_mid()
|
||||
|
||||
func get_begin_ray() -> Vector3:
|
||||
if _bend == null:
|
||||
return (_end.point - _begin.point).normalized()
|
||||
return (_bend.get_begin() - _begin.point).normalized()
|
||||
|
||||
func adjust_begin(distance : float):
|
||||
var new_begin := VisualizationSpot.new()
|
||||
new_begin.point = _begin.point + distance * get_begin_ray()
|
||||
new_begin.normal = _begin.normal
|
||||
if _check_offsets(new_begin, _end):
|
||||
_begin = new_begin
|
||||
|
||||
func get_end() -> VisualizationSpot:
|
||||
return _end
|
||||
|
||||
func get_leg_bend_end() -> Vector3:
|
||||
if _bend == null:
|
||||
return (_end.point - _begin.point)/2.0
|
||||
return _bend.get_end_triangle().get_leg_mid()
|
||||
|
||||
func get_end_left() -> Vector3:
|
||||
var segment := _end.point - get_leg_bend_end()
|
||||
var binormal := segment.cross(_end.normal).normalized()
|
||||
var half_width = binormal*_width/2.0
|
||||
return _end.point - half_width
|
||||
|
||||
func get_end_right() -> Vector3:
|
||||
var segment := _end.point - get_leg_bend_end()
|
||||
var binormal := segment.cross(_end.normal).normalized()
|
||||
var half_width = binormal*_width/2.0
|
||||
return _end.point + half_width
|
||||
|
||||
func get_end_ray() -> Vector3:
|
||||
if _bend == null:
|
||||
return (_end.point - _begin.point).normalized()
|
||||
return (_end.point - _bend.get_end()).normalized()
|
||||
|
||||
func adjust_end(distance : float):
|
||||
var new_end := VisualizationSpot.new()
|
||||
new_end.point = _end.point - distance * get_end_ray()
|
||||
new_end.normal = _end.normal
|
||||
if _check_offsets(_begin, new_end):
|
||||
_end = new_end
|
||||
|
||||
# ---------------------------------------------
|
||||
# Local Methods
|
||||
|
||||
func _check_offsets(p_begin : VisualizationSpot, p_end : VisualizationSpot) -> bool:
|
||||
var dir := (_end.point - _begin.point).normalized()
|
||||
var min_len := MIN_SEGMENT_LENGTH + EPSILON
|
||||
var max_begin := _end.point - dir * min_len
|
||||
var max_end := _begin.point + dir * min_len
|
||||
if _bend != null:
|
||||
max_begin = _bend.get_begin() - dir * min_len
|
||||
max_end = _bend.get_end() + dir * min_len
|
||||
var new_begin_dir := (max_begin - p_begin.point).normalized()
|
||||
var new_end_dir := (p_end.point - max_end).normalized()
|
||||
if new_begin_dir.dot(dir) <= 0.0:
|
||||
_error = "bend start %s is too near %s to be bent with this width and lip" % [ _begin.point, _end.point ]
|
||||
return false
|
||||
if new_end_dir.dot(dir) <= 0.0:
|
||||
_error = "bend end %s is too near %s to be bent with this width and lip" % [ _end.point, _begin.point ]
|
||||
return false
|
||||
return true
|
||||
|
||||
func _has_valid_normal() -> bool:
|
||||
var segment = _end.point - _begin.point
|
||||
var binormal = segment.cross(_begin.normal).normalized()
|
||||
if not binormal.is_normalized():
|
||||
_error = "%s to %s is parallel to normal %s" % [ _begin.point, _end.point, _begin.normal ]
|
||||
return false
|
||||
return true
|
||||
|
||||
func _is_straight() -> bool:
|
||||
if _begin.normal.is_equal_approx(_end.normal):
|
||||
var segment = _end.point - _begin.point
|
||||
if is_equal_approx(segment.dot(_begin.normal), 0.0):
|
||||
return true
|
||||
_error = "%s to %s have same normal but are not in same plane" % [ _begin.point, _end.point ]
|
||||
return false
|
||||
|
||||
func _extend_straight_leg(mesh_node : Node3D, u : float, left : Vector3, right : Vector3, begin : Vector3, end : Vector3, normal : Vector3, mat : Material):
|
||||
var segment := end - begin
|
||||
var binormal := segment.cross(normal).normalized()
|
||||
var half_width = binormal*_width/2.0
|
||||
var seg := begin - end
|
||||
var seg_len := seg.length()
|
||||
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
|
||||
st.set_uv(Vector2(u, 1))
|
||||
st.add_vertex(right)
|
||||
|
||||
st.set_uv(Vector2(u, 0))
|
||||
st.add_vertex(left)
|
||||
|
||||
st.set_uv(Vector2(u+seg_len, 1))
|
||||
st.add_vertex(end+half_width)
|
||||
|
||||
st.set_uv(Vector2(u+seg_len, 0))
|
||||
st.add_vertex(end-half_width)
|
||||
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
|
||||
return u + seg_len
|
||||
|
||||
func _create_straight_leg(mesh_node : Node3D, u : float, begin : Vector3, end : Vector3, normal : Vector3, mat : Material):
|
||||
var segment := end - begin
|
||||
var binormal := segment.cross(normal).normalized()
|
||||
var half_width = binormal*_width/2.0
|
||||
var seg := begin - end
|
||||
var seg_len := seg.length()
|
||||
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
|
||||
st.set_uv(Vector2(u, 1))
|
||||
st.add_vertex(begin+half_width)
|
||||
|
||||
st.set_uv(Vector2(u, 0))
|
||||
st.add_vertex(begin-half_width)
|
||||
|
||||
st.set_uv(Vector2(u+seg_len, 1))
|
||||
st.add_vertex(end+half_width)
|
||||
|
||||
st.set_uv(Vector2(u+seg_len, 0))
|
||||
st.add_vertex(end-half_width)
|
||||
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
|
||||
return u + seg_len
|
||||
|
||||
func _create_begin_triangle(mesh_node : Node3D, u : float, normal : Vector3, triangle : VizTriangle, mat : Material):
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
|
||||
st.set_uv(Vector2(u, 0))
|
||||
st.add_vertex(triangle.leg_left)
|
||||
st.set_uv(Vector2(u + triangle.distance, triangle.get_fwd_side()))
|
||||
st.add_vertex(triangle.leg_fwd)
|
||||
st.set_uv(Vector2(u, 1))
|
||||
st.add_vertex(triangle.leg_right)
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
return u + triangle.distance
|
||||
|
||||
func _create_end_triangle(mesh_node : Node3D, u : float, normal : Vector3, triangle : VizTriangle, mat : Material):
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
st.set_color(Color(1, 0, 0))
|
||||
st.set_normal(normal)
|
||||
|
||||
st.set_uv(Vector2(u + triangle.distance, 0))
|
||||
st.add_vertex(triangle.leg_left)
|
||||
st.set_uv(Vector2(u + triangle.distance, 1))
|
||||
st.add_vertex(triangle.leg_right)
|
||||
st.set_uv(Vector2(u, triangle.get_fwd_side()))
|
||||
st.add_vertex(triangle.leg_fwd)
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
return u + triangle.distance
|
||||
|
||||
func _create_bend(mesh_node : Node3D, u : float, segs : int, sharpness : float, mat : Material):
|
||||
var right_u := u - _bend.get_begin_triangle().distance
|
||||
var left_u := u
|
||||
if _bend.is_angled_against_curve():
|
||||
right_u = u
|
||||
left_u = u - _bend.get_begin_triangle().distance
|
||||
var arc_len := 0.0
|
||||
|
||||
var segment := _bend.get_begin() - _begin.point
|
||||
var binormal := segment.cross(_begin.normal).normalized()
|
||||
var half_width = _bend.get_half_bend_width()
|
||||
var half_width_normal := half_width.normalized()
|
||||
var st := SurfaceTool.new()
|
||||
st.begin(Mesh.PRIMITIVE_TRIANGLE_STRIP)
|
||||
st.set_normal(_begin.normal)
|
||||
st.set_uv(Vector2(right_u, 1))
|
||||
st.add_vertex(_bend.get_begin_triangle().bend_right)
|
||||
st.set_uv(Vector2(left_u, 0))
|
||||
st.add_vertex(_bend.get_begin_triangle().bend_left)
|
||||
var shift_width := _bend.get_shift_width()
|
||||
var last_point := _bend.get_arc_begin_point()
|
||||
var total_len := 0.0
|
||||
for i in range(0, segs):
|
||||
var weight := float(i) / float(segs-1)
|
||||
var cur_point := _bend.get_arc_point(weight, sharpness)
|
||||
total_len += cur_point.distance_to(last_point)
|
||||
last_point = cur_point
|
||||
total_len += _bend.get_arc_end_point().distance_to(last_point)
|
||||
last_point = _bend.get_arc_begin_point()
|
||||
for i in range(1, segs-1):
|
||||
var weight := float(i) / float(segs-1)
|
||||
var cur_point := _bend.get_arc_point(weight, sharpness)
|
||||
arc_len += cur_point.distance_to(last_point)
|
||||
var shift := shift_width * (arc_len / total_len)
|
||||
var pos := cur_point + shift - _bend.get_shift_offset()
|
||||
var cur_normal := Vector3(cur_point - last_point).normalized().cross(half_width_normal)
|
||||
last_point = cur_point
|
||||
st.set_normal(cur_normal)
|
||||
st.set_uv(Vector2(right_u + arc_len, 1))
|
||||
st.add_vertex(pos-half_width)
|
||||
st.set_uv(Vector2(left_u + arc_len, 0))
|
||||
st.add_vertex(pos+half_width)
|
||||
st.set_normal(_end.normal)
|
||||
st.set_uv(Vector2(right_u + total_len, 1))
|
||||
st.add_vertex(_bend.get_end_triangle().bend_right)
|
||||
st.set_uv(Vector2(left_u + total_len, 0))
|
||||
st.add_vertex(_bend.get_end_triangle().bend_left)
|
||||
st.set_material(mat)
|
||||
mesh_node.mesh = st.commit(mesh_node.mesh)
|
||||
u = right_u + total_len
|
||||
if _bend.is_angled_against_curve():
|
||||
u = left_u + total_len
|
||||
return u
|
||||
|
||||
func _to_string():
|
||||
if _bend != null:
|
||||
return "SLEG(%s->%s through %s)" % [ _begin, _end, _bend ]
|
||||
return "SLEG(%s->%s)" % [ _begin, _end ]
|
||||
|
1
addons/vizpath/utilities/viz_simple_leg.gd.uid
Normal file
1
addons/vizpath/utilities/viz_simple_leg.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cb1qc8ghusxos
|
46
addons/vizpath/utilities/viz_triangle.gd
Normal file
46
addons/vizpath/utilities/viz_triangle.gd
Normal file
|
@ -0,0 +1,46 @@
|
|||
extends RefCounted
|
||||
class_name VizTriangle
|
||||
|
||||
var leg_right : Vector3
|
||||
var leg_left : Vector3
|
||||
var leg_fwd : Vector3
|
||||
var bend_right : Vector3
|
||||
var bend_left : Vector3
|
||||
var distance : float
|
||||
var fwd_side : float
|
||||
|
||||
func update(dir : Vector3, join_point : Vector3, binormal : Vector3, p_width : float, p_bend_lip : float, bend_normal : Vector3, bend_side : float, curve_side : float):
|
||||
var half_width := p_width / 2.0
|
||||
if bend_side == 0:
|
||||
leg_left = join_point - half_width * binormal - p_bend_lip * dir
|
||||
leg_right = join_point + half_width * binormal - p_bend_lip * dir
|
||||
bend_left = leg_left
|
||||
bend_right = leg_right
|
||||
distance = 0.0
|
||||
else:
|
||||
var cos_theta := dir.dot(bend_side * bend_normal)
|
||||
var sin_theta := sqrt(1-cos_theta*cos_theta)
|
||||
var width := half_width / sin_theta
|
||||
var lip_distance := p_bend_lip / sin_theta
|
||||
var bend_width = width * cos_theta
|
||||
leg_left = join_point - half_width * binormal - bend_width * dir - lip_distance * dir
|
||||
leg_right = join_point + half_width * binormal - bend_width * dir - lip_distance * dir
|
||||
leg_fwd = join_point - curve_side * bend_side * half_width * binormal + bend_width * dir - lip_distance * dir
|
||||
distance = bend_width * 2.0
|
||||
if bend_side * curve_side < 0:
|
||||
bend_left = leg_left
|
||||
bend_right = leg_fwd
|
||||
fwd_side = 1.0
|
||||
else:
|
||||
bend_left = leg_fwd
|
||||
bend_right = leg_right
|
||||
fwd_side = 0.0
|
||||
|
||||
func get_fwd_side():
|
||||
return fwd_side
|
||||
|
||||
func get_leg_mid() -> Vector3:
|
||||
return leg_left - (leg_left - leg_right) / 2.0
|
||||
|
||||
func get_bend_mid() -> Vector3:
|
||||
return bend_left - (bend_left - bend_right) / 2.0
|
1
addons/vizpath/utilities/viz_triangle.gd.uid
Normal file
1
addons/vizpath/utilities/viz_triangle.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://b07jnfj4y8ef7
|
200
addons/vizpath/visualized_path.gd
Normal file
200
addons/vizpath/visualized_path.gd
Normal file
|
@ -0,0 +1,200 @@
|
|||
## Ths class is designed to create a mesh that
|
||||
## will display a path between pairs of VisualizationSpots.
|
||||
##
|
||||
## To use a VisualizedPath it must be populated with an array
|
||||
## of spots which define the local object space positions and
|
||||
## normals for the path at that point.
|
||||
##
|
||||
## The spots array can be defined programmatically such as by
|
||||
## user action (such as clicking) or defined in the editor using
|
||||
## the VizPath gizmo.
|
||||
##
|
||||
## Not all paths are valid. Putting the spots too close together
|
||||
## or with normals that do not leave enough room for bends to be
|
||||
## created with the defined path characteristics (width, inner radius,
|
||||
## etc.), will result in the path not being displayed and the "error"
|
||||
## attribute being set to the underlying problem.
|
||||
##
|
||||
|
||||
@tool
|
||||
@icon("res://addons/vizpath/images/path.png")
|
||||
extends Node3D
|
||||
class_name VisualizedPath
|
||||
|
||||
signal changed_layout
|
||||
|
||||
## The spots array defines where the path will go between.
|
||||
## See [VisualizationSpot]
|
||||
@export var spots : Array[VisualizationSpot] :
|
||||
set(p_spots):
|
||||
spots = p_spots
|
||||
for spot in spots:
|
||||
if not spot.changed.is_connected(_rebuild):
|
||||
spot.changed.connect(_rebuild)
|
||||
_rebuild()
|
||||
|
||||
## The path_width defines the width of the path, which indirectly
|
||||
## determines how tight the path can turn at a midpoint spot.
|
||||
@export_range(0.005, 100, 0.001) var path_width := 0.1 :
|
||||
set(w):
|
||||
path_width = w
|
||||
_rebuild()
|
||||
|
||||
## The inner_curve_radius defines how tight a turn can be made
|
||||
## at a midpoint spot within the path.
|
||||
@export_range(0.005, 100, 0.001) var inner_curve_radius := 0.1 :
|
||||
set(r):
|
||||
inner_curve_radius = r
|
||||
_rebuild()
|
||||
|
||||
## The num_curve_segs defines how many points will be defined in the
|
||||
## arc that are used to create a turn. More segments will
|
||||
## make a smoother UV mapping and therefore the display of associated material
|
||||
## more accurate.
|
||||
@export_range(4, 128) var num_curve_segs := 32 :
|
||||
set(r):
|
||||
num_curve_segs = r
|
||||
_rebuild()
|
||||
|
||||
## The bend_segs defines the segments in a bend of the path when transitioning
|
||||
## between two spots with normals not in the same plane.
|
||||
@export_range(4, 128) var bend_segs := 6 :
|
||||
set(r):
|
||||
bend_segs = r
|
||||
_rebuild()
|
||||
|
||||
## The bend_lip defines the distance that a segment extends from the intersection
|
||||
## of the planes defined by the beginning and ending normals when those normals
|
||||
## are not in the same plane. Making this a smaller value will make the
|
||||
## segment flatter for more of its length.
|
||||
@export_range(0.005, 100, 0.001) var bend_lip := 0.1 :
|
||||
set(r):
|
||||
bend_lip = r
|
||||
_rebuild()
|
||||
|
||||
## The bend_sharpness defines how sharp the bend in a path. Making this
|
||||
## smaller will result in a tighter bend.
|
||||
@export var bend_sharpness := 1.0 :
|
||||
set(r):
|
||||
bend_sharpness = r
|
||||
_rebuild()
|
||||
|
||||
## The path_mat is the material that will be applied to the underlying mesh
|
||||
## that displays the path. The initial spot in the path will have texture coordinates
|
||||
## that start with U equal to 0.0 and ending at the value calculated as the actual length of the path
|
||||
## in local space. The V will range between 0.0 at the left side of the path, and 1.0 at the
|
||||
## right side of the path.
|
||||
@export var path_mat : Material :
|
||||
set(m):
|
||||
path_mat = m
|
||||
_rebuild()
|
||||
|
||||
## The path_head is a resource (optional) that defines the end of the path by
|
||||
## providing an "apply" method. The provided [VizHead] resource is an example
|
||||
## that draws an arrow head on the end.
|
||||
@export var path_head : VizHead :
|
||||
set(m):
|
||||
path_head = m
|
||||
path_head.changed.connect(_rebuild)
|
||||
_rebuild()
|
||||
|
||||
## The path_tail is a resource (optional) that defines the start of the path by
|
||||
## providing an "apply" method. The provided [VizTail] resource is an example
|
||||
## that draws a rounded cap on the end.
|
||||
@export var path_tail : VizTail :
|
||||
set(m):
|
||||
path_tail = m
|
||||
path_tail.changed.connect(_rebuild)
|
||||
_rebuild()
|
||||
|
||||
@export var suppress_warnings := false :
|
||||
set(s):
|
||||
suppress_warnings = s
|
||||
_rebuild()
|
||||
|
||||
var _mesh_instance : MeshInstance3D
|
||||
var _errors : Array[String]
|
||||
|
||||
func get_triangle_mesh() -> TriangleMesh:
|
||||
if _mesh_instance.mesh != null:
|
||||
return _mesh_instance.mesh.generate_triangle_mesh()
|
||||
return null
|
||||
|
||||
func _ready():
|
||||
_mesh_instance = MeshInstance3D.new()
|
||||
add_child(_mesh_instance)
|
||||
_rebuild()
|
||||
|
||||
func _get_configuration_warnings():
|
||||
if not suppress_warnings:
|
||||
return PackedStringArray(_errors)
|
||||
return PackedStringArray()
|
||||
|
||||
func get_errors() -> Array[String]:
|
||||
return _errors
|
||||
|
||||
func _rebuild():
|
||||
_errors = []
|
||||
if _mesh_instance == null:
|
||||
return
|
||||
if spots.size() < 2:
|
||||
_errors.append("the spots array must have at least 2 entries")
|
||||
_mesh_instance.mesh = null
|
||||
var u := 0.0
|
||||
var segments : Array[VizSegment] = []
|
||||
for idx in range(1, spots.size()):
|
||||
segments.push_back(VizSegment.new(spots[idx-1], spots[idx], path_width, bend_lip))
|
||||
for idx in range(1, segments.size()):
|
||||
if segments[idx-1].is_invalid():
|
||||
_errors.push_back(segments[idx-1].get_error())
|
||||
break
|
||||
var midpoint := VizMid.new(segments[idx-1], segments[idx], path_width, inner_curve_radius)
|
||||
if midpoint.is_invalid():
|
||||
_errors.push_back(midpoint.get_error())
|
||||
break
|
||||
# Creating midpoint may invalidate prior segment
|
||||
if segments[idx-1].is_invalid():
|
||||
_errors.push_back(segments[idx-1].get_error())
|
||||
break
|
||||
if idx == 1:
|
||||
u = _add_tail(segments[idx-1], u)
|
||||
u = segments[idx-1].update_mesh(_mesh_instance, u, bend_segs, bend_sharpness, path_mat)
|
||||
u = midpoint.update_mesh(_mesh_instance, u, num_curve_segs, path_mat)
|
||||
if _errors.size() == 0:
|
||||
if segments[segments.size()-1].is_invalid():
|
||||
_errors.push_back(segments[segments.size()-1].get_error())
|
||||
else:
|
||||
if segments.size() == 1:
|
||||
u = _add_tail(segments[0], u)
|
||||
_add_head(segments[segments.size()-1], u)
|
||||
update_configuration_warnings()
|
||||
changed_layout.emit()
|
||||
|
||||
func _add_head(head : VizSegment, u : float):
|
||||
if path_head != null:
|
||||
var end := head.get_end().point
|
||||
var binormal := head.get_end_binormal()
|
||||
var left := end - binormal * path_width / 2.0
|
||||
var right := end + binormal * path_width / 2.0
|
||||
var normal := head.get_end().normal
|
||||
var direction := head.get_end_ray()
|
||||
var offset := path_head.get_offset(left, right, normal, direction)
|
||||
head.adjust_end(offset)
|
||||
u = head.update_mesh(_mesh_instance, u, bend_segs, bend_sharpness, path_mat)
|
||||
path_head.apply(_mesh_instance, u, left - direction * offset, right - direction * offset, normal, direction, path_mat)
|
||||
else:
|
||||
head.update_mesh(_mesh_instance, u, bend_segs, bend_sharpness, path_mat)
|
||||
|
||||
func _add_tail(tail : VizSegment, u : float) -> float:
|
||||
if path_tail != null:
|
||||
var begin := tail.get_begin().point
|
||||
var binormal := tail.get_begin_binormal()
|
||||
var left := begin - binormal * path_width / 2.0
|
||||
var right := begin + binormal * path_width / 2.0
|
||||
var normal := tail.get_begin().normal
|
||||
var direction := tail.get_begin_ray()
|
||||
var offset := path_tail.get_offset(left, right, normal, direction)
|
||||
tail.adjust_begin(offset)
|
||||
path_tail.apply(_mesh_instance, u, left - direction * offset, right - direction * offset, normal, direction, path_mat)
|
||||
return u + offset
|
||||
return u
|
1
addons/vizpath/visualized_path.gd.uid
Normal file
1
addons/vizpath/visualized_path.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cg3nxpmodi5j2
|
7
addons/vizpath/visualized_path.tscn
Normal file
7
addons/vizpath/visualized_path.tscn
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://b01j6blghusie"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_7md1l"]
|
||||
|
||||
[node name="visualized_path" type="Node3D"]
|
||||
script = ExtResource("1_7md1l")
|
||||
bend_sharpness = 0.0
|
15
addons/vizpath/vizpath.gd
Normal file
15
addons/vizpath/vizpath.gd
Normal file
|
@ -0,0 +1,15 @@
|
|||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
const VizpathGizmoPlugin = preload("res://addons/vizpath/vizpath_gizmo_plugin.gd")
|
||||
|
||||
var gizmo_plugin = VizpathGizmoPlugin.new()
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
gizmo_plugin.set_editor_plugin(self)
|
||||
add_node_3d_gizmo_plugin(gizmo_plugin)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_node_3d_gizmo_plugin(gizmo_plugin)
|
1
addons/vizpath/vizpath.gd.uid
Normal file
1
addons/vizpath/vizpath.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://cf8dbwlct6q32
|
80
addons/vizpath/vizpath_gizmo.gd
Normal file
80
addons/vizpath/vizpath_gizmo.gd
Normal file
|
@ -0,0 +1,80 @@
|
|||
extends EditorNode3DGizmo
|
||||
|
||||
func _redraw():
|
||||
clear()
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
if not path.changed_layout.is_connected(_redraw):
|
||||
path.changed_layout.connect(_redraw)
|
||||
|
||||
var lines = PackedVector3Array()
|
||||
for i in range(path.spots.size()):
|
||||
lines.push_back(path.spots[i].point)
|
||||
lines.push_back(path.spots[i].point + path.spots[i].normal * path.path_width * 2.0)
|
||||
|
||||
var line_material = get_plugin().get_material("line", self)
|
||||
add_lines(lines, line_material, false)
|
||||
|
||||
for i in range(path.spots.size()):
|
||||
var rotation := Quaternion(Vector3.FORWARD, path.spots[i].normal)
|
||||
var basis := Basis(rotation)
|
||||
basis = basis.scaled(Vector3(path.path_width,path.path_width,path.path_width))
|
||||
var transform := Transform3D(basis, path.spots[i].point)
|
||||
add_mesh(get_plugin().spot_mesh, line_material, transform)
|
||||
|
||||
var triangle_mesh := path.get_triangle_mesh()
|
||||
if triangle_mesh != null:
|
||||
add_collision_triangles(triangle_mesh)
|
||||
|
||||
func _subgizmos_intersect_frustum(camera : Camera3D, frustrum : Array[Plane]) -> PackedInt32Array:
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
var gizmos := PackedInt32Array()
|
||||
for i in range(path.spots.size()):
|
||||
var origin := path.global_transform * path.spots[i].point
|
||||
var any_out := false
|
||||
for plane in frustrum:
|
||||
if plane.is_point_over(origin):
|
||||
any_out = true
|
||||
if not any_out:
|
||||
gizmos.push_back(i)
|
||||
return gizmos
|
||||
|
||||
func _subgizmos_intersect_ray(camera : Camera3D, point : Vector2) -> int:
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
for i in range(path.spots.size()):
|
||||
var origin := path.global_transform * path.spots[i].point
|
||||
var p := camera.unproject_position(origin)
|
||||
if p.distance_to(point) < 20:
|
||||
return i
|
||||
return -1
|
||||
|
||||
func _get_subgizmo_transform(id : int) -> Transform3D:
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
var rotation := Quaternion(Vector3.FORWARD, path.spots[id].normal)
|
||||
var basis := Basis(rotation)
|
||||
var transform := Transform3D(basis, path.spots[id].point)
|
||||
return transform
|
||||
|
||||
func _set_subgizmo_transform(id : int, transform : Transform3D):
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
path.spots[id].point = transform.origin
|
||||
path.spots[id].normal = transform.basis * Vector3.FORWARD
|
||||
|
||||
func _commit_subgizmos( ids : PackedInt32Array, restores : Array[Transform3D], cancel : bool):
|
||||
var path := get_node_3d() as VisualizedPath
|
||||
if cancel:
|
||||
for idx in range(ids.size()):
|
||||
var spot := path.spots[ids[idx]]
|
||||
spot.point = restores[idx].origin
|
||||
spot.normal = restores[idx].basis * Vector3.FORWARD
|
||||
else:
|
||||
var vizpath_gizmo_plugin := get_plugin() as EditorNode3DGizmoPlugin
|
||||
var undo_redo = vizpath_gizmo_plugin.editor_plugin.get_undo_redo()
|
||||
undo_redo.create_action("Modify spots")
|
||||
for idx in range(ids.size()):
|
||||
var spot := path.spots[ids[idx]]
|
||||
undo_redo.add_do_property(spot, "point", spot.point)
|
||||
undo_redo.add_undo_property(spot, "point", restores[idx].origin)
|
||||
undo_redo.add_do_property(spot, "normal", spot.normal)
|
||||
undo_redo.add_undo_property(spot, "normal", restores[idx].basis * Vector3.FORWARD)
|
||||
undo_redo.commit_action()
|
||||
|
1
addons/vizpath/vizpath_gizmo.gd.uid
Normal file
1
addons/vizpath/vizpath_gizmo.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://qo6xoq0v7djx
|
24
addons/vizpath/vizpath_gizmo_plugin.gd
Normal file
24
addons/vizpath/vizpath_gizmo_plugin.gd
Normal file
|
@ -0,0 +1,24 @@
|
|||
extends EditorNode3DGizmoPlugin
|
||||
|
||||
const vizpath_gizmo = preload("res://addons/vizpath/vizpath_gizmo.gd")
|
||||
const spot_mesh = preload("res://addons/vizpath/mesh/spot.obj")
|
||||
|
||||
var editor_plugin : EditorPlugin
|
||||
|
||||
func _init():
|
||||
create_material("line", Color(1, 1, 0))
|
||||
create_handle_material("handles")
|
||||
|
||||
func _create_gizmo(node):
|
||||
if node is VisualizedPath:
|
||||
var viz_path_node := node as VisualizedPath
|
||||
var gizmo = vizpath_gizmo.new()
|
||||
return gizmo
|
||||
else:
|
||||
return null
|
||||
|
||||
func _get_gizmo_name():
|
||||
return "VizPath Gizmo"
|
||||
|
||||
func set_editor_plugin(p_plugin : EditorPlugin):
|
||||
editor_plugin = p_plugin
|
1
addons/vizpath/vizpath_gizmo_plugin.gd.uid
Normal file
1
addons/vizpath/vizpath_gizmo_plugin.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://28ida0ysqdac
|
27
default_bus_layout.tres
Normal file
27
default_bus_layout.tres
Normal file
|
@ -0,0 +1,27 @@
|
|||
[gd_resource type="AudioBusLayout" load_steps=4 format=3 uid="uid://cjoxo61mhrs7k"]
|
||||
|
||||
[sub_resource type="AudioEffectCompressor" id="1"]
|
||||
resource_name = "Compressor"
|
||||
threshold = -6.0
|
||||
ratio = 3.0
|
||||
|
||||
[sub_resource type="AudioEffectDelay" id="2"]
|
||||
resource_name = "Delay"
|
||||
|
||||
[sub_resource type="AudioEffectChorus" id="3"]
|
||||
resource_name = "Chorus"
|
||||
wet = 0.2
|
||||
|
||||
[resource]
|
||||
bus/1/name = &"Example Bus"
|
||||
bus/1/solo = false
|
||||
bus/1/mute = false
|
||||
bus/1/bypass_fx = false
|
||||
bus/1/volume_db = 0.0
|
||||
bus/1/send = &"Master"
|
||||
bus/1/effect/0/effect = SubResource("1")
|
||||
bus/1/effect/0/enabled = true
|
||||
bus/1/effect/1/effect = SubResource("2")
|
||||
bus/1/effect/1/enabled = true
|
||||
bus/1/effect/2/effect = SubResource("3")
|
||||
bus/1/effect/2/enabled = false
|
7
default_env.tres
Normal file
7
default_env.tres
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="Environment" load_steps=2 format=3 uid="uid://bp13sdq75jfyy"]
|
||||
|
||||
[sub_resource type="Sky" id="1"]
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
sky = SubResource("1")
|
76
example/vizpath/bend_modes/bend_modes.tscn
Normal file
76
example/vizpath/bend_modes/bend_modes.tscn
Normal file
|
@ -0,0 +1,76 @@
|
|||
[gd_scene load_steps=12 format=3 uid="uid://cjl5544idple4"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_jrlnd"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_4hfv6"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_hf8la"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_s8kkd"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(0, 0, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_7ts2q"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(-0.121931, 0.5, -0.144112)
|
||||
normal = Vector3(0, 0.397131, 0.917762)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_gt1gn"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(0, 0, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_g7sew"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(0.104292, 0.5, -0.144112)
|
||||
normal = Vector3(0, 0.369583, 0.929198)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_in6um"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(0, 0, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_prkqv"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(0.138177, 0.5, 0.0752829)
|
||||
normal = Vector3(0, -0.390349, 0.920667)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_gsc4k"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(-0.00201809, 0, 0)
|
||||
normal = Vector3(0.230778, 0.15166, 0.961114)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_jodll"]
|
||||
script = ExtResource("2_4hfv6")
|
||||
point = Vector3(-0.104844, 0.5, 0.0752829)
|
||||
normal = Vector3(0, -0.629649, 0.776879)
|
||||
|
||||
[node name="bend_modes" type="Node3D"]
|
||||
|
||||
[node name="pos_bend_pos_curve" type="Node3D" parent="."]
|
||||
script = ExtResource("1_jrlnd")
|
||||
spots = Array[ExtResource("2_4hfv6")]([SubResource("Resource_s8kkd"), SubResource("Resource_7ts2q")])
|
||||
path_mat = ExtResource("3_hf8la")
|
||||
|
||||
[node name="neg_bend_pos_curve" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.215276, 0, 0)
|
||||
script = ExtResource("1_jrlnd")
|
||||
spots = Array[ExtResource("2_4hfv6")]([SubResource("Resource_gt1gn"), SubResource("Resource_g7sew")])
|
||||
path_mat = ExtResource("3_hf8la")
|
||||
|
||||
[node name="pos_bend_neg_curve" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.444013, 0, 0)
|
||||
script = ExtResource("1_jrlnd")
|
||||
spots = Array[ExtResource("2_4hfv6")]([SubResource("Resource_in6um"), SubResource("Resource_prkqv")])
|
||||
path_mat = ExtResource("3_hf8la")
|
||||
|
||||
[node name="neg_bend_neg_curve" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.852877, 0, 0)
|
||||
script = ExtResource("1_jrlnd")
|
||||
spots = Array[ExtResource("2_4hfv6")]([SubResource("Resource_gsc4k"), SubResource("Resource_jodll")])
|
||||
path_mat = ExtResource("3_hf8la")
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.981132, -0.0697522, 0.180319, 0, 0.932653, 0.360776, -0.193339, -0.353969, 0.915055, 0.718682, 0.603321, 0.999084)
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.74374, 0.668469, 0, -0.668469, 0.74374, 0, 1.44215, 1.63761)
|
33
example/vizpath/bend_modes/bend_modes2.tscn
Normal file
33
example/vizpath/bend_modes/bend_modes2.tscn
Normal file
|
@ -0,0 +1,33 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://cgalf6c17i3u5"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_bfmfh"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_rhyv7"]
|
||||
[ext_resource type="Material" uid="uid://bb6vecpbvsco2" path="res://example/common/materials/green.tres" id="3_0i5gn"]
|
||||
[ext_resource type="Resource" uid="uid://ca6a3fjxcmbhc" path="res://addons/vizpath/resources/viz_head.tres" id="4_iru8o"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_fbtus"]
|
||||
script = ExtResource("2_rhyv7")
|
||||
point = Vector3(0, 0.094, -0.171)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_o2yh3"]
|
||||
script = ExtResource("2_rhyv7")
|
||||
point = Vector3(0.271296, 0.508832, -0.373052)
|
||||
normal = Vector3(0.564135, -0.105104, 0.818965)
|
||||
|
||||
[node name="bend_modes" type="Node3D"]
|
||||
|
||||
[node name="one_leg2" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0116525, -0.0119494, 0.00156734)
|
||||
script = ExtResource("1_bfmfh")
|
||||
spots = Array[ExtResource("2_rhyv7")]([SubResource("Resource_fbtus"), SubResource("Resource_o2yh3")])
|
||||
path_width = 0.08
|
||||
bend_lip = 0.01
|
||||
path_mat = ExtResource("3_0i5gn")
|
||||
path_head = ExtResource("4_iru8o")
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.866918, -0.0684906, 0.493722, 0, 0.990515, 0.137407, -0.49845, -0.119121, 0.858696, 0.397118, 0.326159, 0.203121)
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.74374, 0.668469, 0, -0.668469, 0.74374, 0, 1.44215, 1.63761)
|
7
example/vizpath/common/materials/green.tres
Normal file
7
example/vizpath/common/materials/green.tres
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="StandardMaterial3D" format=3 uid="uid://bb6vecpbvsco2"]
|
||||
|
||||
[resource]
|
||||
transparency = 1
|
||||
cull_mode = 2
|
||||
albedo_color = Color(0, 1, 0.00392157, 0.631373)
|
||||
emission = Color(0, 1, 0, 1)
|
7
example/vizpath/common/materials/move.tres
Normal file
7
example/vizpath/common/materials/move.tres
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://c4qytbc7juuoa"]
|
||||
|
||||
[ext_resource type="Shader" path="res://example/vizpath/common/shaders/move.gdshader" id="1_obwa6"]
|
||||
|
||||
[resource]
|
||||
render_priority = 0
|
||||
shader = ExtResource("1_obwa6")
|
7
example/vizpath/common/materials/red.tres
Normal file
7
example/vizpath/common/materials/red.tres
Normal file
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="StandardMaterial3D" format=3 uid="uid://cioqoqh7f8l87"]
|
||||
|
||||
[resource]
|
||||
transparency = 1
|
||||
cull_mode = 2
|
||||
albedo_color = Color(1, 0, 0.00392157, 0.631373)
|
||||
emission = Color(0, 1, 0, 1)
|
3
example/vizpath/common/materials/white.tres
Normal file
3
example/vizpath/common/materials/white.tres
Normal file
|
@ -0,0 +1,3 @@
|
|||
[gd_resource type="StandardMaterial3D" format=3 uid="uid://p3gog0gxawyp"]
|
||||
|
||||
[resource]
|
22
example/vizpath/common/mesh/hex-tile.mtl
Normal file
22
example/vizpath/common/mesh/hex-tile.mtl
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Blender 3.5.0 MTL File: 'hex-tile.blend'
|
||||
# www.blender.org
|
||||
|
||||
newmtl Face
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.078428 0.800000 0.056291
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl Hex
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
83
example/vizpath/common/mesh/hex-tile.obj
Normal file
83
example/vizpath/common/mesh/hex-tile.obj
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Blender 3.5.0
|
||||
# www.blender.org
|
||||
mtllib hex-tile.mtl
|
||||
o Circle
|
||||
v 0.000000 0.000000 -1.000000
|
||||
v -0.866025 0.000000 -0.500000
|
||||
v -0.866025 0.000000 0.500000
|
||||
v 0.000000 0.000000 1.000000
|
||||
v 0.866025 0.000000 0.500000
|
||||
v 0.866025 0.000000 -0.500000
|
||||
v 0.000000 0.499561 -0.907686
|
||||
v -0.786079 0.499561 -0.453843
|
||||
v -0.786079 0.499561 0.453843
|
||||
v 0.000000 0.499561 0.907686
|
||||
v 0.786079 0.499561 0.453843
|
||||
v 0.786079 0.499561 -0.453843
|
||||
v -0.866025 0.499561 -0.500000
|
||||
v 0.000000 0.499561 -1.000000
|
||||
v -0.866025 0.499561 0.500000
|
||||
v 0.000000 0.499561 1.000000
|
||||
v 0.866025 0.499561 0.500000
|
||||
v 0.866025 0.499561 -0.500000
|
||||
v -0.000000 0.458301 -0.907686
|
||||
v -0.786079 0.458301 -0.453843
|
||||
v -0.786079 0.458301 0.453843
|
||||
v -0.000000 0.458301 0.907686
|
||||
v 0.786079 0.458301 0.453843
|
||||
v 0.786079 0.458301 -0.453843
|
||||
vn 0.5000 -0.0000 -0.8660
|
||||
vn 0.5000 -0.0000 0.8660
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn 1.0000 -0.0000 -0.0000
|
||||
vn -0.5000 -0.0000 0.8660
|
||||
vn -0.5000 -0.0000 -0.8660
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
s 0
|
||||
usemtl Face
|
||||
f 20/20/8 21/21/8 22/22/8 23/23/8 24/24/8 19/19/8
|
||||
usemtl Hex
|
||||
f 1/1/1 14/14/1 18/18/1 6/6/1
|
||||
f 5/5/2 17/17/2 16/16/2 4/4/2
|
||||
f 3/3/3 15/15/3 13/13/3 2/2/3
|
||||
f 6/6/4 18/18/4 17/17/4 5/5/4
|
||||
f 4/4/5 16/16/5 15/15/5 3/3/5
|
||||
f 2/2/6 13/13/6 14/14/6 1/1/6
|
||||
f 9/9/4 21/21/4 20/20/4 8/8/4
|
||||
f 2/2/7 1/1/7 6/6/7 5/5/7 4/4/7 3/3/7
|
||||
f 7/7/8 14/14/8 13/13/8 8/8/8
|
||||
f 8/8/8 13/13/8 15/15/8 9/9/8
|
||||
f 9/9/8 15/15/8 16/16/8 10/10/8
|
||||
f 10/10/8 16/16/8 17/17/8 11/11/8
|
||||
f 11/11/8 17/17/8 18/18/8 12/12/8
|
||||
f 12/12/8 18/18/8 14/14/8 7/7/8
|
||||
f 12/12/3 24/24/3 23/23/3 11/11/3
|
||||
f 10/10/1 22/22/1 21/21/1 9/9/1
|
||||
f 8/8/2 20/20/2 19/19/2 7/7/2
|
||||
f 7/7/5 19/19/5 24/24/5 12/12/5
|
||||
f 11/11/6 23/23/6 22/22/6 10/10/6
|
25
example/vizpath/common/mesh/hex-tile.obj.import
Normal file
25
example/vizpath/common/mesh/hex-tile.obj.import
Normal file
|
@ -0,0 +1,25 @@
|
|||
[remap]
|
||||
|
||||
importer="wavefront_obj"
|
||||
importer_version=1
|
||||
type="Mesh"
|
||||
uid="uid://burem3qbp7oti"
|
||||
path="res://.godot/imported/hex-tile.obj-ffebd078b94c8039e36db52918aaa2d8.mesh"
|
||||
|
||||
[deps]
|
||||
|
||||
files=["res://.godot/imported/hex-tile.obj-ffebd078b94c8039e36db52918aaa2d8.mesh"]
|
||||
|
||||
source_file="res://example/vizpath/common/mesh/hex-tile.obj"
|
||||
dest_files=["res://.godot/imported/hex-tile.obj-ffebd078b94c8039e36db52918aaa2d8.mesh", "res://.godot/imported/hex-tile.obj-ffebd078b94c8039e36db52918aaa2d8.mesh"]
|
||||
|
||||
[params]
|
||||
|
||||
generate_tangents=true
|
||||
generate_lods=true
|
||||
generate_shadow_mesh=true
|
||||
generate_lightmap_uv2=false
|
||||
generate_lightmap_uv2_texel_size=0.2
|
||||
scale_mesh=Vector3(1, 1, 1)
|
||||
offset_mesh=Vector3(0, 0, 0)
|
||||
force_disable_mesh_compression=false
|
12
example/vizpath/common/mesh/piece.mtl
Normal file
12
example/vizpath/common/mesh/piece.mtl
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Blender 3.5.0 MTL File: 'hex-tile.blend'
|
||||
# www.blender.org
|
||||
|
||||
newmtl piece
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.046634 0.034524
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 2
|
1043
example/vizpath/common/mesh/piece.obj
Normal file
1043
example/vizpath/common/mesh/piece.obj
Normal file
File diff suppressed because it is too large
Load diff
25
example/vizpath/common/mesh/piece.obj.import
Normal file
25
example/vizpath/common/mesh/piece.obj.import
Normal file
|
@ -0,0 +1,25 @@
|
|||
[remap]
|
||||
|
||||
importer="wavefront_obj"
|
||||
importer_version=1
|
||||
type="Mesh"
|
||||
uid="uid://brfhulgwa6r66"
|
||||
path="res://.godot/imported/piece.obj-248a7c726ba7f768f252db36a9d151af.mesh"
|
||||
|
||||
[deps]
|
||||
|
||||
files=["res://.godot/imported/piece.obj-248a7c726ba7f768f252db36a9d151af.mesh"]
|
||||
|
||||
source_file="res://example/vizpath/common/mesh/piece.obj"
|
||||
dest_files=["res://.godot/imported/piece.obj-248a7c726ba7f768f252db36a9d151af.mesh", "res://.godot/imported/piece.obj-248a7c726ba7f768f252db36a9d151af.mesh"]
|
||||
|
||||
[params]
|
||||
|
||||
generate_tangents=true
|
||||
generate_lods=true
|
||||
generate_shadow_mesh=true
|
||||
generate_lightmap_uv2=false
|
||||
generate_lightmap_uv2_texel_size=0.2
|
||||
scale_mesh=Vector3(1, 1, 1)
|
||||
offset_mesh=Vector3(0, 0, 0)
|
||||
force_disable_mesh_compression=false
|
26
example/vizpath/common/shaders/move.gdshader
Normal file
26
example/vizpath/common/shaders/move.gdshader
Normal file
|
@ -0,0 +1,26 @@
|
|||
shader_type spatial;
|
||||
render_mode blend_mix,cull_back,diffuse_burley,specular_schlick_ggx,depth_draw_opaque;
|
||||
|
||||
const vec3 color = vec3(0.000000000, 0.415686011, 1.000000000);
|
||||
varying float elapsed_time;
|
||||
|
||||
float gradient_fct(float x, float y) {
|
||||
if ((y > 0.1) && (y < 0.9)) {
|
||||
if (x < 0.4) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
elapsed_time = TIME;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec2 uv = UV;
|
||||
// float alpha = gradient_fct(fract(uv.x*30.0), uv.y);
|
||||
float alpha = gradient_fct(fract(uv.x*10.0 - elapsed_time*1.5), uv.y);
|
||||
ALBEDO = color;
|
||||
ALPHA = alpha;
|
||||
}
|
1
example/vizpath/common/shaders/move.gdshader.uid
Normal file
1
example/vizpath/common/shaders/move.gdshader.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://7b467fbb45fx
|
139
example/vizpath/hex/hex.tscn
Normal file
139
example/vizpath/hex/hex.tscn
Normal file
|
@ -0,0 +1,139 @@
|
|||
[gd_scene load_steps=15 format=3 uid="uid://c7ir0cihwsbdf"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_1yvne"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_6erg5"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/vizpath/common/materials/move.tres" id="3_1vu2e"]
|
||||
[ext_resource type="Resource" uid="uid://ca6a3fjxcmbhc" path="res://addons/vizpath/resources/viz_head.tres" id="4_g20v5"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://burem3qbp7oti" path="res://example/vizpath/common/mesh/hex-tile.obj" id="4_kooas"]
|
||||
[ext_resource type="Resource" uid="uid://dnaxoh1d4t82c" path="res://addons/vizpath/resources/viz_tail.tres" id="5_ty3ba"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://brfhulgwa6r66" path="res://example/vizpath/common/mesh/piece.obj" id="5_w2ftf"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_qgkxi"]
|
||||
script = ExtResource("2_6erg5")
|
||||
point = Vector3(0.12001, 0, 1.24569)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_s7b42"]
|
||||
script = ExtResource("2_6erg5")
|
||||
point = Vector3(1.0056, 0, -0.279287)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_lfmsk"]
|
||||
script = ExtResource("2_6erg5")
|
||||
point = Vector3(0.110618, 0.512924, -1.88396)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_8kju7"]
|
||||
script = ExtResource("2_6erg5")
|
||||
point = Vector3(-1.47883, 0.0551448, -1.76383)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tygq4"]
|
||||
albedo_color = Color(0.678431, 0.486275, 0.27451, 1)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1lbs8"]
|
||||
albedo_color = Color(0.670588, 0.658824, 0, 1)
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4bfck"]
|
||||
|
||||
[node name="hex" type="Node3D"]
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.992762, -0.0669817, 0.0996872, 0, 0.830033, 0.557714, -0.1201, -0.553677, 0.824025, 1.35237, 2.1656, 3.18067)
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.840718, 0.541473, 0, -0.541473, 0.840718, 0, 2.14547, 0)
|
||||
|
||||
[node name="path" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.63023, -0.203269, -1.17328)
|
||||
script = ExtResource("1_1yvne")
|
||||
spots = Array[ExtResource("2_6erg5")]([SubResource("Resource_qgkxi"), SubResource("Resource_s7b42"), SubResource("Resource_lfmsk"), SubResource("Resource_8kju7")])
|
||||
path_width = 0.3
|
||||
path_mat = ExtResource("3_1vu2e")
|
||||
path_head = ExtResource("4_g20v5")
|
||||
path_tail = ExtResource("5_ty3ba")
|
||||
|
||||
[node name="map" type="Node3D" parent="."]
|
||||
|
||||
[node name="hex1" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.4682, 0)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex2" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.72963, -1.4682, 0)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex3" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.835999, -1.4682, -1.45365)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex4" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.56511, -1.4682, -1.45365)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex5" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.933231, -1.4682, -1.46365)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex6" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0469695, -1.4682, -2.96501)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex7" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71215, -1.20709, -2.97501)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
surface_material_override/0 = SubResource("StandardMaterial3D_tygq4")
|
||||
|
||||
[node name="hex8" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.75632, -1.4682, -2.96501)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex9" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.48265, -1.4682, -2.96501)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex10" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.846, -1.4682, -4.47957)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex11" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.59512, -1.4682, -4.50046)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex12" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.903228, -1.33035, -4.49046)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
surface_material_override/0 = SubResource("StandardMaterial3D_1lbs8")
|
||||
|
||||
[node name="hex13" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0200016, -1.4682, -6.00538)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="hex14" type="MeshInstance3D" parent="map"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.71963, -1.4682, -6.00538)
|
||||
mesh = ExtResource("4_kooas")
|
||||
skeleton = NodePath("../..")
|
||||
|
||||
[node name="piece1" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1.06485, 0, 0, 0, 1.06485, 1.72758, -0.95635, 0.0769689)
|
||||
mesh = ExtResource("5_w2ftf")
|
||||
metadata/_edit_group_ = true
|
||||
|
||||
[node name="piece2" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1.06485, 0, 0, 0, 1.06485, -0.0146859, -0.95635, -2.9499)
|
||||
mesh = ExtResource("5_w2ftf")
|
||||
surface_material_override/0 = SubResource("StandardMaterial3D_4bfck")
|
||||
metadata/_edit_group_ = true
|
37
example/vizpath/mid_bend/mid_bend.tscn
Normal file
37
example/vizpath/mid_bend/mid_bend.tscn
Normal file
|
@ -0,0 +1,37 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://j7iynhxho7c0"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_61koq"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_8om43"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_dlu5u"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_rlmvv"]
|
||||
script = ExtResource("2_8om43")
|
||||
point = Vector3(-0.019576, 0.330117, 0.308354)
|
||||
normal = Vector3(-0.232683, 0, 0.972552)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_4ssj4"]
|
||||
script = ExtResource("2_8om43")
|
||||
point = Vector3(0.353746, 0.567193, 0.0288121)
|
||||
normal = Vector3(-0.283569, 0, 0.958952)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_wiucl"]
|
||||
script = ExtResource("2_8om43")
|
||||
point = Vector3(0.439841, 0.99525, -0.447174)
|
||||
normal = Vector3(0.0776629, 0.993597, 0.0820541)
|
||||
|
||||
[node name="mid_bend" type="Node3D"]
|
||||
|
||||
[node name="path2" type="Node3D" parent="."]
|
||||
transform = Transform3D(0.99644, 0, 0.0843039, 0, 1, 0, -0.0843039, 0, 0.99644, 0.293748, 0, 0)
|
||||
script = ExtResource("1_61koq")
|
||||
spots = Array[ExtResource("2_8om43")]([SubResource("Resource_rlmvv"), SubResource("Resource_4ssj4"), SubResource("Resource_wiucl")])
|
||||
path_width = 0.01
|
||||
inner_curve_radius = 0.05
|
||||
bend_sharpness = 0.307
|
||||
path_mat = ExtResource("3_dlu5u")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.91249, -0.154231, 0.378914, 0, 0.926213, 0.377, -0.4091, -0.344008, 0.84516, 0.951467, 0.854797, 0.660344)
|
31
example/vizpath/mid_bend/mid_bend2.tscn
Normal file
31
example/vizpath/mid_bend/mid_bend2.tscn
Normal file
|
@ -0,0 +1,31 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://dmokry5wki4la"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_tdmdc"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_ed7de"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_jou7f"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_lat08"]
|
||||
script = ExtResource("2_ed7de")
|
||||
point = Vector3(-0.019576, 0.330117, 0.308354)
|
||||
normal = Vector3(-0.883153, 0, 0.469085)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_aq3dt"]
|
||||
script = ExtResource("2_ed7de")
|
||||
point = Vector3(0.492358, 0.739297, 0.295264)
|
||||
normal = Vector3(0.356353, 0.164684, 0.919724)
|
||||
|
||||
[node name="mid_bend" type="Node3D"]
|
||||
|
||||
[node name="path2" type="Node3D" parent="."]
|
||||
transform = Transform3D(0.99644, 0, 0.0843039, 0, 1, 0, -0.0843039, 0, 0.99644, 0.293748, 0, 0)
|
||||
script = ExtResource("1_tdmdc")
|
||||
spots = Array[ExtResource("2_ed7de")]([SubResource("Resource_lat08"), SubResource("Resource_aq3dt")])
|
||||
path_width = 0.05
|
||||
inner_curve_radius = 0.05
|
||||
path_mat = ExtResource("3_jou7f")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.91249, -0.154231, 0.378914, 0, 0.926213, 0.377, -0.4091, -0.344008, 0.84516, 0.951467, 0.854797, 0.868185)
|
30
example/vizpath/one_bend/one_bend.tscn
Normal file
30
example/vizpath/one_bend/one_bend.tscn
Normal file
|
@ -0,0 +1,30 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://8d5a3q2jlkpu"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_1isnb"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_hrr5y"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_ef85y"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_4ssj4"]
|
||||
script = ExtResource("2_hrr5y")
|
||||
point = Vector3(0, 0, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_1jroy"]
|
||||
script = ExtResource("2_hrr5y")
|
||||
point = Vector3(-0.424557, 0.5, -0.472062)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[node name="one_bend" type="Node3D"]
|
||||
|
||||
[node name="path" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.130919, -0.0840064, 0)
|
||||
script = ExtResource("1_1isnb")
|
||||
spots = Array[ExtResource("2_hrr5y")]([SubResource("Resource_4ssj4"), SubResource("Resource_1jroy")])
|
||||
bend_segs = 8
|
||||
path_mat = ExtResource("3_ef85y")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.84005, 0.364052, -0.402221, 0, 0.741409, 0.671053, 0.542508, -0.563718, 0.622821, -0.44569, 0.886962, 0.464843)
|
29
example/vizpath/straight/straight.tscn
Normal file
29
example/vizpath/straight/straight.tscn
Normal file
|
@ -0,0 +1,29 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://dwirjkvwkv75u"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_heaqv"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_flef7"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_fyvtr"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_o651y"]
|
||||
script = ExtResource("2_flef7")
|
||||
point = Vector3(0.359788, 0.518665, -0.0131293)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_4ssj4"]
|
||||
script = ExtResource("2_flef7")
|
||||
point = Vector3(-0.288032, 0.444831, -0.170361)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[node name="straight" type="Node3D"]
|
||||
|
||||
[node name="path" type="Node3D" parent="."]
|
||||
script = ExtResource("1_heaqv")
|
||||
spots = Array[ExtResource("2_flef7")]([SubResource("Resource_o651y"), SubResource("Resource_4ssj4")])
|
||||
bend_lip = 0.05
|
||||
path_mat = ExtResource("3_fyvtr")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(0.631322, 0.489607, -0.60143, 0, 0.775517, 0.631326, 0.775521, -0.39857, 0.489601, -0.535581, 0.968096, 0.314222)
|
37
example/vizpath/three_points/three_points.tscn
Normal file
37
example/vizpath/three_points/three_points.tscn
Normal file
|
@ -0,0 +1,37 @@
|
|||
[gd_scene load_steps=7 format=3 uid="uid://3tjj6ldef4lo"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_2jxs7"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_dhnds"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/common/materials/move.tres" id="3_cjil2"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_o651y"]
|
||||
script = ExtResource("2_dhnds")
|
||||
point = Vector3(0.182239, 0.0924503, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_2clix"]
|
||||
script = ExtResource("2_dhnds")
|
||||
point = Vector3(-0.0228493, 0.395443, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_bwwrl"]
|
||||
script = ExtResource("2_dhnds")
|
||||
point = Vector3(0.90799, 0.724231, 0)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[node name="three_points" type="Node3D"]
|
||||
|
||||
[node name="path" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.778687, -0.65607, 0)
|
||||
script = ExtResource("1_2jxs7")
|
||||
spots = Array[ExtResource("2_dhnds")]([SubResource("Resource_o651y"), SubResource("Resource_2clix"), SubResource("Resource_bwwrl")])
|
||||
path_width = 0.05
|
||||
num_curve_segs = 60
|
||||
bend_segs = 10
|
||||
path_mat = ExtResource("3_cjil2")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.24272)
|
10
example/vizpath/two_bend/two_bend.gd
Normal file
10
example/vizpath/two_bend/two_bend.gd
Normal file
|
@ -0,0 +1,10 @@
|
|||
extends Node3D
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(_delta):
|
||||
pass
|
1
example/vizpath/two_bend/two_bend.gd.uid
Normal file
1
example/vizpath/two_bend/two_bend.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://dh5elyacabw3m
|
62
example/vizpath/two_bend/two_bend.tscn
Normal file
62
example/vizpath/two_bend/two_bend.tscn
Normal file
|
@ -0,0 +1,62 @@
|
|||
[gd_scene load_steps=12 format=3 uid="uid://c55gugehr1r3q"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_3gjiw"]
|
||||
[ext_resource type="Script" path="res://example/two_bend/two_bend.gd" id="1_avpar"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_xhjfb"]
|
||||
[ext_resource type="Material" uid="uid://bb6vecpbvsco2" path="res://example/vizpath/common/materials/green.tres" id="4_dnqvd"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/vizpath/common/materials/move.tres" id="5_cr2c7"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_m5l7s"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(0.576658, 0.1, 0.050687)
|
||||
normal = Vector3(1, 0, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_swer1"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(-0.3, 0.507225, 0)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_u3fio"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(-0.3, 0.1, 0.3)
|
||||
normal = Vector3(0, 0, 1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_h2nq6"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(-0.0696068, 0.591908, 0)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_cl30b"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(-0.492063, 0.105, -0.892321)
|
||||
normal = Vector3(0, 0, -1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_eg1h8"]
|
||||
script = ExtResource("2_xhjfb")
|
||||
point = Vector3(0.557, 0.369389, -0.617691)
|
||||
normal = Vector3(0.988393, 0, 0.151917)
|
||||
|
||||
[node name="two_bend" type="Node3D"]
|
||||
script = ExtResource("1_avpar")
|
||||
|
||||
[node name="path1" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.125237)
|
||||
script = ExtResource("1_3gjiw")
|
||||
spots = Array[ExtResource("2_xhjfb")]([SubResource("Resource_m5l7s"), SubResource("Resource_swer1"), SubResource("Resource_u3fio")])
|
||||
path_width = 0.05
|
||||
path_mat = ExtResource("4_dnqvd")
|
||||
|
||||
[node name="path2" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.0673205)
|
||||
script = ExtResource("1_3gjiw")
|
||||
spots = Array[ExtResource("2_xhjfb")]([SubResource("Resource_m5l7s"), SubResource("Resource_h2nq6"), SubResource("Resource_cl30b"), SubResource("Resource_eg1h8")])
|
||||
inner_curve_radius = 0.05
|
||||
bend_segs = 8
|
||||
bend_lip = 0.05
|
||||
path_mat = ExtResource("5_cr2c7")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.948013, 0.318231, 0, -0.318231, 0.948013, -0.143137, 0.97094, 1.10501)
|
41
example/vizpath/two_points/two_points.tscn
Normal file
41
example/vizpath/two_points/two_points.tscn
Normal file
|
@ -0,0 +1,41 @@
|
|||
[gd_scene load_steps=9 format=3 uid="uid://lya0l1b74f08"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/vizpath/visualized_path.gd" id="1_2ehhl"]
|
||||
[ext_resource type="Script" path="res://addons/vizpath/resources/spot.gd" id="2_7kv0e"]
|
||||
[ext_resource type="Material" uid="uid://c4qytbc7juuoa" path="res://example/vizpath/common/materials/move.tres" id="3_pq303"]
|
||||
[ext_resource type="Resource" uid="uid://ca6a3fjxcmbhc" path="res://addons/vizpath/resources/viz_head.tres" id="4_exeba"]
|
||||
[ext_resource type="Resource" uid="uid://dnaxoh1d4t82c" path="res://addons/vizpath/resources/viz_tail.tres" id="5_76glu"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_o651y"]
|
||||
script = ExtResource("2_7kv0e")
|
||||
point = Vector3(0, 0.114297, -0.0441982)
|
||||
normal = Vector3(0, 0, -1)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_2clix"]
|
||||
script = ExtResource("2_7kv0e")
|
||||
point = Vector3(-0.346671, 0.276115, 0.160896)
|
||||
normal = Vector3(-1, 0, 0)
|
||||
|
||||
[sub_resource type="Resource" id="Resource_rwwtj"]
|
||||
script = ExtResource("2_7kv0e")
|
||||
point = Vector3(-0.140459, 0.608702, 0.100734)
|
||||
normal = Vector3(0, 1, 0)
|
||||
|
||||
[node name="two_points" type="Node3D"]
|
||||
|
||||
[node name="path" type="Node3D" parent="."]
|
||||
transform = Transform3D(-0.992377, 0, -0.123238, 0, 1, 0, 0.123238, 0, -0.992377, 0, 0, 0)
|
||||
script = ExtResource("1_2ehhl")
|
||||
spots = Array[ExtResource("2_7kv0e")]([SubResource("Resource_o651y"), SubResource("Resource_2clix"), SubResource("Resource_rwwtj")])
|
||||
path_width = 0.05
|
||||
inner_curve_radius = 0.01
|
||||
bend_lip = 0.05
|
||||
path_mat = ExtResource("3_pq303")
|
||||
path_head = ExtResource("4_exeba")
|
||||
path_tail = ExtResource("5_76glu")
|
||||
|
||||
[node name="light" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.828627, 0.559801, 0, -0.559801, 0.828627, 0, 1.47828, 1.16019)
|
||||
|
||||
[node name="camera" type="Camera3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.24272)
|
BIN
icon.png
Normal file
BIN
icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
34
icon.png.import
Normal file
34
icon.png.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c0wdd27awcglc"
|
||||
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -91,6 +91,6 @@ layout_mode = 2
|
|||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 4
|
||||
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/ResumeButton" to="." method="_on_resume_button_pressed"]
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/ResumeButton" to="." method="_on_button_pressed"]
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/ResumeButton" to="." method="_on_resume_button_pressed"]
|
||||
[connection signal="pressed" from="MarginContainer/VBoxContainer/ExitButton" to="." method="_on_exit_button_pressed"]
|
||||
|
|
81
show_spectrum.gd
Normal file
81
show_spectrum.gd
Normal file
|
@ -0,0 +1,81 @@
|
|||
extends Node2D
|
||||
|
||||
|
||||
const VU_COUNT = 16
|
||||
const FREQ_MAX = 11050.0
|
||||
|
||||
const WIDTH = 800
|
||||
const HEIGHT = 250
|
||||
const HEIGHT_SCALE = 8.0
|
||||
const MIN_DB = 60
|
||||
const ANIMATION_SPEED = 0.1
|
||||
|
||||
var spectrum
|
||||
var min_values = []
|
||||
var max_values = []
|
||||
|
||||
|
||||
func _draw():
|
||||
var w = WIDTH / VU_COUNT
|
||||
for i in range(VU_COUNT):
|
||||
var min_height = min_values[i]
|
||||
var max_height = max_values[i]
|
||||
var height = lerp(min_height, max_height, ANIMATION_SPEED)
|
||||
|
||||
draw_rect(
|
||||
Rect2(w * i, HEIGHT - height, w - 2, height),
|
||||
Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 0.6)
|
||||
)
|
||||
draw_line(
|
||||
Vector2(w * i, HEIGHT - height),
|
||||
Vector2(w * i + w - 2, HEIGHT - height),
|
||||
Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 1.0),
|
||||
2.0,
|
||||
true
|
||||
)
|
||||
|
||||
# Draw a reflection of the bars with lower opacity.
|
||||
draw_rect(
|
||||
Rect2(w * i, HEIGHT, w - 2, height),
|
||||
Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 0.6) * Color(1, 1, 1, 0.125)
|
||||
)
|
||||
draw_line(
|
||||
Vector2(w * i, HEIGHT + height),
|
||||
Vector2(w * i + w - 2, HEIGHT + height),
|
||||
Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 1.0) * Color(1, 1, 1, 0.125),
|
||||
2.0,
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
var data = []
|
||||
var prev_hz = 0
|
||||
|
||||
for i in range(1, VU_COUNT + 1):
|
||||
var hz = i * FREQ_MAX / VU_COUNT
|
||||
var magnitude = spectrum.get_magnitude_for_frequency_range(prev_hz, hz).length()
|
||||
var energy = clampf((MIN_DB + linear_to_db(magnitude)) / MIN_DB, 0, 1)
|
||||
var height = energy * HEIGHT * HEIGHT_SCALE
|
||||
data.append(height)
|
||||
prev_hz = hz
|
||||
|
||||
for i in range(VU_COUNT):
|
||||
if data[i] > max_values[i]:
|
||||
max_values[i] = data[i]
|
||||
else:
|
||||
max_values[i] = lerp(max_values[i], data[i], ANIMATION_SPEED)
|
||||
|
||||
if data[i] <= 0.0:
|
||||
min_values[i] = lerp(min_values[i], 0.0, ANIMATION_SPEED)
|
||||
|
||||
# Sound plays back continuously, so the graph needs to be updated every frame.
|
||||
queue_redraw()
|
||||
|
||||
|
||||
func _ready():
|
||||
spectrum = AudioServer.get_bus_effect_instance(0, 0)
|
||||
min_values.resize(VU_COUNT)
|
||||
max_values.resize(VU_COUNT)
|
||||
min_values.fill(0.0)
|
||||
max_values.fill(0.0)
|
1
show_spectrum.gd.uid
Normal file
1
show_spectrum.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://x3hrdg2smx4f
|
14
show_spectrum.tscn
Normal file
14
show_spectrum.tscn
Normal file
|
@ -0,0 +1,14 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://dsit517glos2s"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://x3hrdg2smx4f" path="res://show_spectrum.gd" id="1"]
|
||||
|
||||
[node name="ShowSpectrum" type="Node2D"]
|
||||
position = Vector2(136, 80)
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Player" type="AudioStreamPlayer" parent="."]
|
||||
autoplay = true
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="."]
|
||||
position = Vector2(0, 144)
|
||||
offset = Vector2(440, 100)
|
1
source/vizpath/.gdignore
Normal file
1
source/vizpath/.gdignore
Normal file
|
@ -0,0 +1 @@
|
|||
icon.svg
|
1
source/vizpath/.gitignore
vendored
Normal file
1
source/vizpath/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.blend[0-9]
|
BIN
source/vizpath/asset_image.xcf
Normal file
BIN
source/vizpath/asset_image.xcf
Normal file
Binary file not shown.
BIN
source/vizpath/hex-tile.blend
Normal file
BIN
source/vizpath/hex-tile.blend
Normal file
Binary file not shown.
47
source/vizpath/icon.svg
Normal file
47
source/vizpath/icon.svg
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
sodipodi:docname="icon.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.69664703"
|
||||
inkscape:cx="109.09398"
|
||||
inkscape:cy="445.70635"
|
||||
inkscape:window-width="2492"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#0000d9;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 30.753041,132.21182 c 0,0 10.010254,-15.2619 18.023962,-22.0133 8.013709,-6.7514 22.573376,-7.54391 30.155161,1.21654 7.581785,8.76044 6.189859,17.90833 18.236116,19.42593 9.9617,1.25499 21.88274,-11.14017 21.88274,-11.14017 l -5.48923,-7.62409 19.34583,2.49538 -4.21336,17.76136 -4.3721,-6.47877 c 0,0 -13.47411,13.05178 -27.817042,12.90117 -14.342932,-0.1506 -17.860759,-14.58992 -22.628979,-21.50294 -4.76822,-6.91302 -14.511224,-5.45497 -19.83986,0.35161 -5.328637,5.80657 -16.145755,19.59209 -16.145755,19.59209 z"
|
||||
id="path42"
|
||||
sodipodi:nodetypes="czzsccccczzzcc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
BIN
source/vizpath/ladder.blend
Normal file
BIN
source/vizpath/ladder.blend
Normal file
Binary file not shown.
2
source/vizpath/ladder.mtl
Normal file
2
source/vizpath/ladder.mtl
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Blender 3.5.0 MTL File: 'ladder.blend'
|
||||
# www.blender.org
|
1345
source/vizpath/ladder.obj
Normal file
1345
source/vizpath/ladder.obj
Normal file
File diff suppressed because it is too large
Load diff
BIN
source/vizpath/piece.blend
Normal file
BIN
source/vizpath/piece.blend
Normal file
Binary file not shown.
2
source/vizpath/piece.mtl
Normal file
2
source/vizpath/piece.mtl
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Blender 3.5.0 MTL File: 'ladder.blend'
|
||||
# www.blender.org
|
2547
source/vizpath/piece.obj
Normal file
2547
source/vizpath/piece.obj
Normal file
File diff suppressed because it is too large
Load diff
BIN
source/vizpath/preview_image.png
Normal file
BIN
source/vizpath/preview_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 189 KiB |
BIN
source/vizpath/spot.blend
Normal file
BIN
source/vizpath/spot.blend
Normal file
Binary file not shown.
BIN
source/vizpath/thumbnail.png
Normal file
BIN
source/vizpath/thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
source/vizpath/thumbnail.xcf
Normal file
BIN
source/vizpath/thumbnail.xcf
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue