WIP: Brush assets project #106303
|
@ -259,6 +259,28 @@ else()
|
|||
set(WITH_UNITY_BUILD OFF)
|
||||
endif()
|
||||
|
||||
if(COMMAND target_precompile_headers)
|
||||
# Disabling is needed for `./tools/utils_maintenance/code_clean.py` to function.
|
||||
option(WITH_COMPILER_PRECOMPILED_HEADERS "\
|
||||
Use pre-compiled headers to speed up compilation."
|
||||
ON
|
||||
)
|
||||
mark_as_advanced(WITH_COMPILER_PRECOMPILED_HEADERS)
|
||||
|
||||
if(WITH_CLANG_TIDY AND CMAKE_COMPILER_IS_GNUCC)
|
||||
if(WITH_COMPILER_PRECOMPILED_HEADERS)
|
||||
message(STATUS
|
||||
"Clang-Tidy and GCC precompiled headers are incompatible, disabling precompiled headers"
|
||||
)
|
||||
set(WITH_COMPILER_PRECOMPILED_HEADERS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WITH_COMPILER_PRECOMPILED_HEADERS)
|
||||
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(WITH_IK_ITASC "\
|
||||
Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)"
|
||||
ON
|
||||
|
@ -759,8 +781,10 @@ if(WIN32)
|
|||
option(WITH_TBB_MALLOC_PROXY "Enable the TBB malloc replacement" ON)
|
||||
endif()
|
||||
|
||||
option(WITH_EXPERIMENTAL_FEATURES "Enable experimental features" ON)
|
||||
|
||||
# This should be turned off when Blender enter beta/rc/release
|
||||
if("${BLENDER_VERSION_CYCLE}" STREQUAL "alpha")
|
||||
if("${BLENDER_VERSION_CYCLE}" STREQUAL "alpha" AND WITH_EXPERIMENTAL_FEATURES)
|
||||
set(WITH_EXPERIMENTAL_FEATURES ON)
|
||||
else()
|
||||
set(WITH_EXPERIMENTAL_FEATURES OFF)
|
||||
|
|
|
@ -25,7 +25,12 @@ if EXIST %PYTHON% (
|
|||
)
|
||||
|
||||
if NOT EXIST %PYTHON% (
|
||||
echo Warning: Python not found, there is likely an issue with the library folder
|
||||
REM Only emit this warning when the library folder exists but the
|
||||
REM python folder does not. As we don't want to concern people that
|
||||
REM run make update for the first time.
|
||||
if EXIST %BLENDER_DIR%\..\lib\win64_vc15 (
|
||||
echo Warning: Python not found, there is likely an issue with the library folder
|
||||
)
|
||||
set PYTHON=""
|
||||
)
|
||||
|
||||
|
|
|
@ -135,6 +135,12 @@ static int gwl_registry_handler_interface_slot_max();
|
|||
static int gwl_registry_handler_interface_slot_from_string(const char *interface);
|
||||
static const GWL_RegistryHandler *gwl_registry_handler_from_interface_slot(int interface_slot);
|
||||
|
||||
static bool xkb_compose_state_feed_and_get_utf8(
|
||||
xkb_compose_state *compose_state,
|
||||
xkb_state *state,
|
||||
const xkb_keycode_t key,
|
||||
char r_utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)]);
|
||||
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
static void gwl_display_event_thread_destroy(GWL_Display *display);
|
||||
|
||||
|
@ -1103,6 +1109,37 @@ static void gwl_seat_key_layout_active_state_update_mask(GWL_Seat *seat)
|
|||
}
|
||||
}
|
||||
|
||||
/** Callback that runs from GHOST's timer. */
|
||||
static void gwl_seat_key_repeat_timer_fn(GHOST_ITimerTask *task, uint64_t time_ms)
|
||||
{
|
||||
GWL_KeyRepeatPlayload *payload = static_cast<GWL_KeyRepeatPlayload *>(task->getUserData());
|
||||
|
||||
GWL_Seat *seat = payload->seat;
|
||||
wl_surface *wl_surface_focus = seat->keyboard.wl.surface_window;
|
||||
if (UNLIKELY(wl_surface_focus == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
GHOST_SystemWayland *system = seat->system;
|
||||
const uint64_t event_ms = payload->time_ms_init + time_ms;
|
||||
/* Calculate this value every time in case modifier keys are pressed. */
|
||||
|
||||
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
|
||||
if (seat->xkb.compose_state &&
|
||||
xkb_compose_state_feed_and_get_utf8(
|
||||
seat->xkb.compose_state, seat->xkb.state, payload->key_code, utf8_buf))
|
||||
{
|
||||
/* `utf8_buf` has been filled by a compose action. */
|
||||
}
|
||||
else {
|
||||
xkb_state_key_get_utf8(seat->xkb.state, payload->key_code, utf8_buf, sizeof(utf8_buf));
|
||||
}
|
||||
|
||||
system->pushEvent_maybe_pending(new GHOST_EventKey(
|
||||
event_ms, GHOST_kEventKeyDown, win, payload->key_data.gkey, true, utf8_buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Caller must lock `timer_mutex`.
|
||||
*/
|
||||
|
@ -2761,13 +2798,11 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat,
|
|||
}
|
||||
|
||||
static void keyboard_depressed_state_push_events_from_change(
|
||||
GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev)
|
||||
GWL_Seat *seat,
|
||||
GHOST_IWindow *win,
|
||||
const uint64_t event_ms,
|
||||
const GWL_KeyboardDepressedState &key_depressed_prev)
|
||||
{
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl.surface_window);
|
||||
const GHOST_SystemWayland *system = seat->system;
|
||||
/* Caller has no time-stamp, set from system. */
|
||||
const uint64_t event_ms = system->getMilliSeconds();
|
||||
|
||||
/* Separate key up and down into separate passes so key down events always come after key up.
|
||||
* Do this so users of GHOST can use the last pressed or released modifier to check
|
||||
* if the modifier is held instead of counting modifiers pressed as is done here,
|
||||
|
@ -4718,6 +4753,8 @@ static void keyboard_handle_enter(void *data,
|
|||
CLOG_INFO(LOG, 2, "enter");
|
||||
|
||||
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface);
|
||||
|
||||
seat->keyboard.serial = serial;
|
||||
seat->keyboard.wl.surface_window = wl_surface;
|
||||
|
||||
|
@ -4729,6 +4766,12 @@ static void keyboard_handle_enter(void *data,
|
|||
GWL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
|
||||
keyboard_depressed_state_reset(seat);
|
||||
|
||||
/* Keep track of the last held repeating key, start the repeat timer if one exists. */
|
||||
struct {
|
||||
uint32_t key = std::numeric_limits<uint32_t>::max();
|
||||
xkb_keysym_t sym = 0;
|
||||
} repeat;
|
||||
|
||||
uint32_t *key;
|
||||
WL_ARRAY_FOR_EACH (key, keys) {
|
||||
const xkb_keycode_t key_code = *key + EVDEV_OFFSET;
|
||||
|
@ -4738,9 +4781,41 @@ static void keyboard_handle_enter(void *data,
|
|||
if (gkey != GHOST_kKeyUnknown) {
|
||||
keyboard_depressed_state_key_event(seat, gkey, GHOST_kEventKeyDown);
|
||||
}
|
||||
|
||||
if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb.state), key_code)) {
|
||||
repeat.key = *key;
|
||||
repeat.sym = sym;
|
||||
}
|
||||
}
|
||||
|
||||
keyboard_depressed_state_push_events_from_change(seat, key_depressed_prev);
|
||||
/* Caller has no time-stamp, set from system. */
|
||||
const uint64_t event_ms = seat->system->getMilliSeconds();
|
||||
keyboard_depressed_state_push_events_from_change(seat, win, event_ms, key_depressed_prev);
|
||||
|
||||
if ((repeat.key != std::numeric_limits<uint32_t>::max()) && (seat->key_repeat.rate > 0)) {
|
||||
/* Since the key has been held, immediately send a press event.
|
||||
* This also ensures the key will be registered as pressed, see #117896. */
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
std::lock_guard lock_timer_guard{*seat->system->timer_mutex};
|
||||
#endif
|
||||
/* Should have been cleared on leave, set here just in case. */
|
||||
if (UNLIKELY(seat->key_repeat.timer)) {
|
||||
keyboard_handle_key_repeat_cancel(seat);
|
||||
}
|
||||
|
||||
const xkb_keycode_t key_code = repeat.key + EVDEV_OFFSET;
|
||||
const GHOST_TKey gkey = xkb_map_gkey_or_scan_code(repeat.sym, repeat.key);
|
||||
|
||||
GWL_KeyRepeatPlayload *key_repeat_payload = new GWL_KeyRepeatPlayload();
|
||||
key_repeat_payload->seat = seat;
|
||||
key_repeat_payload->key_code = key_code;
|
||||
key_repeat_payload->key_data.gkey = gkey;
|
||||
|
||||
gwl_seat_key_repeat_timer_add(seat, gwl_seat_key_repeat_timer_fn, key_repeat_payload, false);
|
||||
/* Ensure there is a press event on enter so this is known to be held before any mouse
|
||||
* button events which may use a key-binding that depends on this key being held. */
|
||||
gwl_seat_key_repeat_timer_fn(seat->key_repeat.timer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5031,33 +5106,7 @@ static void keyboard_handle_key(void *data,
|
|||
}
|
||||
|
||||
if (key_repeat_payload) {
|
||||
auto key_repeat_fn = [](GHOST_ITimerTask *task, uint64_t time_ms) {
|
||||
GWL_KeyRepeatPlayload *payload = static_cast<GWL_KeyRepeatPlayload *>(task->getUserData());
|
||||
|
||||
GWL_Seat *seat = payload->seat;
|
||||
if (wl_surface *wl_surface_focus = seat->keyboard.wl.surface_window) {
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
GHOST_SystemWayland *system = seat->system;
|
||||
const uint64_t event_ms = payload->time_ms_init + time_ms;
|
||||
/* Calculate this value every time in case modifier keys are pressed. */
|
||||
|
||||
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
|
||||
if (seat->xkb.compose_state &&
|
||||
xkb_compose_state_feed_and_get_utf8(
|
||||
seat->xkb.compose_state, seat->xkb.state, payload->key_code, utf8_buf))
|
||||
{
|
||||
/* `utf8_buf` has been filled by a compose action. */
|
||||
}
|
||||
else {
|
||||
xkb_state_key_get_utf8(seat->xkb.state, payload->key_code, utf8_buf, sizeof(utf8_buf));
|
||||
}
|
||||
|
||||
system->pushEvent_maybe_pending(new GHOST_EventKey(
|
||||
event_ms, GHOST_kEventKeyDown, win, payload->key_data.gkey, true, utf8_buf));
|
||||
}
|
||||
};
|
||||
|
||||
gwl_seat_key_repeat_timer_add(seat, key_repeat_fn, key_repeat_payload, true);
|
||||
gwl_seat_key_repeat_timer_add(seat, gwl_seat_key_repeat_timer_fn, key_repeat_payload, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
|
|||
)
|
||||
|
||||
|
||||
# cache-type can be 'PSYS' 'HAIR' 'FLUID' etc.
|
||||
# cache-type can be 'PSYS' 'HAIR' etc. ('FLUID' uses its own cache)
|
||||
|
||||
def point_cache_ui(self, cache, enabled, cachetype):
|
||||
layout = self.layout
|
||||
|
@ -130,12 +130,8 @@ def point_cache_ui(self, cache, enabled, cachetype):
|
|||
col.operator("ptcache.add", icon='ADD', text="")
|
||||
col.operator("ptcache.remove", icon='REMOVE', text="")
|
||||
|
||||
if cachetype in {'PSYS', 'HAIR', 'FLUID'}:
|
||||
if cachetype in {'PSYS', 'HAIR'}:
|
||||
col = layout.column()
|
||||
|
||||
if cachetype == 'FLUID':
|
||||
col.prop(cache, "use_library_path", text="Use Library Path")
|
||||
|
||||
col.prop(cache, "use_external")
|
||||
|
||||
if cache.use_external:
|
||||
|
@ -149,14 +145,14 @@ def point_cache_ui(self, cache, enabled, cachetype):
|
|||
col.alignment = 'RIGHT'
|
||||
col.label(text=cache_info)
|
||||
else:
|
||||
if cachetype in {'FLUID', 'DYNAMIC_PAINT'}:
|
||||
if cachetype == 'DYNAMIC_PAINT':
|
||||
if not is_saved:
|
||||
col = layout.column(align=True)
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text="Cache is disabled until the file is saved")
|
||||
layout.enabled = False
|
||||
|
||||
if not cache.use_external or cachetype == 'FLUID':
|
||||
if not cache.use_external:
|
||||
col = layout.column(align=True)
|
||||
|
||||
if cachetype not in {'PSYS', 'DYNAMIC_PAINT'}:
|
||||
|
@ -164,18 +160,18 @@ def point_cache_ui(self, cache, enabled, cachetype):
|
|||
col.prop(cache, "frame_start", text="Simulation Start")
|
||||
col.prop(cache, "frame_end")
|
||||
|
||||
if cachetype not in {'FLUID', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
|
||||
if cachetype not in {'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
|
||||
col.prop(cache, "frame_step")
|
||||
|
||||
cache_info = cache.info
|
||||
if cachetype != 'FLUID' and cache_info: # avoid empty space.
|
||||
if cache_info: # avoid empty space.
|
||||
col = layout.column(align=True)
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text=cache_info)
|
||||
|
||||
can_bake = True
|
||||
|
||||
if cachetype not in {'FLUID', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
|
||||
if cachetype not in {'DYNAMIC_PAINT', 'RIGID_BODY'}:
|
||||
if not is_saved:
|
||||
col = layout.column(align=True)
|
||||
col.alignment = 'RIGHT'
|
||||
|
|
|
@ -1598,7 +1598,7 @@ class USERPREF_UL_asset_libraries(UIList):
|
|||
class USERPREF_UL_extension_repos(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
|
||||
repo = item
|
||||
icon = 'WORLD' if repo.use_remote_path else 'DISK_DRIVE'
|
||||
icon = 'NETWORK_DRIVE' if repo.use_remote_path else 'DISK_DRIVE'
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(repo, "name", text="", icon=icon, emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
|
@ -1615,6 +1615,24 @@ class USERPREF_UL_extension_repos(UIList):
|
|||
|
||||
layout.prop(repo, "enabled", text="", emboss=False, icon='CHECKBOX_HLT' if repo.enabled else 'CHECKBOX_DEHLT')
|
||||
|
||||
def filter_items(self, _context, data, propname):
|
||||
# Repositories has no index, converting to a list.
|
||||
items = list(getattr(data, propname))
|
||||
|
||||
flags = [self.bitflag_filter_item] * len(items)
|
||||
|
||||
indices = [None] * len(items)
|
||||
for index, orig_index in enumerate(sorted(
|
||||
range(len(items)),
|
||||
key=lambda i: (
|
||||
items[i].use_remote_path is False,
|
||||
items[i].name.lower(),
|
||||
)
|
||||
)):
|
||||
indices[orig_index] = index
|
||||
|
||||
return flags, indices
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Save/Load Panels
|
||||
|
|
|
@ -7,14 +7,6 @@ if(WITH_LEGACY_OPENGL)
|
|||
endif()
|
||||
|
||||
if(WITH_CLANG_TIDY AND NOT MSVC)
|
||||
if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
message(WARNING "Currently Clang-Tidy might fail with GCC toolchain, switch to Clang toolchain if that happens")
|
||||
if(COMMAND target_precompile_headers)
|
||||
message(STATUS "Clang-Tidy and GCC precompiled headers are incompatible, disabling precompiled headers")
|
||||
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(ClangTidy REQUIRED)
|
||||
set(CMAKE_C_CLANG_TIDY
|
||||
${CLANG_TIDY_EXECUTABLE};--extra-arg=-Wno-error=unknown-warning-option)
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
/* Name of sub-directory inside #BLENDER_DATAFILES that contains font files. */
|
||||
#define BLF_DATAFILES_FONTS_DIR "fonts"
|
||||
|
@ -254,6 +256,10 @@ void BLF_rotation(int fontid, float angle);
|
|||
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax);
|
||||
void BLF_wordwrap(int fontid, int wrap_width);
|
||||
|
||||
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
|
||||
blender::StringRef str,
|
||||
const int max_pixel_width);
|
||||
|
||||
#if BLF_BLUR_ENABLE
|
||||
void BLF_blur(int fontid, int size);
|
||||
#endif
|
||||
|
|
|
@ -935,6 +935,17 @@ void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
|
|||
BLF_draw_buffer_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
|
||||
blender::StringRef str,
|
||||
const int max_pixel_width)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
if (!font) {
|
||||
return {};
|
||||
}
|
||||
return blf_font_string_wrap(font, str, max_pixel_width);
|
||||
}
|
||||
|
||||
char *BLF_display_name_from_file(const char *filepath)
|
||||
{
|
||||
/* While listing font directories this function can be called simultaneously from a greater
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "BLI_string_cursor_utf8.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
|
@ -1085,6 +1086,7 @@ void blf_str_offset_to_glyph_bounds(FontBLF *font,
|
|||
static void blf_font_wrap_apply(FontBLF *font,
|
||||
const char *str,
|
||||
const size_t str_len,
|
||||
const int max_pixel_width,
|
||||
ResultBLF *r_info,
|
||||
void (*callback)(FontBLF *font,
|
||||
GlyphCacheBLF *gc,
|
||||
|
@ -1109,7 +1111,7 @@ static void blf_font_wrap_apply(FontBLF *font,
|
|||
struct WordWrapVars {
|
||||
ft_pix wrap_width;
|
||||
size_t start, last[2];
|
||||
} wrap = {font->wrap_width != -1 ? ft_pix_from_int(font->wrap_width) : INT_MAX, 0, {0, 0}};
|
||||
} wrap = {max_pixel_width != -1 ? ft_pix_from_int(max_pixel_width) : INT_MAX, 0, {0, 0}};
|
||||
|
||||
// printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str);
|
||||
while ((i < str_len) && str[i]) {
|
||||
|
@ -1198,7 +1200,8 @@ static void blf_font_draw__wrap_cb(FontBLF *font,
|
|||
}
|
||||
void blf_font_draw__wrap(FontBLF *font, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, nullptr);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_draw__wrap_cb, nullptr);
|
||||
}
|
||||
|
||||
/** Utility for #blf_font_boundbox__wrap. */
|
||||
|
@ -1223,7 +1226,8 @@ void blf_font_boundbox__wrap(
|
|||
box->ymin = 32000;
|
||||
box->ymax = -32000;
|
||||
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_boundbox_wrap_cb, box);
|
||||
}
|
||||
|
||||
/** Utility for #blf_font_draw_buffer__wrap. */
|
||||
|
@ -1241,7 +1245,37 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
|
|||
const size_t str_len,
|
||||
ResultBLF *r_info)
|
||||
{
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, nullptr);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_draw_buffer__wrap_cb, nullptr);
|
||||
}
|
||||
|
||||
/** Wrap a blender::StringRef. */
|
||||
static void blf_font_string_wrap_cb(FontBLF * /*font*/,
|
||||
GlyphCacheBLF * /*gc*/,
|
||||
const char *str,
|
||||
const size_t str_len,
|
||||
ft_pix /*pen_y*/,
|
||||
void *str_list_ptr)
|
||||
{
|
||||
blender::Vector<blender::StringRef> *list = static_cast<blender::Vector<blender::StringRef> *>(
|
||||
str_list_ptr);
|
||||
blender::StringRef line(str, str + str_len);
|
||||
list->append(line);
|
||||
}
|
||||
|
||||
blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
blender::StringRef str,
|
||||
int max_pixel_width)
|
||||
{
|
||||
blender::Vector<blender::StringRef> list;
|
||||
blf_font_wrap_apply(font,
|
||||
str.data(),
|
||||
size_t(str.size()),
|
||||
max_pixel_width,
|
||||
nullptr,
|
||||
blf_font_string_wrap_cb,
|
||||
&list);
|
||||
return list;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
struct FontBLF;
|
||||
struct GlyphBLF;
|
||||
struct GlyphCacheBLF;
|
||||
|
@ -96,6 +99,10 @@ void blf_font_draw__wrap(struct FontBLF *font,
|
|||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
|
||||
blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
blender::StringRef str,
|
||||
int max_pixel_width);
|
||||
|
||||
/**
|
||||
* Use fixed column width, but an utf8 character may occupy multiple columns.
|
||||
*/
|
||||
|
|
|
@ -110,6 +110,7 @@ enum eCbEvent {
|
|||
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST,
|
||||
BKE_CB_EVT_EXTENSION_REPOS_SYNC,
|
||||
BKE_CB_EVT_EXTENSION_REPOS_UPGRADE,
|
||||
BKE_CB_EVT_EXTENSION_DROP_URL,
|
||||
BKE_CB_EVT_TOT,
|
||||
};
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef,
|
|||
const char *module,
|
||||
const char *custom_dirpath);
|
||||
void BKE_preferences_extension_repo_remove(UserDef *userdef, bUserExtensionRepo *repo);
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add_default(UserDef *userdef);
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add_default_user(UserDef *userdef);
|
||||
|
||||
void BKE_preferences_extension_repo_name_set(UserDef *userdef,
|
||||
bUserExtensionRepo *repo,
|
||||
|
|
|
@ -1417,6 +1417,9 @@ UserDef *BKE_blendfile_userdef_from_defaults()
|
|||
|
||||
BKE_preferences_asset_library_default_add(userdef);
|
||||
|
||||
BKE_preferences_extension_repo_add_default(userdef);
|
||||
BKE_preferences_extension_repo_add_default_user(userdef);
|
||||
|
||||
return userdef;
|
||||
}
|
||||
|
||||
|
|
|
@ -538,7 +538,7 @@ void layer_adjustments_to_modifiers(Main &bmain,
|
|||
STRNCPY(tmd->influence.layer_name, gpl->info);
|
||||
|
||||
char modifier_name[64];
|
||||
BLI_snprintf(modifier_name, 64, "Tint %s", gpl->info);
|
||||
SNPRINTF(modifier_name, "Tint %s", gpl->info);
|
||||
STRNCPY(md->name, modifier_name);
|
||||
BKE_modifier_unique_name(&dst_object.modifiers, md);
|
||||
|
||||
|
@ -558,7 +558,7 @@ void layer_adjustments_to_modifiers(Main &bmain,
|
|||
auto *md = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
|
||||
|
||||
char modifier_name[64];
|
||||
BLI_snprintf(modifier_name, 64, "Thickness %s", gpl->info);
|
||||
SNPRINTF(modifier_name, "Thickness %s", gpl->info);
|
||||
STRNCPY(md->modifier.name, modifier_name);
|
||||
BKE_modifier_unique_name(&dst_object.modifiers, &md->modifier);
|
||||
md->node_group = offset_radius_node_tree;
|
||||
|
|
|
@ -193,6 +193,22 @@ void BKE_preferences_extension_repo_remove(UserDef *userdef, bUserExtensionRepo
|
|||
BLI_freelinkN(&userdef->extension_repos, repo);
|
||||
}
|
||||
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add_default(UserDef *userdef)
|
||||
{
|
||||
bUserExtensionRepo *repo = BKE_preferences_extension_repo_add(
|
||||
userdef, "Blender Official", "blender_official", "");
|
||||
STRNCPY(repo->remote_path, "https://extensions.blender.org");
|
||||
repo->flag |= USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH;
|
||||
return repo;
|
||||
}
|
||||
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add_default_user(UserDef *userdef)
|
||||
{
|
||||
bUserExtensionRepo *repo = BKE_preferences_extension_repo_add(
|
||||
userdef, "User Default", "user_default", "");
|
||||
return repo;
|
||||
}
|
||||
|
||||
void BKE_preferences_extension_repo_name_set(UserDef *userdef,
|
||||
bUserExtensionRepo *repo,
|
||||
const char *name)
|
||||
|
|
|
@ -133,3 +133,7 @@ if(WITH_GTESTS)
|
|||
)
|
||||
blender_add_test_suite_lib(blenloader "${TEST_SRC}" "${INC}" "${INC_SYS}" "${TEST_LIB}")
|
||||
endif()
|
||||
|
||||
if(WITH_EXPERIMENTAL_FEATURES)
|
||||
add_definitions(-DWITH_EXPERIMENTAL_FEATURES)
|
||||
endif()
|
|
@ -923,6 +923,13 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
}
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(402, 6)) {
|
||||
if (BLI_listbase_is_empty(&userdef->extension_repos)) {
|
||||
BKE_preferences_extension_repo_add_default(userdef);
|
||||
BKE_preferences_extension_repo_add_default_user(userdef);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
BKE_preferences_asset_shelf_settings_ensure_catalog_path_enabled(
|
||||
userdef, "VIEW3D_AST_brush_sculpt", "Brushes/Mesh/Sculpt/Cloth");
|
||||
|
@ -955,10 +962,11 @@ void BLO_sanitize_experimental_features_userpref_blend(UserDef *userdef)
|
|||
*
|
||||
* At that time master already has its version bumped so its user preferences
|
||||
* are not touched by these settings. */
|
||||
|
||||
#ifdef WITH_EXPERIMENTAL_FEATURES
|
||||
if (BKE_blender_version_is_alpha()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
MEMSET_STRUCT_AFTER(&userdef->experimental, 0, SANITIZE_AFTER_HERE);
|
||||
}
|
||||
|
|
|
@ -81,59 +81,29 @@ void GaussianBlurBaseOperation::update_memory_buffer_partial(MemoryBuffer *outpu
|
|||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const int2 unit_offset = dimension_ == eDimension::X ? int2(1, 0) : int2(0, 1);
|
||||
MemoryBuffer *input = inputs[IMAGE_INPUT_INDEX];
|
||||
const rcti &input_rect = input->get_rect();
|
||||
BuffersIterator<float> it = output->iterate_with({input}, area);
|
||||
|
||||
int min_input_coord = -1;
|
||||
int max_input_coord = -1;
|
||||
int elem_stride = -1;
|
||||
std::function<int()> get_current_coord;
|
||||
switch (dimension_) {
|
||||
case eDimension::X:
|
||||
min_input_coord = input_rect.xmin;
|
||||
max_input_coord = input_rect.xmax;
|
||||
elem_stride = input->elem_stride;
|
||||
get_current_coord = [&] { return it.x; };
|
||||
break;
|
||||
case eDimension::Y:
|
||||
min_input_coord = input_rect.ymin;
|
||||
max_input_coord = input_rect.ymax;
|
||||
elem_stride = input->row_stride;
|
||||
get_current_coord = [&] { return it.y; };
|
||||
break;
|
||||
}
|
||||
|
||||
for (; !it.is_end(); ++it) {
|
||||
const int coord = get_current_coord();
|
||||
const int coord_min = max_ii(coord - filtersize_, min_input_coord);
|
||||
const int coord_max = min_ii(coord + filtersize_ + 1, max_input_coord);
|
||||
|
||||
float ATTR_ALIGN(16) color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float multiplier_accum = 0.0f;
|
||||
|
||||
const int step = QualityStepHelper::get_step();
|
||||
const float *in = it.in(0) + (intptr_t(coord_min) - coord) * elem_stride;
|
||||
const int in_stride = elem_stride * step;
|
||||
int gauss_idx = (coord_min - coord) + filtersize_;
|
||||
const int gauss_end = gauss_idx + (coord_max - coord_min);
|
||||
for (BuffersIterator<float> it = output->iterate_with({input}, area); !it.is_end(); ++it) {
|
||||
alignas(16) float4 accumulated_color = float4(0.0f);
|
||||
#if BLI_HAVE_SSE2
|
||||
__m128 accum_r = _mm_load_ps(color_accum);
|
||||
for (; gauss_idx < gauss_end; in += in_stride, gauss_idx += step) {
|
||||
__m128 reg_a = _mm_load_ps(in);
|
||||
reg_a = _mm_mul_ps(reg_a, gausstab_sse_[gauss_idx]);
|
||||
accum_r = _mm_add_ps(accum_r, reg_a);
|
||||
multiplier_accum += gausstab_[gauss_idx];
|
||||
__m128 accumulated_color_sse = _mm_setzero_ps();
|
||||
for (int i = -filtersize_; i <= filtersize_; i++) {
|
||||
const int2 offset = unit_offset * i;
|
||||
__m128 weight = gausstab_sse_[i + filtersize_];
|
||||
__m128 color = _mm_load_ps(input->get_elem_clamped(it.x + offset.x, it.y + offset.y));
|
||||
__m128 weighted_color = _mm_mul_ps(color, weight);
|
||||
accumulated_color_sse = _mm_add_ps(accumulated_color_sse, weighted_color);
|
||||
}
|
||||
_mm_store_ps(color_accum, accum_r);
|
||||
_mm_store_ps(accumulated_color, accumulated_color_sse);
|
||||
#else
|
||||
for (; gauss_idx < gauss_end; in += in_stride, gauss_idx += step) {
|
||||
const float multiplier = gausstab_[gauss_idx];
|
||||
madd_v4_v4fl(color_accum, in, multiplier);
|
||||
multiplier_accum += multiplier;
|
||||
for (int i = -filtersize_; i <= filtersize_; i++) {
|
||||
const int2 offset = unit_offset * i;
|
||||
const float weight = gausstab_[i + filtersize_];
|
||||
const float4 color = input->get_elem_clamped(it.x + offset.x, it.y + offset.y);
|
||||
accumulated_color += color * weight;
|
||||
}
|
||||
#endif
|
||||
mul_v4_v4fl(it.out, color_accum, 1.0f / multiplier_accum);
|
||||
copy_v4_v4(it.out, accumulated_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,16 +32,19 @@ void HueSaturationValueCorrectOperation::execute_pixel_sampled(float output[4],
|
|||
|
||||
input_program_->read_sampled(hsv, x, y, sampler);
|
||||
|
||||
/* We parametrize the curve using the hue value. */
|
||||
const float parameter = hsv[0];
|
||||
|
||||
/* adjust hue, scaling returned default 0.5 up to 1 */
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 0, hsv[0]);
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 0, parameter);
|
||||
hsv[0] += f - 0.5f;
|
||||
|
||||
/* adjust saturation, scaling returned default 0.5 up to 1 */
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 1, hsv[0]);
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 1, parameter);
|
||||
hsv[1] *= (f * 2.0f);
|
||||
|
||||
/* adjust value, scaling returned default 0.5 up to 1 */
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 2, hsv[0]);
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 2, parameter);
|
||||
hsv[2] *= (f * 2.0f);
|
||||
|
||||
hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
|
||||
|
@ -67,16 +70,19 @@ void HueSaturationValueCorrectOperation::update_memory_buffer_partial(MemoryBuff
|
|||
for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
|
||||
copy_v4_v4(hsv, it.in(0));
|
||||
|
||||
/* We parametrize the curve using the hue value. */
|
||||
const float parameter = hsv[0];
|
||||
|
||||
/* Adjust hue, scaling returned default 0.5 up to 1. */
|
||||
float f = BKE_curvemapping_evaluateF(curve_mapping_, 0, hsv[0]);
|
||||
float f = BKE_curvemapping_evaluateF(curve_mapping_, 0, parameter);
|
||||
hsv[0] += f - 0.5f;
|
||||
|
||||
/* Adjust saturation, scaling returned default 0.5 up to 1. */
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 1, hsv[0]);
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 1, parameter);
|
||||
hsv[1] *= (f * 2.0f);
|
||||
|
||||
/* Adjust value, scaling returned default 0.5 up to 1. */
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 2, hsv[0]);
|
||||
f = BKE_curvemapping_evaluateF(curve_mapping_, 2, parameter);
|
||||
hsv[2] *= (f * 2.0f);
|
||||
|
||||
hsv[0] = hsv[0] - floorf(hsv[0]); /* Mod 1.0. */
|
||||
|
|
|
@ -4,25 +4,10 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl)
|
||||
|
||||
/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize
|
||||
* parameters accordingly. */
|
||||
#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range)
|
||||
|
||||
/* Curve maps are stored in texture samplers, so ensure that the parameters evaluate the sampler at
|
||||
* the center of the pixels, because samplers are evaluated using linear interpolation. Given the
|
||||
* parameter in the [0, 1] range. */
|
||||
float compute_curve_map_coordinates(float parameter)
|
||||
{
|
||||
/* Curve maps have a fixed width of 257. We offset by the equivalent of half a pixel and scale
|
||||
* down such that the normalized parameter 1.0 corresponds to the center of the last pixel. */
|
||||
const float sampler_resolution = 257.0;
|
||||
float sampler_offset = 0.5 / sampler_resolution;
|
||||
float sampler_scale = 1.0 - (1.0 / sampler_resolution);
|
||||
return parameter * sampler_scale + sampler_offset;
|
||||
}
|
||||
|
||||
/* Same as compute_curve_map_coordinates but vectorized. */
|
||||
vec2 compute_curve_map_coordinates(vec2 parameters)
|
||||
vec3 compute_curve_map_coordinates(vec3 parameters)
|
||||
{
|
||||
const float sampler_resolution = 257.0;
|
||||
float sampler_offset = 0.5 / sampler_resolution;
|
||||
|
@ -41,21 +26,18 @@ void node_composite_hue_correct(float factor,
|
|||
vec4 hsv;
|
||||
rgb_to_hsv(color, hsv);
|
||||
|
||||
/* First, adjust the hue channel on its own, since corrections in the saturation and value
|
||||
* channels depends on the new value of the hue, not its original value. A curve map value of 0.5
|
||||
* means no change in hue, so adjust the value to get an identity at 0.5. Since the identity of
|
||||
* addition is 0, we subtract 0.5 (0.5 - 0.5 = 0). */
|
||||
const float hue_parameter = NORMALIZE_PARAMETER(hsv.x, minimums.x, range_dividers.x);
|
||||
float hue_coordinates = compute_curve_map_coordinates(hue_parameter);
|
||||
hsv.x += texture(curve_map, vec2(hue_coordinates, layer)).x - 0.5;
|
||||
|
||||
/* Second, adjust the saturation and value based on the new value of the hue. A curve map value
|
||||
* of 0.5 means no change in hue, so adjust the value to get an identity at 0.5. Since the
|
||||
* identity of duplication is 1, we multiply by 2 (0.5 * 2 = 1). */
|
||||
vec2 parameters = NORMALIZE_PARAMETER(hsv.x, minimums.yz, range_dividers.yz);
|
||||
vec2 coordinates = compute_curve_map_coordinates(parameters);
|
||||
hsv.y *= texture(curve_map, vec2(coordinates.x, layer)).y * 2.0;
|
||||
hsv.z *= texture(curve_map, vec2(coordinates.y, layer)).z * 2.0;
|
||||
/* First, normalize the hue value into the [0, 1] range for each of the curve maps and compute
|
||||
* the proper sampler coordinates for interpolation, then adjust each of the Hue, Saturation, and
|
||||
* Values accordingly to the following rules. A curve map value of 0.5 means no change in hue, so
|
||||
* adjust the value to get an identity at 0.5. Since the identity of addition is 0, we subtract
|
||||
* 0.5 (0.5 - 0.5 = 0). A curve map value of 0.5 means no change in saturation or value, so
|
||||
* adjust the value to get an identity at 0.5. Since the identity of multiplication is 1, we
|
||||
* multiply by 2 (0.5 * 2 = 1). */
|
||||
vec3 parameters = (hsv.xxx - minimums) * range_dividers;
|
||||
vec3 coordinates = compute_curve_map_coordinates(parameters);
|
||||
hsv.x += texture(curve_map, vec2(coordinates.x, layer)).x - 0.5;
|
||||
hsv.y *= texture(curve_map, vec2(coordinates.y, layer)).y * 2.0;
|
||||
hsv.z *= texture(curve_map, vec2(coordinates.z, layer)).z * 2.0;
|
||||
|
||||
/* Sanitize the new hue and saturation values. */
|
||||
hsv.x = fract(hsv.x);
|
||||
|
|
|
@ -123,10 +123,24 @@ vec3 lightprobe_eval(LightProbeSample samp, ClosureReflection reflection, vec3 P
|
|||
return mix(radiance_cube, radiance_sh, fac);
|
||||
}
|
||||
|
||||
/* Return the equivalent reflective roughness resulting in a similar lobe. */
|
||||
float lightprobe_refraction_roughness_remapping(float roughness, float ior)
|
||||
{
|
||||
/* This is a very rough mapping used by manually curve fitting the apparent roughness
|
||||
* (blurriness) of GGX reflections and GGX refraction.
|
||||
* A better fit is desirable if it is in the same order of complexity. */
|
||||
if (ior > 1.0) {
|
||||
return roughness * sqrt_fast(1.0 - 1.0 / ior);
|
||||
}
|
||||
else {
|
||||
return roughness * sqrt_fast(saturate(1.0 - ior)) * 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 lightprobe_refraction_dominant_dir(vec3 N, vec3 V, float ior, float roughness)
|
||||
{
|
||||
/* Reusing same thing as lightprobe_reflection_dominant_dir for now.
|
||||
* TODO(fclem): Find something better that take IOR and roughness into account. */
|
||||
/* Reusing same thing as lightprobe_reflection_dominant_dir for now with the roughness mapped to
|
||||
* reflection roughness. */
|
||||
float m = square(roughness);
|
||||
vec3 R = refract(-V, N, 1.0 / ior);
|
||||
float smoothness = 1.0 - m;
|
||||
|
@ -136,13 +150,15 @@ vec3 lightprobe_refraction_dominant_dir(vec3 N, vec3 V, float ior, float roughne
|
|||
|
||||
vec3 lightprobe_eval(LightProbeSample samp, ClosureRefraction cl, vec3 P, vec3 V)
|
||||
{
|
||||
vec3 L = lightprobe_refraction_dominant_dir(cl.N, V, cl.ior, cl.roughness);
|
||||
float effective_roughness = lightprobe_refraction_roughness_remapping(cl.roughness, cl.ior);
|
||||
|
||||
float lod = sphere_probe_roughness_to_lod(cl.roughness);
|
||||
vec3 L = lightprobe_refraction_dominant_dir(cl.N, V, cl.ior, effective_roughness);
|
||||
|
||||
float lod = sphere_probe_roughness_to_lod(effective_roughness);
|
||||
vec3 radiance_cube = lightprobe_spherical_sample_normalized_with_parallax(
|
||||
samp.spherical_id, P, L, lod, samp.volume_irradiance);
|
||||
|
||||
float fac = sphere_probe_roughness_to_mix_fac(cl.roughness);
|
||||
float fac = sphere_probe_roughness_to_mix_fac(effective_roughness);
|
||||
vec3 radiance_sh = spherical_harmonics_evaluate_lambert(L, samp.volume_irradiance);
|
||||
return mix(radiance_cube, radiance_sh, fac);
|
||||
}
|
||||
|
|
|
@ -3271,6 +3271,9 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
|
|||
float *hsv = cpicker->hsv_perceptual;
|
||||
float hsv_n[3];
|
||||
|
||||
/* Is this the larger color canvas or narrow color slider? */
|
||||
bool is_canvas = ELEM(hsv_but->gradient_type, UI_GRAD_SV, UI_GRAD_HV, UI_GRAD_HS);
|
||||
|
||||
/* Initialize for compatibility. */
|
||||
copy_v3_v3(hsv_n, hsv);
|
||||
|
||||
|
@ -3292,15 +3295,15 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
|
|||
imm_draw_box_wire_2d(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
|
||||
immUnbindProgram();
|
||||
|
||||
if (BLI_rcti_size_x(rect) / BLI_rcti_size_y(rect) < 3) {
|
||||
/* This is for the full square HSV cube. */
|
||||
if (is_canvas) {
|
||||
/* Round cursor in the large square area. */
|
||||
float margin = (4.0f * UI_SCALE_FAC);
|
||||
CLAMP(x, rect->xmin + margin, rect->xmax - margin);
|
||||
CLAMP(y, rect->ymin + margin, rect->ymax - margin);
|
||||
ui_hsv_cursor(x, y, zoom, rgb, hsv, but->flag & UI_SELECT);
|
||||
}
|
||||
else {
|
||||
/* This is for the narrow horizontal gradient. */
|
||||
/* Square indicator in the narrow area. */
|
||||
rctf rectf;
|
||||
BLI_rctf_rcti_copy(&rectf, rect);
|
||||
const float margin = (2.0f * UI_SCALE_FAC);
|
||||
|
|
|
@ -354,7 +354,7 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
|
|||
static const EnumPropertyItem repo_type_items[] = {
|
||||
{int(bUserExtensionRepoAddType::Remote),
|
||||
"REMOTE",
|
||||
ICON_WORLD,
|
||||
ICON_NETWORK_DRIVE,
|
||||
"Add Remote Repository",
|
||||
"Add a repository referencing an remote repository "
|
||||
"with support for listing and updating extensions"},
|
||||
|
@ -630,6 +630,33 @@ static void PREFERENCES_OT_extension_repo_upgrade(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Drop Extension Operator
|
||||
* \{ */
|
||||
|
||||
static int preferences_extension_url_drop_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char *url = RNA_string_get_alloc(op->ptr, "url", nullptr, 0, nullptr);
|
||||
BKE_callback_exec_string(CTX_data_main(C), BKE_CB_EVT_EXTENSION_DROP_URL, url);
|
||||
MEM_freeN(url);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void PREFERENCES_OT_extension_url_drop(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Drop Extension URL";
|
||||
ot->description = "Handle dropping an extension URL";
|
||||
ot->idname = "PREFERENCES_OT_extension_url_drop";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = preferences_extension_url_drop_exec;
|
||||
|
||||
RNA_def_string(ot->srna, "url", nullptr, 0, "URL", "Location of the extension to install");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Associate File Type Operator (Windows only)
|
||||
* \{ */
|
||||
|
@ -746,6 +773,96 @@ static void PREFERENCES_OT_unassociate_blend(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Drag & Drop URL
|
||||
* \{ */
|
||||
|
||||
static bool drop_extension_url_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
{
|
||||
if (!U.experimental.use_extension_repos) {
|
||||
return false;
|
||||
}
|
||||
if (drag->type != WM_DRAG_STRING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string &str = WM_drag_get_string(drag);
|
||||
|
||||
/* Only URL formatted text. */
|
||||
const char *cstr = str.c_str();
|
||||
if (!(STRPREFIX(cstr, "http://") || STRPREFIX(cstr, "https://") || STRPREFIX(cstr, "file://"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only single line strings. */
|
||||
if (str.find('\n') != std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
const char *cstr_ext = BLI_path_extension(cstr);
|
||||
if (!(cstr_ext && STRCASEEQ(cstr_ext, ".zip"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void drop_extension_url_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
/* Copy drag URL to properties. */
|
||||
const std::string &str = WM_drag_get_string(drag);
|
||||
RNA_string_set(drop->ptr, "url", str.c_str());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Drag & Drop Paths
|
||||
* \{ */
|
||||
|
||||
static bool drop_extension_path_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/)
|
||||
{
|
||||
if (!U.experimental.use_extension_repos) {
|
||||
return false;
|
||||
}
|
||||
if (drag->type != WM_DRAG_PATH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *cstr = WM_drag_get_single_path(drag);
|
||||
const char *cstr_ext = BLI_path_extension(cstr);
|
||||
if (!(cstr_ext && STRCASEEQ(cstr_ext, ".zip"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void drop_extension_path_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop)
|
||||
{
|
||||
/* Copy drag URL to properties. */
|
||||
const char *cstr = WM_drag_get_single_path(drag);
|
||||
RNA_string_set(drop->ptr, "url", cstr);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
static void ED_dropbox_drop_extension()
|
||||
{
|
||||
ListBase *lb = WM_dropboxmap_find("Window", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
||||
WM_dropbox_add(lb,
|
||||
"PREFERENCES_OT_extension_url_drop",
|
||||
drop_extension_url_poll,
|
||||
drop_extension_url_copy,
|
||||
nullptr,
|
||||
nullptr);
|
||||
WM_dropbox_add(lb,
|
||||
"PREFERENCES_OT_extension_url_drop",
|
||||
drop_extension_path_poll,
|
||||
drop_extension_path_copy,
|
||||
nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void ED_operatortypes_userpref()
|
||||
{
|
||||
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
|
||||
|
@ -760,7 +877,10 @@ void ED_operatortypes_userpref()
|
|||
WM_operatortype_append(PREFERENCES_OT_extension_repo_remove);
|
||||
WM_operatortype_append(PREFERENCES_OT_extension_repo_sync);
|
||||
WM_operatortype_append(PREFERENCES_OT_extension_repo_upgrade);
|
||||
WM_operatortype_append(PREFERENCES_OT_extension_url_drop);
|
||||
|
||||
WM_operatortype_append(PREFERENCES_OT_associate_blend);
|
||||
WM_operatortype_append(PREFERENCES_OT_unassociate_blend);
|
||||
|
||||
ED_dropbox_drop_extension();
|
||||
}
|
||||
|
|
|
@ -596,7 +596,7 @@ void GPU_shader_constant_bool_ex(GPUShader *sh, int location, bool value)
|
|||
Shader &shader = *unwrap(sh);
|
||||
BLI_assert(shader.constants.types[location] == gpu::shader::Type::BOOL);
|
||||
shader.constants.is_dirty |= assign_if_different(shader.constants.values[location].u,
|
||||
static_cast<uint32_t>(value));
|
||||
uint32_t(value));
|
||||
}
|
||||
|
||||
void GPU_shader_constant_int(GPUShader *sh, const char *name, int value)
|
||||
|
|
|
@ -63,7 +63,7 @@ void node_tex_voronoi_f1_1d(vec3 coord,
|
|||
params.max_distance = 0.5 + 0.5 * params.randomness;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, w);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ void node_tex_voronoi_smooth_f1_1d(vec3 coord,
|
|||
params.max_distance = 0.5 + 0.5 * params.randomness;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, w);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ void node_tex_voronoi_f2_1d(vec3 coord,
|
|||
params.max_distance = (0.5 + 0.5 * params.randomness) * 2.0;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, w);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ void node_tex_voronoi_f1_2d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec2(0.0), vec2(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord.xy);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ void node_tex_voronoi_smooth_f1_2d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec2(0.0), vec2(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord.xy);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ void node_tex_voronoi_f2_2d(vec3 coord,
|
|||
2.0;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord.xy);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ void node_tex_voronoi_f1_3d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec3(0.0), vec3(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ void node_tex_voronoi_smooth_f1_3d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec3(0.0), vec3(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ void node_tex_voronoi_f2_3d(vec3 coord,
|
|||
2.0;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, coord);
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
}
|
||||
|
||||
|
@ -501,7 +501,7 @@ void node_tex_voronoi_f1_4d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec4(0.0), vec4(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, vec4(coord, w));
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ void node_tex_voronoi_smooth_f1_4d(vec3 coord,
|
|||
params.max_distance = voronoi_distance(vec4(0.0), vec4(0.5 + 0.5 * params.randomness), params);
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, vec4(coord, w));
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ void node_tex_voronoi_f2_4d(vec3 coord,
|
|||
2.0;
|
||||
VoronoiOutput Output = fractal_voronoi_x_fx(params, vec4(coord, w));
|
||||
outDistance = Output.Distance;
|
||||
outColor.xyz = Output.Color;
|
||||
outColor = vec4(Output.Color, 1.0);
|
||||
outPosition = Output.Position.xyz;
|
||||
outW = Output.Position.w;
|
||||
}
|
||||
|
|
|
@ -356,5 +356,5 @@ ImbAnimType imb_get_anim_type(const char *filepath)
|
|||
bool IMB_isanim(const char *filepath)
|
||||
{
|
||||
ImbAnimType type = imb_get_anim_type(filepath);
|
||||
return (type != ImbAnimType::NotAnim && type != ImbAnimType::Sequence);
|
||||
return !ELEM(type, ImbAnimType::NotAnim, ImbAnimType::Sequence);
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
|
|||
{"_extension_repos_update_post", "on changes to extension repos (after)"},
|
||||
{"_extension_repos_sync", "on creating or synchronizing the active repository"},
|
||||
{"_extension_repos_upgrade", "on upgrading the active repository"},
|
||||
{"_extension_drop_url", "on dropping a URL"},
|
||||
|
||||
/* sets the permanent tag */
|
||||
#define APP_CB_OTHER_FIELDS 1
|
||||
|
|
|
@ -31,7 +31,7 @@ static void __cpuid(
|
|||
}
|
||||
#endif
|
||||
|
||||
static int cpu_supports_sse42(void)
|
||||
static int cpu_supports_sse42()
|
||||
{
|
||||
int result[4], num;
|
||||
__cpuid(result, 0);
|
||||
|
@ -39,17 +39,17 @@ static int cpu_supports_sse42(void)
|
|||
|
||||
if (num >= 1) {
|
||||
__cpuid(result, 0x00000001);
|
||||
return (result[2] & ((int)1 << 20)) != 0;
|
||||
return (result[2] & (int(1) << 20)) != 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *cpu_brand_string(void)
|
||||
static const char *cpu_brand_string()
|
||||
{
|
||||
static char buf[49] = {0};
|
||||
int result[4] = {0};
|
||||
__cpuid(result, 0x80000000);
|
||||
if (result[0] >= (int)0x80000004) {
|
||||
if (result[0] >= int(0x80000004)) {
|
||||
__cpuid((int *)(buf + 0), 0x80000002);
|
||||
__cpuid((int *)(buf + 16), 0x80000003);
|
||||
__cpuid((int *)(buf + 32), 0x80000004);
|
||||
|
@ -60,7 +60,7 @@ static const char *cpu_brand_string(void)
|
|||
}
|
||||
return buf_ptr;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -91,7 +91,7 @@ BOOL WINAPI DllMain(HINSTANCE /* hinstDLL */, DWORD fdwReason, LPVOID /* lpvRese
|
|||
# include <cstdio>
|
||||
# include <cstdlib>
|
||||
|
||||
static __attribute__((constructor)) void cpu_check(void)
|
||||
static __attribute__((constructor)) void cpu_check()
|
||||
{
|
||||
# ifdef __x86_64
|
||||
if (!cpu_supports_sse42()) {
|
||||
|
|
|
@ -327,7 +327,7 @@ def process_commands(cmake_dir: str, data: Sequence[str]) -> Optional[ProcessedC
|
|||
return None
|
||||
|
||||
# Check for unsupported configurations.
|
||||
for arg in ("WITH_UNITY_BUILD", "WITH_COMPILER_CCACHE"):
|
||||
for arg in ("WITH_UNITY_BUILD", "WITH_COMPILER_CCACHE", "WITH_COMPILER_PRECOMPILED_HEADERS"):
|
||||
if cmake_cache_var_is_true(cmake_cache_var(cmake_dir, arg)):
|
||||
sys.stderr.write("The option '%s' must be disabled for proper functionality\n" % arg)
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue