mirror of
https://github.com/Relintai/pandemonium_engine_minimal.git
synced 2025-04-28 07:24:58 +02:00
Removed 3d nodes.
This commit is contained in:
parent
7a0bc5ed4d
commit
88b9952ce0
@ -1,149 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="AudioStreamPlayer3D" inherits="Spatial" version="4.2">
|
||||
<brief_description>
|
||||
Plays positional sound in 3D space.
|
||||
</brief_description>
|
||||
<description>
|
||||
Plays a sound effect with directed sound effects, dampens with distance if needed, generates effect of hearable position in space. For greater realism, a low-pass filter is automatically applied to distant sounds. This can be disabled by setting [member attenuation_filter_cutoff_hz] to [code]20500[/code].
|
||||
By default, audio is heard from the camera position. This can be changed by adding a [Listener] node to the scene and enabling it by calling [method Listener.make_current] on it.
|
||||
See also [AudioStreamPlayer] to play a sound non-positionally.
|
||||
[b]Note:[/b] Hiding an [AudioStreamPlayer3D] node does not disable its audio output. To temporarily disable an [AudioStreamPlayer3D]'s audio output, set [member unit_db] to a very low value like [code]-100[/code] (which isn't audible to human hearing).
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>$DOCS_URL/tutorials/audio/audio_streams.md</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_playback_position">
|
||||
<return type="float" />
|
||||
<description>
|
||||
Returns the position in the [AudioStream].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_stream_playback">
|
||||
<return type="AudioStreamPlayback" />
|
||||
<description>
|
||||
Returns the [AudioStreamPlayback] object associated with this [AudioStreamPlayer3D].
|
||||
</description>
|
||||
</method>
|
||||
<method name="play">
|
||||
<return type="void" />
|
||||
<argument index="0" name="from_position" type="float" default="0.0" />
|
||||
<description>
|
||||
Plays the audio from the given position [code]from_position[/code], in seconds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="seek">
|
||||
<return type="void" />
|
||||
<argument index="0" name="to_position" type="float" />
|
||||
<description>
|
||||
Sets the position from which audio will be played, in seconds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="stop">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Stops the audio.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="area_mask" type="int" setter="set_area_mask" getter="get_area_mask" default="1">
|
||||
Determines which [Area] layers affect the sound for reverb and audio bus effects. Areas can be used to redirect [AudioStream]s so that they play in a certain audio bus. An example of how you might use this is making a "water" area so that sounds played in the water are redirected through an audio bus to make them sound like they are being played underwater.
|
||||
</member>
|
||||
<member name="attenuation_filter_cutoff_hz" type="float" setter="set_attenuation_filter_cutoff_hz" getter="get_attenuation_filter_cutoff_hz" default="5000.0">
|
||||
Dampens audio using a low-pass filter above this frequency, in Hz. To disable the dampening effect entirely, set this to [code]20500[/code] as this frequency is above the human hearing limit.
|
||||
</member>
|
||||
<member name="attenuation_filter_db" type="float" setter="set_attenuation_filter_db" getter="get_attenuation_filter_db" default="-24.0">
|
||||
Amount how much the filter affects the loudness, in decibels.
|
||||
</member>
|
||||
<member name="attenuation_model" type="int" setter="set_attenuation_model" getter="get_attenuation_model" enum="AudioStreamPlayer3D.AttenuationModel" default="0">
|
||||
Decides if audio should get quieter with distance linearly, quadratically, logarithmically, or not be affected by distance, effectively disabling attenuation.
|
||||
</member>
|
||||
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled" default="false">
|
||||
If [code]true[/code], audio plays when the AudioStreamPlayer3D node is added to scene tree.
|
||||
</member>
|
||||
<member name="bus" type="StringName" setter="set_bus" getter="get_bus" default="@"Master"">
|
||||
The bus on which this audio is playing.
|
||||
[b]Note:[/b] When setting this property, keep in mind that no validation is performed to see if the given name matches an existing bus. This is because audio bus layouts might be loaded after this property is set. If this given name can't be resolved at runtime, it will fall back to [code]"Master"[/code].
|
||||
</member>
|
||||
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking" default="0">
|
||||
Decides in which step the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] should be calculated.
|
||||
[b]Note:[/b] Only effective if the current [Camera]'s [member Camera.doppler_tracking] property is set to a value other than [constant Camera.DOPPLER_TRACKING_DISABLED].
|
||||
</member>
|
||||
<member name="emission_angle_degrees" type="float" setter="set_emission_angle" getter="get_emission_angle" default="45.0">
|
||||
The angle in which the audio reaches cameras undampened.
|
||||
</member>
|
||||
<member name="emission_angle_enabled" type="bool" setter="set_emission_angle_enabled" getter="is_emission_angle_enabled" default="false">
|
||||
If [code]true[/code], the audio should be dampened according to the direction of the sound.
|
||||
</member>
|
||||
<member name="emission_angle_filter_attenuation_db" type="float" setter="set_emission_angle_filter_attenuation_db" getter="get_emission_angle_filter_attenuation_db" default="-12.0">
|
||||
Dampens audio if camera is outside of [member emission_angle_degrees] and [member emission_angle_enabled] is set by this factor, in decibels.
|
||||
</member>
|
||||
<member name="max_db" type="float" setter="set_max_db" getter="get_max_db" default="3.0">
|
||||
Sets the absolute maximum of the soundlevel, in decibels.
|
||||
</member>
|
||||
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0">
|
||||
Sets the distance from which the [member out_of_range_mode] takes effect. Has no effect if set to 0.
|
||||
</member>
|
||||
<member name="out_of_range_mode" type="int" setter="set_out_of_range_mode" getter="get_out_of_range_mode" enum="AudioStreamPlayer3D.OutOfRangeMode" default="0">
|
||||
Decides if audio should pause when source is outside of [member max_distance] range.
|
||||
</member>
|
||||
<member name="panning_strength" type="float" setter="set_panning_strength" getter="get_panning_strength" default="1.0">
|
||||
Scales the panning strength for this node by multiplying the base [member ProjectSettings.audio/3d_panning_strength] with this factor. Higher values will pan audio from left to right more dramatically than lower values.
|
||||
</member>
|
||||
<member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale" default="1.0">
|
||||
The pitch and the tempo of the audio, as a multiplier of the audio sample's sample rate.
|
||||
</member>
|
||||
<member name="playing" type="bool" setter="_set_playing" getter="is_playing" default="false">
|
||||
If [code]true[/code], audio is playing.
|
||||
</member>
|
||||
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
|
||||
The [AudioStream] resource to be played.
|
||||
</member>
|
||||
<member name="stream_paused" type="bool" setter="set_stream_paused" getter="get_stream_paused" default="false">
|
||||
If [code]true[/code], the playback is paused. You can resume it by setting [member stream_paused] to [code]false[/code].
|
||||
</member>
|
||||
<member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db" default="0.0">
|
||||
The base sound level unaffected by dampening, in decibels.
|
||||
</member>
|
||||
<member name="unit_size" type="float" setter="set_unit_size" getter="get_unit_size" default="1.0">
|
||||
The factor for the attenuation effect. Higher values make the sound audible over a larger distance.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="finished">
|
||||
<description>
|
||||
Emitted when the audio stops playing.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="ATTENUATION_INVERSE_DISTANCE" value="0" enum="AttenuationModel">
|
||||
Linear dampening of loudness according to distance.
|
||||
</constant>
|
||||
<constant name="ATTENUATION_INVERSE_SQUARE_DISTANCE" value="1" enum="AttenuationModel">
|
||||
Squared dampening of loudness according to distance.
|
||||
</constant>
|
||||
<constant name="ATTENUATION_LOGARITHMIC" value="2" enum="AttenuationModel">
|
||||
Logarithmic dampening of loudness according to distance.
|
||||
</constant>
|
||||
<constant name="ATTENUATION_DISABLED" value="3" enum="AttenuationModel">
|
||||
No dampening of loudness according to distance. The sound will still be heard positionally, unlike an [AudioStreamPlayer]. [constant ATTENUATION_DISABLED] can be combined with a [member max_distance] value greater than [code]0.0[/code] to achieve linear attenuation clamped to a sphere of a defined size.
|
||||
</constant>
|
||||
<constant name="OUT_OF_RANGE_MIX" value="0" enum="OutOfRangeMode">
|
||||
Mix this audio in, even when it's out of range. This increases CPU usage, but keeps the sound playing at the correct position if the camera leaves and enters the [AudioStreamPlayer3D]'s [member max_distance] radius.
|
||||
</constant>
|
||||
<constant name="OUT_OF_RANGE_PAUSE" value="1" enum="OutOfRangeMode">
|
||||
Pause this audio when it gets out of range. This decreases CPU usage, but will cause the sound to restart if the camera leaves and enters the [AudioStreamPlayer3D]'s [member max_distance] radius.
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_DISABLED" value="0" enum="DopplerTracking">
|
||||
Disables doppler tracking.
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1" enum="DopplerTracking">
|
||||
Executes doppler tracking in idle step (every rendered frame).
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2" enum="DopplerTracking">
|
||||
Executes doppler tracking in physics step (every simulated physics frame).
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BoxShape" inherits="Shape" version="4.2">
|
||||
<brief_description>
|
||||
Box shape resource.
|
||||
</brief_description>
|
||||
<description>
|
||||
3D box shape that can be a child of a [PhysicsBody] or [Area].
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="3D Physics Tests Demo">https://godotengine.org/asset-library/asset/675</link>
|
||||
<link title="3D Kinematic Character Demo">https://godotengine.org/asset-library/asset/126</link>
|
||||
<link title="3D Platformer Demo">https://godotengine.org/asset-library/asset/125</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3( 1, 1, 1 )">
|
||||
The box's half extents. The width, height and depth of this shape is twice the half extents.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,379 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="CPUParticles" inherits="GeometryInstance" version="4.2">
|
||||
<brief_description>
|
||||
CPU-based 3D particle emitter.
|
||||
</brief_description>
|
||||
<description>
|
||||
CPU-based 3D particle node used to create a variety of particle systems and effects.
|
||||
See also [Particles], which provides the same functionality with hardware acceleration, but may not run on older devices.
|
||||
[b]Note:[/b] Unlike [Particles], the visibility rect is generated on-the-fly and doesn't need to be configured by the user.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_param" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<description>
|
||||
Returns the base value of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_param_curve" qualifiers="const">
|
||||
<return type="Curve" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<description>
|
||||
Returns the [Curve] of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_param_randomness" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<description>
|
||||
Returns the randomness factor of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_particle_flag" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="flag" type="int" enum="CPUParticles.Flags" />
|
||||
<description>
|
||||
Returns the enabled state of the given flag (see [enum Flags] for options).
|
||||
</description>
|
||||
</method>
|
||||
<method name="restart">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Restarts the particle emitter.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_param">
|
||||
<return type="void" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<argument index="1" name="value" type="float" />
|
||||
<description>
|
||||
Sets the base value of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_param_curve">
|
||||
<return type="void" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<argument index="1" name="curve" type="Curve" />
|
||||
<description>
|
||||
Sets the [Curve] of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_param_randomness">
|
||||
<return type="void" />
|
||||
<argument index="0" name="param" type="int" enum="CPUParticles.Parameter" />
|
||||
<argument index="1" name="randomness" type="float" />
|
||||
<description>
|
||||
Sets the randomness factor of the parameter specified by [enum Parameter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_particle_flag">
|
||||
<return type="void" />
|
||||
<argument index="0" name="flag" type="int" enum="CPUParticles.Flags" />
|
||||
<argument index="1" name="enable" type="bool" />
|
||||
<description>
|
||||
Enables or disables the given flag (see [enum Flags] for options).
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="amount" type="int" setter="set_amount" getter="get_amount" default="8">
|
||||
The number of particles emitted in one emission cycle (corresponding to the [member lifetime]).
|
||||
[b]Note:[/b] Changing [member amount] will reset the particle emission, therefore removing all particles that were already emitted before changing [member amount].
|
||||
</member>
|
||||
<member name="angle" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Initial rotation applied to each particle, in degrees.
|
||||
</member>
|
||||
<member name="angle_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's rotation will be animated along this [Curve].
|
||||
</member>
|
||||
<member name="angle_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Rotation randomness ratio.
|
||||
</member>
|
||||
<member name="angular_velocity" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Initial angular velocity applied to each particle in [i]degrees[/i] per second. Sets the speed of rotation of the particle.
|
||||
</member>
|
||||
<member name="angular_velocity_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's angular velocity will vary along this [Curve].
|
||||
</member>
|
||||
<member name="angular_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Angular velocity randomness ratio.
|
||||
</member>
|
||||
<member name="anim_offset" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Particle animation offset.
|
||||
</member>
|
||||
<member name="anim_offset_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's animation offset will vary along this [Curve].
|
||||
</member>
|
||||
<member name="anim_offset_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Animation offset randomness ratio.
|
||||
</member>
|
||||
<member name="anim_speed" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Particle animation speed.
|
||||
</member>
|
||||
<member name="anim_speed_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's animation speed will vary along this [Curve].
|
||||
</member>
|
||||
<member name="anim_speed_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Animation speed randomness ratio.
|
||||
</member>
|
||||
<member name="color" type="Color" setter="set_color" getter="get_color" default="Color( 1, 1, 1, 1 )">
|
||||
Each particle's initial color.
|
||||
[b]Note:[/b] [member color] multiplies the particle mesh's vertex colors. To have a visible effect on a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member color] will have no visible effect.
|
||||
</member>
|
||||
<member name="color_initial_ramp" type="Gradient" setter="set_color_initial_ramp" getter="get_color_initial_ramp">
|
||||
Each particle's initial color will vary along this [GradientTexture] (multiplied with [member color]).
|
||||
[b]Note:[/b] [member color_initial_ramp] multiplies the particle mesh's vertex colors. To have a visible effect on a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member color_initial_ramp] will have no visible effect.
|
||||
</member>
|
||||
<member name="color_ramp" type="Gradient" setter="set_color_ramp" getter="get_color_ramp">
|
||||
Each particle's color will vary along this [GradientTexture] over its lifetime (multiplied with [member color]).
|
||||
[b]Note:[/b] [member color_ramp] multiplies the particle mesh's vertex colors. To have a visible effect on a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member color_ramp] will have no visible effect.
|
||||
</member>
|
||||
<member name="damping" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
The rate at which particles lose velocity.
|
||||
</member>
|
||||
<member name="damping_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Damping will vary along this [Curve].
|
||||
</member>
|
||||
<member name="damping_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Damping randomness ratio.
|
||||
</member>
|
||||
<member name="direction" type="Vector3" setter="set_direction" getter="get_direction" default="Vector3( 1, 0, 0 )">
|
||||
Unit vector specifying the particles' emission direction.
|
||||
</member>
|
||||
<member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="CPUParticles.DrawOrder" default="0">
|
||||
Particle draw order. Uses [enum DrawOrder] values.
|
||||
</member>
|
||||
<member name="emission_box_extents" type="Vector3" setter="set_emission_box_extents" getter="get_emission_box_extents">
|
||||
The rectangle's extents if [member emission_shape] is set to [constant EMISSION_SHAPE_BOX].
|
||||
</member>
|
||||
<member name="emission_colors" type="PoolColorArray" setter="set_emission_colors" getter="get_emission_colors">
|
||||
Sets the [Color]s to modulate particles by when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS].
|
||||
[b]Note:[/b] [member emission_colors] multiplies the particle mesh's vertex colors. To have a visible effect on a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] [i]must[/i] be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function. Otherwise, [member emission_colors] will have no visible effect.
|
||||
</member>
|
||||
<member name="emission_normals" type="PoolVector3Array" setter="set_emission_normals" getter="get_emission_normals">
|
||||
Sets the direction the particles will be emitted in when using [constant EMISSION_SHAPE_DIRECTED_POINTS].
|
||||
</member>
|
||||
<member name="emission_points" type="PoolVector3Array" setter="set_emission_points" getter="get_emission_points">
|
||||
Sets the initial positions to spawn particles when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS].
|
||||
</member>
|
||||
<member name="emission_ring_axis" type="Vector3" setter="set_emission_ring_axis" getter="get_emission_ring_axis">
|
||||
The axis for the ring shaped emitter when using [constant EMISSION_SHAPE_RING].
|
||||
</member>
|
||||
<member name="emission_ring_height" type="float" setter="set_emission_ring_height" getter="get_emission_ring_height">
|
||||
The height for the ring shaped emitter when using [constant EMISSION_SHAPE_RING].
|
||||
</member>
|
||||
<member name="emission_ring_inner_radius" type="float" setter="set_emission_ring_inner_radius" getter="get_emission_ring_inner_radius">
|
||||
The inner radius for the ring shaped emitter when using [constant EMISSION_SHAPE_RING].
|
||||
</member>
|
||||
<member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius">
|
||||
The radius for the ring shaped emitter when using [constant EMISSION_SHAPE_RING].
|
||||
</member>
|
||||
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="CPUParticles.EmissionShape" default="0">
|
||||
Particles will be emitted inside this region. See [enum EmissionShape] for possible values.
|
||||
</member>
|
||||
<member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius">
|
||||
The sphere's radius if [enum EmissionShape] is set to [constant EMISSION_SHAPE_SPHERE].
|
||||
</member>
|
||||
<member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="true">
|
||||
If [code]true[/code], particles are being emitted.
|
||||
</member>
|
||||
<member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio" default="0.0">
|
||||
How rapidly particles in an emission cycle are emitted. If greater than [code]0[/code], there will be a gap in emissions before the next cycle begins.
|
||||
</member>
|
||||
<member name="fixed_fps" type="int" setter="set_fixed_fps" getter="get_fixed_fps" default="0">
|
||||
The particle system's frame rate is fixed to a value. For instance, changing the value to 2 will make the particles render at 2 frames per second. Note this does not slow down the particle system itself.
|
||||
</member>
|
||||
<member name="flag_align_y" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
|
||||
Align Y axis of particle with the direction of its velocity.
|
||||
</member>
|
||||
<member name="flag_disable_z" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
|
||||
If [code]true[/code], particles will not move on the z axis.
|
||||
</member>
|
||||
<member name="flag_rotate_y" type="bool" setter="set_particle_flag" getter="get_particle_flag" default="false">
|
||||
If [code]true[/code], particles rotate around Y axis by [member angle].
|
||||
</member>
|
||||
<member name="flatness" type="float" setter="set_flatness" getter="get_flatness" default="0.0">
|
||||
Amount of [member spread] in Y/Z plane. A value of [code]1[/code] restricts particles to X/Z plane.
|
||||
</member>
|
||||
<member name="fract_delta" type="bool" setter="set_fractional_delta" getter="get_fractional_delta" default="true">
|
||||
If [code]true[/code], results in fractional delta calculation which has a smoother particles display effect.
|
||||
</member>
|
||||
<member name="gravity" type="Vector3" setter="set_gravity" getter="get_gravity" default="Vector3( 0, -9.8, 0 )">
|
||||
Gravity applied to every particle.
|
||||
</member>
|
||||
<member name="hue_variation" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Initial hue variation applied to each particle.
|
||||
</member>
|
||||
<member name="hue_variation_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's hue will vary along this [Curve].
|
||||
</member>
|
||||
<member name="hue_variation_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Hue variation randomness ratio.
|
||||
</member>
|
||||
<member name="initial_velocity" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Initial velocity magnitude for each particle. Direction comes from [member spread] and the node's orientation.
|
||||
</member>
|
||||
<member name="initial_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Initial velocity randomness ratio.
|
||||
</member>
|
||||
<member name="lifetime" type="float" setter="set_lifetime" getter="get_lifetime" default="1.0">
|
||||
The amount of time each particle will exist (in seconds).
|
||||
</member>
|
||||
<member name="lifetime_randomness" type="float" setter="set_lifetime_randomness" getter="get_lifetime_randomness" default="0.0">
|
||||
Particle lifetime randomness ratio.
|
||||
</member>
|
||||
<member name="linear_accel" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Linear acceleration applied to each particle in the direction of motion.
|
||||
</member>
|
||||
<member name="linear_accel_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's linear acceleration will vary along this [Curve].
|
||||
</member>
|
||||
<member name="linear_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Linear acceleration randomness ratio.
|
||||
</member>
|
||||
<member name="local_coords" type="bool" setter="set_use_local_coordinates" getter="get_use_local_coordinates" default="true">
|
||||
If [code]true[/code], particles use the parent node's coordinate space. If [code]false[/code], they use global coordinates.
|
||||
</member>
|
||||
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
|
||||
The [Mesh] used for each particle. If [code]null[/code], particles will be spheres.
|
||||
</member>
|
||||
<member name="one_shot" type="bool" setter="set_one_shot" getter="get_one_shot" default="false">
|
||||
If [code]true[/code], only one emission cycle occurs. If set [code]true[/code] during a cycle, emission will stop at the cycle's end.
|
||||
</member>
|
||||
<member name="orbit_velocity" type="float" setter="set_param" getter="get_param">
|
||||
Orbital velocity applied to each particle. Makes the particles circle around origin in the local XY plane. Specified in number of full rotations around origin per second.
|
||||
This property is only available when [member flag_disable_z] is [code]true[/code].
|
||||
</member>
|
||||
<member name="orbit_velocity_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's orbital velocity will vary along this [Curve].
|
||||
</member>
|
||||
<member name="orbit_velocity_random" type="float" setter="set_param_randomness" getter="get_param_randomness">
|
||||
Orbital velocity randomness ratio.
|
||||
</member>
|
||||
<member name="preprocess" type="float" setter="set_pre_process_time" getter="get_pre_process_time" default="0.0">
|
||||
Particle system starts as if it had already run for this many seconds.
|
||||
</member>
|
||||
<member name="radial_accel" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Radial acceleration applied to each particle. Makes particle accelerate away from origin.
|
||||
</member>
|
||||
<member name="radial_accel_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's radial acceleration will vary along this [Curve].
|
||||
</member>
|
||||
<member name="radial_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Radial acceleration randomness ratio.
|
||||
</member>
|
||||
<member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0">
|
||||
Emission lifetime randomness ratio.
|
||||
</member>
|
||||
<member name="scale_amount" type="float" setter="set_param" getter="get_param" default="1.0">
|
||||
Initial scale applied to each particle. This can be set to a negative value to flip the particle on all axes.
|
||||
</member>
|
||||
<member name="scale_amount_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's scale will vary along this [Curve].
|
||||
</member>
|
||||
<member name="scale_amount_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Scale randomness ratio.
|
||||
</member>
|
||||
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
|
||||
Particle system's running speed scaling ratio. A value of [code]0[/code] can be used to pause the particles.
|
||||
</member>
|
||||
<member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0">
|
||||
Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Applied to X/Z plane and Y/Z planes.
|
||||
</member>
|
||||
<member name="tangential_accel" type="float" setter="set_param" getter="get_param" default="0.0">
|
||||
Tangential acceleration applied to each particle. Tangential acceleration is perpendicular to the particle's velocity giving the particles a swirling motion.
|
||||
</member>
|
||||
<member name="tangential_accel_curve" type="Curve" setter="set_param_curve" getter="get_param_curve">
|
||||
Each particle's tangential acceleration will vary along this [Curve].
|
||||
</member>
|
||||
<member name="tangential_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0">
|
||||
Tangential acceleration randomness ratio.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="DRAW_ORDER_INDEX" value="0" enum="DrawOrder">
|
||||
Particles are drawn in the order emitted.
|
||||
</constant>
|
||||
<constant name="DRAW_ORDER_LIFETIME" value="1" enum="DrawOrder">
|
||||
Particles are drawn in order of remaining lifetime.
|
||||
</constant>
|
||||
<constant name="DRAW_ORDER_VIEW_DEPTH" value="2" enum="DrawOrder">
|
||||
Particles are drawn in order of depth.
|
||||
</constant>
|
||||
<constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set initial velocity properties.
|
||||
</constant>
|
||||
<constant name="PARAM_ANGULAR_VELOCITY" value="1" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set angular velocity properties.
|
||||
</constant>
|
||||
<constant name="PARAM_ORBIT_VELOCITY" value="2" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set orbital velocity properties.
|
||||
</constant>
|
||||
<constant name="PARAM_LINEAR_ACCEL" value="3" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set linear acceleration properties.
|
||||
</constant>
|
||||
<constant name="PARAM_RADIAL_ACCEL" value="4" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set radial acceleration properties.
|
||||
</constant>
|
||||
<constant name="PARAM_TANGENTIAL_ACCEL" value="5" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set tangential acceleration properties.
|
||||
</constant>
|
||||
<constant name="PARAM_DAMPING" value="6" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set damping properties.
|
||||
</constant>
|
||||
<constant name="PARAM_ANGLE" value="7" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set angle properties.
|
||||
</constant>
|
||||
<constant name="PARAM_SCALE" value="8" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set scale properties.
|
||||
</constant>
|
||||
<constant name="PARAM_HUE_VARIATION" value="9" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set hue variation properties.
|
||||
</constant>
|
||||
<constant name="PARAM_ANIM_SPEED" value="10" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set animation speed properties.
|
||||
</constant>
|
||||
<constant name="PARAM_ANIM_OFFSET" value="11" enum="Parameter">
|
||||
Use with [method set_param], [method set_param_randomness], and [method set_param_curve] to set animation offset properties.
|
||||
</constant>
|
||||
<constant name="PARAM_MAX" value="12" enum="Parameter">
|
||||
Represents the size of the [enum Parameter] enum.
|
||||
</constant>
|
||||
<constant name="FLAG_ALIGN_Y_TO_VELOCITY" value="0" enum="Flags">
|
||||
Use with [method set_particle_flag] to set [member flag_align_y].
|
||||
</constant>
|
||||
<constant name="FLAG_ROTATE_Y" value="1" enum="Flags">
|
||||
Use with [method set_particle_flag] to set [member flag_rotate_y].
|
||||
</constant>
|
||||
<constant name="FLAG_DISABLE_Z" value="2" enum="Flags">
|
||||
Use with [method set_particle_flag] to set [member flag_disable_z].
|
||||
</constant>
|
||||
<constant name="FLAG_MAX" value="3" enum="Flags">
|
||||
Represents the size of the [enum Flags] enum.
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_POINT" value="0" enum="EmissionShape">
|
||||
All particles will be emitted from a single point.
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_SPHERE" value="1" enum="EmissionShape">
|
||||
Particles will be emitted in the volume of a sphere.
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_BOX" value="2" enum="EmissionShape">
|
||||
Particles will be emitted in the volume of a box.
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_POINTS" value="3" enum="EmissionShape">
|
||||
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle color will be modulated by [member emission_colors].
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
|
||||
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors].
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_RING" value="5" enum="EmissionShape">
|
||||
Particles will be emitted in a ring or cylinder.
|
||||
</constant>
|
||||
<constant name="EMISSION_SHAPE_MAX" value="6" enum="EmissionShape">
|
||||
Represents the size of the [enum EmissionShape] enum.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,213 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="Camera" inherits="Spatial" version="4.2">
|
||||
<brief_description>
|
||||
Camera node, displays from a point of view.
|
||||
</brief_description>
|
||||
<description>
|
||||
Camera is a special node that displays what is visible from its current location. Cameras register themselves in the nearest [Viewport] node (when ascending the tree). Only one camera can be active per viewport. If no viewport is available ascending the tree, the camera will register in the global viewport. In other words, a camera just provides 3D display capabilities to a [Viewport], and, without one, a scene registered in that [Viewport] (or higher viewports) can't be displayed.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="clear_current">
|
||||
<return type="void" />
|
||||
<argument index="0" name="enable_next" type="bool" default="true" />
|
||||
<description>
|
||||
If this is the current camera, remove it from being current. If [code]enable_next[/code] is [code]true[/code], request to make the next camera current, if any.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_camera_rid" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Returns the camera's RID from the [RenderingServer].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_camera_transform" qualifiers="const">
|
||||
<return type="Transform" />
|
||||
<description>
|
||||
Returns the transform of the camera plus the vertical ([member v_offset]) and horizontal ([member h_offset]) offsets; and any other adjustments made to the position and orientation of the camera by subclassed cameras such as [ClippedCamera], [InterpolatedCamera] and [ARVRCamera].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_cull_mask_bit" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="layer" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the given [code]layer[/code] in the [member cull_mask] is enabled, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_frustum" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Returns the camera's frustum planes in world space units as an array of [Plane]s in the following order: near, far, left, top, right, bottom. Not to be confused with [member frustum_offset].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_position_behind" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="world_point" type="Vector3" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the given position is behind the camera.
|
||||
[b]Note:[/b] A position which returns [code]false[/code] may still be outside the camera's field of view.
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_current">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Makes this camera the current camera for the [Viewport] (see class description). If the camera node is outside the scene tree, it will attempt to become current once it's added.
|
||||
</description>
|
||||
</method>
|
||||
<method name="project_local_ray_normal" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<description>
|
||||
Returns a normal vector from the screen point location directed along the camera. Orthogonal cameras are normalized. Perspective cameras account for perspective, screen width/height, etc.
|
||||
</description>
|
||||
</method>
|
||||
<method name="project_position" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<argument index="1" name="z_depth" type="float" />
|
||||
<description>
|
||||
Returns the 3D point in world space that maps to the given 2D coordinate in the [Viewport] rectangle on a plane that is the given [code]z_depth[/code] distance into the scene away from the camera.
|
||||
</description>
|
||||
</method>
|
||||
<method name="project_ray_normal" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<description>
|
||||
Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
</description>
|
||||
</method>
|
||||
<method name="project_ray_origin" qualifiers="const">
|
||||
<return type="Vector3" />
|
||||
<argument index="0" name="screen_point" type="Vector2" />
|
||||
<description>
|
||||
Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the inverse camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_cull_mask_bit">
|
||||
<return type="void" />
|
||||
<argument index="0" name="layer" type="int" />
|
||||
<argument index="1" name="enable" type="bool" />
|
||||
<description>
|
||||
Enables or disables the given [code]layer[/code] in the [member cull_mask].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_frustum">
|
||||
<return type="void" />
|
||||
<argument index="0" name="size" type="float" />
|
||||
<argument index="1" name="offset" type="Vector2" />
|
||||
<argument index="2" name="z_near" type="float" />
|
||||
<argument index="3" name="z_far" type="float" />
|
||||
<description>
|
||||
Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_orthogonal">
|
||||
<return type="void" />
|
||||
<argument index="0" name="size" type="float" />
|
||||
<argument index="1" name="z_near" type="float" />
|
||||
<argument index="2" name="z_far" type="float" />
|
||||
<description>
|
||||
Sets the camera projection to orthogonal mode (see [constant PROJECTION_ORTHOGONAL]), by specifying a [code]size[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units. (As a hint, 2D games often use this projection, with values specified in pixels.)
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_perspective">
|
||||
<return type="void" />
|
||||
<argument index="0" name="fov" type="float" />
|
||||
<argument index="1" name="z_near" type="float" />
|
||||
<argument index="2" name="z_far" type="float" />
|
||||
<description>
|
||||
Sets the camera projection to perspective mode (see [constant PROJECTION_PERSPECTIVE]), by specifying a [code]fov[/code] (field of view) angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units.
|
||||
</description>
|
||||
</method>
|
||||
<method name="unproject_position" qualifiers="const">
|
||||
<return type="Vector2" />
|
||||
<argument index="0" name="world_point" type="Vector3" />
|
||||
<description>
|
||||
Returns the 2D coordinate in the [Viewport] rectangle that maps to the given 3D point in world space.
|
||||
[b]Note:[/b] When using this to position GUI elements over a 3D viewport, use [method is_position_behind] to prevent them from appearing if the 3D point is behind the camera:
|
||||
[codeblock]
|
||||
# This code block is part of a script that inherits from Spatial.
|
||||
# `control` is a reference to a node inheriting from Control.
|
||||
control.visible = not get_viewport().get_camera().is_position_behind(global_transform.origin)
|
||||
control.rect_position = get_viewport().get_camera().unproject_position(global_transform.origin)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
|
||||
The culling mask that describes which 3D render layers are rendered by this camera.
|
||||
</member>
|
||||
<member name="current" type="bool" setter="set_current" getter="is_current" default="false">
|
||||
If [code]true[/code], the ancestor [Viewport] is currently using this camera.
|
||||
If multiple cameras are in the scene, one will always be made current. For example, if two [Camera] nodes are present in the scene and only one is current, setting one camera's [member current] to [code]false[/code] will cause the other camera to be made current.
|
||||
</member>
|
||||
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="Camera.DopplerTracking" default="0">
|
||||
If not [constant DOPPLER_TRACKING_DISABLED], this camera will simulate the [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] for objects changed in particular [code]_process[/code] methods. The Doppler effect is only simulated for [AudioStreamPlayer3D] nodes that have [member AudioStreamPlayer3D.doppler_tracking] set to a value other than [constant AudioStreamPlayer3D.DOPPLER_TRACKING_DISABLED].
|
||||
[b]Note:[/b] To toggle the Doppler effect preview in the editor, use the Perspective menu in the top-left corner of the 3D viewport and toggle [b]Enable Doppler[/b].
|
||||
</member>
|
||||
<member name="environment" type="Environment3D" setter="set_environment" getter="get_environment">
|
||||
The [Environment3D] to use for this camera.
|
||||
</member>
|
||||
<member name="far" type="float" setter="set_zfar" getter="get_zfar" default="100.0">
|
||||
The distance to the far culling boundary for this camera relative to its local Z axis.
|
||||
</member>
|
||||
<member name="fov" type="float" setter="set_fov" getter="get_fov" default="70.0">
|
||||
The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle.
|
||||
For reference, the default vertical field of view value ([code]70.0[/code]) is equivalent to a horizontal FOV of:
|
||||
- ~86.07 degrees in a 4:3 viewport
|
||||
- ~96.50 degrees in a 16:10 viewport
|
||||
- ~102.45 degrees in a 16:9 viewport
|
||||
- ~117.06 degrees in a 21:9 viewport
|
||||
</member>
|
||||
<member name="frustum_offset" type="Vector2" setter="set_frustum_offset" getter="get_frustum_offset" default="Vector2( 0, 0 )">
|
||||
The camera's frustum offset. This can be changed from the default to create "tilted frustum" effects such as [url=https://zdoom.org/wiki/Y-shearing]Y-shearing[/url].
|
||||
</member>
|
||||
<member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset" default="0.0">
|
||||
The horizontal (X) offset of the camera viewport.
|
||||
</member>
|
||||
<member name="keep_aspect" type="int" setter="set_keep_aspect_mode" getter="get_keep_aspect_mode" enum="Camera.KeepAspect" default="1">
|
||||
The axis to lock during [member fov]/[member size] adjustments. Can be either [constant KEEP_WIDTH] or [constant KEEP_HEIGHT].
|
||||
</member>
|
||||
<member name="near" type="float" setter="set_znear" getter="get_znear" default="0.05">
|
||||
The distance to the near culling boundary for this camera relative to its local Z axis.
|
||||
</member>
|
||||
<member name="projection" type="int" setter="set_projection" getter="get_projection" enum="Camera.ProjectionMode" default="0">
|
||||
The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size.
|
||||
</member>
|
||||
<member name="size" type="float" setter="set_size" getter="get_size" default="1.0">
|
||||
The camera's size in meters measured as the diameter of the width or height, depending on [member keep_aspect]. Only applicable in orthogonal and frustum modes.
|
||||
</member>
|
||||
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
|
||||
The vertical (Y) offset of the camera viewport.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="PROJECTION_PERSPECTIVE" value="0" enum="ProjectionMode">
|
||||
Perspective projection. Objects on the screen becomes smaller when they are far away.
|
||||
</constant>
|
||||
<constant name="PROJECTION_ORTHOGONAL" value="1" enum="ProjectionMode">
|
||||
Orthogonal projection, also known as orthographic projection. Objects remain the same size on the screen no matter how far away they are.
|
||||
</constant>
|
||||
<constant name="PROJECTION_FRUSTUM" value="2" enum="ProjectionMode">
|
||||
Frustum projection. This mode allows adjusting [member frustum_offset] to create "tilted frustum" effects.
|
||||
</constant>
|
||||
<constant name="KEEP_WIDTH" value="0" enum="KeepAspect">
|
||||
Preserves the horizontal aspect ratio; also known as Vert- scaling. This is usually the best option for projects running in portrait mode, as taller aspect ratios will benefit from a wider vertical FOV.
|
||||
</constant>
|
||||
<constant name="KEEP_HEIGHT" value="1" enum="KeepAspect">
|
||||
Preserves the vertical aspect ratio; also known as Hor+ scaling. This is usually the best option for projects running in landscape mode, as wider aspect ratios will automatically benefit from a wider horizontal FOV.
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_DISABLED" value="0" enum="DopplerTracking">
|
||||
Disables [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] simulation (default).
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1" enum="DopplerTracking">
|
||||
Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how audio is perceived (changing the audio's [member AudioStreamPlayer3D.pitch_scale]).
|
||||
</constant>
|
||||
<constant name="DOPPLER_TRACKING_PHYSICS_STEP" value="2" enum="DopplerTracking">
|
||||
Simulate [url=https://en.wikipedia.org/wiki/Doppler_effect]Doppler effect[/url] by tracking positions of objects that are changed in [code]_physics_process[/code]. Changes in the relative velocity of this camera compared to those objects affect how audio is perceived (changing the audio's [member AudioStreamPlayer3D.pitch_scale]).
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorExportPlugin" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
A script that is executed when exporting the project.
|
||||
</brief_description>
|
||||
<description>
|
||||
[EditorExportPlugin]s are automatically invoked whenever the user exports the project. Their most common use is to determine what files are being included in the exported project. For each plugin, [method _export_begin] is called at the beginning of the export process and then [method _export_file] is called for each exported file.
|
||||
To use [EditorExportPlugin], register it using the [method EditorPlugin.add_export_plugin] method first.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_export_begin" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="features" type="PoolStringArray" />
|
||||
<argument index="1" name="is_debug" type="bool" />
|
||||
<argument index="2" name="path" type="String" />
|
||||
<argument index="3" name="flags" type="int" />
|
||||
<description>
|
||||
Virtual method to be overridden by the user. It is called when the export starts and provides all information about the export. [code]features[/code] is the list of features for the export, [code]is_debug[/code] is [code]true[/code] for debug builds, [code]path[/code] is the target path for the exported project. [code]flags[/code] is only used when running a runnable profile, e.g. when using native run on Android.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_export_end" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Virtual method to be overridden by the user. Called when the export is finished.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_export_file" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="type" type="String" />
|
||||
<argument index="2" name="features" type="PoolStringArray" />
|
||||
<description>
|
||||
Virtual method to be overridden by the user. Called for each exported file, providing arguments that can be used to identify the file. [code]path[/code] is the path of the file, [code]type[/code] is the [Resource] represented by the file (e.g. [PackedScene]) and [code]features[/code] is the list of features for the export.
|
||||
Calling [method skip] inside this callback will make the file not included in the export.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_file">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="file" type="PoolByteArray" />
|
||||
<argument index="2" name="remap" type="bool" />
|
||||
<description>
|
||||
Adds a custom file to be exported. [code]path[/code] is the virtual path that can be used to load the file, [code]file[/code] is the binary data of the file. If [code]remap[/code] is [code]true[/code], file will not be exported, but instead remapped to the given [code]path[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_bundle_file">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Adds an iOS bundle file from the given [code]path[/code] to the exported project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_cpp_code">
|
||||
<return type="void" />
|
||||
<argument index="0" name="code" type="String" />
|
||||
<description>
|
||||
Adds a C++ code to the iOS export. The final code is created from the code appended by each active export plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_embedded_framework">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Adds a dynamic library (*.dylib, *.framework) to Linking Phase in iOS's Xcode project and embeds it into resulting binary.
|
||||
[b]Note:[/b] For static libraries (*.a) works in same way as [method add_ios_framework].
|
||||
This method should not be used for System libraries as they are already present on the device.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_framework">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Adds a static library (*.a) or dynamic library (*.dylib, *.framework) to Linking Phase in iOS's Xcode project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_linker_flags">
|
||||
<return type="void" />
|
||||
<argument index="0" name="flags" type="String" />
|
||||
<description>
|
||||
Adds linker flags for the iOS export.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_plist_content">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plist_content" type="String" />
|
||||
<description>
|
||||
Adds content for iOS Property List files.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_ios_project_static_lib">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Adds a static lib from the given [code]path[/code] to the iOS project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_osx_plugin_file">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Adds file or directory matching [code]path[/code] to [code]PlugIns[/code] directory of macOS app bundle.
|
||||
[b]Note:[/b] This is useful only for macOS exports.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_shared_object">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="tags" type="PoolStringArray" />
|
||||
<description>
|
||||
Adds a shared object or a directory containing only shared objects with the given [code]tags[/code] and destination [code]path[/code].
|
||||
[b]Note:[/b] In case of macOS exports, those shared objects will be added to [code]Frameworks[/code] directory of app bundle.
|
||||
In case of a directory code-sign will error if you place non code object in directory.
|
||||
</description>
|
||||
</method>
|
||||
<method name="skip">
|
||||
<return type="void" />
|
||||
<description>
|
||||
To be called inside [method _export_file]. Skips the current file, so it's not included in the export.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorFileDialog" inherits="ConfirmationDialog" version="4.2">
|
||||
<brief_description>
|
||||
A modified version of [FileDialog] used by the editor.
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_filter">
|
||||
<return type="void" />
|
||||
<argument index="0" name="filter" type="String" />
|
||||
<description>
|
||||
Adds a comma-delimited file extension filter option to the [EditorFileDialog] with an optional semi-colon-delimited label.
|
||||
For example, [code]"*.tscn, *.scn; Scenes"[/code] results in filter text "Scenes (*.tscn, *.scn)".
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_filters">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Removes all filters except for "All Files (*)".
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_vbox">
|
||||
<return type="VBoxContainer" />
|
||||
<description>
|
||||
Returns the [code]VBoxContainer[/code] used to display the file system.
|
||||
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member CanvasItem.visible] property.
|
||||
</description>
|
||||
</method>
|
||||
<method name="invalidate">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Notify the [EditorFileDialog] that its view of the data is no longer accurate. Updates the view contents on next view update.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="access" type="int" setter="set_access" getter="get_access" enum="EditorFileDialog.Access" default="0">
|
||||
The location from which the user may select a file, including [code]res://[/code], [code]user://[/code], and the local file system.
|
||||
</member>
|
||||
<member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir">
|
||||
The currently occupied directory.
|
||||
</member>
|
||||
<member name="current_file" type="String" setter="set_current_file" getter="get_current_file">
|
||||
The currently selected file.
|
||||
</member>
|
||||
<member name="current_path" type="String" setter="set_current_path" getter="get_current_path">
|
||||
The file system path in the address bar.
|
||||
</member>
|
||||
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
|
||||
<member name="disable_overwrite_warning" type="bool" setter="set_disable_overwrite_warning" getter="is_overwrite_warning_disabled" default="false">
|
||||
If [code]true[/code], the [EditorFileDialog] will not warn the user before overwriting files.
|
||||
</member>
|
||||
<member name="display_mode" type="int" setter="set_display_mode" getter="get_display_mode" enum="EditorFileDialog.DisplayMode" default="0">
|
||||
The view format in which the [EditorFileDialog] displays resources to the user.
|
||||
</member>
|
||||
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="EditorFileDialog.Mode" default="4">
|
||||
The purpose of the [EditorFileDialog], which defines the allowed behaviors.
|
||||
</member>
|
||||
<member name="resizable" type="bool" setter="set_resizable" getter="get_resizable" overrides="WindowDialog" default="true" />
|
||||
<member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files" default="false">
|
||||
If [code]true[/code], hidden files and directories will be visible in the [EditorFileDialog].
|
||||
</member>
|
||||
<member name="window_title" type="String" setter="set_title" getter="get_title" overrides="WindowDialog" default=""Save a File"" />
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="dir_selected">
|
||||
<argument index="0" name="dir" type="String" />
|
||||
<description>
|
||||
Emitted when a directory is selected.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="file_selected">
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Emitted when a file is selected.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="files_selected">
|
||||
<argument index="0" name="paths" type="PoolStringArray" />
|
||||
<description>
|
||||
Emitted when multiple files are selected.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="MODE_OPEN_FILE" value="0" enum="Mode">
|
||||
The [EditorFileDialog] can select only one file. Accepting the window will open the file.
|
||||
</constant>
|
||||
<constant name="MODE_OPEN_FILES" value="1" enum="Mode">
|
||||
The [EditorFileDialog] can select multiple files. Accepting the window will open all files.
|
||||
</constant>
|
||||
<constant name="MODE_OPEN_DIR" value="2" enum="Mode">
|
||||
The [EditorFileDialog] can select only one directory. Accepting the window will open the directory.
|
||||
</constant>
|
||||
<constant name="MODE_OPEN_ANY" value="3" enum="Mode">
|
||||
The [EditorFileDialog] can select a file or directory. Accepting the window will open it.
|
||||
</constant>
|
||||
<constant name="MODE_SAVE_FILE" value="4" enum="Mode">
|
||||
The [EditorFileDialog] can select only one file. Accepting the window will save the file.
|
||||
</constant>
|
||||
<constant name="ACCESS_RESOURCES" value="0" enum="Access">
|
||||
The [EditorFileDialog] can only view [code]res://[/code] directory contents.
|
||||
</constant>
|
||||
<constant name="ACCESS_USERDATA" value="1" enum="Access">
|
||||
The [EditorFileDialog] can only view [code]user://[/code] directory contents.
|
||||
</constant>
|
||||
<constant name="ACCESS_FILESYSTEM" value="2" enum="Access">
|
||||
The [EditorFileDialog] can view the entire local file system.
|
||||
</constant>
|
||||
<constant name="DISPLAY_THUMBNAILS" value="0" enum="DisplayMode">
|
||||
The [EditorFileDialog] displays resources as thumbnails.
|
||||
</constant>
|
||||
<constant name="DISPLAY_LIST" value="1" enum="DisplayMode">
|
||||
The [EditorFileDialog] displays resources as a list of filenames.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorFileSystem" inherits="Node" version="4.2">
|
||||
<brief_description>
|
||||
Resource filesystem, as the editor sees it.
|
||||
</brief_description>
|
||||
<description>
|
||||
This object holds information of all resources in the filesystem, their types, etc.
|
||||
[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_resource_filesystem].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_file_type" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Returns the resource type of the file, given the full path. This returns a string such as [code]"Resource"[/code] or [code]"GDScript"[/code], [i]not[/i] a file extension such as [code]".gd"[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_filesystem">
|
||||
<return type="EditorFileSystemDirectory" />
|
||||
<description>
|
||||
Gets the root directory object.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_filesystem_path">
|
||||
<return type="EditorFileSystemDirectory" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Returns a view into the filesystem at [code]path[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_scanning_progress" qualifiers="const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
Returns the scan progress for 0 to 1 if the FS is being scanned.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_scanning" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] of the filesystem is being scanned.
|
||||
</description>
|
||||
</method>
|
||||
<method name="scan">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Scan the filesystem for changes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="scan_sources">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Check if the source of any imported resource changed.
|
||||
</description>
|
||||
</method>
|
||||
<method name="update_file">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Update a file information. Call this if an external program (not Godot) modified the file.
|
||||
</description>
|
||||
</method>
|
||||
<method name="update_script_classes">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Scans the script files and updates the list of custom class names.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<signals>
|
||||
<signal name="filesystem_changed">
|
||||
<description>
|
||||
Emitted if the filesystem changed.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resources_reimported">
|
||||
<argument index="0" name="resources" type="PoolStringArray" />
|
||||
<description>
|
||||
Emitted if a resource is reimported.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resources_reload">
|
||||
<argument index="0" name="resources" type="PoolStringArray" />
|
||||
<description>
|
||||
Emitted if at least one resource is reloaded when the filesystem is scanned.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="sources_changed">
|
||||
<argument index="0" name="exist" type="bool" />
|
||||
<description>
|
||||
Emitted if the source of any imported file changed.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,108 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorFileSystemDirectory" inherits="Object" version="4.2">
|
||||
<brief_description>
|
||||
A directory for the resource filesystem.
|
||||
</brief_description>
|
||||
<description>
|
||||
A more generalized, low-level variation of the directory concept.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="find_dir_index" qualifiers="const">
|
||||
<return type="int" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns the index of the directory with name [code]name[/code] or [code]-1[/code] if not found.
|
||||
</description>
|
||||
</method>
|
||||
<method name="find_file_index" qualifiers="const">
|
||||
<return type="int" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns the index of the file with name [code]name[/code] or [code]-1[/code] if not found.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the name of the file at index [code]idx[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Returns the number of files in this directory.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_import_is_valid" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the file at index [code]idx[/code] imported properly.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_path" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the path to the file at index [code]idx[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_script_class_extends" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the base class of the script class defined in the file at index [code]idx[/code]. If the file doesn't define a script class using the [code]class_name[/code] syntax, this will return an empty string.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_script_class_name" qualifiers="const">
|
||||
<return type="String" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the name of the script class defined in the file at index [code]idx[/code]. If the file doesn't define a script class using the [code]class_name[/code] syntax, this will return an empty string.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_type" qualifiers="const">
|
||||
<return type="StringName" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the resource type of the file at index [code]idx[/code]. This returns a string such as [code]"Resource"[/code] or [code]"GDScript"[/code], [i]not[/i] a file extension such as [code]".gd"[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_name">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the name of this directory.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_parent">
|
||||
<return type="EditorFileSystemDirectory" />
|
||||
<description>
|
||||
Returns the parent directory for this directory or [code]null[/code] if called on a directory at [code]res://[/code] or [code]user://[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_path" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the path to this directory.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_subdir">
|
||||
<return type="EditorFileSystemDirectory" />
|
||||
<argument index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the subdirectory at index [code]idx[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_subdir_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Returns the number of subdirectories in this directory.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,149 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorImportPlugin" inherits="ResourceImporter" version="4.2">
|
||||
<brief_description>
|
||||
Registers a custom resource importer in the editor. Use the class to parse any file and import it as a new resource type.
|
||||
</brief_description>
|
||||
<description>
|
||||
[EditorImportPlugin]s provide a way to extend the editor's resource import functionality. Use them to import resources from custom files or to provide alternatives to the editor's existing importers.
|
||||
EditorImportPlugins work by associating with specific file extensions and a resource type. See [method get_recognized_extensions] and [method get_resource_type]. They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].import[/code] directory (see [member ProjectSettings.application/config/use_hidden_project_data_directory]).
|
||||
Below is an example EditorImportPlugin that imports a [Mesh] from a file with the extension ".special" or ".spec":
|
||||
[codeblock]
|
||||
tool
|
||||
extends EditorImportPlugin
|
||||
|
||||
func get_importer_name():
|
||||
return "my.special.plugin"
|
||||
|
||||
func get_visible_name():
|
||||
return "Special Mesh"
|
||||
|
||||
func get_recognized_extensions():
|
||||
return ["special", "spec"]
|
||||
|
||||
func get_save_extension():
|
||||
return "mesh"
|
||||
|
||||
func get_resource_type():
|
||||
return "Mesh"
|
||||
|
||||
func get_preset_count():
|
||||
return 1
|
||||
|
||||
func get_preset_name(i):
|
||||
return "Default"
|
||||
|
||||
func get_import_options(i):
|
||||
return [{"name": "my_option", "default_value": false}]
|
||||
|
||||
func import(source_file, save_path, options, platform_variants, gen_files):
|
||||
var file = File.new()
|
||||
if file.open(source_file, File.READ) != OK:
|
||||
return FAILED
|
||||
|
||||
var mesh = Mesh.new()
|
||||
# Fill the Mesh with data read in "file", left as an exercise to the reader
|
||||
|
||||
var filename = save_path + "." + get_save_extension()
|
||||
return ResourceSaver.save(filename, mesh)
|
||||
[/codeblock]
|
||||
To use [EditorImportPlugin], register it using the [method EditorPlugin.add_import_plugin] method first.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>$DOCS_URL/tutorials/plugins/editor/import_plugins.md</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_import_options" qualifiers="virtual">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="preset" type="int" />
|
||||
<description>
|
||||
Gets the options and default values for the preset at this index. Returns an Array of Dictionaries with the following keys: [code]name[/code], [code]default_value[/code], [code]property_hint[/code] (optional), [code]hint_string[/code] (optional), [code]usage[/code] (optional).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_import_order" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Gets the order of this importer to be run when importing resources. Importers with [i]lower[/i] import orders will be called first, and higher values will be called later. Use this to ensure the importer runs after the dependencies are already imported. The default import order is [code]0[/code] unless overridden by a specific importer. See [enum ResourceImporter.ImportOrder] for some predefined values.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_importer_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Gets the unique name of the importer.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_option_visibility" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="option" type="String" />
|
||||
<argument index="1" name="options" type="Dictionary" />
|
||||
<description>
|
||||
This method can be overridden to hide specific import options if conditions are met. This is mainly useful for hiding options that depend on others if one of them is disabled. For example:
|
||||
[codeblock]
|
||||
func get_option_visibility(option, options):
|
||||
# Only show the lossy quality setting if the compression mode is set to "Lossy".
|
||||
if option == "compress/lossy_quality" and options.has("compress/mode"):
|
||||
return int(options["compress/mode"]) == COMPRESS_LOSSY
|
||||
|
||||
return true
|
||||
[/codeblock]
|
||||
Return [code]true[/code] to make all options always visible.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_preset_count" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Gets the number of initial presets defined by the plugin. Use [method get_import_options] to get the default options for the preset and [method get_preset_name] to get the name of the preset.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_preset_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<argument index="0" name="preset" type="int" />
|
||||
<description>
|
||||
Gets the name of the options preset at this index.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_priority" qualifiers="virtual">
|
||||
<return type="float" />
|
||||
<description>
|
||||
Gets the priority of this plugin for the recognized extension. Higher priority plugins will be preferred. The default priority is [code]1.0[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_recognized_extensions" qualifiers="virtual">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets the list of file extensions to associate with this loader (case-insensitive). e.g. [code]["obj"][/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_resource_type" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Gets the Godot resource type associated with this loader. e.g. [code]"Mesh"[/code] or [code]"Animation"[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_save_extension" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Gets the extension used to save this resource in the [code].import[/code] directory (see [member ProjectSettings.application/config/use_hidden_project_data_directory]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_visible_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Gets the name to display in the import window. You should choose this name as a continuation to "Import as", e.g. "Import as Special Mesh".
|
||||
</description>
|
||||
</method>
|
||||
<method name="import" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<argument index="0" name="source_file" type="String" />
|
||||
<argument index="1" name="save_path" type="String" />
|
||||
<argument index="2" name="options" type="Dictionary" />
|
||||
<argument index="3" name="platform_variants" type="Array" />
|
||||
<argument index="4" name="gen_files" type="Array" />
|
||||
<description>
|
||||
Imports [code]source_file[/code] into [code]save_path[/code] with the import [code]options[/code] specified. The [code]platform_variants[/code] and [code]gen_files[/code] arrays will be modified by this function.
|
||||
This method must be overridden to do the actual importing work. See this class' description for an example of overriding this method.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,192 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorInspector" inherits="ScrollContainer" version="4.2">
|
||||
<brief_description>
|
||||
A control used to edit properties of an object.
|
||||
</brief_description>
|
||||
<description>
|
||||
This is the control that implements property editing in the editor's Settings dialogs, the Inspector dock, etc. To get the [EditorInspector] used in the editor's Inspector dock, use [method EditorInterface.get_inspector].
|
||||
[EditorInspector] will show properties in the same order as the array returned by [method Object.get_property_list].
|
||||
If a property's name is path-like (i.e. if it contains forward slashes), [EditorInspector] will create nested sections for "directories" along the path. For example, if a property is named [code]highlighting/gdscript/node_path_color[/code], it will be shown as "Node Path Color" inside the "GDScript" section nested inside the "Highlighting" section.
|
||||
If a property has [constant @GlobalScope.PROPERTY_USAGE_GROUP] usage, it will group subsequent properties whose name starts with the property's hint string. The group ends when a property does not start with that hint string or when a new group starts. An empty group name effectively ends the current group. [EditorInspector] will create a top-level section for each group. For example, if a property with group usage is named [code]Collide With[/code] and its hint string is [code]collide_with_[/code], a subsequent [code]collide_with_area[/code] property will be shown as "Area" inside the "Collide With" section.
|
||||
[b]Note:[/b] Unlike sections created from path-like property names, [EditorInspector] won't capitalize the name for sections created from groups. So properties with group usage usually use capitalized names instead of snake_cased names.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="collapse_all_folding">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="edit">
|
||||
<return type="void" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="expand_all_folding">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_edited_object">
|
||||
<return type="Object" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_object_class" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_property_clipboard" qualifiers="const">
|
||||
<return type="Variant" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_property_prefix" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_scroll_offset" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_sub_inspector" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_using_folding">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="refresh">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Refreshes the inspector.
|
||||
[b]Note:[/b] To save on CPU resources, calling this method will do nothing if the time specified in [code]docks/property_editor/auto_refresh_interval[/code] editor setting hasn't passed yet since this method was last called. (By default, this interval is set to 0.3 seconds.)
|
||||
</description>
|
||||
</method>
|
||||
<method name="register_text_enter">
|
||||
<return type="void" />
|
||||
<argument index="0" name="line_edit" type="Node" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_hide_script">
|
||||
<return type="void" />
|
||||
<argument index="0" name="hide" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_object_class">
|
||||
<return type="void" />
|
||||
<argument index="0" name="class" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_property_clipboard">
|
||||
<return type="void" />
|
||||
<argument index="0" name="value" type="Variant" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_property_prefix">
|
||||
<return type="void" />
|
||||
<argument index="0" name="prefix" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_scroll_offset">
|
||||
<return type="void" />
|
||||
<argument index="0" name="offset" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_show_categories">
|
||||
<return type="void" />
|
||||
<argument index="0" name="show" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_sub_inspector">
|
||||
<return type="void" />
|
||||
<argument index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_use_doc_hints">
|
||||
<return type="void" />
|
||||
<argument index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_use_filter">
|
||||
<return type="void" />
|
||||
<argument index="0" name="use" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_use_folding">
|
||||
<return type="void" />
|
||||
<argument index="0" name="enable" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="scroll_horizontal_enabled" type="bool" setter="set_enable_h_scroll" getter="is_h_scroll_enabled" overrides="ScrollContainer" default="false" />
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="object_id_selected">
|
||||
<argument index="0" name="id" type="int" />
|
||||
<description>
|
||||
Emitted when the Edit button of an [Object] has been pressed in the inspector. This is mainly used in the remote scene tree inspector.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_edited">
|
||||
<argument index="0" name="property" type="String" />
|
||||
<description>
|
||||
Emitted when a property is edited in the inspector.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_keyed">
|
||||
<argument index="0" name="property" type="String" />
|
||||
<description>
|
||||
Emitted when a property is keyed in the inspector. Properties can be keyed by clicking the "key" icon next to a property when the Animation panel is toggled.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_selected">
|
||||
<argument index="0" name="property" type="String" />
|
||||
<description>
|
||||
Emitted when a property is selected in the inspector.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_toggled">
|
||||
<argument index="0" name="property" type="String" />
|
||||
<argument index="1" name="checked" type="bool" />
|
||||
<description>
|
||||
Emitted when a boolean property is toggled in the inspector.
|
||||
[b]Note:[/b] This signal is never emitted if the internal [code]autoclear[/code] property enabled. Since this property is always enabled in the editor inspector, this signal is never emitted by the editor itself.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resource_selected">
|
||||
<argument index="0" name="res" type="Object" />
|
||||
<argument index="1" name="prop" type="String" />
|
||||
<description>
|
||||
Emitted when a resource is selected in the inspector.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="restart_requested">
|
||||
<description>
|
||||
Emitted when a property that requires a restart to be applied is edited in the inspector. This is only used in the Project Settings and Editor Settings.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorInspectorPlugin" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
Plugin for adding custom property editors on inspector.
|
||||
</brief_description>
|
||||
<description>
|
||||
[EditorInspectorPlugin] allows adding custom property editors to [EditorInspector].
|
||||
When an object is edited, the [method can_handle] function is called and must return [code]true[/code] if the object type is supported.
|
||||
If supported, the function [method parse_begin] will be called, allowing to place custom controls at the beginning of the class.
|
||||
Subsequently, the [method parse_category] and [method parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too.
|
||||
Finally, [method parse_end] will be called.
|
||||
On each of these calls, the "add" functions can be called.
|
||||
To use [EditorInspectorPlugin], register it using the [method EditorPlugin.add_inspector_plugin] method first.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Inspector plugins">$DOCS_URL/tutorials/plugins/editor/inspector_plugins.md</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_custom_control">
|
||||
<return type="void" />
|
||||
<argument index="0" name="control" type="Control" />
|
||||
<description>
|
||||
Adds a custom control, which is not necessarily a property editor.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_property_editor">
|
||||
<return type="void" />
|
||||
<argument index="0" name="property" type="String" />
|
||||
<argument index="1" name="editor" type="Control" />
|
||||
<description>
|
||||
Adds a property editor for an individual property. The [code]editor[/code] control must extend [EditorProperty].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_property_editor_for_multiple_properties">
|
||||
<return type="void" />
|
||||
<argument index="0" name="label" type="String" />
|
||||
<argument index="1" name="properties" type="PoolStringArray" />
|
||||
<argument index="2" name="editor" type="Control" />
|
||||
<description>
|
||||
Adds an editor that allows modifying multiple properties. The [code]editor[/code] control must extend [EditorProperty].
|
||||
</description>
|
||||
</method>
|
||||
<method name="can_handle" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this object can be handled by this plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="parse_begin" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<description>
|
||||
Called to allow adding controls at the beginning of the list.
|
||||
</description>
|
||||
</method>
|
||||
<method name="parse_category" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<argument index="1" name="category" type="String" />
|
||||
<description>
|
||||
Called to allow adding controls at the beginning of the category.
|
||||
</description>
|
||||
</method>
|
||||
<method name="parse_end" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Called to allow adding controls at the end of the list.
|
||||
</description>
|
||||
</method>
|
||||
<method name="parse_property" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<argument index="1" name="type" type="int" />
|
||||
<argument index="2" name="path" type="String" />
|
||||
<argument index="3" name="hint" type="int" />
|
||||
<argument index="4" name="hint_text" type="String" />
|
||||
<argument index="5" name="usage" type="int" />
|
||||
<description>
|
||||
Called to allow adding property specific editors to the inspector. Usually these inherit [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,273 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorInterface" inherits="Node" version="4.2">
|
||||
<brief_description>
|
||||
Godot editor's interface.
|
||||
</brief_description>
|
||||
<description>
|
||||
EditorInterface gives you control over Godot editor's window. It allows customizing the window, saving and (re-)loading scenes, rendering mesh previews, inspecting and editing resources and objects, and provides access to [EditorSettings], [EditorFileSystem], [EditorResourcePreview], [EditorScriptEditor], the editor viewport, and information about scenes.
|
||||
[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorPlugin.get_editor_interface].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="edit_node">
|
||||
<return type="void" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<description>
|
||||
Edits the given [Node]. The node will be also selected if it's inside the scene tree.
|
||||
</description>
|
||||
</method>
|
||||
<method name="edit_resource">
|
||||
<return type="void" />
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<description>
|
||||
Edits the given [Resource]. If the resource is a [Script] you can also edit it with [method edit_script] to specify the line and column position.
|
||||
</description>
|
||||
</method>
|
||||
<method name="edit_script">
|
||||
<return type="void" />
|
||||
<argument index="0" name="script" type="Script" />
|
||||
<argument index="1" name="line" type="int" default="-1" />
|
||||
<argument index="2" name="column" type="int" default="0" />
|
||||
<argument index="3" name="grab_focus" type="bool" default="true" />
|
||||
<description>
|
||||
Edits the given [Script]. The line and column on which to open the script can also be specified. The script will be open with the user-configured editor for the script's language which may be an external editor.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_base_control">
|
||||
<return type="Control" />
|
||||
<description>
|
||||
Returns the main container of Godot editor's window. For example, you can use it to retrieve the size of the container and place your controls accordingly.
|
||||
[b]Warning:[/b] Removing and freeing this node will render the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_class_icon">
|
||||
<return type="Texture" />
|
||||
<argument index="0" name="class" type="String" />
|
||||
<argument index="1" name="fallback" type="String" />
|
||||
<description>
|
||||
Returns the editor icon bound to a class name or the [code]fallback[/code] class's icon if not found. The [code]fallback[/code] defaults to "Object". If still not found, returns [code]null[/code].
|
||||
[b]Node:[/b] This includes icons from custom types (see [method EditorPlugin.add_custom_type]) and global script classes from [ScriptServer].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_current_path" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the current path being viewed in the [FileSystemDock].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_edited_scene_root">
|
||||
<return type="Node" />
|
||||
<description>
|
||||
Returns the edited (current) scene's root [Node].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_scale" qualifiers="const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
Returns the actual scale of the editor UI ([code]1.0[/code] being 100% scale). This can be used to adjust position and dimensions of the UI added by plugins.
|
||||
[b]Note:[/b] This value is set via the [code]interface/editor/display_scale[/code] and [code]interface/editor/custom_display_scale[/code] editor settings. Editor must be restarted for changes to be properly applied.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_settings">
|
||||
<return type="EditorSettings" />
|
||||
<description>
|
||||
Returns the editor's [EditorSettings] instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_viewport">
|
||||
<return type="Control" />
|
||||
<description>
|
||||
Returns the main editor control. Use this as a parent for main screens.
|
||||
[b]Note:[/b] This returns the main editor control containing the whole editor, not the 2D or 3D viewports specifically.
|
||||
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_file_system_dock">
|
||||
<return type="FileSystemDock" />
|
||||
<description>
|
||||
Returns the editor's [FileSystemDock] instance.
|
||||
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_inspector" qualifiers="const">
|
||||
<return type="EditorInspector" />
|
||||
<description>
|
||||
Returns the editor's [EditorInspector] instance.
|
||||
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_object_icon">
|
||||
<return type="Texture" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<argument index="1" name="fallback" type="String" />
|
||||
<description>
|
||||
Returns the editor icon bound to [Object] [code]object[/code] or the class [code]fallback[/code] if a type cannot be determined. If [code]object[/code] extends [Script], then return the editor icon bound to the scripted class, not the actual script. If still not found, return [code]null[/code].
|
||||
[b]Note:[/b] if you need the editor icon for a script such as [GDScript], use [method get_class_icon].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_open_scenes" qualifiers="const">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Returns an [Array] with the file paths of the currently opened scenes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_playing_scene" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the name of the scene that is being played. If no scene is currently being played, returns an empty string.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_resource_filesystem">
|
||||
<return type="EditorFileSystem" />
|
||||
<description>
|
||||
Returns the editor's [EditorFileSystem] instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_resource_previewer">
|
||||
<return type="EditorResourcePreview" />
|
||||
<description>
|
||||
Returns the editor's [EditorResourcePreview] instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_script_editor">
|
||||
<return type="EditorScriptEditor" />
|
||||
<description>
|
||||
Returns the editor's [EditorScriptEditor] instance.
|
||||
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_selected_path" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the path of the directory currently selected in the [FileSystemDock]. If a file is selected, its base directory will be returned using [method String.get_base_dir] instead.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_selection">
|
||||
<return type="EditorSelection" />
|
||||
<description>
|
||||
Returns the editor's [EditorSelection] instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="inspect_object">
|
||||
<return type="void" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<argument index="1" name="for_property" type="String" default="""" />
|
||||
<argument index="2" name="inspector_only" type="bool" default="false" />
|
||||
<description>
|
||||
Shows the given property on the given [code]object[/code] in the editor's Inspector dock. If [code]inspector_only[/code] is [code]true[/code], plugins will not attempt to edit [code]object[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_playing_scene" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if a scene is currently being played, [code]false[/code] otherwise. Paused scenes are considered as being played.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_plugin_enabled" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="plugin" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the specified [code]plugin[/code] is enabled. The plugin name is the same as its directory name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_mesh_previews">
|
||||
<return type="Array" />
|
||||
<argument index="0" name="meshes" type="Array" />
|
||||
<argument index="1" name="preview_size" type="int" />
|
||||
<description>
|
||||
Returns mesh previews rendered at the given size as an [Array] of [Texture]s.
|
||||
</description>
|
||||
</method>
|
||||
<method name="open_scene_from_path">
|
||||
<return type="void" />
|
||||
<argument index="0" name="scene_filepath" type="String" />
|
||||
<description>
|
||||
Opens the scene at the given path.
|
||||
</description>
|
||||
</method>
|
||||
<method name="play_current_scene">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Plays the currently active scene.
|
||||
</description>
|
||||
</method>
|
||||
<method name="play_custom_scene">
|
||||
<return type="void" />
|
||||
<argument index="0" name="scene_filepath" type="String" />
|
||||
<description>
|
||||
Plays the scene specified by its filepath.
|
||||
</description>
|
||||
</method>
|
||||
<method name="play_main_scene">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Plays the main scene.
|
||||
</description>
|
||||
</method>
|
||||
<method name="reload_scene_from_path">
|
||||
<return type="void" />
|
||||
<argument index="0" name="scene_filepath" type="String" />
|
||||
<description>
|
||||
Reloads the scene at the given path.
|
||||
</description>
|
||||
</method>
|
||||
<method name="save_scene">
|
||||
<return type="int" enum="Error" />
|
||||
<description>
|
||||
Saves the scene. Returns either [code]OK[/code] or [code]ERR_CANT_CREATE[/code] (see [@GlobalScope] constants).
|
||||
</description>
|
||||
</method>
|
||||
<method name="save_scene_as">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="with_preview" type="bool" default="true" />
|
||||
<description>
|
||||
Saves the scene as a file at [code]path[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="select_file">
|
||||
<return type="void" />
|
||||
<argument index="0" name="file" type="String" />
|
||||
<description>
|
||||
Selects the file, with the path provided by [code]file[/code], in the FileSystem dock.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_main_screen_editor">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Sets the editor's current main screen to the one specified in [code]name[/code]. It will also make the editor's tab button at the top to be visible if it weren't. [code]name[/code] must match the text of the tab in question exactly like: [code]2D[/code], [code]3D[/code], [code]Script[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_main_screen_editor_tab_button_visible">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="visible" type="bool" />
|
||||
<description>
|
||||
Sets whether the specified main screen's button is visible or not. Will not change the main screen. [code]name[/code] must match the text of the tab in question exactly like: [code]2D[/code], [code]3D[/code], [code]Script[/code], [code]AssetLib[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_plugin_enabled">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="String" />
|
||||
<argument index="1" name="enabled" type="bool" />
|
||||
<description>
|
||||
Sets the enabled status of a plugin. The plugin name is the same as its directory name.
|
||||
</description>
|
||||
</method>
|
||||
<method name="stop_playing_scene">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Stops the scene that is currently playing.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="distraction_free_mode" type="bool" setter="set_distraction_free_mode" getter="is_distraction_free_mode_enabled">
|
||||
If [code]true[/code], enables distraction-free mode which hides side docks to increase the space available for the main view.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,608 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorPlugin" inherits="Node" version="4.2">
|
||||
<brief_description>
|
||||
Used by the editor to extend its functionality.
|
||||
</brief_description>
|
||||
<description>
|
||||
Plugins are used by the editor to extend functionality. The most common types of plugins are those which edit a given node or resource type, import plugins and export plugins. See also [EditorScript] to add functions to the editor.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>$DOCS_URL/tutorials/plugins/editor/index.md</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_autoload_singleton">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="path" type="String" />
|
||||
<description>
|
||||
Adds a script at [code]path[/code] to the Autoload list as [code]name[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_control_to_bottom_panel">
|
||||
<return type="ToolButton" />
|
||||
<argument index="0" name="control" type="Control" />
|
||||
<argument index="1" name="title" type="String" />
|
||||
<description>
|
||||
Adds a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_bottom_panel] and free it with [method Node.queue_free].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_control_to_container">
|
||||
<return type="void" />
|
||||
<argument index="0" name="container" type="int" enum="EditorPlugin.CustomControlContainer" />
|
||||
<argument index="1" name="control" type="Control" />
|
||||
<description>
|
||||
Adds a custom control to a container (see [enum CustomControlContainer]). There are many locations where custom controls can be added in the editor UI.
|
||||
Please remember that you have to manage the visibility of your custom controls yourself (and likely hide it after adding it).
|
||||
When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_container] and free it with [method Node.queue_free].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_control_to_dock">
|
||||
<return type="void" />
|
||||
<argument index="0" name="slot" type="int" enum="EditorPlugin.DockSlot" />
|
||||
<argument index="1" name="control" type="Control" />
|
||||
<description>
|
||||
Adds the control to a specific dock slot (see [enum DockSlot] for options).
|
||||
If the dock is repositioned and as long as the plugin is active, the editor will save the dock position on further sessions.
|
||||
When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_docks] and free it with [method Node.queue_free].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_convert_menu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="handler" type="Object" />
|
||||
<argument index="2" name="callback" type="String" />
|
||||
<argument index="3" name="ud" type="Variant" default="null" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_convert_submenu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="submenu" type="Object" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_custom_type">
|
||||
<return type="void" />
|
||||
<argument index="0" name="type" type="String" />
|
||||
<argument index="1" name="base" type="String" />
|
||||
<argument index="2" name="script" type="Script" />
|
||||
<argument index="3" name="icon" type="Texture" />
|
||||
<description>
|
||||
Adds a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed.
|
||||
When given node or resource is selected, the base type will be instanced (ie, "Spatial", "Control", "Resource"), then the script will be loaded and set to this object.
|
||||
You can use the virtual method [method handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
|
||||
During run-time, this will be a simple object with a script so this function does not need to be called then.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_export_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorExportPlugin" />
|
||||
<description>
|
||||
Registers a new [EditorExportPlugin]. Export plugins are used to perform tasks when the project is being exported.
|
||||
See [method add_inspector_plugin] for an example of how to register a plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_import_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="importer" type="EditorImportPlugin" />
|
||||
<description>
|
||||
Registers a new [EditorImportPlugin]. Import plugins are used to import custom and unsupported assets as a custom [Resource] type.
|
||||
[b]Note:[/b] If you want to import custom 3D asset formats use [method add_scene_import_plugin] instead.
|
||||
See [method add_inspector_plugin] for an example of how to register a plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_inspector_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorInspectorPlugin" />
|
||||
<description>
|
||||
Registers a new [EditorInspectorPlugin]. Inspector plugins are used to extend [EditorInspector] and provide custom configuration tools for your object's properties.
|
||||
[b]Note:[/b] Always use [method remove_inspector_plugin] to remove the registered [EditorInspectorPlugin] when your [EditorPlugin] is disabled to prevent leaks and an unexpected behavior.
|
||||
[codeblock]
|
||||
const MyInspectorPlugin = preload("res://addons/your_addon/path/to/your/script.gd")
|
||||
var inspector_plugin = MyInspectorPlugin.new()
|
||||
|
||||
func _enter_tree():
|
||||
add_inspector_plugin(inspector_plugin)
|
||||
|
||||
func _exit_tree():
|
||||
remove_inspector_plugin(inspector_plugin)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_scene_import_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="scene_importer" type="EditorSceneImporter" />
|
||||
<description>
|
||||
Registers a new [EditorSceneImporter]. Scene importers are used to import custom 3D asset formats as scenes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_spatial_gizmo_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorSpatialGizmoPlugin" />
|
||||
<description>
|
||||
Registers a new [EditorSpatialGizmoPlugin]. Gizmo plugins are used to add custom gizmos to the 3D preview viewport for a [Spatial].
|
||||
See [method add_inspector_plugin] for an example of how to register a plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_tool_menu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="handler" type="Object" />
|
||||
<argument index="2" name="callback" type="String" />
|
||||
<argument index="3" name="ud" type="Variant" default="null" />
|
||||
<description>
|
||||
Adds a custom menu item to [b]Project > Tools[/b] as [code]name[/code] that calls [code]callback[/code] on an instance of [code]handler[/code] with a parameter [code]ud[/code] when user activates it.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_tool_submenu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="submenu" type="Object" />
|
||||
<description>
|
||||
Adds a custom submenu under [b]Project > Tools >[/b] [code]name[/code]. [code]submenu[/code] should be an object of class [PopupMenu]. This submenu should be cleaned up using [code]remove_tool_menu_item(name)[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="apply_changes" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
This method is called when the editor is about to save the project, switch to another tab, etc. It asks the plugin to apply any pending state changes to ensure consistency.
|
||||
This is used, for example, in shader editors to let the plugin know that it must apply the shader code being written by the user to the object.
|
||||
</description>
|
||||
</method>
|
||||
<method name="build" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
This method is called when the editor is about to run the project. The plugin can then perform required operations before the project runs.
|
||||
This method must return a boolean. If this method returns [code]false[/code], the project will not run. The run is aborted immediately, so this also prevents all other plugins' [method build] methods from running.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clear all the state and reset the object being edited to zero. This ensures your plugin does not keep editing a currently existing node, or a node from the wrong scene.
|
||||
</description>
|
||||
</method>
|
||||
<method name="disable_plugin" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Called by the engine when the user disables the [EditorPlugin] in the Plugin tab of the project settings window.
|
||||
</description>
|
||||
</method>
|
||||
<method name="edit" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<description>
|
||||
This function is used for plugins that edit specific object types (nodes or resources). It requests the editor to edit the given object.
|
||||
</description>
|
||||
</method>
|
||||
<method name="enable_plugin" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Called by the engine when the user enables the [EditorPlugin] in the Plugin tab of the project settings window.
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_canvas_draw_over_viewport" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="overlay" type="Control" />
|
||||
<description>
|
||||
Called by the engine when the 2D editor's viewport is updated. Use the [code]overlay[/code] [Control] for drawing. You can update the viewport manually by calling [method update_overlays].
|
||||
[codeblock]
|
||||
func forward_canvas_draw_over_viewport(overlay):
|
||||
# Draw a circle at cursor position.
|
||||
overlay.draw_circle(overlay.get_local_mouse_position(), 64, Color.white)
|
||||
|
||||
func forward_canvas_gui_input(event):
|
||||
if event is InputEventMouseMotion:
|
||||
# Redraw viewport when cursor is moved.
|
||||
update_overlays()
|
||||
return true
|
||||
return false
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_canvas_force_draw_over_viewport" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="overlay" type="Control" />
|
||||
<description>
|
||||
This method is the same as [method forward_canvas_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
|
||||
You need to enable calling of this method by using [method set_force_draw_over_forwarding_enabled].
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_canvas_gui_input" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="event" type="InputEvent" />
|
||||
<description>
|
||||
Called when there is a root node in the current edited scene, [method handles] is implemented and an [InputEvent] happens in the 2D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
|
||||
[codeblock]
|
||||
# Prevents the InputEvent to reach other Editor classes
|
||||
func forward_canvas_gui_input(event):
|
||||
var forward = true
|
||||
return forward
|
||||
[/codeblock]
|
||||
Must [code]return false[/code] in order to forward the [InputEvent] to other Editor classes. Example:
|
||||
[codeblock]
|
||||
# Consumes InputEventMouseMotion and forwards other InputEvent types
|
||||
func forward_canvas_gui_input(event):
|
||||
var forward = false
|
||||
if event is InputEventMouseMotion:
|
||||
forward = true
|
||||
return forward
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_spatial_draw_over_viewport" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="overlay" type="Control" />
|
||||
<description>
|
||||
Called by the engine when the 3D editor's viewport is updated. Use the [code]overlay[/code] [Control] for drawing. You can update the viewport manually by calling [method update_overlays].
|
||||
[codeblock]
|
||||
func forward_spatial_draw_over_viewport(overlay):
|
||||
# Draw a circle at cursor position.
|
||||
overlay.draw_circle(overlay.get_local_mouse_position(), 64)
|
||||
|
||||
func forward_spatial_gui_input(camera, event):
|
||||
if event is InputEventMouseMotion:
|
||||
# Redraw viewport when cursor is moved.
|
||||
update_overlays()
|
||||
return true
|
||||
return false
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_spatial_force_draw_over_viewport" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="overlay" type="Control" />
|
||||
<description>
|
||||
This method is the same as [method forward_spatial_draw_over_viewport], except it draws on top of everything. Useful when you need an extra layer that shows over anything else.
|
||||
You need to enable calling of this method by using [method set_force_draw_over_forwarding_enabled].
|
||||
</description>
|
||||
</method>
|
||||
<method name="forward_spatial_gui_input" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<argument index="0" name="camera" type="Camera" />
|
||||
<argument index="1" name="event" type="InputEvent" />
|
||||
<description>
|
||||
Called when there is a root node in the current edited scene, [method handles] is implemented and an [InputEvent] happens in the 3D viewport. Intercepts the [InputEvent], if [code]return true[/code] [EditorPlugin] consumes the [code]event[/code], otherwise forwards [code]event[/code] to other Editor classes. Example:
|
||||
[codeblock]
|
||||
# Prevents the InputEvent to reach other Editor classes
|
||||
func forward_spatial_gui_input(camera, event):
|
||||
return EditorPlugin.AFTER_GUI_INPUT_STOP
|
||||
[/codeblock]
|
||||
Must [code]return false[/code] in order to forward the [InputEvent] to other Editor classes. Example:
|
||||
[codeblock]
|
||||
# Consumes InputEventMouseMotion and forwards other InputEvent types
|
||||
func forward_spatial_gui_input(camera, event):
|
||||
var forward = EditorPlugin.AFTER_GUI_INPUT_STOP
|
||||
if event is InputEventMouseMotion:
|
||||
forward = EditorPlugin.AFTER_GUI_INPUT_PASS
|
||||
return forward
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_breakpoints" qualifiers="virtual">
|
||||
<return type="PoolStringArray" />
|
||||
<description>
|
||||
This is for editors that edit script-based objects. You can return a list of breakpoints in the format ([code]script:line[/code]), for example: [code]res://path_to_script.gd:25[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_interface">
|
||||
<return type="EditorInterface" />
|
||||
<description>
|
||||
Returns the [EditorInterface] object that gives you control over Godot editor's window and its functionalities.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_plugin_icon" qualifiers="virtual">
|
||||
<return type="Texture" />
|
||||
<description>
|
||||
Override this method in your plugin to return a [Texture] in order to give it an icon.
|
||||
For main screen plugins, this appears at the top of the screen, to the right of the "2D", "3D", "Script", and "AssetLib" buttons.
|
||||
Ideally, the plugin icon should be white with a transparent background and 16x16 pixels in size.
|
||||
[codeblock]
|
||||
func get_plugin_icon():
|
||||
# You can use a custom icon:
|
||||
return preload("res://addons/my_plugin/my_plugin_icon.svg")
|
||||
# Or use a built-in icon:
|
||||
return get_editor_interface().get_base_control().get_icon("Node", "EditorIcons")
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_plugin_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Override this method in your plugin to provide the name of the plugin when displayed in the Godot editor.
|
||||
For main screen plugins, this appears at the top of the screen, to the right of the "2D", "3D", "Script", and "AssetLib" buttons.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_script_create_dialog">
|
||||
<return type="ScriptCreateDialog" />
|
||||
<description>
|
||||
Gets the Editor's dialogue used for making scripts.
|
||||
[b]Note:[/b] Users can configure it before use.
|
||||
[b]Warning:[/b] Removing and freeing this node will render a part of the editor useless and may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_state" qualifiers="virtual">
|
||||
<return type="Dictionary" />
|
||||
<description>
|
||||
Override this method to provide a state data you want to be saved, like view position, grid settings, folding, etc. This is used when saving the scene (so state is kept when opening it again) and for switching tabs (so state can be restored when the tab returns). This data is automatically saved for each scene in an [code]editstate[/code] file in the editor metadata folder. If you want to store global (scene-independent) editor data for your plugin, you can use [method get_window_layout] instead.
|
||||
Use [method set_state] to restore your saved state.
|
||||
[b]Note:[/b] This method should not be used to save important settings that should persist with the project.
|
||||
[b]Note:[/b] You must implement [method get_plugin_name] for the state to be stored and restored correctly.
|
||||
[codeblock]
|
||||
func get_state():
|
||||
var state = {"zoom": zoom, "preferred_color": my_color}
|
||||
return state
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_undo_redo">
|
||||
<return type="UndoRedo" />
|
||||
<description>
|
||||
Gets the undo/redo object. Most actions in the editor can be undoable, so use this object to make sure this happens when it's worth it.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_window_layout" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="layout" type="ConfigFile" />
|
||||
<description>
|
||||
Override this method to provide the GUI layout of the plugin or any other data you want to be stored. This is used to save the project's editor layout when [method queue_save_layout] is called or the editor layout was changed (for example changing the position of a dock). The data is stored in the [code]editor_layout.cfg[/code] file in the editor metadata directory.
|
||||
Use [method set_window_layout] to restore your saved layout.
|
||||
[codeblock]
|
||||
func get_window_layout(configuration):
|
||||
configuration.set_value("MyPlugin", "window_position", $Window.position)
|
||||
configuration.set_value("MyPlugin", "icon_color", $Icon.modulate)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="handles" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="object" type="Object" />
|
||||
<description>
|
||||
Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method edit] and [method make_visible] called when the editor requests them. If you have declared the methods [method forward_canvas_gui_input] and [method forward_spatial_gui_input] these will be called too.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_main_screen" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this is a main screen editor plugin (it goes in the workspace selector together with [b]2D[/b], [b]3D[/b], [b]Script[/b] and [b]AssetLib[/b]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="hide_bottom_panel">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Minimizes the bottom panel.
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_bottom_panel_item_visible">
|
||||
<return type="void" />
|
||||
<argument index="0" name="item" type="Control" />
|
||||
<description>
|
||||
Makes a specific item in the bottom panel visible.
|
||||
</description>
|
||||
</method>
|
||||
<method name="make_visible" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="visible" type="bool" />
|
||||
<description>
|
||||
This function will be called when the editor is requested to become visible. It is used for plugins that edit a specific object type.
|
||||
Remember that you have to manage the visibility of all your editor controls manually.
|
||||
</description>
|
||||
</method>
|
||||
<method name="queue_save_layout" qualifiers="const">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Queue save the project's editor layout.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_autoload_singleton">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Removes an Autoload [code]name[/code] from the list.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_control_from_bottom_panel">
|
||||
<return type="void" />
|
||||
<argument index="0" name="control" type="Control" />
|
||||
<description>
|
||||
Removes the control from the bottom panel. You have to manually [method Node.queue_free] the control.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_control_from_container">
|
||||
<return type="void" />
|
||||
<argument index="0" name="container" type="int" enum="EditorPlugin.CustomControlContainer" />
|
||||
<argument index="1" name="control" type="Control" />
|
||||
<description>
|
||||
Removes the control from the specified container. You have to manually [method Node.queue_free] the control.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_control_from_docks">
|
||||
<return type="void" />
|
||||
<argument index="0" name="control" type="Control" />
|
||||
<description>
|
||||
Removes the control from the dock. You have to manually [method Node.queue_free] the control.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_convert_menu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_custom_type">
|
||||
<return type="void" />
|
||||
<argument index="0" name="type" type="String" />
|
||||
<description>
|
||||
Removes a custom type added by [method add_custom_type].
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_export_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorExportPlugin" />
|
||||
<description>
|
||||
Removes an export plugin registered by [method add_export_plugin].
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_import_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="importer" type="EditorImportPlugin" />
|
||||
<description>
|
||||
Removes an import plugin registered by [method add_import_plugin].
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_inspector_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorInspectorPlugin" />
|
||||
<description>
|
||||
Removes an inspector plugin registered by [method add_import_plugin]
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_scene_import_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="scene_importer" type="EditorSceneImporter" />
|
||||
<description>
|
||||
Removes a scene importer registered by [method add_scene_import_plugin].
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_spatial_gizmo_plugin">
|
||||
<return type="void" />
|
||||
<argument index="0" name="plugin" type="EditorSpatialGizmoPlugin" />
|
||||
<description>
|
||||
Removes a gizmo plugin registered by [method add_spatial_gizmo_plugin].
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_tool_menu_item">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Removes a menu [code]name[/code] from [b]Project > Tools[/b].
|
||||
</description>
|
||||
</method>
|
||||
<method name="save_external_data" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
This method is called after the editor saves the project or when it's closed. It asks the plugin to save edited external scenes/resources.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_force_draw_over_forwarding_enabled">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Enables calling of [method forward_canvas_force_draw_over_viewport] for the 2D editor and [method forward_spatial_force_draw_over_viewport] for the 3D editor when their viewports are updated. You need to call this method only once and it will work permanently for this plugin.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_input_event_forwarding_always_enabled">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Use this method if you always want to receive inputs from 3D view screen inside [method forward_spatial_gui_input]. It might be especially usable if your plugin will want to use raycast in the scene.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_state" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="state" type="Dictionary" />
|
||||
<description>
|
||||
Restore the state saved by [method get_state]. This method is called when the current scene tab is changed in the editor.
|
||||
[b]Note:[/b] Your plugin must implement [method get_plugin_name], otherwise it will not be recognized and this method will not be called.
|
||||
[codeblock]
|
||||
func set_state(data):
|
||||
zoom = data.get("zoom", 1.0)
|
||||
preferred_color = data.get("my_color", Color.white)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_window_layout" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="layout" type="ConfigFile" />
|
||||
<description>
|
||||
Restore the plugin GUI layout and data saved by [method get_window_layout]. This method is called for every plugin on editor startup. Use the provided [code]configuration[/code] file to read your saved data.
|
||||
[codeblock]
|
||||
func set_window_layout(configuration):
|
||||
$Window.position = configuration.get_value("MyPlugin", "window_position", Vector2())
|
||||
$Icon.modulate = configuration.get_value("MyPlugin", "icon_color", Color.white)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="update_overlays" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Updates the overlays of the 2D and 3D editor viewport. Causes methods [method forward_canvas_draw_over_viewport], [method forward_canvas_force_draw_over_viewport], [method forward_spatial_draw_over_viewport] and [method forward_spatial_force_draw_over_viewport] to be called.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<signals>
|
||||
<signal name="main_screen_changed">
|
||||
<argument index="0" name="screen_name" type="String" />
|
||||
<description>
|
||||
Emitted when user changes the workspace ([b]2D[/b], [b]3D[/b], [b]Script[/b], [b]AssetLib[/b]). Also works with custom screens defined by plugins.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resource_saved">
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<description>
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="scene_changed">
|
||||
<argument index="0" name="scene_root" type="Node" />
|
||||
<description>
|
||||
Emitted when the scene is changed in the editor. The argument will return the root node of the scene that has just become active. If this scene is new and empty, the argument will be [code]null[/code].
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="scene_closed">
|
||||
<argument index="0" name="filepath" type="String" />
|
||||
<description>
|
||||
Emitted when user closes a scene. The argument is file path to a closed scene.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="CONTAINER_TOOLBAR" value="0" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_SPATIAL_EDITOR_MENU" value="1" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_SPATIAL_EDITOR_SIDE_LEFT" value="2" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_SPATIAL_EDITOR_SIDE_RIGHT" value="3" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_SPATIAL_EDITOR_BOTTOM" value="4" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_CANVAS_EDITOR_MENU" value="5" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_CANVAS_EDITOR_SIDE_LEFT" value="6" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_CANVAS_EDITOR_SIDE_RIGHT" value="7" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_CANVAS_EDITOR_BOTTOM" value="8" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_PROPERTY_EDITOR_BOTTOM" value="9" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_PROJECT_SETTING_TAB_LEFT" value="10" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="CONTAINER_PROJECT_SETTING_TAB_RIGHT" value="11" enum="CustomControlContainer">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_LEFT_UL" value="0" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_LEFT_BL" value="1" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_LEFT_UR" value="2" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_LEFT_BR" value="3" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_RIGHT_UL" value="4" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_RIGHT_BL" value="5" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_RIGHT_UR" value="6" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_RIGHT_BR" value="7" enum="DockSlot">
|
||||
</constant>
|
||||
<constant name="DOCK_SLOT_MAX" value="8" enum="DockSlot">
|
||||
Represents the size of the [enum DockSlot] enum.
|
||||
</constant>
|
||||
<constant name="AFTER_GUI_INPUT_PASS" value="0" enum="AfterGUIInput">
|
||||
</constant>
|
||||
<constant name="AFTER_GUI_INPUT_STOP" value="1" enum="AfterGUIInput">
|
||||
</constant>
|
||||
<constant name="AFTER_GUI_INPUT_NO_DESELECT" value="2" enum="AfterGUIInput">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,143 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorProperty" inherits="Container" version="4.2">
|
||||
<brief_description>
|
||||
Custom control to edit properties for adding into the inspector.
|
||||
</brief_description>
|
||||
<description>
|
||||
This control allows property editing for one or multiple properties into [EditorInspector]. It is added via [EditorInspectorPlugin].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_focusable">
|
||||
<return type="void" />
|
||||
<argument index="0" name="control" type="Control" />
|
||||
<description>
|
||||
If any of the controls added can gain keyboard focus, add it here. This ensures that focus will be restored if the inspector is refreshed.
|
||||
</description>
|
||||
</method>
|
||||
<method name="emit_changed">
|
||||
<return type="void" />
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<argument index="1" name="value" type="Variant" />
|
||||
<argument index="2" name="field" type="StringName" default="@""" />
|
||||
<argument index="3" name="changing" type="bool" default="false" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_edited_object">
|
||||
<return type="Object" />
|
||||
<description>
|
||||
Gets the edited object.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_edited_property">
|
||||
<return type="StringName" />
|
||||
<description>
|
||||
Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin.parse_property]), then this will return the property.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_bottom_editor">
|
||||
<return type="void" />
|
||||
<argument index="0" name="editor" type="Control" />
|
||||
<description>
|
||||
Puts the [code]editor[/code] control below the property label. The control must be previously added using [method Node.add_child].
|
||||
</description>
|
||||
</method>
|
||||
<method name="update_property" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
When this virtual function is called, you must update your editor.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="checkable" type="bool" setter="set_checkable" getter="is_checkable" default="false">
|
||||
Used by the inspector, set to [code]true[/code] when the property is checkable.
|
||||
</member>
|
||||
<member name="checked" type="bool" setter="set_checked" getter="is_checked" default="false">
|
||||
Used by the inspector, set to [code]true[/code] when the property is checked.
|
||||
</member>
|
||||
<member name="draw_red" type="bool" setter="set_draw_red" getter="is_draw_red" default="false">
|
||||
Used by the inspector, set to [code]true[/code] when the property is drawn with the editor theme's warning color. This is used for editable children's properties.
|
||||
</member>
|
||||
<member name="keying" type="bool" setter="set_keying" getter="is_keying" default="false">
|
||||
Used by the inspector, set to [code]true[/code] when the property can add keys for animation.
|
||||
</member>
|
||||
<member name="label" type="String" setter="set_label" getter="get_label" default="""">
|
||||
Set this property to change the label (if you want to show one).
|
||||
</member>
|
||||
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
|
||||
Used by the inspector, set to [code]true[/code] when the property is read-only.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="multiple_properties_changed">
|
||||
<argument index="0" name="properties" type="PoolStringArray" />
|
||||
<argument index="1" name="value" type="Array" />
|
||||
<description>
|
||||
Emit it if you want multiple properties modified at the same time. Do not use if added via [method EditorInspectorPlugin.parse_property].
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="object_id_selected">
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<description>
|
||||
Used by sub-inspectors. Emit it if what was selected was an Object ID.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_changed">
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<argument index="1" name="value" type="Variant" />
|
||||
<argument index="2" name="field" type="String" />
|
||||
<argument index="3" name="changing" type="bool" />
|
||||
<description>
|
||||
Do not emit this manually, use the [method emit_changed] method instead.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_checked">
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<argument index="1" name="checked" type="bool" />
|
||||
<description>
|
||||
Emitted when a property was checked. Used internally.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_keyed">
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<description>
|
||||
Emit it if you want to add this value as an animation key (check for keying being enabled first).
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_keyed_with_value">
|
||||
<argument index="0" name="property" type="StringName" />
|
||||
<argument index="1" name="value" type="Variant" />
|
||||
<description>
|
||||
Emit it if you want to key a property with a single value.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="property_pinned">
|
||||
<argument index="0" name="property" type="String" />
|
||||
<argument index="1" name="pinned" type="bool" />
|
||||
<description>
|
||||
Emit it if you want to mark (or unmark) the value of a property for being saved regardless of being equal to the default value.
|
||||
The default value is the one the property will get when the node is just instantiated and can come from an ancestor scene in the inheritance/instancing chain, a script or a builtin class.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resource_selected">
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="resource" type="Resource" />
|
||||
<description>
|
||||
If you want a sub-resource to be edited, emit this signal with the resource.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="selected">
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="focusable_idx" type="int" />
|
||||
<description>
|
||||
Emitted when selected. Used internally.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorResourceConversionPlugin" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_convert" qualifiers="virtual">
|
||||
<return type="Resource" />
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_converts_to" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorResourcePicker" inherits="HBoxContainer" version="4.2">
|
||||
<brief_description>
|
||||
Godot editor's control for selecting [Resource] type properties.
|
||||
</brief_description>
|
||||
<description>
|
||||
This [Control] node is used in the editor's Inspector dock to allow editing of [Resource] type properties. It provides options for creating, loading, saving and converting resources. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
|
||||
[b]Note:[/b] This [Control] does not include any editor for the resource, as editing is controlled by the Inspector dock itself or sub-Inspectors.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="can_drop_data_fw" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="position" type="Vector2" />
|
||||
<argument index="1" name="data" type="Variant" />
|
||||
<argument index="2" name="from" type="Control" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="drop_data_fw">
|
||||
<return type="void" />
|
||||
<argument index="0" name="position" type="Vector2" />
|
||||
<argument index="1" name="data" type="Variant" />
|
||||
<argument index="2" name="from" type="Control" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_allowed_types" qualifiers="const">
|
||||
<return type="PoolStringArray" />
|
||||
<description>
|
||||
Returns a list of all allowed types and subtypes corresponding to the [member base_type]. If the [member base_type] is empty, an empty list is returned.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_drag_data_fw">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="position" type="Vector2" />
|
||||
<argument index="1" name="from" type="Control" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="handle_menu_selected" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<description>
|
||||
This virtual method can be implemented to handle context menu items not handled by default. See [method set_create_options].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_create_options" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="menu_node" type="Object" />
|
||||
<description>
|
||||
This virtual method is called when updating the context menu of [EditorResourcePicker]. Implement this method to override the "New ..." items with your own options. [code]menu_node[/code] is a reference to the [PopupMenu] node.
|
||||
[b]Note:[/b] Implement [method handle_menu_selected] to handle these custom items.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_toggle_pressed">
|
||||
<return type="void" />
|
||||
<argument index="0" name="pressed" type="bool" />
|
||||
<description>
|
||||
Sets the toggle mode state for the main button. Works only if [member toggle_mode] is set to [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="base_type" type="String" setter="set_base_type" getter="get_base_type" default="""">
|
||||
The base type of allowed resource types. Can be a comma-separated list of several options.
|
||||
</member>
|
||||
<member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true">
|
||||
If [code]true[/code], the value can be selected and edited.
|
||||
</member>
|
||||
<member name="edited_resource" type="Resource" setter="set_edited_resource" getter="get_edited_resource">
|
||||
The edited resource value.
|
||||
</member>
|
||||
<member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode" default="false">
|
||||
If [code]true[/code], the main button with the resource preview works in the toggle mode. Use [method set_toggle_pressed] to manually set the state.
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="resource_changed">
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<description>
|
||||
Emitted when the value of the edited resource was changed.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="resource_selected">
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<argument index="1" name="edit" type="bool" />
|
||||
<description>
|
||||
Emitted when the resource value was set and user clicked to edit it. When [code]edit[/code] is [code]true[/code], the signal was caused by the context menu "Edit" option.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorResourcePreview" inherits="Node" version="4.2">
|
||||
<brief_description>
|
||||
Helper to generate previews of resources or files.
|
||||
</brief_description>
|
||||
<description>
|
||||
This object is used to generate previews for resources of files.
|
||||
[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_resource_previewer].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_preview_generator">
|
||||
<return type="void" />
|
||||
<argument index="0" name="generator" type="EditorResourcePreviewGenerator" />
|
||||
<description>
|
||||
Create an own, custom preview generator.
|
||||
</description>
|
||||
</method>
|
||||
<method name="check_for_invalidation">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Check if the resource changed, if so, it will be invalidated and the corresponding signal emitted.
|
||||
</description>
|
||||
</method>
|
||||
<method name="queue_edited_resource_preview">
|
||||
<return type="void" />
|
||||
<argument index="0" name="resource" type="Resource" />
|
||||
<argument index="1" name="receiver" type="Object" />
|
||||
<argument index="2" name="receiver_func" type="StringName" />
|
||||
<argument index="3" name="userdata" type="Variant" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="queue_resource_preview">
|
||||
<return type="void" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="receiver" type="Object" />
|
||||
<argument index="2" name="receiver_func" type="StringName" />
|
||||
<argument index="3" name="userdata" type="Variant" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_preview_generator">
|
||||
<return type="void" />
|
||||
<argument index="0" name="generator" type="EditorResourcePreviewGenerator" />
|
||||
<description>
|
||||
Removes a custom preview generator.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<signals>
|
||||
<signal name="preview_invalidated">
|
||||
<argument index="0" name="path" type="String" />
|
||||
<description>
|
||||
Emitted if a preview was invalidated (changed). [code]path[/code] corresponds to the path of the preview.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorResourcePreviewGenerator" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
Custom generator of previews.
|
||||
</brief_description>
|
||||
<description>
|
||||
Custom code to generate previews. Please check [code]file_dialog/thumbnail_size[/code] in [EditorSettings] to find out the right size to do previews at.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="can_generate_small_preview" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
If this function returns [code]true[/code], the generator will call [method generate] or [method generate_from_path] for small previews as well.
|
||||
By default, it returns [code]false[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate" qualifiers="virtual">
|
||||
<return type="Texture" />
|
||||
<argument index="0" name="from" type="Resource" />
|
||||
<argument index="1" name="size" type="Vector2" />
|
||||
<description>
|
||||
Generate a preview from a given resource with the specified size. This must always be implemented.
|
||||
Returning an empty texture is an OK way to fail and let another generator take care.
|
||||
Care must be taken because this function is always called from a thread (not the main thread).
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate_from_path" qualifiers="virtual">
|
||||
<return type="Texture" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="size" type="Vector2" />
|
||||
<description>
|
||||
Generate a preview directly from a path with the specified size. Implementing this is optional, as default code will load and call [method generate].
|
||||
Returning an empty texture is an OK way to fail and let another generator take care.
|
||||
Care must be taken because this function is always called from a thread (not the main thread).
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate_small_preview_automatically" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
If this function returns [code]true[/code], the generator will automatically generate the small previews from the normal preview texture generated by the methods [method generate] or [method generate_from_path].
|
||||
By default, it returns [code]false[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="handles" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="type" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if your generator supports the resource of type [code]type[/code].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSceneImporter" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
Imports scenes from third-parties' 3D files.
|
||||
</brief_description>
|
||||
<description>
|
||||
[EditorSceneImporter] allows to define an importer script for a third-party 3D format.
|
||||
To use [EditorSceneImporter], register it using the [method EditorPlugin.add_scene_import_plugin] method first.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_get_extensions" qualifiers="virtual">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_import_flags" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_import_animation" qualifiers="virtual">
|
||||
<return type="Animation" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="flags" type="int" />
|
||||
<argument index="2" name="bake_fps" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_import_scene" qualifiers="virtual">
|
||||
<return type="Node" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="flags" type="int" />
|
||||
<argument index="2" name="bake_fps" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="import_animation_from_other_importer">
|
||||
<return type="Animation" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="flags" type="int" />
|
||||
<argument index="2" name="bake_fps" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="import_scene_from_other_importer">
|
||||
<return type="Node" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="flags" type="int" />
|
||||
<argument index="2" name="bake_fps" type="int" />
|
||||
<argument index="3" name="compress_flags" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
<constant name="IMPORT_SCENE" value="1">
|
||||
</constant>
|
||||
<constant name="IMPORT_ANIMATION" value="2">
|
||||
</constant>
|
||||
<constant name="IMPORT_ANIMATION_DETECT_LOOP" value="4">
|
||||
</constant>
|
||||
<constant name="IMPORT_ANIMATION_OPTIMIZE" value="8">
|
||||
</constant>
|
||||
<constant name="IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS" value="16">
|
||||
</constant>
|
||||
<constant name="IMPORT_ANIMATION_KEEP_VALUE_TRACKS" value="32">
|
||||
</constant>
|
||||
<constant name="IMPORT_GENERATE_TANGENT_ARRAYS" value="256">
|
||||
</constant>
|
||||
<constant name="IMPORT_FAIL_ON_MISSING_DEPENDENCIES" value="512">
|
||||
</constant>
|
||||
<constant name="IMPORT_MATERIALS_IN_INSTANCES" value="1024">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorScenePostImport" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
Post-processes scenes after import.
|
||||
</brief_description>
|
||||
<description>
|
||||
Imported scenes can be automatically modified right after import by setting their [b]Custom Script[/b] Import property to a [code]tool[/code] script that inherits from this class.
|
||||
The [method post_import] callback receives the imported scene's root node and returns the modified version of the scene. Usage example:
|
||||
[codeblock]
|
||||
tool # Needed so it runs in editor
|
||||
extends EditorScenePostImport
|
||||
|
||||
# This sample changes all node names
|
||||
|
||||
# Called right after the scene is imported and gets the root node
|
||||
func post_import(scene):
|
||||
# Change all node names to "modified_[oldnodename]"
|
||||
iterate(scene)
|
||||
return scene # Remember to return the imported scene
|
||||
|
||||
func iterate(node):
|
||||
if node != null:
|
||||
node.name = "modified_" + node.name
|
||||
for child in node.get_children():
|
||||
iterate(child)
|
||||
[/codeblock]
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>$DOCS_URL/tutorials/assets_pipeline/importing_scenes.html#custom-script</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_source_file" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the source file path which got imported (e.g. [code]res://scene.dae[/code]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_source_folder" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the resource folder the imported scene file is located in.
|
||||
</description>
|
||||
</method>
|
||||
<method name="post_import" qualifiers="virtual">
|
||||
<return type="Object" />
|
||||
<argument index="0" name="scene" type="Object" />
|
||||
<description>
|
||||
Called after the scene was imported. This method must return the modified version of the scene.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorScript" inherits="Reference" version="4.2">
|
||||
<brief_description>
|
||||
Base script that can be used to add extension functions to the editor.
|
||||
</brief_description>
|
||||
<description>
|
||||
Scripts extending this class and implementing its [method _run] method can be executed from the Script Editor's [b]File > Run[/b] menu option (or by pressing [kbd]Ctrl + Shift + X[/kbd]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]s instead.
|
||||
[b]Note:[/b] Extending scripts need to have [code]tool[/code] mode enabled.
|
||||
[b]Example script:[/b]
|
||||
[codeblock]
|
||||
tool
|
||||
extends EditorScript
|
||||
|
||||
func _run():
|
||||
print("Hello from the Godot Editor!")
|
||||
[/codeblock]
|
||||
[b]Note:[/b] The script is run in the Editor context, which means the output is visible in the console window started with the Editor (stdout) instead of the usual Godot [b]Output[/b] dock.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_run" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
This method is executed by the Editor when [b]File > Run[/b] is used.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_root_node">
|
||||
<return type="void" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<description>
|
||||
Adds [code]node[/code] as a child of the root node in the editor context.
|
||||
[b]Warning:[/b] The implementation of this method is currently disabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_interface">
|
||||
<return type="EditorInterface" />
|
||||
<description>
|
||||
Returns the [EditorInterface] singleton instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_scene">
|
||||
<return type="Node" />
|
||||
<description>
|
||||
Returns the Editor's currently active scene.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorScriptPicker" inherits="EditorResourcePicker" version="4.2">
|
||||
<brief_description>
|
||||
Godot editor's control for selecting the [code]script[/code] property of a [Node].
|
||||
</brief_description>
|
||||
<description>
|
||||
Similar to [EditorResourcePicker] this [Control] node is used in the editor's Inspector dock, but only to edit the [code]script[/code] property of a [Node]. Default options for creating new resources of all possible subtypes are replaced with dedicated buttons that open the "Attach Node Script" dialog. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
|
||||
[b]Note:[/b] You must set the [member script_owner] for the custom context menu items to work.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="script_owner" type="Node" setter="set_script_owner" getter="get_script_owner">
|
||||
The owner [Node] of the script property that holds the edited resource.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSelection" inherits="Object" version="4.2">
|
||||
<brief_description>
|
||||
Manages the SceneTree selection in the editor.
|
||||
</brief_description>
|
||||
<description>
|
||||
This object manages the SceneTree selection in the editor.
|
||||
[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_selection].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_node">
|
||||
<return type="void" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<description>
|
||||
Adds a node to the selection.
|
||||
[b]Note:[/b] The newly selected node will not be automatically edited in the inspector. If you want to edit a node, use [method EditorInterface.edit_node].
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clear the selection.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_selected_nodes">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets the list of selected nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_transformable_selected_nodes">
|
||||
<return type="Array" />
|
||||
<description>
|
||||
Gets the list of selected nodes, optimized for transform operations (i.e. moving them, rotating, etc). This list avoids situations where a node is selected and also child/grandchild.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_node">
|
||||
<return type="void" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<description>
|
||||
Removes a node from the selection.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<signals>
|
||||
<signal name="selection_changed">
|
||||
<description>
|
||||
Emitted when the selection changes.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,851 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSettings" inherits="Resource" version="4.2">
|
||||
<brief_description>
|
||||
Object that holds the project-independent editor settings.
|
||||
</brief_description>
|
||||
<description>
|
||||
Object that holds the project-independent editor settings. These settings are generally visible in the [b]Editor > Editor Settings[/b] menu.
|
||||
Property names use slash delimiters to distinguish sections. Setting values can be of any [Variant] type. It's recommended to use [code]snake_case[/code] for editor settings to be consistent with the Godot editor itself.
|
||||
Accessing the settings can be done using the following methods, such as:
|
||||
[codeblock]
|
||||
# `settings.set("some/property", value)` also works as this class overrides `_set()` internally.
|
||||
settings.set_setting("some/property",value)
|
||||
|
||||
# `settings.get("some/property", value)` also works as this class overrides `_get()` internally.
|
||||
settings.get_setting("some/property")
|
||||
|
||||
var list_of_settings = settings.get_property_list()
|
||||
[/codeblock]
|
||||
[b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_editor_settings].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_property_info">
|
||||
<return type="void" />
|
||||
<argument index="0" name="info" type="Dictionary" />
|
||||
<description>
|
||||
Adds a custom property info to a property. The dictionary must contain:
|
||||
- [code]name[/code]: [String] (the name of the property)
|
||||
- [code]type[/code]: [int] (see [enum Variant.Type])
|
||||
- optionally [code]hint[/code]: [int] (see [enum PropertyHint]) and [code]hint_string[/code]: [String]
|
||||
[b]Example:[/b]
|
||||
[codeblock]
|
||||
editor_settings.set("category/property_name", 0)
|
||||
|
||||
var property_info = {
|
||||
"name": "category/property_name",
|
||||
"type": TYPE_INT,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "one,two,three"
|
||||
}
|
||||
|
||||
editor_settings.add_property_info(property_info)
|
||||
[/codeblock]
|
||||
</description>
|
||||
</method>
|
||||
<method name="erase">
|
||||
<return type="void" />
|
||||
<argument index="0" name="property" type="String" />
|
||||
<description>
|
||||
Erases the setting whose name is specified by [code]property[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_favorites" qualifiers="const">
|
||||
<return type="PoolStringArray" />
|
||||
<description>
|
||||
Returns the list of favorite files and directories for this project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_project_metadata" qualifiers="const">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="section" type="String" />
|
||||
<argument index="1" name="key" type="String" />
|
||||
<argument index="2" name="default" type="Variant" default="null" />
|
||||
<description>
|
||||
Returns project-specific metadata for the [code]section[/code] and [code]key[/code] specified. If the metadata doesn't exist, [code]default[/code] will be returned instead. See also [method set_project_metadata].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_project_settings_dir" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the project-specific settings path. Projects all have a unique subdirectory inside the settings path where project-specific settings are saved.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_recent_dirs" qualifiers="const">
|
||||
<return type="PoolStringArray" />
|
||||
<description>
|
||||
Returns the list of recently visited folders in the file dialog for this project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_setting" qualifiers="const">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns the value of the setting specified by [code]name[/code]. This is equivalent to using [method Object.get] on the EditorSettings instance.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_settings_dir" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Gets the global settings path for the engine. Inside this path, you can find some standard paths such as:
|
||||
[code]settings/tmp[/code] - Used for temporary storage of files
|
||||
[code]settings/templates[/code] - Where export templates are located
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_setting" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the setting specified by [code]name[/code] exists, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
<method name="property_can_revert">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the setting specified by [code]name[/code] can have its value reverted to the default value, [code]false[/code] otherwise. When this method returns [code]true[/code], a Revert button will display next to the setting in the Editor Settings.
|
||||
</description>
|
||||
</method>
|
||||
<method name="property_get_revert">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<description>
|
||||
Returns the default value of the setting specified by [code]name[/code]. This is the value that would be applied when clicking the Revert button in the Editor Settings.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_favorites">
|
||||
<return type="void" />
|
||||
<argument index="0" name="dirs" type="PoolStringArray" />
|
||||
<description>
|
||||
Sets the list of favorite files and directories for this project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_initial_value">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="StringName" />
|
||||
<argument index="1" name="value" type="Variant" />
|
||||
<argument index="2" name="update_current" type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_project_metadata">
|
||||
<return type="void" />
|
||||
<argument index="0" name="section" type="String" />
|
||||
<argument index="1" name="key" type="String" />
|
||||
<argument index="2" name="data" type="Variant" />
|
||||
<description>
|
||||
Sets project-specific metadata with the [code]section[/code], [code]key[/code] and [code]data[/code] specified. This metadata is stored outside the project folder and therefore won't be checked into version control. See also [method get_project_metadata].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_recent_dirs">
|
||||
<return type="void" />
|
||||
<argument index="0" name="dirs" type="PoolStringArray" />
|
||||
<description>
|
||||
Sets the list of recently visited folders in the file dialog for this project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_setting">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="value" type="Variant" />
|
||||
<description>
|
||||
Sets the [code]value[/code] of the setting specified by [code]name[/code]. This is equivalent to using [method Object.set] on the EditorSettings instance.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="docks/filesystem/always_show_folders" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays folders in the FileSystem dock's bottom pane when split mode is enabled. If [code]false[/code], only files will be displayed in the bottom pane. Split mode can be toggled by pressing the icon next to the [code]res://[/code] folder path.
|
||||
[b]Note:[/b] This setting has no effect when split mode is disabled (which is the default).
|
||||
</member>
|
||||
<member name="docks/filesystem/dock_mode" type="int" setter="" getter="">
|
||||
Controls where the editor will display the FileSystem panel.
|
||||
</member>
|
||||
<member name="docks/filesystem/split_mode" type="int" setter="" getter="">
|
||||
Controls whether the FileSystem panel can be split horizontally or vertically.
|
||||
</member>
|
||||
<member name="docks/filesystem/thumbnail_size" type="int" setter="" getter="">
|
||||
The thumbnail size to use in the FileSystem dock (in pixels). See also [member filesystem/file_dialog/thumbnail_size].
|
||||
</member>
|
||||
<member name="docks/property_editor/auto_refresh_interval" type="float" setter="" getter="">
|
||||
The refresh interval to use for the inspector dock's properties. The effect of this setting is mainly noticeable when adjusting gizmos in the 2D/3D editor and looking at the inspector at the same time. Lower values make the inspector more often, but take up more CPU time.
|
||||
</member>
|
||||
<member name="docks/property_editor/subresource_hue_tint" type="float" setter="" getter="">
|
||||
The tint intensity to use for the subresources background in the inspector dock. The tint is used to distinguish between different subresources in the inspector. Higher values result in a more noticeable background color difference.
|
||||
</member>
|
||||
<member name="docks/scene_tree/start_create_dialog_fully_expanded" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the Create dialog (Create New Node/Create New Resource) will start with all its sections expanded. Otherwise, sections will be collapsed until the user starts searching (which will automatically expand sections as needed).
|
||||
</member>
|
||||
<member name="editors/2d/bone_color1" type="Color" setter="" getter="">
|
||||
The "start" stop of the color gradient to use for bones in the 2D skeleton editor.
|
||||
</member>
|
||||
<member name="editors/2d/bone_color2" type="Color" setter="" getter="">
|
||||
The "end" stop of the color gradient to use for bones in the 2D skeleton editor.
|
||||
</member>
|
||||
<member name="editors/2d/bone_ik_color" type="Color" setter="" getter="">
|
||||
The color to use for inverse kinematics-enabled bones in the 2D skeleton editor.
|
||||
</member>
|
||||
<member name="editors/2d/bone_outline_color" type="Color" setter="" getter="">
|
||||
The outline color to use for non-selected bones in the 2D skeleton editor. See also [member editors/2d/bone_selected_color].
|
||||
</member>
|
||||
<member name="editors/2d/bone_outline_size" type="int" setter="" getter="">
|
||||
The outline size in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_width].
|
||||
</member>
|
||||
<member name="editors/2d/bone_selected_color" type="Color" setter="" getter="">
|
||||
The color to use for selected bones in the 2D skeleton editor. See also [member editors/2d/bone_outline_color].
|
||||
</member>
|
||||
<member name="editors/2d/bone_width" type="int" setter="" getter="">
|
||||
The bone width in the 2D skeleton editor (in pixels). See also [member editors/2d/bone_outline_size].
|
||||
</member>
|
||||
<member name="editors/2d/constrain_editor_view" type="bool" setter="" getter="">
|
||||
If [code]true[/code], prevents the 2D editor viewport from leaving the scene. Limits are calculated dynamically based on nodes present in the current scene. If [code]false[/code], the 2D editor viewport will be able to move freely, but you risk getting lost when zooming out too far. You can refocus on the scene by selecting a node then pressing [kbd]F[/kbd].
|
||||
</member>
|
||||
<member name="editors/2d/grid_color" type="Color" setter="" getter="">
|
||||
The grid color to use in the 2D editor.
|
||||
</member>
|
||||
<member name="editors/2d/guides_color" type="Color" setter="" getter="">
|
||||
The guides color to use in the 2D editor. Guides can be created by dragging the mouse cursor from the rulers.
|
||||
</member>
|
||||
<member name="editors/2d/pan_speed" type="int" setter="" getter="">
|
||||
The pan speed factor when scrolling the mouse wheel on the 2D editor viewport. Only effective if [member editors/2d/scroll_to_pan] is [code]true[/code].
|
||||
</member>
|
||||
<member name="editors/2d/scroll_to_pan" type="bool" setter="" getter="">
|
||||
If [code]true[/code], scrolling the mouse wheel will pan vertically instead of zoom in the 2D editor. Holding [kbd]Shift[/kbd] at the same time will pan horizontally instead of vertically. See [member editors/2d/pan_speed] to adjust the scrolling speed.
|
||||
[b]Note:[/b] If [code]true[/code], holding [kbd]Ctrl[/kbd] will temporarily override this behavior and will zoom instead of pan.
|
||||
</member>
|
||||
<member name="editors/2d/simple_panning" type="bool" setter="" getter="">
|
||||
If [code]true[/code], allows panning in the 2D editor viewport by holding [kbd]Space[/kbd], without having to hold any mouse buttons at the same time. This can be useful to improve navigation usability when using a trackpad.
|
||||
</member>
|
||||
<member name="editors/2d/smart_snapping_line_color" type="Color" setter="" getter="">
|
||||
The color to use when drawing smart snapping lines in the 2D editor. The smart snapping lines will automatically display when moving 2D nodes if smart snapping is enabled in the Snapping Options menu at the top of the 2D editor viewport.
|
||||
</member>
|
||||
<member name="editors/2d/viewport_border_color" type="Color" setter="" getter="">
|
||||
The color of the viewport border in the 2D editor. This border represents the viewport's size at the base resolution defined in the Project Settings. Objects placed outside this border will not be visible unless a [Camera2D] node is used, or unless the window is resized and the stretch mode is set to [code]disabled[/code].
|
||||
</member>
|
||||
<member name="editors/2d/warped_mouse_panning" type="bool" setter="" getter="">
|
||||
If [code]true[/code], wraps around the mouse cursor when it reaches one of the 2D editor viewport's edges. This makes panning over large areas easier, as you don't have to stop and reposition the mouse every time it's about to hit the screen's borders.
|
||||
</member>
|
||||
<member name="editors/3d/default_fov" type="float" setter="" getter="">
|
||||
The default camera field of view to use in the 3D editor (in degrees). The camera field of view can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera field of view adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
|
||||
</member>
|
||||
<member name="editors/3d/default_z_far" type="float" setter="" getter="">
|
||||
The default camera far clip distance to use in the 3D editor (in degrees). Higher values make it possible to view objects placed further away from the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera far clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera far clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
|
||||
</member>
|
||||
<member name="editors/3d/default_z_near" type="float" setter="" getter="">
|
||||
The default camera near clip distance to use in the 3D editor (in degrees). Lower values make it possible to view objects placed closer to the camera, at the cost of lower precision in the depth buffer (which can result in visible Z-fighting in the distance). The camera near clip distance can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera near clip distance adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a Camera3D node is being previewed in the editor.
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_activation_modifier" type="int" setter="" getter="">
|
||||
The modifier key to use to enable freelook in the 3D editor (on top of pressing the right mouse button).
|
||||
[b]Note:[/b] Regardless of this setting, the freelook toggle keyboard shortcut ([kbd]Shift + F[/kbd] by default) is always available.
|
||||
[b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_base_speed" type="float" setter="" getter="">
|
||||
The base 3D freelook speed in units per second. This can be adjusted by using the mouse wheel while in freelook mode, or by holding down the "fast" or "slow" modifier keys ([kbd]Shift[/kbd] and [kbd]Alt[/kbd] by default, respectively).
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_inertia" type="float" setter="" getter="">
|
||||
The inertia of the 3D freelook camera. Higher values make the camera start and stop slower, which looks smoother but adds latency.
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_navigation_scheme" type="int" setter="" getter="">
|
||||
The navigation scheme to use when freelook is enabled in the 3D editor. Some of the navigation schemes below may be more convenient when designing specific levels in the 3D editor.
|
||||
- [b]Default:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move relative to the camera, taking its pitch angle into account for the movement.
|
||||
- [b]Partially Axis-Locked:[/b] The "Freelook Forward" and "Freelook Backward" keys will move relative to the camera, taking its pitch angle into account for the movement. The "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement.
|
||||
- [b]Fully Axis-Locked:[/b] The "Freelook Forward", "Freelook Backward", "Freelook Up" and "Freelook Down" keys will move in an "absolute" manner, [i]not[/i] taking the camera's pitch angle into account for the movement.
|
||||
See also [member editors/3d/navigation/navigation_scheme].
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_sensitivity" type="float" setter="" getter="">
|
||||
The mouse sensitivity to use while freelook mode is active in the 3D editor. See also [member editors/3d/navigation_feel/orbit_sensitivity].
|
||||
</member>
|
||||
<member name="editors/3d/freelook/freelook_speed_zoom_link" type="bool" setter="" getter="">
|
||||
If [code]true[/code], freelook speed is linked to the zoom value used in the camera orbit mode in the 3D editor.
|
||||
</member>
|
||||
<member name="editors/3d/grid_division_level_bias" type="float" setter="" getter="">
|
||||
The grid division bias to use in the 3D editor. Negative values will cause small grid divisions to appear earlier, whereas positive values will cause small grid divisions to appear later.
|
||||
</member>
|
||||
<member name="editors/3d/grid_division_level_max" type="int" setter="" getter="">
|
||||
The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get larger than [code]1 ^ grid_division_level_max[/code] units. By default, this means grid divisions cannot get smaller than 100 units each, no matter how far away the camera is from the grid.
|
||||
</member>
|
||||
<member name="editors/3d/grid_division_level_min" type="int" setter="" getter="">
|
||||
The smallest grid division to use in the 3D editor, specified as a power of 2. The grid will not be able to get smaller than [code]1 ^ grid_division_level_min[/code] units. By default, this means grid divisions cannot get smaller than 1 unit each, no matter how close the camera is from the grid.
|
||||
</member>
|
||||
<member name="editors/3d/grid_size" type="int" setter="" getter="">
|
||||
The grid size in units. Higher values prevent the grid from appearing "cut off" at certain angles, but make the grid more demanding to render. Depending on the camera's position, the grid may not be fully visible since a shader is used to fade it progressively.
|
||||
</member>
|
||||
<member name="editors/3d/grid_xy_plane" type="bool" setter="" getter="">
|
||||
If [code]true[/code], render the grid on an XY plane. This can be useful for 3D side-scrolling games.
|
||||
</member>
|
||||
<member name="editors/3d/grid_xz_plane" type="bool" setter="" getter="">
|
||||
If [code]true[/code], render the grid on an XZ plane.
|
||||
</member>
|
||||
<member name="editors/3d/grid_yz_plane" type="bool" setter="" getter="">
|
||||
If [code]true[/code], render the grid on an YZ plane. This can be useful for 3D side-scrolling games.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/emulate_3_button_mouse" type="bool" setter="" getter="">
|
||||
If [code]true[/code], enables 3-button mouse emulation mode. This is useful on laptops when using a trackpad.
|
||||
When 3-button mouse emulation mode is enabled, the pan, zoom and orbit modifiers can always be used in the 3D editor viewport, even when not holding down any mouse button.
|
||||
[b]Note:[/b] No matter the orbit modifier configured in [member editors/3d/navigation/orbit_modifier], [kbd]Alt[/kbd] will always remain usable for orbiting in this mode to improve usability with graphics tablets.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/emulate_numpad" type="bool" setter="" getter="">
|
||||
If [code]true[/code], allows using the top row [kbd]0[/kbd]-[kbd]9[/kbd] keys to function as their equivalent numpad keys for 3D editor navigation. This should be enabled on keyboards that have no numeric keypad available.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/invert_x_axis" type="bool" setter="" getter="">
|
||||
If [code]true[/code], invert the horizontal mouse axis when panning or orbiting in the 3D editor. This setting does [i]not[/i] apply to freelook mode.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/invert_y_axis" type="bool" setter="" getter="">
|
||||
If [code]true[/code], invert the vertical mouse axis when panning, orbiting, or using freelook mode in the 3D editor.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/navigation_scheme" type="int" setter="" getter="">
|
||||
The navigation scheme to use in the 3D editor. Changing this setting will affect the mouse buttons that must be held down to perform certain operations in the 3D editor viewport.
|
||||
- [b]Godot[/b] Middle mouse button to orbit, [kbd]Shift + Middle mouse button[/kbd] to pan. [kbd]Mouse wheel[/kbd] to zoom.
|
||||
- [b]Maya:[/b] [kbd]Alt + Left mouse button[/kbd] to orbit. [kbd]Middle mouse button[/kbd] to pan, [kbd]Shift + Middle mouse button[/kbd] to pan 10 times faster. [kbd]Mouse wheel[/kbd] to zoom.
|
||||
- [b]Modo:[/b] [kbd]Alt + Left mouse button[/kbd] to orbit. [kbd]Alt + Shift + Left mouse button[/kbd] to pan. [kbd]Ctrl + Alt + Left mouse button[/kbd] to zoom.
|
||||
See also [member editors/3d/freelook/freelook_navigation_scheme].
|
||||
[b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/orbit_modifier" type="int" setter="" getter="">
|
||||
The modifier key that must be held to orbit in the 3D editor.
|
||||
[b]Note:[/b] If [member editors/3d/navigation/emulate_3_button_mouse] is [code]true[/code], [kbd]Alt[/kbd] will always remain usable for orbiting to improve usability with graphics tablets.
|
||||
[b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/pan_modifier" type="int" setter="" getter="">
|
||||
The modifier key that must be held to pan in the 3D editor.
|
||||
[b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/warped_mouse_panning" type="bool" setter="" getter="">
|
||||
If [code]true[/code], warps the mouse around the 3D viewport while panning in the 3D editor. This makes it possible to pan over a large area without having to exit panning then mouse the mouse back constantly.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/zoom_modifier" type="int" setter="" getter="">
|
||||
The modifier key that must be held to zoom in the 3D editor.
|
||||
[b]Note:[/b] On certain window managers on Linux, the [kbd]Alt[/kbd] key will be intercepted by the window manager when clicking a mouse button at the same time. This means Godot will not see the modifier key as being pressed.
|
||||
</member>
|
||||
<member name="editors/3d/navigation/zoom_style" type="int" setter="" getter="">
|
||||
The mouse cursor movement direction to use when zooming by moving the mouse. This does not affect zooming with the mouse wheel.
|
||||
</member>
|
||||
<member name="editors/3d/navigation_feel/orbit_inertia" type="float" setter="" getter="">
|
||||
The inertia to use when orbiting in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
|
||||
</member>
|
||||
<member name="editors/3d/navigation_feel/orbit_sensitivity" type="float" setter="" getter="">
|
||||
The mouse sensitivity to use when orbiting in the 3D editor. See also [member editors/3d/freelook/freelook_sensitivity].
|
||||
</member>
|
||||
<member name="editors/3d/navigation_feel/translation_inertia" type="float" setter="" getter="">
|
||||
The inertia to use when panning in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
|
||||
</member>
|
||||
<member name="editors/3d/navigation_feel/zoom_inertia" type="float" setter="" getter="">
|
||||
The inertia to use when zooming in the 3D editor. Higher values make the camera start and stop slower, which looks smoother but adds latency.
|
||||
</member>
|
||||
<member name="editors/3d/primary_grid_color" type="Color" setter="" getter="">
|
||||
The color to use for the primary 3D grid. The color's alpha channel affects the grid's opacity.
|
||||
</member>
|
||||
<member name="editors/3d/primary_grid_steps" type="int" setter="" getter="">
|
||||
If set above 0, where a primary grid line should be drawn. By default, primary lines are configured to be more visible than secondary lines. This helps with measurements in the 3D editor. See also [member editors/3d/primary_grid_color] and [member editors/3d/secondary_grid_color].
|
||||
</member>
|
||||
<member name="editors/3d/secondary_grid_color" type="Color" setter="" getter="">
|
||||
The color to use for the secondary 3D grid. This is generally a less visible color than [member editors/3d/primary_grid_color]. The color's alpha channel affects the grid's opacity.
|
||||
</member>
|
||||
<member name="editors/3d/selection_box_color" type="Color" setter="" getter="">
|
||||
The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity.
|
||||
</member>
|
||||
<member name="editors/animation/autorename_animation_tracks" type="bool" setter="" getter="">
|
||||
If [code]true[/code], automatically updates animation tracks' target paths when renaming or reparenting nodes in the Scene tree dock.
|
||||
</member>
|
||||
<member name="editors/animation/confirm_insert_track" type="bool" setter="" getter="">
|
||||
If [code]true[/code], display a confirmation dialog when adding a new track to an animation by pressing the "key" icon next to a property.
|
||||
</member>
|
||||
<member name="editors/animation/default_create_bezier_tracks" type="bool" setter="" getter="">
|
||||
If [code]true[/code], create a Bezier track instead of a standard track when pressing the "key" icon next to a property. Bezier tracks provide more control over animation curves, but are more difficult to adjust quickly.
|
||||
</member>
|
||||
<member name="editors/animation/default_create_reset_tracks" type="bool" setter="" getter="">
|
||||
If [code]true[/code], create a [code]RESET[/code] track when creating a new animation track. This track can be used to restore the animation to a "default" state.
|
||||
</member>
|
||||
<member name="editors/animation/onion_layers_future_color" type="Color" setter="" getter="">
|
||||
The modulate color to use for "future" frames displayed in the animation editor's onion skinning feature.
|
||||
</member>
|
||||
<member name="editors/animation/onion_layers_past_color" type="Color" setter="" getter="">
|
||||
The modulate color to use for "past" frames displayed in the animation editor's onion skinning feature.
|
||||
</member>
|
||||
<member name="editors/poly_editor/point_grab_radius" type="int" setter="" getter="">
|
||||
The radius of each point's clickable area in 2D and 3D polygon editors (in pixels). Increase this value if you are having trouble selecting points in polygon editors. However, increasing this value may make it more difficult to select points located close to each other.
|
||||
</member>
|
||||
<member name="editors/poly_editor/show_previous_outline" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays a gray outline matching the polygon's previous shape while dragging one of the points.
|
||||
</member>
|
||||
<member name="editors/visual_editors/minimap_opacity" type="float" setter="" getter="">
|
||||
The opacity of the minimap displayed in the bottom-right corner of the visual script and visual shader editors.
|
||||
</member>
|
||||
<member name="filesystem/directories/autoscan_project_path" type="String" setter="" getter="">
|
||||
The folder where projects should be scanned for (recursively), in a way similar to the project manager's [b]Scan[/b]button. This can be set to the same value as [member filesystem/directories/default_project_path] for convenience.
|
||||
[b]Note:[/b] Setting this path to a folder with very large amounts of files/folders can slow down the project manager startup significantly. To keep the project manager quick to start up, it is recommended to set this value to a folder as "specific" as possible.
|
||||
</member>
|
||||
<member name="filesystem/directories/default_project_path" type="String" setter="" getter="">
|
||||
The folder where new projects should be created by default when clicking the project manager's [b]New Project[/b] button. This can be set to the same value as [member filesystem/directories/autoscan_project_path] for convenience.
|
||||
</member>
|
||||
<member name="filesystem/file_dialog/display_mode" type="int" setter="" getter="">
|
||||
The display mode to use in the editor's file dialogs.
|
||||
- [b]Thumbnails[/b] takes more space, but displays dynamic resource thumbnails, making resources easier to preview without having to open them.
|
||||
- [b]List[/b] is more compact but doesn't display dynamic resource thumbnails. Instead, it displays static icons based on the file extension.
|
||||
</member>
|
||||
<member name="filesystem/file_dialog/show_hidden_files" type="bool" setter="" getter="">
|
||||
If [code]true[/code], display hidden files in the editor's file dialogs. Files that have names starting with [code].[/code] are considered hidden (e.g. [code].hidden_file[/code]).
|
||||
</member>
|
||||
<member name="filesystem/file_dialog/thumbnail_size" type="int" setter="" getter="">
|
||||
The thumbnail size to use in the editor's file dialogs (in pixels). See also [member docks/filesystem/thumbnail_size].
|
||||
</member>
|
||||
<member name="filesystem/on_save/compress_binary_resources" type="bool" setter="" getter="">
|
||||
If [code]true[/code], uses lossless compression for binary resources.
|
||||
</member>
|
||||
<member name="filesystem/on_save/safe_save_on_backup_then_rename" type="bool" setter="" getter="">
|
||||
If [code]true[/code], when saving a file, the editor will rename the old file to a different name, save a new file, then only remove the old file once the new file has been saved. This makes loss of data less likely to happen if the editor or operating system exits unexpectedly while saving (e.g. due to a crash or power outage).
|
||||
[b]Note:[/b] On Windows, this feature can interact negatively with certain antivirus programs. In this case, you may have to set this to [code]false[/code] to prevent file locking issues.
|
||||
</member>
|
||||
<member name="interface/editor/accept_dialog_cancel_ok_buttons" type="int" setter="" getter="">
|
||||
How to position the Cancel and OK buttons in the editor's [AcceptDialog]s. Different platforms have different standard behaviors for this, which can be overridden using this setting. This is useful if you use Godot both on Windows and macOS/Linux and your Godot muscle memory is stronger than your OS specific one.
|
||||
- [b]Auto[/b] follows the platform convention: Cancel first on macOS and Linux, OK first on Windows.
|
||||
- [b]Cancel First[/b] forces the ordering Cancel/OK.
|
||||
- [b]OK First[/b] forces the ordering OK/Cancel.
|
||||
</member>
|
||||
<member name="interface/editor/automatically_open_screenshots" type="bool" setter="" getter="">
|
||||
If [code]true[/code], automatically opens screenshots with the default program associated to [code].png[/code] files after a screenshot is taken using the [b]Editor > Take Screenshot[/b] action.
|
||||
</member>
|
||||
<member name="interface/editor/code_font" type="String" setter="" getter="">
|
||||
The font to use for the script editor. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
|
||||
</member>
|
||||
<member name="interface/editor/code_font_size" type="int" setter="" getter="">
|
||||
The size of the font in the script editor. This setting does not impact the font size of the Output panel (see [member run/output/font_size]).
|
||||
</member>
|
||||
<member name="interface/editor/custom_display_scale" type="float" setter="" getter="">
|
||||
The custom editor scale factor to use. This can be used for displays with very high DPI where a scale factor of 200% is not sufficient.
|
||||
[b]Note:[/b] Only effective if [member interface/editor/display_scale] is set to [b]Custom[/b].
|
||||
</member>
|
||||
<member name="interface/editor/dim_editor_on_dialog_popup" type="bool" setter="" getter="">
|
||||
If [code]true[/code], darkens the rest of the editor when a modal dialog is open. If you need to pick colors on the rest of the editor while in modal dialog, disable this option.
|
||||
</member>
|
||||
<member name="interface/editor/display_scale" type="int" setter="" getter="">
|
||||
The display scale factor to use for the editor interface. Higher values are more suited to hiDPI/Retina displays.
|
||||
If set to [b]Auto[/b], the editor scale is automatically determined based on the screen resolution and reported display DPI. This heuristic is not always ideal, which means you can get better results by setting the editor scale manually.
|
||||
If set to [b]Custom[/b], the scaling value in [member interface/editor/custom_display_scale] will be used.
|
||||
</member>
|
||||
<member name="interface/editor/editor_language" type="String" setter="" getter="">
|
||||
The language to use for the editor interface.
|
||||
Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url]
|
||||
</member>
|
||||
<member name="interface/editor/font_antialiased" type="bool" setter="" getter="">
|
||||
If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font.
|
||||
</member>
|
||||
<member name="interface/editor/font_hinting" type="int" setter="" getter="">
|
||||
The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes:
|
||||
- [b]None:[/b] Don't use font hinting when rasterizing the font. This results in a smooth font, but it can look blurry.
|
||||
- [b]Light:[/b] Use hinting on the X axis only. This is a compromise between font sharpness and smoothness.
|
||||
- [b]Normal:[/b] Use hinting on both X and Y axes. This results in a sharp font, but it doesn't look very smooth.
|
||||
If set to [b]Auto[/b], the font hinting mode will be set to match the current operating system in use. This means the [b]Light[/b] hinting mode will be used on Windows and Linux, and the [b]None[/b] hinting mode will be used on macOS.
|
||||
</member>
|
||||
<member name="interface/editor/hide_main_screen_plugin_names" type="bool" setter="" getter="">
|
||||
If [code]true[/code] the names of the main screen plugins will be hidden (when they have an icon).
|
||||
</member>
|
||||
<member name="interface/editor/low_processor_mode_sleep_usec" type="float" setter="" getter="">
|
||||
The amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops. However, higher values will result in a less responsive editor. The default value is set to allow for maximum smoothness on monitors up to 144 Hz. See also [member interface/editor/unfocused_low_processor_mode_sleep_usec].
|
||||
</member>
|
||||
<member name="interface/editor/main_font" type="String" setter="" getter="">
|
||||
The font to use for the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
|
||||
</member>
|
||||
<member name="interface/editor/main_font_bold" type="String" setter="" getter="">
|
||||
The font to use for bold text in the editor interface. Must be a resource of a [Font] type such as a [code].ttf[/code] or [code].otf[/code] font file.
|
||||
</member>
|
||||
<member name="interface/editor/main_font_size" type="int" setter="" getter="">
|
||||
The size of the font in the editor interface.
|
||||
</member>
|
||||
<member name="interface/editor/quit_confirmation" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays a confirmation dialog when exiting the editor when there are no unsaved changes.
|
||||
[b]Note:[/b] Regardless of this setting, the editor will [i]always[/i] display a quit confirmation dialog when there are unsaved changes.
|
||||
</member>
|
||||
<member name="interface/editor/save_each_scene_on_quit" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the editor will save all scenes when confirming the [b]Save[/b] action when quitting the editor or quitting to the project list. If [code]false[/code], the editor will ask to save each scene individually.
|
||||
</member>
|
||||
<member name="interface/editor/separate_distraction_mode" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the editor's Script tab will have a separate distraction mode setting from the 2D/3D/AssetLib tabs. If [code]false[/code], the distraction-free mode toggle is shared between all tabs.
|
||||
</member>
|
||||
<member name="interface/editor/unfocused_low_processor_mode_sleep_usec" type="float" setter="" getter="">
|
||||
When the editor window is unfocused, the amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops (in addition to improving the running project's performance if the editor has to redraw continuously). However, higher values will result in a less responsive editor. The default value is set to limit the editor to 20 FPS when the editor window is unfocused. See also [member interface/editor/low_processor_mode_sleep_usec].
|
||||
</member>
|
||||
<member name="interface/inspector/max_array_dictionary_items_per_page" type="int" setter="" getter="">
|
||||
The number of [Array] or [Dictionary] items to display on each "page" in the inspector. Higher values allow viewing more values per page, but take more time to load. This increased load time is noticeable when selecting nodes that have array or dictionary properties in the editor.
|
||||
</member>
|
||||
<member name="interface/scene_tabs/minimum_width" type="int" setter="" getter="">
|
||||
The minimum width to use for each scene tab (in pixels). Only effective if [member interface/scene_tabs/resize_if_many_tabs] is [code]true[/code].
|
||||
</member>
|
||||
<member name="interface/scene_tabs/resize_if_many_tabs" type="bool" setter="" getter="">
|
||||
If [code]true[/code], sets the scene tabs' minimum width to [member interface/scene_tabs/minimum_width].
|
||||
</member>
|
||||
<member name="interface/scene_tabs/show_script_button" type="bool" setter="" getter="">
|
||||
If [code]true[/code], show a button next to each scene tab that opens the scene's "dominant" script when clicked. The "dominant" script is the one that is at the highest level in the scene's hierarchy.
|
||||
</member>
|
||||
<member name="interface/scene_tabs/show_thumbnail_on_hover" type="bool" setter="" getter="">
|
||||
If [code]true[/code], display an automatically-generated thumbnail when hovering scene tabs with the mouse. Scene thumbnails are generated when saving the scene.
|
||||
</member>
|
||||
<member name="interface/theme/accent_color" type="Color" setter="" getter="">
|
||||
The color to use for "highlighted" user interface elements in the editor (pressed and hovered items).
|
||||
</member>
|
||||
<member name="interface/theme/additional_spacing" type="float" setter="" getter="">
|
||||
The spacing to add for buttons and list items in the editor (in pixels). Increasing this value is useful to improve usability on touch screens, at the cost of reducing the amount of usable screen real estate.
|
||||
</member>
|
||||
<member name="interface/theme/base_color" type="Color" setter="" getter="">
|
||||
The base color to use for user interface elements in the editor. Secondary colors (such as darker/lighter variants) are derived from this color.
|
||||
</member>
|
||||
<member name="interface/theme/border_size" type="int" setter="" getter="">
|
||||
The border size to use for interface elements (in pixels).
|
||||
</member>
|
||||
<member name="interface/theme/contrast" type="float" setter="" getter="">
|
||||
The contrast factor to use when deriving the editor theme's base color (see [member interface/theme/base_color]). When using a positive values, the derived colors will be [i]darker[/i] than the base color. This contrast factor can be set to a negative value, which will make the derived colors [i]brighter[/i] than the base color. Negative contrast rates often look better for light themes.
|
||||
</member>
|
||||
<member name="interface/theme/custom_theme" type="String" setter="" getter="">
|
||||
The custom theme resource to use for the editor. Must be a Godot theme resource in [code].tres[/code] or [code].res[/code] format.
|
||||
</member>
|
||||
<member name="interface/theme/highlight_tabs" type="bool" setter="" getter="">
|
||||
If [code]true[/code], makes the background of selected tabs more contrasted in the editor theme (brighter on dark themes, darker on light themes).
|
||||
</member>
|
||||
<member name="interface/theme/icon_and_font_color" type="int" setter="" getter="">
|
||||
The icon and font color scheme to use in the editor.
|
||||
- [b]Auto[/b] determines the color scheme to use automatically based on [member interface/theme/base_color].
|
||||
- [b]Dark[/b] makes fonts and icons light (suitable for dark themes).
|
||||
- [b]Light[/b] makes fonts and icons dark (suitable for light themes). Icon colors are automatically converted by the editor following [url=https://github.com/godotengine/godot/blob/master/editor/editor_themes.cpp#L135]this set of rules[/url].
|
||||
</member>
|
||||
<member name="interface/theme/preset" type="String" setter="" getter="">
|
||||
The editor theme preset to use.
|
||||
</member>
|
||||
<member name="interface/theme/relationship_line_opacity" type="float" setter="" getter="">
|
||||
The opacity to use when drawing relationship lines in the editor's [Tree]-based GUIs (such as the Scene tree dock).
|
||||
</member>
|
||||
<member name="interface/theme/use_graph_node_headers" type="bool" setter="" getter="">
|
||||
If [code]true[/code], use colored header backgrounds for individual [GraphNode]s in the visual script and visual shader editors. This can improve usability when frequently using these editors at low zoom levels.
|
||||
</member>
|
||||
<member name="interface/touchscreen/enable_long_press_as_right_click" type="bool" setter="" getter="">
|
||||
If [code]true[/code], long press on touchscreen is treated as right click.
|
||||
[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
|
||||
</member>
|
||||
<member name="interface/touchscreen/enable_pan_and_scale_gestures" type="bool" setter="" getter="">
|
||||
If [code]true[/code], enable two finger pan and scale gestures on touchscreen devices.
|
||||
[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
|
||||
</member>
|
||||
<member name="interface/touchscreen/increase_scrollbar_touch_area" type="bool" setter="" getter="">
|
||||
If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
|
||||
[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
|
||||
</member>
|
||||
<member name="interface/touchscreen/scale_gizmo_handles" type="float" setter="" getter="">
|
||||
Specify the multiplier to apply to the scale for the editor gizmo handles to improve usability on touchscreen devices.
|
||||
[b]Note:[/b] Defaults to [code]1[/code] on non-touchscreen devices.
|
||||
</member>
|
||||
<member name="network/debug/remote_host" type="String" setter="" getter="">
|
||||
The address to listen to when starting the remote debugger. This can be set to [code]0.0.0.0[/code] to allow external clients to connect to the remote debugger (instead of restricting the remote debugger to connections from [code]localhost[/code]).
|
||||
</member>
|
||||
<member name="network/debug/remote_port" type="int" setter="" getter="">
|
||||
The port to listen to when starting the remote debugger. Godot will try to use port numbers above the configured number if the configured number is already taken by another application.
|
||||
</member>
|
||||
<member name="network/ssl/editor_ssl_certificates" type="String" setter="" getter="">
|
||||
The SSL certificate bundle to use for HTTP requests made within the editor (e.g. from the AssetLib tab). If left empty, the [url=https://github.com/godotengine/godot/blob/master/thirdparty/certs/ca-certificates.crt]included Mozilla certificate bundle[/url] will be used.
|
||||
</member>
|
||||
<member name="project_manager/sorting_order" type="int" setter="" getter="">
|
||||
The sorting order to use in the project manager. When changing the sorting order in the project manager, this setting is set permanently in the editor settings.
|
||||
</member>
|
||||
<member name="run/auto_save/save_before_running" type="bool" setter="" getter="">
|
||||
If [code]true[/code], saves all scenes and scripts automatically before running the project. Setting this to [code]false[/code] prevents the editor from saving if there are no changes which can speed up the project startup slightly, but it makes it possible to run a project that has unsaved changes. (Unsaved changes will not be visible in the running project.)
|
||||
</member>
|
||||
<member name="run/output/always_clear_output_on_play" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the editor will clear the Output panel when running the project.
|
||||
</member>
|
||||
<member name="run/output/always_close_output_on_stop" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the editor will collapse the Output panel when stopping the project.
|
||||
</member>
|
||||
<member name="run/output/always_open_output_on_play" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the editor will expand the Output panel when running the project.
|
||||
</member>
|
||||
<member name="run/output/font_size" type="int" setter="" getter="">
|
||||
The size of the font in the [b]Output[/b] panel at the bottom of the editor. This setting does not impact the font size of the script editor (see [member interface/editor/code_font_size]).
|
||||
</member>
|
||||
<member name="run/window_placement/rect" type="int" setter="" getter="">
|
||||
The window mode to use to display the project when starting the project from the editor.
|
||||
</member>
|
||||
<member name="run/window_placement/rect_custom_position" type="Vector2" setter="" getter="">
|
||||
The custom position to use when starting the project from the editor (in pixels from the top-left corner). Only effective if [member run/window_placement/rect] is set to [b]Custom Position[/b].
|
||||
</member>
|
||||
<member name="run/window_placement/screen" type="int" setter="" getter="">
|
||||
The monitor to display the project on when starting the project from the editor.
|
||||
</member>
|
||||
<member name="text_editor/appearance/code_folding" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays the folding arrows next to indented code sections and allows code folding. If [code]false[/code], hides the folding arrows next to indented code sections and disallows code folding.
|
||||
</member>
|
||||
<member name="text_editor/appearance/line_length_guideline_hard_column" type="int" setter="" getter="">
|
||||
The column at which to display a subtle line as a line length guideline for scripts. This should generally be greater than [member text_editor/appearance/line_length_guideline_soft_column].
|
||||
</member>
|
||||
<member name="text_editor/appearance/line_length_guideline_soft_column" type="int" setter="" getter="">
|
||||
The column at which to display a [i]very[/i] subtle line as a line length guideline for scripts. This should generally be lower than [member text_editor/appearance/line_length_guideline_hard_column].
|
||||
</member>
|
||||
<member name="text_editor/appearance/line_numbers_zero_padded" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays line numbers with zero padding (e.g. [code]007[/code] instead of [code]7[/code]).
|
||||
</member>
|
||||
<member name="text_editor/appearance/show_bookmark_gutter" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays a gutter at the left containing icons for bookmarks.
|
||||
</member>
|
||||
<member name="text_editor/appearance/show_breakpoint_gutter" type="bool" setter="" getter="">
|
||||
If [code]true[/code], shows breakpoint gutter and its icons. If [code]false[/code], breakpoints will still be active but it won't be possible to add or remove breakpoints.
|
||||
</member>
|
||||
<member name="text_editor/appearance/show_info_gutter" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays a gutter at the left containing icons for methods with signal connections.
|
||||
</member>
|
||||
<member name="text_editor/appearance/show_line_length_guidelines" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays line length guidelines to help you keep line lengths in check. See also [member text_editor/appearance/line_length_guideline_soft_column] and [member text_editor/appearance/line_length_guideline_soft_column].
|
||||
</member>
|
||||
<member name="text_editor/appearance/show_line_numbers" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays line numbers in the gutter at the left.
|
||||
</member>
|
||||
<member name="text_editor/appearance/word_wrap" type="bool" setter="" getter="">
|
||||
If [code]true[/code], wraps long lines over multiple lines to avoid horizontal scrolling. This is a display-only feature; it does not actually insert line breaks in your scripts.
|
||||
</member>
|
||||
<member name="text_editor/completion/add_type_hints" type="bool" setter="" getter="">
|
||||
If [code]true[/code], adds static typing hints such as [code]-> void[/code] and [code]: int[/code] when performing method definition autocompletion.
|
||||
</member>
|
||||
<member name="text_editor/completion/auto_brace_complete" type="bool" setter="" getter="">
|
||||
If [code]true[/code], automatically completes braces when making use of code completion.
|
||||
</member>
|
||||
<member name="text_editor/completion/callhint_tooltip_offset" type="Vector2" setter="" getter="">
|
||||
The offset to use when displaying [i]callhints[/i] (non-interactive tooltips that appear during function autocompletion) in the script editor (in pixels). Not to be confused with the code completion dialog, which is interactive.
|
||||
</member>
|
||||
<member name="text_editor/completion/code_complete_delay" type="float" setter="" getter="">
|
||||
The delay in seconds after which autocompletion suggestions should be displayed when the user stops typing.
|
||||
</member>
|
||||
<member name="text_editor/completion/complete_file_paths" type="bool" setter="" getter="">
|
||||
If [code]true[/code], provides autocompletion suggestions for file paths in methods such as [code]load()[/code] and [code]preload()[/code].
|
||||
</member>
|
||||
<member name="text_editor/completion/idle_parse_delay" type="float" setter="" getter="">
|
||||
The delay in seconds after which the script editor should check for errors when the user stops typing.
|
||||
</member>
|
||||
<member name="text_editor/completion/put_callhint_tooltip_below_current_line" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the code completion tooltip will appear below the current line unless there is no space on screen below the current line. If [code]false[/code], the code completion tooltip will appear above the current line.
|
||||
</member>
|
||||
<member name="text_editor/completion/use_single_quotes" type="bool" setter="" getter="">
|
||||
If [code]true[/code], performs string autocompletion with single quotes. If [code]false[/code], performs string autocompletion with double quotes (which matches the [url=https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url]).
|
||||
</member>
|
||||
<member name="text_editor/cursor/block_caret" type="bool" setter="" getter="">
|
||||
If [code]true[/code], use a block-shaped caret instead of a line-shaped caret in the script editor.
|
||||
</member>
|
||||
<member name="text_editor/cursor/caret_blink" type="bool" setter="" getter="">
|
||||
If [code]true[/code], makes the caret blink according to [member text_editor/cursor/caret_blink_speed]. Disabling this setting can improve battery life on laptops if you spend long amounts of time in the script editor, since it will reduce the frequency at which the editor needs to be redrawn.
|
||||
</member>
|
||||
<member name="text_editor/cursor/caret_blink_speed" type="float" setter="" getter="">
|
||||
The interval at which to blink the caret (in seconds). See also [member text_editor/cursor/caret_blink].
|
||||
</member>
|
||||
<member name="text_editor/cursor/right_click_moves_caret" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the caret will be moved when right-clicking somewhere in the script editor (like when left-clicking or middle-clicking). If [code]false[/code], the caret will only be moved when left-clicking or middle-clicking somewhere.
|
||||
</member>
|
||||
<member name="text_editor/cursor/scroll_past_end_of_file" type="bool" setter="" getter="">
|
||||
If [code]true[/code], allows scrolling past the end of the file in the script editor.
|
||||
</member>
|
||||
<member name="text_editor/files/autosave_interval_secs" type="int" setter="" getter="">
|
||||
If set to a value greater than [code]0[/code], automatically saves the current script following the specified interval (in seconds). This can be used to prevent data loss if the editor crashes.
|
||||
</member>
|
||||
<member name="text_editor/files/restore_scripts_on_load" type="bool" setter="" getter="">
|
||||
If [code]true[/code], reopens scripts that were opened in the last session when the editor is reopened on a given project.
|
||||
</member>
|
||||
<member name="text_editor/files/trim_trailing_whitespace_on_save" type="bool" setter="" getter="">
|
||||
If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy.
|
||||
</member>
|
||||
<member name="text_editor/help/help_font_size" type="int" setter="" getter="">
|
||||
The font size to use for the editor help (built-in class reference).
|
||||
</member>
|
||||
<member name="text_editor/help/help_source_font_size" type="int" setter="" getter="">
|
||||
The font size to use for code samples in the editor help (built-in class reference).
|
||||
</member>
|
||||
<member name="text_editor/help/help_title_font_size" type="int" setter="" getter="">
|
||||
The font size to use for headings in the editor help (built-in class reference).
|
||||
</member>
|
||||
<member name="text_editor/help/show_help_index" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays a table of contents at the left of the editor help (at the location where the members overview would appear when editing a script).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/background_color" type="Color" setter="" getter="">
|
||||
The script editor's background color. If set to a translucent color, the editor theme's base color will be visible behind.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/base_type_color" type="Color" setter="" getter="">
|
||||
The script editor's base type color (used for types like [Vector2], [Vector3], ...).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/bookmark_color" type="Color" setter="" getter="">
|
||||
The script editor's bookmark icon color (displayed in the gutter).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/brace_mismatch_color" type="Color" setter="" getter="">
|
||||
The script editor's brace mismatch color. Used when the caret is currently on a mismatched brace, parenthesis or bracket character.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/breakpoint_color" type="Color" setter="" getter="">
|
||||
The script editor's breakpoint icon color (displayed in the gutter).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/caret_background_color" type="Color" setter="" getter="">
|
||||
The script editor's caret background color.
|
||||
[b]Note:[/b] This setting has no effect as it's currently unused.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/caret_color" type="Color" setter="" getter="">
|
||||
The script editor's caret color.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/code_folding_color" type="Color" setter="" getter="">
|
||||
The script editor's color for the code folding icon (displayed in the gutter).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/comment_color" type="Color" setter="" getter="">
|
||||
The script editor's comment color.
|
||||
[b]Note:[/b] In GDScript, unlike Python, multiline strings are not considered to be comments, and will use the string highlighting color instead.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/completion_background_color" type="Color" setter="" getter="">
|
||||
The script editor's autocompletion box background color.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/completion_existing_color" type="Color" setter="" getter="">
|
||||
The script editor's autocompletion box background color to highlight existing characters in the completion results. This should be a translucent color so that [member text_editor/highlighting/completion_selected_color] can be seen behind.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/completion_font_color" type="Color" setter="" getter="">
|
||||
The script editor's autocompletion box text color.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/completion_scroll_color" type="Color" setter="" getter="">
|
||||
The script editor's autocompletion box scroll bar color.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/completion_selected_color" type="Color" setter="" getter="">
|
||||
The script editor's autocompletion box background color for the currently selected line.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/control_flow_keyword_color" type="Color" setter="" getter="">
|
||||
The script editor's control flow keyword color (used for keywords like [code]if[/code], [code]for[/code], [code]return[/code], ...).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/current_line_color" type="Color" setter="" getter="">
|
||||
The script editor's background color for the line the caret is currently on. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/highlighting/mark_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/engine_type_color" type="Color" setter="" getter="">
|
||||
The script editor's engine type color ([Vector2], [Vector3], [Color], ...).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/executing_line_color" type="Color" setter="" getter="">
|
||||
The script editor's color for the debugger's executing line icon (displayed in the gutter).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/function_color" type="Color" setter="" getter="">
|
||||
The script editor's function call color.
|
||||
[b]Note:[/b] When using the GDScript syntax highlighter, this is replaced by the function definition color configured in the syntax theme for function definitions (e.g. [code]func _ready():[/code]).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/highlight_all_occurrences" type="bool" setter="" getter="">
|
||||
If [code]true[/code], highlights all occurrences of the currently selected text in the script editor. See also [member text_editor/highlighting/word_highlighted_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/highlight_current_line" type="bool" setter="" getter="">
|
||||
If [code]true[/code], colors the background of the line the caret is currently on with [member text_editor/highlighting/current_line_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/highlight_type_safe_lines" type="bool" setter="" getter="">
|
||||
If [code]true[/code], highlights type-safe lines by displaying their line number color with [member text_editor/highlighting/safe_line_number_color] instead of [member text_editor/highlighting/line_number_color]. Type-safe lines are lines of code where the type of all variables is known at compile-time. These type-safe lines will run faster in Godot 4.0 and later thanks to typed instructions.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/keyword_color" type="Color" setter="" getter="">
|
||||
The script editor's non-control flow keyword color (used for keywords like [code]var[/code], [code]func[/code], some built-in methods, ...).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/line_length_guideline_color" type="Color" setter="" getter="">
|
||||
The script editor's color for the line length guideline. The "hard" line length guideline will be drawn with this color, whereas the "soft" line length guideline will be drawn with an opacity twice as low.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/line_number_color" type="Color" setter="" getter="">
|
||||
The script editor's color for line numbers. See also [member text_editor/highlighting/safe_line_number_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/mark_color" type="Color" setter="" getter="">
|
||||
The script editor's background color for lines with errors. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/highlighting/current_line_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/member_variable_color" type="Color" setter="" getter="">
|
||||
The script editor's color for member variables on objects (e.g. [code]self.some_property[/code]).
|
||||
[b]Note:[/b] This color is not used for local variable declaration and access.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/number_color" type="Color" setter="" getter="">
|
||||
The script editor's color for numbers (integer and floating-point).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/safe_line_number_color" type="Color" setter="" getter="">
|
||||
The script editor's color for type-safe line numbers. See also [member text_editor/highlighting/line_number_color].
|
||||
[b]Note:[/b] Only displayed if [member text_editor/highlighting/highlight_type_safe_lines] is [code]true[/code].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/search_result_border_color" type="Color" setter="" getter="">
|
||||
The script editor's color for the border of search results. This border helps bring further attention to the search result. Set this color's opacity to 0 to disable the border.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/search_result_color" type="Color" setter="" getter="">
|
||||
The script editor's background color for search results.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/selection_color" type="Color" setter="" getter="">
|
||||
The script editor's background color for the currently selected text.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/string_color" type="Color" setter="" getter="">
|
||||
The script editor's color for strings (single-line and multi-line).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/symbol_color" type="Color" setter="" getter="">
|
||||
The script editor's color for operators ([code]( ) [ ] { } + - * /[/code], ...).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/text_color" type="Color" setter="" getter="">
|
||||
The script editor's color for text not highlighted by any syntax highlighting rule.
|
||||
</member>
|
||||
<member name="text_editor/highlighting/text_selected_color" type="Color" setter="" getter="">
|
||||
The script editor's background color for text. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/highlighting/current_line_color].
|
||||
</member>
|
||||
<member name="text_editor/highlighting/user_type_color" type="Color" setter="" getter="">
|
||||
The script editor's color for user-defined types (using [code]class_name[/code]).
|
||||
</member>
|
||||
<member name="text_editor/highlighting/word_highlighted_color" type="Color" setter="" getter="">
|
||||
The script editor's color for words highlighted by selecting them. Only visible if [member text_editor/highlighting/highlight_all_occurrences] is [code]true[/code].
|
||||
</member>
|
||||
<member name="text_editor/indent/auto_indent" type="bool" setter="" getter="">
|
||||
If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line.
|
||||
</member>
|
||||
<member name="text_editor/indent/convert_indent_on_save" type="bool" setter="" getter="">
|
||||
If [code]true[/code], converts indentation to match the script editor's indentation settings when saving a script. See also [member text_editor/indent/type].
|
||||
</member>
|
||||
<member name="text_editor/indent/draw_spaces" type="bool" setter="" getter="">
|
||||
If [code]true[/code], draws space characters as centered points.
|
||||
</member>
|
||||
<member name="text_editor/indent/draw_tabs" type="bool" setter="" getter="">
|
||||
If [code]true[/code], draws tab characters as chevrons.
|
||||
</member>
|
||||
<member name="text_editor/indent/size" type="int" setter="" getter="">
|
||||
When using tab indentation, determines the length of each tab. When using space indentation, determines how many spaces are inserted when pressing [kbd]Tab[/kbd] and when automatic indentation is performed.
|
||||
</member>
|
||||
<member name="text_editor/indent/type" type="int" setter="" getter="">
|
||||
The indentation style to use (tabs or spaces).
|
||||
[b]Note:[/b] The [url=$DOCS_URL/getting_started/scripting/gdscript/gdscript_styleguide.html]GDScript style guide[/url] recommends using tabs for indentation. It is advised to change this setting only if you need to work on a project that currently uses spaces for indentation.
|
||||
</member>
|
||||
<member name="text_editor/navigation/drag_and_drop_selection" type="bool" setter="" getter="">
|
||||
If [code]true[/code], allows drag-and-dropping text in the script editor to move text. Disable this if you find yourself accidentally drag-and-dropping text in the script editor.
|
||||
</member>
|
||||
<member name="text_editor/navigation/minimap_width" type="int" setter="" getter="">
|
||||
The width of the minimap in the script editor (in pixels).
|
||||
</member>
|
||||
<member name="text_editor/navigation/mouse_extra_buttons_navigate_history" type="bool" setter="" getter="">
|
||||
If [code]true[/code], the mouse's additional side buttons will be usable to navigate in the script editor's file history. Set this to [code]false[/code] if you're using the side buttons for other purposes (such as a push-to-talk button in a VoIP program).
|
||||
</member>
|
||||
<member name="text_editor/navigation/show_minimap" type="bool" setter="" getter="">
|
||||
If [code]true[/code], draws an overview of the script near the scroll bar. The minimap can be left-clicked to scroll directly to a location in an "absolute" manner.
|
||||
</member>
|
||||
<member name="text_editor/navigation/smooth_scrolling" type="bool" setter="" getter="">
|
||||
If [code]true[/code], allows scrolling in sub-line intervals and enables a smooth scrolling animation when using the mouse wheel to scroll.
|
||||
[b]Note:[/b] [member text_editor/navigation/smooth_scrolling] currently behaves poorly in projects where [member ProjectSettings.physics/common/physics_fps] has been increased significantly from its default value ([code]60[/code]). In this case, it is recommended to disable this setting.
|
||||
</member>
|
||||
<member name="text_editor/navigation/stay_in_script_editor_on_node_selected" type="bool" setter="" getter="">
|
||||
If [code]true[/code], prevents automatically switching between the Script and 2D/3D screens when selecting a node in the Scene tree dock.
|
||||
</member>
|
||||
<member name="text_editor/navigation/v_scroll_speed" type="int" setter="" getter="">
|
||||
The number of pixels to scroll with every mouse wheel increment. Higher values make the script scroll by faster when using the mouse wheel.
|
||||
[b]Note:[/b] You can hold down [kbd]Alt[/kbd] while using the mouse wheel to temporarily scroll 5 times faster.
|
||||
</member>
|
||||
<member name="text_editor/script_list/show_members_overview" type="bool" setter="" getter="">
|
||||
If [code]true[/code], displays an overview of the current script's member variables and functions at the left of the script editor. See also [member text_editor/tools/sort_members_outline_alphabetically].
|
||||
</member>
|
||||
<member name="text_editor/theme/color_theme" type="String" setter="" getter="">
|
||||
The syntax theme to use in the script editor.
|
||||
You can save your own syntax theme from your current settings by using [b]File > Theme > Save As...[/b] at the top of the script editor. The syntax theme will then be available locally in the list of color themes.
|
||||
You can find additional syntax themes to install in the [url=https://github.com/godotengine/godot-syntax-themes]godot-syntax-themes[/url] repository.
|
||||
</member>
|
||||
<member name="text_editor/theme/line_spacing" type="int" setter="" getter="">
|
||||
The space to add between lines (in pixels). Greater line spacing can help improve readability at the cost of displaying fewer lines on screen.
|
||||
</member>
|
||||
<member name="text_editor/tools/sort_members_outline_alphabetically" type="bool" setter="" getter="">
|
||||
If [code]true[/code], sorts the members outline (located at the left of the script editor) using alphabetical order. If [code]false[/code], sorts the members outline depending on the order in which members are found in the script.
|
||||
[b]Note:[/b] Only effective if [member text_editor/script_list/show_members_overview] is [code]true[/code].
|
||||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="settings_changed">
|
||||
<description>
|
||||
Emitted after any editor setting has changed.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="NOTIFICATION_EDITOR_SETTINGS_CHANGED" value="10000">
|
||||
Emitted after any editor setting has changed. It's used by various editor plugins to update their visuals on theme changes or logic on configuration changes.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -1,213 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSpatialGizmo" inherits="SpatialGizmo" version="4.2">
|
||||
<brief_description>
|
||||
Gizmo for editing Spatial objects.
|
||||
</brief_description>
|
||||
<description>
|
||||
Gizmo that is used for providing custom visualization and editing (handles and subgizmos) for Spatial objects. Can be overridden to create custom gizmos, but for simple gizmos creating a [EditorSpatialGizmoPlugin] is usually recommended.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_collision_segments">
|
||||
<return type="void" />
|
||||
<argument index="0" name="segments" type="PoolVector3Array" />
|
||||
<description>
|
||||
Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this method during [method redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_collision_triangles">
|
||||
<return type="void" />
|
||||
<argument index="0" name="triangles" type="TriangleMesh" />
|
||||
<description>
|
||||
Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this method during [method redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_handles">
|
||||
<return type="void" />
|
||||
<argument index="0" name="handles" type="PoolVector3Array" />
|
||||
<argument index="1" name="material" type="Material" />
|
||||
<argument index="2" name="ids" type="PoolIntArray" />
|
||||
<argument index="3" name="billboard" type="bool" default="false" />
|
||||
<argument index="4" name="secondary" type="bool" default="false" />
|
||||
<description>
|
||||
Adds a list of handles (points) which can be used to edit the properties of the gizmo's Spatial. The [code]ids[/code] argument can be used to specify a custom identifier for each handle, if an empty [code]Array[/code] is passed, the ids will be assigned automatically from the [code]handles[/code] argument order.
|
||||
The [code]secondary[/code] argument marks the added handles as secondary, meaning they will normally have less selection priority than regular handles. When the user is holding the shift key secondary handles will switch to have higher priority than regular handles. This change in priority can be used to place multiple handles at the same point while still giving the user control on their selection.
|
||||
There are virtual methods which will be called upon editing of these handles. Call this method during [method _redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_lines">
|
||||
<return type="void" />
|
||||
<argument index="0" name="lines" type="PoolVector3Array" />
|
||||
<argument index="1" name="material" type="Material" />
|
||||
<argument index="2" name="billboard" type="bool" default="false" />
|
||||
<argument index="3" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )" />
|
||||
<description>
|
||||
Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this method during [method redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_mesh">
|
||||
<return type="void" />
|
||||
<argument index="0" name="mesh" type="Mesh" />
|
||||
<argument index="1" name="material" type="Material" default="null" />
|
||||
<argument index="2" name="transform" type="Transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )" />
|
||||
<argument index="3" name="skeleton" type="SkinReference" default="null" />
|
||||
<description>
|
||||
Adds a mesh to the gizmo with the specified [code]material[/code], local [code]transform[/code] and [code]skeleton[/code]. Call this method during [method _redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_unscaled_billboard">
|
||||
<return type="void" />
|
||||
<argument index="0" name="material" type="Material" />
|
||||
<argument index="1" name="default_scale" type="float" default="1" />
|
||||
<argument index="2" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )" />
|
||||
<description>
|
||||
Adds an unscaled billboard for visualization and selection. Call this method during [method _redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Removes everything in the gizmo including meshes, collisions and handles.
|
||||
</description>
|
||||
</method>
|
||||
<method name="commit_handle" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="secondary" type="bool" />
|
||||
<argument index="2" name="restore" type="Variant" />
|
||||
<argument index="3" name="cancel" type="bool" default="false" />
|
||||
<description>
|
||||
Override this method to commit a handle being edited (handles must have been previously added by [method add_handles]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo".
|
||||
If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the committed handle is secondary (see [method add_handles] for more information).
|
||||
</description>
|
||||
</method>
|
||||
<method name="commit_subgizmos" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="ids" type="PoolIntArray" />
|
||||
<argument index="1" name="restore" type="Array" />
|
||||
<argument index="2" name="cancel" type="bool" default="false" />
|
||||
<description>
|
||||
Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo".
|
||||
If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return the name of an edited handle (handles must have been previously added by [method add_handles]). Handles can be named for reference to the user when editing.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method add_handles] for more information).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_value" qualifiers="virtual">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle].
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method add_handles] for more information).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_plugin" qualifiers="const">
|
||||
<return type="EditorSpatialGizmoPlugin" />
|
||||
<description>
|
||||
Returns the [EditorSpatialGizmoPlugin] that owns this gizmo. It's useful to retrieve materials using [method EditorSpatialGizmoPlugin.get_material].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_spatial_node" qualifiers="const">
|
||||
<return type="Spatial" />
|
||||
<description>
|
||||
Returns the Spatial node associated with this gizmo.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_subgizmo_selection" qualifiers="const">
|
||||
<return type="PoolIntArray" />
|
||||
<description>
|
||||
Returns a list of the currently selected subgizmos. Can be used to highlight selected elements during [method _redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_subgizmo_transform" qualifiers="virtual">
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<description>
|
||||
Override this method to return the current transform of a subgizmo. This transform will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_subgizmos].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_handle_highlighted" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return [code]true[/code] whenever the given handle should be highlighted in the editor.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method add_handles] for more information).
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_subgizmo_selected" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="arg0" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the given subgizmo is currently selected. Can be used to highlight selected elements during [method _redraw].
|
||||
</description>
|
||||
</method>
|
||||
<method name="redraw" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method clear] at the beginning of this method and then add visual elements depending on the node's properties.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_handle" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="secondary" type="bool" />
|
||||
<argument index="2" name="camera" type="Camera" />
|
||||
<argument index="3" name="point" type="Vector2" />
|
||||
<description>
|
||||
Override this method to update the node properties when the user drags a gizmo handle (previously added with [method add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the edited handle is secondary (see [method add_handles] for more information).
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_hidden">
|
||||
<return type="void" />
|
||||
<argument index="0" name="hidden" type="bool" />
|
||||
<description>
|
||||
Sets the gizmo's hidden state. If [code]true[/code], the gizmo will be hidden. If [code]false[/code], it will be shown.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_spatial_node">
|
||||
<return type="void" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<description>
|
||||
Sets the reference [Spatial] node for the gizmo. [code]node[/code] must inherit from [Spatial].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_subgizmo_transform" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="id" type="int" />
|
||||
<argument index="1" name="transform" type="Transform" />
|
||||
<description>
|
||||
Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [code]transform[/code] is given in the Spatial's local coordinate system.
|
||||
</description>
|
||||
</method>
|
||||
<method name="subgizmos_intersect_frustum" qualifiers="virtual">
|
||||
<return type="PoolIntArray" />
|
||||
<argument index="0" name="camera" type="Camera" />
|
||||
<argument index="1" name="frustum" type="Array" />
|
||||
<description>
|
||||
Override this method to allow selecting subgizmos using mouse drag box selection. Given a [code]camera[/code] and a [code]frustum[/code], this method should return which subgizmos are contained within the frustum. The [code]frustum[/code] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos].
|
||||
</description>
|
||||
</method>
|
||||
<method name="subgizmos_intersect_ray" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<argument index="0" name="camera" type="Camera" />
|
||||
<argument index="1" name="point" type="Vector2" />
|
||||
<description>
|
||||
Override this method to allow selecting subgizmos using mouse clicks. Given a [code]camera[/code] and a [code]point[/code] in screen coordinates, this method should return which subgizmo should be selected. The returned value should be a unique subgizmo identifier, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,208 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSpatialGizmoPlugin" inherits="Resource" version="4.2">
|
||||
<brief_description>
|
||||
Used by the editor to define Spatial gizmo types.
|
||||
</brief_description>
|
||||
<description>
|
||||
[EditorSpatialGizmoPlugin] allows you to define a new type of Gizmo. There are two main ways to do so: extending [EditorSpatialGizmoPlugin] for the simpler gizmos, or creating a new [EditorSpatialGizmo] type. See the tutorial in the documentation for more info.
|
||||
To use [EditorSpatialGizmoPlugin], register it using the [method EditorPlugin.add_spatial_gizmo_plugin] method first.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link>$DOCS_URL/tutorials/plugins/editor/spatial_gizmos.md</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_material">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="material" type="SpatialMaterial" />
|
||||
<description>
|
||||
Adds a new material to the internal material list for the plugin. It can then be accessed with [method get_material]. Should not be overridden.
|
||||
</description>
|
||||
</method>
|
||||
<method name="can_be_hidden" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Override this method to define whether the gizmos handled by this plugin can be hidden or not. Returns [code]true[/code] if not overridden.
|
||||
</description>
|
||||
</method>
|
||||
<method name="commit_handle" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<argument index="3" name="restore" type="Variant" />
|
||||
<argument index="4" name="cancel" type="bool" default="false" />
|
||||
<description>
|
||||
Override this method to commit a handle being edited (handles must have been previously added by [method EditorSpatialGizmo.add_handles] during [method _redraw]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo".
|
||||
If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the committed handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="commit_subgizmos" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="ids" type="PoolIntArray" />
|
||||
<argument index="2" name="restore" type="Array" />
|
||||
<argument index="3" name="cancel" type="bool" default="false" />
|
||||
<description>
|
||||
Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo".
|
||||
If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action. As with all subgizmo methods, transforms are given in local space respect to the gizmo's Spatial. Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="create_gizmo" qualifiers="virtual">
|
||||
<return type="EditorSpatialGizmo" />
|
||||
<argument index="0" name="spatial" type="Spatial" />
|
||||
<description>
|
||||
Override this method to return a custom [EditorSpatialGizmo] for the spatial nodes of your choice, return [code]null[/code] for the rest of nodes. See also [method has_gizmo].
|
||||
</description>
|
||||
</method>
|
||||
<method name="create_handle_material">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="billboard" type="bool" default="false" />
|
||||
<argument index="2" name="texture" type="Texture" default="null" />
|
||||
<description>
|
||||
Creates a handle material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorSpatialGizmo.add_handles]. Should not be overridden.
|
||||
You can optionally provide a texture to use instead of the default icon.
|
||||
</description>
|
||||
</method>
|
||||
<method name="create_icon_material">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="texture" type="Texture" />
|
||||
<argument index="2" name="on_top" type="bool" default="false" />
|
||||
<argument index="3" name="color" type="Color" default="Color( 1, 1, 1, 1 )" />
|
||||
<description>
|
||||
Creates an icon material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorSpatialGizmo.add_unscaled_billboard]. Should not be overridden.
|
||||
</description>
|
||||
</method>
|
||||
<method name="create_material">
|
||||
<return type="void" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="color" type="Color" />
|
||||
<argument index="2" name="billboard" type="bool" default="false" />
|
||||
<argument index="3" name="on_top" type="bool" default="false" />
|
||||
<argument index="4" name="use_vertex_color" type="bool" default="false" />
|
||||
<description>
|
||||
Creates an unshaded material with its variants (selected and/or editable) and adds them to the internal material list. They can then be accessed with [method get_material] and used in [method EditorSpatialGizmo.add_mesh] and [method EditorSpatialGizmo.add_lines]. Should not be overridden.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_gizmo_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_name" qualifiers="virtual">
|
||||
<return type="String" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to provide gizmo's handle names. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_value" qualifiers="virtual">
|
||||
<return type="Variant" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="index" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle].
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_material">
|
||||
<return type="SpatialMaterial" />
|
||||
<argument index="0" name="name" type="String" />
|
||||
<argument index="1" name="gizmo" type="EditorSpatialGizmo" default="null" />
|
||||
<description>
|
||||
Gets material from the internal list of materials. If an [EditorSpatialGizmo] is provided, it will try to get the corresponding variant (selected and/or editable).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_priority" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Override this method to set the gizmo's priority. Gizmos with higher priority will have precedence when processing inputs like handles or subgizmos selection.
|
||||
All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically get higher priority than built-in gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_subgizmo_transform" qualifiers="virtual">
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<description>
|
||||
Override this method to return the current transform of a subgizmo. As with all subgizmo methods, the transform should be in local space respect to the gizmo's Spatial. This transform will be requested at the start of an edit and used in the [code]restore[/code] argument in [method _commit_subgizmos]. Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_gizmo" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="spatial" type="Spatial" />
|
||||
<description>
|
||||
Override this method to define which Spatial nodes have a gizmo from this plugin. Whenever a [Spatial] node is added to a scene this method is called, if it returns [code]true[/code] the node gets a generic [EditorSpatialGizmo] assigned and is added to this plugin's list of active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_handle_highlighted" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return [code]true[/code] whenever to given handle should be highlighted in the editor. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_selectable_when_hidden" qualifiers="virtual">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Override this method to define whether a Spatial with this gizmo should be selectable even when the gizmo is hidden.
|
||||
</description>
|
||||
</method>
|
||||
<method name="redraw" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<description>
|
||||
Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method EditorSpatialGizmo.clear] at the beginning of this method and then add visual elements depending on the node's properties.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_handle" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<argument index="3" name="camera" type="Camera" />
|
||||
<argument index="4" name="point" type="Vector2" />
|
||||
<description>
|
||||
Override this method to update the node's properties when the user drags a gizmo handle (previously added with [method EditorSpatialGizmo.add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the edited handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_subgizmo_transform" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="transform" type="Transform" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="subgizmos_intersect_frustum" qualifiers="virtual">
|
||||
<return type="PoolIntArray" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="camera" type="Camera" />
|
||||
<argument index="2" name="frustum" type="Array" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="subgizmos_intersect_ray" qualifiers="virtual">
|
||||
<return type="int" />
|
||||
<argument index="0" name="gizmo" type="EditorSpatialGizmo" />
|
||||
<argument index="1" name="camera" type="Camera" />
|
||||
<argument index="2" name="point" type="Vector2" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorSpinSlider" inherits="Range" version="4.2">
|
||||
<brief_description>
|
||||
Godot editor's control for editing numeric values.
|
||||
</brief_description>
|
||||
<description>
|
||||
This [Control] node is used in the editor's Inspector dock to allow editing of numeric values. Can be used with [EditorInspectorPlugin] to recreate the same behavior.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="flat" type="bool" setter="set_flat" getter="is_flat" default="false">
|
||||
</member>
|
||||
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
|
||||
<member name="hide_slider" type="bool" setter="set_hide_slider" getter="is_hiding_slider" default="false">
|
||||
If [code]true[/code], the slider is hidden.
|
||||
</member>
|
||||
<member name="label" type="String" setter="set_label" getter="get_label" default="""">
|
||||
</member>
|
||||
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
|
||||
</member>
|
||||
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="1" />
|
||||
<member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" />
|
||||
</members>
|
||||
<constants>
|
||||
</constants>
|
||||
</class>
|
@ -38,10 +38,6 @@
|
||||
#include "scene/resources/navigation/navigation_mesh.h"
|
||||
#include "scene/resources/navigation_2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include <Recast.h>
|
||||
#endif // _3D_DISABLED
|
||||
|
@ -29,7 +29,6 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "area_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/audio_server.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
|
@ -43,10 +43,6 @@ void Camera2D::_update_scroll() {
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
update();
|
||||
// Only set viewport transform when not bound to the main viewport.
|
||||
if (get_viewport() == get_tree()->get_edited_scene_root()->get_viewport()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!viewport) {
|
||||
|
@ -47,7 +47,7 @@ bool Listener2D::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
||||
bool Listener2D::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (p_name == "current") {
|
||||
if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
|
||||
if (is_inside_tree()) {
|
||||
r_ret = current;
|
||||
} else {
|
||||
r_ret = is_current();
|
||||
@ -65,18 +65,14 @@ void Listener2D::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
void Listener2D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (!get_tree()->is_node_being_edited(this) && current) {
|
||||
make_current();
|
||||
}
|
||||
make_current();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (!get_tree()->is_node_being_edited(this)) {
|
||||
if (is_current()) {
|
||||
clear_current();
|
||||
current = true; // Keep it true.
|
||||
} else {
|
||||
current = false;
|
||||
}
|
||||
if (is_current()) {
|
||||
clear_current();
|
||||
current = true; // Keep it true.
|
||||
} else {
|
||||
current = false;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -99,7 +95,7 @@ void Listener2D::clear_current() {
|
||||
}
|
||||
|
||||
bool Listener2D::is_current() const {
|
||||
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
|
||||
if (is_inside_tree()) {
|
||||
return get_viewport()->get_listener_2d() == this;
|
||||
} else {
|
||||
return current;
|
||||
|
@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
if env["disable_3d"]:
|
||||
env.add_source_files(env.scene_sources, "spatial.cpp")
|
||||
env.add_source_files(env.scene_sources, "skeleton.cpp")
|
||||
env.add_source_files(env.scene_sources, "particles.cpp")
|
||||
env.add_source_files(env.scene_sources, "visual_instance.cpp")
|
||||
env.add_source_files(env.scene_sources, "world_environment.cpp")
|
||||
else:
|
||||
env.add_source_files(env.scene_sources, "*.cpp")
|
@ -1,808 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* audio_stream_player_3d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "audio_stream_player_3d.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/3d/listener.h"
|
||||
#include "scene/3d/spatial_velocity_tracker.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004)
|
||||
// Speaker-Placement Correction Amplitude Panning (SPCAP)
|
||||
class Spcap {
|
||||
private:
|
||||
struct Speaker {
|
||||
Vector3 direction;
|
||||
real_t effective_number_of_speakers; // precalculated
|
||||
mutable real_t squared_gain; // temporary
|
||||
};
|
||||
|
||||
PoolVector<Speaker> speakers;
|
||||
|
||||
public:
|
||||
Spcap(unsigned int speaker_count, const Vector3 *speaker_directions) {
|
||||
this->speakers.resize(speaker_count);
|
||||
PoolVector<Speaker>::Write w = this->speakers.write();
|
||||
for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) {
|
||||
w[speaker_num].direction = speaker_directions[speaker_num];
|
||||
w[speaker_num].squared_gain = 0.0;
|
||||
w[speaker_num].effective_number_of_speakers = 0.0;
|
||||
for (unsigned int other_speaker_num = 0; other_speaker_num < speaker_count; other_speaker_num++) {
|
||||
w[speaker_num].effective_number_of_speakers += 0.5 * (1.0 + w[speaker_num].direction.dot(w[other_speaker_num].direction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_speaker_count() const {
|
||||
return (unsigned int)this->speakers.size();
|
||||
}
|
||||
|
||||
Vector3 get_speaker_direction(unsigned int index) const {
|
||||
return this->speakers.read()[index].direction;
|
||||
}
|
||||
|
||||
void calculate(const Vector3 &source_direction, real_t tightness, unsigned int volume_count, real_t *volumes) const {
|
||||
PoolVector<Speaker>::Read r = this->speakers.read();
|
||||
real_t sum_squared_gains = 0.0;
|
||||
for (unsigned int speaker_num = 0; speaker_num < (unsigned int)this->speakers.size(); speaker_num++) {
|
||||
real_t initial_gain = 0.5 * powf(1.0 + r[speaker_num].direction.dot(source_direction), tightness) / r[speaker_num].effective_number_of_speakers;
|
||||
r[speaker_num].squared_gain = initial_gain * initial_gain;
|
||||
sum_squared_gains += r[speaker_num].squared_gain;
|
||||
}
|
||||
|
||||
for (unsigned int speaker_num = 0; speaker_num < MIN(volume_count, (unsigned int)this->speakers.size()); speaker_num++) {
|
||||
volumes[speaker_num] = sqrtf(r[speaker_num].squared_gain / sum_squared_gains);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: hardcoded main speaker directions for 2, 3.1, 5.1 and 7.1 setups - these are simplified and could also be made configurable
|
||||
static const Vector3 speaker_directions[7] = {
|
||||
Vector3(-1.0, 0.0, -1.0).normalized(), // front-left
|
||||
Vector3(1.0, 0.0, -1.0).normalized(), // front-right
|
||||
Vector3(0.0, 0.0, -1.0).normalized(), // center
|
||||
Vector3(-1.0, 0.0, 1.0).normalized(), // rear-left
|
||||
Vector3(1.0, 0.0, 1.0).normalized(), // rear-right
|
||||
Vector3(-1.0, 0.0, 0.0).normalized(), // side-left
|
||||
Vector3(1.0, 0.0, 0.0).normalized(), // side-right
|
||||
};
|
||||
|
||||
void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tightness, AudioStreamPlayer3D::Output &output) {
|
||||
unsigned int speaker_count; // only main speakers (no LFE)
|
||||
switch (AudioServer::get_singleton()->get_speaker_mode()) {
|
||||
default: //fallthrough
|
||||
case AudioServer::SPEAKER_MODE_STEREO:
|
||||
speaker_count = 2;
|
||||
break;
|
||||
case AudioServer::SPEAKER_SURROUND_31:
|
||||
speaker_count = 3;
|
||||
break;
|
||||
case AudioServer::SPEAKER_SURROUND_51:
|
||||
speaker_count = 5;
|
||||
break;
|
||||
case AudioServer::SPEAKER_SURROUND_71:
|
||||
speaker_count = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
Spcap spcap(speaker_count, speaker_directions); //TODO: should only be created/recreated once the speaker mode / speaker positions changes
|
||||
real_t volumes[7];
|
||||
spcap.calculate(source_dir, tightness, speaker_count, volumes);
|
||||
|
||||
switch (AudioServer::get_singleton()->get_speaker_mode()) {
|
||||
case AudioServer::SPEAKER_SURROUND_71:
|
||||
output.vol[3].l = volumes[5]; // side-left
|
||||
output.vol[3].r = volumes[6]; // side-right
|
||||
//fallthrough
|
||||
case AudioServer::SPEAKER_SURROUND_51:
|
||||
output.vol[2].l = volumes[3]; // rear-left
|
||||
output.vol[2].r = volumes[4]; // rear-right
|
||||
//fallthrough
|
||||
case AudioServer::SPEAKER_SURROUND_31:
|
||||
output.vol[1].r = 1.0; // LFE - always full power
|
||||
output.vol[1].l = volumes[2]; // center
|
||||
//fallthrough
|
||||
case AudioServer::SPEAKER_MODE_STEREO:
|
||||
output.vol[0].r = volumes[1]; // front-right
|
||||
output.vol[0].l = volumes[0]; // front-left
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_mix_audio() {
|
||||
if (!stream_playback.is_valid() || !active.is_set() ||
|
||||
(stream_paused && !stream_paused_fade_out)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool started = false;
|
||||
if (setseek.get() >= 0.0) {
|
||||
stream_playback->start(setseek.get());
|
||||
setseek.set(-1.0); //reset seek
|
||||
started = true;
|
||||
}
|
||||
|
||||
//get data
|
||||
AudioFrame *buffer = mix_buffer.ptrw();
|
||||
int buffer_size = mix_buffer.size();
|
||||
|
||||
if (stream_paused_fade_out) {
|
||||
// Short fadeout ramp
|
||||
buffer_size = MIN(buffer_size, 128);
|
||||
}
|
||||
|
||||
// Mix if we're not paused or we're fading out
|
||||
if ((output_count.get() > 0 || out_of_range_mode == OUT_OF_RANGE_MIX)) {
|
||||
float output_pitch_scale = 0.0;
|
||||
if (output_count.get()) {
|
||||
//used for doppler, not realistic but good enough
|
||||
for (int i = 0; i < output_count.get(); i++) {
|
||||
output_pitch_scale += outputs[i].pitch_scale;
|
||||
}
|
||||
output_pitch_scale /= float(output_count.get());
|
||||
} else {
|
||||
output_pitch_scale = 1.0;
|
||||
}
|
||||
|
||||
stream_playback->mix(buffer, pitch_scale * output_pitch_scale, buffer_size);
|
||||
}
|
||||
|
||||
//write all outputs
|
||||
for (int i = 0; i < output_count.get(); i++) {
|
||||
Output current = outputs[i];
|
||||
|
||||
//see if current output exists, to keep volume ramp
|
||||
bool found = false;
|
||||
for (int j = i; j < prev_output_count; j++) {
|
||||
if (prev_outputs[j].viewport == current.viewport) {
|
||||
if (j != i) {
|
||||
SWAP(prev_outputs[j], prev_outputs[i]);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool interpolate_filter = !started;
|
||||
|
||||
if (!found) {
|
||||
//create new if was not used before
|
||||
if (prev_output_count < MAX_OUTPUTS) {
|
||||
prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport
|
||||
prev_output_count++;
|
||||
}
|
||||
prev_outputs[i] = current;
|
||||
interpolate_filter = false;
|
||||
}
|
||||
|
||||
//mix!
|
||||
|
||||
int buffers = AudioServer::get_singleton()->get_channel_count();
|
||||
|
||||
for (int k = 0; k < buffers; k++) {
|
||||
AudioFrame target_volume = stream_paused_fade_out ? AudioFrame(0.f, 0.f) : current.vol[k];
|
||||
AudioFrame vol_prev = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : prev_outputs[i].vol[k];
|
||||
AudioFrame vol_inc = (target_volume - vol_prev) / float(buffer_size);
|
||||
AudioFrame vol = vol_prev;
|
||||
|
||||
if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k)) {
|
||||
continue; //may have been deleted, will be updated on process
|
||||
}
|
||||
|
||||
AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k);
|
||||
current.filter.set_mode(AudioFilterSW::HIGHSHELF);
|
||||
current.filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate());
|
||||
current.filter.set_cutoff(attenuation_filter_cutoff_hz);
|
||||
current.filter.set_resonance(1);
|
||||
current.filter.set_stages(1);
|
||||
current.filter.set_gain(current.filter_gain);
|
||||
|
||||
if (interpolate_filter) {
|
||||
current.filter_process[k * 2 + 0] = prev_outputs[i].filter_process[k * 2 + 0];
|
||||
current.filter_process[k * 2 + 1] = prev_outputs[i].filter_process[k * 2 + 1];
|
||||
|
||||
current.filter_process[k * 2 + 0].set_filter(¤t.filter, false);
|
||||
current.filter_process[k * 2 + 1].set_filter(¤t.filter, false);
|
||||
|
||||
current.filter_process[k * 2 + 0].update_coeffs(buffer_size);
|
||||
current.filter_process[k * 2 + 1].update_coeffs(buffer_size);
|
||||
for (int j = 0; j < buffer_size; j++) {
|
||||
AudioFrame f = buffer[j] * vol;
|
||||
current.filter_process[k * 2 + 0].process_one_interp(f.l);
|
||||
current.filter_process[k * 2 + 1].process_one_interp(f.r);
|
||||
|
||||
target[j] += f;
|
||||
vol += vol_inc;
|
||||
}
|
||||
} else {
|
||||
current.filter_process[k * 2 + 0].set_filter(¤t.filter);
|
||||
current.filter_process[k * 2 + 1].set_filter(¤t.filter);
|
||||
|
||||
current.filter_process[k * 2 + 0].update_coeffs();
|
||||
current.filter_process[k * 2 + 1].update_coeffs();
|
||||
for (int j = 0; j < buffer_size; j++) {
|
||||
AudioFrame f = buffer[j] * vol;
|
||||
current.filter_process[k * 2 + 0].process_one(f.l);
|
||||
current.filter_process[k * 2 + 1].process_one(f.r);
|
||||
|
||||
target[j] += f;
|
||||
vol += vol_inc;
|
||||
}
|
||||
}
|
||||
|
||||
if (current.reverb_bus_index >= 0) {
|
||||
if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.reverb_bus_index, k)) {
|
||||
continue; //may have been deleted, will be updated on process
|
||||
}
|
||||
|
||||
AudioFrame *rtarget = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.reverb_bus_index, k);
|
||||
|
||||
if (current.reverb_bus_index == prev_outputs[i].reverb_bus_index) {
|
||||
AudioFrame rvol_inc = (current.reverb_vol[k] - prev_outputs[i].reverb_vol[k]) / float(buffer_size);
|
||||
AudioFrame rvol = prev_outputs[i].reverb_vol[k];
|
||||
|
||||
for (int j = 0; j < buffer_size; j++) {
|
||||
rtarget[j] += buffer[j] * rvol;
|
||||
rvol += rvol_inc;
|
||||
}
|
||||
} else {
|
||||
AudioFrame rvol = current.reverb_vol[k];
|
||||
for (int j = 0; j < buffer_size; j++) {
|
||||
rtarget[j] += buffer[j] * rvol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev_outputs[i] = current;
|
||||
}
|
||||
|
||||
prev_output_count = output_count.get();
|
||||
|
||||
//stream is no longer active, disable this.
|
||||
if (!stream_playback->is_playing()) {
|
||||
active.clear();
|
||||
}
|
||||
|
||||
output_ready.clear();
|
||||
stream_paused_fade_in = false;
|
||||
stream_paused_fade_out = false;
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
|
||||
float att = 0;
|
||||
switch (attenuation_model) {
|
||||
case ATTENUATION_INVERSE_DISTANCE: {
|
||||
att = Math::linear2db(1.0 / ((p_distance / unit_size) + CMP_EPSILON));
|
||||
} break;
|
||||
case ATTENUATION_INVERSE_SQUARE_DISTANCE: {
|
||||
float d = (p_distance / unit_size);
|
||||
d *= d;
|
||||
att = Math::linear2db(1.0 / (d + CMP_EPSILON));
|
||||
} break;
|
||||
case ATTENUATION_LOGARITHMIC: {
|
||||
att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON);
|
||||
} break;
|
||||
case ATTENUATION_DISABLED:
|
||||
break;
|
||||
default: {
|
||||
ERR_PRINT("Unknown attenuation type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
att += unit_db;
|
||||
if (att > max_db) {
|
||||
att = max_db;
|
||||
}
|
||||
|
||||
return att;
|
||||
}
|
||||
|
||||
void _update_sound() {
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
velocity_tracker->reset(get_global_transform().origin);
|
||||
AudioServer::get_singleton()->add_callback(_mix_audios, this);
|
||||
if (autoplay && !Engine::get_singleton()->is_editor_hint()) {
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
AudioServer::get_singleton()->remove_callback(_mix_audios, this);
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_PAUSED) {
|
||||
if (!can_process()) {
|
||||
// Node can't process so we start fading out to silence
|
||||
set_stream_paused(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_UNPAUSED) {
|
||||
set_stream_paused(false);
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
|
||||
velocity_tracker->update_position(get_global_transform().origin);
|
||||
}
|
||||
}
|
||||
|
||||
//start playing if requested
|
||||
if (setplay.get() >= 0.0) {
|
||||
setseek.set(setplay.get());
|
||||
active.set();
|
||||
setplay.set(-1);
|
||||
//do not update, this makes it easier to animate (will shut off otherwise)
|
||||
///_change_notify("playing"); //update property in editor
|
||||
}
|
||||
|
||||
//stop playing if no longer active
|
||||
if (!active.is_set()) {
|
||||
set_physics_process_internal(false);
|
||||
//do not update, this makes it easier to animate (will shut off otherwise)
|
||||
//_change_notify("playing"); //update property in editor
|
||||
emit_signal("finished");
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
|
||||
// Instancing audio streams can cause large memory allocations, do it prior to AudioServer::lock.
|
||||
Ref<AudioStreamPlayback> pre_instanced_playback;
|
||||
if (p_stream.is_valid()) {
|
||||
pre_instanced_playback = p_stream->instance_playback();
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->lock();
|
||||
|
||||
mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
|
||||
|
||||
if (stream_playback.is_valid()) {
|
||||
stream_playback.unref();
|
||||
stream.unref();
|
||||
active.clear();
|
||||
setseek.set(-1);
|
||||
}
|
||||
|
||||
if (p_stream.is_valid()) {
|
||||
stream = p_stream;
|
||||
stream_playback = pre_instanced_playback;
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->unlock();
|
||||
|
||||
if (p_stream.is_valid() && stream_playback.is_null()) {
|
||||
stream.unref();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {
|
||||
return stream;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_unit_db(float p_volume) {
|
||||
unit_db = p_volume;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_unit_db() const {
|
||||
return unit_db;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_unit_size(float p_volume) {
|
||||
unit_size = p_volume;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_unit_size() const {
|
||||
return unit_size;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_max_db(float p_boost) {
|
||||
max_db = p_boost;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_max_db() const {
|
||||
return max_db;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) {
|
||||
ERR_FAIL_COND(!(p_pitch_scale > 0.0));
|
||||
pitch_scale = p_pitch_scale;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_pitch_scale() const {
|
||||
return pitch_scale;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::play(float p_from_pos) {
|
||||
if (!is_playing()) {
|
||||
// Reset the prev_output_count if the stream is stopped
|
||||
prev_output_count = 0;
|
||||
}
|
||||
|
||||
if (stream_playback.is_valid()) {
|
||||
setplay.set(p_from_pos);
|
||||
output_ready.clear();
|
||||
set_physics_process_internal(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::seek(float p_seconds) {
|
||||
if (stream_playback.is_valid()) {
|
||||
setseek.set(p_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::stop() {
|
||||
if (stream_playback.is_valid()) {
|
||||
active.clear();
|
||||
set_physics_process_internal(false);
|
||||
setplay.set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioStreamPlayer3D::is_playing() const {
|
||||
if (stream_playback.is_valid()) {
|
||||
return active.is_set() || setplay.get() >= 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_playback_position() {
|
||||
if (stream_playback.is_valid()) {
|
||||
float ss = setseek.get();
|
||||
if (ss >= 0.0) {
|
||||
return ss;
|
||||
}
|
||||
return stream_playback->get_playback_position();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_bus(const StringName &p_bus) {
|
||||
//if audio is active, must lock this
|
||||
AudioServer::get_singleton()->lock();
|
||||
bus = p_bus;
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
StringName AudioStreamPlayer3D::get_bus() const {
|
||||
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
|
||||
if (AudioServer::get_singleton()->get_bus_name(i) == bus) {
|
||||
return bus;
|
||||
}
|
||||
}
|
||||
return "Master";
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_autoplay(bool p_enable) {
|
||||
autoplay = p_enable;
|
||||
}
|
||||
bool AudioStreamPlayer3D::is_autoplay_enabled() {
|
||||
return autoplay;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_set_playing(bool p_enable) {
|
||||
if (p_enable) {
|
||||
play();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
bool AudioStreamPlayer3D::_is_active() const {
|
||||
return active.is_set();
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
|
||||
if (property.name == "bus") {
|
||||
String options;
|
||||
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
|
||||
if (i > 0) {
|
||||
options += ",";
|
||||
}
|
||||
String name = AudioServer::get_singleton()->get_bus_name(i);
|
||||
options += name;
|
||||
}
|
||||
|
||||
property.hint_string = options;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_bus_layout_changed() {
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_max_distance(float p_metres) {
|
||||
ERR_FAIL_COND(p_metres < 0.0);
|
||||
max_distance = p_metres;
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_max_distance() const {
|
||||
return max_distance;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_area_mask(uint32_t p_mask) {
|
||||
area_mask = p_mask;
|
||||
}
|
||||
|
||||
uint32_t AudioStreamPlayer3D::get_area_mask() const {
|
||||
return area_mask;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) {
|
||||
emission_angle_enabled = p_enable;
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
bool AudioStreamPlayer3D::is_emission_angle_enabled() const {
|
||||
return emission_angle_enabled;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_emission_angle(float p_angle) {
|
||||
ERR_FAIL_COND(p_angle < 0 || p_angle > 90);
|
||||
emission_angle = p_angle;
|
||||
update_gizmos();
|
||||
_change_notify("emission_angle");
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_emission_angle() const {
|
||||
return emission_angle;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db) {
|
||||
emission_angle_filter_attenuation_db = p_angle_attenuation_db;
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db() const {
|
||||
return emission_angle_filter_attenuation_db;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz(float p_hz) {
|
||||
attenuation_filter_cutoff_hz = p_hz;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz() const {
|
||||
return attenuation_filter_cutoff_hz;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_attenuation_filter_db(float p_db) {
|
||||
attenuation_filter_db = p_db;
|
||||
}
|
||||
float AudioStreamPlayer3D::get_attenuation_filter_db() const {
|
||||
return attenuation_filter_db;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) {
|
||||
ERR_FAIL_INDEX((int)p_model, 4);
|
||||
attenuation_model = p_model;
|
||||
}
|
||||
|
||||
AudioStreamPlayer3D::AttenuationModel AudioStreamPlayer3D::get_attenuation_model() const {
|
||||
return attenuation_model;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_out_of_range_mode(OutOfRangeMode p_mode) {
|
||||
ERR_FAIL_INDEX((int)p_mode, 2);
|
||||
out_of_range_mode = p_mode;
|
||||
}
|
||||
|
||||
AudioStreamPlayer3D::OutOfRangeMode AudioStreamPlayer3D::get_out_of_range_mode() const {
|
||||
return out_of_range_mode;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {
|
||||
if (doppler_tracking == p_tracking) {
|
||||
return;
|
||||
}
|
||||
|
||||
doppler_tracking = p_tracking;
|
||||
|
||||
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
|
||||
set_notify_transform(true);
|
||||
velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);
|
||||
if (is_inside_tree()) {
|
||||
velocity_tracker->reset(get_global_transform().origin);
|
||||
}
|
||||
} else {
|
||||
set_notify_transform(false);
|
||||
}
|
||||
}
|
||||
|
||||
AudioStreamPlayer3D::DopplerTracking AudioStreamPlayer3D::get_doppler_tracking() const {
|
||||
return doppler_tracking;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_stream_paused(bool p_pause) {
|
||||
if (p_pause != stream_paused) {
|
||||
stream_paused = p_pause;
|
||||
stream_paused_fade_in = !stream_paused;
|
||||
stream_paused_fade_out = stream_paused;
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioStreamPlayer3D::get_stream_paused() const {
|
||||
return stream_paused;
|
||||
}
|
||||
|
||||
Ref<AudioStreamPlayback> AudioStreamPlayer3D::get_stream_playback() {
|
||||
return stream_playback;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::set_panning_strength(float p_panning_strength) {
|
||||
ERR_FAIL_COND_MSG(p_panning_strength < 0, "Panning strength must be a positive number.");
|
||||
panning_strength = p_panning_strength;
|
||||
}
|
||||
|
||||
float AudioStreamPlayer3D::get_panning_strength() const {
|
||||
return panning_strength;
|
||||
}
|
||||
|
||||
void AudioStreamPlayer3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream);
|
||||
ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_unit_db", "unit_db"), &AudioStreamPlayer3D::set_unit_db);
|
||||
ClassDB::bind_method(D_METHOD("get_unit_db"), &AudioStreamPlayer3D::get_unit_db);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_unit_size", "unit_size"), &AudioStreamPlayer3D::set_unit_size);
|
||||
ClassDB::bind_method(D_METHOD("get_unit_size"), &AudioStreamPlayer3D::get_unit_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db);
|
||||
ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pitch_scale", "pitch_scale"), &AudioStreamPlayer3D::set_pitch_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_pitch_scale"), &AudioStreamPlayer3D::get_pitch_scale);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer3D::play, DEFVAL(0.0));
|
||||
ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer3D::seek);
|
||||
ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer3D::is_playing);
|
||||
ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayer3D::get_playback_position);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer3D::set_bus);
|
||||
ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer3D::get_bus);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer3D::set_autoplay);
|
||||
ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer3D::is_autoplay_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer3D::_set_playing);
|
||||
ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer3D::_is_active);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_max_distance", "metres"), &AudioStreamPlayer3D::set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer3D::get_max_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer3D::set_area_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer3D::get_area_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_emission_angle", "degrees"), &AudioStreamPlayer3D::set_emission_angle);
|
||||
ClassDB::bind_method(D_METHOD("get_emission_angle"), &AudioStreamPlayer3D::get_emission_angle);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_emission_angle_enabled", "enabled"), &AudioStreamPlayer3D::set_emission_angle_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_emission_angle_enabled"), &AudioStreamPlayer3D::is_emission_angle_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_emission_angle_filter_attenuation_db", "db"), &AudioStreamPlayer3D::set_emission_angle_filter_attenuation_db);
|
||||
ClassDB::bind_method(D_METHOD("get_emission_angle_filter_attenuation_db"), &AudioStreamPlayer3D::get_emission_angle_filter_attenuation_db);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_attenuation_filter_cutoff_hz", "degrees"), &AudioStreamPlayer3D::set_attenuation_filter_cutoff_hz);
|
||||
ClassDB::bind_method(D_METHOD("get_attenuation_filter_cutoff_hz"), &AudioStreamPlayer3D::get_attenuation_filter_cutoff_hz);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_attenuation_filter_db", "db"), &AudioStreamPlayer3D::set_attenuation_filter_db);
|
||||
ClassDB::bind_method(D_METHOD("get_attenuation_filter_db"), &AudioStreamPlayer3D::get_attenuation_filter_db);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_attenuation_model", "model"), &AudioStreamPlayer3D::set_attenuation_model);
|
||||
ClassDB::bind_method(D_METHOD("get_attenuation_model"), &AudioStreamPlayer3D::get_attenuation_model);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_out_of_range_mode", "mode"), &AudioStreamPlayer3D::set_out_of_range_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_out_of_range_mode"), &AudioStreamPlayer3D::get_out_of_range_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &AudioStreamPlayer3D::set_doppler_tracking);
|
||||
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &AudioStreamPlayer3D::get_doppler_tracking);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_stream_paused", "pause"), &AudioStreamPlayer3D::set_stream_paused);
|
||||
ClassDB::bind_method(D_METHOD("get_stream_paused"), &AudioStreamPlayer3D::get_stream_paused);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_panning_strength", "panning_strength"), &AudioStreamPlayer3D::set_panning_strength);
|
||||
ClassDB::bind_method(D_METHOD("get_panning_strength"), &AudioStreamPlayer3D::get_panning_strength);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_stream_playback"), &AudioStreamPlayer3D::get_stream_playback);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Logarithmic,Disabled"), "set_attenuation_model", "get_attenuation_model");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01,or_greater"), "set_max_distance", "get_max_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "out_of_range_mode", PROPERTY_HINT_ENUM, "Mix,Pause"), "set_out_of_range_mode", "get_out_of_range_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "panning_strength", PROPERTY_HINT_RANGE, "0,3,0.01,or_greater"), "set_panning_strength", "get_panning_strength");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask");
|
||||
ADD_GROUP("Emission Angle", "emission_angle");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emission_angle_enabled"), "set_emission_angle_enabled", "is_emission_angle_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db");
|
||||
ADD_GROUP("Attenuation Filter", "attenuation_filter_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db");
|
||||
ADD_GROUP("Doppler", "doppler_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
|
||||
|
||||
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_DISTANCE);
|
||||
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE);
|
||||
BIND_ENUM_CONSTANT(ATTENUATION_LOGARITHMIC);
|
||||
BIND_ENUM_CONSTANT(ATTENUATION_DISABLED);
|
||||
|
||||
BIND_ENUM_CONSTANT(OUT_OF_RANGE_MIX);
|
||||
BIND_ENUM_CONSTANT(OUT_OF_RANGE_PAUSE);
|
||||
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED);
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("finished"));
|
||||
}
|
||||
|
||||
AudioStreamPlayer3D::AudioStreamPlayer3D() {
|
||||
unit_db = 0;
|
||||
unit_size = 1;
|
||||
attenuation_model = ATTENUATION_INVERSE_DISTANCE;
|
||||
max_db = 3;
|
||||
pitch_scale = 1.0;
|
||||
autoplay = false;
|
||||
setseek.set(-1);
|
||||
prev_output_count = 0;
|
||||
max_distance = 0;
|
||||
setplay.set(-1);
|
||||
area_mask = 1;
|
||||
emission_angle = 45;
|
||||
emission_angle_enabled = false;
|
||||
emission_angle_filter_attenuation_db = -12;
|
||||
attenuation_filter_cutoff_hz = 5000;
|
||||
attenuation_filter_db = -24;
|
||||
out_of_range_mode = OUT_OF_RANGE_MIX;
|
||||
doppler_tracking = DOPPLER_TRACKING_DISABLED;
|
||||
stream_paused = false;
|
||||
stream_paused_fade_in = false;
|
||||
stream_paused_fade_out = false;
|
||||
|
||||
velocity_tracker.instance();
|
||||
AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed");
|
||||
set_disable_scale(true);
|
||||
cached_global_panning_strength = ProjectSettings::get_singleton()->get("audio/3d_panning_strength");
|
||||
}
|
||||
AudioStreamPlayer3D::~AudioStreamPlayer3D() {
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
#ifndef AUDIO_STREAM_PLAYER_3D_H
|
||||
#define AUDIO_STREAM_PLAYER_3D_H
|
||||
/*************************************************************************/
|
||||
/* audio_stream_player_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/os/safe_refcount.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "servers/audio/audio_filter_sw.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
class Camera;
|
||||
class AudioStreamPlayback;
|
||||
class SpatialVelocityTracker;
|
||||
|
||||
class AudioStreamPlayer3D : public Spatial {
|
||||
GDCLASS(AudioStreamPlayer3D, Spatial);
|
||||
|
||||
public:
|
||||
enum AttenuationModel {
|
||||
ATTENUATION_INVERSE_DISTANCE,
|
||||
ATTENUATION_INVERSE_SQUARE_DISTANCE,
|
||||
ATTENUATION_LOGARITHMIC,
|
||||
ATTENUATION_DISABLED,
|
||||
};
|
||||
|
||||
enum OutOfRangeMode {
|
||||
OUT_OF_RANGE_MIX,
|
||||
OUT_OF_RANGE_PAUSE,
|
||||
};
|
||||
|
||||
enum DopplerTracking {
|
||||
DOPPLER_TRACKING_DISABLED,
|
||||
DOPPLER_TRACKING_IDLE_STEP,
|
||||
DOPPLER_TRACKING_PHYSICS_STEP
|
||||
};
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_OUTPUTS = 8,
|
||||
MAX_INTERSECT_AREAS = 32
|
||||
|
||||
};
|
||||
|
||||
struct Output {
|
||||
AudioFilterSW filter;
|
||||
AudioFilterSW::Processor filter_process[8];
|
||||
AudioFrame vol[4];
|
||||
float filter_gain;
|
||||
float pitch_scale;
|
||||
int bus_index;
|
||||
int reverb_bus_index;
|
||||
AudioFrame reverb_vol[4];
|
||||
Viewport *viewport; //pointer only used for reference to previous mix
|
||||
|
||||
Output() {
|
||||
filter_gain = 0;
|
||||
viewport = nullptr;
|
||||
reverb_bus_index = -1;
|
||||
bus_index = -1;
|
||||
}
|
||||
};
|
||||
|
||||
Output outputs[MAX_OUTPUTS];
|
||||
SafeNumeric<int> output_count;
|
||||
SafeFlag output_ready;
|
||||
|
||||
//these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks)
|
||||
Output prev_outputs[MAX_OUTPUTS];
|
||||
int prev_output_count;
|
||||
|
||||
Ref<AudioStreamPlayback> stream_playback;
|
||||
Ref<AudioStream> stream;
|
||||
Vector<AudioFrame> mix_buffer;
|
||||
|
||||
SafeNumeric<float> setseek;
|
||||
SafeFlag active;
|
||||
SafeNumeric<float> setplay;
|
||||
|
||||
AttenuationModel attenuation_model;
|
||||
float unit_db;
|
||||
float unit_size;
|
||||
float max_db;
|
||||
float pitch_scale;
|
||||
bool autoplay;
|
||||
bool stream_paused;
|
||||
bool stream_paused_fade_in;
|
||||
bool stream_paused_fade_out;
|
||||
StringName bus;
|
||||
|
||||
static void _calc_output_vol(const Vector3 &source_dir, real_t tightness, Output &output);
|
||||
void _mix_audio();
|
||||
static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer3D *>(self)->_mix_audio(); }
|
||||
|
||||
void _set_playing(bool p_enable);
|
||||
bool _is_active() const;
|
||||
|
||||
void _bus_layout_changed();
|
||||
|
||||
uint32_t area_mask;
|
||||
|
||||
bool emission_angle_enabled;
|
||||
float emission_angle;
|
||||
float emission_angle_filter_attenuation_db;
|
||||
float attenuation_filter_cutoff_hz;
|
||||
float attenuation_filter_db;
|
||||
|
||||
float max_distance;
|
||||
|
||||
Ref<SpatialVelocityTracker> velocity_tracker;
|
||||
|
||||
DopplerTracking doppler_tracking;
|
||||
|
||||
OutOfRangeMode out_of_range_mode;
|
||||
|
||||
float _get_attenuation_db(float p_distance) const;
|
||||
|
||||
float panning_strength = 1.0f;
|
||||
float cached_global_panning_strength = 1.0f;
|
||||
|
||||
protected:
|
||||
void _validate_property(PropertyInfo &property) const;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_stream(Ref<AudioStream> p_stream);
|
||||
Ref<AudioStream> get_stream() const;
|
||||
|
||||
void set_unit_db(float p_volume);
|
||||
float get_unit_db() const;
|
||||
|
||||
void set_unit_size(float p_volume);
|
||||
float get_unit_size() const;
|
||||
|
||||
void set_max_db(float p_boost);
|
||||
float get_max_db() const;
|
||||
|
||||
void set_pitch_scale(float p_pitch_scale);
|
||||
float get_pitch_scale() const;
|
||||
|
||||
void play(float p_from_pos = 0.0);
|
||||
void seek(float p_seconds);
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
float get_playback_position();
|
||||
|
||||
void set_bus(const StringName &p_bus);
|
||||
StringName get_bus() const;
|
||||
|
||||
void set_autoplay(bool p_enable);
|
||||
bool is_autoplay_enabled();
|
||||
|
||||
void set_max_distance(float p_metres);
|
||||
float get_max_distance() const;
|
||||
|
||||
void set_area_mask(uint32_t p_mask);
|
||||
uint32_t get_area_mask() const;
|
||||
|
||||
void set_emission_angle_enabled(bool p_enable);
|
||||
bool is_emission_angle_enabled() const;
|
||||
|
||||
void set_emission_angle(float p_angle);
|
||||
float get_emission_angle() const;
|
||||
|
||||
void set_emission_angle_filter_attenuation_db(float p_angle_attenuation_db);
|
||||
float get_emission_angle_filter_attenuation_db() const;
|
||||
|
||||
void set_attenuation_filter_cutoff_hz(float p_hz);
|
||||
float get_attenuation_filter_cutoff_hz() const;
|
||||
|
||||
void set_attenuation_filter_db(float p_db);
|
||||
float get_attenuation_filter_db() const;
|
||||
|
||||
void set_attenuation_model(AttenuationModel p_model);
|
||||
AttenuationModel get_attenuation_model() const;
|
||||
|
||||
void set_out_of_range_mode(OutOfRangeMode p_mode);
|
||||
OutOfRangeMode get_out_of_range_mode() const;
|
||||
|
||||
void set_doppler_tracking(DopplerTracking p_tracking);
|
||||
DopplerTracking get_doppler_tracking() const;
|
||||
|
||||
void set_stream_paused(bool p_pause);
|
||||
bool get_stream_paused() const;
|
||||
|
||||
void set_panning_strength(float p_panning_strength);
|
||||
float get_panning_strength() const;
|
||||
|
||||
Ref<AudioStreamPlayback> get_stream_playback();
|
||||
|
||||
AudioStreamPlayer3D();
|
||||
~AudioStreamPlayer3D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(AudioStreamPlayer3D::AttenuationModel)
|
||||
VARIANT_ENUM_CAST(AudioStreamPlayer3D::OutOfRangeMode)
|
||||
VARIANT_ENUM_CAST(AudioStreamPlayer3D::DopplerTracking)
|
||||
#endif // AUDIO_STREAM_PLAYER_3D_H
|
@ -1,685 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/math/projection.h"
|
||||
#include "scene/3d/spatial_velocity_tracker.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/resources/environment_3d.h"
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/mesh/surface_tool.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
|
||||
void Camera::_update_audio_listener_state() {
|
||||
}
|
||||
|
||||
void Camera::_request_camera_update() {
|
||||
_update_camera();
|
||||
}
|
||||
|
||||
void Camera::_update_camera_mode() {
|
||||
force_change = true;
|
||||
switch (mode) {
|
||||
case PROJECTION_PERSPECTIVE: {
|
||||
set_perspective(fov, near, far);
|
||||
|
||||
} break;
|
||||
case PROJECTION_ORTHOGONAL: {
|
||||
set_orthogonal(size, near, far);
|
||||
} break;
|
||||
case PROJECTION_FRUSTUM: {
|
||||
set_frustum(size, frustum_offset, near, far);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::_validate_property(PropertyInfo &p_property) const {
|
||||
if (p_property.name == "fov") {
|
||||
if (mode != PROJECTION_PERSPECTIVE) {
|
||||
p_property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
}
|
||||
} else if (p_property.name == "size") {
|
||||
if (mode != PROJECTION_ORTHOGONAL && mode != PROJECTION_FRUSTUM) {
|
||||
p_property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
}
|
||||
} else if (p_property.name == "frustum_offset") {
|
||||
if (mode != PROJECTION_FRUSTUM) {
|
||||
p_property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::_update_camera() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_transform(camera, get_camera_transform());
|
||||
|
||||
// here goes listener stuff
|
||||
/*
|
||||
if (viewport_ptr && is_inside_scene() && is_current())
|
||||
get_world()->_camera_transform_changed_notify();
|
||||
*/
|
||||
|
||||
if (get_tree()->is_node_being_edited(this) || !is_current()) {
|
||||
return;
|
||||
}
|
||||
|
||||
get_world()->_camera_transform_changed_notify();
|
||||
|
||||
if (get_world_3d().is_valid()) {
|
||||
get_world_3d()->_update_camera(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::_physics_interpolated_changed() {
|
||||
RenderingServer::get_singleton()->camera_set_interpolated(camera, is_physics_interpolated());
|
||||
}
|
||||
|
||||
void Camera::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
// Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD
|
||||
// and Spatial will handle it first, including clearing its reference to the Viewport,
|
||||
// therefore making it impossible to subclasses to access it
|
||||
world = get_world();
|
||||
ERR_FAIL_COND(!world);
|
||||
|
||||
bool first_camera = world->_camera_add(this);
|
||||
if (current || first_camera) {
|
||||
world->_camera_set(this);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
_request_camera_update();
|
||||
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
|
||||
velocity_tracker->update_position(get_global_transform().origin);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
|
||||
if (is_physics_interpolated()) {
|
||||
RenderingServer::get_singleton()->camera_reset_physics_interpolation(camera);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
if (!get_tree()->is_node_being_edited(this)) {
|
||||
if (is_current()) {
|
||||
clear_current();
|
||||
current = true; //keep it true
|
||||
|
||||
} else {
|
||||
current = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (world) {
|
||||
world->_camera_remove(this);
|
||||
world = nullptr;
|
||||
}
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_BECAME_CURRENT: {
|
||||
if (world) {
|
||||
world->_world_3d_register_camera(this);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_LOST_CURRENT: {
|
||||
if (world) {
|
||||
world->_world_3d_remove_camera(this);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Transform Camera::get_camera_transform() const {
|
||||
Transform tr = get_global_transform().orthonormalized();
|
||||
tr.origin += tr.basis.get_axis(1) * v_offset;
|
||||
tr.origin += tr.basis.get_axis(0) * h_offset;
|
||||
return tr;
|
||||
}
|
||||
|
||||
void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
|
||||
if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
fov = p_fovy_degrees;
|
||||
near = p_z_near;
|
||||
far = p_z_far;
|
||||
mode = PROJECTION_PERSPECTIVE;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_perspective(camera, fov, near, far);
|
||||
update_gizmos();
|
||||
force_change = false;
|
||||
}
|
||||
void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
|
||||
if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
size = p_size;
|
||||
|
||||
near = p_z_near;
|
||||
far = p_z_far;
|
||||
mode = PROJECTION_ORTHOGONAL;
|
||||
force_change = false;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_orthogonal(camera, size, near, far);
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
void Camera::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
|
||||
if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM) {
|
||||
return;
|
||||
}
|
||||
|
||||
size = p_size;
|
||||
frustum_offset = p_offset;
|
||||
|
||||
near = p_z_near;
|
||||
far = p_z_far;
|
||||
mode = PROJECTION_FRUSTUM;
|
||||
force_change = false;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far);
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
void Camera::set_projection(Camera::ProjectionMode p_mode) {
|
||||
if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) {
|
||||
mode = p_mode;
|
||||
_update_camera_mode();
|
||||
_change_notify();
|
||||
}
|
||||
}
|
||||
|
||||
RID Camera::get_camera() const {
|
||||
return camera;
|
||||
};
|
||||
|
||||
void Camera::make_current() {
|
||||
current = true;
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
get_world()->_camera_set(this);
|
||||
|
||||
//get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this);
|
||||
}
|
||||
|
||||
void Camera::clear_current(bool p_enable_next) {
|
||||
current = false;
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_world()->get_camera() == this) {
|
||||
get_world()->_camera_set(nullptr);
|
||||
|
||||
if (p_enable_next) {
|
||||
get_world()->_camera_make_next_current(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::set_current(bool p_current) {
|
||||
if (p_current) {
|
||||
make_current();
|
||||
} else {
|
||||
clear_current();
|
||||
}
|
||||
}
|
||||
|
||||
bool Camera::is_current() const {
|
||||
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
|
||||
return get_world()->get_camera() == this;
|
||||
} else {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 Camera::project_ray_normal(const Point2 &p_pos) const {
|
||||
Vector3 ray = project_local_ray_normal(p_pos);
|
||||
return get_camera_transform().basis.xform(ray).normalized();
|
||||
};
|
||||
|
||||
Vector3 Camera::project_local_ray_normal(const Point2 &p_pos) const {
|
||||
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
|
||||
|
||||
Size2 viewport_size = get_world()->get_camera_rect_size();
|
||||
Vector2 cpos = get_world()->get_camera_coords(p_pos);
|
||||
Vector3 ray;
|
||||
|
||||
if (mode == PROJECTION_ORTHOGONAL) {
|
||||
ray = Vector3(0, 0, -1);
|
||||
} else {
|
||||
Projection cm;
|
||||
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
Vector2 screen_he = cm.get_viewport_half_extents();
|
||||
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -near).normalized();
|
||||
}
|
||||
|
||||
return ray;
|
||||
};
|
||||
|
||||
Vector3 Camera::project_ray_origin(const Point2 &p_pos) const {
|
||||
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
|
||||
|
||||
Size2 viewport_size = get_world()->get_camera_rect_size();
|
||||
Vector2 cpos = get_world()->get_camera_coords(p_pos);
|
||||
ERR_FAIL_COND_V(viewport_size.y == 0, Vector3());
|
||||
|
||||
if (mode == PROJECTION_PERSPECTIVE) {
|
||||
return get_camera_transform().origin;
|
||||
} else {
|
||||
Vector2 pos = cpos / viewport_size;
|
||||
float vsize, hsize;
|
||||
if (keep_aspect == KEEP_WIDTH) {
|
||||
vsize = size / viewport_size.aspect();
|
||||
hsize = size;
|
||||
} else {
|
||||
hsize = size * viewport_size.aspect();
|
||||
vsize = size;
|
||||
}
|
||||
|
||||
Vector3 ray;
|
||||
ray.x = pos.x * (hsize)-hsize / 2;
|
||||
ray.y = (1.0 - pos.y) * (vsize)-vsize / 2;
|
||||
ray.z = -near;
|
||||
ray = get_camera_transform().xform(ray);
|
||||
return ray;
|
||||
};
|
||||
};
|
||||
|
||||
bool Camera::is_position_behind(const Vector3 &p_pos) const {
|
||||
Transform t = get_global_transform();
|
||||
Vector3 eyedir = -t.basis.get_axis(2).normalized();
|
||||
return eyedir.dot(p_pos - t.origin) < near;
|
||||
}
|
||||
|
||||
Vector<Vector3> Camera::get_near_plane_points() const {
|
||||
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector<Vector3>(), "Camera is not inside scene.");
|
||||
|
||||
Size2 viewport_size = get_world()->get_visible_rect().size;
|
||||
|
||||
Projection cm;
|
||||
|
||||
if (mode == PROJECTION_ORTHOGONAL) {
|
||||
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
} else {
|
||||
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
}
|
||||
|
||||
Vector3 endpoints[8];
|
||||
cm.get_endpoints(Transform(), endpoints);
|
||||
|
||||
Vector<Vector3> points;
|
||||
points.push_back(Vector3());
|
||||
for (int i = 0; i < 4; i++) {
|
||||
points.push_back(endpoints[i + 4]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
Point2 Camera::unproject_position(const Vector3 &p_pos) const {
|
||||
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene.");
|
||||
|
||||
Size2 viewport_size = get_world()->get_visible_rect().size;
|
||||
|
||||
Projection cm;
|
||||
|
||||
if (mode == PROJECTION_ORTHOGONAL) {
|
||||
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
} else {
|
||||
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
}
|
||||
|
||||
Plane p(get_camera_transform().xform_inv(p_pos), 1.0);
|
||||
|
||||
p = cm.xform(p);
|
||||
p.normal /= p.d;
|
||||
|
||||
Point2 res;
|
||||
res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x;
|
||||
res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const {
|
||||
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
|
||||
|
||||
if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) {
|
||||
return get_global_transform().origin;
|
||||
}
|
||||
Size2 viewport_size = get_world()->get_visible_rect().size;
|
||||
|
||||
Projection cm;
|
||||
|
||||
if (mode == PROJECTION_ORTHOGONAL) {
|
||||
cm.set_orthogonal(size, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
|
||||
} else {
|
||||
cm.set_perspective(fov, viewport_size.aspect(), p_z_depth, far, keep_aspect == KEEP_WIDTH);
|
||||
}
|
||||
|
||||
Vector2 vp_he = cm.get_viewport_half_extents();
|
||||
|
||||
Vector2 point;
|
||||
point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0;
|
||||
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
|
||||
point *= vp_he;
|
||||
|
||||
Vector3 p(point.x, point.y, -p_z_depth);
|
||||
|
||||
return get_camera_transform().xform(p);
|
||||
}
|
||||
|
||||
/*
|
||||
void Camera::_camera_make_current(Node *p_camera) {
|
||||
|
||||
|
||||
if (p_camera==this) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,camera);
|
||||
active=true;
|
||||
} else {
|
||||
if (active && p_camera==NULL) {
|
||||
//detech camera because no one else will claim it
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,RID());
|
||||
}
|
||||
active=false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Camera::set_environment(const Ref<Environment3D> &p_environment) {
|
||||
environment = p_environment;
|
||||
if (environment.is_valid()) {
|
||||
RS::get_singleton()->camera_set_environment(camera, environment->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->camera_set_environment(camera, RID());
|
||||
}
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
Ref<Environment3D> Camera::get_environment() const {
|
||||
return environment;
|
||||
}
|
||||
|
||||
void Camera::set_keep_aspect_mode(KeepAspect p_aspect) {
|
||||
keep_aspect = p_aspect;
|
||||
RenderingServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH);
|
||||
_update_camera_mode();
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
Camera::KeepAspect Camera::get_keep_aspect_mode() const {
|
||||
return keep_aspect;
|
||||
}
|
||||
|
||||
void Camera::set_doppler_tracking(DopplerTracking p_tracking) {
|
||||
if (doppler_tracking == p_tracking) {
|
||||
return;
|
||||
}
|
||||
|
||||
doppler_tracking = p_tracking;
|
||||
if (p_tracking != DOPPLER_TRACKING_DISABLED) {
|
||||
velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);
|
||||
if (is_inside_tree()) {
|
||||
velocity_tracker->reset(get_global_transform().origin);
|
||||
}
|
||||
}
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
Camera::DopplerTracking Camera::get_doppler_tracking() const {
|
||||
return doppler_tracking;
|
||||
}
|
||||
|
||||
void Camera::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("project_ray_normal", "screen_point"), &Camera::project_ray_normal);
|
||||
ClassDB::bind_method(D_METHOD("project_local_ray_normal", "screen_point"), &Camera::project_local_ray_normal);
|
||||
ClassDB::bind_method(D_METHOD("project_ray_origin", "screen_point"), &Camera::project_ray_origin);
|
||||
ClassDB::bind_method(D_METHOD("unproject_position", "world_point"), &Camera::unproject_position);
|
||||
ClassDB::bind_method(D_METHOD("is_position_behind", "world_point"), &Camera::is_position_behind);
|
||||
ClassDB::bind_method(D_METHOD("project_position", "screen_point", "z_depth"), &Camera::project_position);
|
||||
ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective);
|
||||
ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal);
|
||||
ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera::set_frustum);
|
||||
ClassDB::bind_method(D_METHOD("make_current"), &Camera::make_current);
|
||||
ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera::clear_current, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("set_current", "enable"), &Camera::set_current);
|
||||
ClassDB::bind_method(D_METHOD("is_current"), &Camera::is_current);
|
||||
ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera::get_camera_transform);
|
||||
ClassDB::bind_method(D_METHOD("get_fov"), &Camera::get_fov);
|
||||
ClassDB::bind_method(D_METHOD("get_frustum_offset"), &Camera::get_frustum_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_size"), &Camera::get_size);
|
||||
ClassDB::bind_method(D_METHOD("get_zfar"), &Camera::get_zfar);
|
||||
ClassDB::bind_method(D_METHOD("get_znear"), &Camera::get_znear);
|
||||
ClassDB::bind_method(D_METHOD("set_fov", "fov"), &Camera::set_fov);
|
||||
ClassDB::bind_method(D_METHOD("set_frustum_offset", "frustum_offset"), &Camera::set_frustum_offset);
|
||||
ClassDB::bind_method(D_METHOD("set_size", "size"), &Camera::set_size);
|
||||
ClassDB::bind_method(D_METHOD("set_zfar", "zfar"), &Camera::set_zfar);
|
||||
ClassDB::bind_method(D_METHOD("set_znear", "znear"), &Camera::set_znear);
|
||||
ClassDB::bind_method(D_METHOD("get_projection"), &Camera::get_projection);
|
||||
ClassDB::bind_method(D_METHOD("set_projection", "projection"), &Camera::set_projection);
|
||||
ClassDB::bind_method(D_METHOD("set_h_offset", "ofs"), &Camera::set_h_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera::get_h_offset);
|
||||
ClassDB::bind_method(D_METHOD("set_v_offset", "ofs"), &Camera::set_v_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_v_offset"), &Camera::get_v_offset);
|
||||
ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Camera::set_cull_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Camera::get_cull_mask);
|
||||
ClassDB::bind_method(D_METHOD("set_environment", "env"), &Camera::set_environment);
|
||||
ClassDB::bind_method(D_METHOD("get_environment"), &Camera::get_environment);
|
||||
ClassDB::bind_method(D_METHOD("set_keep_aspect_mode", "mode"), &Camera::set_keep_aspect_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"), &Camera::get_keep_aspect_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera::set_doppler_tracking);
|
||||
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking);
|
||||
ClassDB::bind_method(D_METHOD("get_frustum"), &Camera::get_frustum);
|
||||
ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera::get_camera);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera::set_cull_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_cull_mask_bit", "layer"), &Camera::get_cull_mask_bit);
|
||||
|
||||
//ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current );
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "keep_aspect", PROPERTY_HINT_ENUM, "Keep Width,Keep Height"), "set_keep_aspect_mode", "get_keep_aspect_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment3D"), "set_environment", "get_environment");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.001"), "set_size", "get_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
|
||||
|
||||
BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
|
||||
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
|
||||
BIND_ENUM_CONSTANT(PROJECTION_FRUSTUM);
|
||||
|
||||
BIND_ENUM_CONSTANT(KEEP_WIDTH);
|
||||
BIND_ENUM_CONSTANT(KEEP_HEIGHT);
|
||||
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED);
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);
|
||||
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);
|
||||
}
|
||||
|
||||
float Camera::get_fov() const {
|
||||
return fov;
|
||||
}
|
||||
|
||||
float Camera::get_size() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
float Camera::get_znear() const {
|
||||
return near;
|
||||
}
|
||||
|
||||
Vector2 Camera::get_frustum_offset() const {
|
||||
return frustum_offset;
|
||||
}
|
||||
|
||||
float Camera::get_zfar() const {
|
||||
return far;
|
||||
}
|
||||
|
||||
Camera::ProjectionMode Camera::get_projection() const {
|
||||
return mode;
|
||||
}
|
||||
|
||||
void Camera::set_fov(float p_fov) {
|
||||
ERR_FAIL_COND(p_fov < 1 || p_fov > 179);
|
||||
fov = p_fov;
|
||||
_update_camera_mode();
|
||||
_change_notify("fov");
|
||||
}
|
||||
|
||||
void Camera::set_size(float p_size) {
|
||||
ERR_FAIL_COND(p_size < 0.001 || p_size > 16384);
|
||||
size = p_size;
|
||||
_update_camera_mode();
|
||||
_change_notify("size");
|
||||
}
|
||||
|
||||
void Camera::set_znear(float p_znear) {
|
||||
near = p_znear;
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
void Camera::set_frustum_offset(Vector2 p_offset) {
|
||||
frustum_offset = p_offset;
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
void Camera::set_zfar(float p_zfar) {
|
||||
far = p_zfar;
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
void Camera::set_cull_mask(uint32_t p_layers) {
|
||||
layers = p_layers;
|
||||
RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers);
|
||||
_update_camera_mode();
|
||||
}
|
||||
|
||||
uint32_t Camera::get_cull_mask() const {
|
||||
return layers;
|
||||
}
|
||||
|
||||
void Camera::set_cull_mask_bit(int p_layer, bool p_enable) {
|
||||
ERR_FAIL_INDEX(p_layer, 32);
|
||||
if (p_enable) {
|
||||
set_cull_mask(layers | (1 << p_layer));
|
||||
} else {
|
||||
set_cull_mask(layers & (~(1 << p_layer)));
|
||||
}
|
||||
}
|
||||
|
||||
bool Camera::get_cull_mask_bit(int p_layer) const {
|
||||
ERR_FAIL_INDEX_V(p_layer, 32, false);
|
||||
return (layers & (1 << p_layer));
|
||||
}
|
||||
|
||||
Vector<Plane> Camera::get_frustum() const {
|
||||
ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>());
|
||||
|
||||
Size2 viewport_size = get_world()->get_visible_rect().size;
|
||||
Projection cm;
|
||||
if (mode == PROJECTION_PERSPECTIVE) {
|
||||
cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
} else {
|
||||
cm.set_orthogonal(size, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH);
|
||||
}
|
||||
|
||||
return cm.get_projection_planes(get_camera_transform());
|
||||
}
|
||||
|
||||
void Camera::set_v_offset(float p_offset) {
|
||||
v_offset = p_offset;
|
||||
_update_camera();
|
||||
}
|
||||
|
||||
float Camera::get_v_offset() const {
|
||||
return v_offset;
|
||||
}
|
||||
|
||||
void Camera::set_h_offset(float p_offset) {
|
||||
h_offset = p_offset;
|
||||
_update_camera();
|
||||
}
|
||||
|
||||
float Camera::get_h_offset() const {
|
||||
return h_offset;
|
||||
}
|
||||
|
||||
Vector3 Camera::get_doppler_tracked_velocity() const {
|
||||
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
|
||||
return velocity_tracker->get_tracked_linear_velocity();
|
||||
} else {
|
||||
return Vector3();
|
||||
}
|
||||
}
|
||||
Camera::Camera() {
|
||||
camera = RID_PRIME(RenderingServer::get_singleton()->camera_create());
|
||||
size = 1;
|
||||
fov = 0;
|
||||
frustum_offset = Vector2();
|
||||
near = 0;
|
||||
far = 0;
|
||||
current = false;
|
||||
world = nullptr;
|
||||
force_change = false;
|
||||
mode = PROJECTION_PERSPECTIVE;
|
||||
set_perspective(70.0, 0.05, 100.0);
|
||||
keep_aspect = KEEP_HEIGHT;
|
||||
layers = 0xfffff;
|
||||
v_offset = 0;
|
||||
h_offset = 0;
|
||||
RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers);
|
||||
//active=false;
|
||||
velocity_tracker.instance();
|
||||
doppler_tracking = DOPPLER_TRACKING_DISABLED;
|
||||
set_notify_transform(true);
|
||||
set_disable_scale(true);
|
||||
}
|
||||
|
||||
Camera::~Camera() {
|
||||
RenderingServer::get_singleton()->free(camera);
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
/*************************************************************************/
|
||||
/* camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class SpatialVelocityTracker;
|
||||
class Viewport;
|
||||
class Environment3D;
|
||||
class World;
|
||||
|
||||
class Camera : public Spatial {
|
||||
GDCLASS(Camera, Spatial);
|
||||
|
||||
public:
|
||||
enum ProjectionMode {
|
||||
|
||||
PROJECTION_PERSPECTIVE,
|
||||
PROJECTION_ORTHOGONAL,
|
||||
PROJECTION_FRUSTUM
|
||||
};
|
||||
|
||||
enum KeepAspect {
|
||||
KEEP_WIDTH,
|
||||
KEEP_HEIGHT
|
||||
};
|
||||
|
||||
enum DopplerTracking {
|
||||
DOPPLER_TRACKING_DISABLED,
|
||||
DOPPLER_TRACKING_IDLE_STEP,
|
||||
DOPPLER_TRACKING_PHYSICS_STEP
|
||||
};
|
||||
|
||||
private:
|
||||
bool force_change;
|
||||
bool current;
|
||||
World *world;
|
||||
|
||||
ProjectionMode mode;
|
||||
|
||||
float fov;
|
||||
float size;
|
||||
Vector2 frustum_offset;
|
||||
float near, far;
|
||||
float v_offset;
|
||||
float h_offset;
|
||||
KeepAspect keep_aspect;
|
||||
|
||||
RID camera;
|
||||
RID scenario_id;
|
||||
|
||||
//String camera_group;
|
||||
|
||||
uint32_t layers;
|
||||
|
||||
Ref<Environment3D> environment;
|
||||
|
||||
//void _camera_make_current(Node *p_camera);
|
||||
friend class Viewport;
|
||||
void _update_audio_listener_state();
|
||||
|
||||
DopplerTracking doppler_tracking;
|
||||
Ref<SpatialVelocityTracker> velocity_tracker;
|
||||
|
||||
protected:
|
||||
void _update_camera();
|
||||
virtual void _request_camera_update();
|
||||
void _update_camera_mode();
|
||||
|
||||
virtual void _physics_interpolated_changed();
|
||||
|
||||
void _notification(int p_what);
|
||||
virtual void _validate_property(PropertyInfo &p_property) const;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
||||
NOTIFICATION_BECAME_CURRENT = 50,
|
||||
NOTIFICATION_LOST_CURRENT = 51
|
||||
};
|
||||
|
||||
void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
|
||||
void set_orthogonal(float p_size, float p_z_near, float p_z_far);
|
||||
void set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
|
||||
void set_projection(Camera::ProjectionMode p_mode);
|
||||
|
||||
void make_current();
|
||||
void clear_current(bool p_enable_next = true);
|
||||
void set_current(bool p_current);
|
||||
bool is_current() const;
|
||||
|
||||
RID get_camera() const;
|
||||
|
||||
float get_fov() const;
|
||||
float get_size() const;
|
||||
float get_zfar() const;
|
||||
float get_znear() const;
|
||||
Vector2 get_frustum_offset() const;
|
||||
|
||||
ProjectionMode get_projection() const;
|
||||
|
||||
void set_fov(float p_fov);
|
||||
void set_size(float p_size);
|
||||
void set_zfar(float p_zfar);
|
||||
void set_znear(float p_znear);
|
||||
void set_frustum_offset(Vector2 p_offset);
|
||||
|
||||
virtual Transform get_camera_transform() const;
|
||||
|
||||
virtual Vector3 project_ray_normal(const Point2 &p_pos) const;
|
||||
virtual Vector3 project_ray_origin(const Point2 &p_pos) const;
|
||||
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
|
||||
virtual Point2 unproject_position(const Vector3 &p_pos) const;
|
||||
bool is_position_behind(const Vector3 &p_pos) const;
|
||||
virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const;
|
||||
|
||||
Vector<Vector3> get_near_plane_points() const;
|
||||
|
||||
void set_cull_mask(uint32_t p_layers);
|
||||
uint32_t get_cull_mask() const;
|
||||
|
||||
void set_cull_mask_bit(int p_layer, bool p_enable);
|
||||
bool get_cull_mask_bit(int p_layer) const;
|
||||
|
||||
virtual Vector<Plane> get_frustum() const;
|
||||
|
||||
void set_environment(const Ref<Environment3D> &p_environment);
|
||||
Ref<Environment3D> get_environment() const;
|
||||
|
||||
void set_keep_aspect_mode(KeepAspect p_aspect);
|
||||
KeepAspect get_keep_aspect_mode() const;
|
||||
|
||||
void set_v_offset(float p_offset);
|
||||
float get_v_offset() const;
|
||||
|
||||
void set_h_offset(float p_offset);
|
||||
float get_h_offset() const;
|
||||
|
||||
void set_doppler_tracking(DopplerTracking p_tracking);
|
||||
DopplerTracking get_doppler_tracking() const;
|
||||
|
||||
Vector3 get_doppler_tracked_velocity() const;
|
||||
|
||||
Camera();
|
||||
~Camera();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Camera::ProjectionMode);
|
||||
VARIANT_ENUM_CAST(Camera::KeepAspect);
|
||||
VARIANT_ENUM_CAST(Camera::DopplerTracking);
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,367 +0,0 @@
|
||||
#ifndef CPU_PARTICLES_H
|
||||
#define CPU_PARTICLES_H
|
||||
/*************************************************************************/
|
||||
/* cpu_particles.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
#include "core/containers/rid.h"
|
||||
#include "core/os/safe_refcount.h"
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
class Curve;
|
||||
class Gradient;
|
||||
|
||||
class CPUParticles : public GeometryInstance {
|
||||
private:
|
||||
GDCLASS(CPUParticles, GeometryInstance);
|
||||
|
||||
public:
|
||||
enum DrawOrder {
|
||||
DRAW_ORDER_INDEX,
|
||||
DRAW_ORDER_LIFETIME,
|
||||
DRAW_ORDER_VIEW_DEPTH,
|
||||
DRAW_ORDER_MAX
|
||||
};
|
||||
|
||||
enum Parameter {
|
||||
|
||||
PARAM_INITIAL_LINEAR_VELOCITY,
|
||||
PARAM_ANGULAR_VELOCITY,
|
||||
PARAM_ORBIT_VELOCITY,
|
||||
PARAM_LINEAR_ACCEL,
|
||||
PARAM_RADIAL_ACCEL,
|
||||
PARAM_TANGENTIAL_ACCEL,
|
||||
PARAM_DAMPING,
|
||||
PARAM_ANGLE,
|
||||
PARAM_SCALE,
|
||||
PARAM_HUE_VARIATION,
|
||||
PARAM_ANIM_SPEED,
|
||||
PARAM_ANIM_OFFSET,
|
||||
PARAM_MAX
|
||||
};
|
||||
|
||||
enum Flags {
|
||||
FLAG_ALIGN_Y_TO_VELOCITY,
|
||||
FLAG_ROTATE_Y,
|
||||
FLAG_DISABLE_Z,
|
||||
FLAG_MAX
|
||||
};
|
||||
|
||||
enum EmissionShape {
|
||||
EMISSION_SHAPE_POINT,
|
||||
EMISSION_SHAPE_SPHERE,
|
||||
EMISSION_SHAPE_BOX,
|
||||
EMISSION_SHAPE_POINTS,
|
||||
EMISSION_SHAPE_DIRECTED_POINTS,
|
||||
EMISSION_SHAPE_RING,
|
||||
EMISSION_SHAPE_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
bool emitting;
|
||||
|
||||
// Previous minimal data for the particle,
|
||||
// for interpolation.
|
||||
struct ParticleBase {
|
||||
void blank() {
|
||||
for (int n = 0; n < 4; n++) {
|
||||
custom[n] = 0.0;
|
||||
}
|
||||
}
|
||||
Transform transform;
|
||||
Color color;
|
||||
float custom[4];
|
||||
};
|
||||
|
||||
struct Particle : public ParticleBase {
|
||||
void copy_to(ParticleBase &r_o) {
|
||||
r_o.transform = transform;
|
||||
r_o.color = color;
|
||||
memcpy(r_o.custom, custom, sizeof(custom));
|
||||
}
|
||||
Vector3 velocity;
|
||||
bool active;
|
||||
float angle_rand;
|
||||
float scale_rand;
|
||||
float hue_rot_rand;
|
||||
float anim_offset_rand;
|
||||
Color start_color_rand;
|
||||
float time;
|
||||
float lifetime;
|
||||
Color base_color;
|
||||
|
||||
uint32_t seed;
|
||||
};
|
||||
|
||||
float time;
|
||||
float inactive_time;
|
||||
float frame_remainder;
|
||||
int cycle;
|
||||
bool redraw;
|
||||
|
||||
RID multimesh;
|
||||
|
||||
PoolVector<Particle> particles;
|
||||
LocalVector<ParticleBase> particles_prev;
|
||||
PoolVector<float> particle_data;
|
||||
PoolVector<float> particle_data_prev;
|
||||
PoolVector<int> particle_order;
|
||||
|
||||
struct SortLifetime {
|
||||
const Particle *particles;
|
||||
|
||||
bool operator()(int p_a, int p_b) const {
|
||||
return particles[p_a].time > particles[p_b].time;
|
||||
}
|
||||
};
|
||||
|
||||
struct SortAxis {
|
||||
const Particle *particles;
|
||||
Vector3 axis;
|
||||
bool operator()(int p_a, int p_b) const {
|
||||
return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
bool one_shot;
|
||||
|
||||
float lifetime;
|
||||
float pre_process_time;
|
||||
float explosiveness_ratio;
|
||||
float randomness_ratio;
|
||||
float lifetime_randomness;
|
||||
float speed_scale;
|
||||
bool local_coords;
|
||||
int fixed_fps;
|
||||
bool fractional_delta;
|
||||
|
||||
SafeFlag can_update;
|
||||
|
||||
DrawOrder draw_order;
|
||||
|
||||
Ref<Mesh> mesh;
|
||||
|
||||
////////
|
||||
|
||||
Vector3 direction;
|
||||
float spread;
|
||||
float flatness;
|
||||
|
||||
float parameters[PARAM_MAX];
|
||||
float randomness[PARAM_MAX];
|
||||
|
||||
Ref<Curve> curve_parameters[PARAM_MAX];
|
||||
Color color;
|
||||
Ref<Gradient> color_ramp;
|
||||
Ref<Gradient> color_initial_ramp;
|
||||
|
||||
bool flags[FLAG_MAX];
|
||||
|
||||
EmissionShape emission_shape;
|
||||
float emission_sphere_radius;
|
||||
Vector3 emission_box_extents;
|
||||
PoolVector<Vector3> emission_points;
|
||||
PoolVector<Vector3> emission_normals;
|
||||
PoolVector<Color> emission_colors;
|
||||
int emission_point_count;
|
||||
float emission_ring_height;
|
||||
float emission_ring_inner_radius;
|
||||
float emission_ring_radius;
|
||||
Vector3 emission_ring_axis;
|
||||
|
||||
Vector3 gravity;
|
||||
|
||||
void _update_internal(bool p_on_physics_tick);
|
||||
void _particles_process(float p_delta);
|
||||
void _particle_process(Particle &r_p, const Transform &p_emission_xform, float p_local_delta, float &r_tv);
|
||||
void _update_particle_data_buffer();
|
||||
|
||||
Mutex update_mutex;
|
||||
bool _interpolated = false;
|
||||
|
||||
// Hard coded to true for now, if we decide after testing to always enable this
|
||||
// when using interpolation we can remove the variable, else we can expose to the UI.
|
||||
bool _streaky = true;
|
||||
|
||||
void _update_render_thread();
|
||||
|
||||
void _set_redraw(bool p_redraw);
|
||||
void _set_particles_processing(bool p_enable);
|
||||
void _refresh_interpolation_state();
|
||||
|
||||
void _fill_particle_data(const ParticleBase &p_source, float *r_dest, bool p_active) const {
|
||||
const Transform &t = p_source.transform;
|
||||
|
||||
if (p_active) {
|
||||
r_dest[0] = t.basis.rows[0][0];
|
||||
r_dest[1] = t.basis.rows[0][1];
|
||||
r_dest[2] = t.basis.rows[0][2];
|
||||
r_dest[3] = t.origin.x;
|
||||
r_dest[4] = t.basis.rows[1][0];
|
||||
r_dest[5] = t.basis.rows[1][1];
|
||||
r_dest[6] = t.basis.rows[1][2];
|
||||
r_dest[7] = t.origin.y;
|
||||
r_dest[8] = t.basis.rows[2][0];
|
||||
r_dest[9] = t.basis.rows[2][1];
|
||||
r_dest[10] = t.basis.rows[2][2];
|
||||
r_dest[11] = t.origin.z;
|
||||
} else {
|
||||
memset(r_dest, 0, sizeof(float) * 12);
|
||||
}
|
||||
|
||||
Color c = p_source.color;
|
||||
uint8_t *data8 = (uint8_t *)&r_dest[12];
|
||||
data8[0] = CLAMP(c.r * 255.0, 0, 255);
|
||||
data8[1] = CLAMP(c.g * 255.0, 0, 255);
|
||||
data8[2] = CLAMP(c.b * 255.0, 0, 255);
|
||||
data8[3] = CLAMP(c.a * 255.0, 0, 255);
|
||||
|
||||
r_dest[13] = p_source.custom[0];
|
||||
r_dest[14] = p_source.custom[1];
|
||||
r_dest[15] = p_source.custom[2];
|
||||
r_dest[16] = p_source.custom[3];
|
||||
}
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
AABB get_aabb() const;
|
||||
PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_emitting(bool p_emitting);
|
||||
void set_amount(int p_amount);
|
||||
void set_lifetime(float p_lifetime);
|
||||
void set_one_shot(bool p_one_shot);
|
||||
void set_pre_process_time(float p_time);
|
||||
void set_explosiveness_ratio(float p_ratio);
|
||||
void set_randomness_ratio(float p_ratio);
|
||||
void set_lifetime_randomness(float p_random);
|
||||
void set_use_local_coordinates(bool p_enable);
|
||||
void set_speed_scale(float p_scale);
|
||||
|
||||
bool is_emitting() const;
|
||||
int get_amount() const;
|
||||
float get_lifetime() const;
|
||||
bool get_one_shot() const;
|
||||
float get_pre_process_time() const;
|
||||
float get_explosiveness_ratio() const;
|
||||
float get_randomness_ratio() const;
|
||||
float get_lifetime_randomness() const;
|
||||
bool get_use_local_coordinates() const;
|
||||
float get_speed_scale() const;
|
||||
|
||||
void set_fixed_fps(int p_count);
|
||||
int get_fixed_fps() const;
|
||||
|
||||
void set_fractional_delta(bool p_enable);
|
||||
bool get_fractional_delta() const;
|
||||
|
||||
void set_draw_order(DrawOrder p_order);
|
||||
DrawOrder get_draw_order() const;
|
||||
|
||||
void set_mesh(const Ref<Mesh> &p_mesh);
|
||||
Ref<Mesh> get_mesh() const;
|
||||
|
||||
///////////////////
|
||||
|
||||
void set_direction(Vector3 p_direction);
|
||||
Vector3 get_direction() const;
|
||||
|
||||
void set_spread(float p_spread);
|
||||
float get_spread() const;
|
||||
|
||||
void set_flatness(float p_flatness);
|
||||
float get_flatness() const;
|
||||
|
||||
void set_param(Parameter p_param, float p_value);
|
||||
float get_param(Parameter p_param) const;
|
||||
|
||||
void set_param_randomness(Parameter p_param, float p_value);
|
||||
float get_param_randomness(Parameter p_param) const;
|
||||
|
||||
void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve);
|
||||
Ref<Curve> get_param_curve(Parameter p_param) const;
|
||||
|
||||
void set_color(const Color &p_color);
|
||||
Color get_color() const;
|
||||
|
||||
void set_color_ramp(const Ref<Gradient> &p_ramp);
|
||||
Ref<Gradient> get_color_ramp() const;
|
||||
|
||||
void set_color_initial_ramp(const Ref<Gradient> &p_ramp);
|
||||
Ref<Gradient> get_color_initial_ramp() const;
|
||||
|
||||
void set_particle_flag(Flags p_flag, bool p_enable);
|
||||
bool get_particle_flag(Flags p_flag) const;
|
||||
|
||||
void set_emission_shape(EmissionShape p_shape);
|
||||
void set_emission_sphere_radius(float p_radius);
|
||||
void set_emission_box_extents(Vector3 p_extents);
|
||||
void set_emission_points(const PoolVector<Vector3> &p_points);
|
||||
void set_emission_normals(const PoolVector<Vector3> &p_normals);
|
||||
void set_emission_colors(const PoolVector<Color> &p_colors);
|
||||
void set_emission_ring_height(float p_height);
|
||||
void set_emission_ring_inner_radius(float p_inner_radius);
|
||||
void set_emission_ring_radius(float p_radius);
|
||||
void set_emission_ring_axis(Vector3 p_axis);
|
||||
|
||||
EmissionShape get_emission_shape() const;
|
||||
float get_emission_sphere_radius() const;
|
||||
Vector3 get_emission_box_extents() const;
|
||||
PoolVector<Vector3> get_emission_points() const;
|
||||
PoolVector<Vector3> get_emission_normals() const;
|
||||
PoolVector<Color> get_emission_colors() const;
|
||||
float get_emission_ring_height() const;
|
||||
float get_emission_ring_inner_radius() const;
|
||||
float get_emission_ring_radius() const;
|
||||
Vector3 get_emission_ring_axis() const;
|
||||
|
||||
void set_gravity(const Vector3 &p_gravity);
|
||||
Vector3 get_gravity() const;
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
void restart();
|
||||
|
||||
CPUParticles();
|
||||
~CPUParticles();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(CPUParticles::DrawOrder)
|
||||
VARIANT_ENUM_CAST(CPUParticles::Parameter)
|
||||
VARIANT_ENUM_CAST(CPUParticles::Flags)
|
||||
VARIANT_ENUM_CAST(CPUParticles::EmissionShape)
|
||||
|
||||
#endif // CPU_PARTICLES_H
|
@ -1,76 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* cull_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "cull_instance.h"
|
||||
|
||||
VARIANT_ENUM_CAST(CullInstance::PortalMode);
|
||||
|
||||
void CullInstance::set_portal_mode(CullInstance::PortalMode p_mode) {
|
||||
_portal_mode = p_mode;
|
||||
_refresh_portal_mode();
|
||||
}
|
||||
|
||||
CullInstance::PortalMode CullInstance::get_portal_mode() const {
|
||||
return _portal_mode;
|
||||
}
|
||||
|
||||
void CullInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_portal_mode", "mode"), &CullInstance::set_portal_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_portal_mode"), &CullInstance::get_portal_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_include_in_bound", "enabled"), &CullInstance::set_include_in_bound);
|
||||
ClassDB::bind_method(D_METHOD("get_include_in_bound"), &CullInstance::get_include_in_bound);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_allow_merging", "enabled"), &CullInstance::set_allow_merging);
|
||||
ClassDB::bind_method(D_METHOD("get_allow_merging"), &CullInstance::get_allow_merging);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_portal_autoplace_priority", "priority"), &CullInstance::set_portal_autoplace_priority);
|
||||
ClassDB::bind_method(D_METHOD("get_portal_autoplace_priority"), &CullInstance::get_portal_autoplace_priority);
|
||||
|
||||
ADD_GROUP("Portals", "");
|
||||
|
||||
BIND_ENUM_CONSTANT(PORTAL_MODE_STATIC);
|
||||
BIND_ENUM_CONSTANT(PORTAL_MODE_DYNAMIC);
|
||||
BIND_ENUM_CONSTANT(PORTAL_MODE_ROAMING);
|
||||
BIND_ENUM_CONSTANT(PORTAL_MODE_GLOBAL);
|
||||
BIND_ENUM_CONSTANT(PORTAL_MODE_IGNORE);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "portal_mode", PROPERTY_HINT_ENUM, "Static,Dynamic,Roaming,Global,Ignore"), "set_portal_mode", "get_portal_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_in_bound"), "set_include_in_bound", "get_include_in_bound");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_merging"), "set_allow_merging", "get_allow_merging");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "autoplace_priority", PROPERTY_HINT_RANGE, "-16,16,1", PROPERTY_USAGE_DEFAULT), "set_portal_autoplace_priority", "get_portal_autoplace_priority");
|
||||
}
|
||||
|
||||
CullInstance::CullInstance() {
|
||||
_portal_mode = PORTAL_MODE_STATIC;
|
||||
_include_in_bound = true;
|
||||
_allow_merging = true;
|
||||
_portal_autoplace_priority = 0;
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
#ifndef CULL_INSTANCE_H
|
||||
#define CULL_INSTANCE_H
|
||||
/*************************************************************************/
|
||||
/* cull_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class CullInstance : public Spatial {
|
||||
GDCLASS(CullInstance, Spatial);
|
||||
|
||||
public:
|
||||
enum PortalMode {
|
||||
PORTAL_MODE_STATIC, // not moving within a room
|
||||
PORTAL_MODE_DYNAMIC, // moving within room
|
||||
PORTAL_MODE_ROAMING, // moving between rooms
|
||||
PORTAL_MODE_GLOBAL, // frustum culled only
|
||||
PORTAL_MODE_IGNORE, // don't show at all - e.g. manual bounds, hidden portals
|
||||
};
|
||||
|
||||
void set_portal_mode(CullInstance::PortalMode p_mode);
|
||||
CullInstance::PortalMode get_portal_mode() const;
|
||||
|
||||
void set_include_in_bound(bool p_enabled) { _include_in_bound = p_enabled; }
|
||||
bool get_include_in_bound() const { return _include_in_bound; }
|
||||
|
||||
void set_allow_merging(bool p_enabled) { _allow_merging = p_enabled; }
|
||||
bool get_allow_merging() const { return _allow_merging; }
|
||||
|
||||
void set_portal_autoplace_priority(int p_priority) { _portal_autoplace_priority = p_priority; }
|
||||
int get_portal_autoplace_priority() const { return _portal_autoplace_priority; }
|
||||
|
||||
CullInstance();
|
||||
|
||||
protected:
|
||||
virtual void _refresh_portal_mode() = 0;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
PortalMode _portal_mode;
|
||||
bool _include_in_bound : 1;
|
||||
bool _allow_merging : 1;
|
||||
|
||||
// Allows instances to prefer to be autoplaced
|
||||
// in specific RoomGroups. This allows building exteriors
|
||||
// to be autoplaced in outside RoomGroups, allowing a complete
|
||||
// exterior / interior of building in one reusable Scene.
|
||||
// The default value 0 gives no preference (chooses the highest priority).
|
||||
// All other values will autoplace in the selected RoomGroup priority by preference.
|
||||
int _portal_autoplace_priority;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,154 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* immediate_geometry.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "immediate_geometry.h"
|
||||
|
||||
void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture> &p_texture) {
|
||||
RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID());
|
||||
if (p_texture.is_valid()) {
|
||||
cached_textures.push_back(p_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void ImmediateGeometry::set_normal(const Vector3 &p_normal) {
|
||||
RS::get_singleton()->immediate_normal(im, p_normal);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::set_tangent(const Plane &p_tangent) {
|
||||
RS::get_singleton()->immediate_tangent(im, p_tangent);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::set_color(const Color &p_color) {
|
||||
RS::get_singleton()->immediate_color(im, p_color);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::set_uv(const Vector2 &p_uv) {
|
||||
RS::get_singleton()->immediate_uv(im, p_uv);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::set_uv2(const Vector2 &p_uv2) {
|
||||
RS::get_singleton()->immediate_uv2(im, p_uv2);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::add_vertex(const Vector3 &p_vertex) {
|
||||
RS::get_singleton()->immediate_vertex(im, p_vertex);
|
||||
if (empty) {
|
||||
aabb.position = p_vertex;
|
||||
aabb.size = Vector3();
|
||||
empty = false;
|
||||
} else {
|
||||
aabb.expand_to(p_vertex);
|
||||
}
|
||||
}
|
||||
|
||||
void ImmediateGeometry::end() {
|
||||
RS::get_singleton()->immediate_end(im);
|
||||
}
|
||||
|
||||
void ImmediateGeometry::clear() {
|
||||
RS::get_singleton()->immediate_clear(im);
|
||||
empty = true;
|
||||
cached_textures.clear();
|
||||
}
|
||||
|
||||
AABB ImmediateGeometry::get_aabb() const {
|
||||
return aabb;
|
||||
}
|
||||
PoolVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) {
|
||||
for (int i = 1; i <= p_lats; i++) {
|
||||
double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats);
|
||||
double z0 = Math::sin(lat0);
|
||||
double zr0 = Math::cos(lat0);
|
||||
|
||||
double lat1 = Math_PI * (-0.5 + (double)i / p_lats);
|
||||
double z1 = Math::sin(lat1);
|
||||
double zr1 = Math::cos(lat1);
|
||||
|
||||
for (int j = p_lons; j >= 1; j--) {
|
||||
double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons;
|
||||
double x0 = Math::cos(lng0);
|
||||
double y0 = Math::sin(lng0);
|
||||
|
||||
double lng1 = 2 * Math_PI * (double)(j) / p_lons;
|
||||
double x1 = Math::cos(lng1);
|
||||
double y1 = Math::sin(lng1);
|
||||
|
||||
Vector3 v[4] = {
|
||||
Vector3(x1 * zr0, z0, y1 * zr0),
|
||||
Vector3(x1 * zr1, z1, y1 * zr1),
|
||||
Vector3(x0 * zr1, z1, y0 * zr1),
|
||||
Vector3(x0 * zr0, z0, y0 * zr0)
|
||||
};
|
||||
|
||||
#define ADD_POINT(m_idx) \
|
||||
if (p_add_uv) { \
|
||||
set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \
|
||||
set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \
|
||||
} \
|
||||
set_normal(v[m_idx]); \
|
||||
add_vertex(v[m_idx] * p_radius);
|
||||
|
||||
ADD_POINT(0);
|
||||
ADD_POINT(1);
|
||||
ADD_POINT(2);
|
||||
|
||||
ADD_POINT(2);
|
||||
ADD_POINT(3);
|
||||
ADD_POINT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImmediateGeometry::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry::begin, DEFVAL(Ref<Texture>()));
|
||||
ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry::set_normal);
|
||||
ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry::set_tangent);
|
||||
ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry::set_color);
|
||||
ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry::set_uv);
|
||||
ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry::set_uv2);
|
||||
ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry::add_vertex);
|
||||
ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry::add_sphere, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry::end);
|
||||
ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry::clear);
|
||||
}
|
||||
|
||||
ImmediateGeometry::ImmediateGeometry() {
|
||||
im = RID_PRIME(RenderingServer::get_singleton()->immediate_create());
|
||||
set_base(im);
|
||||
empty = true;
|
||||
}
|
||||
|
||||
ImmediateGeometry::~ImmediateGeometry() {
|
||||
RenderingServer::get_singleton()->free(im);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
#ifndef IMMEDIATE_GEOMETRY_H
|
||||
#define IMMEDIATE_GEOMETRY_H
|
||||
/*************************************************************************/
|
||||
/* immediate_geometry.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
|
||||
class Texture;
|
||||
|
||||
class ImmediateGeometry : public GeometryInstance {
|
||||
GDCLASS(ImmediateGeometry, GeometryInstance);
|
||||
|
||||
RID im;
|
||||
//a list of textures drawn need to be kept, to avoid references
|
||||
// in RenderingServer from becoming invalid if the texture is no longer used
|
||||
List<Ref<Texture>> cached_textures;
|
||||
bool empty;
|
||||
AABB aabb;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture> &p_texture = Ref<Texture>());
|
||||
void set_normal(const Vector3 &p_normal);
|
||||
void set_tangent(const Plane &p_tangent);
|
||||
void set_color(const Color &p_color);
|
||||
void set_uv(const Vector2 &p_uv);
|
||||
void set_uv2(const Vector2 &p_uv2);
|
||||
|
||||
void add_vertex(const Vector3 &p_vertex);
|
||||
|
||||
void end();
|
||||
void clear();
|
||||
|
||||
void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true);
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
ImmediateGeometry();
|
||||
~ImmediateGeometry();
|
||||
};
|
||||
|
||||
#endif // IMMEDIATE_GEOMETRY_H
|
@ -1,92 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* importer_mesh_instance_3d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "importer_mesh_instance_3d.h"
|
||||
|
||||
#include "scene/resources/mesh/importer_mesh.h"
|
||||
|
||||
void ImporterMeshInstance3D::set_mesh(const Ref<ImporterMesh> &p_mesh) {
|
||||
mesh = p_mesh;
|
||||
}
|
||||
Ref<ImporterMesh> ImporterMeshInstance3D::get_mesh() const {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
void ImporterMeshInstance3D::set_skin(const Ref<Skin> &p_skin) {
|
||||
skin = p_skin;
|
||||
}
|
||||
Ref<Skin> ImporterMeshInstance3D::get_skin() const {
|
||||
return skin;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImporterMeshInstance3D::set_surface_material(int p_idx, const Ref<Material> &p_material) {
|
||||
ERR_FAIL_COND(p_idx < 0);
|
||||
if (p_idx >= surface_materials.size()) {
|
||||
surface_materials.resize(p_idx + 1);
|
||||
}
|
||||
|
||||
surface_materials.write[p_idx] = p_material;
|
||||
}
|
||||
Ref<Material> ImporterMeshInstance3D::get_surface_material(int p_idx) const {
|
||||
ERR_FAIL_COND_V(p_idx < 0, Ref<Material>());
|
||||
if (p_idx >= surface_materials.size()) {
|
||||
return Ref<Material>();
|
||||
}
|
||||
return surface_materials[p_idx];
|
||||
}
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
void ImporterMeshInstance3D::set_skeleton_path(const NodePath &p_path) {
|
||||
skeleton_path = p_path;
|
||||
}
|
||||
NodePath ImporterMeshInstance3D::get_skeleton_path() const {
|
||||
return skeleton_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImporterMeshInstance3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &ImporterMeshInstance3D::set_mesh);
|
||||
ClassDB::bind_method(D_METHOD("get_mesh"), &ImporterMeshInstance3D::get_mesh);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "ImporterMesh"), "set_mesh", "get_mesh");
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
ClassDB::bind_method(D_METHOD("set_skin", "skin"), &ImporterMeshInstance3D::set_skin);
|
||||
ClassDB::bind_method(D_METHOD("get_skin"), &ImporterMeshInstance3D::get_skin);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "skin", PROPERTY_HINT_RESOURCE_TYPE, "Skin"), "set_skin", "get_skin");
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path"), &ImporterMeshInstance3D::set_skeleton_path);
|
||||
ClassDB::bind_method(D_METHOD("get_skeleton_path"), &ImporterMeshInstance3D::get_skeleton_path);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton"), "set_skeleton_path", "get_skeleton_path");
|
||||
#endif
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* importer_mesh_instance_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef IMPORTER_MESH_INSTANCE_3D_H
|
||||
#define IMPORTER_MESH_INSTANCE_3D_H
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
#include "modules/skeleton_3d/resources/skin.h"
|
||||
#endif
|
||||
|
||||
class ImporterMesh;
|
||||
|
||||
class ImporterMeshInstance3D : public Spatial {
|
||||
GDCLASS(ImporterMeshInstance3D, Spatial)
|
||||
|
||||
Ref<ImporterMesh> mesh;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
Ref<Skin> skin;
|
||||
NodePath skeleton_path;
|
||||
#endif
|
||||
Vector<Ref<Material>> surface_materials;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_mesh(const Ref<ImporterMesh> &p_mesh);
|
||||
Ref<ImporterMesh> get_mesh() const;
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
void set_skin(const Ref<Skin> &p_skin);
|
||||
Ref<Skin> get_skin() const;
|
||||
#endif
|
||||
|
||||
void set_surface_material(int p_idx, const Ref<Material> &p_material);
|
||||
Ref<Material> get_surface_material(int p_idx) const;
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
void set_skeleton_path(const NodePath &p_path);
|
||||
NodePath get_skeleton_path() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // IMPORTER_MESH_INSTANCE_3D_H
|
@ -1,166 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* interpolated_camera.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "interpolated_camera.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
|
||||
void InterpolatedCamera::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
_update_process_mode();
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
if (!enabled) {
|
||||
break;
|
||||
}
|
||||
if (has_node(target)) {
|
||||
Spatial *node = Object::cast_to<Spatial>(get_node(target));
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
float delta = speed * (process_mode == INTERPOLATED_CAMERA_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
|
||||
Transform target_xform = node->get_global_transform();
|
||||
Transform local_transform = get_global_transform();
|
||||
local_transform = local_transform.interpolate_with(target_xform, delta);
|
||||
set_global_transform(local_transform);
|
||||
Camera *cam = Object::cast_to<Camera>(node);
|
||||
if (cam) {
|
||||
if (cam->get_projection() == get_projection()) {
|
||||
float new_near = Math::lerp(get_znear(), cam->get_znear(), delta);
|
||||
float new_far = Math::lerp(get_zfar(), cam->get_zfar(), delta);
|
||||
|
||||
if (cam->get_projection() == PROJECTION_ORTHOGONAL) {
|
||||
float size = Math::lerp(get_size(), cam->get_size(), delta);
|
||||
set_orthogonal(size, new_near, new_far);
|
||||
} else {
|
||||
float fov = Math::lerp(get_fov(), cam->get_fov(), delta);
|
||||
set_perspective(fov, new_near, new_far);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_process_mode(InterpolatedCameraProcessMode p_mode) {
|
||||
if (process_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
process_mode = p_mode;
|
||||
_update_process_mode();
|
||||
}
|
||||
|
||||
InterpolatedCamera::InterpolatedCameraProcessMode InterpolatedCamera::get_process_mode() const {
|
||||
return process_mode;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::_set_target(const Object *p_target) {
|
||||
ERR_FAIL_NULL(p_target);
|
||||
set_target(Object::cast_to<Spatial>(p_target));
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_target(const Spatial *p_target) {
|
||||
ERR_FAIL_NULL(p_target);
|
||||
target = get_path_to(p_target);
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_target_path(const NodePath &p_path) {
|
||||
target = p_path;
|
||||
}
|
||||
|
||||
NodePath InterpolatedCamera::get_target_path() const {
|
||||
return target;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_interpolation_enabled(bool p_enable) {
|
||||
if (enabled == p_enable) {
|
||||
return;
|
||||
}
|
||||
enabled = p_enable;
|
||||
_update_process_mode();
|
||||
}
|
||||
|
||||
void InterpolatedCamera::_update_process_mode() {
|
||||
if (Engine::get_singleton()->is_editor_hint() || !enabled) {
|
||||
set_process_internal(false);
|
||||
set_physics_process_internal(false);
|
||||
} else if (process_mode == INTERPOLATED_CAMERA_PROCESS_IDLE) {
|
||||
set_process_internal(true);
|
||||
set_physics_process_internal(false);
|
||||
} else {
|
||||
set_process_internal(false);
|
||||
set_physics_process_internal(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool InterpolatedCamera::is_interpolation_enabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::set_speed(real_t p_speed) {
|
||||
speed = p_speed;
|
||||
}
|
||||
|
||||
real_t InterpolatedCamera::get_speed() const {
|
||||
return speed;
|
||||
}
|
||||
|
||||
void InterpolatedCamera::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_target_path", "target_path"), &InterpolatedCamera::set_target_path);
|
||||
ClassDB::bind_method(D_METHOD("get_target_path"), &InterpolatedCamera::get_target_path);
|
||||
ClassDB::bind_method(D_METHOD("set_target", "target"), &InterpolatedCamera::_set_target);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_speed", "speed"), &InterpolatedCamera::set_speed);
|
||||
ClassDB::bind_method(D_METHOD("get_speed"), &InterpolatedCamera::get_speed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interpolation_enabled", "target_path"), &InterpolatedCamera::set_interpolation_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_interpolation_enabled"), &InterpolatedCamera::is_interpolation_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &InterpolatedCamera::set_process_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_process_mode"), &InterpolatedCamera::get_process_mode);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target"), "set_target_path", "get_target_path");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed"), "set_speed", "get_speed");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_interpolation_enabled", "is_interpolation_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
|
||||
|
||||
BIND_ENUM_CONSTANT(INTERPOLATED_CAMERA_PROCESS_PHYSICS);
|
||||
BIND_ENUM_CONSTANT(INTERPOLATED_CAMERA_PROCESS_IDLE);
|
||||
}
|
||||
|
||||
InterpolatedCamera::InterpolatedCamera() {
|
||||
enabled = false;
|
||||
speed = 1;
|
||||
process_mode = INTERPOLATED_CAMERA_PROCESS_IDLE;
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
#ifndef INTERPOLATED_CAMERA_H
|
||||
#define INTERPOLATED_CAMERA_H
|
||||
/*************************************************************************/
|
||||
/* interpolated_camera.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/camera.h"
|
||||
|
||||
class InterpolatedCamera : public Camera {
|
||||
GDCLASS(InterpolatedCamera, Camera);
|
||||
|
||||
public:
|
||||
enum InterpolatedCameraProcessMode {
|
||||
INTERPOLATED_CAMERA_PROCESS_PHYSICS,
|
||||
INTERPOLATED_CAMERA_PROCESS_IDLE
|
||||
};
|
||||
|
||||
private:
|
||||
bool enabled;
|
||||
real_t speed;
|
||||
NodePath target;
|
||||
InterpolatedCameraProcessMode process_mode;
|
||||
|
||||
void _update_process_mode();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
void _set_target(const Object *p_target);
|
||||
|
||||
public:
|
||||
void set_target(const Spatial *p_target);
|
||||
void set_target_path(const NodePath &p_path);
|
||||
NodePath get_target_path() const;
|
||||
|
||||
void set_speed(real_t p_speed);
|
||||
real_t get_speed() const;
|
||||
|
||||
void set_interpolation_enabled(bool p_enable);
|
||||
bool is_interpolation_enabled() const;
|
||||
|
||||
void set_process_mode(InterpolatedCameraProcessMode p_mode);
|
||||
InterpolatedCameraProcessMode get_process_mode() const;
|
||||
|
||||
InterpolatedCamera();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(InterpolatedCamera::InterpolatedCameraProcessMode);
|
||||
|
||||
#endif // INTERPOLATED_CAMERA_H
|
File diff suppressed because it is too large
Load Diff
@ -1,256 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* label_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef LABEL_3D_H
|
||||
#define LABEL_3D_H
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/font/font.h"
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
|
||||
class TriangleMesh;
|
||||
|
||||
class Label3D : public GeometryInstance {
|
||||
GDCLASS(Label3D, GeometryInstance);
|
||||
|
||||
public:
|
||||
enum DrawFlags {
|
||||
FLAG_SHADED,
|
||||
FLAG_DOUBLE_SIDED,
|
||||
FLAG_DISABLE_DEPTH_TEST,
|
||||
FLAG_FIXED_SIZE,
|
||||
FLAG_MAX
|
||||
};
|
||||
|
||||
enum AlphaCutMode {
|
||||
ALPHA_CUT_DISABLED,
|
||||
ALPHA_CUT_DISCARD,
|
||||
ALPHA_CUT_OPAQUE_PREPASS
|
||||
};
|
||||
|
||||
enum Align {
|
||||
|
||||
ALIGN_LEFT,
|
||||
ALIGN_CENTER,
|
||||
ALIGN_RIGHT,
|
||||
ALIGN_FILL
|
||||
};
|
||||
|
||||
enum VAlign {
|
||||
|
||||
VALIGN_TOP,
|
||||
VALIGN_CENTER,
|
||||
VALIGN_BOTTOM,
|
||||
VALIGN_FILL
|
||||
};
|
||||
|
||||
private:
|
||||
real_t pixel_size = 0.01;
|
||||
bool flags[FLAG_MAX] = {};
|
||||
AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
|
||||
float alpha_scissor_threshold = 0.5;
|
||||
|
||||
AABB aabb;
|
||||
|
||||
mutable Ref<TriangleMesh> triangle_mesh;
|
||||
RID mesh;
|
||||
|
||||
struct SurfaceData {
|
||||
PoolVector3Array mesh_vertices;
|
||||
PoolVector3Array mesh_normals;
|
||||
PoolRealArray mesh_tangents;
|
||||
PoolColorArray mesh_colors;
|
||||
PoolVector2Array mesh_uvs;
|
||||
PoolIntArray indices;
|
||||
int offset = 0;
|
||||
float z_shift = 0.0;
|
||||
RID material;
|
||||
};
|
||||
|
||||
struct SurfaceKey {
|
||||
uint64_t texture_id;
|
||||
int32_t priority;
|
||||
|
||||
bool operator==(const SurfaceKey &p_b) const {
|
||||
return (texture_id == p_b.texture_id) && (priority == p_b.priority);
|
||||
}
|
||||
|
||||
SurfaceKey(uint64_t p_texture_id, int p_priority) {
|
||||
texture_id = p_texture_id;
|
||||
priority = p_priority;
|
||||
}
|
||||
};
|
||||
|
||||
struct SurfaceKeyHasher {
|
||||
_FORCE_INLINE_ static uint32_t hash(const SurfaceKey &p_a) {
|
||||
uint32_t hash = hash_djb2_one_32(p_a.texture_id);
|
||||
return hash_djb2_one_32(p_a.priority, hash);
|
||||
}
|
||||
};
|
||||
|
||||
HashMap<SurfaceKey, SurfaceData, SurfaceKeyHasher> surfaces;
|
||||
|
||||
struct WordCache {
|
||||
enum {
|
||||
CHAR_NEWLINE = -1,
|
||||
CHAR_WRAPLINE = -2
|
||||
};
|
||||
int char_pos; // if -1, then newline
|
||||
int word_len;
|
||||
int pixel_width;
|
||||
int space_count;
|
||||
WordCache *next;
|
||||
WordCache() {
|
||||
char_pos = 0;
|
||||
word_len = 0;
|
||||
pixel_width = 0;
|
||||
next = nullptr;
|
||||
space_count = 0;
|
||||
}
|
||||
};
|
||||
bool word_cache_dirty = true;
|
||||
|
||||
WordCache *word_cache = nullptr;
|
||||
int line_count = 0;
|
||||
|
||||
Align horizontal_alignment = ALIGN_CENTER;
|
||||
VAlign vertical_alignment = VALIGN_CENTER;
|
||||
String text;
|
||||
String xl_text;
|
||||
bool uppercase = false;
|
||||
|
||||
bool autowrap = false;
|
||||
float width = 500.0;
|
||||
|
||||
Ref<Font> font_override;
|
||||
mutable Ref<Font> theme_font;
|
||||
Color modulate = Color(1, 1, 1, 1);
|
||||
Point2 lbl_offset;
|
||||
int outline_render_priority = -1;
|
||||
int render_priority = 0;
|
||||
|
||||
Color outline_modulate = Color(0, 0, 0, 1);
|
||||
|
||||
float line_spacing = 0.f;
|
||||
|
||||
RID base_material;
|
||||
SpatialMaterial::BillboardMode billboard_mode = SpatialMaterial::BILLBOARD_DISABLED;
|
||||
|
||||
bool pending_update = false;
|
||||
|
||||
void regenerate_word_cache();
|
||||
int get_longest_line_width() const;
|
||||
float _generate_glyph_surfaces(const Ref<Font> &p_font, CharType p_char, CharType p_next, Vector2 p_offset, const Color &p_modulate, int p_priority, bool p_outline);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
void _im_update();
|
||||
void _font_changed();
|
||||
void _queue_update();
|
||||
|
||||
void _shape();
|
||||
|
||||
public:
|
||||
void set_horizontal_alignment(Align p_alignment);
|
||||
Align get_horizontal_alignment() const;
|
||||
|
||||
void set_vertical_alignment(VAlign p_alignment);
|
||||
VAlign get_vertical_alignment() const;
|
||||
|
||||
void set_render_priority(int p_priority);
|
||||
int get_render_priority() const;
|
||||
|
||||
void set_outline_render_priority(int p_priority);
|
||||
int get_outline_render_priority() const;
|
||||
|
||||
void set_text(const String &p_string);
|
||||
String get_text() const;
|
||||
|
||||
void set_uppercase(bool p_uppercase);
|
||||
bool is_uppercase() const;
|
||||
|
||||
void set_font(const Ref<Font> &p_font);
|
||||
Ref<Font> get_font() const;
|
||||
Ref<Font> _get_font_or_default() const;
|
||||
|
||||
void set_line_spacing(float p_size);
|
||||
float get_line_spacing() const;
|
||||
|
||||
void set_modulate(const Color &p_color);
|
||||
Color get_modulate() const;
|
||||
|
||||
void set_outline_modulate(const Color &p_color);
|
||||
Color get_outline_modulate() const;
|
||||
|
||||
void set_autowrap(bool p_mode);
|
||||
bool get_autowrap() const;
|
||||
|
||||
void set_width(float p_width);
|
||||
float get_width() const;
|
||||
|
||||
void set_pixel_size(real_t p_amount);
|
||||
real_t get_pixel_size() const;
|
||||
|
||||
void set_offset(const Point2 &p_offset);
|
||||
Point2 get_offset() const;
|
||||
|
||||
void set_draw_flag(DrawFlags p_flag, bool p_enable);
|
||||
bool get_draw_flag(DrawFlags p_flag) const;
|
||||
|
||||
void set_alpha_cut_mode(AlphaCutMode p_mode);
|
||||
AlphaCutMode get_alpha_cut_mode() const;
|
||||
|
||||
void set_alpha_scissor_threshold(float p_threshold);
|
||||
float get_alpha_scissor_threshold() const;
|
||||
|
||||
void set_billboard_mode(SpatialMaterial::BillboardMode p_mode);
|
||||
SpatialMaterial::BillboardMode get_billboard_mode() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
Ref<TriangleMesh> generate_triangle_mesh() const;
|
||||
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
Label3D();
|
||||
~Label3D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Label3D::DrawFlags);
|
||||
VARIANT_ENUM_CAST(Label3D::AlphaCutMode);
|
||||
VARIANT_ENUM_CAST(Label3D::Align);
|
||||
VARIANT_ENUM_CAST(Label3D::VAlign);
|
||||
|
||||
#endif // LABEL_3D_H
|
@ -1,460 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* light.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "light.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "scene/resources/mesh/surface_tool.h"
|
||||
|
||||
void Light::set_param(Param p_param, float p_value) {
|
||||
ERR_FAIL_INDEX(p_param, PARAM_MAX);
|
||||
param[p_param] = p_value;
|
||||
|
||||
RS::get_singleton()->light_set_param(light, RS::LightParam(p_param), p_value);
|
||||
|
||||
if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) {
|
||||
update_gizmos();
|
||||
|
||||
if (p_param == PARAM_SPOT_ANGLE) {
|
||||
_change_notify("spot_angle");
|
||||
update_configuration_warning();
|
||||
} else if (p_param == PARAM_RANGE) {
|
||||
_change_notify("omni_range");
|
||||
_change_notify("spot_range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Light::get_param(Param p_param) const {
|
||||
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
|
||||
return param[p_param];
|
||||
}
|
||||
|
||||
void Light::set_shadow(bool p_enable) {
|
||||
shadow = p_enable;
|
||||
RS::get_singleton()->light_set_shadow(light, p_enable);
|
||||
|
||||
if (type == RenderingServer::LIGHT_SPOT) {
|
||||
update_configuration_warning();
|
||||
}
|
||||
}
|
||||
bool Light::has_shadow() const {
|
||||
return shadow;
|
||||
}
|
||||
|
||||
void Light::set_negative(bool p_enable) {
|
||||
negative = p_enable;
|
||||
RS::get_singleton()->light_set_negative(light, p_enable);
|
||||
}
|
||||
bool Light::is_negative() const {
|
||||
return negative;
|
||||
}
|
||||
|
||||
void Light::set_cull_mask(uint32_t p_cull_mask) {
|
||||
cull_mask = p_cull_mask;
|
||||
RS::get_singleton()->light_set_cull_mask(light, p_cull_mask);
|
||||
}
|
||||
uint32_t Light::get_cull_mask() const {
|
||||
return cull_mask;
|
||||
}
|
||||
|
||||
void Light::set_color(const Color &p_color) {
|
||||
color = p_color;
|
||||
RS::get_singleton()->light_set_color(light, p_color);
|
||||
// The gizmo color depends on the light color, so update it.
|
||||
update_gizmos();
|
||||
}
|
||||
Color Light::get_color() const {
|
||||
return color;
|
||||
}
|
||||
|
||||
void Light::set_shadow_color(const Color &p_shadow_color) {
|
||||
shadow_color = p_shadow_color;
|
||||
RS::get_singleton()->light_set_shadow_color(light, p_shadow_color);
|
||||
}
|
||||
|
||||
Color Light::get_shadow_color() const {
|
||||
return shadow_color;
|
||||
}
|
||||
|
||||
void Light::set_shadow_reverse_cull_face(bool p_enable) {
|
||||
reverse_cull = p_enable;
|
||||
RS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull);
|
||||
}
|
||||
|
||||
bool Light::get_shadow_reverse_cull_face() const {
|
||||
return reverse_cull;
|
||||
}
|
||||
|
||||
AABB Light::get_aabb() const {
|
||||
if (type == RenderingServer::LIGHT_DIRECTIONAL) {
|
||||
return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
|
||||
|
||||
} else if (type == RenderingServer::LIGHT_OMNI) {
|
||||
return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
|
||||
|
||||
} else if (type == RenderingServer::LIGHT_SPOT) {
|
||||
float len = param[PARAM_RANGE];
|
||||
float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len;
|
||||
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
|
||||
}
|
||||
|
||||
return AABB();
|
||||
}
|
||||
|
||||
PoolVector<Face3> Light::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
void Light::owner_changed_notify() {
|
||||
// For cases where owner changes _after_ entering tree (as example, editor editing).
|
||||
_update_visibility();
|
||||
}
|
||||
|
||||
void Light::_update_visibility() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool editor_ok = true;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (editor_only) {
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
editor_ok = false;
|
||||
} else {
|
||||
editor_ok = (get_tree()->get_edited_scene_root() && (this == get_tree()->get_edited_scene_root() || get_owner() == get_tree()->get_edited_scene_root()));
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (editor_only) {
|
||||
editor_ok = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok);
|
||||
|
||||
_change_notify("geometry/visible");
|
||||
}
|
||||
|
||||
void Light::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
_update_visibility();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
_update_visibility();
|
||||
}
|
||||
}
|
||||
|
||||
void Light::set_editor_only(bool p_editor_only) {
|
||||
editor_only = p_editor_only;
|
||||
_update_visibility();
|
||||
}
|
||||
|
||||
bool Light::is_editor_only() const {
|
||||
return editor_only;
|
||||
}
|
||||
|
||||
void Light::_validate_property(PropertyInfo &property) const {
|
||||
if (RenderingServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
void Light::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light::set_editor_only);
|
||||
ClassDB::bind_method(D_METHOD("is_editor_only"), &Light::is_editor_only);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &Light::set_param);
|
||||
ClassDB::bind_method(D_METHOD("get_param", "param"), &Light::get_param);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow", "enabled"), &Light::set_shadow);
|
||||
ClassDB::bind_method(D_METHOD("has_shadow"), &Light::has_shadow);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_negative", "enabled"), &Light::set_negative);
|
||||
ClassDB::bind_method(D_METHOD("is_negative"), &Light::is_negative);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cull_mask", "cull_mask"), &Light::set_cull_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_cull_mask"), &Light::get_cull_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_color", "color"), &Light::set_color);
|
||||
ClassDB::bind_method(D_METHOD("get_color"), &Light::get_color);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light::set_shadow_reverse_cull_face);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light::get_shadow_reverse_cull_face);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_color", "shadow_color"), &Light::set_shadow_color);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light::get_shadow_color);
|
||||
|
||||
ADD_GROUP("Light", "light_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_ENERGY);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_INDIRECT_ENERGY);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_size", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater"), "set_param", "get_param", PARAM_SIZE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,16,0.001,or_greater"), "set_param", "get_param", PARAM_SPECULAR);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
ADD_GROUP("Shadow", "shadow_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_bias", PROPERTY_HINT_RANGE, "-10,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "shadow_contact", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
|
||||
ADD_GROUP("Editor", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
|
||||
ADD_GROUP("", "");
|
||||
|
||||
BIND_ENUM_CONSTANT(PARAM_ENERGY);
|
||||
BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY);
|
||||
BIND_ENUM_CONSTANT(PARAM_SIZE);
|
||||
BIND_ENUM_CONSTANT(PARAM_SPECULAR);
|
||||
BIND_ENUM_CONSTANT(PARAM_RANGE);
|
||||
BIND_ENUM_CONSTANT(PARAM_ATTENUATION);
|
||||
BIND_ENUM_CONSTANT(PARAM_SPOT_ANGLE);
|
||||
BIND_ENUM_CONSTANT(PARAM_SPOT_ATTENUATION);
|
||||
BIND_ENUM_CONSTANT(PARAM_CONTACT_SHADOW_SIZE);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_MAX_DISTANCE);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_1_OFFSET);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_2_OFFSET);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_SPLIT_3_OFFSET);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_NORMAL_BIAS);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS);
|
||||
BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
||||
BIND_ENUM_CONSTANT(PARAM_MAX);
|
||||
}
|
||||
|
||||
Light::Light(RenderingServer::LightType p_type) {
|
||||
type = p_type;
|
||||
switch (p_type) {
|
||||
case RS::LIGHT_DIRECTIONAL:
|
||||
light = RID_PRIME(RenderingServer::get_singleton()->directional_light_create());
|
||||
break;
|
||||
case RS::LIGHT_OMNI:
|
||||
light = RID_PRIME(RenderingServer::get_singleton()->omni_light_create());
|
||||
break;
|
||||
case RS::LIGHT_SPOT:
|
||||
light = RID_PRIME(RenderingServer::get_singleton()->spot_light_create());
|
||||
break;
|
||||
default: {
|
||||
};
|
||||
}
|
||||
|
||||
RS::get_singleton()->instance_set_base(get_instance(), light);
|
||||
|
||||
reverse_cull = false;
|
||||
|
||||
editor_only = false;
|
||||
set_color(Color(1, 1, 1, 1));
|
||||
set_shadow(false);
|
||||
set_negative(false);
|
||||
set_cull_mask(0xFFFFFFFF);
|
||||
|
||||
set_param(PARAM_ENERGY, 1);
|
||||
set_param(PARAM_INDIRECT_ENERGY, 1);
|
||||
set_param(PARAM_SIZE, 0);
|
||||
set_param(PARAM_SPECULAR, 0.5);
|
||||
set_param(PARAM_RANGE, 5);
|
||||
set_param(PARAM_ATTENUATION, 1);
|
||||
set_param(PARAM_SPOT_ANGLE, 45);
|
||||
set_param(PARAM_SPOT_ATTENUATION, 1);
|
||||
set_param(PARAM_CONTACT_SHADOW_SIZE, 0);
|
||||
set_param(PARAM_SHADOW_MAX_DISTANCE, 0);
|
||||
set_param(PARAM_SHADOW_SPLIT_1_OFFSET, 0.1);
|
||||
set_param(PARAM_SHADOW_SPLIT_2_OFFSET, 0.2);
|
||||
set_param(PARAM_SHADOW_SPLIT_3_OFFSET, 0.5);
|
||||
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.0);
|
||||
set_param(PARAM_SHADOW_BIAS, 0.15);
|
||||
set_disable_scale(true);
|
||||
}
|
||||
|
||||
Light::Light() {
|
||||
type = RenderingServer::LIGHT_DIRECTIONAL;
|
||||
ERR_PRINT("Light should not be instanced directly; use the DirectionalLight, OmniLight or SpotLight subtypes instead.");
|
||||
}
|
||||
|
||||
Light::~Light() {
|
||||
RS::get_singleton()->instance_set_base(get_instance(), RID());
|
||||
|
||||
if (light.is_valid()) {
|
||||
RenderingServer::get_singleton()->free(light);
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////
|
||||
|
||||
void DirectionalLight::set_shadow_mode(ShadowMode p_mode) {
|
||||
shadow_mode = p_mode;
|
||||
RS::get_singleton()->light_directional_set_shadow_mode(light, RS::LightDirectionalShadowMode(p_mode));
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const {
|
||||
return shadow_mode;
|
||||
}
|
||||
|
||||
void DirectionalLight::set_shadow_depth_range(ShadowDepthRange p_range) {
|
||||
shadow_depth_range = p_range;
|
||||
RS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, RS::LightDirectionalShadowDepthRangeMode(p_range));
|
||||
}
|
||||
|
||||
DirectionalLight::ShadowDepthRange DirectionalLight::get_shadow_depth_range() const {
|
||||
return shadow_depth_range;
|
||||
}
|
||||
|
||||
void DirectionalLight::set_blend_splits(bool p_enable) {
|
||||
blend_splits = p_enable;
|
||||
RS::get_singleton()->light_directional_set_blend_splits(light, p_enable);
|
||||
}
|
||||
|
||||
bool DirectionalLight::is_blend_splits_enabled() const {
|
||||
return blend_splits;
|
||||
}
|
||||
|
||||
void DirectionalLight::_validate_property(PropertyInfo &property) const {
|
||||
if (shadow_mode == SHADOW_ORTHOGONAL && (property.name == "directional_shadow_split_1" || property.name == "directional_shadow_blend_splits" || property.name == "directional_shadow_bias_split_scale")) {
|
||||
// Split 2, split blending and bias split scale are only used with the PSSM 2 Splits and PSSM 4 Splits shadow modes.
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
}
|
||||
|
||||
if ((shadow_mode == SHADOW_ORTHOGONAL || shadow_mode == SHADOW_PARALLEL_2_SPLITS) && (property.name == "directional_shadow_split_2" || property.name == "directional_shadow_split_3")) {
|
||||
// Splits 3 and 4 are only used with the PSSM 4 Splits shadow mode.
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR;
|
||||
}
|
||||
|
||||
Light::_validate_property(property);
|
||||
}
|
||||
|
||||
void DirectionalLight::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight::set_shadow_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight::get_shadow_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_depth_range", "mode"), &DirectionalLight::set_shadow_depth_range);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_depth_range"), &DirectionalLight::get_shadow_depth_range);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight::set_blend_splits);
|
||||
ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight::is_blend_splits_enabled);
|
||||
|
||||
ADD_GROUP("Directional Shadow", "directional_shadow_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 3 Splits (Slow),PSSM 4 Splits (Very Slow)"), "set_shadow_mode", "get_shadow_mode");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_bias_split_scale", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_depth_range", PROPERTY_HINT_ENUM, "Stable,Optimized"), "set_shadow_depth_range", "get_shadow_depth_range");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL);
|
||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS);
|
||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_3_SPLITS);
|
||||
BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS);
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_STABLE);
|
||||
BIND_ENUM_CONSTANT(SHADOW_DEPTH_RANGE_OPTIMIZED);
|
||||
}
|
||||
|
||||
DirectionalLight::DirectionalLight() :
|
||||
Light(RenderingServer::LIGHT_DIRECTIONAL) {
|
||||
set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8);
|
||||
set_param(PARAM_SHADOW_BIAS, 0.1);
|
||||
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
|
||||
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25);
|
||||
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
|
||||
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
|
||||
|
||||
blend_splits = false;
|
||||
}
|
||||
|
||||
void OmniLight::set_shadow_mode(ShadowMode p_mode) {
|
||||
shadow_mode = p_mode;
|
||||
RS::get_singleton()->light_omni_set_shadow_mode(light, RS::LightOmniShadowMode(p_mode));
|
||||
}
|
||||
|
||||
OmniLight::ShadowMode OmniLight::get_shadow_mode() const {
|
||||
return shadow_mode;
|
||||
}
|
||||
|
||||
void OmniLight::set_shadow_detail(ShadowDetail p_detail) {
|
||||
shadow_detail = p_detail;
|
||||
RS::get_singleton()->light_omni_set_shadow_detail(light, RS::LightOmniShadowDetail(p_detail));
|
||||
}
|
||||
OmniLight::ShadowDetail OmniLight::get_shadow_detail() const {
|
||||
return shadow_detail;
|
||||
}
|
||||
|
||||
void OmniLight::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight::set_shadow_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight::get_shadow_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_shadow_detail", "detail"), &OmniLight::set_shadow_detail);
|
||||
ClassDB::bind_method(D_METHOD("get_shadow_detail"), &OmniLight::get_shadow_detail);
|
||||
|
||||
ADD_GROUP("Omni", "omni_");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.001,or_greater"), "set_param", "get_param", PARAM_RANGE);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_detail", PROPERTY_HINT_ENUM, "Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail");
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID);
|
||||
BIND_ENUM_CONSTANT(SHADOW_CUBE);
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_DETAIL_VERTICAL);
|
||||
BIND_ENUM_CONSTANT(SHADOW_DETAIL_HORIZONTAL);
|
||||
}
|
||||
|
||||
OmniLight::OmniLight() :
|
||||
Light(RenderingServer::LIGHT_OMNI) {
|
||||
set_shadow_mode(SHADOW_CUBE);
|
||||
set_shadow_detail(SHADOW_DETAIL_HORIZONTAL);
|
||||
}
|
||||
|
||||
String SpotLight::get_configuration_warning() const {
|
||||
String warning = Light::get_configuration_warning();
|
||||
|
||||
if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
|
||||
warning += TTR("A SpotLight with an angle wider than 90 degrees cannot cast shadows.");
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
void SpotLight::_bind_methods() {
|
||||
ADD_GROUP("Spot", "spot_");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.001,or_greater"), "set_param", "get_param", PARAM_RANGE);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_param", "get_param", PARAM_SPOT_ANGLE);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
|
||||
}
|
212
scene/3d/light.h
212
scene/3d/light.h
@ -1,212 +0,0 @@
|
||||
#ifndef LIGHT_H
|
||||
#define LIGHT_H
|
||||
/*************************************************************************/
|
||||
/* light.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class Light : public VisualInstance {
|
||||
GDCLASS(Light, VisualInstance);
|
||||
OBJ_CATEGORY("3D Light Nodes");
|
||||
|
||||
public:
|
||||
enum Param {
|
||||
PARAM_ENERGY = RS::LIGHT_PARAM_ENERGY,
|
||||
PARAM_INDIRECT_ENERGY = RS::LIGHT_PARAM_INDIRECT_ENERGY,
|
||||
PARAM_SIZE = RS::LIGHT_PARAM_SIZE,
|
||||
PARAM_SPECULAR = RS::LIGHT_PARAM_SPECULAR,
|
||||
PARAM_RANGE = RS::LIGHT_PARAM_RANGE,
|
||||
PARAM_ATTENUATION = RS::LIGHT_PARAM_ATTENUATION,
|
||||
PARAM_SPOT_ANGLE = RS::LIGHT_PARAM_SPOT_ANGLE,
|
||||
PARAM_SPOT_ATTENUATION = RS::LIGHT_PARAM_SPOT_ATTENUATION,
|
||||
PARAM_CONTACT_SHADOW_SIZE = RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE,
|
||||
PARAM_SHADOW_MAX_DISTANCE = RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE,
|
||||
PARAM_SHADOW_SPLIT_1_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
|
||||
PARAM_SHADOW_SPLIT_2_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
|
||||
PARAM_SHADOW_SPLIT_3_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
|
||||
PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
|
||||
PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS,
|
||||
PARAM_SHADOW_BIAS_SPLIT_SCALE = RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
|
||||
PARAM_MAX = RS::LIGHT_PARAM_MAX
|
||||
};
|
||||
|
||||
private:
|
||||
Color color;
|
||||
float param[PARAM_MAX];
|
||||
Color shadow_color;
|
||||
bool shadow;
|
||||
bool negative;
|
||||
bool reverse_cull;
|
||||
uint32_t cull_mask;
|
||||
RS::LightType type;
|
||||
bool editor_only;
|
||||
void _update_visibility();
|
||||
|
||||
// bind helpers
|
||||
|
||||
virtual void owner_changed_notify();
|
||||
|
||||
protected:
|
||||
RID light;
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
Light(RenderingServer::LightType p_type);
|
||||
|
||||
public:
|
||||
RS::LightType get_light_type() const { return type; }
|
||||
|
||||
void set_editor_only(bool p_editor_only);
|
||||
bool is_editor_only() const;
|
||||
|
||||
void set_param(Param p_param, float p_value);
|
||||
float get_param(Param p_param) const;
|
||||
|
||||
void set_shadow(bool p_enable);
|
||||
bool has_shadow() const;
|
||||
|
||||
void set_negative(bool p_enable);
|
||||
bool is_negative() const;
|
||||
|
||||
void set_cull_mask(uint32_t p_cull_mask);
|
||||
uint32_t get_cull_mask() const;
|
||||
|
||||
void set_color(const Color &p_color);
|
||||
Color get_color() const;
|
||||
|
||||
void set_shadow_color(const Color &p_shadow_color);
|
||||
Color get_shadow_color() const;
|
||||
|
||||
void set_shadow_reverse_cull_face(bool p_enable);
|
||||
bool get_shadow_reverse_cull_face() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
Light();
|
||||
~Light();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Light::Param);
|
||||
|
||||
class DirectionalLight : public Light {
|
||||
GDCLASS(DirectionalLight, Light);
|
||||
|
||||
public:
|
||||
enum ShadowMode {
|
||||
SHADOW_ORTHOGONAL,
|
||||
SHADOW_PARALLEL_2_SPLITS,
|
||||
SHADOW_PARALLEL_3_SPLITS,
|
||||
SHADOW_PARALLEL_4_SPLITS
|
||||
};
|
||||
|
||||
enum ShadowDepthRange {
|
||||
SHADOW_DEPTH_RANGE_STABLE = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE,
|
||||
SHADOW_DEPTH_RANGE_OPTIMIZED = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED,
|
||||
};
|
||||
|
||||
private:
|
||||
bool blend_splits;
|
||||
ShadowMode shadow_mode;
|
||||
ShadowDepthRange shadow_depth_range;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
void set_shadow_mode(ShadowMode p_mode);
|
||||
ShadowMode get_shadow_mode() const;
|
||||
|
||||
void set_shadow_depth_range(ShadowDepthRange p_range);
|
||||
ShadowDepthRange get_shadow_depth_range() const;
|
||||
|
||||
void set_blend_splits(bool p_enable);
|
||||
bool is_blend_splits_enabled() const;
|
||||
|
||||
DirectionalLight();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(DirectionalLight::ShadowMode)
|
||||
VARIANT_ENUM_CAST(DirectionalLight::ShadowDepthRange)
|
||||
|
||||
class OmniLight : public Light {
|
||||
GDCLASS(OmniLight, Light);
|
||||
|
||||
public:
|
||||
// omni light
|
||||
enum ShadowMode {
|
||||
SHADOW_DUAL_PARABOLOID,
|
||||
SHADOW_CUBE,
|
||||
};
|
||||
|
||||
// omni light
|
||||
enum ShadowDetail {
|
||||
SHADOW_DETAIL_VERTICAL,
|
||||
SHADOW_DETAIL_HORIZONTAL
|
||||
};
|
||||
|
||||
private:
|
||||
ShadowMode shadow_mode;
|
||||
ShadowDetail shadow_detail;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_shadow_mode(ShadowMode p_mode);
|
||||
ShadowMode get_shadow_mode() const;
|
||||
|
||||
void set_shadow_detail(ShadowDetail p_detail);
|
||||
ShadowDetail get_shadow_detail() const;
|
||||
|
||||
OmniLight();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(OmniLight::ShadowMode)
|
||||
VARIANT_ENUM_CAST(OmniLight::ShadowDetail)
|
||||
|
||||
class SpotLight : public Light {
|
||||
GDCLASS(SpotLight, Light);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
SpotLight() :
|
||||
Light(RenderingServer::LIGHT_SPOT) {}
|
||||
};
|
||||
|
||||
#endif
|
@ -1,158 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* listener.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "listener.h"
|
||||
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
|
||||
void Listener::_update_audio_listener_state() {
|
||||
}
|
||||
|
||||
void Listener::_request_listener_update() {
|
||||
_update_listener();
|
||||
}
|
||||
|
||||
bool Listener::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == "current") {
|
||||
if (p_value.operator bool()) {
|
||||
make_current();
|
||||
} else {
|
||||
clear_current();
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool Listener::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (p_name == "current") {
|
||||
if (is_inside_tree() && get_tree()->is_node_being_edited(this)) {
|
||||
r_ret = current;
|
||||
} else {
|
||||
r_ret = is_current();
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Listener::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, "current"));
|
||||
}
|
||||
|
||||
void Listener::_update_listener() {
|
||||
if (is_inside_tree() && is_current()) {
|
||||
get_viewport()->_listener_transform_changed_notify();
|
||||
}
|
||||
}
|
||||
|
||||
void Listener::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
bool first_listener = get_viewport()->_listener_add(this);
|
||||
if (!get_tree()->is_node_being_edited(this) && (current || first_listener)) {
|
||||
make_current();
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
_request_listener_update();
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
if (!get_tree()->is_node_being_edited(this)) {
|
||||
if (is_current()) {
|
||||
clear_current();
|
||||
current = true; //keep it true
|
||||
|
||||
} else {
|
||||
current = false;
|
||||
}
|
||||
}
|
||||
|
||||
get_viewport()->_listener_remove(this);
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Transform Listener::get_listener_transform() const {
|
||||
return get_global_transform().orthonormalized();
|
||||
}
|
||||
|
||||
void Listener::make_current() {
|
||||
current = true;
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
get_viewport()->_listener_set(this);
|
||||
}
|
||||
|
||||
void Listener::clear_current() {
|
||||
current = false;
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_viewport()->get_listener() == this) {
|
||||
get_viewport()->_listener_set(nullptr);
|
||||
get_viewport()->_listener_make_next_current(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool Listener::is_current() const {
|
||||
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
|
||||
return get_viewport()->get_listener() == this;
|
||||
} else {
|
||||
return current;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Listener::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("make_current"), &Listener::make_current);
|
||||
ClassDB::bind_method(D_METHOD("clear_current"), &Listener::clear_current);
|
||||
ClassDB::bind_method(D_METHOD("is_current"), &Listener::is_current);
|
||||
ClassDB::bind_method(D_METHOD("get_listener_transform"), &Listener::get_listener_transform);
|
||||
}
|
||||
|
||||
Listener::Listener() {
|
||||
current = false;
|
||||
force_change = false;
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
||||
Listener::~Listener() {
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
#ifndef LISTENER_H
|
||||
#define LISTENER_H
|
||||
/*************************************************************************/
|
||||
/* listener.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class Viewport;
|
||||
|
||||
class Listener : public Spatial {
|
||||
GDCLASS(Listener, Spatial);
|
||||
|
||||
private:
|
||||
bool force_change;
|
||||
bool current;
|
||||
|
||||
RID scenario_id;
|
||||
|
||||
friend class Viewport;
|
||||
void _update_audio_listener_state();
|
||||
|
||||
protected:
|
||||
void _update_listener();
|
||||
virtual void _request_listener_update();
|
||||
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void make_current();
|
||||
void clear_current();
|
||||
bool is_current() const;
|
||||
|
||||
virtual Transform get_listener_transform() const;
|
||||
|
||||
Listener();
|
||||
~Listener();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,841 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* mesh_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "mesh_instance.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/core_string_names.h"
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
|
||||
bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) {
|
||||
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
|
||||
//add to it that it's probably found on first call to _set anyway.
|
||||
|
||||
if (!get_instance().is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RBMap<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.find(p_name);
|
||||
if (E) {
|
||||
E->get().value = p_value;
|
||||
RenderingServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), E->get().idx, E->get().value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_name.operator String().begins_with("material/")) {
|
||||
int idx = p_name.operator String().get_slicec('/', 1).to_int();
|
||||
if (idx >= materials.size() || idx < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_surface_material(idx, p_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshInstance::_get(const StringName &p_name, Variant &r_ret) const {
|
||||
if (!get_instance().is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RBMap<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.find(p_name);
|
||||
if (E) {
|
||||
r_ret = E->get().value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_name.operator String().begins_with("material/")) {
|
||||
int idx = p_name.operator String().get_slicec('/', 1).to_int();
|
||||
if (idx >= materials.size() || idx < 0) {
|
||||
return false;
|
||||
}
|
||||
r_ret = materials[idx];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MeshInstance::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
List<String> ls;
|
||||
for (const RBMap<StringName, BlendShapeTrack>::Element *E = blend_shape_tracks.front(); E; E = E->next()) {
|
||||
ls.push_back(E->key());
|
||||
}
|
||||
|
||||
ls.sort();
|
||||
|
||||
for (List<String>::Element *E = ls.front(); E; E = E->next()) {
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, E->get(), PROPERTY_HINT_RANGE, "-1,1,0.00001"));
|
||||
}
|
||||
|
||||
if (mesh.is_valid()) {
|
||||
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
||||
p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshInstance::set_mesh(const Ref<Mesh> &p_mesh) {
|
||||
if (mesh == p_mesh) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mesh.is_valid()) {
|
||||
mesh->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_mesh_changed);
|
||||
}
|
||||
|
||||
mesh = p_mesh;
|
||||
|
||||
blend_shape_tracks.clear();
|
||||
if (mesh.is_valid()) {
|
||||
for (int i = 0; i < mesh->get_blend_shape_count(); i++) {
|
||||
BlendShapeTrack mt;
|
||||
mt.idx = i;
|
||||
mt.value = 0;
|
||||
blend_shape_tracks["blend_shapes/" + String(mesh->get_blend_shape_name(i))] = mt;
|
||||
}
|
||||
|
||||
mesh->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->_mesh_changed);
|
||||
materials.resize(mesh->get_surface_count());
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
_initialize_skinning(false, true);
|
||||
#endif
|
||||
} else {
|
||||
set_base(RID());
|
||||
}
|
||||
|
||||
update_gizmos();
|
||||
|
||||
_change_notify();
|
||||
}
|
||||
Ref<Mesh> MeshInstance::get_mesh() const {
|
||||
return mesh;
|
||||
}
|
||||
|
||||
AABB MeshInstance::get_aabb() const {
|
||||
if (!mesh.is_null()) {
|
||||
return mesh->get_aabb();
|
||||
}
|
||||
|
||||
return AABB();
|
||||
}
|
||||
|
||||
PoolVector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const {
|
||||
if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
if (mesh.is_null()) {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
return mesh->get_faces();
|
||||
}
|
||||
|
||||
Node *MeshInstance::create_trimesh_collision_node() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MeshInstance::create_trimesh_collision() {
|
||||
}
|
||||
|
||||
Node *MeshInstance::create_multiple_convex_collisions_node() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MeshInstance::create_multiple_convex_collisions() {
|
||||
}
|
||||
|
||||
Node *MeshInstance::create_convex_collision_node(bool p_clean, bool p_simplify) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MeshInstance::create_convex_collision(bool p_clean, bool p_simplify) {
|
||||
}
|
||||
|
||||
void MeshInstance::_notification(int p_what) {
|
||||
}
|
||||
|
||||
int MeshInstance::get_surface_material_count() const {
|
||||
return materials.size();
|
||||
}
|
||||
|
||||
void MeshInstance::set_surface_material(int p_surface, const Ref<Material> &p_material) {
|
||||
ERR_FAIL_INDEX(p_surface, materials.size());
|
||||
|
||||
materials.write[p_surface] = p_material;
|
||||
|
||||
if (materials[p_surface].is_valid()) {
|
||||
RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID());
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Material> MeshInstance::get_surface_material(int p_surface) const {
|
||||
ERR_FAIL_INDEX_V(p_surface, materials.size(), Ref<Material>());
|
||||
|
||||
return materials[p_surface];
|
||||
}
|
||||
|
||||
Ref<Material> MeshInstance::get_active_material(int p_surface) const {
|
||||
Ref<Material> material_override = get_material_override();
|
||||
if (material_override.is_valid()) {
|
||||
return material_override;
|
||||
}
|
||||
|
||||
Ref<Material> surface_material = get_surface_material(p_surface);
|
||||
if (surface_material.is_valid()) {
|
||||
return surface_material;
|
||||
}
|
||||
|
||||
Ref<Mesh> mesh = get_mesh();
|
||||
if (mesh.is_valid()) {
|
||||
return mesh->surface_get_material(p_surface);
|
||||
}
|
||||
|
||||
return Ref<Material>();
|
||||
}
|
||||
|
||||
void MeshInstance::set_material_override(const Ref<Material> &p_material) {
|
||||
if (p_material == get_material_override()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeometryInstance::set_material_override(p_material);
|
||||
}
|
||||
|
||||
void MeshInstance::set_material_overlay(const Ref<Material> &p_material) {
|
||||
if (p_material == get_material_overlay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeometryInstance::set_material_overlay(p_material);
|
||||
}
|
||||
|
||||
void MeshInstance::_mesh_changed() {
|
||||
ERR_FAIL_COND(mesh.is_null());
|
||||
materials.resize(mesh->get_surface_count());
|
||||
}
|
||||
|
||||
void MeshInstance::create_debug_tangents() {
|
||||
Vector<Vector3> lines;
|
||||
Vector<Color> colors;
|
||||
|
||||
Ref<Mesh> mesh = get_mesh();
|
||||
if (!mesh.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->get_surface_count(); i++) {
|
||||
Array arrays = mesh->surface_get_arrays(i);
|
||||
Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX];
|
||||
Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL];
|
||||
if (norms.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
Vector<float> tangents = arrays[Mesh::ARRAY_TANGENT];
|
||||
if (tangents.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < verts.size(); j++) {
|
||||
Vector3 v = verts[j];
|
||||
Vector3 n = norms[j];
|
||||
Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]);
|
||||
Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3];
|
||||
|
||||
lines.push_back(v); //normal
|
||||
colors.push_back(Color(0, 0, 1)); //color
|
||||
lines.push_back(v + n * 0.04); //normal
|
||||
colors.push_back(Color(0, 0, 1)); //color
|
||||
|
||||
lines.push_back(v); //tangent
|
||||
colors.push_back(Color(1, 0, 0)); //color
|
||||
lines.push_back(v + t * 0.04); //tangent
|
||||
colors.push_back(Color(1, 0, 0)); //color
|
||||
|
||||
lines.push_back(v); //binormal
|
||||
colors.push_back(Color(0, 1, 0)); //color
|
||||
lines.push_back(v + b * 0.04); //binormal
|
||||
colors.push_back(Color(0, 1, 0)); //color
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.size()) {
|
||||
Ref<SpatialMaterial> sm;
|
||||
sm.instance();
|
||||
|
||||
sm->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
|
||||
sm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
|
||||
sm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
|
||||
Ref<ArrayMesh> am;
|
||||
am.instance();
|
||||
Array a;
|
||||
a.resize(Mesh::ARRAY_MAX);
|
||||
a[Mesh::ARRAY_VERTEX] = lines;
|
||||
a[Mesh::ARRAY_COLOR] = colors;
|
||||
|
||||
am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a);
|
||||
am->surface_set_material(0, sm);
|
||||
|
||||
MeshInstance *mi = memnew(MeshInstance);
|
||||
mi->set_mesh(am);
|
||||
mi->set_name("DebugTangents");
|
||||
add_child(mi);
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshInstance::merge_meshes(Vector<Variant> p_list, bool p_use_global_space, bool p_check_compatibility) {
|
||||
// bound function only support variants, so we need to convert to a list of MeshInstances
|
||||
Vector<MeshInstance *> mis;
|
||||
|
||||
for (int n = 0; n < p_list.size(); n++) {
|
||||
MeshInstance *mi = Object::cast_to<MeshInstance>(p_list[n]);
|
||||
if (mi) {
|
||||
if (mi != this) {
|
||||
mis.push_back(mi);
|
||||
} else {
|
||||
ERR_PRINT("Destination MeshInstance cannot be a source.");
|
||||
}
|
||||
} else {
|
||||
ERR_PRINT("Only MeshInstances can be merged.");
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!mis.size(), "Array contains no MeshInstances");
|
||||
return _merge_meshes(mis, p_use_global_space, p_check_compatibility);
|
||||
}
|
||||
|
||||
bool MeshInstance::is_mergeable_with(Node *p_other) const {
|
||||
const MeshInstance *mi = Object::cast_to<MeshInstance>(p_other);
|
||||
|
||||
if (mi) {
|
||||
return _is_mergeable_with(*mi);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshInstance::_is_mergeable_with(const MeshInstance &p_other) const {
|
||||
if (!get_mesh().is_valid() || !p_other.get_mesh().is_valid()) {
|
||||
return false;
|
||||
}
|
||||
if (!get_allow_merging() || !p_other.get_allow_merging()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// various settings that must match
|
||||
if (get_material_overlay() != p_other.get_material_overlay()) {
|
||||
return false;
|
||||
}
|
||||
if (get_material_override() != p_other.get_material_override()) {
|
||||
return false;
|
||||
}
|
||||
if (get_cast_shadows_setting() != p_other.get_cast_shadows_setting()) {
|
||||
return false;
|
||||
}
|
||||
if (is_visible() != p_other.is_visible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ref<Mesh> rmesh_a = get_mesh();
|
||||
Ref<Mesh> rmesh_b = p_other.get_mesh();
|
||||
|
||||
int num_surfaces = rmesh_a->get_surface_count();
|
||||
if (num_surfaces != rmesh_b->get_surface_count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int n = 0; n < num_surfaces; n++) {
|
||||
// materials must match
|
||||
if (get_active_material(n) != p_other.get_active_material(n)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// formats must match
|
||||
uint32_t format_a = rmesh_a->surface_get_format(n);
|
||||
uint32_t format_b = rmesh_b->surface_get_format(n);
|
||||
|
||||
if (format_a != format_b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE : These three commented out sections below are more conservative
|
||||
// checks for whether to allow mesh merging. I am not absolutely sure a priori
|
||||
// how conservative we need to be, so we can further enable this if testing
|
||||
// shows they are required.
|
||||
|
||||
// if (get_surface_material_count() != p_other.get_surface_material_count()) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// for (int n = 0; n < get_surface_material_count(); n++) {
|
||||
// if (get_surface_material(n) != p_other.get_surface_material(n)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// test only allow identical meshes
|
||||
// if (get_mesh() != p_other.get_mesh()) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshInstance::_merge_into_mesh_data(const MeshInstance &p_mi, const Transform &p_dest_tr_inv, int p_surface_id, LocalVector<Vector3> &r_verts, LocalVector<Vector3> &r_norms, LocalVector<real_t> &r_tangents, LocalVector<Color> &r_colors, LocalVector<Vector2> &r_uvs, LocalVector<Vector2> &r_uv2s, LocalVector<int> &r_inds) {
|
||||
_merge_log("\t\t\tmesh data from " + p_mi.get_name());
|
||||
|
||||
// get the mesh verts in local space
|
||||
Ref<Mesh> rmesh = p_mi.get_mesh();
|
||||
|
||||
if (rmesh->get_surface_count() <= p_surface_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
Array arrays = rmesh->surface_get_arrays(p_surface_id);
|
||||
|
||||
LocalVector<Vector3> verts = PoolVector<Vector3>(arrays[RS::ARRAY_VERTEX]);
|
||||
if (!verts.size()) {
|
||||
// early out if there are no vertices, no point in doing anything else
|
||||
return;
|
||||
}
|
||||
|
||||
LocalVector<Vector3> normals = PoolVector<Vector3>(arrays[RS::ARRAY_NORMAL]);
|
||||
LocalVector<real_t> tangents = PoolVector<real_t>(arrays[RS::ARRAY_TANGENT]);
|
||||
LocalVector<Color> colors = PoolVector<Color>(arrays[RS::ARRAY_COLOR]);
|
||||
LocalVector<Vector2> uvs = PoolVector<Vector2>(arrays[RS::ARRAY_TEX_UV]);
|
||||
LocalVector<Vector2> uv2s = PoolVector<Vector2>(arrays[RS::ARRAY_TEX_UV2]);
|
||||
LocalVector<int> indices = PoolVector<int>(arrays[RS::ARRAY_INDEX]);
|
||||
|
||||
// The attributes present must match the first mesh for the attributes
|
||||
// to remain in sync. Here we reject meshes with different attributes.
|
||||
// We could alternatively invent missing attributes.
|
||||
// This should hopefully be already caught by the mesh_format, but is included just in case here.
|
||||
|
||||
// Don't perform these checks on the first Mesh, the first Mesh is a master
|
||||
// and determines the attributes we want to be present.
|
||||
if (r_verts.size() != 0) {
|
||||
if ((bool)r_norms.size() != (bool)normals.size()) {
|
||||
ERR_FAIL_MSG("Attribute mismatch with first Mesh (Normals), ignoring surface.");
|
||||
}
|
||||
if ((bool)r_tangents.size() != (bool)tangents.size()) {
|
||||
ERR_FAIL_MSG("Attribute mismatch with first Mesh (Tangents), ignoring surface.");
|
||||
}
|
||||
if ((bool)r_colors.size() != (bool)colors.size()) {
|
||||
ERR_FAIL_MSG("Attribute mismatch with first Mesh (Colors), ignoring surface.");
|
||||
}
|
||||
if ((bool)r_uvs.size() != (bool)uvs.size()) {
|
||||
ERR_FAIL_MSG("Attribute mismatch with first Mesh (UVs), ignoring surface.");
|
||||
}
|
||||
if ((bool)r_uv2s.size() != (bool)uv2s.size()) {
|
||||
ERR_FAIL_MSG("Attribute mismatch with first Mesh (UV2s), ignoring surface.");
|
||||
}
|
||||
}
|
||||
|
||||
// The checking for valid triangles should be on WORLD SPACE vertices,
|
||||
// NOT model space
|
||||
|
||||
// special case, if no indices, create some
|
||||
int num_indices_before = indices.size();
|
||||
if (!_ensure_indices_valid(indices, verts)) {
|
||||
_merge_log("\tignoring INVALID TRIANGLES (duplicate indices or zero area triangle) detected in " + p_mi.get_name() + ", num inds before / after " + itos(num_indices_before) + " / " + itos(indices.size()));
|
||||
}
|
||||
|
||||
// the first index of this mesh is offset from the verts we already have stored in the merged mesh
|
||||
int starting_index = r_verts.size();
|
||||
|
||||
// transform verts to world space
|
||||
Transform tr = p_mi.get_global_transform();
|
||||
|
||||
// But relative to the destination transform.
|
||||
// This can either be identity (when the destination is global space),
|
||||
// or the global transform of the owner MeshInstance (if using local space is selected).
|
||||
tr = p_dest_tr_inv * tr;
|
||||
|
||||
// to transform normals
|
||||
Basis normal_basis = tr.basis.inverse();
|
||||
normal_basis.transpose();
|
||||
|
||||
int num_verts = verts.size();
|
||||
|
||||
// verts
|
||||
DEV_ASSERT(num_verts > 0);
|
||||
int first_vert = r_verts.size();
|
||||
r_verts.resize(first_vert + num_verts);
|
||||
Vector3 *dest_verts = &r_verts[first_vert];
|
||||
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
Vector3 pt_world = tr.xform(verts[n]);
|
||||
*dest_verts++ = pt_world;
|
||||
}
|
||||
|
||||
// normals
|
||||
if (normals.size()) {
|
||||
int first_norm = r_norms.size();
|
||||
r_norms.resize(first_norm + num_verts);
|
||||
Vector3 *dest_norms = &r_norms[first_norm];
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
Vector3 pt_norm = normal_basis.xform(normals[n]);
|
||||
pt_norm.normalize();
|
||||
*dest_norms++ = pt_norm;
|
||||
}
|
||||
}
|
||||
|
||||
// tangents
|
||||
if (tangents.size()) {
|
||||
int first_tang = r_tangents.size();
|
||||
r_tangents.resize(first_tang + (num_verts * 4));
|
||||
real_t *dest_tangents = &r_tangents[first_tang];
|
||||
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
int tstart = n * 4;
|
||||
Vector3 pt_tangent = Vector3(tangents[tstart], tangents[tstart + 1], tangents[tstart + 2]);
|
||||
real_t fourth = tangents[tstart + 3];
|
||||
|
||||
pt_tangent = normal_basis.xform(pt_tangent);
|
||||
pt_tangent.normalize();
|
||||
*dest_tangents++ = pt_tangent.x;
|
||||
*dest_tangents++ = pt_tangent.y;
|
||||
*dest_tangents++ = pt_tangent.z;
|
||||
*dest_tangents++ = fourth;
|
||||
}
|
||||
}
|
||||
|
||||
// colors
|
||||
if (colors.size()) {
|
||||
int first_col = r_colors.size();
|
||||
r_colors.resize(first_col + num_verts);
|
||||
Color *dest_colors = &r_colors[first_col];
|
||||
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
*dest_colors++ = colors[n];
|
||||
}
|
||||
}
|
||||
|
||||
// uvs
|
||||
if (uvs.size()) {
|
||||
int first_uv = r_uvs.size();
|
||||
r_uvs.resize(first_uv + num_verts);
|
||||
Vector2 *dest_uvs = &r_uvs[first_uv];
|
||||
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
*dest_uvs++ = uvs[n];
|
||||
}
|
||||
}
|
||||
|
||||
// uv2s
|
||||
if (uv2s.size()) {
|
||||
int first_uv2 = r_uv2s.size();
|
||||
r_uv2s.resize(first_uv2 + num_verts);
|
||||
Vector2 *dest_uv2s = &r_uv2s[first_uv2];
|
||||
|
||||
for (int n = 0; n < num_verts; n++) {
|
||||
*dest_uv2s++ = uv2s[n];
|
||||
}
|
||||
}
|
||||
|
||||
// indices
|
||||
if (indices.size()) {
|
||||
int first_ind = r_inds.size();
|
||||
r_inds.resize(first_ind + indices.size());
|
||||
int *dest_inds = &r_inds[first_ind];
|
||||
|
||||
for (unsigned int n = 0; n < indices.size(); n++) {
|
||||
int ind = indices[n] + starting_index;
|
||||
*dest_inds++ = ind;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshInstance::_ensure_indices_valid(LocalVector<int> &r_indices, const PoolVector<Vector3> &p_verts) const {
|
||||
// no indices? create some
|
||||
if (!r_indices.size()) {
|
||||
_merge_log("\t\t\t\tindices are blank, creating...");
|
||||
|
||||
// indices are blank!! let's create some, assuming the mesh is using triangles
|
||||
r_indices.resize(p_verts.size());
|
||||
|
||||
// this is assuming each triangle vertex is unique
|
||||
for (unsigned int n = 0; n < r_indices.size(); n++) {
|
||||
r_indices[n] = n;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_check_for_valid_indices(r_indices, p_verts, nullptr)) {
|
||||
LocalVector<int> new_inds;
|
||||
_check_for_valid_indices(r_indices, p_verts, &new_inds);
|
||||
|
||||
// copy the new indices
|
||||
r_indices = new_inds;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for invalid tris, or make a list of the valid triangles, depending on whether r_inds is set
|
||||
bool MeshInstance::_check_for_valid_indices(const LocalVector<int> &p_inds, const PoolVector<Vector3> &p_verts, LocalVector<int> *r_inds) const {
|
||||
int nTris = p_inds.size();
|
||||
nTris /= 3;
|
||||
int indCount = 0;
|
||||
|
||||
for (int t = 0; t < nTris; t++) {
|
||||
int i0 = p_inds[indCount++];
|
||||
int i1 = p_inds[indCount++];
|
||||
int i2 = p_inds[indCount++];
|
||||
|
||||
bool ok = true;
|
||||
|
||||
// if the indices are the same, the triangle is invalid
|
||||
if (i0 == i1) {
|
||||
ok = false;
|
||||
}
|
||||
if (i1 == i2) {
|
||||
ok = false;
|
||||
}
|
||||
if (i0 == i2) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// check positions
|
||||
if (ok) {
|
||||
// vertex positions
|
||||
const Vector3 &p0 = p_verts[i0];
|
||||
const Vector3 &p1 = p_verts[i1];
|
||||
const Vector3 &p2 = p_verts[i2];
|
||||
|
||||
// if the area is zero, the triangle is invalid (and will crash xatlas if we use it)
|
||||
if (_triangle_is_degenerate(p0, p1, p2, 0.00001)) {
|
||||
_merge_log("\t\tdetected zero area triangle, ignoring");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
// if the triangle is ok, we will output it if we are outputting
|
||||
if (r_inds) {
|
||||
r_inds->push_back(i0);
|
||||
r_inds->push_back(i1);
|
||||
r_inds->push_back(i2);
|
||||
}
|
||||
} else {
|
||||
// if triangle not ok, return failed check if we are not outputting
|
||||
if (!r_inds) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeshInstance::_triangle_is_degenerate(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, real_t p_epsilon) const {
|
||||
// not interested in the actual area, but numerical stability
|
||||
Vector3 edge1 = p_b - p_a;
|
||||
Vector3 edge2 = p_c - p_a;
|
||||
|
||||
// for numerical stability keep these values reasonably high
|
||||
edge1 *= 1024.0;
|
||||
edge2 *= 1024.0;
|
||||
|
||||
Vector3 vec = edge1.cross(edge2);
|
||||
real_t sl = vec.length_squared();
|
||||
|
||||
if (sl <= p_epsilon) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If p_check_compatibility is set to false you MUST have performed a prior check using
|
||||
// is_mergeable_with, otherwise you could get mismatching surface formats leading to graphical errors etc.
|
||||
bool MeshInstance::_merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility) {
|
||||
if (p_list.size() < 1) {
|
||||
// should not happen but just in case
|
||||
return false;
|
||||
}
|
||||
|
||||
// use the first mesh instance to get common data like number of surfaces
|
||||
const MeshInstance *first = p_list[0];
|
||||
|
||||
// Mesh compatibility checking. This is relatively expensive, so if done already (e.g. in Room system)
|
||||
// this step can be avoided.
|
||||
LocalVector<bool> compat_list;
|
||||
if (p_check_compatibility) {
|
||||
compat_list.resize(p_list.size());
|
||||
|
||||
for (int n = 0; n < p_list.size(); n++) {
|
||||
compat_list[n] = false;
|
||||
}
|
||||
|
||||
compat_list[0] = true;
|
||||
|
||||
for (uint32_t n = 1; n < compat_list.size(); n++) {
|
||||
compat_list[n] = first->_is_mergeable_with(*p_list[n]);
|
||||
|
||||
if (compat_list[n] == false) {
|
||||
WARN_PRINT("MeshInstance " + p_list[n]->get_name() + " is incompatible for merging with " + first->get_name() + ", ignoring.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> am;
|
||||
am.instance();
|
||||
|
||||
// If we want a local space result, we need the world space transform of this MeshInstance
|
||||
// available to back transform verts from world space.
|
||||
Transform dest_tr_inv;
|
||||
if (!p_use_global_space) {
|
||||
if (is_inside_tree()) {
|
||||
dest_tr_inv = get_global_transform();
|
||||
dest_tr_inv.affine_invert();
|
||||
} else {
|
||||
WARN_PRINT("MeshInstance must be inside tree to merge using local space, falling back to global space.");
|
||||
}
|
||||
}
|
||||
|
||||
for (int s = 0; s < first->get_mesh()->get_surface_count(); s++) {
|
||||
LocalVector<Vector3> verts;
|
||||
LocalVector<Vector3> normals;
|
||||
LocalVector<real_t> tangents;
|
||||
LocalVector<Color> colors;
|
||||
LocalVector<Vector2> uvs;
|
||||
LocalVector<Vector2> uv2s;
|
||||
LocalVector<int> inds;
|
||||
|
||||
for (int n = 0; n < p_list.size(); n++) {
|
||||
// Ignore if the mesh is incompatible
|
||||
if (p_check_compatibility && (!compat_list[n])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_merge_into_mesh_data(*p_list[n], dest_tr_inv, s, verts, normals, tangents, colors, uvs, uv2s, inds);
|
||||
} // for n through source meshes
|
||||
|
||||
if (!verts.size()) {
|
||||
WARN_PRINT_ONCE("No vertices for surface");
|
||||
}
|
||||
|
||||
// sanity check on the indices
|
||||
for (unsigned int n = 0; n < inds.size(); n++) {
|
||||
int i = inds[n];
|
||||
if ((unsigned int)i >= verts.size()) {
|
||||
WARN_PRINT_ONCE("Mesh index out of range, invalid mesh, aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Array arr;
|
||||
arr.resize(Mesh::ARRAY_MAX);
|
||||
arr[Mesh::ARRAY_VERTEX] = PoolVector<Vector3>(verts);
|
||||
if (normals.size()) {
|
||||
arr[Mesh::ARRAY_NORMAL] = PoolVector<Vector3>(normals);
|
||||
}
|
||||
if (tangents.size()) {
|
||||
arr[Mesh::ARRAY_TANGENT] = PoolVector<real_t>(tangents);
|
||||
}
|
||||
if (colors.size()) {
|
||||
arr[Mesh::ARRAY_COLOR] = PoolVector<Color>(colors);
|
||||
}
|
||||
if (uvs.size()) {
|
||||
arr[Mesh::ARRAY_TEX_UV] = PoolVector<Vector2>(uvs);
|
||||
}
|
||||
if (uv2s.size()) {
|
||||
arr[Mesh::ARRAY_TEX_UV2] = PoolVector<Vector2>(uv2s);
|
||||
}
|
||||
arr[Mesh::ARRAY_INDEX] = PoolVector<int>(inds);
|
||||
|
||||
am->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr, Array(), Mesh::ARRAY_COMPRESS_DEFAULT);
|
||||
} // for s through surfaces
|
||||
|
||||
// set all the surfaces on the mesh
|
||||
set_mesh(am);
|
||||
|
||||
// set merged materials
|
||||
int num_surfaces = first->get_mesh()->get_surface_count();
|
||||
for (int n = 0; n < num_surfaces; n++) {
|
||||
set_surface_material(n, first->get_active_material(n));
|
||||
}
|
||||
|
||||
// set some properties to match the merged meshes
|
||||
set_material_overlay(first->get_material_overlay());
|
||||
set_material_override(first->get_material_override());
|
||||
set_cast_shadows_setting(first->get_cast_shadows_setting());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshInstance::_merge_log(String p_string) const {
|
||||
print_verbose(p_string);
|
||||
}
|
||||
|
||||
void MeshInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MeshInstance::set_mesh);
|
||||
ClassDB::bind_method(D_METHOD("get_mesh"), &MeshInstance::get_mesh);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance::get_surface_material_count);
|
||||
ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance::set_surface_material);
|
||||
ClassDB::bind_method(D_METHOD("get_surface_material", "surface"), &MeshInstance::get_surface_material);
|
||||
ClassDB::bind_method(D_METHOD("get_active_material", "surface"), &MeshInstance::get_active_material);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance::create_trimesh_collision);
|
||||
ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT);
|
||||
ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance::create_multiple_convex_collisions);
|
||||
ClassDB::set_method_flags("MeshInstance", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT);
|
||||
ClassDB::bind_method(D_METHOD("create_convex_collision", "clean", "simplify"), &MeshInstance::create_convex_collision, DEFVAL(true), DEFVAL(false));
|
||||
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
|
||||
ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents);
|
||||
ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_mergeable_with", "other_mesh_instance"), &MeshInstance::is_mergeable_with);
|
||||
ClassDB::bind_method(D_METHOD("merge_meshes", "mesh_instances", "use_global_space", "check_compatibility"), &MeshInstance::merge_meshes, DEFVAL(Vector<Variant>()), DEFVAL(false), DEFVAL(true));
|
||||
ClassDB::set_method_flags("MeshInstance", "merge_meshes", METHOD_FLAGS_DEFAULT);
|
||||
}
|
||||
|
||||
MeshInstance::MeshInstance() {
|
||||
}
|
||||
|
||||
MeshInstance::~MeshInstance() {
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
#ifndef MESH_INSTANCE_H
|
||||
#define MESH_INSTANCE_H
|
||||
/*************************************************************************/
|
||||
/* mesh_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
#include "core/containers/local_vector.h"
|
||||
#include "core/object/reference.h"
|
||||
|
||||
class Mesh;
|
||||
class NodePath;
|
||||
|
||||
class MeshInstance : public GeometryInstance {
|
||||
GDCLASS(MeshInstance, GeometryInstance);
|
||||
|
||||
protected:
|
||||
Ref<Mesh> mesh;
|
||||
|
||||
struct BlendShapeTrack {
|
||||
int idx;
|
||||
float value;
|
||||
BlendShapeTrack() {
|
||||
idx = 0;
|
||||
value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
RBMap<StringName, BlendShapeTrack> blend_shape_tracks;
|
||||
Vector<Ref<Material>> materials;
|
||||
|
||||
void _mesh_changed();
|
||||
|
||||
private:
|
||||
// merging
|
||||
bool _merge_meshes(Vector<MeshInstance *> p_list, bool p_use_global_space, bool p_check_compatibility);
|
||||
bool _is_mergeable_with(const MeshInstance &p_other) const;
|
||||
void _merge_into_mesh_data(const MeshInstance &p_mi, const Transform &p_dest_tr_inv, int p_surface_id, LocalVector<Vector3> &r_verts, LocalVector<Vector3> &r_norms, LocalVector<real_t> &r_tangents, LocalVector<Color> &r_colors, LocalVector<Vector2> &r_uvs, LocalVector<Vector2> &r_uv2s, LocalVector<int> &r_inds);
|
||||
bool _ensure_indices_valid(LocalVector<int> &r_indices, const PoolVector<Vector3> &p_verts) const;
|
||||
bool _check_for_valid_indices(const LocalVector<int> &p_inds, const PoolVector<Vector3> &p_verts, LocalVector<int> *r_inds) const;
|
||||
bool _triangle_is_degenerate(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, real_t p_epsilon) const;
|
||||
void _merge_log(String p_string) const;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_mesh(const Ref<Mesh> &p_mesh);
|
||||
Ref<Mesh> get_mesh() const;
|
||||
|
||||
int get_surface_material_count() const;
|
||||
void set_surface_material(int p_surface, const Ref<Material> &p_material);
|
||||
Ref<Material> get_surface_material(int p_surface) const;
|
||||
Ref<Material> get_active_material(int p_surface) const;
|
||||
|
||||
virtual void set_material_override(const Ref<Material> &p_material);
|
||||
|
||||
virtual void set_material_overlay(const Ref<Material> &p_material);
|
||||
|
||||
void set_software_skinning_transform_normals(bool p_enabled);
|
||||
bool is_software_skinning_transform_normals_enabled() const;
|
||||
|
||||
Node *create_trimesh_collision_node();
|
||||
void create_trimesh_collision();
|
||||
|
||||
Node *create_multiple_convex_collisions_node();
|
||||
void create_multiple_convex_collisions();
|
||||
|
||||
Node *create_convex_collision_node(bool p_clean = true, bool p_simplify = false);
|
||||
void create_convex_collision(bool p_clean = true, bool p_simplify = false);
|
||||
|
||||
void create_debug_tangents();
|
||||
|
||||
// merging
|
||||
bool is_mergeable_with(Node *p_other) const;
|
||||
bool merge_meshes(Vector<Variant> p_list, bool p_use_global_space, bool p_check_compatibility);
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
MeshInstance();
|
||||
~MeshInstance();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,89 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* multimesh_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "multimesh_instance.h"
|
||||
|
||||
#include "scene/resources/mesh/multimesh.h"
|
||||
|
||||
void MultiMeshInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_multimesh", "multimesh"), &MultiMeshInstance::set_multimesh);
|
||||
ClassDB::bind_method(D_METHOD("get_multimesh"), &MultiMeshInstance::get_multimesh);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multimesh", PROPERTY_HINT_RESOURCE_TYPE, "MultiMesh"), "set_multimesh", "get_multimesh");
|
||||
}
|
||||
|
||||
void MultiMeshInstance::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
_refresh_interpolated();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMeshInstance::set_multimesh(const Ref<MultiMesh> &p_multimesh) {
|
||||
multimesh = p_multimesh;
|
||||
if (multimesh.is_valid()) {
|
||||
set_base(multimesh->get_rid());
|
||||
_refresh_interpolated();
|
||||
} else {
|
||||
set_base(RID());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMeshInstance::_refresh_interpolated() {
|
||||
if (is_inside_tree() && multimesh.is_valid()) {
|
||||
bool interpolated = is_physics_interpolated_and_enabled();
|
||||
multimesh->set_physics_interpolated(interpolated);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<MultiMesh> MultiMeshInstance::get_multimesh() const {
|
||||
return multimesh;
|
||||
}
|
||||
|
||||
PoolVector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
AABB MultiMeshInstance::get_aabb() const {
|
||||
if (multimesh.is_null()) {
|
||||
return AABB();
|
||||
} else {
|
||||
return multimesh->get_aabb();
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMeshInstance::_physics_interpolated_changed() {
|
||||
VisualInstance::_physics_interpolated_changed();
|
||||
_refresh_interpolated();
|
||||
}
|
||||
|
||||
MultiMeshInstance::MultiMeshInstance() {
|
||||
}
|
||||
|
||||
MultiMeshInstance::~MultiMeshInstance() {
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
#ifndef MULTIMESH_INSTANCE_H
|
||||
#define MULTIMESH_INSTANCE_H
|
||||
/*************************************************************************/
|
||||
/* multimesh_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
#include "core/object/reference.h"
|
||||
|
||||
class MultiMesh;
|
||||
|
||||
class MultiMeshInstance : public GeometryInstance {
|
||||
GDCLASS(MultiMeshInstance, GeometryInstance);
|
||||
|
||||
Ref<MultiMesh> multimesh;
|
||||
|
||||
void _refresh_interpolated();
|
||||
|
||||
protected:
|
||||
virtual void _physics_interpolated_changed();
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
// bind helpers
|
||||
|
||||
public:
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
|
||||
Ref<MultiMesh> get_multimesh() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
|
||||
MultiMeshInstance();
|
||||
~MultiMeshInstance();
|
||||
};
|
||||
|
||||
#endif // MULTIMESH_INSTANCE_H
|
@ -1,507 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* path.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "path.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "scene/resources/curve.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
Path::Path() {
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
if (st && st->is_debugging_paths_hint()) {
|
||||
debug_instance = RS::get_singleton()->instance_create();
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
||||
set_curve(Ref<Curve3D>(memnew(Curve3D))); //create one by default
|
||||
}
|
||||
|
||||
Path::~Path() {
|
||||
if (debug_instance.is_valid()) {
|
||||
RS::get_singleton()->free(debug_instance);
|
||||
}
|
||||
if (debug_mesh.is_valid()) {
|
||||
RS::get_singleton()->free(debug_mesh->get_rid());
|
||||
}
|
||||
}
|
||||
|
||||
void Path::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
if (st && st->is_debugging_paths_hint()) {
|
||||
_update_debug_mesh();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
if (st && st->is_debugging_paths_hint()) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (is_inside_tree() && debug_instance.is_valid()) {
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Path::_update_debug_mesh() {
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
if (!(st && st->is_debugging_paths_hint())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!debug_mesh.is_valid()) {
|
||||
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
|
||||
}
|
||||
|
||||
if (!(curve.is_valid())) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
return;
|
||||
}
|
||||
if (curve->get_point_count() < 2) {
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Vector3> vertex_array;
|
||||
|
||||
for (int i = 1; i < curve->get_point_count(); i++) {
|
||||
Vector3 line_end = curve->get_point_position(i);
|
||||
Vector3 line_start = curve->get_point_position(i - 1);
|
||||
vertex_array.push_back(line_start);
|
||||
vertex_array.push_back(line_end);
|
||||
}
|
||||
|
||||
Array mesh_array;
|
||||
mesh_array.resize(Mesh::ARRAY_MAX);
|
||||
mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
|
||||
|
||||
debug_mesh->clear_surfaces();
|
||||
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_array);
|
||||
|
||||
RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
|
||||
RS::get_singleton()->mesh_surface_set_material(debug_mesh->get_rid(), 0, st->get_debug_paths_material()->get_rid());
|
||||
|
||||
if (is_inside_tree()) {
|
||||
RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
|
||||
RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
|
||||
RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
|
||||
}
|
||||
}
|
||||
|
||||
void Path::_curve_changed() {
|
||||
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
|
||||
update_gizmos();
|
||||
}
|
||||
if (is_inside_tree()) {
|
||||
emit_signal("curve_changed");
|
||||
}
|
||||
|
||||
// update the configuration warnings of all children of type PathFollow
|
||||
// previously used for PathFollowOriented (now enforced orientation is done in PathFollow)
|
||||
if (is_inside_tree()) {
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
PathFollow *child = Object::cast_to<PathFollow>(get_child(i));
|
||||
if (child) {
|
||||
child->update_configuration_warning();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SceneTree *st = SceneTree::get_singleton();
|
||||
if (st && st->is_debugging_paths_hint()) {
|
||||
_update_debug_mesh();
|
||||
}
|
||||
}
|
||||
|
||||
void Path::set_curve(const Ref<Curve3D> &p_curve) {
|
||||
if (curve.is_valid()) {
|
||||
curve->disconnect("changed", this, "_curve_changed");
|
||||
}
|
||||
|
||||
curve = p_curve;
|
||||
|
||||
if (curve.is_valid()) {
|
||||
curve->connect("changed", this, "_curve_changed");
|
||||
}
|
||||
_curve_changed();
|
||||
}
|
||||
|
||||
Ref<Curve3D> Path::get_curve() const {
|
||||
return curve;
|
||||
}
|
||||
|
||||
void Path::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &Path::set_curve);
|
||||
ClassDB::bind_method(D_METHOD("get_curve"), &Path::get_curve);
|
||||
ClassDB::bind_method(D_METHOD("_curve_changed"), &Path::_curve_changed);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("curve_changed"));
|
||||
}
|
||||
|
||||
//////////////
|
||||
|
||||
void PathFollow::_update_transform(bool p_update_xyz_rot) {
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Curve3D> c = path->get_curve();
|
||||
if (!c.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float bl = c->get_baked_length();
|
||||
if (bl == 0.0) {
|
||||
return;
|
||||
}
|
||||
float bi = c->get_bake_interval();
|
||||
float o_next = offset + bi;
|
||||
float o_prev = offset - bi;
|
||||
|
||||
if (loop) {
|
||||
o_next = Math::fposmod(o_next, bl);
|
||||
o_prev = Math::fposmod(o_prev, bl);
|
||||
} else if (rotation_mode == ROTATION_ORIENTED) {
|
||||
if (o_next >= bl) {
|
||||
o_next = bl;
|
||||
}
|
||||
if (o_prev <= 0) {
|
||||
o_prev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 pos = c->interpolate_baked(offset, cubic);
|
||||
Transform t = get_transform();
|
||||
// Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
|
||||
// will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
|
||||
|
||||
if (rotation_mode == ROTATION_ORIENTED) {
|
||||
Vector3 forward = c->interpolate_baked(o_next, cubic) - pos;
|
||||
|
||||
// Try with the previous position
|
||||
if (forward.length_squared() < CMP_EPSILON2) {
|
||||
forward = pos - c->interpolate_baked(o_prev, cubic);
|
||||
}
|
||||
|
||||
if (forward.length_squared() < CMP_EPSILON2) {
|
||||
forward = Vector3(0, 0, 1);
|
||||
} else {
|
||||
forward.normalize();
|
||||
}
|
||||
|
||||
Vector3 up = c->interpolate_baked_up_vector(offset, true);
|
||||
|
||||
if (o_next < offset) {
|
||||
Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
|
||||
Vector3 axis = up.cross(up1);
|
||||
|
||||
if (axis.length_squared() < CMP_EPSILON2) {
|
||||
axis = forward;
|
||||
} else {
|
||||
axis.normalize();
|
||||
}
|
||||
|
||||
up.rotate(axis, up.angle_to(up1) * 0.5f);
|
||||
}
|
||||
|
||||
Vector3 scale = t.basis.get_scale();
|
||||
Vector3 sideways = up.cross(forward).normalized();
|
||||
up = forward.cross(sideways).normalized();
|
||||
|
||||
t.basis.set(sideways, up, forward);
|
||||
t.basis.scale_local(scale);
|
||||
|
||||
t.origin = pos + sideways * h_offset + up * v_offset;
|
||||
} else if (rotation_mode != ROTATION_NONE) {
|
||||
// perform parallel transport
|
||||
//
|
||||
// see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
|
||||
// for a discussion about why not Frenet frame.
|
||||
|
||||
t.origin = pos;
|
||||
|
||||
if (p_update_xyz_rot && delta_offset != 0) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
|
||||
Vector3 t_prev = (pos - c->interpolate_baked(offset - delta_offset, cubic)).normalized();
|
||||
Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized();
|
||||
|
||||
Vector3 axis = t_prev.cross(t_cur);
|
||||
float dot = t_prev.dot(t_cur);
|
||||
|
||||
// acos does clamping.
|
||||
float angle = Math::acos(dot);
|
||||
|
||||
if (likely(!Math::is_zero_approx(angle))) {
|
||||
if (rotation_mode == ROTATION_Y) {
|
||||
// assuming we're referring to global Y-axis. is this correct?
|
||||
axis.x = 0;
|
||||
axis.z = 0;
|
||||
} else if (rotation_mode == ROTATION_XY) {
|
||||
axis.z = 0;
|
||||
} else if (rotation_mode == ROTATION_XYZ) {
|
||||
// all components are allowed
|
||||
}
|
||||
|
||||
if (likely(!Math::is_zero_approx(axis.length()))) {
|
||||
t.rotate_basis(axis.normalized(), angle);
|
||||
}
|
||||
}
|
||||
|
||||
// do the additional tilting
|
||||
float tilt_angle = c->interpolate_baked_tilt(offset);
|
||||
Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
|
||||
|
||||
if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
|
||||
if (rotation_mode == ROTATION_Y) {
|
||||
tilt_axis.x = 0;
|
||||
tilt_axis.z = 0;
|
||||
} else if (rotation_mode == ROTATION_XY) {
|
||||
tilt_axis.z = 0;
|
||||
} else if (rotation_mode == ROTATION_XYZ) {
|
||||
// all components are allowed
|
||||
}
|
||||
|
||||
if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
|
||||
t.rotate_basis(tilt_axis.normalized(), tilt_angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.translate_local(Vector3(h_offset, v_offset, 0));
|
||||
} else {
|
||||
t.origin = pos + Vector3(h_offset, v_offset, 0);
|
||||
}
|
||||
|
||||
set_transform(t);
|
||||
}
|
||||
|
||||
void PathFollow::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
Node *parent = get_parent();
|
||||
if (parent) {
|
||||
path = Object::cast_to<Path>(parent);
|
||||
if (path) {
|
||||
_update_transform(false);
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
path = nullptr;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void PathFollow::set_cubic_interpolation(bool p_enable) {
|
||||
cubic = p_enable;
|
||||
}
|
||||
|
||||
bool PathFollow::get_cubic_interpolation() const {
|
||||
return cubic;
|
||||
}
|
||||
|
||||
void PathFollow::_validate_property(PropertyInfo &property) const {
|
||||
if (property.name == "offset") {
|
||||
float max = 10000;
|
||||
if (path && path->get_curve().is_valid()) {
|
||||
max = path->get_curve()->get_baked_length();
|
||||
}
|
||||
|
||||
property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater";
|
||||
}
|
||||
}
|
||||
|
||||
String PathFollow::get_configuration_warning() const {
|
||||
if (!is_visible_in_tree() || !is_inside_tree()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
String warning = Spatial::get_configuration_warning();
|
||||
if (!Object::cast_to<Path>(get_parent())) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("PathFollow only works when set as a child of a Path node.");
|
||||
} else {
|
||||
Path *path = Object::cast_to<Path>(get_parent());
|
||||
if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path's Curve resource.");
|
||||
}
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
void PathFollow::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &PathFollow::set_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_offset"), &PathFollow::get_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &PathFollow::set_h_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_h_offset"), &PathFollow::get_h_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &PathFollow::set_v_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_v_offset"), &PathFollow::get_v_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &PathFollow::set_unit_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_unit_offset"), &PathFollow::get_unit_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_rotation_mode", "rotation_mode"), &PathFollow::set_rotation_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_rotation_mode"), &PathFollow::get_rotation_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &PathFollow::set_cubic_interpolation);
|
||||
ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &PathFollow::get_cubic_interpolation);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow::set_loop);
|
||||
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow::has_loop);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01,or_lesser,or_greater"), "set_offset", "get_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
|
||||
|
||||
BIND_ENUM_CONSTANT(ROTATION_NONE);
|
||||
BIND_ENUM_CONSTANT(ROTATION_Y);
|
||||
BIND_ENUM_CONSTANT(ROTATION_XY);
|
||||
BIND_ENUM_CONSTANT(ROTATION_XYZ);
|
||||
BIND_ENUM_CONSTANT(ROTATION_ORIENTED);
|
||||
}
|
||||
|
||||
void PathFollow::set_offset(float p_offset) {
|
||||
ERR_FAIL_COND(!isfinite(p_offset));
|
||||
delta_offset = p_offset - offset;
|
||||
offset = p_offset;
|
||||
|
||||
if (path) {
|
||||
if (path->get_curve().is_valid()) {
|
||||
float path_length = path->get_curve()->get_baked_length();
|
||||
|
||||
if (loop) {
|
||||
offset = Math::fposmod(offset, path_length);
|
||||
if (!Math::is_zero_approx(p_offset) && Math::is_zero_approx(offset)) {
|
||||
offset = path_length;
|
||||
}
|
||||
} else {
|
||||
offset = CLAMP(offset, 0, path_length);
|
||||
}
|
||||
}
|
||||
|
||||
_update_transform();
|
||||
}
|
||||
_change_notify("offset");
|
||||
_change_notify("unit_offset");
|
||||
}
|
||||
|
||||
void PathFollow::set_h_offset(float p_h_offset) {
|
||||
h_offset = p_h_offset;
|
||||
if (path) {
|
||||
_update_transform();
|
||||
}
|
||||
}
|
||||
|
||||
float PathFollow::get_h_offset() const {
|
||||
return h_offset;
|
||||
}
|
||||
|
||||
void PathFollow::set_v_offset(float p_v_offset) {
|
||||
v_offset = p_v_offset;
|
||||
if (path) {
|
||||
_update_transform();
|
||||
}
|
||||
}
|
||||
|
||||
float PathFollow::get_v_offset() const {
|
||||
return v_offset;
|
||||
}
|
||||
|
||||
float PathFollow::get_offset() const {
|
||||
return offset;
|
||||
}
|
||||
|
||||
void PathFollow::set_unit_offset(float p_unit_offset) {
|
||||
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
|
||||
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
|
||||
}
|
||||
}
|
||||
|
||||
float PathFollow::get_unit_offset() const {
|
||||
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
|
||||
return get_offset() / path->get_curve()->get_baked_length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
|
||||
rotation_mode = p_rotation_mode;
|
||||
|
||||
update_configuration_warning();
|
||||
_update_transform();
|
||||
}
|
||||
|
||||
PathFollow::RotationMode PathFollow::get_rotation_mode() const {
|
||||
return rotation_mode;
|
||||
}
|
||||
|
||||
void PathFollow::set_loop(bool p_loop) {
|
||||
loop = p_loop;
|
||||
}
|
||||
|
||||
bool PathFollow::has_loop() const {
|
||||
return loop;
|
||||
}
|
||||
|
||||
PathFollow::PathFollow() {
|
||||
offset = 0;
|
||||
delta_offset = 0;
|
||||
h_offset = 0;
|
||||
v_offset = 0;
|
||||
path = nullptr;
|
||||
rotation_mode = ROTATION_XYZ;
|
||||
cubic = true;
|
||||
loop = true;
|
||||
}
|
123
scene/3d/path.h
123
scene/3d/path.h
@ -1,123 +0,0 @@
|
||||
#ifndef PATH_H
|
||||
#define PATH_H
|
||||
/*************************************************************************/
|
||||
/* path.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class Curve3D;
|
||||
|
||||
class Path : public Spatial {
|
||||
GDCLASS(Path, Spatial);
|
||||
|
||||
Ref<Curve3D> curve;
|
||||
|
||||
void _curve_changed();
|
||||
|
||||
RID debug_instance;
|
||||
Ref<ArrayMesh> debug_mesh;
|
||||
|
||||
private:
|
||||
void _update_debug_mesh();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_curve(const Ref<Curve3D> &p_curve);
|
||||
Ref<Curve3D> get_curve() const;
|
||||
|
||||
Path();
|
||||
~Path();
|
||||
};
|
||||
|
||||
class PathFollow : public Spatial {
|
||||
GDCLASS(PathFollow, Spatial);
|
||||
|
||||
public:
|
||||
enum RotationMode {
|
||||
|
||||
ROTATION_NONE,
|
||||
ROTATION_Y,
|
||||
ROTATION_XY,
|
||||
ROTATION_XYZ,
|
||||
ROTATION_ORIENTED
|
||||
};
|
||||
|
||||
private:
|
||||
Path *path;
|
||||
real_t delta_offset; // change in offset since last _update_transform
|
||||
real_t offset;
|
||||
real_t h_offset;
|
||||
real_t v_offset;
|
||||
bool cubic;
|
||||
bool loop;
|
||||
RotationMode rotation_mode;
|
||||
|
||||
void _update_transform(bool p_update_xyz_rot = true);
|
||||
|
||||
protected:
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_offset(float p_offset);
|
||||
float get_offset() const;
|
||||
|
||||
void set_h_offset(float p_h_offset);
|
||||
float get_h_offset() const;
|
||||
|
||||
void set_v_offset(float p_v_offset);
|
||||
float get_v_offset() const;
|
||||
|
||||
void set_unit_offset(float p_unit_offset);
|
||||
float get_unit_offset() const;
|
||||
|
||||
void set_loop(bool p_loop);
|
||||
bool has_loop() const;
|
||||
|
||||
void set_rotation_mode(RotationMode p_rotation_mode);
|
||||
RotationMode get_rotation_mode() const;
|
||||
|
||||
void set_cubic_interpolation(bool p_enable);
|
||||
bool get_cubic_interpolation() const;
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
PathFollow();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(PathFollow::RotationMode);
|
||||
|
||||
#endif // PATH_H
|
@ -1,35 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* position_3d.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "position_3d.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
|
||||
Position3D::Position3D() {
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
#ifndef POSITION_3D_H
|
||||
#define POSITION_3D_H
|
||||
/*************************************************************************/
|
||||
/* position_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class Position3D : public Spatial {
|
||||
GDCLASS(Position3D, Spatial);
|
||||
|
||||
public:
|
||||
Position3D();
|
||||
};
|
||||
|
||||
#endif // POSITION_3D_H
|
@ -1,187 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* proximity_group.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "proximity_group.h"
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
|
||||
void ProximityGroup::_clear_groups() {
|
||||
RBMap<StringName, uint32_t>::Element *E;
|
||||
const int size = 16;
|
||||
|
||||
do {
|
||||
StringName remove_list[size];
|
||||
E = groups.front();
|
||||
int num = 0;
|
||||
while (E && num < size) {
|
||||
if (E->get() != group_version) {
|
||||
remove_list[num++] = E->key();
|
||||
}
|
||||
|
||||
E = E->next();
|
||||
}
|
||||
for (int i = 0; i < num; i++) {
|
||||
groups.erase(remove_list[i]);
|
||||
}
|
||||
} while (E);
|
||||
}
|
||||
|
||||
void ProximityGroup::_update_groups() {
|
||||
if (grid_radius == Vector3(0, 0, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
++group_version;
|
||||
|
||||
Vector3 pos = get_global_transform().get_origin();
|
||||
Vector3 vcell = pos / cell_size;
|
||||
int cell[3] = { Math::fast_ftoi(vcell.x), Math::fast_ftoi(vcell.y), Math::fast_ftoi(vcell.z) };
|
||||
|
||||
_add_groups(cell, group_name, 0);
|
||||
|
||||
_clear_groups();
|
||||
}
|
||||
|
||||
void ProximityGroup::_add_groups(int *p_cell, String p_base, int p_depth) {
|
||||
p_base = p_base + "|";
|
||||
if (grid_radius[p_depth] == 0) {
|
||||
if (p_depth == 2) {
|
||||
_new_group(p_base);
|
||||
} else {
|
||||
_add_groups(p_cell, p_base, p_depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int start = p_cell[p_depth] - grid_radius[p_depth];
|
||||
int end = p_cell[p_depth] + grid_radius[p_depth];
|
||||
|
||||
for (int i = start; i <= end; i++) {
|
||||
String gname = p_base + itos(i);
|
||||
if (p_depth == 2) {
|
||||
_new_group(gname);
|
||||
} else {
|
||||
_add_groups(p_cell, gname, p_depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProximityGroup::_new_group(StringName p_name) {
|
||||
const RBMap<StringName, uint32_t>::Element *E = groups.find(p_name);
|
||||
if (!E) {
|
||||
add_to_group(p_name);
|
||||
}
|
||||
|
||||
groups[p_name] = group_version;
|
||||
}
|
||||
|
||||
void ProximityGroup::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_EXIT_TREE:
|
||||
++group_version;
|
||||
_clear_groups();
|
||||
break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
_update_groups();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProximityGroup::broadcast(String p_method, Variant p_parameters) {
|
||||
RBMap<StringName, uint32_t>::Element *E;
|
||||
E = groups.front();
|
||||
while (E) {
|
||||
get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFAULT, E->key(), "_proximity_group_broadcast", p_method, p_parameters);
|
||||
E = E->next();
|
||||
}
|
||||
}
|
||||
|
||||
void ProximityGroup::_proximity_group_broadcast(String p_method, Variant p_parameters) {
|
||||
if (dispatch_mode == MODE_PROXY) {
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
get_parent()->call(p_method, p_parameters);
|
||||
} else {
|
||||
emit_signal("broadcast", p_method, p_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
void ProximityGroup::set_group_name(const String &p_group_name) {
|
||||
group_name = p_group_name;
|
||||
}
|
||||
|
||||
String ProximityGroup::get_group_name() const {
|
||||
return group_name;
|
||||
}
|
||||
|
||||
void ProximityGroup::set_dispatch_mode(DispatchMode p_mode) {
|
||||
dispatch_mode = p_mode;
|
||||
}
|
||||
|
||||
ProximityGroup::DispatchMode ProximityGroup::get_dispatch_mode() const {
|
||||
return dispatch_mode;
|
||||
}
|
||||
|
||||
void ProximityGroup::set_grid_radius(const Vector3 &p_radius) {
|
||||
grid_radius = p_radius;
|
||||
}
|
||||
|
||||
Vector3 ProximityGroup::get_grid_radius() const {
|
||||
return grid_radius;
|
||||
}
|
||||
|
||||
void ProximityGroup::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_group_name", "name"), &ProximityGroup::set_group_name);
|
||||
ClassDB::bind_method(D_METHOD("get_group_name"), &ProximityGroup::get_group_name);
|
||||
ClassDB::bind_method(D_METHOD("set_dispatch_mode", "mode"), &ProximityGroup::set_dispatch_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_dispatch_mode"), &ProximityGroup::get_dispatch_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_grid_radius", "radius"), &ProximityGroup::set_grid_radius);
|
||||
ClassDB::bind_method(D_METHOD("get_grid_radius"), &ProximityGroup::get_grid_radius);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("broadcast", "method", "parameters"), &ProximityGroup::broadcast);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_proximity_group_broadcast", "method", "parameters"), &ProximityGroup::_proximity_group_broadcast);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "group_name"), "set_group_name", "get_group_name");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "dispatch_mode", PROPERTY_HINT_ENUM, "Proxy,Signal"), "set_dispatch_mode", "get_dispatch_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "grid_radius"), "set_grid_radius", "get_grid_radius");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("broadcast", PropertyInfo(Variant::STRING, "method"), PropertyInfo(Variant::ARRAY, "parameters")));
|
||||
|
||||
BIND_ENUM_CONSTANT(MODE_PROXY);
|
||||
BIND_ENUM_CONSTANT(MODE_SIGNAL);
|
||||
}
|
||||
|
||||
ProximityGroup::ProximityGroup() {
|
||||
group_version = 0;
|
||||
dispatch_mode = MODE_PROXY;
|
||||
|
||||
cell_size = 1.0;
|
||||
grid_radius = Vector3(1, 1, 1);
|
||||
set_notify_transform(true);
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
#ifndef PROXIMITY_GROUP_H
|
||||
#define PROXIMITY_GROUP_H
|
||||
/*************************************************************************/
|
||||
/* proximity_group.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class ProximityGroup : public Spatial {
|
||||
GDCLASS(ProximityGroup, Spatial);
|
||||
|
||||
public:
|
||||
enum DispatchMode {
|
||||
MODE_PROXY,
|
||||
MODE_SIGNAL,
|
||||
};
|
||||
|
||||
private:
|
||||
RBMap<StringName, uint32_t> groups;
|
||||
|
||||
String group_name;
|
||||
DispatchMode dispatch_mode;
|
||||
Vector3 grid_radius;
|
||||
|
||||
float cell_size;
|
||||
uint32_t group_version;
|
||||
|
||||
void _clear_groups();
|
||||
void _update_groups();
|
||||
void _add_groups(int *p_cell, String p_base, int p_depth);
|
||||
void _new_group(StringName p_name);
|
||||
|
||||
void _proximity_group_broadcast(String p_method, Variant p_parameters);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_group_name(const String &p_group_name);
|
||||
String get_group_name() const;
|
||||
|
||||
void set_dispatch_mode(DispatchMode p_mode);
|
||||
DispatchMode get_dispatch_mode() const;
|
||||
|
||||
void set_grid_radius(const Vector3 &p_radius);
|
||||
Vector3 get_grid_radius() const;
|
||||
|
||||
void broadcast(String p_method, Variant p_parameters);
|
||||
|
||||
ProximityGroup();
|
||||
~ProximityGroup() {}
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(ProximityGroup::DispatchMode);
|
||||
|
||||
#endif // PROXIMITY_GROUP_H
|
@ -1,259 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* reflection_probe.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "reflection_probe.h"
|
||||
#include "scene/resources/sky.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
void ReflectionProbe::set_intensity(float p_intensity) {
|
||||
intensity = p_intensity;
|
||||
RS::get_singleton()->reflection_probe_set_intensity(probe, p_intensity);
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_intensity() const {
|
||||
return intensity;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient(Color p_ambient) {
|
||||
interior_ambient = p_ambient;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient);
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient_energy(float p_energy) {
|
||||
interior_ambient_energy = p_energy;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy);
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_interior_ambient_energy() const {
|
||||
return interior_ambient_energy;
|
||||
}
|
||||
|
||||
Color ReflectionProbe::get_interior_ambient() const {
|
||||
return interior_ambient;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) {
|
||||
interior_ambient_probe_contribution = p_contribution;
|
||||
RS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution);
|
||||
}
|
||||
|
||||
float ReflectionProbe::get_interior_ambient_probe_contribution() const {
|
||||
return interior_ambient_probe_contribution;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_max_distance(float p_distance) {
|
||||
max_distance = p_distance;
|
||||
RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance);
|
||||
}
|
||||
float ReflectionProbe::get_max_distance() const {
|
||||
return max_distance;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_extents(const Vector3 &p_extents) {
|
||||
extents = p_extents;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (extents[i] < 0.01) {
|
||||
extents[i] = 0.01;
|
||||
}
|
||||
|
||||
if (extents[i] - 0.01 < ABS(origin_offset[i])) {
|
||||
origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01);
|
||||
_change_notify("origin_offset");
|
||||
}
|
||||
}
|
||||
|
||||
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
|
||||
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
|
||||
_change_notify("extents");
|
||||
update_gizmos();
|
||||
}
|
||||
Vector3 ReflectionProbe::get_extents() const {
|
||||
return extents;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
|
||||
origin_offset = p_extents;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (extents[i] - 0.01 < ABS(origin_offset[i])) {
|
||||
origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01);
|
||||
}
|
||||
}
|
||||
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
|
||||
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
|
||||
|
||||
_change_notify("origin_offset");
|
||||
update_gizmos();
|
||||
}
|
||||
Vector3 ReflectionProbe::get_origin_offset() const {
|
||||
return origin_offset;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_enable_box_projection(bool p_enable) {
|
||||
box_projection = p_enable;
|
||||
RS::get_singleton()->reflection_probe_set_enable_box_projection(probe, p_enable);
|
||||
}
|
||||
bool ReflectionProbe::is_box_projection_enabled() const {
|
||||
return box_projection;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_as_interior(bool p_enable) {
|
||||
interior = p_enable;
|
||||
RS::get_singleton()->reflection_probe_set_as_interior(probe, interior);
|
||||
_change_notify();
|
||||
}
|
||||
|
||||
bool ReflectionProbe::is_set_as_interior() const {
|
||||
return interior;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_enable_shadows(bool p_enable) {
|
||||
enable_shadows = p_enable;
|
||||
RS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_enable);
|
||||
}
|
||||
bool ReflectionProbe::are_shadows_enabled() const {
|
||||
return enable_shadows;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_cull_mask(uint32_t p_layers) {
|
||||
cull_mask = p_layers;
|
||||
RS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers);
|
||||
}
|
||||
uint32_t ReflectionProbe::get_cull_mask() const {
|
||||
return cull_mask;
|
||||
}
|
||||
|
||||
void ReflectionProbe::set_update_mode(UpdateMode p_mode) {
|
||||
update_mode = p_mode;
|
||||
RS::get_singleton()->reflection_probe_set_update_mode(probe, RS::ReflectionProbeUpdateMode(p_mode));
|
||||
}
|
||||
|
||||
ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const {
|
||||
return update_mode;
|
||||
}
|
||||
|
||||
AABB ReflectionProbe::get_aabb() const {
|
||||
AABB aabb;
|
||||
aabb.position = -origin_offset;
|
||||
aabb.size = origin_offset + extents;
|
||||
return aabb;
|
||||
}
|
||||
PoolVector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
|
||||
if (property.name == "interior/ambient_color" || property.name == "interior/ambient_energy" || property.name == "interior/ambient_contrib") {
|
||||
if (!interior) {
|
||||
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectionProbe::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_intensity", "intensity"), &ReflectionProbe::set_intensity);
|
||||
ClassDB::bind_method(D_METHOD("get_intensity"), &ReflectionProbe::get_intensity);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient", "ambient"), &ReflectionProbe::set_interior_ambient);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient"), &ReflectionProbe::get_interior_ambient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient_energy", "ambient_energy"), &ReflectionProbe::set_interior_ambient_energy);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient_energy"), &ReflectionProbe::get_interior_ambient_energy);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_interior_ambient_probe_contribution", "ambient_probe_contribution"), &ReflectionProbe::set_interior_ambient_probe_contribution);
|
||||
ClassDB::bind_method(D_METHOD("get_interior_ambient_probe_contribution"), &ReflectionProbe::get_interior_ambient_probe_contribution);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_max_distance", "max_distance"), &ReflectionProbe::set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_max_distance"), &ReflectionProbe::get_max_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_extents", "extents"), &ReflectionProbe::set_extents);
|
||||
ClassDB::bind_method(D_METHOD("get_extents"), &ReflectionProbe::get_extents);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_origin_offset", "origin_offset"), &ReflectionProbe::set_origin_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_origin_offset"), &ReflectionProbe::get_origin_offset);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_as_interior", "enable"), &ReflectionProbe::set_as_interior);
|
||||
ClassDB::bind_method(D_METHOD("is_set_as_interior"), &ReflectionProbe::is_set_as_interior);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_enable_box_projection", "enable"), &ReflectionProbe::set_enable_box_projection);
|
||||
ClassDB::bind_method(D_METHOD("is_box_projection_enabled"), &ReflectionProbe::is_box_projection_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_enable_shadows", "enable"), &ReflectionProbe::set_enable_shadows);
|
||||
ClassDB::bind_method(D_METHOD("are_shadows_enabled"), &ReflectionProbe::are_shadows_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cull_mask", "layers"), &ReflectionProbe::set_cull_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_cull_mask"), &ReflectionProbe::get_cull_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &ReflectionProbe::set_update_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_update_mode"), &ReflectionProbe::get_update_mode);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_shadows"), "set_enable_shadows", "are_shadows_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
|
||||
|
||||
ADD_GROUP("Interior", "interior_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior_enable"), "set_as_interior", "is_set_as_interior");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "interior_ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_interior_ambient", "get_interior_ambient");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution");
|
||||
|
||||
BIND_ENUM_CONSTANT(UPDATE_ONCE);
|
||||
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
|
||||
}
|
||||
|
||||
ReflectionProbe::ReflectionProbe() {
|
||||
intensity = 1.0;
|
||||
interior_ambient = Color(0, 0, 0);
|
||||
interior_ambient_probe_contribution = 0;
|
||||
interior_ambient_energy = 1.0;
|
||||
max_distance = 0;
|
||||
extents = Vector3(1, 1, 1);
|
||||
origin_offset = Vector3(0, 0, 0);
|
||||
box_projection = false;
|
||||
interior = false;
|
||||
enable_shadows = false;
|
||||
cull_mask = (1 << 20) - 1;
|
||||
update_mode = UPDATE_ONCE;
|
||||
|
||||
probe = RID_PRIME(RenderingServer::get_singleton()->reflection_probe_create());
|
||||
RS::get_singleton()->instance_set_base(get_instance(), probe);
|
||||
set_disable_scale(true);
|
||||
}
|
||||
|
||||
ReflectionProbe::~ReflectionProbe() {
|
||||
RS::get_singleton()->free(probe);
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
#ifndef REFLECTIONPROBE_H
|
||||
#define REFLECTIONPROBE_H
|
||||
/*************************************************************************/
|
||||
/* reflection_probe.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
class ReflectionProbe : public VisualInstance {
|
||||
GDCLASS(ReflectionProbe, VisualInstance);
|
||||
|
||||
public:
|
||||
enum UpdateMode {
|
||||
UPDATE_ONCE,
|
||||
UPDATE_ALWAYS,
|
||||
};
|
||||
|
||||
private:
|
||||
RID probe;
|
||||
float intensity;
|
||||
float max_distance;
|
||||
Vector3 extents;
|
||||
Vector3 origin_offset;
|
||||
bool box_projection;
|
||||
bool enable_shadows;
|
||||
bool interior;
|
||||
Color interior_ambient;
|
||||
float interior_ambient_energy;
|
||||
float interior_ambient_probe_contribution;
|
||||
|
||||
uint32_t cull_mask;
|
||||
UpdateMode update_mode;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
void set_intensity(float p_intensity);
|
||||
float get_intensity() const;
|
||||
|
||||
void set_interior_ambient(Color p_ambient);
|
||||
Color get_interior_ambient() const;
|
||||
|
||||
void set_interior_ambient_energy(float p_energy);
|
||||
float get_interior_ambient_energy() const;
|
||||
|
||||
void set_interior_ambient_probe_contribution(float p_contribution);
|
||||
float get_interior_ambient_probe_contribution() const;
|
||||
|
||||
void set_max_distance(float p_distance);
|
||||
float get_max_distance() const;
|
||||
|
||||
void set_extents(const Vector3 &p_extents);
|
||||
Vector3 get_extents() const;
|
||||
|
||||
void set_origin_offset(const Vector3 &p_extents);
|
||||
Vector3 get_origin_offset() const;
|
||||
|
||||
void set_as_interior(bool p_enable);
|
||||
bool is_set_as_interior() const;
|
||||
|
||||
void set_enable_box_projection(bool p_enable);
|
||||
bool is_box_projection_enabled() const;
|
||||
|
||||
void set_enable_shadows(bool p_enable);
|
||||
bool are_shadows_enabled() const;
|
||||
|
||||
void set_cull_mask(uint32_t p_layers);
|
||||
uint32_t get_cull_mask() const;
|
||||
|
||||
void set_update_mode(UpdateMode p_mode);
|
||||
UpdateMode get_update_mode() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
ReflectionProbe();
|
||||
~ReflectionProbe();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode);
|
||||
|
||||
#endif // REFLECTIONPROBE_H
|
@ -1,226 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* remote_transform.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "remote_transform.h"
|
||||
|
||||
void RemoteTransform::_update_cache() {
|
||||
cache = 0;
|
||||
if (has_node(remote_node)) {
|
||||
Node *node = get_node(remote_node);
|
||||
if (!node || this == node || node->is_a_parent_of(this) || this->is_a_parent_of(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache = node->get_instance_id();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteTransform::_update_remote() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cache) {
|
||||
return;
|
||||
}
|
||||
|
||||
Spatial *n = Object::cast_to<Spatial>(ObjectDB::get_instance(cache));
|
||||
if (!n) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!n->is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//todo make faster
|
||||
if (use_global_coordinates) {
|
||||
if (update_remote_position && update_remote_rotation && update_remote_scale) {
|
||||
n->set_global_transform(get_global_transform());
|
||||
} else {
|
||||
Transform our_trans = get_global_transform();
|
||||
|
||||
if (update_remote_rotation) {
|
||||
n->set_rotation(our_trans.basis.get_rotation());
|
||||
}
|
||||
|
||||
if (update_remote_scale) {
|
||||
n->set_scale(our_trans.basis.get_scale());
|
||||
}
|
||||
|
||||
if (update_remote_position) {
|
||||
Transform n_trans = n->get_global_transform();
|
||||
|
||||
n_trans.set_origin(our_trans.get_origin());
|
||||
n->set_global_transform(n_trans);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (update_remote_position && update_remote_rotation && update_remote_scale) {
|
||||
n->set_transform(get_transform());
|
||||
} else {
|
||||
Transform our_trans = get_transform();
|
||||
|
||||
if (update_remote_rotation) {
|
||||
n->set_rotation(our_trans.basis.get_rotation());
|
||||
}
|
||||
|
||||
if (update_remote_scale) {
|
||||
n->set_scale(our_trans.basis.get_scale());
|
||||
}
|
||||
|
||||
if (update_remote_position) {
|
||||
Transform n_trans = n->get_transform();
|
||||
|
||||
n_trans.set_origin(our_trans.get_origin());
|
||||
n->set_transform(n_trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteTransform::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
_update_cache();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (!is_inside_tree()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cache) {
|
||||
_update_remote();
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteTransform::set_remote_node(const NodePath &p_remote_node) {
|
||||
remote_node = p_remote_node;
|
||||
if (is_inside_tree()) {
|
||||
_update_cache();
|
||||
_update_remote();
|
||||
}
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
NodePath RemoteTransform::get_remote_node() const {
|
||||
return remote_node;
|
||||
}
|
||||
|
||||
void RemoteTransform::set_use_global_coordinates(const bool p_enable) {
|
||||
use_global_coordinates = p_enable;
|
||||
}
|
||||
|
||||
bool RemoteTransform::get_use_global_coordinates() const {
|
||||
return use_global_coordinates;
|
||||
}
|
||||
|
||||
void RemoteTransform::set_update_position(const bool p_update) {
|
||||
update_remote_position = p_update;
|
||||
_update_remote();
|
||||
}
|
||||
|
||||
bool RemoteTransform::get_update_position() const {
|
||||
return update_remote_position;
|
||||
}
|
||||
|
||||
void RemoteTransform::set_update_rotation(const bool p_update) {
|
||||
update_remote_rotation = p_update;
|
||||
_update_remote();
|
||||
}
|
||||
|
||||
bool RemoteTransform::get_update_rotation() const {
|
||||
return update_remote_rotation;
|
||||
}
|
||||
|
||||
void RemoteTransform::set_update_scale(const bool p_update) {
|
||||
update_remote_scale = p_update;
|
||||
_update_remote();
|
||||
}
|
||||
|
||||
bool RemoteTransform::get_update_scale() const {
|
||||
return update_remote_scale;
|
||||
}
|
||||
|
||||
void RemoteTransform::force_update_cache() {
|
||||
_update_cache();
|
||||
}
|
||||
|
||||
String RemoteTransform::get_configuration_warning() const {
|
||||
String warning = Spatial::get_configuration_warning();
|
||||
if (!has_node(remote_node) || !Object::cast_to<Spatial>(get_node(remote_node))) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("The \"Remote Path\" property must point to a valid Spatial or Spatial-derived node to work.");
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
void RemoteTransform::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node);
|
||||
ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node);
|
||||
ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform::force_update_cache);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates);
|
||||
ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform::set_update_position);
|
||||
ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform::get_update_position);
|
||||
ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform::set_update_rotation);
|
||||
ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform::get_update_rotation);
|
||||
ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform::set_update_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform::get_update_scale);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_remote_node", "get_remote_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates");
|
||||
|
||||
ADD_GROUP("Update", "update_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale");
|
||||
}
|
||||
|
||||
RemoteTransform::RemoteTransform() {
|
||||
use_global_coordinates = true;
|
||||
update_remote_position = true;
|
||||
update_remote_rotation = true;
|
||||
update_remote_scale = true;
|
||||
|
||||
cache = 0;
|
||||
set_notify_transform(true);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
#ifndef REMOTETRANSFORM_H
|
||||
#define REMOTETRANSFORM_H
|
||||
/*************************************************************************/
|
||||
/* remote_transform.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class RemoteTransform : public Spatial {
|
||||
GDCLASS(RemoteTransform, Spatial);
|
||||
|
||||
NodePath remote_node;
|
||||
|
||||
ObjectID cache;
|
||||
|
||||
bool use_global_coordinates;
|
||||
bool update_remote_position;
|
||||
bool update_remote_rotation;
|
||||
bool update_remote_scale;
|
||||
|
||||
void _update_remote();
|
||||
void _update_cache();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void set_remote_node(const NodePath &p_remote_node);
|
||||
NodePath get_remote_node() const;
|
||||
|
||||
void set_use_global_coordinates(const bool p_enable);
|
||||
bool get_use_global_coordinates() const;
|
||||
|
||||
void set_update_position(const bool p_update);
|
||||
bool get_update_position() const;
|
||||
|
||||
void set_update_rotation(const bool p_update);
|
||||
bool get_update_rotation() const;
|
||||
|
||||
void set_update_scale(const bool p_update);
|
||||
bool get_update_scale() const;
|
||||
|
||||
void force_update_cache();
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
|
||||
RemoteTransform();
|
||||
};
|
||||
|
||||
#endif // REMOTETRANSFORM_H
|
@ -1,131 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* spatial_velocity_tracker.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "spatial_velocity_tracker.h"
|
||||
#include "core/config/engine.h"
|
||||
|
||||
void SpatialVelocityTracker::set_track_physics_step(bool p_track_physics_step) {
|
||||
physics_step = p_track_physics_step;
|
||||
}
|
||||
|
||||
bool SpatialVelocityTracker::is_tracking_physics_step() const {
|
||||
return physics_step;
|
||||
}
|
||||
void SpatialVelocityTracker::update_position(const Vector3 &p_position) {
|
||||
PositionHistory ph;
|
||||
ph.position = p_position;
|
||||
if (physics_step) {
|
||||
ph.frame = Engine::get_singleton()->get_physics_frames();
|
||||
} else {
|
||||
ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
|
||||
}
|
||||
|
||||
if (position_history_len == 0 || position_history[0].frame != ph.frame) { //in same frame, use latest
|
||||
position_history_len = MIN(position_history.size(), position_history_len + 1);
|
||||
for (int i = position_history_len - 1; i > 0; i--) {
|
||||
position_history.write[i] = position_history[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
position_history.write[0] = ph;
|
||||
}
|
||||
Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const {
|
||||
Vector3 linear_velocity;
|
||||
|
||||
float max_time = 1 / 5.0; //maximum time to interpolate a velocity
|
||||
|
||||
Vector3 distance_accum;
|
||||
float time_accum = 0.0;
|
||||
float base_time = 0.0;
|
||||
|
||||
if (position_history_len) {
|
||||
if (physics_step) {
|
||||
uint64_t base = Engine::get_singleton()->get_physics_frames();
|
||||
base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_physics_ticks_per_second();
|
||||
} else {
|
||||
uint64_t base = Engine::get_singleton()->get_idle_frame_ticks();
|
||||
base_time = double(base - position_history[0].frame) / 1000000.0;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < position_history_len - 1; i++) {
|
||||
float delta = 0.0;
|
||||
uint64_t diff = position_history[i].frame - position_history[i + 1].frame;
|
||||
Vector3 distance = position_history[i].position - position_history[i + 1].position;
|
||||
|
||||
if (physics_step) {
|
||||
delta = float(diff) / Engine::get_singleton()->get_physics_ticks_per_second();
|
||||
} else {
|
||||
delta = double(diff) / 1000000.0;
|
||||
}
|
||||
|
||||
if (base_time + time_accum + delta > max_time) {
|
||||
break;
|
||||
}
|
||||
|
||||
distance_accum += distance;
|
||||
time_accum += delta;
|
||||
}
|
||||
|
||||
if (time_accum) {
|
||||
linear_velocity = distance_accum / time_accum;
|
||||
}
|
||||
|
||||
return linear_velocity;
|
||||
}
|
||||
|
||||
void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) {
|
||||
PositionHistory ph;
|
||||
ph.position = p_new_pos;
|
||||
if (physics_step) {
|
||||
ph.frame = Engine::get_singleton()->get_physics_frames();
|
||||
} else {
|
||||
ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
|
||||
}
|
||||
|
||||
position_history.write[0] = ph;
|
||||
position_history_len = 1;
|
||||
}
|
||||
|
||||
void SpatialVelocityTracker::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_track_physics_step", "enable"), &SpatialVelocityTracker::set_track_physics_step);
|
||||
ClassDB::bind_method(D_METHOD("is_tracking_physics_step"), &SpatialVelocityTracker::is_tracking_physics_step);
|
||||
ClassDB::bind_method(D_METHOD("update_position", "position"), &SpatialVelocityTracker::update_position);
|
||||
ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &SpatialVelocityTracker::get_tracked_linear_velocity);
|
||||
ClassDB::bind_method(D_METHOD("reset", "position"), &SpatialVelocityTracker::reset);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "track_physics_step"), "set_track_physics_step", "is_tracking_physics_step");
|
||||
}
|
||||
|
||||
SpatialVelocityTracker::SpatialVelocityTracker() {
|
||||
position_history.resize(4); // should be configurable
|
||||
position_history_len = 0;
|
||||
physics_step = false;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
#ifndef SPATIAL_VELOCITY_TRACKER_H
|
||||
#define SPATIAL_VELOCITY_TRACKER_H
|
||||
/*************************************************************************/
|
||||
/* spatial_velocity_tracker.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/spatial.h"
|
||||
|
||||
class SpatialVelocityTracker : public Reference {
|
||||
GDCLASS(SpatialVelocityTracker, Reference);
|
||||
|
||||
struct PositionHistory {
|
||||
uint64_t frame;
|
||||
Vector3 position;
|
||||
};
|
||||
|
||||
bool physics_step;
|
||||
Vector<PositionHistory> position_history;
|
||||
int position_history_len;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void reset(const Vector3 &p_new_pos);
|
||||
void set_track_physics_step(bool p_track_physics_step);
|
||||
bool is_tracking_physics_step() const;
|
||||
void update_position(const Vector3 &p_position);
|
||||
Vector3 get_tracked_linear_velocity() const;
|
||||
|
||||
SpatialVelocityTracker();
|
||||
};
|
||||
|
||||
#endif // SPATIAL_VELOCITY_TRACKER_H
|
File diff suppressed because it is too large
Load Diff
@ -1,258 +0,0 @@
|
||||
#ifndef SPRITE_3D_H
|
||||
#define SPRITE_3D_H
|
||||
/*************************************************************************/
|
||||
/* sprite_3d.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/3d/visual_instance.h"
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
|
||||
class TriangleMesh;
|
||||
class SpriteFrames;
|
||||
|
||||
class SpriteBase3D : public GeometryInstance {
|
||||
GDCLASS(SpriteBase3D, GeometryInstance);
|
||||
|
||||
mutable Ref<TriangleMesh> triangle_mesh; //cached
|
||||
|
||||
public:
|
||||
enum DrawFlags {
|
||||
FLAG_TRANSPARENT,
|
||||
FLAG_SHADED,
|
||||
FLAG_DOUBLE_SIDED,
|
||||
FLAG_DISABLE_DEPTH_TEST,
|
||||
FLAG_FIXED_SIZE,
|
||||
FLAG_MAX
|
||||
|
||||
};
|
||||
|
||||
enum AlphaCutMode {
|
||||
ALPHA_CUT_DISABLED,
|
||||
ALPHA_CUT_DISCARD,
|
||||
ALPHA_CUT_OPAQUE_PREPASS
|
||||
};
|
||||
|
||||
private:
|
||||
bool color_dirty;
|
||||
Color color_accum;
|
||||
|
||||
SpriteBase3D *parent_sprite;
|
||||
List<SpriteBase3D *> children;
|
||||
List<SpriteBase3D *>::Element *pI;
|
||||
|
||||
bool centered;
|
||||
Point2 offset;
|
||||
|
||||
bool hflip;
|
||||
bool vflip;
|
||||
|
||||
Color modulate;
|
||||
int render_priority = 0;
|
||||
float opacity;
|
||||
|
||||
Vector3::Axis axis;
|
||||
float pixel_size;
|
||||
AABB aabb;
|
||||
|
||||
RID mesh;
|
||||
RID material;
|
||||
|
||||
bool flags[FLAG_MAX];
|
||||
AlphaCutMode alpha_cut;
|
||||
SpatialMaterial::BillboardMode billboard_mode;
|
||||
bool pending_update;
|
||||
void _im_update();
|
||||
|
||||
void _propagate_color_changed();
|
||||
|
||||
protected:
|
||||
Color _get_color_accum();
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
virtual void _draw() = 0;
|
||||
void draw_texture_rect(Ref<Texture> p_texture, Rect2 p_dst_rect, Rect2 p_src_rect);
|
||||
_FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
|
||||
_FORCE_INLINE_ RID &get_mesh() { return mesh; }
|
||||
_FORCE_INLINE_ RID &get_material() { return material; }
|
||||
|
||||
uint32_t mesh_surface_offsets[RS::ARRAY_MAX];
|
||||
PoolByteArray mesh_buffer;
|
||||
uint32_t mesh_stride[RS::ARRAY_MAX];
|
||||
uint32_t mesh_surface_format;
|
||||
|
||||
void _queue_update();
|
||||
|
||||
public:
|
||||
void set_centered(bool p_center);
|
||||
bool is_centered() const;
|
||||
|
||||
void set_offset(const Point2 &p_offset);
|
||||
Point2 get_offset() const;
|
||||
|
||||
void set_flip_h(bool p_flip);
|
||||
bool is_flipped_h() const;
|
||||
|
||||
void set_flip_v(bool p_flip);
|
||||
bool is_flipped_v() const;
|
||||
|
||||
void set_modulate(const Color &p_color);
|
||||
Color get_modulate() const;
|
||||
|
||||
void set_opacity(float p_amount);
|
||||
float get_opacity() const;
|
||||
|
||||
void set_render_priority(int p_priority);
|
||||
int get_render_priority() const;
|
||||
|
||||
void set_pixel_size(float p_amount);
|
||||
float get_pixel_size() const;
|
||||
|
||||
void set_axis(Vector3::Axis p_axis);
|
||||
Vector3::Axis get_axis() const;
|
||||
|
||||
void set_draw_flag(DrawFlags p_flag, bool p_enable);
|
||||
bool get_draw_flag(DrawFlags p_flag) const;
|
||||
|
||||
void set_alpha_cut_mode(AlphaCutMode p_mode);
|
||||
AlphaCutMode get_alpha_cut_mode() const;
|
||||
void set_billboard_mode(SpatialMaterial::BillboardMode p_mode);
|
||||
SpatialMaterial::BillboardMode get_billboard_mode() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const = 0;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
Ref<TriangleMesh> generate_triangle_mesh() const;
|
||||
|
||||
SpriteBase3D();
|
||||
~SpriteBase3D();
|
||||
};
|
||||
|
||||
class Sprite3D : public SpriteBase3D {
|
||||
GDCLASS(Sprite3D, SpriteBase3D);
|
||||
Ref<Texture> texture;
|
||||
|
||||
bool region;
|
||||
Rect2 region_rect;
|
||||
|
||||
int frame;
|
||||
|
||||
int vframes;
|
||||
int hframes;
|
||||
|
||||
protected:
|
||||
virtual void _draw();
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
void set_texture(const Ref<Texture> &p_texture);
|
||||
Ref<Texture> get_texture() const;
|
||||
|
||||
void set_region(bool p_region);
|
||||
bool is_region() const;
|
||||
|
||||
void set_region_rect(const Rect2 &p_region_rect);
|
||||
Rect2 get_region_rect() const;
|
||||
|
||||
void set_frame(int p_frame);
|
||||
int get_frame() const;
|
||||
|
||||
void set_frame_coords(const Vector2 &p_coord);
|
||||
Vector2 get_frame_coords() const;
|
||||
|
||||
void set_vframes(int p_amount);
|
||||
int get_vframes() const;
|
||||
|
||||
void set_hframes(int p_amount);
|
||||
int get_hframes() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
Sprite3D();
|
||||
//~Sprite3D();
|
||||
};
|
||||
|
||||
class AnimatedSprite3D : public SpriteBase3D {
|
||||
GDCLASS(AnimatedSprite3D, SpriteBase3D);
|
||||
|
||||
Ref<SpriteFrames> frames;
|
||||
bool playing;
|
||||
StringName animation;
|
||||
int frame;
|
||||
|
||||
bool centered;
|
||||
|
||||
float timeout;
|
||||
|
||||
bool hflip;
|
||||
bool vflip;
|
||||
|
||||
Color modulate;
|
||||
|
||||
void _res_changed();
|
||||
|
||||
void _reset_timeout();
|
||||
void _set_playing(bool p_playing);
|
||||
bool _is_playing() const;
|
||||
|
||||
protected:
|
||||
virtual void _draw();
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
|
||||
Ref<SpriteFrames> get_sprite_frames() const;
|
||||
|
||||
void play(const StringName &p_animation = StringName());
|
||||
void stop();
|
||||
bool is_playing() const;
|
||||
|
||||
void set_animation(const StringName &p_animation);
|
||||
StringName get_animation() const;
|
||||
|
||||
void set_frame(int p_frame);
|
||||
int get_frame() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
virtual String get_configuration_warning() const;
|
||||
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options, const String "e_style) const;
|
||||
|
||||
AnimatedSprite3D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags);
|
||||
VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode);
|
||||
#endif // SPRITE_3D_H
|
@ -1,334 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* visibility_notifier.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "visibility_notifier.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
#include "scene/animation/animation_tree.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
|
||||
void VisibilityNotifier::_enter_camera(Camera *p_camera) {
|
||||
ERR_FAIL_COND(cameras.has(p_camera));
|
||||
cameras.insert(p_camera);
|
||||
|
||||
bool in_gameplay = _in_gameplay;
|
||||
|
||||
|
||||
if ((cameras.size() == 1) && in_gameplay) {
|
||||
emit_signal(SceneStringNames::get_singleton()->screen_entered);
|
||||
_screen_enter();
|
||||
}
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera);
|
||||
}
|
||||
|
||||
void VisibilityNotifier::_exit_camera(Camera *p_camera) {
|
||||
ERR_FAIL_COND(!cameras.has(p_camera));
|
||||
cameras.erase(p_camera);
|
||||
|
||||
bool in_gameplay = _in_gameplay;
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->camera_exited, p_camera);
|
||||
if ((cameras.size() == 0) && (in_gameplay)) {
|
||||
emit_signal(SceneStringNames::get_singleton()->screen_exited);
|
||||
|
||||
_screen_exit();
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityNotifier::set_max_distance(real_t p_max_distance) {
|
||||
if (p_max_distance > CMP_EPSILON) {
|
||||
_max_distance = p_max_distance;
|
||||
_max_distance_squared = _max_distance * _max_distance;
|
||||
_max_distance_active = true;
|
||||
|
||||
// make sure world aabb centre is up to date
|
||||
if (is_inside_world()) {
|
||||
AABB world_aabb = get_global_transform().xform(aabb);
|
||||
_world_aabb_center = world_aabb.get_center();
|
||||
}
|
||||
} else {
|
||||
_max_distance = 0.0;
|
||||
_max_distance_squared = 0.0;
|
||||
_max_distance_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityNotifier::set_aabb(const AABB &p_aabb) {
|
||||
if (aabb == p_aabb) {
|
||||
return;
|
||||
}
|
||||
aabb = p_aabb;
|
||||
|
||||
if (is_inside_world()) {
|
||||
AABB world_aabb = get_global_transform().xform(aabb);
|
||||
get_world_3d()->_update_notifier(this, world_aabb);
|
||||
_world_aabb_center = world_aabb.get_center();
|
||||
}
|
||||
|
||||
_change_notify("aabb");
|
||||
update_gizmos();
|
||||
}
|
||||
|
||||
AABB VisibilityNotifier::get_aabb() const {
|
||||
return aabb;
|
||||
}
|
||||
|
||||
void VisibilityNotifier::_refresh_portal_mode() {
|
||||
|
||||
}
|
||||
|
||||
void VisibilityNotifier::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
world = get_world_3d();
|
||||
ERR_FAIL_COND(!world.is_valid());
|
||||
|
||||
AABB world_aabb = get_global_transform().xform(aabb);
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
world->_register_notifier(this, world_aabb);
|
||||
}
|
||||
#else
|
||||
world->_register_notifier(this, world_aabb);
|
||||
#endif
|
||||
_world_aabb_center = world_aabb.get_center();
|
||||
_refresh_portal_mode();
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
AABB world_aabb = get_global_transform().xform(aabb);
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
world->_update_notifier(this, world_aabb);
|
||||
}
|
||||
#else
|
||||
world->_update_notifier(this, world_aabb);
|
||||
#endif
|
||||
if (_max_distance_active) {
|
||||
_world_aabb_center = world_aabb.get_center();
|
||||
}
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
ERR_FAIL_COND(!world.is_valid());
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
||||
world->_remove_notifier(this);
|
||||
}
|
||||
#else
|
||||
world->_remove_notifier(this);
|
||||
#endif
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_ENTER_GAMEPLAY: {
|
||||
_in_gameplay = true;
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_GAMEPLAY: {
|
||||
_in_gameplay = false;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
bool VisibilityNotifier::is_on_screen() const {
|
||||
return (cameras.size() != 0) && _in_gameplay;
|
||||
}
|
||||
|
||||
void VisibilityNotifier::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibilityNotifier::set_aabb);
|
||||
ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier::get_aabb);
|
||||
ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier::is_on_screen);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_max_distance", "distance"), &VisibilityNotifier::set_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_max_distance"), &VisibilityNotifier::get_max_distance);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_max_distance", "get_max_distance");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera")));
|
||||
ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera")));
|
||||
ADD_SIGNAL(MethodInfo("screen_entered"));
|
||||
ADD_SIGNAL(MethodInfo("screen_exited"));
|
||||
}
|
||||
|
||||
VisibilityNotifier::VisibilityNotifier() {
|
||||
aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
|
||||
set_notify_transform(true);
|
||||
_in_gameplay = false;
|
||||
_max_distance_active = false;
|
||||
_max_distance = 0.0;
|
||||
_max_distance_squared = 0.0;
|
||||
_max_distance_leadin_counter = 1; // this could later be exposed as a property if necessary
|
||||
}
|
||||
|
||||
VisibilityNotifier::~VisibilityNotifier() {
|
||||
if (_cull_instance_rid != RID()) {
|
||||
RenderingServer::get_singleton()->free(_cull_instance_rid);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void VisibilityEnabler::_screen_enter() {
|
||||
for (RBMap<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
_change_node_state(E->key(), true);
|
||||
}
|
||||
|
||||
visible = true;
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_screen_exit() {
|
||||
for (RBMap<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
_change_node_state(E->key(), false);
|
||||
}
|
||||
|
||||
visible = false;
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_find_nodes(Node *p_node) {
|
||||
bool add = false;
|
||||
Variant meta;
|
||||
|
||||
if (Object::cast_to<AnimationPlayer>(p_node) || Object::cast_to<AnimationTree>(p_node)) {
|
||||
add = true;
|
||||
}
|
||||
|
||||
{
|
||||
AnimationTree *at = Object::cast_to<AnimationTree>(p_node);
|
||||
if (at) {
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
p_node->connect(SceneStringNames::get_singleton()->tree_exiting, this, "_node_removed", varray(p_node), CONNECT_ONESHOT);
|
||||
nodes[p_node] = meta;
|
||||
_change_node_state(p_node, false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
Node *c = p_node->get_child(i);
|
||||
if (c->get_filename() != String()) {
|
||||
continue; //skip, instance
|
||||
}
|
||||
|
||||
_find_nodes(c);
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Node *from = this;
|
||||
//find where current scene starts
|
||||
while (from->get_parent() && from->get_filename() == String()) {
|
||||
from = from->get_parent();
|
||||
}
|
||||
|
||||
_find_nodes(from);
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (RBMap<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
if (!visible) {
|
||||
_change_node_state(E->key(), true);
|
||||
}
|
||||
E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, "_node_removed");
|
||||
}
|
||||
|
||||
nodes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_change_node_state(Node *p_node, bool p_enabled) {
|
||||
ERR_FAIL_COND(!nodes.has(p_node));
|
||||
|
||||
if (enabler[ENABLER_PAUSE_ANIMATIONS]) {
|
||||
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
|
||||
if (ap) {
|
||||
ap->set_active(p_enabled);
|
||||
} else {
|
||||
AnimationTree *at = Object::cast_to<AnimationTree>(p_node);
|
||||
if (at) {
|
||||
at->set_active(p_enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_node_removed(Node *p_node) {
|
||||
if (!visible) {
|
||||
_change_node_state(p_node, true);
|
||||
}
|
||||
nodes.erase(p_node);
|
||||
}
|
||||
|
||||
void VisibilityEnabler::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler::set_enabler);
|
||||
ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler::is_enabler_enabled);
|
||||
ClassDB::bind_method(D_METHOD("_node_removed"), &VisibilityEnabler::_node_removed);
|
||||
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES);
|
||||
|
||||
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
|
||||
BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
|
||||
BIND_ENUM_CONSTANT(ENABLER_MAX);
|
||||
}
|
||||
|
||||
void VisibilityEnabler::set_enabler(Enabler p_enabler, bool p_enable) {
|
||||
ERR_FAIL_INDEX(p_enabler, ENABLER_MAX);
|
||||
enabler[p_enabler] = p_enable;
|
||||
}
|
||||
bool VisibilityEnabler::is_enabler_enabled(Enabler p_enabler) const {
|
||||
ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false);
|
||||
return enabler[p_enabler];
|
||||
}
|
||||
|
||||
VisibilityEnabler::VisibilityEnabler() {
|
||||
for (int i = 0; i < ENABLER_MAX; i++) {
|
||||
enabler[i] = true;
|
||||
}
|
||||
|
||||
visible = false;
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
#ifndef VISIBILITY_NOTIFIER_H
|
||||
#define VISIBILITY_NOTIFIER_H
|
||||
/*************************************************************************/
|
||||
/* visibility_notifier.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/cull_instance.h"
|
||||
|
||||
class World3D;
|
||||
class Camera;
|
||||
|
||||
class VisibilityNotifier : public CullInstance {
|
||||
GDCLASS(VisibilityNotifier, CullInstance);
|
||||
|
||||
Ref<World3D> world;
|
||||
RBSet<Camera *> cameras;
|
||||
|
||||
AABB aabb;
|
||||
Vector3 _world_aabb_center;
|
||||
|
||||
// if using rooms and portals
|
||||
RID _cull_instance_rid;
|
||||
bool _in_gameplay;
|
||||
|
||||
bool _max_distance_active;
|
||||
real_t _max_distance;
|
||||
real_t _max_distance_squared;
|
||||
|
||||
// This is a first number of frames where distance objects
|
||||
// are forced seen as visible, to make sure their animations
|
||||
// and physics positions etc are something reasonable.
|
||||
uint32_t _max_distance_leadin_counter;
|
||||
|
||||
protected:
|
||||
virtual void _screen_enter() {}
|
||||
virtual void _screen_exit() {}
|
||||
virtual void _refresh_portal_mode();
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
friend struct SpatialIndexer;
|
||||
|
||||
void _enter_camera(Camera *p_camera);
|
||||
void _exit_camera(Camera *p_camera);
|
||||
|
||||
public:
|
||||
void set_aabb(const AABB &p_aabb);
|
||||
AABB get_aabb() const;
|
||||
bool is_on_screen() const;
|
||||
|
||||
// This is only currently kept up to date if max_distance is active
|
||||
const Vector3 &get_world_aabb_center() const { return _world_aabb_center; }
|
||||
|
||||
void set_max_distance(real_t p_max_distance);
|
||||
real_t get_max_distance() const { return _max_distance; }
|
||||
real_t get_max_distance_squared() const { return _max_distance_squared; }
|
||||
bool is_max_distance_active() const { return _max_distance_active; }
|
||||
bool inside_max_distance_leadin() {
|
||||
if (!_max_distance_leadin_counter) {
|
||||
return false;
|
||||
}
|
||||
_max_distance_leadin_counter--;
|
||||
return true;
|
||||
}
|
||||
|
||||
VisibilityNotifier();
|
||||
~VisibilityNotifier();
|
||||
};
|
||||
|
||||
class VisibilityEnabler : public VisibilityNotifier {
|
||||
GDCLASS(VisibilityEnabler, VisibilityNotifier);
|
||||
|
||||
public:
|
||||
enum Enabler {
|
||||
ENABLER_PAUSE_ANIMATIONS,
|
||||
ENABLER_FREEZE_BODIES,
|
||||
ENABLER_MAX
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void _screen_enter();
|
||||
virtual void _screen_exit();
|
||||
|
||||
bool visible;
|
||||
|
||||
void _find_nodes(Node *p_node);
|
||||
|
||||
RBMap<Node *, Variant> nodes;
|
||||
void _node_removed(Node *p_node);
|
||||
bool enabler[ENABLER_MAX];
|
||||
|
||||
void _change_node_state(Node *p_node, bool p_enabled);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_enabler(Enabler p_enabler, bool p_enable);
|
||||
bool is_enabler_enabled(Enabler p_enabler) const;
|
||||
|
||||
VisibilityEnabler();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(VisibilityEnabler::Enabler);
|
||||
|
||||
#endif // VISIBILITY_NOTIFIER_H
|
@ -1,398 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* visual_instance.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "visual_instance.h"
|
||||
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/rendering_server.h"
|
||||
//#include "skeleton.h"
|
||||
|
||||
AABB VisualInstance::get_transformed_aabb() const {
|
||||
return get_global_transform().xform(get_aabb());
|
||||
}
|
||||
|
||||
void VisualInstance::_refresh_portal_mode() {
|
||||
}
|
||||
|
||||
void VisualInstance::_update_visibility() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool visible = is_visible_in_tree();
|
||||
|
||||
// keep a quick flag available in each node.
|
||||
// no need to call is_visible_in_tree all over the place,
|
||||
// providing it is propagated with a notification.
|
||||
bool already_visible = _is_vi_visible();
|
||||
_set_vi_visible(visible);
|
||||
|
||||
// if making visible, make sure the visual server is up to date with the transform
|
||||
if (visible && (!already_visible)) {
|
||||
if (!_is_using_identity_transform()) {
|
||||
Transform gt = get_global_transform();
|
||||
RenderingServer::get_singleton()->instance_set_transform(instance, gt);
|
||||
}
|
||||
}
|
||||
|
||||
_change_notify("visible");
|
||||
RS::get_singleton()->instance_set_visible(get_instance(), visible);
|
||||
}
|
||||
|
||||
void VisualInstance::set_instance_use_identity_transform(bool p_enable) {
|
||||
// prevent sending instance transforms when using global coords
|
||||
_set_use_identity_transform(p_enable);
|
||||
|
||||
if (is_inside_tree()) {
|
||||
if (p_enable) {
|
||||
// want to make sure instance is using identity transform
|
||||
RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
|
||||
} else {
|
||||
// want to make sure instance is up to date
|
||||
RenderingServer::get_singleton()->instance_set_transform(instance, Transform());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisualInstance::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_WORLD: {
|
||||
// CHECK SKELETON => moving skeleton attaching logic to MeshInstance
|
||||
/*
|
||||
Skeleton *skeleton=Object::cast_to<Skeleton>(get_parent());
|
||||
if (skeleton)
|
||||
RenderingServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() );
|
||||
*/
|
||||
ERR_FAIL_COND(get_world_3d().is_null());
|
||||
RenderingServer::get_singleton()->instance_set_scenario(instance, get_world_3d()->get_scenario());
|
||||
_update_visibility();
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (_is_vi_visible() || is_physics_interpolated_and_enabled()) {
|
||||
if (!_is_using_identity_transform()) {
|
||||
Transform gt = get_global_transform();
|
||||
RenderingServer::get_singleton()->instance_set_transform(instance, gt);
|
||||
|
||||
// For instance when first adding to the tree, when the previous transform is
|
||||
// unset, to prevent streaking from the origin.
|
||||
if (_is_physics_interpolation_reset_requested()) {
|
||||
if (_is_vi_visible()) {
|
||||
_notification(NOTIFICATION_RESET_PHYSICS_INTERPOLATION);
|
||||
}
|
||||
_set_physics_interpolation_reset_requested(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
|
||||
if (_is_vi_visible() && is_physics_interpolated()) {
|
||||
RenderingServer::get_singleton()->instance_reset_physics_interpolation(instance);
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
RenderingServer::get_singleton()->instance_set_scenario(instance, RID());
|
||||
RenderingServer::get_singleton()->instance_attach_skeleton(instance, RID());
|
||||
|
||||
// the vi visible flag is always set to invisible when outside the tree,
|
||||
// so it can detect re-entering the tree and becoming visible, and send
|
||||
// the transform to the visual server
|
||||
_set_vi_visible(false);
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_visibility();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualInstance::_physics_interpolated_changed() {
|
||||
RenderingServer::get_singleton()->instance_set_interpolated(instance, is_physics_interpolated());
|
||||
}
|
||||
|
||||
RID VisualInstance::get_instance() const {
|
||||
return instance;
|
||||
}
|
||||
|
||||
RID VisualInstance::_get_visual_instance_rid() const {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void VisualInstance::set_layer_mask(uint32_t p_mask) {
|
||||
layers = p_mask;
|
||||
RenderingServer::get_singleton()->instance_set_layer_mask(instance, p_mask);
|
||||
}
|
||||
|
||||
uint32_t VisualInstance::get_layer_mask() const {
|
||||
return layers;
|
||||
}
|
||||
|
||||
void VisualInstance::set_layer_mask_bit(int p_layer, bool p_enable) {
|
||||
ERR_FAIL_INDEX(p_layer, 32);
|
||||
if (p_enable) {
|
||||
set_layer_mask(layers | (1 << p_layer));
|
||||
} else {
|
||||
set_layer_mask(layers & (~(1 << p_layer)));
|
||||
}
|
||||
}
|
||||
|
||||
bool VisualInstance::get_layer_mask_bit(int p_layer) const {
|
||||
ERR_FAIL_INDEX_V(p_layer, 32, false);
|
||||
return (layers & (1 << p_layer));
|
||||
}
|
||||
|
||||
void VisualInstance::set_sorting_offset(float p_offset) {
|
||||
sorting_offset = p_offset;
|
||||
RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center);
|
||||
}
|
||||
|
||||
float VisualInstance::get_sorting_offset() {
|
||||
return sorting_offset;
|
||||
}
|
||||
|
||||
void VisualInstance::set_sorting_use_aabb_center(bool p_enabled) {
|
||||
sorting_use_aabb_center = p_enabled;
|
||||
RenderingServer::get_singleton()->instance_set_pivot_data(instance, sorting_offset, sorting_use_aabb_center);
|
||||
}
|
||||
|
||||
bool VisualInstance::is_sorting_use_aabb_center() {
|
||||
return sorting_use_aabb_center;
|
||||
}
|
||||
|
||||
void VisualInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance::_get_visual_instance_rid);
|
||||
ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance::set_base);
|
||||
ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance::get_base);
|
||||
ClassDB::bind_method(D_METHOD("get_instance"), &VisualInstance::get_instance);
|
||||
ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &VisualInstance::set_layer_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance::get_layer_mask);
|
||||
ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "layer", "enabled"), &VisualInstance::set_layer_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_layer_mask_bit", "layer"), &VisualInstance::get_layer_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb);
|
||||
ClassDB::bind_method(D_METHOD("set_sorting_offset", "offset"), &VisualInstance::set_sorting_offset);
|
||||
ClassDB::bind_method(D_METHOD("get_sorting_offset"), &VisualInstance::get_sorting_offset);
|
||||
ClassDB::bind_method(D_METHOD("set_sorting_use_aabb_center", "enabled"), &VisualInstance::set_sorting_use_aabb_center);
|
||||
ClassDB::bind_method(D_METHOD("is_sorting_use_aabb_center"), &VisualInstance::is_sorting_use_aabb_center);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
|
||||
|
||||
ADD_GROUP("Sorting", "sorting_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "sorting_offset"), "set_sorting_offset", "get_sorting_offset");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sorting_use_aabb_center"), "set_sorting_use_aabb_center", "is_sorting_use_aabb_center");
|
||||
}
|
||||
|
||||
void VisualInstance::set_base(const RID &p_base) {
|
||||
RenderingServer::get_singleton()->instance_set_base(instance, p_base);
|
||||
base = p_base;
|
||||
}
|
||||
|
||||
RID VisualInstance::get_base() const {
|
||||
return base;
|
||||
}
|
||||
|
||||
VisualInstance::VisualInstance() {
|
||||
instance = RID_PRIME(RenderingServer::get_singleton()->instance_create());
|
||||
RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id());
|
||||
layers = 1;
|
||||
sorting_offset = 0.0f;
|
||||
sorting_use_aabb_center = true;
|
||||
set_notify_transform(true);
|
||||
}
|
||||
|
||||
VisualInstance::~VisualInstance() {
|
||||
RenderingServer::get_singleton()->free(instance);
|
||||
}
|
||||
|
||||
void GeometryInstance::set_material_override(const Ref<Material> &p_material) {
|
||||
material_override = p_material;
|
||||
RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
|
||||
}
|
||||
|
||||
Ref<Material> GeometryInstance::get_material_override() const {
|
||||
return material_override;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_material_overlay(const Ref<Material> &p_material) {
|
||||
material_overlay = p_material;
|
||||
RS::get_singleton()->instance_geometry_set_material_overlay(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
|
||||
}
|
||||
|
||||
Ref<Material> GeometryInstance::get_material_overlay() const {
|
||||
return material_overlay;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_lod_min_distance(float p_dist) {
|
||||
lod_min_distance = p_dist;
|
||||
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_lod_min_distance() const {
|
||||
return lod_min_distance;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_lod_max_distance(float p_dist) {
|
||||
lod_max_distance = p_dist;
|
||||
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_lod_max_distance() const {
|
||||
return lod_max_distance;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_lod_min_hysteresis(float p_dist) {
|
||||
lod_min_hysteresis = p_dist;
|
||||
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_lod_min_hysteresis() const {
|
||||
return lod_min_hysteresis;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_lod_max_hysteresis(float p_dist) {
|
||||
lod_max_hysteresis = p_dist;
|
||||
RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_lod_max_hysteresis() const {
|
||||
return lod_max_hysteresis;
|
||||
}
|
||||
|
||||
void GeometryInstance::_notification(int p_what) {
|
||||
}
|
||||
|
||||
void GeometryInstance::set_flag(Flags p_flag, bool p_value) {
|
||||
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
|
||||
if (flags[p_flag] == p_value) {
|
||||
return;
|
||||
}
|
||||
|
||||
flags[p_flag] = p_value;
|
||||
RS::get_singleton()->instance_geometry_set_flag(get_instance(), (RS::InstanceFlags)p_flag, p_value);
|
||||
}
|
||||
|
||||
bool GeometryInstance::get_flag(Flags p_flag) const {
|
||||
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
|
||||
|
||||
return flags[p_flag];
|
||||
}
|
||||
|
||||
void GeometryInstance::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) {
|
||||
shadow_casting_setting = p_shadow_casting_setting;
|
||||
|
||||
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (RS::ShadowCastingSetting)p_shadow_casting_setting);
|
||||
}
|
||||
|
||||
GeometryInstance::ShadowCastingSetting GeometryInstance::get_cast_shadows_setting() const {
|
||||
return shadow_casting_setting;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_extra_cull_margin(float p_margin) {
|
||||
ERR_FAIL_COND(p_margin < 0);
|
||||
extra_cull_margin = p_margin;
|
||||
RS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin);
|
||||
}
|
||||
|
||||
float GeometryInstance::get_extra_cull_margin() const {
|
||||
return extra_cull_margin;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_custom_aabb(AABB aabb) {
|
||||
RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb);
|
||||
}
|
||||
|
||||
void GeometryInstance::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance::set_material_override);
|
||||
ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance::get_material_override);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_material_overlay", "material"), &GeometryInstance::set_material_overlay);
|
||||
ClassDB::bind_method(D_METHOD("get_material_overlay"), &GeometryInstance::get_material_overlay);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance::set_flag);
|
||||
ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance::get_flag);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
|
||||
ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis", "mode"), &GeometryInstance::set_lod_max_hysteresis);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance::get_lod_max_hysteresis);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance::set_lod_max_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance::get_lod_max_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance::set_lod_min_hysteresis);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance::get_lod_min_hysteresis);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_lod_min_distance", "mode"), &GeometryInstance::set_lod_min_distance);
|
||||
ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance::get_lod_min_distance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin);
|
||||
ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &GeometryInstance::set_custom_aabb);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_aabb"), &GeometryInstance::get_aabb);
|
||||
|
||||
ADD_GROUP("Geometry", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_override", "get_material_override");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_overlay", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_overlay", "get_material_overlay");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
|
||||
|
||||
ADD_GROUP("LOD", "lod_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis");
|
||||
|
||||
//ADD_SIGNAL( MethodInfo("visibility_changed"));
|
||||
|
||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
|
||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON);
|
||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
|
||||
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
|
||||
|
||||
BIND_ENUM_CONSTANT(FLAG_DRAW_NEXT_FRAME_IF_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(FLAG_MAX);
|
||||
}
|
||||
|
||||
GeometryInstance::GeometryInstance() {
|
||||
lod_min_distance = 0;
|
||||
lod_max_distance = 0;
|
||||
lod_min_hysteresis = 0;
|
||||
lod_max_hysteresis = 0;
|
||||
|
||||
for (int i = 0; i < FLAG_MAX; i++) {
|
||||
flags[i] = false;
|
||||
}
|
||||
|
||||
shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
|
||||
extra_cull_margin = 0;
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
#ifndef VISUAL_INSTANCE_H
|
||||
#define VISUAL_INSTANCE_H
|
||||
/*************************************************************************/
|
||||
/* visual_instance.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/containers/rid.h"
|
||||
#include "core/math/face3.h"
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/3d/cull_instance.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class Material;
|
||||
|
||||
class VisualInstance : public CullInstance {
|
||||
GDCLASS(VisualInstance, CullInstance);
|
||||
OBJ_CATEGORY("3D Visual Nodes");
|
||||
|
||||
RID base;
|
||||
RID instance;
|
||||
uint32_t layers;
|
||||
float sorting_offset;
|
||||
bool sorting_use_aabb_center;
|
||||
|
||||
RID _get_visual_instance_rid() const;
|
||||
|
||||
protected:
|
||||
void _update_visibility();
|
||||
virtual void _refresh_portal_mode();
|
||||
virtual void _physics_interpolated_changed();
|
||||
void set_instance_use_identity_transform(bool p_enable);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum GetFacesFlags {
|
||||
FACES_SOLID = 1, // solid geometry
|
||||
FACES_ENCLOSING = 2,
|
||||
FACES_DYNAMIC = 4 // dynamic object geometry
|
||||
};
|
||||
|
||||
RID get_instance() const;
|
||||
virtual AABB get_aabb() const = 0;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
|
||||
|
||||
virtual AABB get_transformed_aabb() const; // helper
|
||||
|
||||
void set_base(const RID &p_base);
|
||||
RID get_base() const;
|
||||
|
||||
void set_layer_mask(uint32_t p_mask);
|
||||
uint32_t get_layer_mask() const;
|
||||
|
||||
void set_layer_mask_bit(int p_layer, bool p_enable);
|
||||
bool get_layer_mask_bit(int p_layer) const;
|
||||
|
||||
void set_sorting_offset(float p_offset);
|
||||
float get_sorting_offset();
|
||||
|
||||
void set_sorting_use_aabb_center(bool p_enabled);
|
||||
bool is_sorting_use_aabb_center();
|
||||
|
||||
VisualInstance();
|
||||
~VisualInstance();
|
||||
};
|
||||
|
||||
class GeometryInstance : public VisualInstance {
|
||||
GDCLASS(GeometryInstance, VisualInstance);
|
||||
|
||||
public:
|
||||
enum Flags {
|
||||
FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE,
|
||||
FLAG_MAX = RS::INSTANCE_FLAG_MAX,
|
||||
};
|
||||
|
||||
enum ShadowCastingSetting {
|
||||
SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF,
|
||||
SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON,
|
||||
SHADOW_CASTING_SETTING_DOUBLE_SIDED = RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED,
|
||||
SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY
|
||||
};
|
||||
|
||||
private:
|
||||
bool flags[FLAG_MAX];
|
||||
ShadowCastingSetting shadow_casting_setting;
|
||||
Ref<Material> material_override;
|
||||
Ref<Material> material_overlay;
|
||||
float lod_min_distance;
|
||||
float lod_max_distance;
|
||||
float lod_min_hysteresis;
|
||||
float lod_max_hysteresis;
|
||||
|
||||
float extra_cull_margin;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_flag(Flags p_flag, bool p_value);
|
||||
bool get_flag(Flags p_flag) const;
|
||||
|
||||
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
|
||||
ShadowCastingSetting get_cast_shadows_setting() const;
|
||||
|
||||
void set_lod_min_distance(float p_dist);
|
||||
float get_lod_min_distance() const;
|
||||
|
||||
void set_lod_max_distance(float p_dist);
|
||||
float get_lod_max_distance() const;
|
||||
|
||||
void set_lod_min_hysteresis(float p_dist);
|
||||
float get_lod_min_hysteresis() const;
|
||||
|
||||
void set_lod_max_hysteresis(float p_dist);
|
||||
float get_lod_max_hysteresis() const;
|
||||
|
||||
virtual void set_material_override(const Ref<Material> &p_material);
|
||||
Ref<Material> get_material_override() const;
|
||||
|
||||
virtual void set_material_overlay(const Ref<Material> &p_material);
|
||||
Ref<Material> get_material_overlay() const;
|
||||
|
||||
void set_extra_cull_margin(float p_margin);
|
||||
float get_extra_cull_margin() const;
|
||||
|
||||
void set_custom_aabb(AABB aabb);
|
||||
|
||||
GeometryInstance();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(GeometryInstance::Flags);
|
||||
VARIANT_ENUM_CAST(GeometryInstance::ShadowCastingSetting);
|
||||
|
||||
#endif
|
@ -1,118 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* world_environment.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "world_environment_3d.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/main/viewport.h"
|
||||
|
||||
#include "scene/resources/environment_3d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
|
||||
void WorldEnvironment3D::_notification(int p_what) {
|
||||
if (p_what == Spatial::NOTIFICATION_ENTER_WORLD || p_what == Spatial::NOTIFICATION_ENTER_TREE) {
|
||||
if (environment.is_valid()) {
|
||||
if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
|
||||
WARN_PRINT("World already has an environment (Another WorldEnvironment3D?), overriding.");
|
||||
}
|
||||
get_viewport()->find_world_3d()->set_environment(environment);
|
||||
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
|
||||
}
|
||||
|
||||
} else if (p_what == Spatial::NOTIFICATION_EXIT_WORLD || p_what == Spatial::NOTIFICATION_EXIT_TREE) {
|
||||
if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
|
||||
get_viewport()->find_world_3d()->set_environment(Ref<Environment3D>());
|
||||
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldEnvironment3D::set_environment(const Ref<Environment3D> &p_environment) {
|
||||
if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) {
|
||||
get_viewport()->find_world_3d()->set_environment(Ref<Environment3D>());
|
||||
remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
|
||||
//clean up
|
||||
}
|
||||
|
||||
environment = p_environment;
|
||||
if (is_inside_tree() && environment.is_valid()) {
|
||||
if (get_viewport()->find_world_3d()->get_environment().is_valid()) {
|
||||
WARN_PRINT("World already has an environment (Another WorldEnvironment3D?), overriding.");
|
||||
}
|
||||
get_viewport()->find_world_3d()->set_environment(environment);
|
||||
add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()));
|
||||
}
|
||||
|
||||
update_configuration_warning();
|
||||
}
|
||||
|
||||
Ref<Environment3D> WorldEnvironment3D::get_environment() const {
|
||||
return environment;
|
||||
}
|
||||
|
||||
String WorldEnvironment3D::get_configuration_warning() const {
|
||||
String warning = Node::get_configuration_warning();
|
||||
if (!environment.is_valid()) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("WorldEnvironment3D requires its \"Environment3D\" property to contain an Environment3D to have a visible effect.");
|
||||
return warning;
|
||||
}
|
||||
|
||||
if (/*!is_visible_in_tree() ||*/ !is_inside_tree()) {
|
||||
return String();
|
||||
}
|
||||
|
||||
List<Node *> nodes;
|
||||
get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), &nodes);
|
||||
|
||||
if (nodes.size() > 1) {
|
||||
if (warning != String()) {
|
||||
warning += "\n\n";
|
||||
}
|
||||
warning += TTR("Only one WorldEnvironment3D is allowed per scene (or set of instanced scenes).");
|
||||
}
|
||||
|
||||
// Commenting this warning for now, I think it makes no sense. If anyone can figure out what its supposed to do, feedback welcome. Else it should be deprecated.
|
||||
//if (environment.is_valid() && get_viewport() && !get_viewport()->get_camera() && environment->get_background() != Environment3D::BG_CANVAS) {
|
||||
// return TTR("This WorldEnvironment3D is ignored. Either add a Camera (for 3D scenes) or set this environment's Background Mode to Canvas (for 2D scenes).");
|
||||
//}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
void WorldEnvironment3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_environment", "env"), &WorldEnvironment3D::set_environment);
|
||||
ClassDB::bind_method(D_METHOD("get_environment"), &WorldEnvironment3D::get_environment);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment3D"), "set_environment", "get_environment");
|
||||
}
|
||||
|
||||
WorldEnvironment3D::WorldEnvironment3D() {
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
#ifndef SCENARIO_FX_H
|
||||
#define SCENARIO_FX_H
|
||||
/*************************************************************************/
|
||||
/* world_environment.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/main/node.h"
|
||||
|
||||
class Environment3D;
|
||||
|
||||
class WorldEnvironment3D : public Node {
|
||||
GDCLASS(WorldEnvironment3D, Node);
|
||||
|
||||
Ref<Environment3D> environment;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_environment(const Ref<Environment3D> &p_environment);
|
||||
Ref<Environment3D> get_environment() const;
|
||||
|
||||
String get_configuration_warning() const;
|
||||
|
||||
WorldEnvironment3D();
|
||||
};
|
||||
|
||||
#endif
|
@ -33,66 +33,10 @@
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/message_queue.h"
|
||||
#include "scene/main/node_2d.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/animation/animation.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
#include "modules/skeleton_3d/nodes/skeleton.h"
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_settings.h"
|
||||
|
||||
#ifdef MODULE_SKELETON_2D_ENABLED
|
||||
#include "modules/skeleton_2d/nodes/skeleton_2d.h"
|
||||
#endif
|
||||
|
||||
void AnimatedValuesBackup::update_skeletons() {
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
if (entries[i].bone_idx != -1) {
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
// 3D bone
|
||||
Object::cast_to<Skeleton>(entries[i].object)->notification(Skeleton::NOTIFICATION_UPDATE_SKELETON);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MODULE_SKELETON_2D_ENABLED
|
||||
Bone2D *bone = Object::cast_to<Bone2D>(entries[i].object);
|
||||
if (bone && bone->skeleton) {
|
||||
// 2D bone
|
||||
bone->skeleton->_update_transform();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatedValuesBackup::restore() const {
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
const AnimatedValuesBackup::Entry *entry = &entries[i];
|
||||
if (entry->bone_idx == -1) {
|
||||
entry->object->set_indexed(entry->subpath, entry->value);
|
||||
}
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
else {
|
||||
Array arr = entry->value;
|
||||
if (arr.size() == 3) {
|
||||
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_position(entry->bone_idx, arr[0]);
|
||||
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_rotation(entry->bone_idx, arr[1]);
|
||||
Object::cast_to<Skeleton>(entry->object)->set_bone_pose_scale(entry->bone_idx, arr[2]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatedValuesBackup::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("restore"), &AnimatedValuesBackup::restore);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
|
||||
String name = p_name;
|
||||
|
||||
@ -313,61 +257,6 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
|
||||
node_cache->resource = resource;
|
||||
node_cache->node_2d = Object::cast_to<Node2D>(child);
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
if (a->track_get_type(i) == Animation::TYPE_POSITION_3D || a->track_get_type(i) == Animation::TYPE_ROTATION_3D || a->track_get_type(i) == Animation::TYPE_SCALE_3D) {
|
||||
// special cases and caches for transform tracks
|
||||
|
||||
if (node_cache->last_setup_pass != setup_pass) {
|
||||
node_cache->loc_used = false;
|
||||
node_cache->rot_used = false;
|
||||
node_cache->scale_used = false;
|
||||
}
|
||||
|
||||
// cache spatial
|
||||
node_cache->spatial = Object::cast_to<Spatial>(child);
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
// cache skeleton
|
||||
node_cache->skeleton = Object::cast_to<Skeleton>(child);
|
||||
if (node_cache->skeleton) {
|
||||
if (a->track_get_path(i).get_subname_count() == 1) {
|
||||
StringName bone_name = a->track_get_path(i).get_subname(0);
|
||||
|
||||
node_cache->bone_idx = node_cache->skeleton->find_bone(bone_name);
|
||||
if (node_cache->bone_idx < 0) {
|
||||
// broken track (nonexistent bone)
|
||||
node_cache->skeleton = nullptr;
|
||||
node_cache->spatial = nullptr;
|
||||
ERR_CONTINUE(node_cache->bone_idx < 0);
|
||||
}
|
||||
Transform rest = node_cache->skeleton->get_bone_rest(bone_idx);
|
||||
node_cache->init_loc = rest.origin;
|
||||
node_cache->init_rot = rest.basis.get_rotation_quaternion();
|
||||
node_cache->init_scale = rest.basis.get_scale();
|
||||
} else {
|
||||
// no property, just use spatialnode
|
||||
node_cache->skeleton = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (a->track_get_type(i)) {
|
||||
case Animation::TYPE_POSITION_3D: {
|
||||
node_cache->loc_used = true;
|
||||
} break;
|
||||
case Animation::TYPE_ROTATION_3D: {
|
||||
node_cache->rot_used = true;
|
||||
} break;
|
||||
case Animation::TYPE_SCALE_3D: {
|
||||
node_cache->scale_used = true;
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
|
||||
if (!node_cache->property_anim.has(a->track_get_path(i).get_concatenated_subnames())) {
|
||||
TrackNodeCache::PropertyAnim pa;
|
||||
@ -433,85 +322,10 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
|
||||
|
||||
switch (a->track_get_type(i)) {
|
||||
case Animation::TYPE_POSITION_3D: {
|
||||
#ifndef _3D_DISABLED
|
||||
if (!nc->spatial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3 loc;
|
||||
|
||||
Error err = a->position_track_interpolate(i, p_time, &loc);
|
||||
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
|
||||
|
||||
if (err != OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nc->accum_pass != accum_pass) {
|
||||
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
|
||||
cache_update[cache_update_size++] = nc;
|
||||
nc->accum_pass = accum_pass;
|
||||
nc->loc_accum = loc;
|
||||
nc->rot_accum = nc->init_rot;
|
||||
nc->scale_accum = nc->init_scale;
|
||||
} else {
|
||||
nc->loc_accum = nc->loc_accum.linear_interpolate(loc, p_interp);
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
} break;
|
||||
case Animation::TYPE_ROTATION_3D: {
|
||||
#ifndef _3D_DISABLED
|
||||
if (!nc->spatial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Quaternion rot;
|
||||
|
||||
Error err = a->rotation_track_interpolate(i, p_time, &rot);
|
||||
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
|
||||
|
||||
if (err != OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nc->accum_pass != accum_pass) {
|
||||
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
|
||||
cache_update[cache_update_size++] = nc;
|
||||
nc->accum_pass = accum_pass;
|
||||
nc->loc_accum = nc->init_loc;
|
||||
nc->rot_accum = rot;
|
||||
nc->scale_accum = nc->init_scale;
|
||||
} else {
|
||||
nc->rot_accum = nc->rot_accum.slerp(rot, p_interp);
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
} break;
|
||||
case Animation::TYPE_SCALE_3D: {
|
||||
#ifndef _3D_DISABLED
|
||||
if (!nc->spatial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3 scale;
|
||||
|
||||
Error err = a->scale_track_interpolate(i, p_time, &scale);
|
||||
//ERR_CONTINUE(err!=OK); //used for testing, should be removed
|
||||
|
||||
if (err != OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nc->accum_pass != accum_pass) {
|
||||
ERR_CONTINUE(cache_update_size >= NODE_CACHE_UPDATE_MAX);
|
||||
cache_update[cache_update_size++] = nc;
|
||||
nc->accum_pass = accum_pass;
|
||||
nc->loc_accum = nc->init_loc;
|
||||
nc->rot_accum = nc->init_rot;
|
||||
nc->scale_accum = scale;
|
||||
} else {
|
||||
nc->scale_accum = nc->scale_accum.linear_interpolate(scale, p_interp);
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
if (!nc->node) {
|
||||
@ -966,35 +780,6 @@ void AnimationPlayer::_animation_update_transforms() {
|
||||
TrackNodeCache *nc = cache_update[i];
|
||||
|
||||
ERR_CONTINUE(nc->accum_pass != accum_pass);
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
if (nc->skeleton && nc->bone_idx >= 0) {
|
||||
if (nc->loc_used) {
|
||||
nc->skeleton->set_bone_pose_position(nc->bone_idx, nc->loc_accum);
|
||||
}
|
||||
if (nc->rot_used) {
|
||||
nc->skeleton->set_bone_pose_rotation(nc->bone_idx, nc->rot_accum);
|
||||
}
|
||||
if (nc->scale_used) {
|
||||
nc->skeleton->set_bone_pose_scale(nc->bone_idx, nc->scale_accum);
|
||||
}
|
||||
|
||||
} else
|
||||
#endif
|
||||
if (nc->spatial) {
|
||||
if (nc->loc_used) {
|
||||
nc->spatial->set_translation(nc->loc_accum);
|
||||
}
|
||||
if (nc->rot_used) {
|
||||
nc->spatial->set_rotation(nc->rot_accum.get_euler());
|
||||
}
|
||||
if (nc->scale_used) {
|
||||
nc->spatial->set_scale(nc->scale_accum);
|
||||
}
|
||||
}
|
||||
#endif // _3D_DISABLED
|
||||
}
|
||||
}
|
||||
|
||||
@ -1642,104 +1427,6 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i
|
||||
Node::get_argument_options(p_function, p_idx, r_options, quote_style);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Ref<AnimatedValuesBackup> AnimationPlayer::backup_animated_values(Node *p_root_override) {
|
||||
Ref<AnimatedValuesBackup> backup;
|
||||
if (!playback.current.from) {
|
||||
return backup;
|
||||
}
|
||||
|
||||
_ensure_node_caches(playback.current.from, p_root_override);
|
||||
|
||||
backup.instance();
|
||||
for (int i = 0; i < playback.current.from->node_cache.size(); i++) {
|
||||
TrackNodeCache *nc = playback.current.from->node_cache[i];
|
||||
if (!nc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
if (nc->skeleton) {
|
||||
if (nc->bone_idx == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AnimatedValuesBackup::Entry entry;
|
||||
|
||||
Array arr;
|
||||
arr.resize(3);
|
||||
arr[0] = nc->skeleton->get_bone_pose_position(nc->bone_idx);
|
||||
arr[1] = nc->skeleton->get_bone_pose_rotation(nc->bone_idx);
|
||||
arr[2] = nc->skeleton->get_bone_pose_scale(nc->bone_idx);
|
||||
entry.value = nc;
|
||||
|
||||
backup->entries.push_back(entry);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (nc->spatial) {
|
||||
AnimatedValuesBackup::Entry entry;
|
||||
entry.object = nc->spatial;
|
||||
entry.subpath.push_back("transform");
|
||||
entry.value = nc->spatial->get_transform();
|
||||
entry.bone_idx = -1;
|
||||
backup->entries.push_back(entry);
|
||||
} else {
|
||||
for (RBMap<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.front(); E; E = E->next()) {
|
||||
AnimatedValuesBackup::Entry entry;
|
||||
entry.object = E->value().object;
|
||||
entry.subpath = E->value().subpath;
|
||||
bool valid;
|
||||
entry.value = E->value().object->get_indexed(E->value().subpath, &valid);
|
||||
entry.bone_idx = -1;
|
||||
if (valid) {
|
||||
backup->entries.push_back(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return backup;
|
||||
}
|
||||
|
||||
Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
|
||||
ERR_FAIL_COND_V(!can_apply_reset(), Ref<AnimatedValuesBackup>());
|
||||
|
||||
Ref<Animation> reset_anim = animation_set["RESET"].animation;
|
||||
|
||||
Node *root_node = get_node_or_null(root);
|
||||
ERR_FAIL_COND_V(!root_node, Ref<AnimatedValuesBackup>());
|
||||
|
||||
AnimationPlayer *aux_player = memnew(AnimationPlayer);
|
||||
EditorNode::get_singleton()->add_child(aux_player);
|
||||
aux_player->add_animation("RESET", reset_anim);
|
||||
aux_player->set_assigned_animation("RESET");
|
||||
// Forcing the use of the original root because the scene where original player belongs may be not the active one
|
||||
Node *root = get_node(get_root());
|
||||
Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(root);
|
||||
aux_player->seek(0.0f, true);
|
||||
aux_player->queue_delete();
|
||||
|
||||
if (p_user_initiated) {
|
||||
Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values();
|
||||
old_values->restore();
|
||||
|
||||
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
|
||||
ur->create_action(TTR("Anim Apply Reset"));
|
||||
ur->add_do_method(new_values.ptr(), "restore");
|
||||
ur->add_undo_method(old_values.ptr(), "restore");
|
||||
ur->commit_action();
|
||||
}
|
||||
|
||||
return old_values;
|
||||
}
|
||||
|
||||
bool AnimationPlayer::can_apply_reset() const {
|
||||
return has_animation("RESET") && playback.assigned != StringName("RESET");
|
||||
}
|
||||
#endif
|
||||
|
||||
void AnimationPlayer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_node_removed"), &AnimationPlayer::_node_removed);
|
||||
ClassDB::bind_method(D_METHOD("_animation_changed"), &AnimationPlayer::_animation_changed);
|
||||
|
@ -33,40 +33,10 @@
|
||||
#include "core/object/reference.h"
|
||||
#include "scene/main/node.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
class Resource;
|
||||
class Spatial;
|
||||
class Node2D;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
class Skeleton;
|
||||
#endif
|
||||
class Animation;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
class AnimatedValuesBackup : public Reference {
|
||||
GDCLASS(AnimatedValuesBackup, Reference);
|
||||
|
||||
struct Entry {
|
||||
Object *object;
|
||||
Vector<StringName> subpath; // Unused if bone
|
||||
int bone_idx; // -1 if not a bone
|
||||
Variant value;
|
||||
};
|
||||
Vector<Entry> entries;
|
||||
|
||||
friend class AnimationPlayer;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void update_skeletons();
|
||||
void restore() const;
|
||||
};
|
||||
#endif
|
||||
|
||||
class AnimationPlayer : public Node {
|
||||
GDCLASS(AnimationPlayer, Node);
|
||||
OBJ_CATEGORY("Animation Nodes");
|
||||
@ -104,11 +74,7 @@ private:
|
||||
uint32_t id;
|
||||
Ref<Resource> resource;
|
||||
Node *node;
|
||||
Spatial *spatial;
|
||||
Node2D *node_2d;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
Skeleton *skeleton;
|
||||
#endif
|
||||
int bone_idx;
|
||||
// accumulated transforms
|
||||
|
||||
@ -170,11 +136,7 @@ private:
|
||||
TrackNodeCache() :
|
||||
id(0),
|
||||
node(nullptr),
|
||||
spatial(nullptr),
|
||||
node_2d(nullptr),
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
skeleton(nullptr),
|
||||
#endif
|
||||
bone_idx(-1),
|
||||
accum_pass(0),
|
||||
audio_playing(false),
|
||||
|
@ -34,14 +34,9 @@
|
||||
#include "animation_player.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/method_bind_ext.gen.inc"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
#include "modules/skeleton_3d/nodes/skeleton.h"
|
||||
#endif
|
||||
|
||||
void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
if (get_script_instance()) {
|
||||
Array parameters = get_script_instance()->call("get_parameter_list");
|
||||
@ -617,85 +612,6 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
|
||||
case Animation::TYPE_POSITION_3D:
|
||||
case Animation::TYPE_ROTATION_3D:
|
||||
case Animation::TYPE_SCALE_3D: {
|
||||
#ifndef _3D_DISABLED
|
||||
Spatial *spatial = Object::cast_to<Spatial>(child);
|
||||
|
||||
if (!spatial) {
|
||||
ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to spatial: '" + String(path) + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
//Always uses TYPE_POSITION_3D as type (Constructor)
|
||||
//Note that these are stored using their path as the key in a hashmap
|
||||
//So only one will be allocated for a given spatial
|
||||
//track_xform->type = Animation::TYPE_POSITION_3D;
|
||||
TrackCacheTransform *track_xform = memnew(TrackCacheTransform);
|
||||
|
||||
track_xform->spatial = spatial;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
track_xform->skeleton = nullptr;
|
||||
track_xform->bone_idx = -1;
|
||||
#endif
|
||||
|
||||
bool has_rest = false;
|
||||
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
if (path.get_subname_count() == 1 && Object::cast_to<Skeleton>(spatial)) {
|
||||
Skeleton *sk = Object::cast_to<Skeleton>(spatial);
|
||||
track_xform->skeleton = sk;
|
||||
int bone_idx = sk->find_bone(path.get_subname(0));
|
||||
if (bone_idx != -1) {
|
||||
has_rest = true;
|
||||
track_xform->bone_idx = bone_idx;
|
||||
Transform rest = sk->get_bone_rest(bone_idx);
|
||||
track_xform->init_loc = rest.origin;
|
||||
track_xform->ref_rot = rest.basis.get_rotation_quaternion();
|
||||
track_xform->init_rot = track_xform->ref_rot.log();
|
||||
track_xform->init_scale = rest.basis.get_scale();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
track_xform->object = spatial;
|
||||
track_xform->object_id = track_xform->object->get_instance_id();
|
||||
|
||||
track = track_xform;
|
||||
|
||||
switch (track_type) {
|
||||
case Animation::TYPE_POSITION_3D: {
|
||||
track_xform->loc_used = true;
|
||||
} break;
|
||||
case Animation::TYPE_ROTATION_3D: {
|
||||
track_xform->rot_used = true;
|
||||
} break;
|
||||
case Animation::TYPE_SCALE_3D: {
|
||||
track_xform->scale_used = true;
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
// For non Skeleton3D bone animation.
|
||||
if (has_reset_anim && !has_rest) {
|
||||
int rt = reset_anim->find_track(path, track_type);
|
||||
if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
|
||||
switch (track_type) {
|
||||
case Animation::TYPE_POSITION_3D: {
|
||||
track_xform->init_loc = reset_anim->track_get_key_value(rt, 0);
|
||||
} break;
|
||||
case Animation::TYPE_ROTATION_3D: {
|
||||
track_xform->ref_rot = reset_anim->track_get_key_value(rt, 0);
|
||||
track_xform->init_rot = track_xform->ref_rot.log();
|
||||
} break;
|
||||
case Animation::TYPE_SCALE_3D: {
|
||||
track_xform->init_scale = reset_anim->track_get_key_value(rt, 0);
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
case Animation::TYPE_METHOD: {
|
||||
TrackCacheMethod *track_method = memnew(TrackCacheMethod);
|
||||
@ -1491,30 +1407,6 @@ void AnimationTree::_process_graph(float p_delta) {
|
||||
|
||||
root_motion_transform = xform;
|
||||
}
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
else if (t->skeleton && t->bone_idx >= 0) {
|
||||
if (t->loc_used) {
|
||||
t->skeleton->set_bone_pose_position(t->bone_idx, t->loc);
|
||||
}
|
||||
if (t->rot_used) {
|
||||
t->skeleton->set_bone_pose_rotation(t->bone_idx, t->rot);
|
||||
}
|
||||
if (t->scale_used) {
|
||||
t->skeleton->set_bone_pose_scale(t->bone_idx, t->scale);
|
||||
}
|
||||
|
||||
} else if (!t->skeleton) {
|
||||
if (t->loc_used) {
|
||||
t->spatial->set_translation(t->loc);
|
||||
}
|
||||
if (t->rot_used) {
|
||||
t->spatial->set_rotation(t->rot.get_euler());
|
||||
}
|
||||
if (t->scale_used) {
|
||||
t->spatial->set_scale(t->scale);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // _3D_DISABLED
|
||||
} break;
|
||||
case Animation::TYPE_VALUE: {
|
||||
|
@ -34,12 +34,6 @@
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/animation/animation.h"
|
||||
|
||||
#include "modules/modules_enabled.gen.h"
|
||||
|
||||
class Spatial;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
class Skeleton;
|
||||
#endif
|
||||
class AnimationNodeBlendTree;
|
||||
class AnimationPlayer;
|
||||
class AnimationTree;
|
||||
@ -189,11 +183,6 @@ private:
|
||||
};
|
||||
|
||||
struct TrackCacheTransform : public TrackCache {
|
||||
Spatial *spatial;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
Skeleton *skeleton;
|
||||
int bone_idx;
|
||||
#endif
|
||||
bool loc_used;
|
||||
bool rot_used;
|
||||
bool scale_used;
|
||||
@ -207,11 +196,6 @@ private:
|
||||
|
||||
TrackCacheTransform() {
|
||||
type = Animation::TYPE_POSITION_3D;
|
||||
spatial = nullptr;
|
||||
#ifdef MODULE_SKELETON_3D_ENABLED
|
||||
bone_idx = -1;
|
||||
skeleton = nullptr;
|
||||
#endif
|
||||
loc_used = false;
|
||||
rot_used = false;
|
||||
scale_used = false;
|
||||
|
@ -1,203 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* root_motion_view.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "root_motion_view.h"
|
||||
#include "scene/animation/animation_tree.h"
|
||||
#include "scene/resources/material/material.h"
|
||||
#include "scene/resources/material/spatial_material.h"
|
||||
|
||||
void RootMotionView::set_animation_path(const NodePath &p_path) {
|
||||
path = p_path;
|
||||
first = true;
|
||||
}
|
||||
|
||||
NodePath RootMotionView::get_animation_path() const {
|
||||
return path;
|
||||
}
|
||||
|
||||
void RootMotionView::set_color(const Color &p_color) {
|
||||
color = p_color;
|
||||
first = true;
|
||||
}
|
||||
|
||||
Color RootMotionView::get_color() const {
|
||||
return color;
|
||||
}
|
||||
|
||||
void RootMotionView::set_cell_size(float p_size) {
|
||||
cell_size = p_size;
|
||||
first = true;
|
||||
}
|
||||
|
||||
float RootMotionView::get_cell_size() const {
|
||||
return cell_size;
|
||||
}
|
||||
|
||||
void RootMotionView::set_radius(float p_radius) {
|
||||
radius = p_radius;
|
||||
first = true;
|
||||
}
|
||||
|
||||
float RootMotionView::get_radius() const {
|
||||
return radius;
|
||||
}
|
||||
|
||||
void RootMotionView::set_zero_y(bool p_zero_y) {
|
||||
zero_y = p_zero_y;
|
||||
}
|
||||
|
||||
bool RootMotionView::get_zero_y() const {
|
||||
return zero_y;
|
||||
}
|
||||
|
||||
void RootMotionView::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
RS::get_singleton()->immediate_set_material(immediate, SpatialMaterial::get_material_rid_for_2d(false, true, false, false, false));
|
||||
first = true;
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_INTERNAL_PROCESS || p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
|
||||
Transform transform;
|
||||
|
||||
if (has_node(path)) {
|
||||
Node *node = get_node(path);
|
||||
|
||||
AnimationTree *tree = Object::cast_to<AnimationTree>(node);
|
||||
if (tree && tree->is_active() && tree->get_root_motion_track() != NodePath()) {
|
||||
if (is_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_PHYSICS) {
|
||||
set_process_internal(false);
|
||||
set_physics_process_internal(true);
|
||||
}
|
||||
|
||||
if (is_physics_processing_internal() && tree->get_process_mode() == AnimationTree::ANIMATION_PROCESS_IDLE) {
|
||||
set_process_internal(true);
|
||||
set_physics_process_internal(false);
|
||||
}
|
||||
|
||||
transform = tree->get_root_motion_transform();
|
||||
}
|
||||
}
|
||||
|
||||
if (!first && transform == Transform()) {
|
||||
return;
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
||||
transform.orthonormalize(); //don't want scale, too imprecise
|
||||
|
||||
accumulated = accumulated * transform;
|
||||
accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size);
|
||||
if (zero_y) {
|
||||
accumulated.origin.y = 0;
|
||||
}
|
||||
accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size);
|
||||
|
||||
RS::get_singleton()->immediate_clear(immediate);
|
||||
|
||||
int cells_in_radius = int((radius / cell_size) + 1.0);
|
||||
|
||||
RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_LINES);
|
||||
for (int i = -cells_in_radius; i < cells_in_radius; i++) {
|
||||
for (int j = -cells_in_radius; j < cells_in_radius; j++) {
|
||||
Vector3 from(i * cell_size, 0, j * cell_size);
|
||||
Vector3 from_i((i + 1) * cell_size, 0, j * cell_size);
|
||||
Vector3 from_j(i * cell_size, 0, (j + 1) * cell_size);
|
||||
from = accumulated.xform_inv(from);
|
||||
from_i = accumulated.xform_inv(from_i);
|
||||
from_j = accumulated.xform_inv(from_j);
|
||||
|
||||
Color c = color, c_i = color, c_j = color;
|
||||
c.a *= MAX(0, 1.0 - from.length() / radius);
|
||||
c_i.a *= MAX(0, 1.0 - from_i.length() / radius);
|
||||
c_j.a *= MAX(0, 1.0 - from_j.length() / radius);
|
||||
|
||||
RS::get_singleton()->immediate_color(immediate, c);
|
||||
RS::get_singleton()->immediate_vertex(immediate, from);
|
||||
|
||||
RS::get_singleton()->immediate_color(immediate, c_i);
|
||||
RS::get_singleton()->immediate_vertex(immediate, from_i);
|
||||
|
||||
RS::get_singleton()->immediate_color(immediate, c);
|
||||
RS::get_singleton()->immediate_vertex(immediate, from);
|
||||
|
||||
RS::get_singleton()->immediate_color(immediate, c_j);
|
||||
RS::get_singleton()->immediate_vertex(immediate, from_j);
|
||||
}
|
||||
}
|
||||
|
||||
RS::get_singleton()->immediate_end(immediate);
|
||||
}
|
||||
}
|
||||
|
||||
AABB RootMotionView::get_aabb() const {
|
||||
return AABB(Vector3(-radius, 0, -radius), Vector3(radius * 2, 0.001, radius * 2));
|
||||
}
|
||||
PoolVector<Face3> RootMotionView::get_faces(uint32_t p_usage_flags) const {
|
||||
return PoolVector<Face3>();
|
||||
}
|
||||
|
||||
void RootMotionView::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_animation_path", "path"), &RootMotionView::set_animation_path);
|
||||
ClassDB::bind_method(D_METHOD("get_animation_path"), &RootMotionView::get_animation_path);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_color", "color"), &RootMotionView::set_color);
|
||||
ClassDB::bind_method(D_METHOD("get_color"), &RootMotionView::get_color);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_cell_size", "size"), &RootMotionView::set_cell_size);
|
||||
ClassDB::bind_method(D_METHOD("get_cell_size"), &RootMotionView::get_cell_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_radius", "size"), &RootMotionView::set_radius);
|
||||
ClassDB::bind_method(D_METHOD("get_radius"), &RootMotionView::get_radius);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_zero_y", "enable"), &RootMotionView::set_zero_y);
|
||||
ClassDB::bind_method(D_METHOD("get_zero_y"), &RootMotionView::get_zero_y);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "AnimationTree"), "set_animation_path", "get_animation_path");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_cell_size", "get_cell_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.1,16,0.01,or_greater"), "set_radius", "get_radius");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_y"), "set_zero_y", "get_zero_y");
|
||||
}
|
||||
|
||||
RootMotionView::RootMotionView() {
|
||||
zero_y = true;
|
||||
radius = 10;
|
||||
cell_size = 1;
|
||||
set_process_internal(true);
|
||||
immediate = RID_PRIME(RenderingServer::get_singleton()->immediate_create());
|
||||
set_base(immediate);
|
||||
color = Color(0.5, 0.5, 1.0);
|
||||
}
|
||||
|
||||
RootMotionView::~RootMotionView() {
|
||||
set_base(RID());
|
||||
RenderingServer::get_singleton()->free(immediate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
#ifndef ROOT_MOTION_VIEW_H
|
||||
#define ROOT_MOTION_VIEW_H
|
||||
/*************************************************************************/
|
||||
/* root_motion_view.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/visual_instance.h"
|
||||
|
||||
class RootMotionView : public VisualInstance {
|
||||
GDCLASS(RootMotionView, VisualInstance);
|
||||
|
||||
public:
|
||||
RID immediate;
|
||||
NodePath path;
|
||||
float cell_size;
|
||||
float radius;
|
||||
bool use_in_game;
|
||||
Color color;
|
||||
bool first;
|
||||
bool zero_y;
|
||||
|
||||
Transform accumulated;
|
||||
|
||||
private:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_animation_path(const NodePath &p_path);
|
||||
NodePath get_animation_path() const;
|
||||
|
||||
void set_color(const Color &p_color);
|
||||
Color get_color() const;
|
||||
|
||||
void set_cell_size(float p_size);
|
||||
float get_cell_size() const;
|
||||
|
||||
void set_radius(float p_radius);
|
||||
float get_radius() const;
|
||||
|
||||
void set_zero_y(bool p_zero_y);
|
||||
bool get_zero_y() const;
|
||||
|
||||
virtual AABB get_aabb() const;
|
||||
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
|
||||
|
||||
RootMotionView();
|
||||
~RootMotionView();
|
||||
};
|
||||
|
||||
#endif // ROOT_MOTION_VIEW_H
|
@ -304,11 +304,6 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
|
||||
|
||||
//Below everything should only happen on the main thread. Should probably add a check.
|
||||
} else if (command == "request_scene_tree") {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (scene_tree) {
|
||||
scene_tree->_debugger_request_tree();
|
||||
}
|
||||
#endif
|
||||
} else if (command == "request_video_mem") {
|
||||
_send_video_memory();
|
||||
} else if (command == "inspect_object") {
|
||||
@ -329,28 +324,6 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
|
||||
if (scene_tree) {
|
||||
scene_tree->get_root()->set_canvas_transform_override(transform);
|
||||
}
|
||||
} else if (command == "override_camera_3D:set") {
|
||||
bool enable = cmd[1];
|
||||
|
||||
if (scene_tree) {
|
||||
scene_tree->get_root()->enable_camera_override(enable);
|
||||
}
|
||||
} else if (command == "override_camera_3D:transform") {
|
||||
Transform transform = cmd[1];
|
||||
bool is_perspective = cmd[2];
|
||||
float size_or_fov = cmd[3];
|
||||
float near = cmd[4];
|
||||
float far = cmd[5];
|
||||
|
||||
if (scene_tree) {
|
||||
if (is_perspective) {
|
||||
scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
|
||||
} else {
|
||||
scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
|
||||
}
|
||||
scene_tree->get_root()->set_camera_override_transform(transform);
|
||||
}
|
||||
|
||||
} else if (command == "reload_scripts") {
|
||||
reload_all_scripts = true;
|
||||
} else if (command == "breakpoint") {
|
||||
@ -366,7 +339,6 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue,
|
||||
} else if (command == "set_skip_breakpoints") {
|
||||
skip_breakpoints = cmd[1];
|
||||
} else {
|
||||
_parse_live_edit(cmd);
|
||||
}
|
||||
} else {
|
||||
OS::get_singleton()->delay_usec(10000);
|
||||
@ -616,73 +588,6 @@ void ScriptDebuggerRemote::_err_handler(void *ud, const char *p_func, const char
|
||||
sdr->send_error(String::utf8(p_func), String::utf8(p_file), p_line, String::utf8(p_err), String::utf8(p_descr), p_type, si);
|
||||
}
|
||||
|
||||
bool ScriptDebuggerRemote::_parse_live_edit(const Array &p_command) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
String cmdstr = p_command[0];
|
||||
if (!scene_tree || !cmdstr.begins_with("live_")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmdstr == "live_set_root") {
|
||||
scene_tree->_live_edit_root_func(p_command[1], p_command[2]);
|
||||
|
||||
} else if (cmdstr == "live_node_path") {
|
||||
scene_tree->_live_edit_node_path_func(p_command[1], p_command[2]);
|
||||
|
||||
} else if (cmdstr == "live_res_path") {
|
||||
scene_tree->_live_edit_res_path_func(p_command[1], p_command[2]);
|
||||
|
||||
} else if (cmdstr == "live_node_prop_res") {
|
||||
scene_tree->_live_edit_node_set_res_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_node_prop") {
|
||||
scene_tree->_live_edit_node_set_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_res_prop_res") {
|
||||
scene_tree->_live_edit_res_set_res_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_res_prop") {
|
||||
scene_tree->_live_edit_res_set_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_node_call") {
|
||||
scene_tree->_live_edit_node_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7], p_command[8], p_command[9], p_command[10]);
|
||||
|
||||
} else if (cmdstr == "live_res_call") {
|
||||
scene_tree->_live_edit_res_call_func(p_command[1], p_command[2], p_command[3], p_command[4], p_command[5], p_command[6], p_command[7], p_command[8], p_command[9], p_command[10]);
|
||||
|
||||
} else if (cmdstr == "live_create_node") {
|
||||
scene_tree->_live_edit_create_node_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_instance_node") {
|
||||
scene_tree->_live_edit_instance_node_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_remove_node") {
|
||||
scene_tree->_live_edit_remove_node_func(p_command[1]);
|
||||
|
||||
} else if (cmdstr == "live_remove_and_keep_node") {
|
||||
scene_tree->_live_edit_remove_and_keep_node_func(p_command[1], p_command[2]);
|
||||
|
||||
} else if (cmdstr == "live_restore_node") {
|
||||
scene_tree->_live_edit_restore_node_func(p_command[1], p_command[2], p_command[3]);
|
||||
|
||||
} else if (cmdstr == "live_duplicate_node") {
|
||||
scene_tree->_live_edit_duplicate_node_func(p_command[1], p_command[2]);
|
||||
|
||||
} else if (cmdstr == "live_reparent_node") {
|
||||
scene_tree->_live_edit_reparent_node_func(p_command[1], p_command[2], p_command[3], p_command[4]);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
|
||||
Object *obj = ObjectDB::get_instance(p_id);
|
||||
if (!obj) {
|
||||
@ -865,11 +770,6 @@ void ScriptDebuggerRemote::_poll_events() {
|
||||
} else if (command == "save_node") {
|
||||
_save_node(cmd[1], cmd[2]);
|
||||
} else if (command == "request_scene_tree") {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (scene_tree) {
|
||||
scene_tree->_debugger_request_tree();
|
||||
}
|
||||
#endif
|
||||
} else if (command == "request_video_mem") {
|
||||
_send_video_memory();
|
||||
} else if (command == "inspect_object") {
|
||||
@ -918,28 +818,6 @@ void ScriptDebuggerRemote::_poll_events() {
|
||||
if (scene_tree) {
|
||||
scene_tree->get_root()->set_canvas_transform_override(transform);
|
||||
}
|
||||
} else if (command == "override_camera_3D:set") {
|
||||
bool enable = cmd[1];
|
||||
|
||||
if (scene_tree) {
|
||||
scene_tree->get_root()->enable_camera_override(enable);
|
||||
}
|
||||
} else if (command == "override_camera_3D:transform") {
|
||||
Transform transform = cmd[1];
|
||||
bool is_perspective = cmd[2];
|
||||
float size_or_fov = cmd[3];
|
||||
float near = cmd[4];
|
||||
float far = cmd[5];
|
||||
|
||||
if (scene_tree) {
|
||||
if (is_perspective) {
|
||||
scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
|
||||
} else {
|
||||
scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
|
||||
}
|
||||
scene_tree->get_root()->set_camera_override_transform(transform);
|
||||
}
|
||||
|
||||
} else if (command == "reload_scripts") {
|
||||
reload_all_scripts = true;
|
||||
} else if (command == "breakpoint") {
|
||||
@ -952,7 +830,6 @@ void ScriptDebuggerRemote::_poll_events() {
|
||||
} else if (command == "set_skip_breakpoints") {
|
||||
skip_breakpoints = cmd[1];
|
||||
} else {
|
||||
_parse_live_edit(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,8 +133,6 @@ class ScriptDebuggerRemote : public ScriptDebugger {
|
||||
|
||||
SceneTree *scene_tree;
|
||||
|
||||
bool _parse_live_edit(const Array &p_command);
|
||||
|
||||
void _set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value);
|
||||
|
||||
void _send_object_id(ObjectID p_id);
|
||||
|
@ -632,7 +632,7 @@ void FileDialog::set_current_file(const String &p_file) {
|
||||
int lp = p_file.rfind(".");
|
||||
if (lp != -1) {
|
||||
file->select(0, lp);
|
||||
if (file->is_inside_tree() && !get_tree()->is_node_being_edited(file)) {
|
||||
if (file->is_inside_tree()) {
|
||||
file->grab_focus();
|
||||
}
|
||||
}
|
||||
|
@ -751,17 +751,6 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
|
||||
void LineEdit::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
|
||||
EDITOR_DEF("text_editor/cursor/caret_blink", false);
|
||||
cursor_set_blink_enabled(EditorSettings::get_singleton()->is_caret_blink_active());
|
||||
cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
|
||||
|
||||
if (!EditorSettings::get_singleton()->is_connected("settings_changed", this, "_editor_settings_changed")) {
|
||||
EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
update_cached_width();
|
||||
update_placeholder_width();
|
||||
} break;
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "scene/resources/style_box.h"
|
||||
#include "scene/resources/texture.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/rendering/rendering_server_constants.h"
|
||||
#include "servers/rendering/rendering_server_raster.h"
|
||||
|
@ -387,13 +387,6 @@ void Node::_propagate_enter_tree() {
|
||||
|
||||
data.blocked--;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
if (ScriptDebugger::get_singleton() && data.filename != String()) {
|
||||
//used for live edit
|
||||
data.tree->live_scene_edit_cache[data.filename].insert(this);
|
||||
}
|
||||
#endif
|
||||
// enter groups
|
||||
}
|
||||
|
||||
@ -435,27 +428,6 @@ void Node::_propagate_after_exit_branch(bool p_exiting_tree) {
|
||||
void Node::_propagate_exit_tree() {
|
||||
//block while removing children
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
if (ScriptDebugger::get_singleton() && data.filename != String()) {
|
||||
//used for live edit
|
||||
RBMap<String, RBSet<Node *>>::Element *E = data.tree->live_scene_edit_cache.find(data.filename);
|
||||
if (E) {
|
||||
E->get().erase(this);
|
||||
if (E->get().size() == 0) {
|
||||
data.tree->live_scene_edit_cache.erase(E);
|
||||
}
|
||||
}
|
||||
|
||||
RBMap<Node *, RBMap<ObjectID, Node *>>::Element *F = data.tree->live_edit_remove_list.find(this);
|
||||
if (F) {
|
||||
for (RBMap<ObjectID, Node *>::Element *G = F->get().front(); G; G = G->next()) {
|
||||
memdelete(G->get());
|
||||
}
|
||||
data.tree->live_edit_remove_list.erase(F);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
data.blocked++;
|
||||
|
||||
for (HashMap<StringName, Node *>::Element *E = data.children.back(); E; E = E->prev) {
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "core/variant/variant_parser.h"
|
||||
#include "main/input_default.h"
|
||||
#include "node.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/animation/scene_tree_tween.h"
|
||||
#include "scene/debugger/script_debugger_remote.h"
|
||||
#include "scene/main/control.h"
|
||||
@ -60,7 +59,6 @@
|
||||
#include "modules/modules_enabled.gen.h" // For freetype.
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -113,27 +111,6 @@ SceneTreeTimer::SceneTreeTimer() {
|
||||
process_pause = true;
|
||||
}
|
||||
|
||||
// This should be called once per physics tick, to make sure the transform previous and current
|
||||
// is kept up to date on the few spatials that are using client side physics interpolation
|
||||
void SceneTree::ClientPhysicsInterpolation::physics_process() {
|
||||
for (SelfList<Spatial> *E = _spatials_list.first(); E;) {
|
||||
Spatial *spatial = E->self();
|
||||
|
||||
SelfList<Spatial> *current = E;
|
||||
|
||||
// get the next element here BEFORE we potentially delete one
|
||||
E = E->next();
|
||||
|
||||
// This will return false if the spatial has timed out ..
|
||||
// i.e. If get_global_transform_interpolated() has not been called
|
||||
// for a few seconds, we can delete from the list to keep processing
|
||||
// to a minimum.
|
||||
if (!spatial->update_client_physics_interpolation_data()) {
|
||||
_spatials_list.remove(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneTree::tree_changed() {
|
||||
tree_version++;
|
||||
emit_signal(tree_changed_name);
|
||||
@ -594,16 +571,6 @@ bool SceneTree::is_physics_interpolation_enabled() const {
|
||||
return _physics_interpolation_enabled;
|
||||
}
|
||||
|
||||
void SceneTree::client_physics_interpolation_add_spatial(SelfList<Spatial> *p_elem) {
|
||||
// This ensures that _update_physics_interpolation_data() will be called at least once every
|
||||
// physics tick, to ensure the previous and current transforms are kept up to date.
|
||||
_client_physics_interpolation._spatials_list.add(p_elem);
|
||||
}
|
||||
|
||||
void SceneTree::client_physics_interpolation_remove_spatial(SelfList<Spatial> *p_elem) {
|
||||
_client_physics_interpolation._spatials_list.remove(p_elem);
|
||||
}
|
||||
|
||||
void SceneTree::iteration_prepare() {
|
||||
if (_physics_interpolation_enabled) {
|
||||
RenderingServer::get_singleton()->tick();
|
||||
@ -623,11 +590,6 @@ bool SceneTree::iteration(float p_time) {
|
||||
|
||||
current_frame++;
|
||||
|
||||
// Any objects performing client physics interpolation
|
||||
// should be given an opportunity to keep their previous transforms
|
||||
// up to take before each new physics tick.
|
||||
_client_physics_interpolation.physics_process();
|
||||
|
||||
flush_transform_notifications();
|
||||
|
||||
MainLoop::iteration(p_time);
|
||||
@ -962,13 +924,6 @@ void SceneTree::set_quit_on_go_back(bool p_enable) {
|
||||
quit_on_go_back = p_enable;
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
bool SceneTree::is_node_being_edited(const Node *p_node) const {
|
||||
return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
void SceneTree::set_debug_collisions_hint(bool p_enabled) {
|
||||
debug_collisions_hint = p_enabled;
|
||||
@ -1629,20 +1584,6 @@ void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, c
|
||||
_update_root_rect();
|
||||
}
|
||||
|
||||
void SceneTree::set_edited_scene_root(Node *p_node) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
edited_scene_root = p_node;
|
||||
#endif
|
||||
}
|
||||
|
||||
Node *SceneTree::get_edited_scene_root() const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return edited_scene_root;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SceneTree::set_current_scene(Node *p_scene) {
|
||||
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Changing scene can only be done from the main thread.");
|
||||
ERR_FAIL_COND(p_scene && p_scene->get_parent() != root);
|
||||
@ -1710,404 +1651,6 @@ void SceneTree::add_current_scene(Node *p_current) {
|
||||
root->add_child(p_current);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
static void _fill_array(Node *p_node, Array &array, int p_level) {
|
||||
array.push_back(p_node->get_child_count());
|
||||
array.push_back(p_node->get_name());
|
||||
array.push_back(p_node->get_class());
|
||||
array.push_back(p_node->get_instance_id());
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
_fill_array(p_node->get_child(i), array, p_level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneTree::_debugger_request_tree() {
|
||||
Array arr;
|
||||
_fill_array(root, arr, 0);
|
||||
ScriptDebugger::get_singleton()->send_message("scene_tree", arr);
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_node_path_func(const NodePath &p_path, int p_id) {
|
||||
live_edit_node_path_cache[p_id] = p_path;
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_res_path_func(const String &p_path, int p_id) {
|
||||
live_edit_resource_cache[p_id] = p_path;
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_node_set_func(int p_id, const StringName &p_prop, const Variant &p_value) {
|
||||
if (!live_edit_node_path_cache.has(p_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodePath np = live_edit_node_path_cache[p_id];
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(np)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(np);
|
||||
|
||||
n2->set(p_prop, p_value);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_node_set_res_func(int p_id, const StringName &p_prop, const String &p_value) {
|
||||
RES r = ResourceLoader::load(p_value);
|
||||
if (!r.is_valid()) {
|
||||
return;
|
||||
}
|
||||
_live_edit_node_set_func(p_id, p_prop, r);
|
||||
}
|
||||
void SceneTree::_live_edit_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
|
||||
if (!live_edit_node_path_cache.has(p_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodePath np = live_edit_node_path_cache[p_id];
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(np)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(np);
|
||||
|
||||
n2->call(p_method, VARIANT_ARG_PASS);
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_res_set_func(int p_id, const StringName &p_prop, const Variant &p_value) {
|
||||
if (!live_edit_resource_cache.has(p_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String resp = live_edit_resource_cache[p_id];
|
||||
|
||||
if (!ResourceCache::has(resp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RES r = ResourceCache::get(resp);
|
||||
if (!r.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
r->set(p_prop, p_value);
|
||||
}
|
||||
void SceneTree::_live_edit_res_set_res_func(int p_id, const StringName &p_prop, const String &p_value) {
|
||||
RES r = ResourceLoader::load(p_value);
|
||||
if (!r.is_valid()) {
|
||||
return;
|
||||
}
|
||||
_live_edit_res_set_func(p_id, p_prop, r);
|
||||
}
|
||||
void SceneTree::_live_edit_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
|
||||
if (!live_edit_resource_cache.has(p_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String resp = live_edit_resource_cache[p_id];
|
||||
|
||||
if (!ResourceCache::has(resp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RES r = ResourceCache::get(resp);
|
||||
if (!r.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
r->call(p_method, VARIANT_ARG_PASS);
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_root_func(const NodePath &p_scene_path, const String &p_scene_from) {
|
||||
live_edit_root = p_scene_path;
|
||||
live_edit_scene = p_scene_from;
|
||||
}
|
||||
|
||||
void SceneTree::_live_edit_create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_parent)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(p_parent);
|
||||
|
||||
Node *no = Object::cast_to<Node>(ClassDB::instance(p_type));
|
||||
if (!no) {
|
||||
continue;
|
||||
}
|
||||
|
||||
no->set_name(p_name);
|
||||
n2->add_child(no);
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_instance_node_func(const NodePath &p_parent, const String &p_path, const String &p_name) {
|
||||
Ref<PackedScene> ps = ResourceLoader::load(p_path);
|
||||
|
||||
if (!ps.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_parent)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(p_parent);
|
||||
|
||||
Node *no = ps->instance();
|
||||
if (!no) {
|
||||
continue;
|
||||
}
|
||||
|
||||
no->set_name(p_name);
|
||||
n2->add_child(no);
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_remove_node_func(const NodePath &p_at) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F;) {
|
||||
RBSet<Node *>::Element *N = F->next();
|
||||
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_at)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(p_at);
|
||||
|
||||
memdelete(n2);
|
||||
|
||||
F = N;
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_keep_id) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F;) {
|
||||
RBSet<Node *>::Element *N = F->next();
|
||||
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_at)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Node *n2 = n->get_node(p_at);
|
||||
|
||||
n2->get_parent()->remove_child(n2);
|
||||
|
||||
live_edit_remove_list[n][p_keep_id] = n2;
|
||||
|
||||
F = N;
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_at_pos) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F;) {
|
||||
RBSet<Node *>::Element *N = F->next();
|
||||
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_at)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(p_at);
|
||||
|
||||
RBMap<Node *, RBMap<ObjectID, Node *>>::Element *EN = live_edit_remove_list.find(n);
|
||||
|
||||
if (!EN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RBMap<ObjectID, Node *>::Element *FN = EN->get().find(p_id);
|
||||
|
||||
if (!FN) {
|
||||
continue;
|
||||
}
|
||||
n2->add_child(FN->get());
|
||||
|
||||
EN->get().erase(FN);
|
||||
|
||||
if (EN->get().size() == 0) {
|
||||
live_edit_remove_list.erase(EN);
|
||||
}
|
||||
|
||||
F = N;
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_duplicate_node_func(const NodePath &p_at, const String &p_new_name) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_at)) {
|
||||
continue;
|
||||
}
|
||||
Node *n2 = n->get_node(p_at);
|
||||
|
||||
Node *dup = n2->duplicate(Node::DUPLICATE_SIGNALS | Node::DUPLICATE_GROUPS | Node::DUPLICATE_SCRIPTS);
|
||||
|
||||
if (!dup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dup->set_name(p_new_name);
|
||||
n2->get_parent()->add_child(dup);
|
||||
}
|
||||
}
|
||||
void SceneTree::_live_edit_reparent_node_func(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos) {
|
||||
Node *base = nullptr;
|
||||
if (root->has_node(live_edit_root)) {
|
||||
base = root->get_node(live_edit_root);
|
||||
}
|
||||
|
||||
RBMap<String, RBSet<Node *>>::Element *E = live_scene_edit_cache.find(live_edit_scene);
|
||||
if (!E) {
|
||||
return; //scene not editable
|
||||
}
|
||||
|
||||
for (RBSet<Node *>::Element *F = E->get().front(); F; F = F->next()) {
|
||||
Node *n = F->get();
|
||||
|
||||
if (base && !base->is_a_parent_of(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!n->has_node(p_at)) {
|
||||
continue;
|
||||
}
|
||||
Node *nfrom = n->get_node(p_at);
|
||||
|
||||
if (!n->has_node(p_new_place)) {
|
||||
continue;
|
||||
}
|
||||
Node *nto = n->get_node(p_new_place);
|
||||
|
||||
nfrom->get_parent()->remove_child(nfrom);
|
||||
nfrom->set_name(p_new_name);
|
||||
|
||||
nto->add_child(nfrom);
|
||||
if (p_at_pos >= 0) {
|
||||
nto->move_child(nfrom, p_at_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) {
|
||||
emit_signal("files_dropped", p_files, p_from_screen);
|
||||
MainLoop::drop_files(p_files, p_from_screen);
|
||||
@ -2269,9 +1812,6 @@ void SceneTree::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_debug_paths_hint", "enable"), &SceneTree::set_debug_paths_hint);
|
||||
ClassDB::bind_method(D_METHOD("is_debugging_paths_hint"), &SceneTree::is_debugging_paths_hint);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
|
||||
ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
|
||||
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
|
||||
ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled);
|
||||
@ -2355,7 +1895,6 @@ void SceneTree::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
|
||||
ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root");
|
||||
@ -2508,9 +2047,6 @@ SceneTree::SceneTree() {
|
||||
root = memnew(Viewport);
|
||||
root->set_name("root");
|
||||
root->set_handle_input_locally(false);
|
||||
if (!root->get_world_3d().is_valid()) {
|
||||
root->set_world_3d(Ref<World3D>(memnew(World3D)));
|
||||
}
|
||||
|
||||
set_physics_interpolation_enabled(GLOBAL_DEF("physics/common/physics_interpolation", false));
|
||||
// Always disable jitter fix if physics interpolation is enabled -
|
||||
@ -2524,14 +2060,9 @@ SceneTree::SceneTree() {
|
||||
multiplayer_poll = true;
|
||||
set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
|
||||
|
||||
root->set_as_audio_listener(true);
|
||||
root->set_as_audio_listener_2d(true);
|
||||
current_scene = nullptr;
|
||||
|
||||
int ref_atlas_size = GLOBAL_DEF_RST("rendering/quality/reflections/atlas_size", 2048);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_size", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); // next_power_of_2 will return a 0 as min value.
|
||||
int ref_atlas_subdiv = GLOBAL_DEF_RST("rendering/quality/reflections/atlas_subdiv", 8);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,1,or_greater")); // next_power_of_2 will return a 0 as min value.
|
||||
int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"));
|
||||
root->set_msaa(Viewport::MSAA(msaa_mode));
|
||||
@ -2556,40 +2087,6 @@ SceneTree::SceneTree() {
|
||||
const bool use_32_bpc_depth = GLOBAL_GET("rendering/quality/depth/use_32_bpc_depth");
|
||||
root->set_use_32_bpc_depth(use_32_bpc_depth);
|
||||
|
||||
RS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world_3d()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
|
||||
|
||||
{ //load default fallback environment
|
||||
//get possible extensions
|
||||
List<String> exts;
|
||||
ResourceLoader::get_recognized_extensions_for_type("Environment3D", &exts);
|
||||
String ext_hint;
|
||||
for (List<String>::Element *E = exts.front(); E; E = E->next()) {
|
||||
if (ext_hint != String()) {
|
||||
ext_hint += ",";
|
||||
}
|
||||
ext_hint += "*." + E->get();
|
||||
}
|
||||
//get path
|
||||
String env_path = GLOBAL_DEF("rendering/environment/default_environment", "");
|
||||
//setup property
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/environment/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint));
|
||||
env_path = env_path.strip_edges();
|
||||
if (env_path != String()) {
|
||||
Ref<Environment3D> env = ResourceLoader::load(env_path);
|
||||
if (env.is_valid()) {
|
||||
root->get_world_3d()->set_fallback_environment(env);
|
||||
} else {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
//file was erased, clear the field.
|
||||
ProjectSettings::get_singleton()->set("rendering/environment/default_environment", "");
|
||||
} else {
|
||||
//file was erased, notify user.
|
||||
ERR_PRINT(RTR("Default Environment as specified in Project Settings (Rendering -> Environment -> Default Environment) could not be loaded."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stretch_mode = STRETCH_MODE_DISABLED;
|
||||
stretch_aspect = STRETCH_ASPECT_IGNORE;
|
||||
stretch_scale = 1.0;
|
||||
@ -2607,16 +2104,6 @@ SceneTree::SceneTree() {
|
||||
}
|
||||
|
||||
root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
edited_scene_root = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
live_edit_root = NodePath("/root");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
SceneTree::~SceneTree() {
|
||||
|
@ -39,7 +39,6 @@ class PackedScene;
|
||||
class Node;
|
||||
class SceneTreeTween;
|
||||
class ShortCut;
|
||||
class Spatial;
|
||||
class Viewport;
|
||||
class Material;
|
||||
class Mesh;
|
||||
@ -102,11 +101,6 @@ private:
|
||||
Group() { changed = false; };
|
||||
};
|
||||
|
||||
struct ClientPhysicsInterpolation {
|
||||
SelfList<Spatial>::List _spatials_list;
|
||||
void physics_process();
|
||||
} _client_physics_interpolation;
|
||||
|
||||
Viewport *root;
|
||||
|
||||
uint64_t tree_version;
|
||||
@ -139,10 +133,6 @@ private:
|
||||
int64_t current_frame;
|
||||
int64_t current_event;
|
||||
int node_count;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Node *edited_scene_root;
|
||||
#endif
|
||||
struct UGCall {
|
||||
StringName group;
|
||||
StringName call;
|
||||
@ -234,7 +224,6 @@ private:
|
||||
void _flush_delete_queue();
|
||||
//optimization
|
||||
friend class CanvasItem;
|
||||
friend class Spatial;
|
||||
friend class Viewport;
|
||||
|
||||
SelfList<Node>::List xform_change_list;
|
||||
@ -243,40 +232,6 @@ private:
|
||||
|
||||
Ref<ShortCut> debugger_stop_shortcut;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
RBMap<int, NodePath> live_edit_node_path_cache;
|
||||
RBMap<int, String> live_edit_resource_cache;
|
||||
|
||||
NodePath live_edit_root;
|
||||
String live_edit_scene;
|
||||
|
||||
RBMap<String, RBSet<Node *>> live_scene_edit_cache;
|
||||
RBMap<Node *, RBMap<ObjectID, Node *>> live_edit_remove_list;
|
||||
|
||||
void _debugger_request_tree();
|
||||
|
||||
void _live_edit_node_path_func(const NodePath &p_path, int p_id);
|
||||
void _live_edit_res_path_func(const String &p_path, int p_id);
|
||||
|
||||
void _live_edit_node_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
|
||||
void _live_edit_node_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
|
||||
void _live_edit_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
|
||||
void _live_edit_res_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
|
||||
void _live_edit_res_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
|
||||
void _live_edit_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
|
||||
void _live_edit_root_func(const NodePath &p_scene_path, const String &p_scene_from);
|
||||
|
||||
void _live_edit_create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name);
|
||||
void _live_edit_instance_node_func(const NodePath &p_parent, const String &p_path, const String &p_name);
|
||||
void _live_edit_remove_node_func(const NodePath &p_at);
|
||||
void _live_edit_remove_and_keep_node_func(const NodePath &p_at, ObjectID p_keep_id);
|
||||
void _live_edit_restore_node_func(ObjectID p_id, const NodePath &p_at, int p_at_pos);
|
||||
void _live_edit_duplicate_node_func(const NodePath &p_at, const String &p_new_name);
|
||||
void _live_edit_reparent_node_func(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos);
|
||||
|
||||
#endif
|
||||
|
||||
enum {
|
||||
MAX_IDLE_CALLBACKS = 256
|
||||
};
|
||||
@ -343,14 +298,6 @@ public:
|
||||
return idle_process_time;
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool is_node_being_edited(const Node *p_node) const;
|
||||
#else
|
||||
bool is_node_being_edited(const Node *p_node) const {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_pause(bool p_enabled);
|
||||
bool is_paused() const;
|
||||
|
||||
@ -419,9 +366,6 @@ public:
|
||||
//void change_scene(const String& p_path);
|
||||
//Node *get_loaded_scene();
|
||||
|
||||
void set_edited_scene_root(Node *p_node);
|
||||
Node *get_edited_scene_root() const;
|
||||
|
||||
void set_current_scene(Node *p_scene);
|
||||
Node *get_current_scene() const;
|
||||
Error change_scene(const String &p_path);
|
||||
@ -463,9 +407,6 @@ public:
|
||||
void set_physics_interpolation_enabled(bool p_enabled);
|
||||
bool is_physics_interpolation_enabled() const;
|
||||
|
||||
void client_physics_interpolation_add_spatial(SelfList<Spatial> *p_elem);
|
||||
void client_physics_interpolation_remove_spatial(SelfList<Spatial> *p_elem);
|
||||
|
||||
static void add_idle_callback(IdleCallback p_callback);
|
||||
SceneTree();
|
||||
~SceneTree();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,251 +0,0 @@
|
||||
#ifndef SPATIAL_H
|
||||
#define SPATIAL_H
|
||||
/*************************************************************************/
|
||||
/* spatial.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/main/node.h"
|
||||
#include "scene/main/scene_tree.h"
|
||||
|
||||
class World3D;
|
||||
|
||||
class SpatialGizmo : public Reference {
|
||||
GDCLASS(SpatialGizmo, Reference);
|
||||
|
||||
public:
|
||||
virtual void create() = 0;
|
||||
virtual void transform() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void redraw() = 0;
|
||||
virtual void free() = 0;
|
||||
|
||||
SpatialGizmo();
|
||||
virtual ~SpatialGizmo() {}
|
||||
};
|
||||
|
||||
class Spatial : public Node {
|
||||
GDCLASS(Spatial, Node);
|
||||
OBJ_CATEGORY("3D");
|
||||
|
||||
// optionally stored if we need to do interpolation
|
||||
// client side (i.e. not in RenderingServer) so interpolated transforms
|
||||
// can be read back with get_global_transform_interpolated()
|
||||
struct ClientPhysicsInterpolationData {
|
||||
Transform global_xform_curr;
|
||||
Transform global_xform_prev;
|
||||
uint64_t current_physics_tick = 0;
|
||||
uint64_t timeout_physics_tick = 0;
|
||||
};
|
||||
|
||||
enum TransformDirty {
|
||||
DIRTY_NONE = 0,
|
||||
DIRTY_VECTORS = 1,
|
||||
DIRTY_LOCAL = 2,
|
||||
DIRTY_GLOBAL = 4
|
||||
};
|
||||
|
||||
mutable SelfList<Node> xform_change;
|
||||
SelfList<Spatial> _client_physics_interpolation_spatials_list;
|
||||
|
||||
struct Data {
|
||||
mutable Transform global_transform;
|
||||
mutable Transform local_transform;
|
||||
mutable Vector3 rotation;
|
||||
mutable Vector3 scale;
|
||||
|
||||
mutable int dirty;
|
||||
|
||||
bool toplevel_active : 1;
|
||||
bool toplevel : 1;
|
||||
bool inside_world : 1;
|
||||
|
||||
// this is cached, and only currently kept up to date in visual instances
|
||||
// this is set if a visual instance is
|
||||
// (a) in the tree AND (b) visible via is_visible_in_tree() call
|
||||
bool vi_visible : 1;
|
||||
|
||||
bool ignore_notification : 1;
|
||||
bool notify_local_transform : 1;
|
||||
bool notify_transform : 1;
|
||||
|
||||
bool visible : 1;
|
||||
bool disable_scale : 1;
|
||||
|
||||
int children_lock;
|
||||
Spatial *parent;
|
||||
List<Spatial *> children;
|
||||
List<Spatial *>::Element *C;
|
||||
|
||||
ClientPhysicsInterpolationData *client_physics_interpolation_data;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
Vector<Ref<SpatialGizmo>> gizmos;
|
||||
bool gizmos_disabled : 1;
|
||||
bool gizmos_dirty : 1;
|
||||
bool transform_gizmo_visible : 1;
|
||||
#endif
|
||||
|
||||
} data;
|
||||
|
||||
void _update_gizmos();
|
||||
void _notify_dirty();
|
||||
void _propagate_transform_changed(Spatial *p_origin);
|
||||
|
||||
void _propagate_visibility_changed();
|
||||
|
||||
protected:
|
||||
_FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) {
|
||||
data.ignore_notification = p_ignore;
|
||||
}
|
||||
_FORCE_INLINE_ void _update_local_transform() const;
|
||||
|
||||
void _set_vi_visible(bool p_visible);
|
||||
bool _is_vi_visible() const {
|
||||
return data.vi_visible;
|
||||
}
|
||||
Transform _get_global_transform_interpolated(real_t p_interpolation_fraction);
|
||||
void _disable_client_physics_interpolation();
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
||||
NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED,
|
||||
NOTIFICATION_ENTER_WORLD = 41,
|
||||
NOTIFICATION_EXIT_WORLD = 42,
|
||||
NOTIFICATION_VISIBILITY_CHANGED = 43,
|
||||
NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 44,
|
||||
NOTIFICATION_ENTER_GAMEPLAY = 45,
|
||||
NOTIFICATION_EXIT_GAMEPLAY = 46,
|
||||
};
|
||||
|
||||
virtual void notification_callback(int p_message_type);
|
||||
Spatial *get_parent_spatial() const;
|
||||
|
||||
Ref<World3D> get_world_3d() const;
|
||||
|
||||
void set_translation(const Vector3 &p_translation);
|
||||
void set_rotation(const Vector3 &p_euler_rad);
|
||||
void set_rotation_degrees(const Vector3 &p_euler_deg);
|
||||
void set_scale(const Vector3 &p_scale);
|
||||
|
||||
void set_global_translation(const Vector3 &p_translation);
|
||||
void set_global_rotation(const Vector3 &p_euler_rad);
|
||||
|
||||
Vector3 get_translation() const;
|
||||
Vector3 get_rotation() const;
|
||||
Vector3 get_rotation_degrees() const;
|
||||
Vector3 get_scale() const;
|
||||
|
||||
Vector3 get_global_translation() const;
|
||||
Vector3 get_global_rotation() const;
|
||||
|
||||
void set_transform(const Transform &p_transform);
|
||||
void set_global_transform(const Transform &p_transform);
|
||||
|
||||
Transform get_transform() const;
|
||||
Transform get_global_transform() const;
|
||||
Transform get_global_transform_interpolated();
|
||||
bool update_client_physics_interpolation_data();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual Transform get_global_gizmo_transform() const;
|
||||
virtual Transform get_local_gizmo_transform() const;
|
||||
virtual void set_transform_gizmo_visible(bool p_enabled) { data.transform_gizmo_visible = p_enabled; };
|
||||
virtual bool is_transform_gizmo_visible() const { return data.transform_gizmo_visible; };
|
||||
virtual AABB get_fallback_gizmo_aabb() const;
|
||||
#endif
|
||||
|
||||
void set_as_toplevel(bool p_enabled);
|
||||
bool is_set_as_toplevel() const;
|
||||
|
||||
void set_disable_scale(bool p_enabled);
|
||||
bool is_scale_disabled() const;
|
||||
|
||||
void set_disable_gizmos(bool p_enabled);
|
||||
void update_gizmos();
|
||||
void set_subgizmo_selection(Ref<SpatialGizmo> p_gizmo, int p_id, Transform p_transform = Transform());
|
||||
void clear_subgizmo_selection();
|
||||
Vector<Ref<SpatialGizmo>> get_gizmos() const;
|
||||
Vector<Variant> get_gizmos_bind() const;
|
||||
void add_gizmo(Ref<SpatialGizmo> p_gizmo);
|
||||
void remove_gizmo(Ref<SpatialGizmo> p_gizmo);
|
||||
void clear_gizmos();
|
||||
|
||||
_FORCE_INLINE_ bool is_inside_world() const {
|
||||
return data.inside_world;
|
||||
}
|
||||
|
||||
Transform get_relative_transform(const Node *p_parent) const;
|
||||
|
||||
void rotate(const Vector3 &p_axis, float p_angle);
|
||||
void rotate_x(float p_angle);
|
||||
void rotate_y(float p_angle);
|
||||
void rotate_z(float p_angle);
|
||||
void translate(const Vector3 &p_offset);
|
||||
void scale(const Vector3 &p_ratio);
|
||||
|
||||
void rotate_object_local(const Vector3 &p_axis, float p_angle);
|
||||
void scale_object_local(const Vector3 &p_scale);
|
||||
void translate_object_local(const Vector3 &p_offset);
|
||||
|
||||
void global_rotate(const Vector3 &p_axis, float p_angle);
|
||||
void global_scale(const Vector3 &p_scale);
|
||||
void global_translate(const Vector3 &p_offset);
|
||||
|
||||
void look_at(const Vector3 &p_target, const Vector3 &p_up);
|
||||
void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up);
|
||||
|
||||
Vector3 to_local(Vector3 p_global) const;
|
||||
Vector3 to_global(Vector3 p_local) const;
|
||||
|
||||
void set_notify_transform(bool p_enable);
|
||||
bool is_transform_notification_enabled() const;
|
||||
|
||||
void set_notify_local_transform(bool p_enable);
|
||||
bool is_local_transform_notification_enabled() const;
|
||||
|
||||
void orthonormalize();
|
||||
void set_identity();
|
||||
|
||||
void set_visible(bool p_visible);
|
||||
bool is_visible() const;
|
||||
void show();
|
||||
void hide();
|
||||
bool is_visible_in_tree() const;
|
||||
|
||||
void force_update_transform();
|
||||
|
||||
Spatial();
|
||||
~Spatial();
|
||||
};
|
||||
|
||||
#endif
|
@ -39,9 +39,6 @@
|
||||
#include "scene/2d/camera_2d.h"
|
||||
#include "scene/2d/collision_object_2d.h"
|
||||
#include "scene/2d/listener_2d.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/3d/listener.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/main/control.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/menu_button.h"
|
||||
@ -53,7 +50,6 @@
|
||||
#include "scene/main/timer.h"
|
||||
#include "scene/resources/mesh/mesh.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
|
||||
@ -216,34 +212,6 @@ void Viewport::_update_stretch_transform() {
|
||||
_update_global_transform();
|
||||
}
|
||||
|
||||
void Viewport::_own_world_3d_changed() {
|
||||
ERR_FAIL_COND(world_3d.is_null());
|
||||
ERR_FAIL_COND(own_world_3d.is_null());
|
||||
|
||||
World::_own_world_3d_changed();
|
||||
|
||||
if (is_inside_tree()) {
|
||||
RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
|
||||
}
|
||||
|
||||
_update_listener();
|
||||
}
|
||||
|
||||
void Viewport::_on_set_use_own_world_3d(bool p_use_own_world_3d) {
|
||||
if (is_inside_tree()) {
|
||||
RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
|
||||
}
|
||||
|
||||
_update_listener();
|
||||
}
|
||||
|
||||
void Viewport::_on_set_world_3d(const Ref<World3D> &p_old_world) {
|
||||
if (is_inside_tree()) {
|
||||
RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
|
||||
}
|
||||
|
||||
_update_listener();
|
||||
}
|
||||
void Viewport::_on_set_world_2d(const Ref<World2D> &p_old_world_2d) {
|
||||
if (is_inside_tree() && p_old_world_2d.is_valid()) {
|
||||
Ref<World2D> old_world_2d = p_old_world_2d;
|
||||
@ -277,35 +245,6 @@ void Viewport::_notification(int p_what) {
|
||||
RS::get_singleton()->viewport_set_active(viewport, true);
|
||||
} break;
|
||||
case NOTIFICATION_READY: {
|
||||
#ifndef _3D_DISABLED
|
||||
if (listeners.size() && !listener) {
|
||||
Listener *first = nullptr;
|
||||
for (RBSet<Listener *>::Element *E = listeners.front(); E; E = E->next()) {
|
||||
if (first == nullptr || first->is_greater_than(E->get())) {
|
||||
first = E->get();
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
first->make_current();
|
||||
}
|
||||
}
|
||||
|
||||
if (cameras.size() && !camera) {
|
||||
//there are cameras but no current camera, pick first in tree and make it current
|
||||
Camera *first = nullptr;
|
||||
for (RBSet<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
if (first == nullptr || first->is_greater_than(E->get())) {
|
||||
first = E->get();
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
first->make_current();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Enable processing for tooltips, collision debugging, physics object picking, etc.
|
||||
set_physics_process_internal(true);
|
||||
|
||||
@ -635,16 +574,6 @@ Size2 Viewport::get_size() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void Viewport::_update_listener() {
|
||||
/*
|
||||
if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree()))) {
|
||||
SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, find_world_3d()->get_sound_space());
|
||||
} else {
|
||||
SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Viewport::_update_listener_2d() {
|
||||
/*
|
||||
if (is_inside_tree() && audio_listener && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
|
||||
@ -654,19 +583,6 @@ void Viewport::_update_listener_2d() {
|
||||
*/
|
||||
}
|
||||
|
||||
void Viewport::set_as_audio_listener(bool p_enable) {
|
||||
if (p_enable == audio_listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio_listener = p_enable;
|
||||
_update_listener();
|
||||
}
|
||||
|
||||
bool Viewport::is_audio_listener() const {
|
||||
return audio_listener;
|
||||
}
|
||||
|
||||
void Viewport::set_as_audio_listener_2d(bool p_enable) {
|
||||
if (p_enable == audio_listener_2d) {
|
||||
return;
|
||||
@ -696,10 +612,8 @@ void Viewport::_on_before_world_override_changed() {
|
||||
|
||||
void Viewport::_on_after_world_override_changed() {
|
||||
current_canvas = find_world_2d()->get_canvas();
|
||||
RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
|
||||
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
|
||||
|
||||
_update_listener();
|
||||
_update_listener_2d();
|
||||
|
||||
find_world_2d()->_register_world(this, Rect2());
|
||||
@ -812,93 +726,6 @@ Transform2D Viewport::get_global_canvas_transform() const {
|
||||
return global_canvas_transform;
|
||||
}
|
||||
|
||||
void Viewport::_listener_transform_changed_notify() {
|
||||
#ifndef _3D_DISABLED
|
||||
//if (listener)
|
||||
// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, listener->get_listener_transform());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Viewport::_listener_set(Listener *p_listener) {
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
if (listener == p_listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
listener = p_listener;
|
||||
|
||||
_update_listener();
|
||||
_listener_transform_changed_notify();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Viewport::_listener_add(Listener *p_listener) {
|
||||
listeners.insert(p_listener);
|
||||
return listeners.size() == 1;
|
||||
}
|
||||
|
||||
void Viewport::_listener_remove(Listener *p_listener) {
|
||||
listeners.erase(p_listener);
|
||||
if (listener == p_listener) {
|
||||
listener = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
void Viewport::_listener_make_next_current(Listener *p_exclude) {
|
||||
if (listeners.size() > 0) {
|
||||
for (RBSet<Listener *>::Element *E = listeners.front(); E; E = E->next()) {
|
||||
if (p_exclude == E->get()) {
|
||||
continue;
|
||||
}
|
||||
if (!E->get()->is_inside_tree()) {
|
||||
continue;
|
||||
}
|
||||
if (listener != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
E->get()->make_current();
|
||||
}
|
||||
} else {
|
||||
// Attempt to reset listener to the camera position
|
||||
if (camera != nullptr) {
|
||||
_update_listener();
|
||||
_camera_transform_changed_notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Viewport::_camera_set(Camera *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
if (camera == p_camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (camera) {
|
||||
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
|
||||
}
|
||||
camera = p_camera;
|
||||
if (!camera_override) {
|
||||
if (camera) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
|
||||
}
|
||||
}
|
||||
|
||||
if (camera) {
|
||||
camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
|
||||
}
|
||||
|
||||
_update_listener();
|
||||
_camera_transform_changed_notify();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
|
||||
camera_2d = p_camera_2d;
|
||||
}
|
||||
@ -946,88 +773,10 @@ void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
|
||||
}
|
||||
}
|
||||
|
||||
Listener *Viewport::get_listener() const {
|
||||
return listener;
|
||||
}
|
||||
|
||||
Camera2D *Viewport::get_camera_2d() const {
|
||||
return camera_2d;
|
||||
}
|
||||
|
||||
void Viewport::enable_camera_override(bool p_enable) {
|
||||
#ifndef _3D_DISABLED
|
||||
if (p_enable == camera_override) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_enable) {
|
||||
camera_override.rid = RID_PRIME(RenderingServer::get_singleton()->camera_create());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->free(camera_override.rid);
|
||||
camera_override.rid = RID();
|
||||
}
|
||||
|
||||
if (p_enable) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
|
||||
} else if (camera) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Viewport::is_camera_override_enabled() const {
|
||||
return camera_override;
|
||||
}
|
||||
|
||||
void Viewport::set_camera_override_transform(const Transform &p_transform) {
|
||||
if (camera_override) {
|
||||
camera_override.transform = p_transform;
|
||||
RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
|
||||
}
|
||||
}
|
||||
|
||||
Transform Viewport::get_camera_override_transform() const {
|
||||
if (camera_override) {
|
||||
return camera_override.transform;
|
||||
}
|
||||
|
||||
return Transform();
|
||||
}
|
||||
|
||||
void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
|
||||
if (camera_override) {
|
||||
if (camera_override.fov == p_fovy_degrees && camera_override.z_near == p_z_near &&
|
||||
camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_PERSPECTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera_override.fov = p_fovy_degrees;
|
||||
camera_override.z_near = p_z_near;
|
||||
camera_override.z_far = p_z_far;
|
||||
camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far) {
|
||||
if (camera_override) {
|
||||
if (camera_override.size == p_size && camera_override.z_near == p_z_near &&
|
||||
camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_ORTHOGONAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera_override.size = p_size;
|
||||
camera_override.z_near = p_z_near;
|
||||
camera_override.z_far = p_z_far;
|
||||
camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far);
|
||||
}
|
||||
}
|
||||
|
||||
Transform2D Viewport::get_final_transform() const {
|
||||
if (_overriding_world) {
|
||||
return _overriding_world->get_final_transform();
|
||||
@ -3043,9 +2792,6 @@ void Viewport::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener);
|
||||
ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
|
||||
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
|
||||
ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect);
|
||||
@ -3234,11 +2980,9 @@ Viewport::Viewport() {
|
||||
audio_listener_2d = false;
|
||||
transparent_bg = false;
|
||||
parent = nullptr;
|
||||
listener = nullptr;
|
||||
camera_2d = nullptr;
|
||||
override_canvas_transform = false;
|
||||
canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport)
|
||||
arvr = false;
|
||||
size_override = false;
|
||||
size_override_stretch = false;
|
||||
size_override_size = Size2(1, 1);
|
||||
|
@ -38,9 +38,7 @@
|
||||
#include "servers/rendering_server.h"
|
||||
#include "world.h"
|
||||
|
||||
class Camera;
|
||||
class Camera2D;
|
||||
class Listener;
|
||||
class Listener2D;
|
||||
class Control;
|
||||
class CanvasItem;
|
||||
@ -154,21 +152,8 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
Listener *get_listener() const;
|
||||
Camera2D *get_camera_2d() const;
|
||||
|
||||
void enable_camera_override(bool p_enable);
|
||||
bool is_camera_override_enabled() const;
|
||||
|
||||
void set_camera_override_transform(const Transform &p_transform);
|
||||
Transform get_camera_override_transform() const;
|
||||
|
||||
void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
|
||||
void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
|
||||
|
||||
void set_as_audio_listener(bool p_enable);
|
||||
bool is_audio_listener() const;
|
||||
|
||||
Listener2D *get_listener_2d() const;
|
||||
void set_as_audio_listener_2d(bool p_enable);
|
||||
bool is_audio_listener_2d() const;
|
||||
@ -302,17 +287,12 @@ public:
|
||||
Viewport();
|
||||
~Viewport();
|
||||
|
||||
void _camera_set(Camera *p_camera);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _process_picking(bool p_ignore_paused);
|
||||
static void _bind_methods();
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
void _own_world_3d_changed();
|
||||
void _on_set_use_own_world_3d(bool p_use_own_world_3d);
|
||||
void _on_set_world_3d(const Ref<World3D> &p_old_world);
|
||||
void _on_set_world_2d(const Ref<World2D> &p_old_world_2d);
|
||||
|
||||
void _on_before_world_override_changed();
|
||||
@ -323,29 +303,6 @@ private:
|
||||
|
||||
Viewport *parent;
|
||||
|
||||
Listener *listener;
|
||||
RBSet<Listener *> listeners;
|
||||
|
||||
bool arvr;
|
||||
|
||||
struct CameraOverrideData {
|
||||
Transform transform;
|
||||
enum Projection {
|
||||
PROJECTION_PERSPECTIVE,
|
||||
PROJECTION_ORTHOGONAL
|
||||
};
|
||||
Projection projection;
|
||||
float fov;
|
||||
float size;
|
||||
float z_near;
|
||||
float z_far;
|
||||
RID rid;
|
||||
|
||||
operator bool() const {
|
||||
return rid != RID();
|
||||
}
|
||||
} camera_override;
|
||||
|
||||
Camera2D *camera_2d;
|
||||
Listener2D *listener_2d = nullptr;
|
||||
RBSet<CanvasLayer *> canvas_layers;
|
||||
@ -417,7 +374,6 @@ private:
|
||||
StringName unhandled_input_group;
|
||||
StringName unhandled_key_input_group;
|
||||
|
||||
void _update_listener();
|
||||
void _update_listener_2d();
|
||||
|
||||
void _propagate_viewport_notification(Node *p_node, int p_what);
|
||||
@ -548,13 +504,6 @@ private:
|
||||
|
||||
bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check);
|
||||
|
||||
friend class Listener;
|
||||
void _listener_transform_changed_notify();
|
||||
void _listener_set(Listener *p_listener);
|
||||
bool _listener_add(Listener *p_listener); //true if first
|
||||
void _listener_remove(Listener *p_listener);
|
||||
void _listener_make_next_current(Listener *p_exclude);
|
||||
|
||||
friend class Camera2D;
|
||||
void _camera_2d_set(Camera2D *p_camera_2d);
|
||||
|
||||
|
@ -2,17 +2,9 @@
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/core_string_names.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/3d/world_environment_3d.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "viewport.h"
|
||||
|
||||
Camera *World::get_camera() const {
|
||||
return camera;
|
||||
}
|
||||
|
||||
Ref<World2D> World::get_world_2d() const {
|
||||
return world_2d;
|
||||
}
|
||||
@ -43,77 +35,6 @@ void World::set_world_2d(const Ref<World2D> &p_world_2d) {
|
||||
_on_set_world_2d(old_world);
|
||||
}
|
||||
|
||||
Ref<World3D> World::get_world_3d() const {
|
||||
return world_3d;
|
||||
}
|
||||
|
||||
void World::set_world_3d(const Ref<World3D> &p_world_3d) {
|
||||
if (world_3d == p_world_3d) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_exit_world(this);
|
||||
}
|
||||
|
||||
Ref<World3D> old_world = world_3d;
|
||||
|
||||
if (own_world_3d.is_valid() && world_3d.is_valid()) {
|
||||
world_3d->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed");
|
||||
}
|
||||
|
||||
world_3d = p_world_3d;
|
||||
|
||||
if (own_world_3d.is_valid()) {
|
||||
if (world_3d.is_valid()) {
|
||||
own_world_3d = world_3d->duplicate();
|
||||
world_3d->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed");
|
||||
} else {
|
||||
own_world_3d = Ref<World3D>(memnew(World3D));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_enter_world(this);
|
||||
}
|
||||
|
||||
_on_set_world_3d(old_world);
|
||||
}
|
||||
|
||||
bool World::is_using_own_world_3d() const {
|
||||
return own_world_3d.is_valid();
|
||||
}
|
||||
|
||||
void World::set_use_own_world_3d(bool p_use_own_world_3d) {
|
||||
if (p_use_own_world_3d == own_world_3d.is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_exit_world(this);
|
||||
}
|
||||
|
||||
if (p_use_own_world_3d) {
|
||||
if (world_3d.is_valid()) {
|
||||
own_world_3d = world_3d->duplicate();
|
||||
world_3d->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed");
|
||||
} else {
|
||||
own_world_3d = Ref<World3D>(memnew(World3D));
|
||||
}
|
||||
} else {
|
||||
own_world_3d = Ref<World3D>();
|
||||
if (world_3d.is_valid()) {
|
||||
world_3d->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_3d_changed");
|
||||
}
|
||||
}
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_enter_world(this);
|
||||
}
|
||||
|
||||
_on_set_use_own_world_3d(p_use_own_world_3d);
|
||||
}
|
||||
|
||||
bool World::get_override_in_parent_viewport() {
|
||||
return _override_in_parent_viewport;
|
||||
}
|
||||
@ -153,22 +74,6 @@ Ref<World2D> World::find_world_2d() const {
|
||||
}
|
||||
}
|
||||
|
||||
Ref<World3D> World::find_world_3d() const {
|
||||
if (_override_world) {
|
||||
return _override_world->find_world_3d();
|
||||
}
|
||||
|
||||
if (own_world_3d.is_valid()) {
|
||||
return own_world_3d;
|
||||
} else if (world_3d.is_valid()) {
|
||||
return world_3d;
|
||||
} else if (_parent_world) {
|
||||
return _parent_world->find_world_3d();
|
||||
} else {
|
||||
return Ref<World3D>();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<World2D> World::find_world_2d_no_override() const {
|
||||
if (world_2d.is_valid()) {
|
||||
return world_2d;
|
||||
@ -179,18 +84,6 @@ Ref<World2D> World::find_world_2d_no_override() const {
|
||||
}
|
||||
}
|
||||
|
||||
Ref<World3D> World::find_world_3d_no_override() const {
|
||||
if (own_world_3d.is_valid()) {
|
||||
return own_world_3d;
|
||||
} else if (world_3d.is_valid()) {
|
||||
return world_3d;
|
||||
} else if (_parent_world) {
|
||||
return _parent_world->find_world_3d();
|
||||
} else {
|
||||
return Ref<World3D>();
|
||||
}
|
||||
}
|
||||
|
||||
World *World::get_override_world() {
|
||||
return _override_world;
|
||||
}
|
||||
@ -217,13 +110,10 @@ void World::set_override_world(World *p_world) {
|
||||
_overriding_world = NULL;
|
||||
}
|
||||
|
||||
_clear_override_cameras();
|
||||
|
||||
_override_world = p_world;
|
||||
|
||||
if (_override_world) {
|
||||
_override_world->_overriding_world = this;
|
||||
_add_override_cameras(_override_world);
|
||||
}
|
||||
|
||||
_on_after_world_override_changed();
|
||||
@ -351,78 +241,6 @@ void World::update_worlds() {
|
||||
Rect2 xformed_rect = (get_global_canvas_transform() * get_canvas_transform()).affine_inverse().xform(abstracted_rect);
|
||||
find_world_2d()->_update_world(this, xformed_rect);
|
||||
find_world_2d()->_update();
|
||||
|
||||
find_world_3d()->_update(get_tree()->get_frame());
|
||||
}
|
||||
|
||||
void World::_world_3d_register_camera(Camera *p_camera) {
|
||||
if (_override_world) {
|
||||
_override_world->_world_3d_register_camera_as_override(p_camera);
|
||||
}
|
||||
|
||||
_world_3d_register_camera_no_override(p_camera);
|
||||
}
|
||||
|
||||
void World::_world_3d_remove_camera(Camera *p_camera) {
|
||||
if (_override_world) {
|
||||
_override_world->_world_3d_remove_camera_as_override(p_camera);
|
||||
}
|
||||
|
||||
_world_3d_remove_camera_no_override(p_camera);
|
||||
}
|
||||
|
||||
void World::_world_3d_register_camera_no_override(Camera *p_camera) {
|
||||
find_world_3d_no_override()->_register_camera(p_camera);
|
||||
}
|
||||
|
||||
void World::_world_3d_remove_camera_no_override(Camera *p_camera) {
|
||||
find_world_3d_no_override()->_remove_camera(p_camera);
|
||||
}
|
||||
|
||||
void World::_world_3d_register_camera_as_override(Camera *p_camera) {
|
||||
//find_world_3d_no_override()->_register_camera(p_camera);
|
||||
|
||||
_override_cameras.push_back(p_camera);
|
||||
|
||||
_camera_add(p_camera);
|
||||
}
|
||||
|
||||
void World::_world_3d_remove_camera_as_override(Camera *p_camera) {
|
||||
//find_world_3d_no_override()->_remove_camera(p_camera);
|
||||
|
||||
_override_cameras.erase(p_camera);
|
||||
|
||||
_camera_remove(p_camera);
|
||||
}
|
||||
|
||||
void World::_clear_override_cameras() {
|
||||
while (_override_cameras.size() > 0) {
|
||||
_world_3d_remove_camera_as_override(_override_cameras[0]);
|
||||
}
|
||||
|
||||
_camera_set(_own_active_camera);
|
||||
_own_active_camera = NULL;
|
||||
}
|
||||
|
||||
void World::_add_override_cameras(World *p_from) {
|
||||
_own_active_camera = camera;
|
||||
|
||||
Ref<World3D> w3d = p_from->find_world_3d_no_override();
|
||||
|
||||
ERR_FAIL_COND(!w3d.is_valid());
|
||||
|
||||
List<Camera *> cameras;
|
||||
w3d->get_camera_list(&cameras);
|
||||
|
||||
for (List<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
Camera *cam = E->get();
|
||||
|
||||
_world_3d_register_camera_as_override(cam);
|
||||
}
|
||||
|
||||
if (p_from->get_camera()) {
|
||||
_camera_set(p_from->get_camera());
|
||||
}
|
||||
}
|
||||
|
||||
World::World() {
|
||||
@ -430,83 +248,10 @@ World::World() {
|
||||
_override_world = NULL;
|
||||
_overriding_world = NULL;
|
||||
_override_in_parent_viewport = false;
|
||||
camera = NULL;
|
||||
_own_active_camera = NULL;
|
||||
}
|
||||
World::~World() {
|
||||
}
|
||||
|
||||
void World::_camera_transform_changed_notify() {
|
||||
#ifndef _3D_DISABLED
|
||||
// If there is an active listener in the scene, it takes priority over the camera
|
||||
// if (camera && !listener)
|
||||
// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform());
|
||||
#endif
|
||||
}
|
||||
|
||||
void World::_camera_set(Camera *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
if (camera == p_camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (camera) {
|
||||
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
|
||||
}
|
||||
camera = p_camera;
|
||||
|
||||
/*
|
||||
if (!camera_override) {
|
||||
if (camera) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (camera) {
|
||||
camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
|
||||
}
|
||||
|
||||
_update_listener();
|
||||
_camera_transform_changed_notify();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool World::_camera_add(Camera *p_camera) {
|
||||
cameras.insert(p_camera);
|
||||
return cameras.size() == 1;
|
||||
}
|
||||
|
||||
void World::_camera_remove(Camera *p_camera) {
|
||||
cameras.erase(p_camera);
|
||||
if (camera == p_camera) {
|
||||
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
|
||||
camera = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
void World::_camera_make_next_current(Camera *p_exclude) {
|
||||
for (RBSet<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
if (p_exclude == E->get()) {
|
||||
continue;
|
||||
}
|
||||
if (!E->get()->is_inside_tree()) {
|
||||
continue;
|
||||
}
|
||||
if (camera != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
E->get()->make_current();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void World::_update_listener() {}
|
||||
void World::_update_listener_2d() {}
|
||||
|
||||
void World::_propagate_enter_world(Node *p_node) {
|
||||
@ -514,17 +259,6 @@ void World::_propagate_enter_world(Node *p_node) {
|
||||
if (!p_node->is_inside_tree()) { //may not have entered scene yet
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object::cast_to<Spatial>(p_node) || Object::cast_to<WorldEnvironment3D>(p_node)) {
|
||||
p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD);
|
||||
} else {
|
||||
World *v = Object::cast_to<World>(p_node);
|
||||
if (v) {
|
||||
if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
@ -537,17 +271,6 @@ void World::_propagate_exit_world(Node *p_node) {
|
||||
if (!p_node->is_inside_tree()) { //may have exited scene already
|
||||
return;
|
||||
}
|
||||
|
||||
if (Object::cast_to<Spatial>(p_node) || Object::cast_to<WorldEnvironment3D>(p_node)) {
|
||||
p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD);
|
||||
} else {
|
||||
World *v = Object::cast_to<World>(p_node);
|
||||
if (v) {
|
||||
if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
@ -555,26 +278,6 @@ void World::_propagate_exit_world(Node *p_node) {
|
||||
}
|
||||
}
|
||||
|
||||
void World::_own_world_3d_changed() {
|
||||
ERR_FAIL_COND(world_3d.is_null());
|
||||
ERR_FAIL_COND(own_world_3d.is_null());
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_exit_world(this);
|
||||
}
|
||||
|
||||
own_world_3d = world_3d->duplicate();
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_propagate_enter_world(this);
|
||||
}
|
||||
}
|
||||
|
||||
void World::_on_set_use_own_world_3d(bool p_use_own_world_3d) {
|
||||
}
|
||||
|
||||
void World::_on_set_world_3d(const Ref<World3D> &p_old_world) {
|
||||
}
|
||||
void World::_on_set_world_2d(const Ref<World2D> &p_old_world_2d) {
|
||||
}
|
||||
|
||||
@ -612,33 +315,20 @@ void World::_notification(int p_what) {
|
||||
}
|
||||
|
||||
void World::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_camera"), &World::get_camera);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_world_2d"), &World::get_world_2d);
|
||||
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &World::set_world_2d);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_world_3d"), &World::get_world_3d);
|
||||
ClassDB::bind_method(D_METHOD("set_world_3d", "world"), &World::set_world_3d);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &World::is_using_own_world_3d);
|
||||
ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &World::set_use_own_world_3d);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_override_in_parent_viewport"), &World::get_override_in_parent_viewport);
|
||||
ClassDB::bind_method(D_METHOD("set_override_in_parent_viewport", "enable"), &World::set_override_in_parent_viewport);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_in_parent_viewport"), "set_override_in_parent_viewport", "get_override_in_parent_viewport");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("find_world_2d"), &World::find_world_2d);
|
||||
ClassDB::bind_method(D_METHOD("find_world_3d"), &World::find_world_3d);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_override_world"), &World::get_override_world);
|
||||
ClassDB::bind_method(D_METHOD("get_override_world_or_this"), &World::get_override_world_or_this);
|
||||
ClassDB::bind_method(D_METHOD("set_override_world", "world"), &World::set_override_world_bind);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_own_world_3d_changed"), &World::_own_world_3d_changed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &World::set_canvas_transform);
|
||||
ClassDB::bind_method(D_METHOD("get_canvas_transform"), &World::get_canvas_transform);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_canvas_transform", "get_canvas_transform");
|
||||
|
@ -6,33 +6,21 @@
|
||||
|
||||
#include "node.h"
|
||||
|
||||
class Camera;
|
||||
class World3D;
|
||||
class World2D;
|
||||
|
||||
class World : public Node {
|
||||
GDCLASS(World, Node);
|
||||
|
||||
public:
|
||||
Camera *get_camera() const;
|
||||
|
||||
Ref<World2D> get_world_2d() const;
|
||||
void set_world_2d(const Ref<World2D> &p_world_2d);
|
||||
|
||||
Ref<World3D> get_world_3d() const;
|
||||
void set_world_3d(const Ref<World3D> &p_world);
|
||||
|
||||
bool is_using_own_world_3d() const;
|
||||
void set_use_own_world_3d(const bool p_use_own_world_3d);
|
||||
|
||||
bool get_override_in_parent_viewport();
|
||||
void set_override_in_parent_viewport(const bool value);
|
||||
|
||||
//If a World has an override these are overridden
|
||||
Ref<World2D> find_world_2d() const;
|
||||
Ref<World3D> find_world_3d() const;
|
||||
Ref<World2D> find_world_2d_no_override() const;
|
||||
Ref<World3D> find_world_3d_no_override() const;
|
||||
|
||||
World *get_override_world();
|
||||
World *get_override_world_or_this();
|
||||
@ -78,32 +66,12 @@ public:
|
||||
|
||||
void update_worlds();
|
||||
|
||||
void _world_3d_register_camera(Camera *p_camera);
|
||||
void _world_3d_remove_camera(Camera *p_camera);
|
||||
void _world_3d_register_camera_no_override(Camera *p_camera);
|
||||
void _world_3d_remove_camera_no_override(Camera *p_camera);
|
||||
void _world_3d_register_camera_as_override(Camera *p_camera);
|
||||
void _world_3d_remove_camera_as_override(Camera *p_camera);
|
||||
void _clear_override_cameras();
|
||||
void _add_override_cameras(World *p_from);
|
||||
|
||||
World();
|
||||
~World();
|
||||
|
||||
//friend class Camera;
|
||||
void _camera_transform_changed_notify();
|
||||
virtual void _camera_set(Camera *p_camera);
|
||||
bool _camera_add(Camera *p_camera); //true if first
|
||||
void _camera_remove(Camera *p_camera);
|
||||
void _camera_make_next_current(Camera *p_exclude);
|
||||
|
||||
virtual void _update_listener();
|
||||
virtual void _update_listener_2d();
|
||||
|
||||
protected:
|
||||
virtual void _own_world_3d_changed();
|
||||
virtual void _on_set_use_own_world_3d(bool p_use_own_world_3d);
|
||||
virtual void _on_set_world_3d(const Ref<World3D> &p_old_world);
|
||||
virtual void _on_set_world_2d(const Ref<World2D> &p_old_world_2d);
|
||||
|
||||
virtual void _on_before_world_override_changed();
|
||||
@ -117,8 +85,6 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
Ref<World2D> world_2d;
|
||||
Ref<World3D> world_3d;
|
||||
Ref<World3D> own_world_3d;
|
||||
|
||||
World *_parent_world;
|
||||
|
||||
@ -126,11 +92,6 @@ protected:
|
||||
World *_override_world;
|
||||
World *_overriding_world;
|
||||
|
||||
Camera *camera;
|
||||
RBSet<Camera *> cameras;
|
||||
Camera *_own_active_camera;
|
||||
Vector<Camera *> _override_cameras;
|
||||
|
||||
//override canvas layers vec remove /add on override set, and unset
|
||||
|
||||
Size2 size;
|
||||
|
@ -70,16 +70,12 @@
|
||||
#include "scene/2d/touch_screen_button.h"
|
||||
#include "scene/2d/visibility_notifier_2d.h"
|
||||
#include "scene/2d/y_sort.h"
|
||||
#include "scene/3d/label_3d.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/3d/world_environment_3d.h"
|
||||
#include "scene/animation/animation_blend_space_1d.h"
|
||||
#include "scene/animation/animation_blend_space_2d.h"
|
||||
#include "scene/animation/animation_blend_tree.h"
|
||||
#include "scene/animation/animation_node_state_machine.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
#include "scene/animation/animation_tree.h"
|
||||
#include "scene/animation/root_motion_view.h"
|
||||
#include "scene/animation/scene_tree_tween.h"
|
||||
#include "scene/animation/tween.h"
|
||||
#include "scene/audio/audio_stream_player.h"
|
||||
@ -175,33 +171,8 @@
|
||||
#include "scene/resources/texture.h"
|
||||
#include "scene/resources/video_stream.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
#include "scene/resources/world_3d.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
#include "scene/3d/audio_stream_player_3d.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/3d/cpu_particles.h"
|
||||
#include "scene/3d/immediate_geometry.h"
|
||||
#include "scene/3d/interpolated_camera.h"
|
||||
#include "scene/3d/light.h"
|
||||
#include "scene/3d/listener.h"
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/3d/multimesh_instance.h"
|
||||
#include "scene/3d/path.h"
|
||||
#include "scene/3d/position_3d.h"
|
||||
#include "scene/3d/proximity_group.h"
|
||||
#include "scene/3d/reflection_probe.h"
|
||||
#include "scene/3d/remote_transform.h"
|
||||
#include "scene/3d/spatial_velocity_tracker.h"
|
||||
#include "scene/3d/sprite_3d.h"
|
||||
#include "scene/3d/visibility_notifier.h"
|
||||
#include "scene/resources/environment_3d.h"
|
||||
#include "scene/resources/mesh/multimesh.h"
|
||||
#include "scene/resources/occluder_shape.h"
|
||||
#include "scene/resources/occluder_shape_polygon.h"
|
||||
#endif
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // For freetype.
|
||||
|
||||
static Ref<ResourceFormatSaverText> resource_saver_text;
|
||||
@ -369,8 +340,6 @@ void register_scene_types() {
|
||||
|
||||
/* REGISTER 3D */
|
||||
|
||||
ClassDB::register_class<Spatial>();
|
||||
ClassDB::register_virtual_class<SpatialGizmo>();
|
||||
ClassDB::register_class<AnimationPlayer>();
|
||||
ClassDB::register_class<Tween>();
|
||||
ClassDB::register_class<SceneTreeTween>();
|
||||
@ -404,42 +373,11 @@ void register_scene_types() {
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
ClassDB::register_virtual_class<VisualInstance>();
|
||||
ClassDB::register_virtual_class<CullInstance>();
|
||||
ClassDB::register_virtual_class<GeometryInstance>();
|
||||
ClassDB::register_class<Camera>();
|
||||
ClassDB::register_class<Listener>();
|
||||
ClassDB::register_class<InterpolatedCamera>();
|
||||
ClassDB::register_class<MeshInstance>();
|
||||
ClassDB::register_class<ImmediateGeometry>();
|
||||
ClassDB::register_virtual_class<SpriteBase3D>();
|
||||
ClassDB::register_class<Sprite3D>();
|
||||
ClassDB::register_class<AnimatedSprite3D>();
|
||||
ClassDB::register_class<Label3D>();
|
||||
ClassDB::register_virtual_class<Light>();
|
||||
ClassDB::register_class<DirectionalLight>();
|
||||
ClassDB::register_class<OmniLight>();
|
||||
ClassDB::register_class<SpotLight>();
|
||||
ClassDB::register_class<ReflectionProbe>();
|
||||
ClassDB::register_class<CPUParticles>();
|
||||
ClassDB::register_class<Position3D>();
|
||||
ClassDB::register_class<NavigationMesh>();
|
||||
|
||||
ClassDB::register_class<RootMotionView>();
|
||||
ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
ClassDB::register_class<ProximityGroup>();
|
||||
ClassDB::register_class<MultiMeshInstance>();
|
||||
|
||||
ClassDB::register_class<Curve3D>();
|
||||
ClassDB::register_class<Path>();
|
||||
ClassDB::register_class<PathFollow>();
|
||||
ClassDB::register_class<VisibilityNotifier>();
|
||||
ClassDB::register_class<VisibilityEnabler>();
|
||||
ClassDB::register_class<WorldEnvironment3D>();
|
||||
ClassDB::register_class<RemoteTransform>();
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
@ -533,12 +471,8 @@ void register_scene_types() {
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
ClassDB::register_class<SpatialVelocityTracker>();
|
||||
|
||||
#endif
|
||||
ClassDB::register_class<PhysicsMaterial>();
|
||||
ClassDB::register_class<World3D>();
|
||||
ClassDB::register_class<Environment3D>();
|
||||
ClassDB::register_class<World2D>();
|
||||
ClassDB::register_virtual_class<Texture>();
|
||||
ClassDB::register_virtual_class<Sky>();
|
||||
@ -588,9 +522,6 @@ void register_scene_types() {
|
||||
|
||||
ClassDB::register_class<AudioStreamPlayer>();
|
||||
ClassDB::register_class<AudioStreamPlayer2D>();
|
||||
#ifndef _3D_DISABLED
|
||||
ClassDB::register_class<AudioStreamPlayer3D>();
|
||||
#endif
|
||||
ClassDB::register_virtual_class<VideoStream>();
|
||||
ClassDB::register_class<AudioStreamSample>();
|
||||
|
||||
@ -638,17 +569,14 @@ void register_scene_types() {
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
GLOBAL_DEF("layer_names/2d_render/layer_" + itos(i + 1), "");
|
||||
GLOBAL_DEF("layer_names/3d_render/layer_" + itos(i + 1), "");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
GLOBAL_DEF("layer_names/2d_physics/layer_" + itos(i + 1), "");
|
||||
GLOBAL_DEF("layer_names/3d_physics/layer_" + itos(i + 1), "");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
GLOBAL_DEF("layer_names/2d_navigation/layer_" + itos(i + 1), "");
|
||||
GLOBAL_DEF("layer_names/3d_navigation/layer_" + itos(i + 1), "");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "scene/main/node_2d.h"
|
||||
#include "scene/main/spatial.h"
|
||||
#include "scene/main/control.h"
|
||||
#include "core/input/shortcut.h"
|
||||
#include "scene/main/instance_placeholder.h"
|
||||
@ -190,9 +189,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
|
||||
}
|
||||
WARN_PRINT(vformat("Node %s of type %s cannot be created. A placeholder will be created instead.", snames[n.name], snames[n.type]).ascii().get_data());
|
||||
if (n.parent >= 0 && n.parent < nc && ret_nodes[n.parent]) {
|
||||
if (Object::cast_to<Spatial>(ret_nodes[n.parent])) {
|
||||
obj = memnew(Spatial);
|
||||
} else if (Object::cast_to<Control>(ret_nodes[n.parent])) {
|
||||
if (Object::cast_to<Control>(ret_nodes[n.parent])) {
|
||||
obj = memnew(Control);
|
||||
} else if (Object::cast_to<Node2D>(ret_nodes[n.parent])) {
|
||||
obj = memnew(Node2D);
|
||||
|
@ -1,371 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* world.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "world_3d.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/math/octree.h"
|
||||
#include "core/math/projection.h"
|
||||
#include "scene/3d/camera.h"
|
||||
#include "scene/3d/visibility_notifier.h"
|
||||
#include "scene/main/scene_string_names.h"
|
||||
#include "servers/navigation_server.h"
|
||||
|
||||
struct SpatialIndexer {
|
||||
Octree<VisibilityNotifier> octree;
|
||||
|
||||
struct NotifierData {
|
||||
AABB aabb;
|
||||
OctreeElementID id;
|
||||
};
|
||||
|
||||
RBMap<VisibilityNotifier *, NotifierData> notifiers;
|
||||
struct CameraData {
|
||||
RBMap<VisibilityNotifier *, uint64_t> notifiers;
|
||||
};
|
||||
|
||||
RBMap<Camera *, CameraData> cameras;
|
||||
|
||||
enum {
|
||||
VISIBILITY_CULL_MAX = 32768
|
||||
};
|
||||
|
||||
Vector<VisibilityNotifier *> cull;
|
||||
|
||||
bool changed;
|
||||
uint64_t pass;
|
||||
uint64_t last_frame;
|
||||
|
||||
void _notifier_add(VisibilityNotifier *p_notifier, const AABB &p_rect) {
|
||||
ERR_FAIL_COND(notifiers.has(p_notifier));
|
||||
notifiers[p_notifier].aabb = p_rect;
|
||||
notifiers[p_notifier].id = octree.create(p_notifier, p_rect);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _notifier_update(VisibilityNotifier *p_notifier, const AABB &p_rect) {
|
||||
RBMap<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier);
|
||||
ERR_FAIL_COND(!E);
|
||||
if (E->get().aabb == p_rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
E->get().aabb = p_rect;
|
||||
octree.move(E->get().id, E->get().aabb);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _notifier_remove(VisibilityNotifier *p_notifier) {
|
||||
RBMap<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier);
|
||||
ERR_FAIL_COND(!E);
|
||||
|
||||
octree.erase(E->get().id);
|
||||
notifiers.erase(p_notifier);
|
||||
|
||||
List<Camera *> removed;
|
||||
for (RBMap<Camera *, CameraData>::Element *F = cameras.front(); F; F = F->next()) {
|
||||
RBMap<VisibilityNotifier *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier);
|
||||
|
||||
if (G) {
|
||||
F->get().notifiers.erase(G);
|
||||
removed.push_back(F->key());
|
||||
}
|
||||
}
|
||||
|
||||
while (!removed.empty()) {
|
||||
p_notifier->_exit_camera(removed.front()->get());
|
||||
removed.pop_front();
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _add_camera(Camera *p_camera) {
|
||||
ERR_FAIL_COND(cameras.has(p_camera));
|
||||
CameraData vd;
|
||||
cameras[p_camera] = vd;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _update_camera(Camera *p_camera) {
|
||||
RBMap<Camera *, CameraData>::Element *E = cameras.find(p_camera);
|
||||
ERR_FAIL_COND(!E);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _remove_camera(Camera *p_camera) {
|
||||
ERR_FAIL_COND(!cameras.has(p_camera));
|
||||
List<VisibilityNotifier *> removed;
|
||||
for (RBMap<VisibilityNotifier *, uint64_t>::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) {
|
||||
removed.push_back(E->key());
|
||||
}
|
||||
|
||||
while (!removed.empty()) {
|
||||
removed.front()->get()->_exit_camera(p_camera);
|
||||
removed.pop_front();
|
||||
}
|
||||
|
||||
cameras.erase(p_camera);
|
||||
}
|
||||
|
||||
void _update(uint64_t p_frame) {
|
||||
if (p_frame == last_frame) {
|
||||
return;
|
||||
}
|
||||
last_frame = p_frame;
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RBMap<Camera *, CameraData>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
pass++;
|
||||
|
||||
// prepare camera info
|
||||
Camera *c = E->key();
|
||||
Vector3 cam_pos = c->get_global_transform().origin;
|
||||
Vector<Plane> planes = c->get_frustum();
|
||||
bool cam_is_ortho = c->get_projection() == Camera::PROJECTION_ORTHOGONAL;
|
||||
|
||||
int culled = octree.cull_convex(planes, cull.ptrw(), cull.size());
|
||||
|
||||
VisibilityNotifier **ptr = cull.ptrw();
|
||||
|
||||
List<VisibilityNotifier *> added;
|
||||
List<VisibilityNotifier *> removed;
|
||||
|
||||
for (int i = 0; i < culled; i++) {
|
||||
//notifiers in frustum
|
||||
|
||||
// check and remove notifiers that have a max range
|
||||
VisibilityNotifier &nt = *ptr[i];
|
||||
if (nt.is_max_distance_active() && !cam_is_ortho) {
|
||||
Vector3 offset = nt.get_world_aabb_center() - cam_pos;
|
||||
if ((offset.length_squared() >= nt.get_max_distance_squared()) && !nt.inside_max_distance_leadin()) {
|
||||
// unordered remove
|
||||
cull.set(i, cull[culled - 1]);
|
||||
culled--;
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RBMap<VisibilityNotifier *, uint64_t>::Element *H = E->get().notifiers.find(ptr[i]);
|
||||
if (!H) {
|
||||
E->get().notifiers.insert(ptr[i], pass);
|
||||
added.push_back(ptr[i]);
|
||||
} else {
|
||||
H->get() = pass;
|
||||
}
|
||||
}
|
||||
|
||||
for (RBMap<VisibilityNotifier *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) {
|
||||
if (F->get() != pass) {
|
||||
removed.push_back(F->key());
|
||||
}
|
||||
}
|
||||
|
||||
while (!added.empty()) {
|
||||
added.front()->get()->_enter_camera(E->key());
|
||||
added.pop_front();
|
||||
}
|
||||
|
||||
while (!removed.empty()) {
|
||||
E->get().notifiers.erase(removed.front()->get());
|
||||
removed.front()->get()->_exit_camera(E->key());
|
||||
removed.pop_front();
|
||||
}
|
||||
}
|
||||
changed = false;
|
||||
}
|
||||
|
||||
SpatialIndexer() {
|
||||
pass = 0;
|
||||
last_frame = 0;
|
||||
changed = false;
|
||||
cull.resize(VISIBILITY_CULL_MAX);
|
||||
}
|
||||
};
|
||||
|
||||
void World3D::_register_camera(Camera *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_add_camera(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update_camera(Camera *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_update_camera(p_camera);
|
||||
#endif
|
||||
}
|
||||
void World3D::_remove_camera(Camera *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_remove_camera(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_add(p_notifier, p_rect);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_update(p_notifier, p_rect);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_remove_notifier(VisibilityNotifier *p_notifier) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_remove(p_notifier);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update(uint64_t p_frame) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_update(p_frame);
|
||||
#endif
|
||||
}
|
||||
|
||||
RID World3D::get_space() const {
|
||||
return space;
|
||||
}
|
||||
RID World3D::get_scenario() const {
|
||||
return scenario;
|
||||
}
|
||||
|
||||
RID World3D::get_navigation_map() const {
|
||||
return navigation_map;
|
||||
}
|
||||
|
||||
void World3D::set_environment(const Ref<Environment3D> &p_environment) {
|
||||
if (environment == p_environment) {
|
||||
return;
|
||||
}
|
||||
|
||||
environment = p_environment;
|
||||
if (environment.is_valid()) {
|
||||
RS::get_singleton()->scenario_set_environment(scenario, environment->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->scenario_set_environment(scenario, RID());
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Ref<Environment3D> World3D::get_environment() const {
|
||||
return environment;
|
||||
}
|
||||
|
||||
void World3D::set_fallback_environment(const Ref<Environment3D> &p_environment) {
|
||||
if (fallback_environment == p_environment) {
|
||||
return;
|
||||
}
|
||||
|
||||
fallback_environment = p_environment;
|
||||
if (fallback_environment.is_valid()) {
|
||||
RS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid());
|
||||
} else {
|
||||
RS::get_singleton()->scenario_set_fallback_environment(scenario, RID());
|
||||
}
|
||||
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
Ref<Environment3D> World3D::get_fallback_environment() const {
|
||||
return fallback_environment;
|
||||
}
|
||||
|
||||
void World3D::get_camera_list(List<Camera *> *r_cameras) {
|
||||
for (RBMap<Camera *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) {
|
||||
r_cameras->push_back(E->key());
|
||||
}
|
||||
}
|
||||
|
||||
void World3D::move_cameras_into(Ref<World3D> target) {
|
||||
ERR_FAIL_COND(!target.is_valid());
|
||||
|
||||
List<Camera *> cameras;
|
||||
get_camera_list(&cameras);
|
||||
|
||||
for (List<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
Camera *cam = E->get();
|
||||
|
||||
_remove_camera(cam);
|
||||
target->_register_camera(cam);
|
||||
}
|
||||
}
|
||||
|
||||
void World3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space);
|
||||
ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map);
|
||||
ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment);
|
||||
ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
|
||||
ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World3D::set_fallback_environment);
|
||||
ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World3D::get_fallback_environment);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment3D"), "set_environment", "get_environment");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment3D"), "set_fallback_environment", "get_fallback_environment");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", 0), "", "get_scenario");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState", 0), "", "get_direct_space_state");
|
||||
}
|
||||
|
||||
World3D::World3D() {
|
||||
scenario = RID_PRIME(RenderingServer::get_singleton()->scenario_create());
|
||||
|
||||
// Create default navigation map
|
||||
navigation_map = NavigationServer::get_singleton()->map_create();
|
||||
NavigationServer::get_singleton()->map_set_active(navigation_map, true);
|
||||
NavigationServer::get_singleton()->map_set_up(navigation_map, GLOBAL_DEF("navigation/3d/default_map_up", Vector3(0, 1, 0)));
|
||||
NavigationServer::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.25));
|
||||
NavigationServer::get_singleton()->map_set_cell_height(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_height", 0.25));
|
||||
NavigationServer::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.25));
|
||||
NavigationServer::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_DEF("navigation/3d/default_link_connection_radius", 1.0));
|
||||
NavigationServer::get_singleton()->map_set_use_edge_connections(navigation_map, GLOBAL_DEF("navigation/3d/use_edge_connections", true));
|
||||
|
||||
#ifdef _3D_DISABLED
|
||||
indexer = NULL;
|
||||
#else
|
||||
indexer = memnew(SpatialIndexer);
|
||||
#endif
|
||||
}
|
||||
|
||||
World3D::~World3D() {
|
||||
RenderingServer::get_singleton()->free(scenario);
|
||||
NavigationServer::get_singleton()->free(navigation_map);
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
memdelete(indexer);
|
||||
#endif
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
#ifndef WORLD_3D_H
|
||||
#define WORLD_3D_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* world.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/object/resource.h"
|
||||
#include "scene/resources/environment_3d.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class Camera;
|
||||
class VisibilityNotifier;
|
||||
struct SpatialIndexer;
|
||||
|
||||
class World3D : public Resource {
|
||||
GDCLASS(World3D, Resource);
|
||||
RES_BASE_EXTENSION("world3d");
|
||||
|
||||
private:
|
||||
RID space;
|
||||
RID scenario;
|
||||
RID navigation_map;
|
||||
SpatialIndexer *indexer;
|
||||
Ref<Environment3D> environment;
|
||||
Ref<Environment3D> fallback_environment;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
friend class Camera;
|
||||
friend class VisibilityNotifier;
|
||||
|
||||
void _register_camera(Camera *p_camera);
|
||||
void _update_camera(Camera *p_camera);
|
||||
void _remove_camera(Camera *p_camera);
|
||||
|
||||
void _register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect);
|
||||
void _update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect);
|
||||
void _remove_notifier(VisibilityNotifier *p_notifier);
|
||||
friend class Viewport;
|
||||
friend class World;
|
||||
void _update(uint64_t p_frame);
|
||||
|
||||
public:
|
||||
RID get_space() const;
|
||||
RID get_scenario() const;
|
||||
RID get_navigation_map() const;
|
||||
|
||||
void set_environment(const Ref<Environment3D> &p_environment);
|
||||
Ref<Environment3D> get_environment() const;
|
||||
|
||||
void set_fallback_environment(const Ref<Environment3D> &p_environment);
|
||||
Ref<Environment3D> get_fallback_environment() const;
|
||||
|
||||
void get_camera_list(List<Camera *> *r_cameras);
|
||||
|
||||
void move_cameras_into(Ref<World3D> target);
|
||||
|
||||
World3D();
|
||||
~World3D();
|
||||
};
|
||||
|
||||
#endif // WORLD_3D_H
|
Loading…
Reference in New Issue
Block a user