WIP: Onion Skinning Prototype #107641

Closed
Christoph Lendenfeld wants to merge 22 commits from ChrisLend/blender:onion_skin_test into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
92 changed files with 490 additions and 382 deletions
Showing only changes of commit cd0be6f49e - Show all commits

View File

@ -374,7 +374,7 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
# - Rename remote "upstream" to "origin", which takes care of changing the names of
# remotes the local branches are tracking.
#
# - Change the URL to the "origin", which so was was still pointing to upstream.
# - Change the URL to the "origin", which was still pointing to upstream.
#
# - Re-introduce the "upstream" remote, with the same URL as it had prior to rename.

View File

@ -24,3 +24,4 @@ Several people provided fixes:
- Aaron Carlisle
- Sebastian Parborg
- Leon Zandman
- Richard Antalik

View File

@ -124,7 +124,7 @@ Device_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
}
PyDoc_STRVAR(M_aud_Device_lock_doc,
".. classmethod:: lock()\n\n"
".. method:: lock()\n\n"
" Locks the device so that it's guaranteed, that no samples are\n"
" read from the streams until :meth:`unlock` is called.\n"
" This is useful if you want to do start/stop/pause/resume some\n"
@ -152,7 +152,7 @@ Device_lock(Device* self)
}
PyDoc_STRVAR(M_aud_Device_play_doc,
".. classmethod:: play(sound, keep=False)\n\n"
".. method:: play(sound, keep=False)\n\n"
" Plays a sound.\n\n"
" :arg sound: The sound to play.\n"
" :type sound: :class:`Sound`\n"
@ -212,7 +212,7 @@ Device_play(Device* self, PyObject* args, PyObject* kwds)
}
PyDoc_STRVAR(M_aud_Device_stopAll_doc,
".. classmethod:: stopAll()\n\n"
".. method:: stopAll()\n\n"
" Stops all playing and paused sounds.");
static PyObject *
@ -231,7 +231,7 @@ Device_stopAll(Device* self)
}
PyDoc_STRVAR(M_aud_Device_unlock_doc,
".. classmethod:: unlock()\n\n"
".. method:: unlock()\n\n"
" Unlocks the device after a lock call, see :meth:`lock` for\n"
" details.");

View File

@ -60,7 +60,7 @@ DynamicMusic_dealloc(DynamicMusicP* self)
}
PyDoc_STRVAR(M_aud_DynamicMusic_addScene_doc,
".. classmethod:: addScene(scene)\n\n"
".. method:: addScene(scene)\n\n"
" Adds a new scene.\n\n"
" :arg scene: The scene sound.\n"
" :type scene: :class:`Sound`\n"
@ -90,7 +90,7 @@ DynamicMusic_addScene(DynamicMusicP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_DynamicMusic_addTransition_doc,
".. classmethod:: addTransition(ini, end, transition)\n\n"
".. method:: addTransition(ini, end, transition)\n\n"
" Adds a new scene.\n\n"
" :arg ini: the initial scene foor the transition.\n"
" :type ini: int\n"
@ -125,7 +125,7 @@ DynamicMusic_addTransition(DynamicMusicP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_DynamicMusic_resume_doc,
".. classmethod:: resume()\n\n"
".. method:: resume()\n\n"
" Resumes playback of the scene.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool");
@ -145,7 +145,7 @@ DynamicMusic_resume(DynamicMusicP* self)
}
PyDoc_STRVAR(M_aud_DynamicMusic_pause_doc,
".. classmethod:: pause()\n\n"
".. method:: pause()\n\n"
" Pauses playback of the scene.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool");
@ -165,7 +165,7 @@ DynamicMusic_pause(DynamicMusicP* self)
}
PyDoc_STRVAR(M_aud_DynamicMusic_stop_doc,
".. classmethod:: stop()\n\n"
".. method:: stop()\n\n"
" Stops playback of the scene.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool\n\n");

View File

@ -54,7 +54,7 @@ HRTF_dealloc(HRTFP* self)
}
PyDoc_STRVAR(M_aud_HRTF_addImpulseResponse_doc,
".. classmethod:: addImpulseResponseFromSound(sound, azimuth, elevation)\n\n"
".. method:: addImpulseResponseFromSound(sound, azimuth, elevation)\n\n"
" Adds a new hrtf to the HRTF object\n\n"
" :arg sound: The sound that contains the hrtf.\n"
" :type sound: :class:`Sound`\n"
@ -90,7 +90,7 @@ HRTF_addImpulseResponseFromSound(HRTFP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_HRTF_loadLeftHrtfSet_doc,
".. classmethod:: loadLeftHrtfSet(extension, directory)\n\n"
".. method:: loadLeftHrtfSet(extension, directory)\n\n"
" Loads all HRTFs from a directory.\n\n"
" :arg extension: The file extension of the hrtfs.\n"
" :type extension: string\n"
@ -125,7 +125,7 @@ HRTF_loadLeftHrtfSet(PyTypeObject* type, PyObject* args)
}
PyDoc_STRVAR(M_aud_HRTF_loadRightHrtfSet_doc,
".. classmethod:: loadLeftHrtfSet(extension, directory)\n\n"
".. method:: loadLeftHrtfSet(extension, directory)\n\n"
" Loads all HRTFs from a directory.\n\n"
" :arg extension: The file extension of the hrtfs.\n"
" :type extension: string\n"

View File

@ -38,7 +38,7 @@ Handle_dealloc(Handle* self)
}
PyDoc_STRVAR(M_aud_Handle_pause_doc,
".. classmethod:: pause()\n\n"
".. method:: pause()\n\n"
" Pauses playback.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool");
@ -58,7 +58,7 @@ Handle_pause(Handle* self)
}
PyDoc_STRVAR(M_aud_Handle_resume_doc,
".. classmethod:: resume()\n\n"
".. method:: resume()\n\n"
" Resumes playback.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool");
@ -78,7 +78,7 @@ Handle_resume(Handle* self)
}
PyDoc_STRVAR(M_aud_Handle_stop_doc,
".. classmethod:: stop()\n\n"
".. method:: stop()\n\n"
" Stops playback.\n\n"
" :return: Whether the action succeeded.\n"
" :rtype: bool\n\n"

View File

@ -60,7 +60,7 @@ PlaybackManager_dealloc(PlaybackManagerP* self)
}
PyDoc_STRVAR(M_aud_PlaybackManager_play_doc,
".. classmethod:: play(sound, catKey)\n\n"
".. method:: play(sound, catKey)\n\n"
" Plays a sound through the playback manager and assigns it to a category.\n\n"
" :arg sound: The sound to play.\n"
" :type sound: :class:`Sound`\n"
@ -104,7 +104,7 @@ PlaybackManager_play(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_resume_doc,
".. classmethod:: resume(catKey)\n\n"
".. method:: resume(catKey)\n\n"
" Resumes playback of the catgory.\n\n"
" :arg catKey: the key of the category.\n"
" :type catKey: int\n"
@ -131,7 +131,7 @@ PlaybackManager_resume(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_pause_doc,
".. classmethod:: pause(catKey)\n\n"
".. method:: pause(catKey)\n\n"
" Pauses playback of the category.\n\n"
" :arg catKey: the key of the category.\n"
" :type catKey: int\n"
@ -158,7 +158,7 @@ PlaybackManager_pause(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_add_category_doc,
".. classmethod:: addCategory(volume)\n\n"
".. method:: addCategory(volume)\n\n"
" Adds a category with a custom volume.\n\n"
" :arg volume: The volume for ther new category.\n"
" :type volume: float\n"
@ -185,7 +185,7 @@ PlaybackManager_add_category(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_get_volume_doc,
".. classmethod:: getVolume(catKey)\n\n"
".. method:: getVolume(catKey)\n\n"
" Retrieves the volume of a category.\n\n"
" :arg catKey: the key of the category.\n"
" :type catKey: int\n"
@ -212,7 +212,7 @@ PlaybackManager_get_volume(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_set_volume_doc,
".. classmethod:: setVolume(volume, catKey)\n\n"
".. method:: setVolume(volume, catKey)\n\n"
" Changes the volume of a category.\n\n"
" :arg volume: the new volume value.\n"
" :type volume: float\n"
@ -242,7 +242,7 @@ PlaybackManager_set_volume(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_stop_doc,
".. classmethod:: stop(catKey)\n\n"
".. method:: stop(catKey)\n\n"
" Stops playback of the category.\n\n"
" :arg catKey: the key of the category.\n"
" :type catKey: int\n"
@ -269,7 +269,7 @@ PlaybackManager_stop(PlaybackManagerP* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_PlaybackManager_clean_doc,
".. classmethod:: clean()\n\n"
".. method:: clean()\n\n"
" Cleans all the invalid and finished sound from the playback manager.\n\n");
static PyObject *

View File

@ -99,7 +99,7 @@ Sequence_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
}
PyDoc_STRVAR(M_aud_Sequence_add_doc,
".. classmethod:: add()\n\n"
".. method:: add()\n\n"
" Adds a new entry to the sequence.\n\n"
" :arg sound: The sound this entry should play.\n"
" :type sound: :class:`Sound`\n"
@ -151,7 +151,7 @@ Sequence_add(Sequence* self, PyObject* args, PyObject* kwds)
}
PyDoc_STRVAR(M_aud_Sequence_remove_doc,
".. classmethod:: remove()\n\n"
".. method:: remove()\n\n"
" Removes an entry from the sequence.\n\n"
" :arg entry: The entry to remove.\n"
" :type entry: :class:`SequenceEntry`\n");
@ -183,7 +183,7 @@ Sequence_remove(Sequence* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sequence_setAnimationData_doc,
".. classmethod:: setAnimationData()\n\n"
".. method:: setAnimationData()\n\n"
" Writes animation data to a sequence.\n\n"
" :arg type: The type of animation data.\n"
" :type type: int\n"

View File

@ -43,7 +43,7 @@ SequenceEntry_dealloc(SequenceEntry* self)
}
PyDoc_STRVAR(M_aud_SequenceEntry_move_doc,
".. classmethod:: move()\n\n"
".. method:: move()\n\n"
" Moves the entry.\n\n"
" :arg begin: The new start time.\n"
" :type begin: double\n"
@ -73,7 +73,7 @@ SequenceEntry_move(SequenceEntry* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_SequenceEntry_setAnimationData_doc,
".. classmethod:: setAnimationData()\n\n"
".. method:: setAnimationData()\n\n"
" Writes animation data to a sequenced entry.\n\n"
" :arg type: The type of animation data.\n"
" :type type: int\n"

View File

@ -115,7 +115,7 @@ Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
}
PyDoc_STRVAR(M_aud_Sound_data_doc,
".. classmethod:: data()\n\n"
".. method:: data()\n\n"
" Retrieves the data of the sound as numpy array.\n\n"
" :return: A two dimensional numpy float array.\n"
" :rtype: :class:`numpy.ndarray`\n\n"
@ -146,7 +146,7 @@ Sound_data(Sound* self)
}
PyDoc_STRVAR(M_aud_Sound_write_doc,
".. classmethod:: write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n"
".. method:: write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n"
" Writes the sound to a file.\n\n"
" :arg filename: The path to write to.\n"
" :type filename: string\n"
@ -357,7 +357,7 @@ Sound_buffer(PyTypeObject* type, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_cache_doc,
".. classmethod:: cache()\n\n"
".. method:: cache()\n\n"
" Caches a sound into RAM.\n\n"
" This saves CPU usage needed for decoding and file access if the\n"
" underlying sound reads from a file on the harddisk,\n"
@ -631,7 +631,7 @@ Sound_triangle(PyTypeObject* type, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_accumulate_doc,
".. classmethod:: accumulate(additive=False)\n\n"
".. method:: accumulate(additive=False)\n\n"
" Accumulates a sound by summing over positive input\n"
" differences thus generating a monotonic sigal.\n"
" If additivity is set to true negative input differences get added too,\n"
@ -683,7 +683,7 @@ Sound_accumulate(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_ADSR_doc,
".. classmethod:: ADSR(attack, decay, sustain, release)\n\n"
".. method:: ADSR(attack, decay, sustain, release)\n\n"
" Attack-Decay-Sustain-Release envelopes the volume of a sound.\n"
" Note: there is currently no way to trigger the release with this API.\n\n"
" :arg attack: The attack time in seconds.\n"
@ -726,7 +726,7 @@ Sound_ADSR(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_delay_doc,
".. classmethod:: delay(time)\n\n"
".. method:: delay(time)\n\n"
" Delays by playing adding silence in front of the other sound's data.\n\n"
" :arg time: How many seconds of silence should be added before the sound.\n"
" :type time: float\n"
@ -762,7 +762,7 @@ Sound_delay(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_envelope_doc,
".. classmethod:: envelope(attack, release, threshold, arthreshold)\n\n"
".. method:: envelope(attack, release, threshold, arthreshold)\n\n"
" Delays by playing adding silence in front of the other sound's data.\n\n"
" :arg attack: The attack factor.\n"
" :type attack: float\n"
@ -804,7 +804,7 @@ Sound_envelope(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_fadein_doc,
".. classmethod:: fadein(start, length)\n\n"
".. method:: fadein(start, length)\n\n"
" Fades a sound in by raising the volume linearly in the given\n"
" time interval.\n\n"
" :arg start: Time in seconds when the fading should start.\n"
@ -844,7 +844,7 @@ Sound_fadein(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_fadeout_doc,
".. classmethod:: fadeout(start, length)\n\n"
".. method:: fadeout(start, length)\n\n"
" Fades a sound in by lowering the volume linearly in the given\n"
" time interval.\n\n"
" :arg start: Time in seconds when the fading should start.\n"
@ -886,7 +886,7 @@ Sound_fadeout(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_filter_doc,
".. classmethod:: filter(b, a = (1))\n\n"
".. method:: filter(b, a = (1))\n\n"
" Filters a sound with the supplied IIR filter coefficients.\n"
" Without the second parameter you'll get a FIR filter.\n\n"
" If the first value of the a sequence is 0,\n"
@ -986,7 +986,7 @@ Sound_filter(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_highpass_doc,
".. classmethod:: highpass(frequency, Q=0.5)\n\n"
".. method:: highpass(frequency, Q=0.5)\n\n"
" Creates a second order highpass filter based on the transfer\n"
" function :math:`H(s) = s^2 / (s^2 + s/Q + 1)`\n\n"
" :arg frequency: The cut off trequency of the highpass.\n"
@ -1026,7 +1026,7 @@ Sound_highpass(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_limit_doc,
".. classmethod:: limit(start, end)\n\n"
".. method:: limit(start, end)\n\n"
" Limits a sound within a specific start and end time.\n\n"
" :arg start: Start time in seconds.\n"
" :type start: float\n"
@ -1064,7 +1064,7 @@ Sound_limit(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_loop_doc,
".. classmethod:: loop(count)\n\n"
".. method:: loop(count)\n\n"
" Loops a sound.\n\n"
" :arg count: How often the sound should be looped.\n"
" Negative values mean endlessly.\n"
@ -1104,7 +1104,7 @@ Sound_loop(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_lowpass_doc,
".. classmethod:: lowpass(frequency, Q=0.5)\n\n"
".. method:: lowpass(frequency, Q=0.5)\n\n"
" Creates a second order lowpass filter based on the transfer "
" function :math:`H(s) = 1 / (s^2 + s/Q + 1)`\n\n"
" :arg frequency: The cut off trequency of the lowpass.\n"
@ -1144,7 +1144,7 @@ Sound_lowpass(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_modulate_doc,
".. classmethod:: modulate(sound)\n\n"
".. method:: modulate(sound)\n\n"
" Modulates two factories.\n\n"
" :arg sound: The sound to modulate over the other.\n"
" :type sound: :class:`Sound`\n"
@ -1186,7 +1186,7 @@ Sound_modulate(Sound* self, PyObject* object)
}
PyDoc_STRVAR(M_aud_Sound_pitch_doc,
".. classmethod:: pitch(factor)\n\n"
".. method:: pitch(factor)\n\n"
" Changes the pitch of a sound with a specific factor.\n\n"
" :arg factor: The factor to change the pitch with.\n"
" :type factor: float\n"
@ -1229,7 +1229,7 @@ Sound_pitch(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_rechannel_doc,
".. classmethod:: rechannel(channels)\n\n"
".. method:: rechannel(channels)\n\n"
" Rechannels the sound.\n\n"
" :arg channels: The new channel configuration.\n"
" :type channels: int\n"
@ -1269,7 +1269,7 @@ Sound_rechannel(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_resample_doc,
".. classmethod:: resample(rate, high_quality)\n\n"
".. method:: resample(rate, high_quality)\n\n"
" Resamples the sound.\n\n"
" :arg rate: The new sample rate.\n"
" :type rate: double\n"
@ -1324,7 +1324,7 @@ Sound_resample(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_reverse_doc,
".. classmethod:: reverse()\n\n"
".. method:: reverse()\n\n"
" Plays a sound reversed.\n\n"
" :return: The created :class:`Sound` object.\n"
" :rtype: :class:`Sound`\n\n"
@ -1362,7 +1362,7 @@ Sound_reverse(Sound* self)
}
PyDoc_STRVAR(M_aud_Sound_sum_doc,
".. classmethod:: sum()\n\n"
".. method:: sum()\n\n"
" Sums the samples of a sound.\n\n"
" :return: The created :class:`Sound` object.\n"
" :rtype: :class:`Sound`");
@ -1391,7 +1391,7 @@ Sound_sum(Sound* self)
}
PyDoc_STRVAR(M_aud_Sound_threshold_doc,
".. classmethod:: threshold(threshold = 0)\n\n"
".. method:: threshold(threshold = 0)\n\n"
" Makes a threshold wave out of an audio wave by setting all samples\n"
" with a amplitude >= threshold to 1, all <= -threshold to -1 and\n"
" all between to 0.\n\n"
@ -1430,7 +1430,7 @@ Sound_threshold(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_volume_doc,
".. classmethod:: volume(volume)\n\n"
".. method:: volume(volume)\n\n"
" Changes the volume of a sound.\n\n"
" :arg volume: The new volume..\n"
" :type volume: float\n"
@ -1471,7 +1471,7 @@ Sound_volume(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_join_doc,
".. classmethod:: join(sound)\n\n"
".. method:: join(sound)\n\n"
" Plays two factories in sequence.\n\n"
" :arg sound: The sound to play second.\n"
" :type sound: :class:`Sound`\n"
@ -1514,7 +1514,7 @@ Sound_join(Sound* self, PyObject* object)
}
PyDoc_STRVAR(M_aud_Sound_mix_doc,
".. classmethod:: mix(sound)\n\n"
".. method:: mix(sound)\n\n"
" Mixes two factories.\n\n"
" :arg sound: The sound to mix over the other.\n"
" :type sound: :class:`Sound`\n"
@ -1556,7 +1556,7 @@ Sound_mix(Sound* self, PyObject* object)
}
PyDoc_STRVAR(M_aud_Sound_pingpong_doc,
".. classmethod:: pingpong()\n\n"
".. method:: pingpong()\n\n"
" Plays a sound forward and then backward.\n"
" This is like joining a sound with its reverse.\n\n"
" :return: The created :class:`Sound` object.\n"
@ -1622,7 +1622,7 @@ Sound_list(PyTypeObject* type, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_mutable_doc,
".. classmethod:: mutable()\n\n"
".. method:: mutable()\n\n"
" Creates a sound that will be restarted when sought backwards.\n"
" If the original sound is a sound list, the playing sound can change.\n\n"
" :return: The created :class:`Sound` object.\n"
@ -1652,7 +1652,7 @@ Sound_mutable(Sound* self)
}
PyDoc_STRVAR(M_aud_Sound_list_addSound_doc,
".. classmethod:: addSound(sound)\n\n"
".. method:: addSound(sound)\n\n"
" Adds a new sound to a sound list.\n\n"
" :arg sound: The sound that will be added to the list.\n"
" :type sound: :class:`Sound`\n\n"
@ -1685,7 +1685,7 @@ Sound_list_addSound(Sound* self, PyObject* object)
#ifdef WITH_CONVOLUTION
PyDoc_STRVAR(M_aud_Sound_convolver_doc,
".. classmethod:: convolver()\n\n"
".. method:: convolver()\n\n"
" Creates a sound that will apply convolution to another sound.\n\n"
" :arg impulseResponse: The filter with which convolve the sound.\n"
" :type impulseResponse: :class:`ImpulseResponse`\n"
@ -1734,7 +1734,7 @@ Sound_convolver(Sound* self, PyObject* args)
}
PyDoc_STRVAR(M_aud_Sound_binaural_doc,
".. classmethod:: convolver()\n\n"
".. method:: binaural()\n\n"
" Creates a binaural sound using another sound as source. The original sound must be mono\n\n"
" :arg hrtfs: An HRTF set.\n"
" :type hrtf: :class:`HRTF`\n"

View File

@ -2446,6 +2446,14 @@ def draw_pause(self, context):
layout.prop(cscene, "preview_pause", icon='PLAY' if cscene.preview_pause else 'PAUSE', text="")
def draw_make_links(self, context):
if context.engine == "CYCLES":
layout = self.layout
layout.separator()
layout.operator_menu_enum("object.light_linking_receivers_link", "link_state")
layout.operator_menu_enum("object.light_linking_blockers_link", "link_state")
def get_panels():
exclude_panels = {
'DATA_PT_camera_dof',
@ -2584,6 +2592,7 @@ def register():
bpy.types.RENDER_PT_context.append(draw_device)
bpy.types.VIEW3D_HT_header.append(draw_pause)
bpy.types.VIEW3D_MT_make_links.append(draw_make_links)
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
@ -2597,6 +2606,7 @@ def unregister():
bpy.types.RENDER_PT_context.remove(draw_device)
bpy.types.VIEW3D_HT_header.remove(draw_pause)
bpy.types.VIEW3D_MT_make_links.remove(draw_make_links)
for panel in get_panels():
if 'CYCLES' in panel.COMPAT_ENGINES:

View File

@ -38,6 +38,8 @@ void BlenderSync::sync_light(BL::Object &b_parent,
}
}
light->name = b_light.name().c_str();
/* type */
switch (b_light.type()) {
case BL::Light::type_POINT: {

View File

@ -396,7 +396,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc,
* - Purely reflective closures can't have refraction.
* - Purely refractive closures can't have reflection.
*/
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 1e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_refraction) ||
(is_refraction && !m_refractive) || (!is_refraction && m_refractive && !m_glass))
{
*pdf = 0.0f;
@ -478,7 +478,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type);
const float alpha_x = bsdf->alpha_x;
const float alpha_y = bsdf->alpha_y;
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 1e-7f);
bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 5e-7f);
const float3 N = bsdf->N;
const float cos_NI = dot(N, wi);

View File

@ -32,6 +32,14 @@ ccl_device_inline void integrate_camera_sample(KernelGlobals kg,
path_rng_3D(kg, rng_hash, sample, PRNG_LENS_TIME) :
zero_float3();
/* We use x for time and y,z for lens because in practice with Sobol
* sampling this seems to give better convergence when an object is
* both motion blurred and out of focus, without significantly harming
* convergence for focal blur alone. This is a little surprising,
* because one would expect using x,y for lens (the 2d part) would be
* best, since x,y are the best stratified. Since it's not entirely
* clear why this is, this is probably worth revisiting at some point
* to investigate further. */
const float rand_time = rand_time_lens.x;
const float2 rand_lens = make_float2(rand_time_lens.y, rand_time_lens.z);

View File

@ -49,7 +49,7 @@ ccl_device int shadow_linking_pick_mesh_intersection(KernelGlobals kg,
}
/* Only record primitives that potentially have emission.
* TODO: optimize with a dedicated ray visiblity flag, which could then also be
* TODO: optimize with a dedicated ray visibility flag, which could then also be
* used once lights are in the BVH as geometry? */
const int shader = intersection_get_shader(kg, &current_isect);
const int shader_flags = kernel_data_fetch(shaders, shader).flags;

View File

@ -483,12 +483,7 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
if (!hit)
break;
// TODO: Is the fetch needed here? The shade_surface simply reads isect->object.
int hit_object = (projection_isect.object == OBJECT_NONE) ?
kernel_data_fetch(prim_object, projection_isect.prim) :
projection_isect.object;
if (hit_object == mv.object) {
if (projection_isect.object == mv.object) {
projection_success = true;
break;
}

View File

@ -140,7 +140,9 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
#endif
#ifdef __LIGHT_LINKING__
if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), lamp)) {
if (!light_link_light_match(kg, light_link_receiver_forward(kg, state), lamp) &&
!(path_flag & PATH_RAY_CAMERA))
{
continue;
}
#endif

View File

@ -4,9 +4,12 @@
#pragma once
#include "kernel/integrator/path_state.h"
#include "kernel/integrator/shade_surface.h"
#include "kernel/light/distant.h"
#include "kernel/light/light.h"
#include "kernel/light/sample.h"
#include "kernel/integrator/shade_surface.h"
CCL_NAMESPACE_BEGIN

View File

@ -10,6 +10,8 @@
#include "kernel/film/denoising_passes.h"
#include "kernel/film/light_passes.h"
#include "kernel/light/sample.h"
#include "kernel/integrator/mnee.h"
#include "kernel/integrator/guiding.h"
@ -17,8 +19,6 @@
#include "kernel/integrator/subsurface.h"
#include "kernel/integrator/volume_stack.h"
#include "kernel/light/sample.h"
CCL_NAMESPACE_BEGIN
ccl_device_forceinline void integrate_surface_shader_setup(KernelGlobals kg,
@ -113,14 +113,16 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
ccl_global float *ccl_restrict
render_buffer)
{
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
#ifdef __LIGHT_LINKING__
if (!light_link_object_match(kg, light_link_receiver_forward(kg, state), sd->object)) {
if (!light_link_object_match(kg, light_link_receiver_forward(kg, state), sd->object) &&
!(path_flag & PATH_RAY_CAMERA))
{
return;
}
#endif
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
#ifdef __SHADOW_LINKING__
/* Indirect emission of shadow-linked emissive surfaces is done via shadow rays to dedicated
* light sources. */
@ -284,8 +286,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
const bool is_transmission = dot(ls.D, sd->N) < 0.0f;
#ifdef __MNEE__
int mnee_vertex_count = 0;
#ifdef __MNEE__
IF_KERNEL_FEATURE(MNEE)
{
if (ls.lamp != LAMP_NONE) {

View File

@ -95,9 +95,9 @@ ccl_device_inline void surface_shader_prepare_guiding(KernelGlobals kg,
bssrdf_sampling_fraction /= bsdf_bssrdf_sampling_sum;
}
/* Init guiding */
/* The the roughness because the function returns alpha.x * alpha.y. In addition alpha is squared
* again */
/* Initial guiding */
/* The roughness because the function returns `alpha.x * alpha.y`.
* In addition alpha is squared again. */
float avg_roughness = surface_shader_average_sample_weight_squared_roughness(sd);
avg_roughness = safe_sqrtf(avg_roughness);
if (!fully_opaque || avg_roughness < guiding_roughness_threshold ||

View File

@ -54,8 +54,7 @@ ccl_device float3 background_map_sample(KernelGlobals kg, float2 rand, ccl_priva
int middle = first + step;
if (kernel_data_fetch(light_background_conditional_cdf, index_v * cdf_width + middle).y <
rand.x)
{
rand.x) {
first = middle + 1;
count -= step + 1;
}

View File

@ -311,7 +311,7 @@ ccl_device_forceinline int lights_intersect_impl(KernelGlobals kg,
#ifdef __LIGHT_LINKING__
/* Light linking. */
if (!light_link_light_match(kg, receiver_forward, lamp)) {
if (!light_link_light_match(kg, receiver_forward, lamp) && !(path_flag & PATH_RAY_CAMERA)) {
continue;
}
#endif

View File

@ -29,9 +29,6 @@ ccl_device_inline bool point_light_sample(const ccl_global KernelLight *klight,
ls->Ng = -ls->D;
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
if (!in_volume_segment && ls->eval_fac == 0.0f) {
return false;
}
float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x;
@ -90,10 +87,6 @@ ccl_device_inline bool point_light_sample_from_intersection(
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
ls->pdf = invarea;
if (ls->eval_fac == 0.0f) {
return false;
}
float2 uv = map_to_sphere(ls->Ng);
ls->u = uv.x;
ls->v = uv.y;

View File

@ -13,6 +13,20 @@ CCL_NAMESPACE_BEGIN
* this single threaded on a CPU for repeatable results. */
//#define __DEBUG_CORRELATION__
/*
* The `path_rng_*()` functions below use a shuffled scrambled Sobol
* sequence to generate their samples. Sobol samplers have a property
* that is worth being aware of when choosing how to use the sample
* dimensions:
*
* 1. In general, earlier sets of dimensions are better stratified. So
* prefer e.g. x,y over y,z over z,w for the things that are most
* important to sample well.
* 2. As a rule of thumb, dimensions that are closer to each other are
* better stratified than dimensions that are far. So prefer e.g.
* x,y over x,z.
*/
ccl_device_forceinline float path_rng_1D(KernelGlobals kg,
uint rng_hash,
int sample,

View File

@ -174,6 +174,24 @@ bool Light::has_contribution(Scene *scene)
return !is_zero(effective_shader->emission_estimate);
}
bool Light::has_light_linking() const
{
if (get_light_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
bool Light::has_shadow_linking() const
{
if (get_shadow_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
/* Light Manager */
LightManager::LightManager()

View File

@ -82,6 +82,10 @@ class Light : public Node {
/* Check whether the light has contribution the scene. */
bool has_contribution(Scene *scene);
/* Check whether this light participates in light or shadow linking. */
bool has_light_linking() const;
bool has_shadow_linking() const;
friend class LightManager;
friend class LightTree;
};

View File

@ -276,6 +276,7 @@ struct LightTreeNode {
__forceinline void add(const LightTreeEmitter &emitter)
{
measure.add(emitter.measure);
light_link.add(emitter.light_set_membership);
}
__forceinline Leaf &get_leaf()

View File

@ -403,6 +403,32 @@ bool Object::usable_as_light() const
return false;
}
bool Object::has_light_linking() const
{
if (get_receiver_light_set()) {
return true;
}
if (get_light_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
bool Object::has_shadow_linking() const
{
if (get_blocker_shadow_set()) {
return true;
}
if (get_shadow_set_membership() != LIGHT_LINK_MASK_ALL) {
return true;
}
return false;
}
/* Object Manager */
ObjectManager::ObjectManager()

View File

@ -113,6 +113,11 @@ class Object : public Node {
/* Check whether this object can be used as light-emissive. */
bool usable_as_light() const;
/* Check whether the object participates in light or shadow linking, either as a receiver/blocker
* or emitter. */
bool has_light_linking() const;
bool has_shadow_linking() const;
protected:
/* Specifies the position of the object in scene->objects and
* in the device vectors. Gets set in device_update. */

View File

@ -491,10 +491,10 @@ void Scene::update_kernel_features()
else if (geom->is_pointcloud()) {
kernel_features |= KERNEL_FEATURE_POINTCLOUD;
}
if (object->get_receiver_light_set()) {
if (object->has_light_linking()) {
kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
}
if (object->get_blocker_shadow_set()) {
if (object->has_shadow_linking()) {
kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
}
}
@ -503,6 +503,13 @@ void Scene::update_kernel_features()
if (light->get_use_caustics()) {
has_caustics_light = true;
}
if (light->has_light_linking()) {
kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
}
if (light->has_shadow_linking()) {
kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
}
}
dscene.data.integrator.use_caustics = false;

View File

@ -25,6 +25,8 @@
# define HAVE_MALLOC_STATS
#elif defined(__FreeBSD__)
# include <malloc_np.h>
#elif defined(__OpenBSD__)
# undef USE_MALLOC_USABLE_SIZE
#elif defined(__APPLE__)
# include <malloc/malloc.h>
# define malloc_usable_size malloc_size

View File

@ -1836,7 +1836,8 @@ def km_graph_editor(params):
("graph.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
("graph.paste", {"type": 'V', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("flipped", True)]}),
op_menu("GRAPH_MT_slider", {"type": 'D', "value": 'PRESS'}),
op_menu("GRAPH_MT_key_smoothing", {"type": 'S', "value": 'PRESS', "alt": True}),
op_menu("GRAPH_MT_key_blending", {"type": 'D', "value": 'PRESS', "alt": True}),
("graph.previewrange_set", {"type": 'P', "value": 'PRESS', "ctrl": True, "alt": True}, None),
("graph.view_all", {"type": 'HOME', "value": 'PRESS'}, None),
("graph.view_all", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
@ -4582,7 +4583,6 @@ def km_pose(params):
("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
("pose.blend_to_neighbor", {"type": 'E', "value": 'PRESS', "shift": True, "alt": True}, None),
op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}),
*_template_object_hide_collection_from_number_keys(),
*_template_items_context_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event),
])

View File

@ -372,19 +372,6 @@ class GRAPH_MT_key_snap(Menu):
layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection")
class GRAPH_MT_slider(Menu):
bl_label = "Slider Operators"
def draw(self, _context):
layout = self.layout
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("graph.breakdown", text="Breakdown")
layout.operator("graph.blend_to_neighbor", text="Blend to Neighbor")
layout.operator("graph.blend_to_default", text="Blend to Default Value")
layout.operator("graph.ease", text="Ease")
layout.operator("graph.gaussian_smooth", text="Smooth")
class GRAPH_MT_view_pie(Menu):
bl_label = "View"
@ -526,7 +513,6 @@ classes = (
GRAPH_MT_key_snap,
GRAPH_MT_key_smoothing,
GRAPH_MT_key_blending,
GRAPH_MT_slider,
GRAPH_MT_delete,
GRAPH_MT_context_menu,
GRAPH_MT_channel_context_menu,

View File

@ -3046,10 +3046,6 @@ class VIEW3D_MT_make_links(Menu):
layout.operator("object.data_transfer")
layout.operator("object.datalayout_transfer")
layout.separator()
layout.operator_menu_enum("object.light_linking_receivers_link", "link_state")
layout.operator_menu_enum("object.light_linking_blockers_link", "link_state")
class VIEW3D_MT_brush_paint_modes(Menu):
bl_label = "Enabled Modes"

View File

@ -23,6 +23,7 @@
#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
@ -113,7 +114,7 @@ static int blf_search_by_filepath(const char *filepath)
{
for (int i = 0; i < BLF_MAX_FONT; i++) {
const FontBLF *font = global_font[i];
if (font && STREQ(font->filepath, filepath)) {
if (font && (BLI_path_cmp(font->filepath, filepath) == 0)) {
return i;
}
}
@ -249,7 +250,7 @@ void BLF_unload(const char *filepath)
continue;
}
if (STREQ(font->filepath, filepath)) {
if (BLI_path_cmp(font->filepath, filepath) == 0) {
BLI_assert(font->reference_count > 0);
font->reference_count--;

View File

@ -1436,7 +1436,9 @@ bool blf_ensure_face(FontBLF *font)
* from our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the
* same
* (#101506). Enable again later with change of font, placement, or rendering - Harley. */
if (font && font->filepath && BLI_str_endswith(font->filepath, BLF_DEFAULT_PROPORTIONAL_FONT)) {
if (font && font->filepath &&
(BLI_path_cmp(BLI_path_basename(font->filepath), BLF_DEFAULT_PROPORTIONAL_FONT) == 0))
{
font->face_flags &= ~FT_FACE_FLAG_KERNING;
}
@ -1547,7 +1549,7 @@ static FontBLF *blf_font_new_impl(const char *filepath,
if (font->filepath) {
const char *filename = BLI_path_basename(font->filepath);
for (int i = 0; i < (int)ARRAY_SIZE(static_face_details); i++) {
if (STREQ(static_face_details[i].filename, filename)) {
if (BLI_path_cmp(static_face_details[i].filename, filename) == 0) {
const struct FaceDetails *static_details = &static_face_details[i];
font->unicode_ranges[0] = static_details->coverage1;
font->unicode_ranges[1] = static_details->coverage2;

View File

@ -28,6 +28,9 @@ typedef enum LightLinkingType {
LIGHT_LINKING_BLOCKER,
} LightLinkingType;
/* Free object's light_linking if it is not needed to hold any of collections. */
void BKE_light_linking_free_if_empty(struct Object *object);
/* Get a collection of the given light linking type of the given object. */
struct Collection *BKE_light_linking_collection_get(const struct Object *object,
LightLinkingType link_type);

View File

@ -2495,7 +2495,7 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain,
}
else if (!is_in_partial_resync_hierarchy) {
/* This ID is not tagged for resync, and is part of a loop where none of the other IDs are
* tagged for resync, nothing else to to. */
* tagged for resync, nothing else to do. */
return;
}
/* This ID is not yet tagged for resync, but is part of a loop which is (partially) tagged
@ -4207,7 +4207,7 @@ void BKE_lib_override_library_main_operations_restore(Main *bmain, int *r_report
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->runtime &&
(id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RESTORE) != 0))
{
continue;

View File

@ -25,6 +25,15 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
void BKE_light_linking_free_if_empty(Object *object)
{
if (object->light_linking->receiver_collection == nullptr &&
object->light_linking->blocker_collection == nullptr)
{
MEM_SAFE_FREE(object->light_linking);
}
}
Collection *BKE_light_linking_collection_get(const Object *object,
const LightLinkingType link_type)
{
@ -108,12 +117,7 @@ void BKE_light_linking_collection_assign_only(struct Object *object,
id_us_plus(&new_collection->id);
}
/* Free if empty. */
if (object->light_linking->receiver_collection == nullptr &&
object->light_linking->blocker_collection == nullptr)
{
MEM_SAFE_FREE(object->light_linking);
}
BKE_light_linking_free_if_empty(object);
}
}
@ -182,8 +186,11 @@ void BKE_light_linking_add_receiver_to_collection(Main *bmain,
CollectionLightLinking *collection_light_linking = nullptr;
if (id_type == ID_OB) {
collection_light_linking = light_linking_collection_add_object(
bmain, collection, reinterpret_cast<Object *>(receiver));
Object *object = reinterpret_cast<Object *>(receiver);
if (!OB_TYPE_IS_GEOMETRY(object->type)) {
return;
}
collection_light_linking = light_linking_collection_add_object(bmain, collection, object);
}
else if (id_type == ID_GR) {
collection_light_linking = light_linking_collection_add_collection(
@ -240,6 +247,10 @@ void BKE_light_linking_link_receiver_to_emitter(Main *bmain,
const LightLinkingType link_type,
const eCollectionLightLinkingState link_state)
{
if (!OB_TYPE_IS_GEOMETRY(receiver->type)) {
return;
}
Collection *collection = BKE_light_linking_collection_get(emitter, link_type);
if (!collection) {

View File

@ -1444,6 +1444,16 @@ static void sculptsession_free_pbvh(Object *object)
ss->pbvh = nullptr;
}
ss->vert_to_poly_offsets = {};
ss->vert_to_poly_indices = {};
ss->pmap = {};
ss->edge_to_poly_offsets = {};
ss->edge_to_poly_indices = {};
ss->epmap = {};
ss->vert_to_edge_offsets = {};
ss->vert_to_edge_indices = {};
ss->vemap = {};
MEM_SAFE_FREE(ss->preview_vert_list);
ss->preview_vert_count = 0;

View File

@ -1418,7 +1418,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
});
},
[&]() {
/* Update all normals connected to affected faces faces, even if not explicitly tagged. */
/* Update all normals connected to affected faces, even if not explicitly tagged. */
verts_to_update.reserve(polys_to_update.size());
for (const int poly : polys_to_update) {
verts_to_update.add_multiple(corner_verts.slice(polys[poly]));

View File

@ -31,7 +31,7 @@ namespace blender::index_mask {
* - The second most-significant bit is not used for indices so that #max_segment_size itself can
* be stored in the #int16_t.
* - The maximum number of indices in a segment is 16384, which is generally enough to make the
* overhead per segment negilible when processing large index masks.
* overhead per segment negligible when processing large index masks.
* - A power of two is used for #max_segment_size, because that allows for faster construction of
* index masks for index ranges.
*/
@ -335,7 +335,7 @@ class IndexMask : private IndexMaskData {
*/
void to_bits(MutableBitSpan r_bits) const;
/**
* Set the bools at indies inthe mask to true and all others to false.
* Set the bools at indies in the mask to true and all others to false.
*/
void to_bools(MutableSpan<bool> r_bools) const;
/**

View File

@ -33,9 +33,6 @@
*
* Ideally this could be could be even closer to Python's enumerate(). We might get that in the
* future with newer C++ versions.
*
* One other important feature is the as_span method. This method returns a Span<int64_t>
* that contains the interval as individual numbers.
*/
#include <algorithm>
@ -325,22 +322,11 @@ class IndexRange {
return IndexRange(start_ + n, size_);
}
/**
* Get read-only access to a memory buffer that contains the range as actual numbers.
*/
Span<int64_t> as_span() const;
friend std::ostream &operator<<(std::ostream &stream, IndexRange range)
{
stream << "[" << range.start() << ", " << range.one_after_last() << ")";
return stream;
}
private:
static std::atomic<int64_t> s_current_array_size;
static std::atomic<int64_t *> s_current_array;
Span<int64_t> as_span_internal() const;
};
struct AlignedIndexRanges {

View File

@ -766,16 +766,4 @@ template<typename T> class MutableSpan {
}
};
/** This is defined here, because in `BLI_index_range.hh` `Span` is not yet defined. */
inline Span<int64_t> IndexRange::as_span() const
{
const int64_t min_required_size = start_ + size_;
const int64_t current_array_size = s_current_array_size.load(std::memory_order_acquire);
const int64_t *current_array = s_current_array.load(std::memory_order_acquire);
if (min_required_size <= current_array_size) {
return Span<int64_t>(current_array + start_, size_);
}
return this->as_span_internal();
}
} /* namespace blender */

View File

@ -10,40 +10,6 @@
namespace blender {
static RawVector<RawArray<int64_t, 0>> arrays;
static std::mutex current_array_mutex;
std::atomic<int64_t> IndexRange::s_current_array_size = 0;
std::atomic<int64_t *> IndexRange::s_current_array = nullptr;
Span<int64_t> IndexRange::as_span_internal() const
{
int64_t min_required_size = start_ + size_;
std::lock_guard<std::mutex> lock(current_array_mutex);
/* Double checked lock. */
if (min_required_size <= s_current_array_size) {
return Span<int64_t>(s_current_array + start_, size_);
}
/* Isolate, because a mutex is locked. */
threading::isolate_task([&]() {
int64_t new_size = std::max<int64_t>(1000, power_of_2_max_u(min_required_size));
RawArray<int64_t, 0> new_array(new_size);
threading::parallel_for(IndexRange(new_size), 4096, [&](const IndexRange range) {
for (const int64_t i : range) {
new_array[i] = i;
}
});
arrays.append(std::move(new_array));
s_current_array.store(arrays.last().data(), std::memory_order_release);
s_current_array_size.store(new_size, std::memory_order_release);
});
return Span<int64_t>(s_current_array + start_, size_);
}
AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment)
{
BLI_assert(is_power_of_2_i(alignment));

View File

@ -5,7 +5,8 @@
namespace blender::offset_indices {
OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, const int start_offset)
OffsetIndices<int> accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets,
const int start_offset)
{
int offset = start_offset;
for (const int i : counts_to_offsets.index_range().drop_back(1)) {

View File

@ -655,7 +655,7 @@ void BLI_path_normalize_unc_16(wchar_t *path_16)
void BLI_path_rel(char path[FILE_MAX], const char *basepath)
{
BLI_string_debug_size_after_nil(path, FILE_MAX);
/* A `basepath` starting with `//` will be be made relative multiple times. */
/* A `basepath` starting with `//` will be made relative multiple times. */
BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!");
const char *lslash;
@ -1095,7 +1095,7 @@ void BLI_path_to_display_name(char *display_name, int display_name_maxncpy, cons
bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
{
BLI_string_debug_size_after_nil(path, FILE_MAX);
/* A `basepath` starting with `//` will be be made absolute multiple times. */
/* A `basepath` starting with `//` will be made absolute multiple times. */
BLI_assert_msg(!BLI_path_is_rel(basepath), "The 'basepath' cannot start with '//'!");
const bool wasrelative = BLI_path_is_rel(path);

View File

@ -44,7 +44,8 @@ int BLI_windows_get_executable_dir(char *str)
return 1;
}
bool BLI_windows_is_store_install(void) {
bool BLI_windows_is_store_install(void)
{
char install_dir[FILE_MAXDIR];
BLI_windows_get_executable_dir(install_dir);
return (BLI_strcasestr(install_dir, "\\WindowsApps\\") != NULL);

View File

@ -219,17 +219,6 @@ TEST(index_range, TakeBackLargeN)
EXPECT_EQ(slice.size(), 4);
}
TEST(index_range, AsSpan)
{
IndexRange range = IndexRange(4, 6);
Span<int64_t> span = range.as_span();
EXPECT_EQ(span.size(), 6);
EXPECT_EQ(span[0], 4);
EXPECT_EQ(span[1], 5);
EXPECT_EQ(span[2], 6);
EXPECT_EQ(span[3], 7);
}
TEST(index_range, constexpr_)
{
constexpr IndexRange range = IndexRange(1, 1);

View File

@ -90,7 +90,7 @@ TEST(string, StrCopyUTF8_TruncateEncoding)
TEST(string, StrCopyUTF8_TerminateEncodingEarly)
{
/* A UTF8 sequence that has a null byte before the sequence ends.
* Ensure the the UTF8 sequence does not step over the null byte. */
* Ensure the UTF8 sequence does not step over the null byte. */
#define STRNCPY_UTF8_TERMINATE_EARLY(byte_size, ...) \
{ \
char src[] = {__VA_ARGS__, 0}; \

View File

@ -3984,7 +3984,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
/* In case the current scene is a liboverride, while the ID pointer itself remains valid,
* above update of liboverrides will have completely invalidated its old content, so the
* current viewlayer needs to be searched for again. */
* current view-layer needs to be searched for again. */
if (bfd->cur_view_layer != nullptr) {
bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str());
}

View File

@ -106,7 +106,7 @@ struct Object *DEG_get_original_object(struct Object *object);
struct ID *DEG_get_original_id(struct ID *id);
/**
* Check whether given ID is an original,
* Check whether given ID is an original.
*
* Original IDs are considered all the IDs which are not covered by copy-on-write system and are
* not out-of-main localized data-blocks.

View File

@ -61,6 +61,13 @@ template<class T> static inline const T *get_original(const T *id)
return reinterpret_cast<T *>(DEG_get_original_id(const_cast<ID *>(&id->id)));
}
/* Check whether the ID is suitable to be an input of the dependency graph. */
/* TODO(sergey): Move the function and check to a more generic place. */
bool is_valid_input_id(const ID &id)
{
return (id.tag & LIB_TAG_LOCALIZED) || DEG_is_original_id(&id);
}
} // namespace
namespace blender::deg::light_linking {
@ -153,7 +160,7 @@ void EmitterDataMap::clear()
EmitterData *EmitterDataMap::ensure_data_if_possible(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
const Collection *collection = get_collection(emitter);
BLI_assert(collection);
@ -209,7 +216,7 @@ const EmitterData *EmitterDataMap::get_data(const Object &emitter) const
bool EmitterDataMap::can_skip_emitter(const Object &emitter) const
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
const Collection *collection = get_collection(emitter);
@ -249,7 +256,7 @@ void LinkingData::link_object(const EmitterData &emitter_data,
LightSet &LinkingData::ensure_light_set_for(const Object &object)
{
BLI_assert(DEG_is_original_id(&object.id));
BLI_assert(is_valid_input_id(object.id));
return light_linked_sets_.lookup_or_add_as(&object);
}
@ -363,7 +370,7 @@ void Cache::clear()
void Cache::add_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
add_light_linking_emitter(scene, emitter);
add_shadow_linking_emitter(scene, emitter);
@ -371,7 +378,7 @@ void Cache::add_emitter(const Scene &scene, const Object &emitter)
void Cache::add_light_linking_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
if (light_emitter_data_map_.can_skip_emitter(emitter)) {
return;
@ -390,7 +397,7 @@ void Cache::add_light_linking_emitter(const Scene &scene, const Object &emitter)
void Cache::add_shadow_linking_emitter(const Scene &scene, const Object &emitter)
{
BLI_assert(DEG_is_original_id(&emitter.id));
BLI_assert(is_valid_input_id(emitter.id));
if (shadow_emitter_data_map_.can_skip_emitter(emitter)) {
return;
@ -411,7 +418,7 @@ void Cache::add_receiver_object(const EmitterData &emitter_data,
const CollectionLightLinking &collection_light_linking,
const Object &receiver)
{
BLI_assert(DEG_is_original_id(&receiver.id));
BLI_assert(is_valid_input_id(receiver.id));
if (!can_link_to_emitter(receiver)) {
return;
@ -425,7 +432,7 @@ void Cache::add_blocker_object(const EmitterData &emitter_data,
const CollectionLightLinking &collection_light_linking,
const Object &blocker)
{
BLI_assert(DEG_is_original_id(&blocker.id));
BLI_assert(is_valid_input_id(blocker.id));
if (!can_link_to_emitter(blocker)) {
return;
@ -483,11 +490,18 @@ void Cache::eval_runtime_data(Object &object_eval) const
runtime.shadow_set_membership = EmitterSetMembership::SET_MEMBERSHIP_ALL;
}
const bool need_runtime = (memcmp(&runtime, &runtime_no_links, sizeof(runtime)) != 0);
/* Assign, allocating light linking on demand if needed. */
if (object_eval.light_linking) {
object_eval.light_linking->runtime = runtime;
if (!need_runtime) {
/* Note that this will only remove lazily allocated light_linking on the evaluated object,
* as an empty light_linking is not allowed on the original object. */
BKE_light_linking_free_if_empty(&object_eval);
}
}
else if (memcmp(&runtime, &runtime_no_links, sizeof(runtime)) != 0) {
else if (need_runtime) {
object_eval.light_linking = MEM_cnew<LightLinking>(__func__);
object_eval.light_linking->runtime = runtime;
}

View File

@ -73,7 +73,7 @@ class EmitterData {
static constexpr int MAX_COLLECTION_ID = 63;
/* Mask of a light linking collection this emitter uses in its configuration.
* A single bit is set in this bitfield which corresponds to an identifier of a light linking
* A single bit is set in this bit-field which corresponds to an identifier of a light linking
* collection in the scene. */
uint64_t collection_mask = 0;
@ -121,7 +121,7 @@ class EmitterDataMap {
}
private:
/* Get linked collection depending on whether this is emitter information os for light or shadow
/* Get linked collection depending on whether this is emitter information for light or shadow
* linking. */
/* TODO(sergey): Check whether template specialization is preferred here. */
inline const Collection *get_collection(const Object &emitter) const

View File

@ -32,9 +32,6 @@ void ObjectRuntimeBackup::init_from_object(Object *object)
if (object->light_linking) {
light_linking_runtime = object->light_linking->runtime;
}
else {
memset(&light_linking_runtime, 0, sizeof(light_linking_runtime));
}
BKE_object_runtime_reset(object);
/* Keep bbox (for now at least). */
object->runtime.bb = runtime.bb;
@ -128,8 +125,13 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
}
}
if (object->light_linking) {
object->light_linking->runtime = light_linking_runtime;
if (light_linking_runtime) {
/* Lazily allocate light linking on the evaluated object for the cases when the object is only
* a receiver or a blocker and does not need its own LightLinking on the original object. */
if (!object->light_linking) {
object->light_linking = MEM_cnew<LightLinking>(__func__);
}
object->light_linking->runtime = *light_linking_runtime;
}
object->base_flag = base_flag;

View File

@ -12,6 +12,7 @@
#include "BLI_session_uuid.h"
#include "intern/depsgraph_type.h"
#include "intern/eval/deg_eval_runtime_backup_modifier.h"
#include "intern/eval/deg_eval_runtime_backup_pose.h"
@ -39,7 +40,7 @@ class ObjectRuntimeBackup {
void restore_pose_channel_runtime_data(Object *object);
Object_Runtime runtime;
LightLinkingRuntime light_linking_runtime;
optional<LightLinkingRuntime> light_linking_runtime;
short base_flag;
unsigned short base_local_view_bits;
Map<SessionUUID, ModifierDataBackup> modifier_runtime_data;

View File

@ -1213,7 +1213,7 @@ void EEVEE_material_transparent_output_init(EEVEE_Data *vedata)
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->transparent_accum)});
{
/* This pass Accumulate 1 sample of the transparent pass into the the transparent
/* This pass Accumulate 1 sample of the transparent pass into the transparent
* accumulation buffer. */
DRW_PASS_CREATE(psl->transparent_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_renderpasses_accumulate_sh_get(),

View File

@ -300,7 +300,7 @@ GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void)
{
if (e_data.probe_filter_visibility_sh == nullptr) {
e_data.probe_filter_visibility_sh = DRW_shader_create_from_info_name(
"eevee_legacy_probe_filter_visiblity");
"eevee_legacy_probe_filter_visibility");
}
return e_data.probe_filter_visibility_sh;
}

View File

@ -121,7 +121,7 @@ GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_diffuse_hl2)
.auto_resource_location(true);
/* EEVEE_shaders_probe_filter_visibility_sh_get */
GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_visiblity)
GPU_SHADER_CREATE_INFO(eevee_legacy_probe_filter_visibility)
.define("IRRADIANCE_HL2")
.additional_info("eevee_legacy_irradiance_lib")
.additional_info("draw_fullscreen")

View File

@ -203,7 +203,7 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
matpass.sub_pass = nullptr;
}
else {
ShaderKey shader_key(matpass.gpumat, geometry_type, pipeline_type);
ShaderKey shader_key(matpass.gpumat, geometry_type, pipeline_type, blender_mat->blend_flag);
PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
/* First time encountering this shader. Create a sub that will contain materials using it. */

View File

@ -108,7 +108,7 @@ static inline eMaterialGeometry to_material_geometry(const Object *ob)
/** Unique key to identify each material in the hash-map. */
struct MaterialKey {
Material *mat;
::Material *mat;
uint64_t options;
MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline surface_pipeline)
@ -145,10 +145,14 @@ struct ShaderKey {
GPUShader *shader;
uint64_t options;
ShaderKey(GPUMaterial *gpumat, eMaterialGeometry geometry, eMaterialPipeline pipeline)
ShaderKey(GPUMaterial *gpumat,
eMaterialGeometry geometry,
eMaterialPipeline pipeline,
char blend_flags)
{
shader = GPU_material_get_shader(gpumat);
options = shader_uuid_from_material_type(pipeline, geometry);
options = blend_flags;
options = (options << 6u) | shader_uuid_from_material_type(pipeline, geometry);
options = (options << 16u) | shader_closure_bits_from_flag(gpumat);
}

View File

@ -12,13 +12,9 @@ namespace blender::draw::overlay {
class Background {
private:
const SelectionType selection_type_;
PassSimple bg_ps_ = {"Background"};
public:
Background(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state)
{
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;

View File

@ -17,8 +17,6 @@ namespace blender::draw::overlay {
class Grid {
private:
const SelectionType selection_type_;
UniformBuffer<OVERLAY_GridData> data_;
PassSimple grid_ps_ = {"grid_ps_"};
@ -32,8 +30,6 @@ class Grid {
bool enabled_ = false;
public:
Grid(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state, const View &view)
{
this->update_ubo(state, view);

View File

@ -33,11 +33,11 @@ class Instance {
State state;
/** Overlay types. */
Background background = {selection_type_};
Prepass prepass = {selection_type_};
Background background;
Prepass prepass;
Metaballs metaballs = {selection_type_};
Empties empties = {selection_type_};
Grid grid = {selection_type_};
Grid grid;
Instance(const SelectionType selection_type) : selection_type_(selection_type){};

View File

@ -15,14 +15,10 @@ namespace blender::draw::overlay {
class Prepass {
private:
const SelectionType selection_type_;
PassMain prepass_ps_ = {"prepass"};
PassMain prepass_in_front_ps_ = {"prepass_in_front"};
public:
Prepass(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync(Resources &res, const State &state)
{
auto init_pass = [&](PassMain &pass) {

View File

@ -15,8 +15,9 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(const char *create_info_
/* TODO: This is what it should be like with all variations defined with create infos. */
// std::string create_info_name = base_create_info;
// create_info_name += SelectEngineT::shader_suffix;
// create_info_name += ClippingEnabled ? "_clipped" : "";
// create_info_name += clipping_enabled_ ? "_clipped" : "";
// this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str());
UNUSED_VARS(clipping_enabled_);
/* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(

View File

@ -1,4 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file

View File

@ -122,10 +122,11 @@ void DofPass::init(const SceneState &scene_state)
int2 half_res = scene_state.resolution / 2;
half_res = {max_ii(half_res.x, 1), max_ii(half_res.y, 1)};
source_tx_.ensure_2d(GPU_RGBA16F, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3);
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW;
source_tx_.ensure_2d(GPU_RGBA16F, half_res, usage, nullptr, 3);
source_tx_.ensure_mip_views();
source_tx_.filter_mode(true);
coc_halfres_tx_.ensure_2d(GPU_RG8, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3);
coc_halfres_tx_.ensure_2d(GPU_RG8, half_res, usage, nullptr, 3);
coc_halfres_tx_.ensure_mip_views();
coc_halfres_tx_.filter_mode(true);

View File

@ -410,40 +410,41 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi
const int cur_subdiv = tgpi->type == GP_STROKE_BOX ? tgpi->tot_edges - 1 : tgpi->tot_edges - 2;
if (tgpi->type == GP_STROKE_LINE) {
BLI_strncpy(msg_str,
TIP_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to "
"adjust subdivision number, Shift to align, Alt to center, E: extrude"),
UI_MAX_DRAW_STR);
BLI_strncpy(
msg_str,
TIP_("Line: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- to "
"adjust subdivision number, Shift to align, Alt to center, E: extrude, G: grab"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_POLYLINE) {
BLI_strncpy(msg_str,
TIP_("Polyline: ESC to cancel, LMB to set, Enter/MMB to confirm, WHEEL/+- to "
"adjust subdivision number, Shift to align"),
"adjust subdivision number, Shift to align, G: grab"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_BOX) {
BLI_strncpy(msg_str,
TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- "
"to adjust subdivision number, Shift to square, Alt to center"),
"to adjust subdivision number, Shift to square, Alt to center, G: grab"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_CIRCLE) {
BLI_strncpy(msg_str,
TIP_("Circle: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
"number, Shift to square, Alt to center"),
"number, Shift to square, Alt to center, G: grab"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_ARC) {
BLI_strncpy(
msg_str,
TIP_("Arc: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision number, "
"Shift to square, Alt to center, M: Flip, E: extrude"),
"Shift to square, Alt to center, M: Flip, E: extrude, G: grab"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_CURVE) {
BLI_strncpy(msg_str,
TIP_("Curve: ESC to cancel, Enter/MMB to confirm, WHEEL/+- to adjust subdivision "
"number, Shift to square, Alt to center, E: extrude"),
"number, Shift to square, Alt to center, E: extrude, G: grab"),
UI_MAX_DRAW_STR);
}
@ -1618,7 +1619,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
copy_v2fl_v2i(tgpi->mval, event->mval);
if (tgpi->flag == IN_MOVE) {
bool is_mouse_event = true;
switch (event->type) {
case MOUSEMOVE: {
gpencil_primitive_move(tgpi, false);
@ -1639,8 +1640,14 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
break;
}
default: {
is_mouse_event = false; /* Prevent overwriting `tgpi->mvalo`. */
break;
}
}
if (is_mouse_event) {
copy_v2_v2(tgpi->mvalo, tgpi->mval);
}
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL;
}

View File

@ -373,9 +373,7 @@ ScrArea *ED_screen_temp_space_open(struct bContext *C,
bool dialog);
void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_footer_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
void ED_screens_navigation_bar_tools_menu_create(struct bContext *C,
struct uiLayout *layout,
void *arg);
void ED_screens_region_flip_menu_create(struct bContext *C, struct uiLayout *layout, void *arg);
/**
* \return true if any active area requires to see in 3D.
*/

View File

@ -1245,7 +1245,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
uiItemMenuF(layout,
IFACE_("Navigation Bar"),
ICON_NONE,
ED_screens_navigation_bar_tools_menu_create,
ED_screens_region_flip_menu_create,
nullptr);
}
else if (region->regiontype == RGN_TYPE_FOOTER) {

View File

@ -3631,6 +3631,26 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
/**
* Return the jump type used for cursor motion & back-space/delete actions.
*/
static eStrCursorJumpType ui_textedit_jump_type_from_event(const wmEvent *event)
{
#ifdef __APPLE__
if (event->modifier & KM_OSKEY) {
return STRCUR_JUMP_ALL;
}
if (event->modifier & KM_ALT) {
return STRCUR_JUMP_DELIM;
}
#else
if (event->modifier & KM_CTRL) {
return STRCUR_JUMP_DELIM;
}
#endif
return STRCUR_JUMP_NONE;
}
static void ui_do_but_textedit(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
@ -3777,17 +3797,10 @@ static void ui_do_but_textedit(
break;
case EVT_RIGHTARROWKEY:
case EVT_LEFTARROWKEY: {
eStrCursorJumpDirection direction = (event->type == EVT_RIGHTARROWKEY) ? STRCUR_DIR_NEXT :
STRCUR_DIR_PREV;
#ifdef __APPLE__
eStrCursorJumpType jump = (event->modifier & KM_OSKEY) ?
STRCUR_JUMP_ALL :
((event->modifier & KM_ALT) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE);
#else
eStrCursorJumpType jump = (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE;
#endif
const eStrCursorJumpDirection direction = (event->type == EVT_RIGHTARROWKEY) ?
STRCUR_DIR_NEXT :
STRCUR_DIR_PREV;
const eStrCursorJumpType jump = ui_textedit_jump_type_from_event(event);
ui_textedit_move(but, data, direction, event->modifier & KM_SHIFT, jump);
retval = WM_UI_HANDLER_BREAK;
break;
@ -3833,17 +3846,9 @@ static void ui_do_but_textedit(
break;
case EVT_DELKEY:
case EVT_BACKSPACEKEY: {
eStrCursorJumpDirection direction = (event->type == EVT_DELKEY) ? STRCUR_DIR_NEXT :
STRCUR_DIR_PREV;
#ifdef __APPLE__
eStrCursorJumpType jump = (event->modifier & KM_OSKEY) ?
STRCUR_JUMP_ALL :
((event->modifier & KM_ALT) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE);
#else
eStrCursorJumpType jump = (event->modifier & KM_CTRL) ? STRCUR_JUMP_DELIM :
STRCUR_JUMP_NONE;
#endif
const eStrCursorJumpDirection direction = (event->type == EVT_DELKEY) ? STRCUR_DIR_NEXT :
STRCUR_DIR_PREV;
const eStrCursorJumpType jump = ui_textedit_jump_type_from_event(event);
changed = ui_textedit_delete(but, data, direction, jump);
retval = WM_UI_HANDLER_BREAK;
break;

View File

@ -4297,10 +4297,6 @@ static void screen_area_menu_items(ScrArea *area, uiLayout *layout)
void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{
PointerRNA ptr;
RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
@ -4322,12 +4318,9 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
"SCREEN_OT_header_toggle_menus");
}
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (!ELEM(area->spacetype, SPACE_TOPBAR)) {
uiItemS(layout);
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
ED_screens_region_flip_menu_create(C, layout, NULL);
uiItemS(layout);
screen_area_menu_items(area, layout);
}
@ -4336,31 +4329,26 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_TOP) ?
IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
{
PointerRNA ptr;
RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, area->spacedata.first, &ptr);
uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE);
}
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
ED_screens_region_flip_menu_create(C, layout, NULL);
uiItemS(layout);
screen_area_menu_items(area, layout);
}
void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
void ED_screens_region_flip_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
const ARegion *region = CTX_wm_region(C);
const char *but_flip_str = (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_LEFT) ?
IFACE_("Flip to Right") :
IFACE_("Flip to Left");
const short region_alignment = RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
const char *but_flip_str = region_alignment == RGN_ALIGN_LEFT ? IFACE_("Flip to Right") :
region_alignment == RGN_ALIGN_RIGHT ? IFACE_("Flip to Left") :
region_alignment == RGN_ALIGN_BOTTOM ? IFACE_("Flip to Top") :
IFACE_("Flip to Bottom");
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
@ -4411,7 +4399,7 @@ static int screen_context_menu_invoke(bContext *C,
else if (region->regiontype == RGN_TYPE_NAV_BAR) {
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
ED_screens_region_flip_menu_create(C, layout, NULL);
UI_popup_menu_end(C, pup);
}
}

View File

@ -1180,7 +1180,7 @@ static void vertex_paint_init_session(Depsgraph *depsgraph,
BKE_sculpt_toolsettings_data_ensure(scene);
BLI_assert(ob->sculpt == nullptr);
ob->sculpt = (SculptSession *)MEM_callocN(sizeof(SculptSession), "sculpt session");
ob->sculpt = MEM_new<SculptSession>(__func__);
ob->sculpt->mode_type = object_mode;
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true);

View File

@ -169,7 +169,7 @@ static void SCULPT_dynamic_topology_disable_ex(
CustomData_free_layer_named(&me->pdata, ".sculpt_face_set", me->totpoly);
me->face_sets_color_default = 1;
/* Sync the visibility to vertices manually as the pmap is still not initialized. */
/* Sync the visibility to vertices manually as the `pmap` is still not initialized. */
bool *hide_vert = (bool *)CustomData_get_layer_named_for_write(
&me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert);
if (hide_vert != nullptr) {

View File

@ -237,8 +237,7 @@ static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
static bool associate_blend_poll(bContext *C)
{
#ifdef WIN32
if (BLI_windows_is_store_install())
{
if (BLI_windows_is_store_install()) {
CTX_wm_operator_poll_msg_set(C, "Not available for Microsoft Store installations");
return false;
}
@ -253,7 +252,8 @@ static int associate_blend_exec(bContext *UNUSED(C), wmOperator *op)
{
#ifdef WIN32
if (BLI_windows_is_store_install()) {
BKE_report(op->reports, RPT_ERROR, "Registration not possible from Microsoft Store installations");
BKE_report(
op->reports, RPT_ERROR, "Registration not possible from Microsoft Store installations");
return OPERATOR_CANCELLED;
}

View File

@ -768,6 +768,7 @@ void applyMouseInput(struct TransInfo *t,
const int mval[2],
float output[3]);
void transform_input_update(TransInfo *t, const float fac);
void transform_input_virtual_mval_reset(TransInfo *t);
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);

View File

@ -494,4 +494,18 @@ void transform_input_update(TransInfo *t, const float fac)
}
}
void transform_input_virtual_mval_reset(TransInfo *t)
{
MouseInput *mi = &t->mouse;
if (ELEM(mi->apply, InputAngle, InputAngleSpring)) {
struct InputAngle_Data *data = mi->data;
data->angle = 0.0;
data->mval_prev[0] = mi->imval[0];
data->mval_prev[1] = mi->imval[1];
}
else {
memset(&mi->virtual_mval, 0, sizeof(mi->virtual_mval));
}
}
/** \} */

View File

@ -420,28 +420,42 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
t->context = NULL;
/* Allow navigation while transforming. */
if (t->vod && (exit_code & OPERATOR_PASS_THROUGH) && ED_view3d_navigation_do(C, t->vod, event)) {
if (t->vod && (exit_code & OPERATOR_PASS_THROUGH)) {
RegionView3D *rv3d = t->region->regiondata;
if (rv3d->rflag & RV3D_NAVIGATING) {
/* Do not update transform while navigating. This can be distracting. */
return OPERATOR_RUNNING_MODAL;
const bool is_navigating = (rv3d->rflag & RV3D_NAVIGATING) != 0;
if (ED_view3d_navigation_do(C, t->vod, event)) {
if (!is_navigating) {
/* Navigation has started. */
if (t->modifiers & MOD_PRECISION) {
/* WORKAROUND: Remove precision modification, it may have be unintentionally enabled. */
t->modifiers &= ~MOD_PRECISION;
t->mouse.precision = false;
transform_input_virtual_mval_reset(t);
}
}
if (rv3d->rflag & RV3D_NAVIGATING) {
/* Navigation is running. */
/* Do not update transform while navigating. This can be distracting. */
return OPERATOR_RUNNING_MODAL;
}
{
/* Navigation has ended. */
/* Make sure `t->mval` is up to date before calling #transformViewUpdate. */
copy_v2_v2_int(t->mval, event->mval);
/* Call before #applyMouseInput. */
tranformViewUpdate(t);
/* Mouse input is outdated. */
applyMouseInput(t, &t->mouse, t->mval, t->values);
t->redraw |= TREDRAW_HARD;
}
}
if (t->modifiers & MOD_PRECISION) {
/* Remove Precision modifier, it may have be unintentionally enabled. */
t->modifiers &= ~MOD_PRECISION;
t->mouse.precision = 0;
}
/* Make sure `t->mval` is up to date before calling #transformViewUpdate. */
copy_v2_v2_int(t->mval, event->mval);
/* Call before #applyMouseInput. */
tranformViewUpdate(t);
/* Mouse input is outdated. */
applyMouseInput(t, &t->mouse, t->mval, t->values);
t->redraw |= TREDRAW_HARD;
}
transformApply(C, t);

View File

@ -413,7 +413,8 @@ void split_edges(Mesh &mesh,
});
/* Used for transferring attributes. */
Vector<int> new_to_old_edges_map(IndexRange(new_edges.size()).as_span());
Vector<int> new_to_old_edges_map(new_edges.size());
std::iota(new_to_old_edges_map.begin(), new_to_old_edges_map.end(), 0);
/* Step 1: Split the edges. */

View File

@ -483,16 +483,26 @@ void GPUCodegen::generate_library()
GPUCodegenCreateInfo &info = *create_info;
void *value;
/* Iterate over libraries. We need to keep this struct intact in case
* it is required for the optimization pass. */
blender::Vector<std::string> source_files;
/* Iterate over libraries. We need to keep this struct intact in case it is required for the
* optimization pass. The first pass just collects the keys from the GSET, given items in a GSET
* are unordered this can cause order differences between invocations, so we collect the keys
* first, and sort them before doing actual work, to guarantee stable behavior while still
* having cheap insertions into the GSET */
GHashIterator *ihash = BLI_ghashIterator_new((GHash *)graph.used_libraries);
while (!BLI_ghashIterator_done(ihash)) {
value = BLI_ghashIterator_getKey(ihash);
auto deps = gpu_shader_dependency_get_resolved_source((const char *)value);
info.dependencies_generated.extend_non_duplicates(deps);
source_files.append((const char *)value);
BLI_ghashIterator_step(ihash);
}
BLI_ghashIterator_free(ihash);
std::sort(source_files.begin(), source_files.end());
for (auto &key : source_files) {
auto deps = gpu_shader_dependency_get_resolved_source(key.c_str());
info.dependencies_generated.extend_non_duplicates(deps);
}
}
void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node)

View File

@ -1,3 +1,5 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "GPU_framebuffer.h"

View File

@ -149,10 +149,12 @@ struct ImBuf *IMB_allocFromBuffer(const uint8_t *byte_buffer,
unsigned int h,
unsigned int channels);
/* Assign the content of the corresponding buffer using an implicitly shareable data pointer.
/**
* Assign the content of the corresponding buffer using an implicitly shareable data pointer.
*
* NOTE: Does not modify the the topology (width, height, number of channels) or the mipmaps in any
* way. */
* \note Does not modify the topology (width, height, number of channels)
* or the mipmaps in any way.
*/
void IMB_assign_shared_byte_buffer(struct ImBuf *ibuf,
uint8_t *buffer_data,
const ImplicitSharingInfoHandle *implicit_sharing);
@ -163,24 +165,30 @@ void IMB_assign_shared_float_z_buffer(struct ImBuf *ibuf,
float *buffer_data,
const ImplicitSharingInfoHandle *implicit_sharing);
/* Assign the content of the corresponding buffer with the given data and ownership.
/**
* Assign the content of the corresponding buffer with the given data and ownership.
* The current content of the buffer is released corresponding to its ownership configuration.
*
* NOTE: Does not modify the the topology (width, height, number of channels) or the mipmaps in any
* way. */
* \note Does not modify the topology (width, height, number of channels)
* or the mipmaps in any way.
*/
void IMB_assign_byte_buffer(struct ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership);
void IMB_assign_float_buffer(struct ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership);
void IMB_assign_z_buffer(struct ImBuf *ibuf, int *buffer_data, ImBufOwnership ownership);
void IMB_assign_float_z_buffer(struct ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership);
/* Make corresponding buffers available for modification.
* Is achieved by ensuring that the given ImBuf is the only owner of the underlying buffer data. */
/**
* Make corresponding buffers available for modification.
* Is achieved by ensuring that the given ImBuf is the only owner of the underlying buffer data.
*/
void IMB_make_writable_byte_buffer(struct ImBuf *ibuf);
void IMB_make_writable_float_buffer(struct ImBuf *ibuf);
/* Steal the buffer data pointer: the ImBuf is no longer an owner of this data.
* NOTE: If the ImBuf does not own the data the behavior is undefined.
* NOTE: Stealing encoded buffer resets the encoded size. */
/**
* Steal the buffer data pointer: the ImBuf is no longer an owner of this data.
* \note If the ImBuf does not own the data the behavior is undefined.
* \note Stealing encoded buffer resets the encoded size.
*/
uint8_t *IMB_steal_byte_buffer(struct ImBuf *ibuf);
float *IMB_steal_float_buffer(struct ImBuf *ibuf);
uint8_t *IMB_steal_encoded_buffer(struct ImBuf *ibuf);

View File

@ -279,8 +279,8 @@ typedef struct LightLinkingRuntime {
/* For blocker objects: the index of the light set from which this object casts shadow from.
*
*If there is no shadow shadow in the scene or the blocker is not linked to any emitter this is
*assigned zero. */
* If there is no shadow in the scene or the blocker is not linked to any emitter this is
* assigned zero. */
uint8_t blocker_shadow_set;
uint8_t _pad[6];
@ -289,7 +289,7 @@ typedef struct LightLinkingRuntime {
typedef struct LightLinking {
/* Collections which contains objects (possibly via nested collection indirection) which defines
* the light linking relation: such as whether objects are included or excluded from being lit by
* this emitter (receiver_collection), oe whether they block light from this emitter
* this emitter (receiver_collection), or whether they block light from this emitter
* (blocker_collection).
*
* If the collection is a null pointer then all objects from the current scene are receiving

View File

@ -9,6 +9,7 @@
#define __RNA_TYPES_H__
#include "../blenlib/BLI_sys_types.h"
#include "../blenlib/BLI_utildefines.h"
#ifdef __cplusplus
extern "C" {
@ -81,6 +82,7 @@ typedef enum PropertyUnit {
PROP_UNIT_POWER = (11 << 16), /* W */
PROP_UNIT_TEMPERATURE = (12 << 16), /* C */
} PropertyUnit;
ENUM_OPERATORS(PropertyUnit, PROP_UNIT_TEMPERATURE)
/**
* Use values besides #PROP_SCALE_LINEAR
@ -367,6 +369,7 @@ typedef enum ParameterFlag {
*/
PARM_PYFUNC_OPTIONAL = (1 << 3),
} ParameterFlag;
ENUM_OPERATORS(ParameterFlag, PARM_PYFUNC_OPTIONAL)
struct CollectionPropertyIterator;
struct Link;

View File

@ -1798,7 +1798,7 @@ static char *rna_def_property_lookup_string_func(FILE *f,
fprintf(f, " }\n");
fprintf(f, " }\n");
fprintf(f, " else {\n");
fprintf(f, " name = MEM_mallocN(namelen+1, \"name string\");\n");
fprintf(f, " name = (char *)MEM_mallocN(namelen+1, \"name string\");\n");
fprintf(f,
" %s_%s_get(&iter.ptr, name);\n",
item_name_base->identifier,
@ -1916,7 +1916,8 @@ static void rna_set_raw_offset(FILE *f, StructRNA *srna, PropertyRNA *prop)
{
PropertyDefRNA *dp = rna_find_struct_property_def(srna, prop);
fprintf(f, "\toffsetof(%s, %s), %d", dp->dnastructname, dp->dnaname, prop->rawtype);
fprintf(
f, "\toffsetof(%s, %s), (RawPropertyType)%d", dp->dnastructname, dp->dnaname, prop->rawtype);
}
static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
@ -3506,7 +3507,7 @@ static void rna_generate_internal_property_prototypes(BlenderRNA *UNUSED(brna),
for (prop = srna->cont.properties.first; prop; prop = prop->next) {
fprintf(f,
"%s rna_%s_%s;\n",
"extern %s rna_%s_%s;\n",
rna_property_structname(prop->type),
srna->identifier,
prop->identifier);
@ -4068,7 +4069,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_print_c_string(f, prop->translation_context);
fprintf(f, ",\n");
fprintf(f,
"\t%s, %s | %s, %s, %u, {%u, %u, %u}, %u,\n",
"\t%s, (PropertySubType)((int)%s | (int)%s), %s, %u, {%u, %u, %u}, %u,\n",
RNA_property_typename(prop->type),
rna_property_subtypename(prop->subtype),
rna_property_subtype_unit(prop->subtype),
@ -4093,7 +4094,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_set_raw_offset(f, srna, prop);
}
else {
fprintf(f, "\t0, -1");
fprintf(f, "\t0, PROP_RAW_UNSET");
}
/* our own type - collections/arrays only */

View File

@ -449,7 +449,7 @@ static void rna_CollectionLightLinking_update(Main *bmain, Scene *UNUSED(scene),
{
/* The light linking collection comes from the collection. It does not have shading component,
* but is collected to objects via hierarchy component. Tagging its hierarchy for update will
* lead the the objects which use the collection to update its shading. */
* lead the objects which use the collection to update its shading. */
DEG_id_tag_update(ptr->owner_id, ID_RECALC_HIERARCHY);
/* Tag relations for update so that an updated state of light sets is calculated. */

View File

@ -7037,6 +7037,11 @@ static void rna_def_modifier_nodes(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, 0, "rna_NodesModifier_node_group_update");
prop = RNA_def_property(srna, "simulation_bake_directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_ui_text(
prop, "Simulation Bake Directory", "Location on disk where the bake data is stored");
RNA_def_property_update(prop, 0, NULL);
RNA_define_lib_overridable(false);
}

View File

@ -5908,7 +5908,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
# endif
# ifdef WITH_OPENJPEG
/* Jpeg 2000 */
/* JPEG 2000 */
prop = RNA_def_property(srna, "use_jpeg2k_ycc", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_YCC);
RNA_def_property_ui_text(

View File

@ -653,12 +653,17 @@ static void correctivesmooth_modifier_do(ModifierData *md,
}
else {
int me_numVerts;
rest_coords = em ? BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts) :
BKE_mesh_vert_coords_alloc(static_cast<const Mesh *>(ob->data),
&me_numVerts);
if (em) {
rest_coords = BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts);
is_rest_coords_alloc = true;
}
else {
const Mesh *me = static_cast<const Mesh *>(ob->data);
rest_coords = BKE_mesh_vert_positions(me);
me_numVerts = me->totvert;
}
BLI_assert((uint)me_numVerts == verts_num);
is_rest_coords_alloc = true;
}
#ifdef DEBUG_TIME

View File

@ -1922,6 +1922,8 @@ static void internal_dependencies_panel_draw(const bContext * /*C*/, Panel *pane
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr);
NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data);
uiItemR(layout, ptr, "simulation_bake_directory", 0, "Bake", ICON_NONE);
geo_log::GeoTreeLog *tree_log = get_root_tree_log(*nmd);
if (tree_log == nullptr) {
return;

View File

@ -41,28 +41,30 @@ extern "C" {
/* External Engine */
/** #RenderEngineType.flag */
#define RE_INTERNAL 1
/* #define RE_FLAG_DEPRECATED 2 */
#define RE_USE_PREVIEW 4
#define RE_USE_POSTPROCESS 8
#define RE_USE_EEVEE_VIEWPORT 16
/* #define RE_USE_SAVE_BUFFERS_DEPRECATED 32 */
#define RE_USE_SHADING_NODES_CUSTOM 64
#define RE_USE_SPHERICAL_STEREO 128
#define RE_USE_STEREO_VIEWPORT 256
#define RE_USE_GPU_CONTEXT 512
#define RE_USE_CUSTOM_FREESTYLE 1024
#define RE_USE_NO_IMAGE_SAVE 2048
#define RE_USE_ALEMBIC_PROCEDURAL 4096
enum RenderEngineTypeFlag {
RE_INTERNAL = (1 << 0),
RE_USE_PREVIEW = (1 << 1),
RE_USE_POSTPROCESS = (1 << 2),
RE_USE_EEVEE_VIEWPORT = (1 << 3),
RE_USE_SHADING_NODES_CUSTOM = (1 << 4),
RE_USE_SPHERICAL_STEREO = (1 << 5),
RE_USE_STEREO_VIEWPORT = (1 << 6),
RE_USE_GPU_CONTEXT = (1 << 7),
RE_USE_CUSTOM_FREESTYLE = (1 << 8),
RE_USE_NO_IMAGE_SAVE = (1 << 9),
RE_USE_ALEMBIC_PROCEDURAL = (1 << 10),
};
/** #RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
#define RE_ENGINE_PREVIEW 2
#define RE_ENGINE_DO_DRAW 4
#define RE_ENGINE_DO_UPDATE 8
#define RE_ENGINE_RENDERING 16
#define RE_ENGINE_HIGHLIGHT_TILES 32
#define RE_ENGINE_CAN_DRAW 64
enum RenderEngineFlag {
RE_ENGINE_ANIMATION = (1 << 0),
RE_ENGINE_PREVIEW = (1 << 1),
RE_ENGINE_DO_DRAW = (1 << 2),
RE_ENGINE_DO_UPDATE = (1 << 3),
RE_ENGINE_RENDERING = (1 << 4),
RE_ENGINE_HIGHLIGHT_TILES = (1 << 5),
RE_ENGINE_CAN_DRAW = (1 << 6),
};
extern ListBase R_engines;